aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2013-04-18 09:25:58 -0400
committerAlex Deucher <alexander.deucher@amd.com>2013-04-22 10:39:16 -0400
commit4ed108352d9b60a723a5071ed05e722826c2b72f (patch)
treed2f1500ca5a72b79d073770f28916d68d37a91fa
parent9054ae1ce33f08315616999c742e6656b9967724 (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.c22
-rw-r--r--drivers/gpu/drm/radeon/rv770.c20
-rw-r--r--drivers/gpu/drm/radeon/si.c22
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;