diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2012-02-05 20:34:20 -0500 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2012-05-24 02:31:30 -0400 |
commit | 6b91d6b056ba39633cbdf24b9973df4ac99d7130 (patch) | |
tree | e0bc270e0e4e93e160bf5d5df31f070aaa46e573 | |
parent | a1da205f4203811978ceb4721bfc3728b473bad7 (diff) |
drm/nvc0/pm: enable mpll src pll, and calc mpll coefficients
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | drivers/gpu/drm/nouveau/nvc0_pm.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/nvc0_pm.c b/drivers/gpu/drm/nouveau/nvc0_pm.c index 1348f29b544d..a2f6ae0fa4bd 100644 --- a/drivers/gpu/drm/nouveau/nvc0_pm.c +++ b/drivers/gpu/drm/nouveau/nvc0_pm.c | |||
@@ -166,6 +166,7 @@ struct nvc0_pm_clock { | |||
166 | struct nvc0_pm_state { | 166 | struct nvc0_pm_state { |
167 | struct nouveau_pm_level *perflvl; | 167 | struct nouveau_pm_level *perflvl; |
168 | struct nvc0_pm_clock eng[16]; | 168 | struct nvc0_pm_clock eng[16]; |
169 | struct nvc0_pm_clock mem; | ||
169 | }; | 170 | }; |
170 | 171 | ||
171 | static u32 | 172 | static u32 |
@@ -304,6 +305,48 @@ calc_clk(struct drm_device *dev, int clk, struct nvc0_pm_clock *info, u32 freq) | |||
304 | return 0; | 305 | return 0; |
305 | } | 306 | } |
306 | 307 | ||
308 | static int | ||
309 | calc_mem(struct drm_device *dev, struct nvc0_pm_clock *info, u32 freq) | ||
310 | { | ||
311 | struct pll_lims pll; | ||
312 | int N, M, P, ret; | ||
313 | u32 ctrl; | ||
314 | |||
315 | /* mclk pll input freq comes from another pll, make sure it's on */ | ||
316 | ctrl = nv_rd32(dev, 0x132020); | ||
317 | if (!(ctrl & 0x00000001)) { | ||
318 | /* if not, program it to 567MHz. nfi where this value comes | ||
319 | * from - it looks like it's in the pll limits table for | ||
320 | * 132000 but the binary driver ignores all my attempts to | ||
321 | * change this value. | ||
322 | */ | ||
323 | nv_wr32(dev, 0x137320, 0x00000103); | ||
324 | nv_wr32(dev, 0x137330, 0x81200606); | ||
325 | nv_wait(dev, 0x132020, 0x00010000, 0x00010000); | ||
326 | nv_wr32(dev, 0x132024, 0x0001150f); | ||
327 | nv_mask(dev, 0x132020, 0x00000001, 0x00000001); | ||
328 | nv_wait(dev, 0x137390, 0x00020000, 0x00020000); | ||
329 | nv_mask(dev, 0x132020, 0x00000004, 0x00000004); | ||
330 | } | ||
331 | |||
332 | /* for the moment, until the clock tree is better understood, use | ||
333 | * pll mode for all clock frequencies | ||
334 | */ | ||
335 | ret = get_pll_limits(dev, 0x132000, &pll); | ||
336 | if (ret == 0) { | ||
337 | pll.refclk = read_pll(dev, 0x132020); | ||
338 | if (pll.refclk) { | ||
339 | ret = nva3_calc_pll(dev, &pll, freq, &N, NULL, &M, &P); | ||
340 | if (ret > 0) { | ||
341 | info->coef = (P << 16) | (N << 8) | M; | ||
342 | return 0; | ||
343 | } | ||
344 | } | ||
345 | } | ||
346 | |||
347 | return -EINVAL; | ||
348 | } | ||
349 | |||
307 | void * | 350 | void * |
308 | nvc0_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) | 351 | nvc0_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) |
309 | { | 352 | { |
@@ -336,6 +379,14 @@ nvc0_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) | |||
336 | return ERR_PTR(ret); | 379 | return ERR_PTR(ret); |
337 | } | 380 | } |
338 | 381 | ||
382 | if (perflvl->memory) { | ||
383 | ret = calc_mem(dev, &info->mem, perflvl->memory); | ||
384 | if (ret) { | ||
385 | kfree(info); | ||
386 | return ERR_PTR(ret); | ||
387 | } | ||
388 | } | ||
389 | |||
339 | info->perflvl = perflvl; | 390 | info->perflvl = perflvl; |
340 | return info; | 391 | return info; |
341 | } | 392 | } |