aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_mem.c
diff options
context:
space:
mode:
authorRoy Spliet <r.spliet@student.tudelft.nl>2012-01-09 00:23:07 -0500
committerBen Skeggs <bskeggs@redhat.com>2012-03-13 03:07:50 -0400
commitc7c039fd31be82ecb8d48477955e76badd38141a (patch)
tree0b527eba7fd021ce99c52d9f744d503d0919849c /drivers/gpu/drm/nouveau/nouveau_mem.c
parent03ddf04bdb9cc4cdf8edb231b78f031647498314 (diff)
drm/nouveau/pm: implement DDR2/DDR3/GDDR3/GDDR5 MR generation and validation
Roy Spliet: - Implement according to specs - Simplify - Make array for mc latency registers Martin Peres: - squash and split all the commits from Roy - rework following Ben Skeggs comments - add a form of timings validation - store the initial timings for later use Ben Skeggs - merge slightly modified tidy-up patch with this one - remove perflvl-dropping logic for the moment Signed-off-by: Roy Spliet <r.spliet@student.tudelft.nl> Signed-off-by: Martin Peres <martin.peres@labri.fr> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_mem.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mem.c588
1 files changed, 455 insertions, 133 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c
index 3337f2cfb5f6..1cd29c02a7e9 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c
@@ -471,50 +471,41 @@ nouveau_mem_gart_init(struct drm_device *dev)
471 return 0; 471 return 0;
472} 472}
473 473
474/* XXX: For now a dummy. More samples required, possibly even a card 474static void
475 * Called from nouveau_perf.c */ 475nv40_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr,
476void nv30_mem_timing_entry(struct drm_device *dev, 476 struct nouveau_pm_tbl_entry *e,
477 struct nouveau_pm_tbl_header *hdr, 477 struct nouveau_pm_memtiming *t,
478 struct nouveau_pm_tbl_entry *e, uint8_t magic_number, 478 struct nouveau_pm_memtiming *boot)
479 struct nouveau_pm_memtiming *timing)
480{
481
482 NV_DEBUG(dev, "Timing entry format unknown, "
483 "please contact nouveau developers");
484}
485
486void nv40_mem_timing_entry(struct drm_device *dev,
487 struct nouveau_pm_tbl_header *hdr,
488 struct nouveau_pm_tbl_entry *e,
489 struct nouveau_pm_memtiming *timing)
490{ 479{
491 480
492 timing->reg_0 = (e->tRP << 24 | e->tRAS << 16 | e->tRFC << 8 | e->tRC); 481 t->reg[0] = (e->tRP << 24 | e->tRAS << 16 | e->tRFC << 8 | e->tRC);
493 482
494 /* XXX: I don't trust the -1's and +1's... they must come 483 /* XXX: I don't trust the -1's and +1's... they must come
495 * from somewhere! */ 484 * from somewhere! */
496 timing->reg_1 = (e->tWR + 2 + (timing->tCWL - 1)) << 24 | 485 t->reg[1] = (e->tWR + 2 + (t->tCWL - 1)) << 24 |
497 1 << 16 | 486 1 << 16 |
498 (e->tWTR + 2 + (timing->tCWL - 1)) << 8 | 487 (e->tWTR + 2 + (t->tCWL - 1)) << 8 |
499 (e->tCL + 2 - (timing->tCWL - 1)); 488 (e->tCL + 2 - (t->tCWL - 1));
500 489
501 timing->reg_2 = 0x20200000 | ((timing->tCWL - 1) << 24 | 490 t->reg[2] = 0x20200000 |
502 e->tRRD << 16 | e->tRCDWR << 8 | e->tRCDRD); 491 ((t->tCWL - 1) << 24 |
503 492 e->tRRD << 16 |
504 NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x\n", timing->id, 493 e->tRCDWR << 8 |
505 timing->reg_0, timing->reg_1, timing->reg_2); 494 e->tRCDRD);
495
496 NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x\n", t->id,
497 t->reg[0], t->reg[1], t->reg[2]);
506} 498}
507 499
508void nv50_mem_timing_entry(struct drm_device *dev, struct bit_entry *P, 500static void
509 struct nouveau_pm_tbl_header *hdr, 501nv50_mem_timing_entry(struct drm_device *dev, struct bit_entry *P,
510 struct nouveau_pm_tbl_entry *e, 502 struct nouveau_pm_tbl_header *hdr,
511 struct nouveau_pm_memtiming *timing) 503 struct nouveau_pm_tbl_entry *e,
504 struct nouveau_pm_memtiming *t,
505 struct nouveau_pm_memtiming *boot)
512{ 506{
513 struct drm_nouveau_private *dev_priv = dev->dev_private; 507 struct drm_nouveau_private *dev_priv = dev->dev_private;
514 uint8_t unk18 = 1, 508 uint8_t unk18 = 1, unk20 = 0, unk21 = 0, tmp7_3;
515 unk20 = 0,
516 unk21 = 0,
517 tmp7_3;
518 509
519 switch (min(hdr->entry_len, (u8) 22)) { 510 switch (min(hdr->entry_len, (u8) 22)) {
520 case 22: 511 case 22:
@@ -523,132 +514,414 @@ void nv50_mem_timing_entry(struct drm_device *dev, struct bit_entry *P,
523 unk20 = e->tUNK_20; 514 unk20 = e->tUNK_20;
524 case 20: 515 case 20:
525 if (e->tCWL > 0) 516 if (e->tCWL > 0)
526 timing->tCWL = e->tCWL; 517 t->tCWL = e->tCWL;
527 case 19: 518 case 19:
528 unk18 = e->tUNK_18; 519 unk18 = e->tUNK_18;
529 break; 520 break;
530 } 521 }
531 522
532 timing->reg_0 = (e->tRP << 24 | e->tRAS << 16 | e->tRFC << 8 | e->tRC); 523 t->reg[0] = (e->tRP << 24 | e->tRAS << 16 | e->tRFC << 8 | e->tRC);
533 524
534 timing->reg_1 = (e->tWR + 2 + (timing->tCWL - 1)) << 24 | 525 t->reg[1] = (e->tWR + 2 + (t->tCWL - 1)) << 24 |
535 max(unk18, (u8) 1) << 16 | 526 max(unk18, (u8) 1) << 16 |
536 (e->tWTR + 2 + (timing->tCWL - 1)) << 8; 527 (e->tWTR + 2 + (t->tCWL - 1)) << 8;
537 528
538 timing->reg_2 = ((timing->tCWL - 1) << 24 | e->tRRD << 16 | 529 t->reg[2] = ((t->tCWL - 1) << 24 |
539 e->tRCDWR << 8 | e->tRCDRD); 530 e->tRRD << 16 |
531 e->tRCDWR << 8 |
532 e->tRCDRD);
540 533
541 timing->reg_4 = e->tUNK_13 << 8 | e->tUNK_13; 534 t->reg[4] = e->tUNK_13 << 8 | e->tUNK_13;
542 535
543 timing->reg_5 = (e->tRFC << 24 | max(e->tRCDRD, e->tRCDWR) << 16 | 536 t->reg[5] = (e->tRFC << 24 | max(e->tRCDRD, e->tRCDWR) << 16 | e->tRP);
544 e->tRP);
545 537
546 timing->reg_8 = (nv_rd32(dev, 0x100240) & 0xffffff00); 538 t->reg[8] = boot->reg[8] & 0xffffff00;
547 539
548 if (P->version == 1) { 540 if (P->version == 1) {
549 timing->reg_1 |= (e->tCL + 2 - (timing->tCWL - 1)); 541 t->reg[1] |= (e->tCL + 2 - (t->tCWL - 1));
550 542
551 timing->reg_3 = (0x14 + e->tCL) << 24 | 543 t->reg[3] = (0x14 + e->tCL) << 24 |
552 0x16 << 16 | 544 0x16 << 16 |
553 (e->tCL - 1) << 8 | 545 (e->tCL - 1) << 8 |
554 (e->tCL - 1); 546 (e->tCL - 1);
555 547
556 timing->reg_4 |= (nv_rd32(dev, 0x100230) & 0xffff0000); 548 t->reg[4] |= boot->reg[4] & 0xffff0000;
557 549
558 timing->reg_6 = (0x33 - timing->tCWL) << 16 | 550 t->reg[6] = (0x33 - t->tCWL) << 16 |
559 timing->tCWL << 8 | 551 t->tCWL << 8 |
560 (0x2E + e->tCL - timing->tCWL); 552 (0x2e + e->tCL - t->tCWL);
561 553
562 timing->reg_7 = 0x4000202 | (e->tCL - 1) << 16; 554 t->reg[7] = 0x4000202 | (e->tCL - 1) << 16;
563 555
564 /* XXX: P.version == 1 only has DDR2 and GDDR3? */ 556 /* XXX: P.version == 1 only has DDR2 and GDDR3? */
565 if (dev_priv->vram_type == NV_MEM_TYPE_DDR2) { 557 if (dev_priv->vram_type == NV_MEM_TYPE_DDR2) {
566 timing->reg_5 |= (e->tCL + 3) << 8; 558 t->reg[5] |= (e->tCL + 3) << 8;
567 timing->reg_6 |= (timing->tCWL - 2) << 8; 559 t->reg[6] |= (t->tCWL - 2) << 8;
568 timing->reg_8 |= (e->tCL - 4); 560 t->reg[8] |= (e->tCL - 4);
569 } else { 561 } else {
570 timing->reg_5 |= (e->tCL + 2) << 8; 562 t->reg[5] |= (e->tCL + 2) << 8;
571 timing->reg_6 |= timing->tCWL << 8; 563 t->reg[6] |= t->tCWL << 8;
572 timing->reg_8 |= (e->tCL - 2); 564 t->reg[8] |= (e->tCL - 2);
573 } 565 }
574 } else { 566 } else {
575 timing->reg_1 |= (5 + e->tCL - (timing->tCWL)); 567 t->reg[1] |= (5 + e->tCL - (t->tCWL));
576 568
577 /* XXX: 0xb? 0x30? */ 569 /* XXX: 0xb? 0x30? */
578 timing->reg_3 = (0x30 + e->tCL) << 24 | 570 t->reg[3] = (0x30 + e->tCL) << 24 |
579 (nv_rd32(dev, 0x10022c) & 0x00ff0000) | 571 (boot->reg[3] & 0x00ff0000)|
580 (0xB + e->tCL) << 8 | 572 (0xb + e->tCL) << 8 |
581 (e->tCL - 1); 573 (e->tCL - 1);
582 574
583 timing->reg_4 |= (unk20 << 24 | unk21 << 16); 575 t->reg[4] |= (unk20 << 24 | unk21 << 16);
584 576
585 /* XXX: +6? */ 577 /* XXX: +6? */
586 timing->reg_5 |= (timing->tCWL + 6) << 8; 578 t->reg[5] |= (t->tCWL + 6) << 8;
587 579
588 timing->reg_6 = (0x5A + e->tCL) << 16 | 580 t->reg[6] = (0x5a + e->tCL) << 16 |
589 (6 - e->tCL + timing->tCWL) << 8 | 581 (6 - e->tCL + t->tCWL) << 8 |
590 (0x50 + e->tCL - timing->tCWL); 582 (0x50 + e->tCL - t->tCWL);
591 583
592 tmp7_3 = (nv_rd32(dev, 0x10023c) & 0xff000000) >> 24; 584 tmp7_3 = (boot->reg[7] & 0xff000000) >> 24;
593 timing->reg_7 = (tmp7_3 << 24) | 585 t->reg[7] = (tmp7_3 << 24) |
594 ((tmp7_3 - 6 + e->tCL) << 16) | 586 ((tmp7_3 - 6 + e->tCL) << 16) |
595 0x202; 587 0x202;
596 } 588 }
597 589
598 NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", timing->id, 590 NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", t->id,
599 timing->reg_0, timing->reg_1, 591 t->reg[0], t->reg[1], t->reg[2], t->reg[3]);
600 timing->reg_2, timing->reg_3);
601 NV_DEBUG(dev, " 230: %08x %08x %08x %08x\n", 592 NV_DEBUG(dev, " 230: %08x %08x %08x %08x\n",
602 timing->reg_4, timing->reg_5, 593 t->reg[4], t->reg[5], t->reg[6], t->reg[7]);
603 timing->reg_6, timing->reg_7); 594 NV_DEBUG(dev, " 240: %08x\n", t->reg[8]);
604 NV_DEBUG(dev, " 240: %08x\n", timing->reg_8);
605} 595}
606 596
607void nvc0_mem_timing_entry(struct drm_device *dev, 597static void
608 struct nouveau_pm_tbl_header *hdr, 598nvc0_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr,
609 struct nouveau_pm_tbl_entry *e, 599 struct nouveau_pm_tbl_entry *e,
610 struct nouveau_pm_memtiming *timing) 600 struct nouveau_pm_memtiming *t,
601 struct nouveau_pm_memtiming *boot)
611{ 602{
612 timing->tCWL = e->tCWL; 603 if (e->tCWL > 0)
604 t->tCWL = e->tCWL;
613 605
614 timing->reg_0 = (e->tRP << 24 | (e->tRAS & 0x7f) << 17 | 606 t->reg[0] = (e->tRP << 24 | (e->tRAS & 0x7f) << 17 |
615 e->tRFC << 8 | e->tRC); 607 e->tRFC << 8 | e->tRC);
616 608
617 timing->reg_1 = (nv_rd32(dev, 0x10f294) & 0xff000000) | 609 t->reg[1] = (boot->reg[1] & 0xff000000) |
618 (e->tRCDWR & 0x0f) << 20 | 610 (e->tRCDWR & 0x0f) << 20 |
619 (e->tRCDRD & 0x0f) << 14 | 611 (e->tRCDRD & 0x0f) << 14 |
620 (e->tCWL << 7) | 612 (e->tCWL << 7) |
621 (e->tCL & 0x0f); 613 (e->tCL & 0x0f);
622 614
623 timing->reg_2 = (nv_rd32(dev, 0x10f298) & 0xff0000ff) | 615 t->reg[2] = (boot->reg[2] & 0xff0000ff) |
624 e->tWR << 16 | e->tWTR << 8; 616 e->tWR << 16 | e->tWTR << 8;
625 617
626 timing->reg_3 = (e->tUNK_20&0xf) << 9 | 618 t->reg[3] = (e->tUNK_20 & 0xf) << 9 |
627 (e->tUNK_21 & 0xf) << 5 | 619 (e->tUNK_21 & 0xf) << 5 |
628 (e->tUNK_13 & 0x1f); 620 (e->tUNK_13 & 0x1f);
629 621
630 timing->reg_4 = (nv_rd32(dev, 0x10f2a0) & 0xfff00fff) | 622 t->reg[4] = (boot->reg[4] & 0xfff00fff) |
631 (e->tRRD&0x1f) << 15; 623 (e->tRRD&0x1f) << 15;
632 624
633 NV_DEBUG(dev, "Entry %d: 290: %08x %08x %08x %08x\n", timing->id, 625 NV_DEBUG(dev, "Entry %d: 290: %08x %08x %08x %08x\n", t->id,
634 timing->reg_0, timing->reg_1, 626 t->reg[0], t->reg[1], t->reg[2], t->reg[3]);
635 timing->reg_2, timing->reg_3); 627 NV_DEBUG(dev, " 2a0: %08x\n", t->reg[4]);
636 NV_DEBUG(dev, " 2a0: %08x\n",
637 timing->reg_4);
638} 628}
639 629
640void 630/**
641nouveau_mem_features_entry(uint8_t p_version, struct nouveau_pm_tbl_header *hdr, 631 * MR generation methods
642 struct nouveau_pm_tbl_entry *e, 632 */
643 struct nouveau_pm_memtiming *timing) 633
634static bool
635nouveau_mem_ddr2_mr(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr,
636 struct nouveau_pm_tbl_entry *e,
637 struct nouveau_pm_memtiming *t,
638 struct nouveau_pm_memtiming *boot)
639{
640 t->drive_strength = 0;
641 if (hdr->entry_len < 15) {
642 t->odt = boot->odt;
643 } else {
644 t->odt = e->RAM_FT1 & 0x07;
645 }
646
647 if (e->tCL >= NV_MEM_CL_DDR2_MAX) {
648 NV_WARN(dev, "(%u) Invalid tCL: %u", t->id, e->tCL);
649 return false;
650 }
651
652 if (e->tWR >= NV_MEM_WR_DDR2_MAX) {
653 NV_WARN(dev, "(%u) Invalid tWR: %u", t->id, e->tWR);
654 return false;
655 }
656
657 if (t->odt > 3) {
658 NV_WARN(dev, "(%u) Invalid odt value, assuming disabled: %x",
659 t->id, t->odt);
660 t->odt = 0;
661 }
662
663 t->mr[0] = (boot->mr[0] & 0x100f) |
664 (e->tCL) << 4 |
665 (e->tWR - 1) << 9;
666 t->mr[1] = (boot->mr[1] & 0x101fbb) |
667 (t->odt & 0x1) << 2 |
668 (t->odt & 0x2) << 5;
669
670 NV_DEBUG(dev, "(%u) MR: %08x", t->id, t->mr[0]);
671 return true;
672}
673
674uint8_t nv_mem_wr_lut_ddr3[NV_MEM_WR_DDR3_MAX] = {
675 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 0, 0};
676
677static bool
678nouveau_mem_ddr3_mr(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr,
679 struct nouveau_pm_tbl_entry *e,
680 struct nouveau_pm_memtiming *t,
681 struct nouveau_pm_memtiming *boot)
682{
683 u8 cl = e->tCL - 4;
684
685 t->drive_strength = 0;
686 if (hdr->entry_len < 15) {
687 t->odt = boot->odt;
688 } else {
689 t->odt = e->RAM_FT1 & 0x07;
690 }
691
692 if (e->tCL >= NV_MEM_CL_DDR3_MAX || e->tCL < 4) {
693 NV_WARN(dev, "(%u) Invalid tCL: %u", t->id, e->tCL);
694 return false;
695 }
696
697 if (e->tWR >= NV_MEM_WR_DDR3_MAX || e->tWR < 4) {
698 NV_WARN(dev, "(%u) Invalid tWR: %u", t->id, e->tWR);
699 return false;
700 }
701
702 if (e->tCWL < 5) {
703 NV_WARN(dev, "(%u) Invalid tCWL: %u", t->id, e->tCWL);
704 return false;
705 }
706
707 t->mr[0] = (boot->mr[0] & 0x180b) |
708 /* CAS */
709 (cl & 0x7) << 4 |
710 (cl & 0x8) >> 1 |
711 (nv_mem_wr_lut_ddr3[e->tWR]) << 9;
712 t->mr[1] = (boot->mr[1] & 0x101dbb) |
713 (t->odt & 0x1) << 2 |
714 (t->odt & 0x2) << 5 |
715 (t->odt & 0x4) << 7;
716 t->mr[2] = (boot->mr[2] & 0x20ffb7) | (e->tCWL - 5) << 3;
717
718 NV_DEBUG(dev, "(%u) MR: %08x %08x", t->id, t->mr[0], t->mr[2]);
719 return true;
720}
721
722uint8_t nv_mem_cl_lut_gddr3[NV_MEM_CL_GDDR3_MAX] = {
723 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3, 8, 9, 10, 11};
724uint8_t nv_mem_wr_lut_gddr3[NV_MEM_WR_GDDR3_MAX] = {
725 0, 0, 0, 0, 0, 2, 3, 8, 9, 10, 11, 0, 0, 1, 1, 0, 3};
726
727static bool
728nouveau_mem_gddr3_mr(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr,
729 struct nouveau_pm_tbl_entry *e,
730 struct nouveau_pm_memtiming *t,
731 struct nouveau_pm_memtiming *boot)
644{ 732{
645 if (p_version == 1) { 733 if (hdr->entry_len < 15) {
646 /* XXX: Todo */ 734 t->drive_strength = boot->drive_strength;
647 } else if (p_version == 2) { 735 t->odt = boot->odt;
648 timing->odt = e->RAM_FT1 & 0x1; 736 } else {
649 timing->dll_disable = (e->RAM_FT1 & 0x2) >> 1; 737 t->drive_strength = (e->RAM_FT1 & 0x30) >> 4;
650 timing->ron_pull = (e->RAM_FT1 & 0x4) >> 2; 738 t->odt = e->RAM_FT1 & 0x07;
651 } 739 }
740
741 if (e->tCL >= NV_MEM_CL_GDDR3_MAX) {
742 NV_WARN(dev, "(%u) Invalid tCL: %u", t->id, e->tCL);
743 return false;
744 }
745
746 if (e->tWR >= NV_MEM_WR_GDDR3_MAX) {
747 NV_WARN(dev, "(%u) Invalid tWR: %u", t->id, e->tWR);
748 return false;
749 }
750
751 if (t->odt > 3) {
752 NV_WARN(dev, "(%u) Invalid odt value, assuming autocal: %x",
753 t->id, t->odt);
754 t->odt = 0;
755 }
756
757 t->mr[0] = (boot->mr[0] & 0xe0b) |
758 /* CAS */
759 ((nv_mem_cl_lut_gddr3[e->tCL] & 0x7) << 4) |
760 ((nv_mem_cl_lut_gddr3[e->tCL] & 0x8) >> 2);
761 t->mr[1] = (boot->mr[1] & 0x100f40) | t->drive_strength |
762 (t->odt << 2) |
763 (nv_mem_wr_lut_gddr3[e->tWR] & 0xf) << 4;
764
765 NV_DEBUG(dev, "(%u) MR: %08x %08x", t->id, t->mr[0], t->mr[1]);
766 return true;
767}
768
769static bool
770nouveau_mem_gddr5_mr(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr,
771 struct nouveau_pm_tbl_entry *e,
772 struct nouveau_pm_memtiming *t,
773 struct nouveau_pm_memtiming *boot)
774{
775 if (hdr->entry_len < 15) {
776 t->drive_strength = boot->drive_strength;
777 t->odt = boot->odt;
778 } else {
779 t->drive_strength = (e->RAM_FT1 & 0x30) >> 4;
780 t->odt = e->RAM_FT1 & 0x03;
781 }
782
783 if (e->tCL >= NV_MEM_CL_GDDR5_MAX) {
784 NV_WARN(dev, "(%u) Invalid tCL: %u", t->id, e->tCL);
785 return false;
786 }
787
788 if (e->tWR >= NV_MEM_WR_GDDR5_MAX) {
789 NV_WARN(dev, "(%u) Invalid tWR: %u", t->id, e->tWR);
790 return false;
791 }
792
793 if (t->odt > 3) {
794 NV_WARN(dev, "(%u) Invalid odt value, assuming autocal: %x",
795 t->id, t->odt);
796 t->odt = 0;
797 }
798
799 t->mr[0] = (boot->mr[0] & 0x007) |
800 ((e->tCL - 5) << 3) |
801 ((e->tWR - 4) << 8);
802 t->mr[1] = (boot->mr[1] & 0x1007f0) |
803 t->drive_strength |
804 (t->odt << 2);
805
806 NV_DEBUG(dev, "(%u) MR: %08x %08x", t->id, t->mr[0], t->mr[1]);
807 return true;
808}
809
810static void
811nouveau_mem_copy_current_timings(struct drm_device *dev,
812 struct nouveau_pm_memtiming *t)
813{
814 struct drm_nouveau_private *dev_priv = dev->dev_private;
815 u32 timing_base, timing_regs, mr_base;
816 int i;
817
818 if (dev_priv->card_type >= 0xC0) {
819 timing_base = 0x10f290;
820 mr_base = 0x10f300;
821 } else {
822 timing_base = 0x100220;
823 mr_base = 0x1002c0;
824 }
825
826 t->id = -1;
827
828 switch (dev_priv->card_type) {
829 case NV_50:
830 timing_regs = 9;
831 break;
832 case NV_C0:
833 case NV_D0:
834 timing_regs = 5;
835 break;
836 case NV_30:
837 case NV_40:
838 timing_regs = 3;
839 break;
840 default:
841 timing_regs = 0;
842 return;
843 }
844 for(i = 0; i < timing_regs; i++)
845 t->reg[i] = nv_rd32(dev, timing_base + (0x04 * i));
846
847 t->tCWL = 0;
848 if (dev_priv->card_type < NV_C0) {
849 t->tCWL = ((nv_rd32(dev, 0x100228) & 0x0f000000) >> 24) + 1;
850 }
851
852 t->mr[0] = nv_rd32(dev, mr_base);
853 t->mr[1] = nv_rd32(dev, mr_base + 0x04);
854 t->mr[2] = nv_rd32(dev, mr_base + 0x20);
855 t->mr[3] = nv_rd32(dev, mr_base + 0x24);
856
857 t->odt = 0;
858 t->drive_strength = 0;
859
860 switch (dev_priv->vram_type) {
861 case NV_MEM_TYPE_DDR3:
862 t->odt |= (t->mr[1] & 0x200) >> 7;
863 case NV_MEM_TYPE_DDR2:
864 t->odt |= (t->mr[1] & 0x04) >> 2 |
865 (t->mr[1] & 0x40) >> 5;
866 break;
867 case NV_MEM_TYPE_GDDR3:
868 case NV_MEM_TYPE_GDDR5:
869 t->drive_strength = t->mr[1] & 0x03;
870 t->odt = (t->mr[1] & 0x0c) >> 2;
871 break;
872 default:
873 break;
874 }
875}
876
877static bool
878nouveau_mem_compare_timings(struct drm_device *dev,
879 struct nouveau_pm_memtiming *t1,
880 struct nouveau_pm_memtiming *t2)
881{
882 struct drm_nouveau_private *dev_priv = dev->dev_private;
883
884 switch (dev_priv->card_type) {
885 case 0x50:
886 if (t1->reg[8] != t2->reg[8] ||
887 t1->reg[7] != t2->reg[7] ||
888 t1->reg[6] != t2->reg[6] ||
889 t1->reg[5] != t2->reg[5])
890 return false;
891 case 0xC0:
892 if (t1->reg[4] != t2->reg[4] ||
893 t1->reg[3] != t2->reg[3])
894 return false;
895 case 0x40:
896 if (t1->reg[2] != t2->reg[2] ||
897 t1->reg[1] != t2->reg[1] ||
898 t1->reg[0] != t2->reg[0])
899 return false;
900 break;
901 default:
902 return false;
903 }
904
905 /* RSpliet: may generate many false negatives */
906 switch (dev_priv->vram_type) {
907 case NV_MEM_TYPE_GDDR3:
908 case NV_MEM_TYPE_GDDR5:
909 if (t1->mr[0] == t2->mr[0] ||
910 t1->mr[1] != t2->mr[1])
911 return true;
912 break;
913 case NV_MEM_TYPE_DDR3:
914 if (t1->mr[2] == t2->mr[2])
915 return true;
916 case NV_MEM_TYPE_DDR2:
917 if (t1->mr[0] == t2->mr[0])
918 return true;
919 break;
920 default:
921 return false;
922 }
923
924 return false;
652} 925}
653 926
654/** 927/**
@@ -665,10 +938,24 @@ nouveau_mem_timing_init(struct drm_device *dev)
665 struct nvbios *bios = &dev_priv->vbios; 938 struct nvbios *bios = &dev_priv->vbios;
666 struct bit_entry P; 939 struct bit_entry P;
667 struct nouveau_pm_tbl_header *hdr = NULL; 940 struct nouveau_pm_tbl_header *hdr = NULL;
668 uint8_t tCWL; 941 bool valid_generation = false;
669 u8 *entry; 942 u8 *entry;
670 int i; 943 int i;
671 944
945 memtimings->nr_timing = 0;
946 memtimings->nr_timing_valid = 0;
947 memtimings->supported = 0;
948
949 if (dev_priv->card_type < NV_40) {
950 NV_ERROR(dev, "Timing entry format unknown for card_type %x. "
951 "please contact nouveau developers",
952 dev_priv->card_type);
953 return;
954 }
955
956 /* Copy the current timings */
957 nouveau_mem_copy_current_timings(dev, &memtimings->boot);
958
672 if (bios->type == NVBIOS_BIT) { 959 if (bios->type == NVBIOS_BIT) {
673 if (bit_table(dev, 'P', &P)) 960 if (bit_table(dev, 'P', &P))
674 return; 961 return;
@@ -710,12 +997,6 @@ nouveau_mem_timing_init(struct drm_device *dev)
710 if (!memtimings->timing) 997 if (!memtimings->timing)
711 return; 998 return;
712 999
713 /* Get tCWL from the timing reg for NV_40 and NV_50
714 * Used in calculations later... source unknown */
715 tCWL = 0;
716 if (dev_priv->card_type < NV_C0)
717 tCWL = ((nv_rd32(dev, 0x100228) & 0x0f000000) >> 24) + 1;
718
719 entry = (u8 *) hdr + hdr->header_len; 1000 entry = (u8 *) hdr + hdr->header_len;
720 for (i = 0; i < hdr->entry_cnt; i++, entry += hdr->entry_len) { 1001 for (i = 0; i < hdr->entry_cnt; i++, entry += hdr->entry_len) {
721 struct nouveau_pm_memtiming *timing = &pm->memtimings.timing[i]; 1002 struct nouveau_pm_memtiming *timing = &pm->memtimings.timing[i];
@@ -723,29 +1004,70 @@ nouveau_mem_timing_init(struct drm_device *dev)
723 (struct nouveau_pm_tbl_entry *) entry; 1004 (struct nouveau_pm_tbl_entry *) entry;
724 if (entry[0] == 0) 1005 if (entry[0] == 0)
725 continue; 1006 continue;
1007 memtimings->nr_timing_valid++;
726 1008
727 timing->id = i; 1009 timing->id = i;
728 timing->WR = entry[0]; 1010 timing->tCWL = memtimings->boot.tCWL;
729 timing->CL = entry[2];
730 timing->tCWL = tCWL;
731
732 nouveau_mem_features_entry(P.version, hdr, entry_struct,
733 &pm->memtimings.timing[i]);
734 1011
735 if (dev_priv->card_type <= NV_40) { 1012 /* generate the timngs */
1013 if (dev_priv->card_type == NV_40) {
736 nv40_mem_timing_entry(dev, hdr, entry_struct, 1014 nv40_mem_timing_entry(dev, hdr, entry_struct,
737 &pm->memtimings.timing[i]); 1015 &pm->memtimings.timing[i],
1016 &memtimings->boot);
738 } else if (dev_priv->card_type == NV_50) { 1017 } else if (dev_priv->card_type == NV_50) {
739 nv50_mem_timing_entry(dev, &P, hdr, entry_struct, 1018 nv50_mem_timing_entry(dev, &P, hdr, entry_struct,
740 &pm->memtimings.timing[i]); 1019 &pm->memtimings.timing[i],
1020 &memtimings->boot);
741 } else if (dev_priv->card_type == NV_C0) { 1021 } else if (dev_priv->card_type == NV_C0) {
742 nvc0_mem_timing_entry(dev, hdr, entry_struct, 1022 nvc0_mem_timing_entry(dev, hdr, entry_struct,
743 &pm->memtimings.timing[i]); 1023 &pm->memtimings.timing[i],
1024 &memtimings->boot);
1025 }
1026
1027 /* generate the MR/EMR/... */
1028 switch (dev_priv->vram_type) {
1029 case NV_MEM_TYPE_GDDR3:
1030 nouveau_mem_gddr3_mr(dev, hdr, entry_struct, timing,
1031 &memtimings->boot);
1032 break;
1033 case NV_MEM_TYPE_GDDR5:
1034 nouveau_mem_gddr5_mr(dev, hdr, entry_struct, timing,
1035 &memtimings->boot);
1036 break;
1037 case NV_MEM_TYPE_DDR2:
1038 nouveau_mem_ddr2_mr(dev, hdr, entry_struct, timing,
1039 &memtimings->boot);
1040 break;
1041 case NV_MEM_TYPE_DDR3:
1042 nouveau_mem_ddr3_mr(dev, hdr, entry_struct, timing,
1043 &memtimings->boot);
1044 break;
1045 default:
1046 valid_generation = false;
1047 break;
1048 }
1049
1050 /* some kind of validation */
1051 if (nouveau_mem_compare_timings(dev, timing,
1052 &memtimings->boot)) {
1053 NV_DEBUG(dev, "Copy boot timings from entry %d\n",
1054 timing->id);
1055 memtimings->boot = *timing;
1056 valid_generation = true;
744 } 1057 }
745 } 1058 }
746 1059
747 memtimings->nr_timing = hdr->entry_cnt; 1060 memtimings->nr_timing = hdr->entry_cnt;
748 memtimings->supported = (P.version == 1); 1061 memtimings->supported = (P.version == 1) && valid_generation;
1062
1063 /* if there are no timing entries that cannot
1064 * re-generate the current timings
1065 */
1066 if (memtimings->nr_timing_valid > 0 && !valid_generation) {
1067 NV_INFO(dev,
1068 "Memory timings management may not be working."
1069 " please report to nouveau devs\n");
1070 }
749} 1071}
750 1072
751void 1073void