diff mbox

[1/2] drm/radeon: put UVD PLLs in bypass mode

Message ID 1366291559-7672-1-git-send-email-deathsimple@vodafone.de (mailing list archive)
State New, archived
Headers show

Commit Message

Christian König April 18, 2013, 1:25 p.m. UTC
From: Christian König <christian.koenig@amd.com>

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>
---
 drivers/gpu/drm/radeon/evergreen.c |   22 ++++++++++++++--------
 drivers/gpu/drm/radeon/rv770.c     |   20 +++++++++++++-------
 drivers/gpu/drm/radeon/si.c        |   22 ++++++++++++++--------
 3 files changed, 41 insertions(+), 23 deletions(-)

Comments

Alex Deucher April 18, 2013, 1:52 p.m. UTC | #1
On Thu, Apr 18, 2013 at 9:25 AM, Christian König
<deathsimple@vodafone.de> wrote:
> From: Christian König <christian.koenig@amd.com>
>
> 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>

Looks good.  both applied.

Alex

> ---
>  drivers/gpu/drm/radeon/evergreen.c |   22 ++++++++++++++--------
>  drivers/gpu/drm/radeon/rv770.c     |   20 +++++++++++++-------
>  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 124c193..facfa84 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)
>         unsigned vco_freq;
>         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));
> +
> +       /* put PLL in bypass mode */
> +       WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK);
> +
> +       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;
> +       }
> +
>         /* loop through vco from low to high */
>         for (vco_freq = 125000; vco_freq <= 250000; vco_freq += 100) {
>                 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)
>
>         mdelay(1);
>
> -       /* 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));
> -
> -       /* put PLL in bypass mode */
> -       WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK);
> -
>         r = evergreen_uvd_send_upll_ctlreq(rdev);
>         if (r)
>                 return r;
> diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
> index 777f537..59065ba 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)
>         if (rdev->family == CHIP_RV740)
>                 return evergreen_set_uvd_clocks(rdev, vclk, dclk);
>
> +       /* 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));
> +
> +       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;
> +       }
> +
>         /* loop through vco from low to high */
>         vco_min = max(max(vco_min, vclk), dclk);
>         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)
>                 }
>         }
>
> -       /* 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));
> -
>         /* set UPLL_FB_DIV to 0x50000 */
>         WREG32_P(CG_UPLL_FUNC_CNTL_3, UPLL_FB_DIV(0x50000), ~UPLL_FB_DIV_MASK);
>
> -       /* deassert UPLL_RESET */
> -       WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_RESET_MASK);
> +       /* deassert UPLL_RESET and UPLL_SLEEP */
> +       WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~(UPLL_RESET_MASK | UPLL_SLEEP_MASK));
>
>         /* assert BYPASS EN and FB_DIV[0] <- ??? why? */
>         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 aa2c555..b7d78f2 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)
>         unsigned vco_freq;
>         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));
> +
> +       /* put PLL in bypass mode */
> +       WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK);
> +
> +       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;
> +       }
> +
>         /* loop through vco from low to high */
>         for (vco_freq = 125000; vco_freq <= 250000; vco_freq += 100) {
>                 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)
>
>         mdelay(1);
>
> -       /* 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));
> -
> -       /* put PLL in bypass mode */
> -       WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK);
> -
>         r = si_uvd_send_upll_ctlreq(rdev);
>         if (r)
>                 return r;
> --
> 1.7.10.4
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
diff mbox

Patch

diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 124c193..facfa84 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)
 	unsigned vco_freq;
 	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));
+
+	/* put PLL in bypass mode */
+	WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK);
+
+	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;
+	}
+
 	/* loop through vco from low to high */
 	for (vco_freq = 125000; vco_freq <= 250000; vco_freq += 100) {
 		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)
 
 	mdelay(1);
 
-	/* 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));
-
-	/* put PLL in bypass mode */
-	WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK);
-
 	r = evergreen_uvd_send_upll_ctlreq(rdev);
 	if (r)
 		return r;
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index 777f537..59065ba 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)
 	if (rdev->family == CHIP_RV740)
 		return evergreen_set_uvd_clocks(rdev, vclk, dclk);
 
+	/* 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));
+
+	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;
+	}
+
 	/* loop through vco from low to high */
 	vco_min = max(max(vco_min, vclk), dclk);
 	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)
 		}
 	}
 
-	/* 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));
-
 	/* set UPLL_FB_DIV to 0x50000 */
 	WREG32_P(CG_UPLL_FUNC_CNTL_3, UPLL_FB_DIV(0x50000), ~UPLL_FB_DIV_MASK);
 
-	/* deassert UPLL_RESET */
-	WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_RESET_MASK);
+	/* deassert UPLL_RESET and UPLL_SLEEP */
+	WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~(UPLL_RESET_MASK | UPLL_SLEEP_MASK));
 
 	/* assert BYPASS EN and FB_DIV[0] <- ??? why? */
 	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 aa2c555..b7d78f2 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)
 	unsigned vco_freq;
 	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));
+
+	/* put PLL in bypass mode */
+	WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK);
+
+	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;
+	}
+
 	/* loop through vco from low to high */
 	for (vco_freq = 125000; vco_freq <= 250000; vco_freq += 100) {
 		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)
 
 	mdelay(1);
 
-	/* 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));
-
-	/* put PLL in bypass mode */
-	WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK);
-
 	r = si_uvd_send_upll_ctlreq(rdev);
 	if (r)
 		return r;