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.c397
1 files changed, 257 insertions, 140 deletions
diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c
index ec5481dfcd82..d020ed4979b4 100644
--- a/drivers/gpu/drm/nouveau/nv50_pm.c
+++ b/drivers/gpu/drm/nouveau/nv50_pm.c
@@ -28,6 +28,7 @@
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#include "nouveau_hwsq.h"
31#include "nv50_display.h"
31 32
32enum clk_src { 33enum clk_src {
33 clk_src_crystal, 34 clk_src_crystal,
@@ -352,17 +353,13 @@ nv50_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
352} 353}
353 354
354struct nv50_pm_state { 355struct nv50_pm_state {
356 struct nouveau_pm_level *perflvl;
357 struct hwsq_ucode eclk_hwsq;
355 struct hwsq_ucode mclk_hwsq; 358 struct hwsq_ucode mclk_hwsq;
356 u32 mscript; 359 u32 mscript;
357 360 u32 mmast;
358 u32 emast; 361 u32 mctrl;
359 u32 nctrl; 362 u32 mcoef;
360 u32 ncoef;
361 u32 sctrl;
362 u32 scoef;
363
364 u32 amast;
365 u32 pdivs;
366}; 363};
367 364
368static u32 365static u32
@@ -415,40 +412,153 @@ clk_same(u32 a, u32 b)
415 return ((a / 1000) == (b / 1000)); 412 return ((a / 1000) == (b / 1000));
416} 413}
417 414
415static void
416mclk_precharge(struct nouveau_mem_exec_func *exec)
417{
418 struct nv50_pm_state *info = exec->priv;
419 struct hwsq_ucode *hwsq = &info->mclk_hwsq;
420
421 hwsq_wr32(hwsq, 0x1002d4, 0x00000001);
422}
423
424static void
425mclk_refresh(struct nouveau_mem_exec_func *exec)
426{
427 struct nv50_pm_state *info = exec->priv;
428 struct hwsq_ucode *hwsq = &info->mclk_hwsq;
429
430 hwsq_wr32(hwsq, 0x1002d0, 0x00000001);
431}
432
433static void
434mclk_refresh_auto(struct nouveau_mem_exec_func *exec, bool enable)
435{
436 struct nv50_pm_state *info = exec->priv;
437 struct hwsq_ucode *hwsq = &info->mclk_hwsq;
438
439 hwsq_wr32(hwsq, 0x100210, enable ? 0x80000000 : 0x00000000);
440}
441
442static void
443mclk_refresh_self(struct nouveau_mem_exec_func *exec, bool enable)
444{
445 struct nv50_pm_state *info = exec->priv;
446 struct hwsq_ucode *hwsq = &info->mclk_hwsq;
447
448 hwsq_wr32(hwsq, 0x1002dc, enable ? 0x00000001 : 0x00000000);
449}
450
451static void
452mclk_wait(struct nouveau_mem_exec_func *exec, u32 nsec)
453{
454 struct nv50_pm_state *info = exec->priv;
455 struct hwsq_ucode *hwsq = &info->mclk_hwsq;
456
457 if (nsec > 1000)
458 hwsq_usec(hwsq, (nsec + 500) / 1000);
459}
460
461static u32
462mclk_mrg(struct nouveau_mem_exec_func *exec, int mr)
463{
464 if (mr <= 1)
465 return nv_rd32(exec->dev, 0x1002c0 + ((mr - 0) * 4));
466 if (mr <= 3)
467 return nv_rd32(exec->dev, 0x1002e0 + ((mr - 2) * 4));
468 return 0;
469}
470
471static void
472mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data)
473{
474 struct drm_nouveau_private *dev_priv = exec->dev->dev_private;
475 struct nv50_pm_state *info = exec->priv;
476 struct hwsq_ucode *hwsq = &info->mclk_hwsq;
477
478 if (mr <= 1) {
479 if (dev_priv->vram_rank_B)
480 hwsq_wr32(hwsq, 0x1002c8 + ((mr - 0) * 4), data);
481 hwsq_wr32(hwsq, 0x1002c0 + ((mr - 0) * 4), data);
482 } else
483 if (mr <= 3) {
484 if (dev_priv->vram_rank_B)
485 hwsq_wr32(hwsq, 0x1002e8 + ((mr - 2) * 4), data);
486 hwsq_wr32(hwsq, 0x1002e0 + ((mr - 2) * 4), data);
487 }
488}
489
490static void
491mclk_clock_set(struct nouveau_mem_exec_func *exec)
492{
493 struct nv50_pm_state *info = exec->priv;
494 struct hwsq_ucode *hwsq = &info->mclk_hwsq;
495 u32 ctrl = nv_rd32(exec->dev, 0x004008);
496
497 info->mmast = nv_rd32(exec->dev, 0x00c040);
498 info->mmast &= ~0xc0000000; /* get MCLK_2 from HREF */
499 info->mmast |= 0x0000c000; /* use MCLK_2 as MPLL_BYPASS clock */
500
501 hwsq_wr32(hwsq, 0xc040, info->mmast);
502 hwsq_wr32(hwsq, 0x4008, ctrl | 0x00000200); /* bypass MPLL */
503 if (info->mctrl & 0x80000000)
504 hwsq_wr32(hwsq, 0x400c, info->mcoef);
505 hwsq_wr32(hwsq, 0x4008, info->mctrl);
506}
507
508static void
509mclk_timing_set(struct nouveau_mem_exec_func *exec)
510{
511 struct drm_device *dev = exec->dev;
512 struct nv50_pm_state *info = exec->priv;
513 struct nouveau_pm_level *perflvl = info->perflvl;
514 struct hwsq_ucode *hwsq = &info->mclk_hwsq;
515 int i;
516
517 for (i = 0; i < 9; i++) {
518 u32 reg = 0x100220 + (i * 4);
519 u32 val = nv_rd32(dev, reg);
520 if (val != perflvl->timing.reg[i])
521 hwsq_wr32(hwsq, reg, perflvl->timing.reg[i]);
522 }
523}
524
418static int 525static int
419calc_mclk(struct drm_device *dev, u32 freq, struct hwsq_ucode *hwsq) 526calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl,
527 struct nv50_pm_state *info)
420{ 528{
421 struct drm_nouveau_private *dev_priv = dev->dev_private; 529 struct drm_nouveau_private *dev_priv = dev->dev_private;
530 u32 crtc_mask = nv50_display_active_crtcs(dev);
531 struct nouveau_mem_exec_func exec = {
532 .dev = dev,
533 .precharge = mclk_precharge,
534 .refresh = mclk_refresh,
535 .refresh_auto = mclk_refresh_auto,
536 .refresh_self = mclk_refresh_self,
537 .wait = mclk_wait,
538 .mrg = mclk_mrg,
539 .mrs = mclk_mrs,
540 .clock_set = mclk_clock_set,
541 .timing_set = mclk_timing_set,
542 .priv = info
543 };
544 struct hwsq_ucode *hwsq = &info->mclk_hwsq;
422 struct pll_lims pll; 545 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; 546 int N, M, P;
429 int ret, i; 547 int ret;
430 548
431 /* use pcie refclock if possible, otherwise use mpll */ 549 /* use pcie refclock if possible, otherwise use mpll */
432 ctrl &= ~0x81ff0200; 550 info->mctrl = nv_rd32(dev, 0x004008);
433 if (clk_same(freq, read_clk(dev, clk_src_href))) { 551 info->mctrl &= ~0x81ff0200;
434 ctrl |= 0x00000200 | (pll.log2p_bias << 19); 552 if (clk_same(perflvl->memory, read_clk(dev, clk_src_href))) {
553 info->mctrl |= 0x00000200 | (pll.log2p_bias << 19);
435 } else { 554 } else {
436 ret = calc_pll(dev, 0x4008, &pll, freq, &N, &M, &P); 555 ret = calc_pll(dev, 0x4008, &pll, perflvl->memory, &N, &M, &P);
437 if (ret == 0) 556 if (ret == 0)
438 return -EINVAL; 557 return -EINVAL;
439 558
440 ctrl |= 0x80000000 | (P << 22) | (P << 16); 559 info->mctrl |= 0x80000000 | (P << 22) | (P << 16);
441 ctrl |= pll.log2p_bias << 19; 560 info->mctrl |= pll.log2p_bias << 19;
442 coef = (N << 8) | M; 561 info->mcoef = (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 } 562 }
453 563
454 /* build the ucode which will reclock the memory for us */ 564 /* build the ucode which will reclock the memory for us */
@@ -462,25 +572,10 @@ calc_mclk(struct drm_device *dev, u32 freq, struct hwsq_ucode *hwsq)
462 hwsq_setf(hwsq, 0x10, 0); /* disable bus access */ 572 hwsq_setf(hwsq, 0x10, 0); /* disable bus access */
463 hwsq_op5f(hwsq, 0x00, 0x01); /* no idea :s */ 573 hwsq_op5f(hwsq, 0x00, 0x01); /* no idea :s */
464 574
465 /* prepare memory controller */ 575 ret = nouveau_mem_exec(&exec, perflvl);
466 hwsq_wr32(hwsq, 0x1002d4, 0x00000001); /* precharge banks and idle */ 576 if (ret)
467 hwsq_wr32(hwsq, 0x1002d0, 0x00000001); /* force refresh */ 577 return ret;
468 hwsq_wr32(hwsq, 0x100210, 0x00000000); /* stop the automatic refresh */ 578
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_usec(hwsq, 12); /* wait for the PLL to stabilize */
482
483 hwsq_usec(hwsq, 48); /* may be unnecessary: causes flickering */
484 hwsq_setf(hwsq, 0x10, 1); /* enable bus access */ 579 hwsq_setf(hwsq, 0x10, 1); /* enable bus access */
485 hwsq_op5f(hwsq, 0x00, 0x00); /* no idea, reverse of 0x00, 0x01? */ 580 hwsq_op5f(hwsq, 0x00, 0x00); /* no idea, reverse of 0x00, 0x01? */
486 if (dev_priv->chipset >= 0x92) 581 if (dev_priv->chipset >= 0x92)
@@ -494,10 +589,11 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
494{ 589{
495 struct drm_nouveau_private *dev_priv = dev->dev_private; 590 struct drm_nouveau_private *dev_priv = dev->dev_private;
496 struct nv50_pm_state *info; 591 struct nv50_pm_state *info;
592 struct hwsq_ucode *hwsq;
497 struct pll_lims pll; 593 struct pll_lims pll;
594 u32 out, mast, divs, ctrl;
498 int clk, ret = -EINVAL; 595 int clk, ret = -EINVAL;
499 int N, M, P1, P2; 596 int N, M, P1, P2;
500 u32 out;
501 597
502 if (dev_priv->chipset == 0xaa || 598 if (dev_priv->chipset == 0xaa ||
503 dev_priv->chipset == 0xac) 599 dev_priv->chipset == 0xac)
@@ -506,54 +602,44 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
506 info = kmalloc(sizeof(*info), GFP_KERNEL); 602 info = kmalloc(sizeof(*info), GFP_KERNEL);
507 if (!info) 603 if (!info)
508 return ERR_PTR(-ENOMEM); 604 return ERR_PTR(-ENOMEM);
605 info->perflvl = perflvl;
509 606
510 /* core: for the moment at least, always use nvpll */ 607 /* memory: build hwsq ucode which we'll use to reclock memory.
511 clk = calc_pll(dev, 0x4028, &pll, perflvl->core, &N, &M, &P1); 608 * use pcie refclock if possible, otherwise use mpll */
512 if (clk == 0) 609 info->mclk_hwsq.len = 0;
513 goto error; 610 if (perflvl->memory) {
611 ret = calc_mclk(dev, perflvl, info);
612 if (ret)
613 goto error;
614 info->mscript = perflvl->memscript;
615 }
514 616
515 info->emast = 0x00000003; 617 divs = read_div(dev);
516 info->nctrl = 0x80000000 | (P1 << 19) | (P1 << 16); 618 mast = info->mmast;
517 info->ncoef = (N << 8) | M;
518 619
519 /* shader: tie to nvclk if possible, otherwise use spll. have to be 620 /* start building HWSQ script for engine reclocking */
520 * very careful that the shader clock is at least twice the core, or 621 hwsq = &info->eclk_hwsq;
521 * some chipsets will be very unhappy. i expect most or all of these 622 hwsq_init(hwsq);
522 * cases will be handled by tying to nvclk, but it's possible there's 623 hwsq_setf(hwsq, 0x10, 0); /* disable bus access */
523 * corners 624 hwsq_op5f(hwsq, 0x00, 0x01); /* wait for access disabled? */
524 */
525 if (P1-- && perflvl->shader == (perflvl->core << 1)) {
526 info->emast |= 0x00000020;
527 info->sctrl = 0x00000000 | (P1 << 19) | (P1 << 16);
528 info->scoef = nv_rd32(dev, 0x004024);
529 } else {
530 clk = calc_pll(dev, 0x4020, &pll, perflvl->shader, &N, &M, &P1);
531 if (clk == 0)
532 goto error;
533 625
534 info->emast |= 0x00000030; 626 /* vdec/dom6: switch to "safe" clocks temporarily */
535 info->sctrl = 0x80000000 | (P1 << 19) | (P1 << 16); 627 if (perflvl->vdec) {
536 info->scoef = (N << 8) | M; 628 mast &= ~0x00000c00;
629 divs &= ~0x00000700;
537 } 630 }
538 631
539 /* memory: build hwsq ucode which we'll use to reclock memory */ 632 if (perflvl->dom6) {
540 info->mclk_hwsq.len = 0; 633 mast &= ~0x0c000000;
541 if (perflvl->memory) { 634 divs &= ~0x00000007;
542 clk = calc_mclk(dev, perflvl->memory, &info->mclk_hwsq);
543 if (clk < 0) {
544 ret = clk;
545 goto error;
546 }
547
548 info->mscript = perflvl->memscript;
549 } 635 }
550 636
637 hwsq_wr32(hwsq, 0x00c040, mast);
638
551 /* vdec: avoid modifying xpll until we know exactly how the other 639 /* vdec: avoid modifying xpll until we know exactly how the other
552 * clock domains work, i suspect at least some of them can also be 640 * clock domains work, i suspect at least some of them can also be
553 * tied to xpll... 641 * tied to xpll...
554 */ 642 */
555 info->amast = nv_rd32(dev, 0x00c040);
556 info->pdivs = read_div(dev);
557 if (perflvl->vdec) { 643 if (perflvl->vdec) {
558 /* see how close we can get using nvclk as a source */ 644 /* see how close we can get using nvclk as a source */
559 clk = calc_div(perflvl->core, perflvl->vdec, &P1); 645 clk = calc_div(perflvl->core, perflvl->vdec, &P1);
@@ -566,16 +652,14 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
566 out = calc_div(out, perflvl->vdec, &P2); 652 out = calc_div(out, perflvl->vdec, &P2);
567 653
568 /* select whichever gets us closest */ 654 /* select whichever gets us closest */
569 info->amast &= ~0x00000c00;
570 info->pdivs &= ~0x00000700;
571 if (abs((int)perflvl->vdec - clk) <= 655 if (abs((int)perflvl->vdec - clk) <=
572 abs((int)perflvl->vdec - out)) { 656 abs((int)perflvl->vdec - out)) {
573 if (dev_priv->chipset != 0x98) 657 if (dev_priv->chipset != 0x98)
574 info->amast |= 0x00000c00; 658 mast |= 0x00000c00;
575 info->pdivs |= P1 << 8; 659 divs |= P1 << 8;
576 } else { 660 } else {
577 info->amast |= 0x00000800; 661 mast |= 0x00000800;
578 info->pdivs |= P2 << 8; 662 divs |= P2 << 8;
579 } 663 }
580 } 664 }
581 665
@@ -583,21 +667,82 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
583 * of the host clock frequency 667 * of the host clock frequency
584 */ 668 */
585 if (perflvl->dom6) { 669 if (perflvl->dom6) {
586 info->amast &= ~0x0c000000;
587 if (clk_same(perflvl->dom6, read_clk(dev, clk_src_href))) { 670 if (clk_same(perflvl->dom6, read_clk(dev, clk_src_href))) {
588 info->amast |= 0x00000000; 671 mast |= 0x00000000;
589 } else 672 } else
590 if (clk_same(perflvl->dom6, read_clk(dev, clk_src_hclk))) { 673 if (clk_same(perflvl->dom6, read_clk(dev, clk_src_hclk))) {
591 info->amast |= 0x08000000; 674 mast |= 0x08000000;
592 } else { 675 } else {
593 clk = read_clk(dev, clk_src_hclk) * 3; 676 clk = read_clk(dev, clk_src_hclk) * 3;
594 clk = calc_div(clk, perflvl->dom6, &P1); 677 clk = calc_div(clk, perflvl->dom6, &P1);
595 678
596 info->amast |= 0x0c000000; 679 mast |= 0x0c000000;
597 info->pdivs = (info->pdivs & ~0x00000007) | P1; 680 divs |= P1;
598 } 681 }
599 } 682 }
600 683
684 /* vdec/dom6: complete switch to new clocks */
685 switch (dev_priv->chipset) {
686 case 0x92:
687 case 0x94:
688 case 0x96:
689 hwsq_wr32(hwsq, 0x004800, divs);
690 break;
691 default:
692 hwsq_wr32(hwsq, 0x004700, divs);
693 break;
694 }
695
696 hwsq_wr32(hwsq, 0x00c040, mast);
697
698 /* core/shader: make sure sclk/nvclk are disconnected from their
699 * PLLs (nvclk to dom6, sclk to hclk)
700 */
701 if (dev_priv->chipset < 0x92)
702 mast = (mast & ~0x001000b0) | 0x00100080;
703 else
704 mast = (mast & ~0x000000b3) | 0x00000081;
705
706 hwsq_wr32(hwsq, 0x00c040, mast);
707
708 /* core: for the moment at least, always use nvpll */
709 clk = calc_pll(dev, 0x4028, &pll, perflvl->core, &N, &M, &P1);
710 if (clk == 0)
711 goto error;
712
713 ctrl = nv_rd32(dev, 0x004028) & ~0xc03f0100;
714 mast &= ~0x00100000;
715 mast |= 3;
716
717 hwsq_wr32(hwsq, 0x004028, 0x80000000 | (P1 << 19) | (P1 << 16) | ctrl);
718 hwsq_wr32(hwsq, 0x00402c, (N << 8) | M);
719
720 /* shader: tie to nvclk if possible, otherwise use spll. have to be
721 * very careful that the shader clock is at least twice the core, or
722 * some chipsets will be very unhappy. i expect most or all of these
723 * cases will be handled by tying to nvclk, but it's possible there's
724 * corners
725 */
726 ctrl = nv_rd32(dev, 0x004020) & ~0xc03f0100;
727
728 if (P1-- && perflvl->shader == (perflvl->core << 1)) {
729 hwsq_wr32(hwsq, 0x004020, (P1 << 19) | (P1 << 16) | ctrl);
730 hwsq_wr32(hwsq, 0x00c040, 0x00000020 | mast);
731 } else {
732 clk = calc_pll(dev, 0x4020, &pll, perflvl->shader, &N, &M, &P1);
733 if (clk == 0)
734 goto error;
735 ctrl |= 0x80000000;
736
737 hwsq_wr32(hwsq, 0x004020, (P1 << 19) | (P1 << 16) | ctrl);
738 hwsq_wr32(hwsq, 0x004024, (N << 8) | M);
739 hwsq_wr32(hwsq, 0x00c040, 0x00000030 | mast);
740 }
741
742 hwsq_setf(hwsq, 0x10, 1); /* enable bus access */
743 hwsq_op5f(hwsq, 0x00, 0x00); /* wait for access enabled? */
744 hwsq_fini(hwsq);
745
601 return info; 746 return info;
602error: 747error:
603 kfree(info); 748 kfree(info);
@@ -605,23 +750,24 @@ error:
605} 750}
606 751
607static int 752static int
608prog_mclk(struct drm_device *dev, struct hwsq_ucode *hwsq) 753prog_hwsq(struct drm_device *dev, struct hwsq_ucode *hwsq)
609{ 754{
610 struct drm_nouveau_private *dev_priv = dev->dev_private; 755 struct drm_nouveau_private *dev_priv = dev->dev_private;
611 u32 hwsq_data, hwsq_kick; 756 u32 hwsq_data, hwsq_kick;
612 int i; 757 int i;
613 758
614 if (dev_priv->chipset < 0x90) { 759 if (dev_priv->chipset < 0x94) {
615 hwsq_data = 0x001400; 760 hwsq_data = 0x001400;
616 hwsq_kick = 0x00000003; 761 hwsq_kick = 0x00000003;
617 } else { 762 } else {
618 hwsq_data = 0x080000; 763 hwsq_data = 0x080000;
619 hwsq_kick = 0x00000001; 764 hwsq_kick = 0x00000001;
620 } 765 }
621
622 /* upload hwsq ucode */ 766 /* upload hwsq ucode */
623 nv_mask(dev, 0x001098, 0x00000008, 0x00000000); 767 nv_mask(dev, 0x001098, 0x00000008, 0x00000000);
624 nv_wr32(dev, 0x001304, 0x00000000); 768 nv_wr32(dev, 0x001304, 0x00000000);
769 if (dev_priv->chipset >= 0x92)
770 nv_wr32(dev, 0x001318, 0x00000000);
625 for (i = 0; i < hwsq->len / 4; i++) 771 for (i = 0; i < hwsq->len / 4; i++)
626 nv_wr32(dev, hwsq_data + (i * 4), hwsq->ptr.u32[i]); 772 nv_wr32(dev, hwsq_data + (i * 4), hwsq->ptr.u32[i]);
627 nv_mask(dev, 0x001098, 0x00000018, 0x00000018); 773 nv_mask(dev, 0x001098, 0x00000018, 0x00000018);
@@ -645,20 +791,19 @@ prog_mclk(struct drm_device *dev, struct hwsq_ucode *hwsq)
645int 791int
646nv50_pm_clocks_set(struct drm_device *dev, void *data) 792nv50_pm_clocks_set(struct drm_device *dev, void *data)
647{ 793{
648 struct drm_nouveau_private *dev_priv = dev->dev_private;
649 struct nv50_pm_state *info = data; 794 struct nv50_pm_state *info = data;
650 struct bit_entry M; 795 struct bit_entry M;
651 int ret = 0; 796 int ret = -EBUSY;
652 797
653 /* halt and idle execution engines */ 798 /* halt and idle execution engines */
654 nv_mask(dev, 0x002504, 0x00000001, 0x00000001); 799 nv_mask(dev, 0x002504, 0x00000001, 0x00000001);
655 if (!nv_wait(dev, 0x002504, 0x00000010, 0x00000010)) 800 if (!nv_wait(dev, 0x002504, 0x00000010, 0x00000010))
656 goto error; 801 goto resume;
802 if (!nv_wait(dev, 0x00251c, 0x0000003f, 0x0000003f))
803 goto resume;
657 804
658 /* memory: it is *very* important we change this first, the ucode 805 /* program memory clock, if necessary - must come before engine clock
659 * we build in pre() now has hardcoded 0xc040 values, which can't 806 * reprogramming due to how we construct the hwsq scripts in pre()
660 * change before we execute it or the engine clocks may end up
661 * messed up.
662 */ 807 */
663 if (info->mclk_hwsq.len) { 808 if (info->mclk_hwsq.len) {
664 /* execute some scripts that do ??? from the vbios.. */ 809 /* execute some scripts that do ??? from the vbios.. */
@@ -672,42 +817,14 @@ nv50_pm_clocks_set(struct drm_device *dev, void *data)
672 nouveau_bios_init_exec(dev, info->mscript); 817 nouveau_bios_init_exec(dev, info->mscript);
673 } 818 }
674 819
675 ret = prog_mclk(dev, &info->mclk_hwsq); 820 ret = prog_hwsq(dev, &info->mclk_hwsq);
676 if (ret) 821 if (ret)
677 goto resume; 822 goto resume;
678 } 823 }
679 824
680 /* reclock vdec/dom6 */ 825 /* program engine clocks */
681 nv_mask(dev, 0x00c040, 0x00000c00, 0x00000000); 826 ret = prog_hwsq(dev, &info->eclk_hwsq);
682 switch (dev_priv->chipset) {
683 case 0x92:
684 case 0x94:
685 case 0x96:
686 nv_mask(dev, 0x004800, 0x00000707, info->pdivs);
687 break;
688 default:
689 nv_mask(dev, 0x004700, 0x00000707, info->pdivs);
690 break;
691 }
692 nv_mask(dev, 0x00c040, 0x0c000c00, info->amast);
693 827
694 /* core/shader: make sure sclk/nvclk are disconnected from their
695 * plls (nvclk to dom6, sclk to hclk), modify the plls, and
696 * reconnect sclk/nvclk to their new clock source
697 */
698 if (dev_priv->chipset < 0x92)
699 nv_mask(dev, 0x00c040, 0x001000b0, 0x00100080); /* grrr! */
700 else
701 nv_mask(dev, 0x00c040, 0x000000b3, 0x00000081);
702 nv_mask(dev, 0x004020, 0xc03f0100, info->sctrl);
703 nv_wr32(dev, 0x004024, info->scoef);
704 nv_mask(dev, 0x004028, 0xc03f0100, info->nctrl);
705 nv_wr32(dev, 0x00402c, info->ncoef);
706 nv_mask(dev, 0x00c040, 0x00100033, info->emast);
707
708 goto resume;
709error:
710 ret = -EBUSY;
711resume: 828resume:
712 nv_mask(dev, 0x002504, 0x00000001, 0x00000000); 829 nv_mask(dev, 0x002504, 0x00000001, 0x00000000);
713 kfree(info); 830 kfree(info);