aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2012-11-28 16:55:21 -0500
committerAlex Deucher <alexander.deucher@amd.com>2014-08-27 12:47:53 -0400
commit4a956a70a8d4cc5268a60f6718de58892fa1275e (patch)
treef0a11235bb0d549ca2d8dc7e60dc74db6b8fabaf
parenta8fba64ab08cf4a5baf211f1126b475e03f90fc1 (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.c88
-rw-r--r--drivers/gpu/drm/radeon/r600d.h26
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
123int r600_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) 123int 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