aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorRoy Spliet <r.spliet@student.tudelft.nl>2011-11-25 09:52:22 -0500
committerBen Skeggs <bskeggs@redhat.com>2012-03-13 03:06:26 -0400
commitbfb314652430ceca302bae0981d00903f055eee4 (patch)
tree539d40f333d17c6d1789504297d95fe505e192b1 /drivers/gpu
parentb0103747094b62231fc951dfaca4897f67670874 (diff)
drm/nouveau/pm: improve memory timing generation
- Rename several VBIOS entries to closer match the real world - Add the missing 0x100238 and 0x100240 register values - Parse bit 14 of the VBIOS timing table - "Magic value" -> tCWL, fixing some minor bugs in the process - Also name a few more by their name rather than their number. - Some values seem to be dependent on the memory type. Fix Edits by Martin Peres <martin.peres@labri.fr>: - this is a squash commit - reworked for fixing some style issues 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')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h29
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mem.c156
2 files changed, 120 insertions, 65 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 78302cccf6fd..c5105326db7f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -446,6 +446,11 @@ struct nouveau_pm_memtiming {
446 /* To be written to 0x1002c0 */ 446 /* To be written to 0x1002c0 */
447 u8 CL; 447 u8 CL;
448 u8 WR; 448 u8 WR;
449 u8 tCWL;
450
451 bool odt;
452 bool dll_disable;
453 bool ron_pull;
449}; 454};
450 455
451struct nouveau_pm_tbl_header { 456struct nouveau_pm_tbl_header {
@@ -457,18 +462,26 @@ struct nouveau_pm_tbl_header {
457 462
458struct nouveau_pm_tbl_entry { 463struct nouveau_pm_tbl_entry {
459 u8 tWR; 464 u8 tWR;
460 u8 tUNK_1; 465 u8 tWTR;
461 u8 tCL; 466 u8 tCL;
462 u8 tRP; /* Byte 3 */ 467 u8 tRC;
463 u8 empty_4; 468 u8 empty_4;
464 u8 tRAS; /* Byte 5 */ 469 u8 tRFC; /* Byte 5 */
465 u8 empty_6; 470 u8 empty_6;
466 u8 tRFC; /* Byte 7 */ 471 u8 tRAS; /* Byte 7 */
467 u8 empty_8; 472 u8 empty_8;
468 u8 tRC; /* Byte 9 */ 473 u8 tRP; /* Byte 9 */
469 u8 tUNK_10, tUNK_11, tUNK_12, tUNK_13, tUNK_14; 474 u8 tRCDRD;
470 u8 empty_15,empty_16,empty_17; 475 u8 tRCDWR;
471 u8 tUNK_18, tUNK_19, tUNK_20, tUNK_21; 476 u8 tRRD;
477 u8 tUNK_13;
478 u8 RAM_FT1; /* 14, a bitmask of random RAM features */
479 u8 empty_15;
480 u8 tUNK_16;
481 u8 empty_17;
482 u8 tUNK_18;
483 u8 tCWL;
484 u8 tUNK_20, tUNK_21;
472}; 485};
473 486
474#define NOUVEAU_PM_MAX_LEVEL 8 487#define NOUVEAU_PM_MAX_LEVEL 8
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c
index 5eb9e3df0fec..3337f2cfb5f6 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c
@@ -485,21 +485,21 @@ void nv30_mem_timing_entry(struct drm_device *dev,
485 485
486void nv40_mem_timing_entry(struct drm_device *dev, 486void nv40_mem_timing_entry(struct drm_device *dev,
487 struct nouveau_pm_tbl_header *hdr, 487 struct nouveau_pm_tbl_header *hdr,
488 struct nouveau_pm_tbl_entry *e, uint8_t magic_number, 488 struct nouveau_pm_tbl_entry *e,
489 struct nouveau_pm_memtiming *timing) 489 struct nouveau_pm_memtiming *timing)
490{ 490{
491 491
492 timing->reg_0 = (e->tRC << 24 | e->tRFC << 16 | e->tRAS << 8 | e->tRP); 492 timing->reg_0 = (e->tRP << 24 | e->tRAS << 16 | e->tRFC << 8 | e->tRC);
493 493
494 /* XXX: I don't trust the -1's and +1's... they must come 494 /* XXX: I don't trust the -1's and +1's... they must come
495 * from somewhere! */ 495 * from somewhere! */
496 timing->reg_1 = (e->tWR + 2 + magic_number) << 24 | 496 timing->reg_1 = (e->tWR + 2 + (timing->tCWL - 1)) << 24 |
497 1 << 16 | 497 1 << 16 |
498 (e->tUNK_1 + 2 + magic_number) << 8 | 498 (e->tWTR + 2 + (timing->tCWL - 1)) << 8 |
499 (e->tCL + 2 - magic_number); 499 (e->tCL + 2 - (timing->tCWL - 1));
500 timing->reg_2 = magic_number << 24 | e->tUNK_12 << 16 | 500
501 e->tUNK_11 << 8 | e->tUNK_10; 501 timing->reg_2 = 0x20200000 | ((timing->tCWL - 1) << 24 |
502 timing->reg_2 |= 0x20200000; 502 e->tRRD << 16 | e->tRCDWR << 8 | e->tRCDRD);
503 503
504 NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x\n", timing->id, 504 NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x\n", timing->id,
505 timing->reg_0, timing->reg_1, timing->reg_2); 505 timing->reg_0, timing->reg_1, timing->reg_2);
@@ -507,15 +507,14 @@ void nv40_mem_timing_entry(struct drm_device *dev,
507 507
508void nv50_mem_timing_entry(struct drm_device *dev, struct bit_entry *P, 508void nv50_mem_timing_entry(struct drm_device *dev, struct bit_entry *P,
509 struct nouveau_pm_tbl_header *hdr, 509 struct nouveau_pm_tbl_header *hdr,
510 struct nouveau_pm_tbl_entry *e, uint8_t magic_number, 510 struct nouveau_pm_tbl_entry *e,
511 struct nouveau_pm_memtiming *timing) 511 struct nouveau_pm_memtiming *timing)
512{ 512{
513 struct drm_nouveau_private *dev_priv = dev->dev_private; 513 struct drm_nouveau_private *dev_priv = dev->dev_private;
514
515 uint8_t unk18 = 1, 514 uint8_t unk18 = 1,
516 unk19 = 1,
517 unk20 = 0, 515 unk20 = 0,
518 unk21 = 0; 516 unk21 = 0,
517 tmp7_3;
519 518
520 switch (min(hdr->entry_len, (u8) 22)) { 519 switch (min(hdr->entry_len, (u8) 22)) {
521 case 22: 520 case 22:
@@ -523,55 +522,77 @@ void nv50_mem_timing_entry(struct drm_device *dev, struct bit_entry *P,
523 case 21: 522 case 21:
524 unk20 = e->tUNK_20; 523 unk20 = e->tUNK_20;
525 case 20: 524 case 20:
526 unk19 = e->tUNK_19; 525 if (e->tCWL > 0)
526 timing->tCWL = e->tCWL;
527 case 19: 527 case 19:
528 unk18 = e->tUNK_18; 528 unk18 = e->tUNK_18;
529 break; 529 break;
530 } 530 }
531 531
532 timing->reg_0 = (e->tRC << 24 | e->tRFC << 16 | e->tRAS << 8 | e->tRP); 532 timing->reg_0 = (e->tRP << 24 | e->tRAS << 16 | e->tRFC << 8 | e->tRC);
533 533
534 /* XXX: I don't trust the -1's and +1's... they must come 534 timing->reg_1 = (e->tWR + 2 + (timing->tCWL - 1)) << 24 |
535 * from somewhere! */ 535 max(unk18, (u8) 1) << 16 |
536 timing->reg_1 = (e->tWR + unk19 + 1 + magic_number) << 24 | 536 (e->tWTR + 2 + (timing->tCWL - 1)) << 8;
537 max(unk18, (u8) 1) << 16 | 537
538 (e->tUNK_1 + unk19 + 1 + magic_number) << 8; 538 timing->reg_2 = ((timing->tCWL - 1) << 24 | e->tRRD << 16 |
539 if (dev_priv->chipset == 0xa8) 539 e->tRCDWR << 8 | e->tRCDRD);
540 timing->reg_1 |= (e->tCL - 1);
541 else
542 timing->reg_1 |= (e->tCL + 2 - magic_number);
543 540
544 timing->reg_2 = (e->tUNK_12 << 16 | e->tUNK_11 << 8 | e->tUNK_10); 541 timing->reg_4 = e->tUNK_13 << 8 | e->tUNK_13;
545 542
546 timing->reg_5 = (e->tRAS << 24 | e->tRC); 543 timing->reg_5 = (e->tRFC << 24 | max(e->tRCDRD, e->tRCDWR) << 16 |
547 timing->reg_5 += max(e->tUNK_10, e->tUNK_11) << 16; 544 e->tRP);
545
546 timing->reg_8 = (nv_rd32(dev, 0x100240) & 0xffffff00);
548 547
549 if (P->version == 1) { 548 if (P->version == 1) {
550 timing->reg_2 |= magic_number << 24; 549 timing->reg_1 |= (e->tCL + 2 - (timing->tCWL - 1));
551 550
552 timing->reg_3 = (0x14 + e->tCL) << 24 | 551 timing->reg_3 = (0x14 + e->tCL) << 24 |
553 0x16 << 16 | 552 0x16 << 16 |
554 (e->tCL - 1) << 8 | 553 (e->tCL - 1) << 8 |
555 (e->tCL - 1); 554 (e->tCL - 1);
556 555
557 timing->reg_4 = (nv_rd32(dev, 0x10022c) & 0xffff0000) | 556 timing->reg_4 |= (nv_rd32(dev, 0x100230) & 0xffff0000);
558 e->tUNK_13 << 8 | e->tUNK_13;
559 557
560 timing->reg_5 |= (e->tCL + 2) << 8; 558 timing->reg_6 = (0x33 - timing->tCWL) << 16 |
559 timing->tCWL << 8 |
560 (0x2E + e->tCL - timing->tCWL);
561 561
562 timing->reg_7 = 0x4000202 | (e->tCL - 1) << 16; 562 timing->reg_7 = 0x4000202 | (e->tCL - 1) << 16;
563
564 /* XXX: P.version == 1 only has DDR2 and GDDR3? */
565 if (dev_priv->vram_type == NV_MEM_TYPE_DDR2) {
566 timing->reg_5 |= (e->tCL + 3) << 8;
567 timing->reg_6 |= (timing->tCWL - 2) << 8;
568 timing->reg_8 |= (e->tCL - 4);
569 } else {
570 timing->reg_5 |= (e->tCL + 2) << 8;
571 timing->reg_6 |= timing->tCWL << 8;
572 timing->reg_8 |= (e->tCL - 2);
573 }
563 } else { 574 } else {
564 timing->reg_2 |= (unk19 - 1) << 24; 575 timing->reg_1 |= (5 + e->tCL - (timing->tCWL));
565 /* XXX: reg_10022c for recentish cards pretty much unknown*/ 576
566 timing->reg_3 = e->tCL - 1; 577 /* XXX: 0xb? 0x30? */
567 timing->reg_4 = (unk20 << 24 | unk21 << 16 | 578 timing->reg_3 = (0x30 + e->tCL) << 24 |
568 e->tUNK_13 << 8 | e->tUNK_13); 579 (nv_rd32(dev, 0x10022c) & 0x00ff0000) |
580 (0xB + e->tCL) << 8 |
581 (e->tCL - 1);
582
583 timing->reg_4 |= (unk20 << 24 | unk21 << 16);
584
569 /* XXX: +6? */ 585 /* XXX: +6? */
570 timing->reg_5 |= (unk19 + 6) << 8; 586 timing->reg_5 |= (timing->tCWL + 6) << 8;
571 587
572 /* XXX: reg_10023c currently unknown 588 timing->reg_6 = (0x5A + e->tCL) << 16 |
573 * 10023c seen as 06xxxxxx, 0bxxxxxx or 0fxxxxxx */ 589 (6 - e->tCL + timing->tCWL) << 8 |
574 timing->reg_7 = 0x202; 590 (0x50 + e->tCL - timing->tCWL);
591
592 tmp7_3 = (nv_rd32(dev, 0x10023c) & 0xff000000) >> 24;
593 timing->reg_7 = (tmp7_3 << 24) |
594 ((tmp7_3 - 6 + e->tCL) << 16) |
595 0x202;
575 } 596 }
576 597
577 NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", timing->id, 598 NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", timing->id,
@@ -588,27 +609,46 @@ void nvc0_mem_timing_entry(struct drm_device *dev,
588 struct nouveau_pm_tbl_entry *e, 609 struct nouveau_pm_tbl_entry *e,
589 struct nouveau_pm_memtiming *timing) 610 struct nouveau_pm_memtiming *timing)
590{ 611{
591 timing->reg_0 = (e->tRC << 24 | (e->tRFC & 0x7f) << 17 | 612 timing->tCWL = e->tCWL;
592 e->tRAS << 8 | e->tRP); 613
614 timing->reg_0 = (e->tRP << 24 | (e->tRAS & 0x7f) << 17 |
615 e->tRFC << 8 | e->tRC);
593 616
594 timing->reg_1 = (nv_rd32(dev, 0x10f294) & 0xff000000) | 617 timing->reg_1 = (nv_rd32(dev, 0x10f294) & 0xff000000) |
595 (e->tUNK_11&0x0f) << 20 | (e->tUNK_19 << 7) | 618 (e->tRCDWR & 0x0f) << 20 |
619 (e->tRCDRD & 0x0f) << 14 |
620 (e->tCWL << 7) |
596 (e->tCL & 0x0f); 621 (e->tCL & 0x0f);
597 622
598 timing->reg_2 = (nv_rd32(dev, 0x10f298) & 0xff0000ff) | 623 timing->reg_2 = (nv_rd32(dev, 0x10f298) & 0xff0000ff) |
599 e->tWR << 16 | e->tUNK_1 << 8; 624 e->tWR << 16 | e->tWTR << 8;
600 625
601 timing->reg_3 = e->tUNK_20 << 9 | e->tUNK_13; 626 timing->reg_3 = (e->tUNK_20&0xf) << 9 |
627 (e->tUNK_21 & 0xf) << 5 |
628 (e->tUNK_13 & 0x1f);
602 629
603 timing->reg_4 = (nv_rd32(dev, 0x10f2a0) & 0xfff000ff) | 630 timing->reg_4 = (nv_rd32(dev, 0x10f2a0) & 0xfff00fff) |
604 e->tUNK_12 << 15; 631 (e->tRRD&0x1f) << 15;
605 632
606 NV_DEBUG(dev, "Entry %d: 290: %08x %08x %08x %08x\n", timing->id, 633 NV_DEBUG(dev, "Entry %d: 290: %08x %08x %08x %08x\n", timing->id,
607 timing->reg_0, timing->reg_1, 634 timing->reg_0, timing->reg_1,
608 timing->reg_2, timing->reg_3); 635 timing->reg_2, timing->reg_3);
609 NV_DEBUG(dev, " 2a0: %08x %08x %08x %08x\n", 636 NV_DEBUG(dev, " 2a0: %08x\n",
610 timing->reg_4, timing->reg_5, 637 timing->reg_4);
611 timing->reg_6, timing->reg_7); 638}
639
640void
641nouveau_mem_features_entry(uint8_t p_version, struct nouveau_pm_tbl_header *hdr,
642 struct nouveau_pm_tbl_entry *e,
643 struct nouveau_pm_memtiming *timing)
644{
645 if (p_version == 1) {
646 /* XXX: Todo */
647 } else if (p_version == 2) {
648 timing->odt = e->RAM_FT1 & 0x1;
649 timing->dll_disable = (e->RAM_FT1 & 0x2) >> 1;
650 timing->ron_pull = (e->RAM_FT1 & 0x4) >> 2;
651 }
612} 652}
613 653
614/** 654/**
@@ -625,7 +665,7 @@ nouveau_mem_timing_init(struct drm_device *dev)
625 struct nvbios *bios = &dev_priv->vbios; 665 struct nvbios *bios = &dev_priv->vbios;
626 struct bit_entry P; 666 struct bit_entry P;
627 struct nouveau_pm_tbl_header *hdr = NULL; 667 struct nouveau_pm_tbl_header *hdr = NULL;
628 uint8_t magic_number; 668 uint8_t tCWL;
629 u8 *entry; 669 u8 *entry;
630 int i; 670 int i;
631 671
@@ -670,11 +710,11 @@ nouveau_mem_timing_init(struct drm_device *dev)
670 if (!memtimings->timing) 710 if (!memtimings->timing)
671 return; 711 return;
672 712
673 /* Get "some number" from the timing reg for NV_40 and NV_50 713 /* Get tCWL from the timing reg for NV_40 and NV_50
674 * Used in calculations later... source unknown */ 714 * Used in calculations later... source unknown */
675 magic_number = 0; 715 tCWL = 0;
676 if (P.version == 1) 716 if (dev_priv->card_type < NV_C0)
677 magic_number = (nv_rd32(dev, 0x100228) & 0x0f000000) >> 24; 717 tCWL = ((nv_rd32(dev, 0x100228) & 0x0f000000) >> 24) + 1;
678 718
679 entry = (u8 *) hdr + hdr->header_len; 719 entry = (u8 *) hdr + hdr->header_len;
680 for (i = 0; i < hdr->entry_cnt; i++, entry += hdr->entry_len) { 720 for (i = 0; i < hdr->entry_cnt; i++, entry += hdr->entry_len) {
@@ -687,14 +727,16 @@ nouveau_mem_timing_init(struct drm_device *dev)
687 timing->id = i; 727 timing->id = i;
688 timing->WR = entry[0]; 728 timing->WR = entry[0];
689 timing->CL = entry[2]; 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]);
690 734
691 if (dev_priv->card_type <= NV_40) { 735 if (dev_priv->card_type <= NV_40) {
692 nv40_mem_timing_entry(dev, hdr, entry_struct, 736 nv40_mem_timing_entry(dev, hdr, entry_struct,
693 magic_number,
694 &pm->memtimings.timing[i]); 737 &pm->memtimings.timing[i]);
695 } else if (dev_priv->card_type == NV_50) { 738 } else if (dev_priv->card_type == NV_50) {
696 nv50_mem_timing_entry(dev, &P, hdr, entry_struct, 739 nv50_mem_timing_entry(dev, &P, hdr, entry_struct,
697 magic_number,
698 &pm->memtimings.timing[i]); 740 &pm->memtimings.timing[i]);
699 } else if (dev_priv->card_type == NV_C0) { 741 } else if (dev_priv->card_type == NV_C0) {
700 nvc0_mem_timing_entry(dev, hdr, entry_struct, 742 nvc0_mem_timing_entry(dev, hdr, entry_struct,