diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2012-11-28 16:55:21 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2014-08-27 12:47:53 -0400 |
commit | 4a956a70a8d4cc5268a60f6718de58892fa1275e (patch) | |
tree | f0a11235bb0d549ca2d8dc7e60dc74db6b8fabaf | |
parent | a8fba64ab08cf4a5baf211f1126b475e03f90fc1 (diff) |
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>
-rw-r--r-- | drivers/gpu/drm/radeon/r600.c | 88 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600d.h | 26 |
2 files changed, 114 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index e7dca47b7196..011d97f6fc7f 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
@@ -122,6 +122,94 @@ u32 r600_get_xclk(struct radeon_device *rdev) | |||
122 | 122 | ||
123 | int r600_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) | 123 | int r600_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) |
124 | { | 124 | { |
125 | unsigned fb_div = 0, ref_div, vclk_div = 0, dclk_div = 0; | ||
126 | int r; | ||
127 | |||
128 | /* bypass vclk and dclk with bclk */ | ||
129 | WREG32_P(CG_UPLL_FUNC_CNTL_2, | ||
130 | VCLK_SRC_SEL(1) | DCLK_SRC_SEL(1), | ||
131 | ~(VCLK_SRC_SEL_MASK | DCLK_SRC_SEL_MASK)); | ||
132 | |||
133 | /* assert BYPASS_EN, deassert UPLL_RESET, UPLL_SLEEP and UPLL_CTLREQ */ | ||
134 | WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~( | ||
135 | UPLL_RESET_MASK | UPLL_SLEEP_MASK | UPLL_CTLREQ_MASK)); | ||
136 | |||
137 | if (rdev->family >= CHIP_RS780) | ||
138 | WREG32_P(GFX_MACRO_BYPASS_CNTL, UPLL_BYPASS_CNTL, | ||
139 | ~UPLL_BYPASS_CNTL); | ||
140 | |||
141 | if (!vclk || !dclk) { | ||
142 | /* keep the Bypass mode, put PLL to sleep */ | ||
143 | WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK); | ||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | if (rdev->clock.spll.reference_freq == 10000) | ||
148 | ref_div = 34; | ||
149 | else | ||
150 | ref_div = 4; | ||
151 | |||
152 | r = radeon_uvd_calc_upll_dividers(rdev, vclk, dclk, 50000, 160000, | ||
153 | ref_div + 1, 0xFFF, 2, 30, ~0, | ||
154 | &fb_div, &vclk_div, &dclk_div); | ||
155 | if (r) | ||
156 | return r; | ||
157 | |||
158 | if (rdev->family >= CHIP_RV670 && rdev->family < CHIP_RS780) | ||
159 | fb_div >>= 1; | ||
160 | else | ||
161 | fb_div |= 1; | ||
162 | |||
163 | r = radeon_uvd_send_upll_ctlreq(rdev, CG_UPLL_FUNC_CNTL); | ||
164 | if (r) | ||
165 | return r; | ||
166 | |||
167 | /* assert PLL_RESET */ | ||
168 | WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_RESET_MASK, ~UPLL_RESET_MASK); | ||
169 | |||
170 | /* For RS780 we have to choose ref clk */ | ||
171 | if (rdev->family >= CHIP_RS780) | ||
172 | WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_REFCLK_SRC_SEL_MASK, | ||
173 | ~UPLL_REFCLK_SRC_SEL_MASK); | ||
174 | |||
175 | /* set the required fb, ref and post divder values */ | ||
176 | WREG32_P(CG_UPLL_FUNC_CNTL, | ||
177 | UPLL_FB_DIV(fb_div) | | ||
178 | UPLL_REF_DIV(ref_div), | ||
179 | ~(UPLL_FB_DIV_MASK | UPLL_REF_DIV_MASK)); | ||
180 | WREG32_P(CG_UPLL_FUNC_CNTL_2, | ||
181 | UPLL_SW_HILEN(vclk_div >> 1) | | ||
182 | UPLL_SW_LOLEN((vclk_div >> 1) + (vclk_div & 1)) | | ||
183 | UPLL_SW_HILEN2(dclk_div >> 1) | | ||
184 | UPLL_SW_LOLEN2((dclk_div >> 1) + (dclk_div & 1)) | | ||
185 | UPLL_DIVEN_MASK | UPLL_DIVEN2_MASK, | ||
186 | ~UPLL_SW_MASK); | ||
187 | |||
188 | /* give the PLL some time to settle */ | ||
189 | mdelay(15); | ||
190 | |||
191 | /* deassert PLL_RESET */ | ||
192 | WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_RESET_MASK); | ||
193 | |||
194 | mdelay(15); | ||
195 | |||
196 | /* deassert BYPASS EN */ | ||
197 | WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_BYPASS_EN_MASK); | ||
198 | |||
199 | if (rdev->family >= CHIP_RS780) | ||
200 | WREG32_P(GFX_MACRO_BYPASS_CNTL, 0, ~UPLL_BYPASS_CNTL); | ||
201 | |||
202 | r = radeon_uvd_send_upll_ctlreq(rdev, CG_UPLL_FUNC_CNTL); | ||
203 | if (r) | ||
204 | return r; | ||
205 | |||
206 | /* switch VCLK and DCLK selection */ | ||
207 | WREG32_P(CG_UPLL_FUNC_CNTL_2, | ||
208 | VCLK_SRC_SEL(2) | DCLK_SRC_SEL(2), | ||
209 | ~(VCLK_SRC_SEL_MASK | DCLK_SRC_SEL_MASK)); | ||
210 | |||
211 | mdelay(100); | ||
212 | |||
125 | return 0; | 213 | return 0; |
126 | } | 214 | } |
127 | 215 | ||
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 3df030dc2352..8c3fdd581a72 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h | |||
@@ -1526,9 +1526,35 @@ | |||
1526 | 1526 | ||
1527 | #define UVD_CONTEXT_ID 0xf6f4 | 1527 | #define UVD_CONTEXT_ID 0xf6f4 |
1528 | 1528 | ||
1529 | /* rs780 only */ | ||
1530 | #define GFX_MACRO_BYPASS_CNTL 0x30c0 | ||
1531 | #define SPLL_BYPASS_CNTL (1 << 0) | ||
1532 | #define UPLL_BYPASS_CNTL (1 << 1) | ||
1533 | |||
1534 | #define CG_UPLL_FUNC_CNTL 0x7e0 | ||
1535 | # define UPLL_RESET_MASK 0x00000001 | ||
1536 | # define UPLL_SLEEP_MASK 0x00000002 | ||
1537 | # define UPLL_BYPASS_EN_MASK 0x00000004 | ||
1529 | # define UPLL_CTLREQ_MASK 0x00000008 | 1538 | # define UPLL_CTLREQ_MASK 0x00000008 |
1539 | # define UPLL_FB_DIV(x) ((x) << 4) | ||
1540 | # define UPLL_FB_DIV_MASK 0x0000FFF0 | ||
1541 | # define UPLL_REF_DIV(x) ((x) << 16) | ||
1542 | # define UPLL_REF_DIV_MASK 0x003F0000 | ||
1543 | # define UPLL_REFCLK_SRC_SEL_MASK 0x20000000 | ||
1530 | # define UPLL_CTLACK_MASK 0x40000000 | 1544 | # define UPLL_CTLACK_MASK 0x40000000 |
1531 | # define UPLL_CTLACK2_MASK 0x80000000 | 1545 | # define UPLL_CTLACK2_MASK 0x80000000 |
1546 | #define CG_UPLL_FUNC_CNTL_2 0x7e4 | ||
1547 | # define UPLL_SW_HILEN(x) ((x) << 0) | ||
1548 | # define UPLL_SW_LOLEN(x) ((x) << 4) | ||
1549 | # define UPLL_SW_HILEN2(x) ((x) << 8) | ||
1550 | # define UPLL_SW_LOLEN2(x) ((x) << 12) | ||
1551 | # define UPLL_DIVEN_MASK 0x00010000 | ||
1552 | # define UPLL_DIVEN2_MASK 0x00020000 | ||
1553 | # define UPLL_SW_MASK 0x0003FFFF | ||
1554 | # define VCLK_SRC_SEL(x) ((x) << 20) | ||
1555 | # define VCLK_SRC_SEL_MASK 0x01F00000 | ||
1556 | # define DCLK_SRC_SEL(x) ((x) << 25) | ||
1557 | # define DCLK_SRC_SEL_MASK 0x3E000000 | ||
1532 | 1558 | ||
1533 | /* | 1559 | /* |
1534 | * PM4 | 1560 | * PM4 |