aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nv50_pm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv50_pm.c')
-rw-r--r--drivers/gpu/drm/nouveau/nv50_pm.c207
1 files changed, 145 insertions, 62 deletions
diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c
index e025cae5ef23..22789db48969 100644
--- a/drivers/gpu/drm/nouveau/nv50_pm.c
+++ b/drivers/gpu/drm/nouveau/nv50_pm.c
@@ -27,6 +27,7 @@
27#include "nouveau_bios.h" 27#include "nouveau_bios.h"
28#include "nouveau_hw.h" 28#include "nouveau_hw.h"
29#include "nouveau_pm.h" 29#include "nouveau_pm.h"
30#include "nouveau_hwsq.h"
30 31
31enum clk_src { 32enum clk_src {
32 clk_src_crystal, 33 clk_src_crystal,
@@ -351,6 +352,9 @@ nv50_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
351} 352}
352 353
353struct nv50_pm_state { 354struct nv50_pm_state {
355 struct hwsq_ucode mclk_hwsq;
356 u32 mscript;
357
354 u32 emast; 358 u32 emast;
355 u32 nctrl; 359 u32 nctrl;
356 u32 ncoef; 360 u32 ncoef;
@@ -359,10 +363,6 @@ struct nv50_pm_state {
359 363
360 u32 amast; 364 u32 amast;
361 u32 pdivs; 365 u32 pdivs;
362
363 u32 mscript;
364 u32 mctrl;
365 u32 mcoef;
366}; 366};
367 367
368static u32 368static u32
@@ -415,6 +415,80 @@ clk_same(u32 a, u32 b)
415 return ((a / 1000) == (b / 1000)); 415 return ((a / 1000) == (b / 1000));
416} 416}
417 417
418static int
419calc_mclk(struct drm_device *dev, u32 freq, struct hwsq_ucode *hwsq)
420{
421 struct drm_nouveau_private *dev_priv = dev->dev_private;
422 struct pll_lims pll;
423 u32 mast = nv_rd32(dev, 0x00c040);
424 u32 ctrl = nv_rd32(dev, 0x004008);
425 u32 coef = nv_rd32(dev, 0x00400c);
426 u32 orig = ctrl;
427 u32 crtc_mask = 0;
428 int N, M, P;
429 int ret, i;
430
431 /* use pcie refclock if possible, otherwise use mpll */
432 ctrl &= ~0x81ff0200;
433 if (clk_same(freq, read_clk(dev, clk_src_href))) {
434 ctrl |= 0x00000200 | (pll.log2p_bias << 19);
435 } else {
436 ret = calc_pll(dev, 0x4008, &pll, freq, &N, &M, &P);
437 if (ret == 0)
438 return -EINVAL;
439
440 ctrl |= 0x80000000 | (P << 22) | (P << 16);
441 ctrl |= pll.log2p_bias << 19;
442 coef = (N << 8) | M;
443 }
444
445 mast &= ~0xc0000000; /* get MCLK_2 from HREF */
446 mast |= 0x0000c000; /* use MCLK_2 as MPLL_BYPASS clock */
447
448 /* determine active crtcs */
449 for (i = 0; i < 2; i++) {
450 if (nv_rd32(dev, NV50_PDISPLAY_CRTC_C(i, CLOCK)))
451 crtc_mask |= (1 << i);
452 }
453
454 /* build the ucode which will reclock the memory for us */
455 hwsq_init(hwsq);
456 if (crtc_mask) {
457 hwsq_op5f(hwsq, crtc_mask, 0x00); /* wait for scanout */
458 hwsq_op5f(hwsq, crtc_mask, 0x01); /* wait for vblank */
459 }
460 if (dev_priv->chipset >= 0x92)
461 hwsq_wr32(hwsq, 0x611200, 0x00003300); /* disable scanout */
462 hwsq_unkn(hwsq, 0xb0); /* disable bus access */
463 hwsq_op5f(hwsq, 0x00, 0x01); /* no idea :s */
464
465 /* prepare memory controller */
466 hwsq_wr32(hwsq, 0x1002d4, 0x00000001); /* precharge banks and idle */
467 hwsq_wr32(hwsq, 0x1002d0, 0x00000001); /* force refresh */
468 hwsq_wr32(hwsq, 0x100210, 0x00000000); /* stop the automatic refresh */
469 hwsq_wr32(hwsq, 0x1002dc, 0x00000001); /* start self refresh mode */
470
471 /* reclock memory */
472 hwsq_wr32(hwsq, 0xc040, mast);
473 hwsq_wr32(hwsq, 0x4008, orig | 0x00000200); /* bypass MPLL */
474 hwsq_wr32(hwsq, 0x400c, coef);
475 hwsq_wr32(hwsq, 0x4008, ctrl);
476
477 /* restart memory controller */
478 hwsq_wr32(hwsq, 0x1002d4, 0x00000001); /* precharge banks and idle */
479 hwsq_wr32(hwsq, 0x1002dc, 0x00000000); /* stop self refresh mode */
480 hwsq_wr32(hwsq, 0x100210, 0x80000000); /* restart automatic refresh */
481 hwsq_unkn(hwsq, 0x07); /* wait for the PLL to stabilize (12us) */
482
483 hwsq_unkn(hwsq, 0x0b); /* may be unnecessary: causes flickering */
484 hwsq_unkn(hwsq, 0xd0); /* enable bus access again */
485 hwsq_op5f(hwsq, 0x00, 0x00); /* no idea, reverse of 0x00, 0x01? */
486 if (dev_priv->chipset >= 0x92)
487 hwsq_wr32(hwsq, 0x611200, 0x00003330); /* enable scanout */
488 hwsq_fini(hwsq);
489 return 0;
490}
491
418void * 492void *
419nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) 493nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
420{ 494{
@@ -462,23 +536,16 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
462 info->scoef = (N << 8) | M; 536 info->scoef = (N << 8) | M;
463 } 537 }
464 538
465 /* memory: use pcie refclock if possible, otherwise use mpll */ 539 /* memory: build hwsq ucode which we'll use to reclock memory */
466 info->mscript = perflvl->memscript; 540 info->mclk_hwsq.len = 0;
467 if (clk_same(perflvl->memory, read_clk(dev, clk_src_href))) {
468 info->mctrl = 0x00000200 | (pll.log2p_bias << 19);
469 info->mcoef = nv_rd32(dev, 0x400c);
470 } else
471 if (perflvl->memory) { 541 if (perflvl->memory) {
472 clk = calc_pll(dev, 0x4008, &pll, perflvl->memory, 542 clk = calc_mclk(dev, perflvl->memory, &info->mclk_hwsq);
473 &N, &M, &P1); 543 if (clk < 0) {
474 if (clk == 0) 544 ret = clk;
475 goto error; 545 goto error;
546 }
476 547
477 info->mctrl = 0x80000000 | (P1 << 22) | (P1 << 16); 548 info->mscript = perflvl->memscript;
478 info->mctrl |= pll.log2p_bias << 19;
479 info->mcoef = (N << 8) | M;
480 } else {
481 info->mctrl = 0x00000000;
482 } 549 }
483 550
484 /* vdec: avoid modifying xpll until we know exactly how the other 551 /* vdec: avoid modifying xpll until we know exactly how the other
@@ -537,6 +604,44 @@ error:
537 return ERR_PTR(ret); 604 return ERR_PTR(ret);
538} 605}
539 606
607static int
608prog_mclk(struct drm_device *dev, struct hwsq_ucode *hwsq)
609{
610 struct drm_nouveau_private *dev_priv = dev->dev_private;
611 u32 hwsq_data, hwsq_kick;
612 int i;
613
614 if (dev_priv->chipset < 0x90) {
615 hwsq_data = 0x001400;
616 hwsq_kick = 0x00000003;
617 } else {
618 hwsq_data = 0x080000;
619 hwsq_kick = 0x00000001;
620 }
621
622 /* upload hwsq ucode */
623 nv_mask(dev, 0x001098, 0x00000008, 0x00000000);
624 nv_wr32(dev, 0x001304, 0x00000000);
625 for (i = 0; i < hwsq->len / 4; i++)
626 nv_wr32(dev, hwsq_data + (i * 4), hwsq->ptr.u32[i]);
627 nv_mask(dev, 0x001098, 0x00000018, 0x00000018);
628
629 /* launch, and wait for completion */
630 nv_wr32(dev, 0x00130c, hwsq_kick);
631 if (!nv_wait(dev, 0x001308, 0x00000100, 0x00000000)) {
632 NV_ERROR(dev, "hwsq ucode exec timed out\n");
633 NV_ERROR(dev, "0x001308: 0x%08x\n", nv_rd32(dev, 0x001308));
634 for (i = 0; i < hwsq->len / 4; i++) {
635 NV_ERROR(dev, "0x%06x: 0x%08x\n", 0x1400 + (i * 4),
636 nv_rd32(dev, 0x001400 + (i * 4)));
637 }
638
639 return -EIO;
640 }
641
642 return 0;
643}
644
540int 645int
541nv50_pm_clocks_set(struct drm_device *dev, void *data) 646nv50_pm_clocks_set(struct drm_device *dev, void *data)
542{ 647{
@@ -550,6 +655,28 @@ nv50_pm_clocks_set(struct drm_device *dev, void *data)
550 if (!nv_wait(dev, 0x002504, 0x00000010, 0x00000010)) 655 if (!nv_wait(dev, 0x002504, 0x00000010, 0x00000010))
551 goto error; 656 goto error;
552 657
658 /* memory: it is *very* important we change this first, the ucode
659 * we build in pre() now has hardcoded 0xc040 values, which can't
660 * change before we execute it or the engine clocks may end up
661 * messed up.
662 */
663 if (info->mclk_hwsq.len) {
664 /* execute some scripts that do ??? from the vbios.. */
665 if (!bit_table(dev, 'M', &M) && M.version == 1) {
666 if (M.length >= 6)
667 nouveau_bios_init_exec(dev, ROM16(M.data[5]));
668 if (M.length >= 8)
669 nouveau_bios_init_exec(dev, ROM16(M.data[7]));
670 if (M.length >= 10)
671 nouveau_bios_init_exec(dev, ROM16(M.data[9]));
672 nouveau_bios_init_exec(dev, info->mscript);
673 }
674
675 ret = prog_mclk(dev, &info->mclk_hwsq);
676 if (ret)
677 goto resume;
678 }
679
553 /* reclock vdec/dom6 */ 680 /* reclock vdec/dom6 */
554 nv_mask(dev, 0x00c040, 0x00000c00, 0x00000000); 681 nv_mask(dev, 0x00c040, 0x00000c00, 0x00000000);
555 switch (dev_priv->chipset) { 682 switch (dev_priv->chipset) {
@@ -578,50 +705,6 @@ nv50_pm_clocks_set(struct drm_device *dev, void *data)
578 nv_wr32(dev, 0x00402c, info->ncoef); 705 nv_wr32(dev, 0x00402c, info->ncoef);
579 nv_mask(dev, 0x00c040, 0x00100033, info->emast); 706 nv_mask(dev, 0x00c040, 0x00100033, info->emast);
580 707
581 /* memory */
582 if (!info->mctrl)
583 goto resume;
584
585 /* execute some scripts that do ??? from the vbios.. */
586 if (!bit_table(dev, 'M', &M) && M.version == 1) {
587 if (M.length >= 6)
588 nouveau_bios_init_exec(dev, ROM16(M.data[5]));
589 if (M.length >= 8)
590 nouveau_bios_init_exec(dev, ROM16(M.data[7]));
591 if (M.length >= 10)
592 nouveau_bios_init_exec(dev, ROM16(M.data[9]));
593 nouveau_bios_init_exec(dev, info->mscript);
594 }
595
596 /* disable display */
597 if (dev_priv->chipset >= 0x92) {
598 nv_wr32(dev, 0x611200, 0x00003300);
599 udelay(100);
600 }
601
602 /* prepare ram for reclocking */
603 nv_wr32(dev, 0x1002d4, 0x00000001); /* precharge */
604 nv_wr32(dev, 0x1002d0, 0x00000001); /* refresh */
605 nv_wr32(dev, 0x1002d0, 0x00000001); /* refresh */
606 nv_mask(dev, 0x100210, 0x80000000, 0x00000000); /* no auto-refresh */
607 nv_wr32(dev, 0x1002dc, 0x00000001); /* enable self-refresh */
608
609 /* modify mpll */
610 nv_mask(dev, 0x00c040, 0x0000c000, 0x0000c000);
611 nv_mask(dev, 0x004008, 0x01ff0200, 0x00000200 | info->mctrl);
612 nv_wr32(dev, 0x00400c, info->mcoef);
613 udelay(100);
614 nv_mask(dev, 0x004008, 0x81ff0200, info->mctrl);
615
616 /* re-enable normal operation of memory controller */
617 nv_wr32(dev, 0x1002dc, 0x00000000);
618 nv_mask(dev, 0x100210, 0x80000000, 0x80000000);
619 udelay(100);
620
621 /* re-enable display */
622 if (dev_priv->chipset >= 0x92)
623 nv_wr32(dev, 0x611200, 0x00003330);
624
625 goto resume; 708 goto resume;
626error: 709error:
627 ret = -EBUSY; 710 ret = -EBUSY;