forked from Minki/linux
drm/radeon: add set_uvd_clocks callback for r6xx v4
v2: wake up PLL, set [VD]CLK_SRC, cleanup code v3: handle RV670,RV635,RV620 as well v4: merge rv6xx and rs780/rs880 code, fix ref divider mask Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Christian König <christian.koenig@amd.com>
This commit is contained in:
parent
a8fba64ab0
commit
4a956a70a8
@ -122,6 +122,94 @@ u32 r600_get_xclk(struct radeon_device *rdev)
|
||||
|
||||
int r600_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk)
|
||||
{
|
||||
unsigned fb_div = 0, ref_div, vclk_div = 0, dclk_div = 0;
|
||||
int r;
|
||||
|
||||
/* bypass vclk and dclk with bclk */
|
||||
WREG32_P(CG_UPLL_FUNC_CNTL_2,
|
||||
VCLK_SRC_SEL(1) | DCLK_SRC_SEL(1),
|
||||
~(VCLK_SRC_SEL_MASK | DCLK_SRC_SEL_MASK));
|
||||
|
||||
/* assert BYPASS_EN, deassert UPLL_RESET, UPLL_SLEEP and UPLL_CTLREQ */
|
||||
WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~(
|
||||
UPLL_RESET_MASK | UPLL_SLEEP_MASK | UPLL_CTLREQ_MASK));
|
||||
|
||||
if (rdev->family >= CHIP_RS780)
|
||||
WREG32_P(GFX_MACRO_BYPASS_CNTL, UPLL_BYPASS_CNTL,
|
||||
~UPLL_BYPASS_CNTL);
|
||||
|
||||
if (!vclk || !dclk) {
|
||||
/* keep the Bypass mode, put PLL to sleep */
|
||||
WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rdev->clock.spll.reference_freq == 10000)
|
||||
ref_div = 34;
|
||||
else
|
||||
ref_div = 4;
|
||||
|
||||
r = radeon_uvd_calc_upll_dividers(rdev, vclk, dclk, 50000, 160000,
|
||||
ref_div + 1, 0xFFF, 2, 30, ~0,
|
||||
&fb_div, &vclk_div, &dclk_div);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (rdev->family >= CHIP_RV670 && rdev->family < CHIP_RS780)
|
||||
fb_div >>= 1;
|
||||
else
|
||||
fb_div |= 1;
|
||||
|
||||
r = radeon_uvd_send_upll_ctlreq(rdev, CG_UPLL_FUNC_CNTL);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* assert PLL_RESET */
|
||||
WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_RESET_MASK, ~UPLL_RESET_MASK);
|
||||
|
||||
/* For RS780 we have to choose ref clk */
|
||||
if (rdev->family >= CHIP_RS780)
|
||||
WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_REFCLK_SRC_SEL_MASK,
|
||||
~UPLL_REFCLK_SRC_SEL_MASK);
|
||||
|
||||
/* set the required fb, ref and post divder values */
|
||||
WREG32_P(CG_UPLL_FUNC_CNTL,
|
||||
UPLL_FB_DIV(fb_div) |
|
||||
UPLL_REF_DIV(ref_div),
|
||||
~(UPLL_FB_DIV_MASK | UPLL_REF_DIV_MASK));
|
||||
WREG32_P(CG_UPLL_FUNC_CNTL_2,
|
||||
UPLL_SW_HILEN(vclk_div >> 1) |
|
||||
UPLL_SW_LOLEN((vclk_div >> 1) + (vclk_div & 1)) |
|
||||
UPLL_SW_HILEN2(dclk_div >> 1) |
|
||||
UPLL_SW_LOLEN2((dclk_div >> 1) + (dclk_div & 1)) |
|
||||
UPLL_DIVEN_MASK | UPLL_DIVEN2_MASK,
|
||||
~UPLL_SW_MASK);
|
||||
|
||||
/* give the PLL some time to settle */
|
||||
mdelay(15);
|
||||
|
||||
/* deassert PLL_RESET */
|
||||
WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_RESET_MASK);
|
||||
|
||||
mdelay(15);
|
||||
|
||||
/* deassert BYPASS EN */
|
||||
WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_BYPASS_EN_MASK);
|
||||
|
||||
if (rdev->family >= CHIP_RS780)
|
||||
WREG32_P(GFX_MACRO_BYPASS_CNTL, 0, ~UPLL_BYPASS_CNTL);
|
||||
|
||||
r = radeon_uvd_send_upll_ctlreq(rdev, CG_UPLL_FUNC_CNTL);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* switch VCLK and DCLK selection */
|
||||
WREG32_P(CG_UPLL_FUNC_CNTL_2,
|
||||
VCLK_SRC_SEL(2) | DCLK_SRC_SEL(2),
|
||||
~(VCLK_SRC_SEL_MASK | DCLK_SRC_SEL_MASK));
|
||||
|
||||
mdelay(100);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1526,9 +1526,35 @@
|
||||
|
||||
#define UVD_CONTEXT_ID 0xf6f4
|
||||
|
||||
/* rs780 only */
|
||||
#define GFX_MACRO_BYPASS_CNTL 0x30c0
|
||||
#define SPLL_BYPASS_CNTL (1 << 0)
|
||||
#define UPLL_BYPASS_CNTL (1 << 1)
|
||||
|
||||
#define CG_UPLL_FUNC_CNTL 0x7e0
|
||||
# define UPLL_RESET_MASK 0x00000001
|
||||
# define UPLL_SLEEP_MASK 0x00000002
|
||||
# define UPLL_BYPASS_EN_MASK 0x00000004
|
||||
# define UPLL_CTLREQ_MASK 0x00000008
|
||||
# define UPLL_FB_DIV(x) ((x) << 4)
|
||||
# define UPLL_FB_DIV_MASK 0x0000FFF0
|
||||
# define UPLL_REF_DIV(x) ((x) << 16)
|
||||
# define UPLL_REF_DIV_MASK 0x003F0000
|
||||
# define UPLL_REFCLK_SRC_SEL_MASK 0x20000000
|
||||
# define UPLL_CTLACK_MASK 0x40000000
|
||||
# define UPLL_CTLACK2_MASK 0x80000000
|
||||
#define CG_UPLL_FUNC_CNTL_2 0x7e4
|
||||
# define UPLL_SW_HILEN(x) ((x) << 0)
|
||||
# define UPLL_SW_LOLEN(x) ((x) << 4)
|
||||
# define UPLL_SW_HILEN2(x) ((x) << 8)
|
||||
# define UPLL_SW_LOLEN2(x) ((x) << 12)
|
||||
# define UPLL_DIVEN_MASK 0x00010000
|
||||
# define UPLL_DIVEN2_MASK 0x00020000
|
||||
# define UPLL_SW_MASK 0x0003FFFF
|
||||
# define VCLK_SRC_SEL(x) ((x) << 20)
|
||||
# define VCLK_SRC_SEL_MASK 0x01F00000
|
||||
# define DCLK_SRC_SEL(x) ((x) << 25)
|
||||
# define DCLK_SRC_SEL_MASK 0x3E000000
|
||||
|
||||
/*
|
||||
* PM4
|
||||
|
Loading…
Reference in New Issue
Block a user