aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2012-01-25 01:02:58 -0500
committerBen Skeggs <bskeggs@redhat.com>2012-05-24 02:31:14 -0400
commit65115bb05a9380a256907ae307135248ac1c29b4 (patch)
treea7a37c77e2c3007e6038d97d4eb5b02416e9bc5e /drivers/gpu/drm/nouveau
parent074e747a6d371192419fb5abeabb9686d0cf24a5 (diff)
drm/nva3/pm: hook up to ram reclocking helper
This gets us a start on memory timings. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-rw-r--r--drivers/gpu/drm/nouveau/nva3_pm.c122
1 files changed, 110 insertions, 12 deletions
diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c
index 0f93c54de80c..3d397845dca9 100644
--- a/drivers/gpu/drm/nouveau/nva3_pm.c
+++ b/drivers/gpu/drm/nouveau/nva3_pm.c
@@ -235,6 +235,7 @@ nva3_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
235} 235}
236 236
237struct nva3_pm_state { 237struct nva3_pm_state {
238 struct nouveau_pm_level *perflvl;
238 struct creg nclk; 239 struct creg nclk;
239 struct creg sclk; 240 struct creg sclk;
240 struct creg mclk; 241 struct creg mclk;
@@ -272,6 +273,7 @@ nva3_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
272 if (ret < 0) 273 if (ret < 0)
273 goto out; 274 goto out;
274 275
276 info->perflvl = perflvl;
275out: 277out:
276 if (ret < 0) { 278 if (ret < 0) {
277 kfree(info); 279 kfree(info);
@@ -292,6 +294,112 @@ nva3_pm_grcp_idle(void *data)
292 return false; 294 return false;
293} 295}
294 296
297static void
298mclk_precharge(struct nouveau_mem_exec_func *exec)
299{
300 nv_wr32(exec->dev, 0x1002d4, 0x00000001);
301}
302
303static void
304mclk_refresh(struct nouveau_mem_exec_func *exec)
305{
306 nv_wr32(exec->dev, 0x1002d0, 0x00000001);
307}
308
309static void
310mclk_refresh_auto(struct nouveau_mem_exec_func *exec, bool enable)
311{
312 nv_wr32(exec->dev, 0x100210, enable ? 0x80000000 : 0x00000000);
313}
314
315static void
316mclk_refresh_self(struct nouveau_mem_exec_func *exec, bool enable)
317{
318 nv_wr32(exec->dev, 0x1002dc, enable ? 0x00000001 : 0x00000000);
319}
320
321static void
322mclk_wait(struct nouveau_mem_exec_func *exec, u32 nsec)
323{
324 udelay((nsec + 500) / 1000);
325}
326
327static u32
328mclk_mrg(struct nouveau_mem_exec_func *exec, int mr)
329{
330 if (mr <= 1)
331 return nv_rd32(exec->dev, 0x1002c0 + ((mr - 0) * 4));
332 if (mr <= 3)
333 return nv_rd32(exec->dev, 0x1002e0 + ((mr - 2) * 4));
334 return 0;
335}
336
337static void
338mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data)
339{
340 struct drm_nouveau_private *dev_priv = exec->dev->dev_private;
341
342 if (mr <= 1) {
343 if (dev_priv->vram_rank_B)
344 nv_wr32(exec->dev, 0x1002c8 + ((mr - 0) * 4), data);
345 nv_wr32(exec->dev, 0x1002c0 + ((mr - 0) * 4), data);
346 } else
347 if (mr <= 3) {
348 if (dev_priv->vram_rank_B)
349 nv_wr32(exec->dev, 0x1002e8 + ((mr - 2) * 4), data);
350 nv_wr32(exec->dev, 0x1002e0 + ((mr - 2) * 4), data);
351 }
352}
353
354static void
355mclk_clock_set(struct nouveau_mem_exec_func *exec)
356{
357 struct nva3_pm_state *info = exec->priv;
358 struct drm_device *dev = exec->dev;
359
360 nv_wr32(dev, 0x004018, 0x00001000);
361
362 prog_pll(dev, 0x02, 0x004000, &info->mclk);
363
364 if (nv_rd32(dev, 0x4000) & 0x00000008)
365 nv_wr32(dev, 0x004018, 0x1000d000);
366 else
367 nv_wr32(dev, 0x004018, 0x10005000);
368}
369
370static void
371mclk_timing_set(struct nouveau_mem_exec_func *exec)
372{
373 struct nva3_pm_state *info = exec->priv;
374 struct nouveau_pm_level *perflvl = info->perflvl;
375 int i;
376
377 for (i = 0; i < 9; i++)
378 nv_wr32(exec->dev, 0x100220 + (i * 4), perflvl->timing.reg[i]);
379}
380
381static void
382prog_mem(struct drm_device *dev, struct nva3_pm_state *info)
383{
384 struct nouveau_mem_exec_func exec = {
385 .dev = dev,
386 .precharge = mclk_precharge,
387 .refresh = mclk_refresh,
388 .refresh_auto = mclk_refresh_auto,
389 .refresh_self = mclk_refresh_self,
390 .wait = mclk_wait,
391 .mrg = mclk_mrg,
392 .mrs = mclk_mrs,
393 .clock_set = mclk_clock_set,
394 .timing_set = mclk_timing_set,
395 .priv = info
396 };
397
398 nv_wr32(dev, 0x611200, 0x00003300);
399 nouveau_mem_exec(&exec, info->perflvl);
400 nv_wr32(dev, 0x611200, 0x00003330);
401}
402
295int 403int
296nva3_pm_clocks_set(struct drm_device *dev, void *pre_state) 404nva3_pm_clocks_set(struct drm_device *dev, void *pre_state)
297{ 405{
@@ -321,18 +429,8 @@ nva3_pm_clocks_set(struct drm_device *dev, void *pre_state)
321 prog_clk(dev, 0x20, &info->unka0); 429 prog_clk(dev, 0x20, &info->unka0);
322 prog_clk(dev, 0x21, &info->vdec); 430 prog_clk(dev, 0x21, &info->vdec);
323 431
324 if (info->mclk.clk || info->mclk.pll) { 432 if (info->mclk.clk || info->mclk.pll)
325 nv_wr32(dev, 0x100210, 0); 433 prog_mem(dev, info);
326 nv_wr32(dev, 0x1002dc, 1);
327 nv_wr32(dev, 0x004018, 0x00001000);
328 prog_pll(dev, 0x02, 0x004000, &info->mclk);
329 if (nv_rd32(dev, 0x4000) & 0x00000008)
330 nv_wr32(dev, 0x004018, 0x1000d000);
331 else
332 nv_wr32(dev, 0x004018, 0x10005000);
333 nv_wr32(dev, 0x1002dc, 0);
334 nv_wr32(dev, 0x100210, 0x80000000);
335 }
336 434
337 ret = 0; 435 ret = 0;
338 436