diff options
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_reg.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.c | 31 |
2 files changed, 32 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h index 6ca80a3fe70d..b6391a132f0a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_reg.h +++ b/drivers/gpu/drm/nouveau/nouveau_reg.h | |||
@@ -814,6 +814,7 @@ | |||
814 | #define NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE 0x80000000 | 814 | #define NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE 0x80000000 |
815 | #define NV50_PDISPLAY_SOR_BACKLIGHT_LEVEL 0x00000fff | 815 | #define NV50_PDISPLAY_SOR_BACKLIGHT_LEVEL 0x00000fff |
816 | #define NV50_SOR_DP_CTRL(i,l) (0x0061c10c + (i) * 0x800 + (l) * 0x80) | 816 | #define NV50_SOR_DP_CTRL(i,l) (0x0061c10c + (i) * 0x800 + (l) * 0x80) |
817 | #define NV50_SOR_DP_CTRL_ENABLED 0x00000001 | ||
817 | #define NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED 0x00004000 | 818 | #define NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED 0x00004000 |
818 | #define NV50_SOR_DP_CTRL_LANE_MASK 0x001f0000 | 819 | #define NV50_SOR_DP_CTRL_LANE_MASK 0x001f0000 |
819 | #define NV50_SOR_DP_CTRL_LANE_0_ENABLED 0x00010000 | 820 | #define NV50_SOR_DP_CTRL_LANE_0_ENABLED 0x00010000 |
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index e031904ef7a7..0c762049cb68 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c | |||
@@ -821,6 +821,36 @@ nv50_display_unk20_dp_hack(struct drm_device *dev, struct dcb_entry *dcb) | |||
821 | } | 821 | } |
822 | } | 822 | } |
823 | 823 | ||
824 | /* If programming a TMDS output on a SOR that can also be configured for | ||
825 | * DisplayPort, make sure NV50_SOR_DP_CTRL_ENABLE is forced off. | ||
826 | * | ||
827 | * It looks like the VBIOS TMDS scripts make an attempt at this, however, | ||
828 | * the VBIOS scripts on at least one board I have only switch it off on | ||
829 | * link 0, causing a blank display if the output has previously been | ||
830 | * programmed for DisplayPort. | ||
831 | */ | ||
832 | static void | ||
833 | nv50_display_unk20_dp_set_tmds(struct drm_device *dev, struct dcb_entry *dcb) | ||
834 | { | ||
835 | int or = ffs(dcb->or) - 1, link = !(dcb->dpconf.sor.link & 1); | ||
836 | struct drm_encoder *encoder; | ||
837 | u32 tmp; | ||
838 | |||
839 | if (dcb->type != OUTPUT_TMDS) | ||
840 | return; | ||
841 | |||
842 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
843 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||
844 | |||
845 | if (nv_encoder->dcb->type == OUTPUT_DP) { | ||
846 | tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); | ||
847 | tmp &= ~NV50_SOR_DP_CTRL_ENABLED; | ||
848 | nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp); | ||
849 | break; | ||
850 | } | ||
851 | } | ||
852 | } | ||
853 | |||
824 | static void | 854 | static void |
825 | nv50_display_unk20_handler(struct drm_device *dev) | 855 | nv50_display_unk20_handler(struct drm_device *dev) |
826 | { | 856 | { |
@@ -845,6 +875,7 @@ nv50_display_unk20_handler(struct drm_device *dev) | |||
845 | nouveau_bios_run_display_table(dev, dcbent, script, pclk); | 875 | nouveau_bios_run_display_table(dev, dcbent, script, pclk); |
846 | 876 | ||
847 | nv50_display_unk20_dp_hack(dev, dcbent); | 877 | nv50_display_unk20_dp_hack(dev, dcbent); |
878 | nv50_display_unk20_dp_set_tmds(dev, dcbent); | ||
848 | 879 | ||
849 | tmp = nv_rd32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(head)); | 880 | tmp = nv_rd32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(head)); |
850 | tmp &= ~0x000000f; | 881 | tmp &= ~0x000000f; |