Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b9fa1883 authored by Alex Deucher's avatar Alex Deucher Committed by Christian König
Browse files

drm/radeon: add support for vce 2.0 clock gating

parent 44493ba9
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -2029,8 +2029,18 @@
#define VCE_RB_RPTR			0x2018c
#define VCE_RB_WPTR			0x20190
#define VCE_CLOCK_GATING_A		0x202f8
#	define CGC_CLK_GATE_DLY_TIMER_MASK	(0xf << 0)
#	define CGC_CLK_GATE_DLY_TIMER(x)	((x) << 0)
#	define CGC_CLK_GATER_OFF_DLY_TIMER_MASK	(0xff << 4)
#	define CGC_CLK_GATER_OFF_DLY_TIMER(x)	((x) << 4)
#	define CGC_UENC_WAIT_AWAKE	(1 << 18)
#define VCE_CLOCK_GATING_B		0x202fc
#define VCE_CGTT_CLK_OVERRIDE		0x207a0
#define VCE_UENC_CLOCK_GATING		0x207bc
#	define CLOCK_ON_DELAY_MASK	(0xf << 0)
#	define CLOCK_ON_DELAY(x)	((x) << 0)
#	define CLOCK_OFF_DELAY_MASK	(0xff << 4)
#	define CLOCK_OFF_DELAY(x)	((x) << 4)
#define VCE_UENC_REG_CLOCK_GATING	0x207c0
#define VCE_SYS_INT_EN			0x21300
#	define VCE_SYS_INT_TRAP_INTERRUPT_EN	(1 << 3)
+111 −0
Original line number Diff line number Diff line
@@ -31,6 +31,115 @@
#include "radeon_asic.h"
#include "cikd.h"

static void vce_v2_0_set_sw_cg(struct radeon_device *rdev, bool gated)
{
	u32 tmp;

	if (gated) {
		tmp = RREG32(VCE_CLOCK_GATING_B);
		tmp |= 0xe70000;
		WREG32(VCE_CLOCK_GATING_B, tmp);

		tmp = RREG32(VCE_UENC_CLOCK_GATING);
		tmp |= 0xff000000;
		WREG32(VCE_UENC_CLOCK_GATING, tmp);

		tmp = RREG32(VCE_UENC_REG_CLOCK_GATING);
		tmp &= ~0x3fc;
		WREG32(VCE_UENC_REG_CLOCK_GATING, tmp);

		WREG32(VCE_CGTT_CLK_OVERRIDE, 0);
    } else {
		tmp = RREG32(VCE_CLOCK_GATING_B);
		tmp |= 0xe7;
		tmp &= ~0xe70000;
		WREG32(VCE_CLOCK_GATING_B, tmp);

		tmp = RREG32(VCE_UENC_CLOCK_GATING);
		tmp |= 0x1fe000;
		tmp &= ~0xff000000;
		WREG32(VCE_UENC_CLOCK_GATING, tmp);

		tmp = RREG32(VCE_UENC_REG_CLOCK_GATING);
		tmp |= 0x3fc;
		WREG32(VCE_UENC_REG_CLOCK_GATING, tmp);
	}
}

static void vce_v2_0_set_dyn_cg(struct radeon_device *rdev, bool gated)
{
	u32 orig, tmp;

	tmp = RREG32(VCE_CLOCK_GATING_B);
	tmp &= ~0x00060006;
	if (gated) {
		tmp |= 0xe10000;
	} else {
		tmp |= 0xe1;
		tmp &= ~0xe10000;
	}
	WREG32(VCE_CLOCK_GATING_B, tmp);

	orig = tmp = RREG32(VCE_UENC_CLOCK_GATING);
	tmp &= ~0x1fe000;
	tmp &= ~0xff000000;
	if (tmp != orig)
		WREG32(VCE_UENC_CLOCK_GATING, tmp);

	orig = tmp = RREG32(VCE_UENC_REG_CLOCK_GATING);
	tmp &= ~0x3fc;
	if (tmp != orig)
		WREG32(VCE_UENC_REG_CLOCK_GATING, tmp);

	if (gated)
		WREG32(VCE_CGTT_CLK_OVERRIDE, 0);
}

static void vce_v2_0_disable_cg(struct radeon_device *rdev)
{
	WREG32(VCE_CGTT_CLK_OVERRIDE, 7);
}

void vce_v2_0_enable_mgcg(struct radeon_device *rdev, bool enable)
{
	bool sw_cg = false;

	if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_VCE_MGCG)) {
		if (sw_cg)
			vce_v2_0_set_sw_cg(rdev, true);
		else
			vce_v2_0_set_dyn_cg(rdev, true);
	} else {
		vce_v2_0_disable_cg(rdev);

		if (sw_cg)
			vce_v2_0_set_sw_cg(rdev, false);
		else
			vce_v2_0_set_dyn_cg(rdev, false);
	}
}

static void vce_v2_0_init_cg(struct radeon_device *rdev)
{
	u32 tmp;

	tmp = RREG32(VCE_CLOCK_GATING_A);
	tmp &= ~(CGC_CLK_GATE_DLY_TIMER_MASK | CGC_CLK_GATER_OFF_DLY_TIMER_MASK);
	tmp |= (CGC_CLK_GATE_DLY_TIMER(0) | CGC_CLK_GATER_OFF_DLY_TIMER(4));
	tmp |= CGC_UENC_WAIT_AWAKE;
	WREG32(VCE_CLOCK_GATING_A, tmp);

	tmp = RREG32(VCE_UENC_CLOCK_GATING);
	tmp &= ~(CLOCK_ON_DELAY_MASK | CLOCK_OFF_DELAY_MASK);
	tmp |= (CLOCK_ON_DELAY(0) | CLOCK_OFF_DELAY(4));
	WREG32(VCE_UENC_CLOCK_GATING, tmp);

	tmp = RREG32(VCE_CLOCK_GATING_B);
	tmp |= 0x10;
	tmp &= ~0x100000;
	WREG32(VCE_CLOCK_GATING_B, tmp);
}

int vce_v2_0_resume(struct radeon_device *rdev)
{
	uint64_t addr = rdev->vce.gpu_addr;
@@ -66,5 +175,7 @@ int vce_v2_0_resume(struct radeon_device *rdev)
	WREG32_P(VCE_SYS_INT_EN, VCE_SYS_INT_TRAP_INTERRUPT_EN,
		 ~VCE_SYS_INT_TRAP_INTERRUPT_EN);

	vce_v2_0_init_cg(rdev);

	return 0;
}