diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2010-04-22 18:21:48 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-05-18 23:15:16 -0400 |
commit | afa3b4c37772f21b69980c155515927fdecd3a27 (patch) | |
tree | 754ad8f8089f70ffaa75ff7e01bf185d9213f28d /drivers | |
parent | 17b96cc38d93c65b3bf4e88ce89cc550dc90abf7 (diff) |
drm/nv50: fix suspend/resume with DP outputs
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_encoder.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_reg.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.c | 33 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_sor.c | 15 |
4 files changed, 46 insertions, 5 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index 9f28b94e479b..e1df8209cd0f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h | |||
@@ -48,6 +48,8 @@ struct nouveau_encoder { | |||
48 | union { | 48 | union { |
49 | struct { | 49 | struct { |
50 | int mc_unknown; | 50 | int mc_unknown; |
51 | uint32_t unk0; | ||
52 | uint32_t unk1; | ||
51 | int dpcd_version; | 53 | int dpcd_version; |
52 | int link_nr; | 54 | int link_nr; |
53 | int link_bw; | 55 | int link_bw; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h index aa9b310e41be..6ca80a3fe70d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_reg.h +++ b/drivers/gpu/drm/nouveau/nouveau_reg.h | |||
@@ -826,6 +826,7 @@ | |||
826 | #define NV50_SOR_DP_CTRL_TRAINING_PATTERN_2 0x02000000 | 826 | #define NV50_SOR_DP_CTRL_TRAINING_PATTERN_2 0x02000000 |
827 | #define NV50_SOR_DP_UNK118(i,l) (0x0061c118 + (i) * 0x800 + (l) * 0x80) | 827 | #define NV50_SOR_DP_UNK118(i,l) (0x0061c118 + (i) * 0x800 + (l) * 0x80) |
828 | #define NV50_SOR_DP_UNK120(i,l) (0x0061c120 + (i) * 0x800 + (l) * 0x80) | 828 | #define NV50_SOR_DP_UNK120(i,l) (0x0061c120 + (i) * 0x800 + (l) * 0x80) |
829 | #define NV50_SOR_DP_UNK128(i,l) (0x0061c128 + (i) * 0x800 + (l) * 0x80) | ||
829 | #define NV50_SOR_DP_UNK130(i,l) (0x0061c130 + (i) * 0x800 + (l) * 0x80) | 830 | #define NV50_SOR_DP_UNK130(i,l) (0x0061c130 + (i) * 0x800 + (l) * 0x80) |
830 | 831 | ||
831 | #define NV50_PDISPLAY_USER(i) ((i) * 0x1000 + 0x00640000) | 832 | #define NV50_PDISPLAY_USER(i) ((i) * 0x1000 + 0x00640000) |
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 34156b69594f..580a5d10be93 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c | |||
@@ -784,6 +784,37 @@ ack: | |||
784 | } | 784 | } |
785 | 785 | ||
786 | static void | 786 | static void |
787 | nv50_display_unk20_dp_hack(struct drm_device *dev, struct dcb_entry *dcb) | ||
788 | { | ||
789 | int or = ffs(dcb->or) - 1, link = !(dcb->dpconf.sor.link & 1); | ||
790 | struct drm_encoder *encoder; | ||
791 | uint32_t tmp, unk0 = 0, unk1 = 0; | ||
792 | |||
793 | if (dcb->type != OUTPUT_DP) | ||
794 | return; | ||
795 | |||
796 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
797 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||
798 | |||
799 | if (nv_encoder->dcb == dcb) { | ||
800 | unk0 = nv_encoder->dp.unk0; | ||
801 | unk1 = nv_encoder->dp.unk1; | ||
802 | break; | ||
803 | } | ||
804 | } | ||
805 | |||
806 | if (unk0 || unk1) { | ||
807 | tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); | ||
808 | tmp &= 0xfffffe03; | ||
809 | nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp | unk0); | ||
810 | |||
811 | tmp = nv_rd32(dev, NV50_SOR_DP_UNK128(or, link)); | ||
812 | tmp &= 0xfef080c0; | ||
813 | nv_wr32(dev, NV50_SOR_DP_UNK128(or, link), tmp | unk1); | ||
814 | } | ||
815 | } | ||
816 | |||
817 | static void | ||
787 | nv50_display_unk20_handler(struct drm_device *dev) | 818 | nv50_display_unk20_handler(struct drm_device *dev) |
788 | { | 819 | { |
789 | struct dcb_entry *dcbent; | 820 | struct dcb_entry *dcbent; |
@@ -806,6 +837,8 @@ nv50_display_unk20_handler(struct drm_device *dev) | |||
806 | 837 | ||
807 | nouveau_bios_run_display_table(dev, dcbent, script, pclk); | 838 | nouveau_bios_run_display_table(dev, dcbent, script, pclk); |
808 | 839 | ||
840 | nv50_display_unk20_dp_hack(dev, dcbent); | ||
841 | |||
809 | tmp = nv_rd32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(head)); | 842 | tmp = nv_rd32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(head)); |
810 | tmp &= ~0x000000f; | 843 | tmp &= ~0x000000f; |
811 | nv_wr32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(head), tmp); | 844 | nv_wr32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(head), tmp); |
diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c index 0c68698f23df..b11eaf9c5c7c 100644 --- a/drivers/gpu/drm/nouveau/nv50_sor.c +++ b/drivers/gpu/drm/nouveau/nv50_sor.c | |||
@@ -321,18 +321,23 @@ nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry) | |||
321 | encoder->possible_clones = 0; | 321 | encoder->possible_clones = 0; |
322 | 322 | ||
323 | if (nv_encoder->dcb->type == OUTPUT_DP) { | 323 | if (nv_encoder->dcb->type == OUTPUT_DP) { |
324 | uint32_t mc, or = nv_encoder->or; | 324 | int or = nv_encoder->or, link = !(entry->dpconf.sor.link & 1); |
325 | uint32_t tmp; | ||
325 | 326 | ||
326 | if (dev_priv->chipset < 0x90 || | 327 | if (dev_priv->chipset < 0x90 || |
327 | dev_priv->chipset == 0x92 || dev_priv->chipset == 0xa0) | 328 | dev_priv->chipset == 0x92 || dev_priv->chipset == 0xa0) |
328 | mc = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_C(or)); | 329 | tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_C(or)); |
329 | else | 330 | else |
330 | mc = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_C(or)); | 331 | tmp = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_C(or)); |
331 | 332 | ||
332 | switch ((mc & 0x00000f00) >> 8) { | 333 | switch ((tmp & 0x00000f00) >> 8) { |
333 | case 8: | 334 | case 8: |
334 | case 9: | 335 | case 9: |
335 | nv_encoder->dp.mc_unknown = (mc & 0x000f0000) >> 16; | 336 | nv_encoder->dp.mc_unknown = (tmp & 0x000f0000) >> 16; |
337 | tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); | ||
338 | nv_encoder->dp.unk0 = tmp & 0x000001fc; | ||
339 | tmp = nv_rd32(dev, NV50_SOR_DP_UNK128(or, link)); | ||
340 | nv_encoder->dp.unk1 = tmp & 0x010f7f3f; | ||
336 | break; | 341 | break; |
337 | default: | 342 | default: |
338 | break; | 343 | break; |