aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-07-05 18:54:34 -0400
committerBen Skeggs <bskeggs@redhat.com>2010-07-12 20:13:31 -0400
commit87c0e0e5133e252a6d3d561dd0caeec0244ea9a5 (patch)
tree4135bfa3848b0433e71e40c23534d3e8651b2d70 /drivers
parent835aadbef3b762bc43eceddfec90c9a5a312d3c1 (diff)
drm/nv50: rewrite display irq handler
The previous handler basically worked correctly for a full-blown mode change. However, it did nothing at all when a partial (encoder only) reconfiguation was necessary, leading to the display hanging on certain types of mode switch. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h5
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c328
2 files changed, 190 insertions, 143 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 565981dfd69b..4de342f54fd2 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -610,6 +610,11 @@ struct drm_nouveau_private {
610 struct backlight_device *backlight; 610 struct backlight_device *backlight;
611 611
612 struct nouveau_channel *evo; 612 struct nouveau_channel *evo;
613 struct {
614 struct dcb_entry *dcb;
615 u16 script;
616 u32 pclk;
617 } evo_irq;
613 618
614 struct { 619 struct {
615 struct dentry *channel_root; 620 struct dentry *channel_root;
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 0c762049cb68..711128c42de8 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -559,131 +559,28 @@ int nv50_display_destroy(struct drm_device *dev)
559 return 0; 559 return 0;
560} 560}
561 561
562static inline uint32_t 562static u16
563nv50_display_mode_ctrl(struct drm_device *dev, bool sor, int or) 563nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcb,
564{ 564 u32 mc, int pxclk)
565 struct drm_nouveau_private *dev_priv = dev->dev_private;
566 uint32_t mc;
567
568 if (sor) {
569 if (dev_priv->chipset < 0x90 ||
570 dev_priv->chipset == 0x92 || dev_priv->chipset == 0xa0)
571 mc = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_P(or));
572 else
573 mc = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_P(or));
574 } else {
575 mc = nv_rd32(dev, NV50_PDISPLAY_DAC_MODE_CTRL_P(or));
576 }
577
578 return mc;
579}
580
581static int
582nv50_display_irq_head(struct drm_device *dev, int *phead,
583 struct dcb_entry **pdcbent)
584{
585 struct drm_nouveau_private *dev_priv = dev->dev_private;
586 uint32_t unk30 = nv_rd32(dev, NV50_PDISPLAY_UNK30_CTRL);
587 uint32_t dac = 0, sor = 0;
588 int head, i, or = 0, type = OUTPUT_ANY;
589
590 /* We're assuming that head 0 *or* head 1 will be active here,
591 * and not both. I'm not sure if the hw will even signal both
592 * ever, but it definitely shouldn't for us as we commit each
593 * CRTC separately, and submission will be blocked by the GPU
594 * until we handle each in turn.
595 */
596 NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30);
597 head = ffs((unk30 >> 9) & 3) - 1;
598 if (head < 0)
599 return -EINVAL;
600
601 /* This assumes CRTCs are never bound to multiple encoders, which
602 * should be the case.
603 */
604 for (i = 0; i < 3 && type == OUTPUT_ANY; i++) {
605 uint32_t mc = nv50_display_mode_ctrl(dev, false, i);
606 if (!(mc & (1 << head)))
607 continue;
608
609 switch ((mc >> 8) & 0xf) {
610 case 0: type = OUTPUT_ANALOG; break;
611 case 1: type = OUTPUT_TV; break;
612 default:
613 NV_ERROR(dev, "unknown dac mode_ctrl: 0x%08x\n", dac);
614 return -1;
615 }
616
617 or = i;
618 }
619
620 for (i = 0; i < 4 && type == OUTPUT_ANY; i++) {
621 uint32_t mc = nv50_display_mode_ctrl(dev, true, i);
622 if (!(mc & (1 << head)))
623 continue;
624
625 switch ((mc >> 8) & 0xf) {
626 case 0: type = OUTPUT_LVDS; break;
627 case 1: type = OUTPUT_TMDS; break;
628 case 2: type = OUTPUT_TMDS; break;
629 case 5: type = OUTPUT_TMDS; break;
630 case 8: type = OUTPUT_DP; break;
631 case 9: type = OUTPUT_DP; break;
632 default:
633 NV_ERROR(dev, "unknown sor mode_ctrl: 0x%08x\n", sor);
634 return -1;
635 }
636
637 or = i;
638 }
639
640 NV_DEBUG_KMS(dev, "type %d, or %d\n", type, or);
641 if (type == OUTPUT_ANY) {
642 NV_ERROR(dev, "unknown encoder!!\n");
643 return -1;
644 }
645
646 for (i = 0; i < dev_priv->vbios.dcb.entries; i++) {
647 struct dcb_entry *dcbent = &dev_priv->vbios.dcb.entry[i];
648
649 if (dcbent->type != type)
650 continue;
651
652 if (!(dcbent->or & (1 << or)))
653 continue;
654
655 *phead = head;
656 *pdcbent = dcbent;
657 return 0;
658 }
659
660 NV_ERROR(dev, "no DCB entry for %d %d\n", dac != 0, or);
661 return 0;
662}
663
664static uint32_t
665nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcbent,
666 int pxclk)
667{ 565{
668 struct drm_nouveau_private *dev_priv = dev->dev_private; 566 struct drm_nouveau_private *dev_priv = dev->dev_private;
669 struct nouveau_connector *nv_connector = NULL; 567 struct nouveau_connector *nv_connector = NULL;
670 struct drm_encoder *encoder; 568 struct drm_encoder *encoder;
671 struct nvbios *bios = &dev_priv->vbios; 569 struct nvbios *bios = &dev_priv->vbios;
672 uint32_t mc, script = 0, or; 570 u32 script = 0, or;
673 571
674 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 572 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
675 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 573 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
676 574
677 if (nv_encoder->dcb != dcbent) 575 if (nv_encoder->dcb != dcb)
678 continue; 576 continue;
679 577
680 nv_connector = nouveau_encoder_connector_get(nv_encoder); 578 nv_connector = nouveau_encoder_connector_get(nv_encoder);
681 break; 579 break;
682 } 580 }
683 581
684 or = ffs(dcbent->or) - 1; 582 or = ffs(dcb->or) - 1;
685 mc = nv50_display_mode_ctrl(dev, dcbent->type != OUTPUT_ANALOG, or); 583 switch (dcb->type) {
686 switch (dcbent->type) {
687 case OUTPUT_LVDS: 584 case OUTPUT_LVDS:
688 script = (mc >> 8) & 0xf; 585 script = (mc >> 8) & 0xf;
689 if (bios->fp_no_ddc) { 586 if (bios->fp_no_ddc) {
@@ -774,17 +671,88 @@ nv50_display_vblank_handler(struct drm_device *dev, uint32_t intr)
774static void 671static void
775nv50_display_unk10_handler(struct drm_device *dev) 672nv50_display_unk10_handler(struct drm_device *dev)
776{ 673{
777 struct dcb_entry *dcbent; 674 struct drm_nouveau_private *dev_priv = dev->dev_private;
778 int head, ret; 675 u32 unk30 = nv_rd32(dev, 0x610030), mc;
676 int i, crtc, or, type = OUTPUT_ANY;
779 677
780 ret = nv50_display_irq_head(dev, &head, &dcbent); 678 NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30);
781 if (ret) 679 dev_priv->evo_irq.dcb = NULL;
782 goto ack;
783 680
784 nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) & ~8); 681 nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) & ~8);
785 682
786 nouveau_bios_run_display_table(dev, dcbent, 0, -1); 683 /* Determine which CRTC we're dealing with, only 1 ever will be
684 * signalled at the same time with the current nouveau code.
685 */
686 crtc = ffs((unk30 & 0x00000060) >> 5) - 1;
687 if (crtc < 0)
688 goto ack;
689
690 /* Nothing needs to be done for the encoder */
691 crtc = ffs((unk30 & 0x00000180) >> 7) - 1;
692 if (crtc < 0)
693 goto ack;
787 694
695 /* Find which encoder was connected to the CRTC */
696 for (i = 0; type == OUTPUT_ANY && i < 3; i++) {
697 mc = nv_rd32(dev, NV50_PDISPLAY_DAC_MODE_CTRL_C(i));
698 NV_DEBUG_KMS(dev, "DAC-%d mc: 0x%08x\n", i, mc);
699 if (!(mc & (1 << crtc)))
700 continue;
701
702 switch ((mc & 0x00000f00) >> 8) {
703 case 0: type = OUTPUT_ANALOG; break;
704 case 1: type = OUTPUT_TV; break;
705 default:
706 NV_ERROR(dev, "invalid mc, DAC-%d: 0x%08x\n", i, mc);
707 goto ack;
708 }
709
710 or = i;
711 }
712
713 for (i = 0; type == OUTPUT_ANY && i < 4; i++) {
714 if (dev_priv->chipset < 0x90 ||
715 dev_priv->chipset == 0x92 ||
716 dev_priv->chipset == 0xa0)
717 mc = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_C(i));
718 else
719 mc = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_C(i));
720
721 NV_DEBUG_KMS(dev, "SOR-%d mc: 0x%08x\n", i, mc);
722 if (!(mc & (1 << crtc)))
723 continue;
724
725 switch ((mc & 0x00000f00) >> 8) {
726 case 0: type = OUTPUT_LVDS; break;
727 case 1: type = OUTPUT_TMDS; break;
728 case 2: type = OUTPUT_TMDS; break;
729 case 5: type = OUTPUT_TMDS; break;
730 case 8: type = OUTPUT_DP; break;
731 case 9: type = OUTPUT_DP; break;
732 default:
733 NV_ERROR(dev, "invalid mc, SOR-%d: 0x%08x\n", i, mc);
734 goto ack;
735 }
736
737 or = i;
738 }
739
740 /* There was no encoder to disable */
741 if (type == OUTPUT_ANY)
742 goto ack;
743
744 /* Disable the encoder */
745 for (i = 0; i < dev_priv->vbios.dcb.entries; i++) {
746 struct dcb_entry *dcb = &dev_priv->vbios.dcb.entry[i];
747
748 if (dcb->type == type && (dcb->or & (1 << or))) {
749 nouveau_bios_run_display_table(dev, dcb, 0, -1);
750 dev_priv->evo_irq.dcb = dcb;
751 goto ack;
752 }
753 }
754
755 NV_ERROR(dev, "no dcb for %d %d 0x%08x\n", or, type, mc);
788ack: 756ack:
789 nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK10); 757 nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK10);
790 nv_wr32(dev, 0x610030, 0x80000000); 758 nv_wr32(dev, 0x610030, 0x80000000);
@@ -854,34 +822,104 @@ nv50_display_unk20_dp_set_tmds(struct drm_device *dev, struct dcb_entry *dcb)
854static void 822static void
855nv50_display_unk20_handler(struct drm_device *dev) 823nv50_display_unk20_handler(struct drm_device *dev)
856{ 824{
857 struct dcb_entry *dcbent; 825 struct drm_nouveau_private *dev_priv = dev->dev_private;
858 uint32_t tmp, pclk, script; 826 u32 unk30 = nv_rd32(dev, 0x610030), tmp, pclk, script, mc;
859 int head, or, ret; 827 struct dcb_entry *dcb;
828 int i, crtc, or, type = OUTPUT_ANY;
860 829
861 ret = nv50_display_irq_head(dev, &head, &dcbent); 830 NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30);
862 if (ret) 831 dcb = dev_priv->evo_irq.dcb;
832 if (dcb) {
833 nouveau_bios_run_display_table(dev, dcb, 0, -2);
834 dev_priv->evo_irq.dcb = NULL;
835 }
836
837 /* CRTC clock change requested? */
838 crtc = ffs((unk30 & 0x00000600) >> 9) - 1;
839 if (crtc >= 0) {
840 pclk = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(crtc, CLOCK));
841 pclk &= 0x003fffff;
842
843 nv50_crtc_set_clock(dev, crtc, pclk);
844
845 tmp = nv_rd32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(crtc));
846 tmp &= ~0x000000f;
847 nv_wr32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(crtc), tmp);
848 }
849
850 /* Nothing needs to be done for the encoder */
851 crtc = ffs((unk30 & 0x00000180) >> 7) - 1;
852 if (crtc < 0)
863 goto ack; 853 goto ack;
864 or = ffs(dcbent->or) - 1; 854 pclk = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(crtc, CLOCK)) & 0x003fffff;
865 pclk = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(head, CLOCK)) & 0x3fffff;
866 script = nv50_display_script_select(dev, dcbent, pclk);
867 855
868 NV_DEBUG_KMS(dev, "head %d pxclk: %dKHz\n", head, pclk); 856 /* Find which encoder is connected to the CRTC */
857 for (i = 0; type == OUTPUT_ANY && i < 3; i++) {
858 mc = nv_rd32(dev, NV50_PDISPLAY_DAC_MODE_CTRL_P(i));
859 NV_DEBUG_KMS(dev, "DAC-%d mc: 0x%08x\n", i, mc);
860 if (!(mc & (1 << crtc)))
861 continue;
869 862
870 if (dcbent->type != OUTPUT_DP) 863 switch ((mc & 0x00000f00) >> 8) {
871 nouveau_bios_run_display_table(dev, dcbent, 0, -2); 864 case 0: type = OUTPUT_ANALOG; break;
865 case 1: type = OUTPUT_TV; break;
866 default:
867 NV_ERROR(dev, "invalid mc, DAC-%d: 0x%08x\n", i, mc);
868 goto ack;
869 }
870
871 or = i;
872 }
873
874 for (i = 0; type == OUTPUT_ANY && i < 4; i++) {
875 if (dev_priv->chipset < 0x90 ||
876 dev_priv->chipset == 0x92 ||
877 dev_priv->chipset == 0xa0)
878 mc = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_P(i));
879 else
880 mc = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_P(i));
881
882 NV_DEBUG_KMS(dev, "SOR-%d mc: 0x%08x\n", i, mc);
883 if (!(mc & (1 << crtc)))
884 continue;
885
886 switch ((mc & 0x00000f00) >> 8) {
887 case 0: type = OUTPUT_LVDS; break;
888 case 1: type = OUTPUT_TMDS; break;
889 case 2: type = OUTPUT_TMDS; break;
890 case 5: type = OUTPUT_TMDS; break;
891 case 8: type = OUTPUT_DP; break;
892 case 9: type = OUTPUT_DP; break;
893 default:
894 NV_ERROR(dev, "invalid mc, SOR-%d: 0x%08x\n", i, mc);
895 goto ack;
896 }
872 897
873 nv50_crtc_set_clock(dev, head, pclk); 898 or = i;
899 }
874 900
875 nouveau_bios_run_display_table(dev, dcbent, script, pclk); 901 if (type == OUTPUT_ANY)
902 goto ack;
876 903
877 nv50_display_unk20_dp_hack(dev, dcbent); 904 /* Enable the encoder */
878 nv50_display_unk20_dp_set_tmds(dev, dcbent); 905 for (i = 0; i < dev_priv->vbios.dcb.entries; i++) {
906 dcb = &dev_priv->vbios.dcb.entry[i];
907 if (dcb->type == type && (dcb->or & (1 << or)))
908 break;
909 }
879 910
880 tmp = nv_rd32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(head)); 911 if (i == dev_priv->vbios.dcb.entries) {
881 tmp &= ~0x000000f; 912 NV_ERROR(dev, "no dcb for %d %d 0x%08x\n", or, type, mc);
882 nv_wr32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(head), tmp); 913 goto ack;
914 }
915
916 script = nv50_display_script_select(dev, dcb, mc, pclk);
917 nouveau_bios_run_display_table(dev, dcb, script, pclk);
883 918
884 if (dcbent->type != OUTPUT_ANALOG) { 919 nv50_display_unk20_dp_hack(dev, dcb);
920 nv50_display_unk20_dp_set_tmds(dev, dcb);
921
922 if (dcb->type != OUTPUT_ANALOG) {
885 tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_CLK_CTRL2(or)); 923 tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_CLK_CTRL2(or));
886 tmp &= ~0x00000f0f; 924 tmp &= ~0x00000f0f;
887 if (script & 0x0100) 925 if (script & 0x0100)
@@ -891,6 +929,10 @@ nv50_display_unk20_handler(struct drm_device *dev)
891 nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL2(or), 0); 929 nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL2(or), 0);
892 } 930 }
893 931
932 dev_priv->evo_irq.dcb = dcb;
933 dev_priv->evo_irq.pclk = pclk;
934 dev_priv->evo_irq.script = script;
935
894ack: 936ack:
895 nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK20); 937 nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK20);
896 nv_wr32(dev, 0x610030, 0x80000000); 938 nv_wr32(dev, 0x610030, 0x80000000);
@@ -899,17 +941,17 @@ ack:
899static void 941static void
900nv50_display_unk40_handler(struct drm_device *dev) 942nv50_display_unk40_handler(struct drm_device *dev)
901{ 943{
902 struct dcb_entry *dcbent; 944 struct drm_nouveau_private *dev_priv = dev->dev_private;
903 int head, pclk, script, ret; 945 struct dcb_entry *dcb = dev_priv->evo_irq.dcb;
946 u16 script = dev_priv->evo_irq.script;
947 u32 unk30 = nv_rd32(dev, 0x610030), pclk = dev_priv->evo_irq.pclk;
904 948
905 ret = nv50_display_irq_head(dev, &head, &dcbent); 949 NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30);
906 if (ret) 950 dev_priv->evo_irq.dcb = NULL;
951 if (!dcb)
907 goto ack; 952 goto ack;
908 pclk = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(head, CLOCK)) & 0x3fffff;
909 script = nv50_display_script_select(dev, dcbent, pclk);
910
911 nouveau_bios_run_display_table(dev, dcbent, script, -pclk);
912 953
954 nouveau_bios_run_display_table(dev, dcb, script, -pclk);
913ack: 955ack:
914 nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK40); 956 nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK40);
915 nv_wr32(dev, 0x610030, 0x80000000); 957 nv_wr32(dev, 0x610030, 0x80000000);