diff options
author | Christian König <christian.koenig@amd.com> | 2013-04-18 09:25:58 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-04-22 10:39:16 -0400 |
commit | 4ed108352d9b60a723a5071ed05e722826c2b72f (patch) | |
tree | d2f1500ca5a72b79d073770f28916d68d37a91fa | |
parent | 9054ae1ce33f08315616999c742e6656b9967724 (diff) |
drm/radeon: put UVD PLLs in bypass mode
Just power down the PLL when we get a VCLK or DCLK of zero.
Enabling the bypass mode early should also allow us to
switch UVD clocks on the fly.
Signed-off-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r-- | drivers/gpu/drm/radeon/evergreen.c | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rv770.c | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/si.c | 22 |
3 files changed, 41 insertions, 23 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index d425a4fa0109..0af36e7731e2 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
@@ -189,6 +189,20 @@ int evergreen_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) | |||
189 | unsigned vco_freq; | 189 | unsigned vco_freq; |
190 | int r; | 190 | int r; |
191 | 191 | ||
192 | /* bypass vclk and dclk with bclk */ | ||
193 | WREG32_P(CG_UPLL_FUNC_CNTL_2, | ||
194 | VCLK_SRC_SEL(1) | DCLK_SRC_SEL(1), | ||
195 | ~(VCLK_SRC_SEL_MASK | DCLK_SRC_SEL_MASK)); | ||
196 | |||
197 | /* put PLL in bypass mode */ | ||
198 | WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK); | ||
199 | |||
200 | if (!vclk || !dclk) { | ||
201 | /* keep the Bypass mode, put PLL to sleep */ | ||
202 | WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK); | ||
203 | return 0; | ||
204 | } | ||
205 | |||
192 | /* loop through vco from low to high */ | 206 | /* loop through vco from low to high */ |
193 | for (vco_freq = 125000; vco_freq <= 250000; vco_freq += 100) { | 207 | for (vco_freq = 125000; vco_freq <= 250000; vco_freq += 100) { |
194 | unsigned fb_div = vco_freq / rdev->clock.spll.reference_freq * 16384; | 208 | unsigned fb_div = vco_freq / rdev->clock.spll.reference_freq * 16384; |
@@ -236,14 +250,6 @@ int evergreen_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) | |||
236 | 250 | ||
237 | mdelay(1); | 251 | mdelay(1); |
238 | 252 | ||
239 | /* bypass vclk and dclk with bclk */ | ||
240 | WREG32_P(CG_UPLL_FUNC_CNTL_2, | ||
241 | VCLK_SRC_SEL(1) | DCLK_SRC_SEL(1), | ||
242 | ~(VCLK_SRC_SEL_MASK | DCLK_SRC_SEL_MASK)); | ||
243 | |||
244 | /* put PLL in bypass mode */ | ||
245 | WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK); | ||
246 | |||
247 | r = evergreen_uvd_send_upll_ctlreq(rdev); | 253 | r = evergreen_uvd_send_upll_ctlreq(rdev); |
248 | if (r) | 254 | if (r) |
249 | return r; | 255 | return r; |
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 777f537a32c7..59065ba7c342 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c | |||
@@ -100,6 +100,17 @@ int rv770_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) | |||
100 | if (rdev->family == CHIP_RV740) | 100 | if (rdev->family == CHIP_RV740) |
101 | return evergreen_set_uvd_clocks(rdev, vclk, dclk); | 101 | return evergreen_set_uvd_clocks(rdev, vclk, dclk); |
102 | 102 | ||
103 | /* bypass vclk and dclk with bclk */ | ||
104 | WREG32_P(CG_UPLL_FUNC_CNTL_2, | ||
105 | VCLK_SRC_SEL(1) | DCLK_SRC_SEL(1), | ||
106 | ~(VCLK_SRC_SEL_MASK | DCLK_SRC_SEL_MASK)); | ||
107 | |||
108 | if (!vclk || !dclk) { | ||
109 | /* keep the Bypass mode, put PLL to sleep */ | ||
110 | WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK); | ||
111 | return 0; | ||
112 | } | ||
113 | |||
103 | /* loop through vco from low to high */ | 114 | /* loop through vco from low to high */ |
104 | vco_min = max(max(vco_min, vclk), dclk); | 115 | vco_min = max(max(vco_min, vclk), dclk); |
105 | for (vco_freq = vco_min; vco_freq <= vco_max; vco_freq += 500) { | 116 | for (vco_freq = vco_min; vco_freq <= vco_max; vco_freq += 500) { |
@@ -139,16 +150,11 @@ int rv770_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) | |||
139 | } | 150 | } |
140 | } | 151 | } |
141 | 152 | ||
142 | /* bypass vclk and dclk with bclk */ | ||
143 | WREG32_P(CG_UPLL_FUNC_CNTL_2, | ||
144 | VCLK_SRC_SEL(1) | DCLK_SRC_SEL(1), | ||
145 | ~(VCLK_SRC_SEL_MASK | DCLK_SRC_SEL_MASK)); | ||
146 | |||
147 | /* set UPLL_FB_DIV to 0x50000 */ | 153 | /* set UPLL_FB_DIV to 0x50000 */ |
148 | WREG32_P(CG_UPLL_FUNC_CNTL_3, UPLL_FB_DIV(0x50000), ~UPLL_FB_DIV_MASK); | 154 | WREG32_P(CG_UPLL_FUNC_CNTL_3, UPLL_FB_DIV(0x50000), ~UPLL_FB_DIV_MASK); |
149 | 155 | ||
150 | /* deassert UPLL_RESET */ | 156 | /* deassert UPLL_RESET and UPLL_SLEEP */ |
151 | WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_RESET_MASK); | 157 | WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~(UPLL_RESET_MASK | UPLL_SLEEP_MASK)); |
152 | 158 | ||
153 | /* assert BYPASS EN and FB_DIV[0] <- ??? why? */ | 159 | /* assert BYPASS EN and FB_DIV[0] <- ??? why? */ |
154 | WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK); | 160 | WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK); |
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index aa2c555ba877..b7d78f24cc26 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
@@ -4680,6 +4680,20 @@ int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) | |||
4680 | unsigned vco_freq; | 4680 | unsigned vco_freq; |
4681 | int r; | 4681 | int r; |
4682 | 4682 | ||
4683 | /* bypass vclk and dclk with bclk */ | ||
4684 | WREG32_P(CG_UPLL_FUNC_CNTL_2, | ||
4685 | VCLK_SRC_SEL(1) | DCLK_SRC_SEL(1), | ||
4686 | ~(VCLK_SRC_SEL_MASK | DCLK_SRC_SEL_MASK)); | ||
4687 | |||
4688 | /* put PLL in bypass mode */ | ||
4689 | WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK); | ||
4690 | |||
4691 | if (!vclk || !dclk) { | ||
4692 | /* keep the Bypass mode, put PLL to sleep */ | ||
4693 | WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK); | ||
4694 | return 0; | ||
4695 | } | ||
4696 | |||
4683 | /* loop through vco from low to high */ | 4697 | /* loop through vco from low to high */ |
4684 | for (vco_freq = 125000; vco_freq <= 250000; vco_freq += 100) { | 4698 | for (vco_freq = 125000; vco_freq <= 250000; vco_freq += 100) { |
4685 | unsigned fb_div = vco_freq / rdev->clock.spll.reference_freq * 16384; | 4699 | unsigned fb_div = vco_freq / rdev->clock.spll.reference_freq * 16384; |
@@ -4730,14 +4744,6 @@ int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) | |||
4730 | 4744 | ||
4731 | mdelay(1); | 4745 | mdelay(1); |
4732 | 4746 | ||
4733 | /* bypass vclk and dclk with bclk */ | ||
4734 | WREG32_P(CG_UPLL_FUNC_CNTL_2, | ||
4735 | VCLK_SRC_SEL(1) | DCLK_SRC_SEL(1), | ||
4736 | ~(VCLK_SRC_SEL_MASK | DCLK_SRC_SEL_MASK)); | ||
4737 | |||
4738 | /* put PLL in bypass mode */ | ||
4739 | WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK); | ||
4740 | |||
4741 | r = si_uvd_send_upll_ctlreq(rdev); | 4747 | r = si_uvd_send_upll_ctlreq(rdev); |
4742 | if (r) | 4748 | if (r) |
4743 | return r; | 4749 | return r; |