aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-04-22 18:21:48 -0400
committerBen Skeggs <bskeggs@redhat.com>2010-05-18 23:15:16 -0400
commitafa3b4c37772f21b69980c155515927fdecd3a27 (patch)
tree754ad8f8089f70ffaa75ff7e01bf185d9213f28d /drivers/gpu/drm
parent17b96cc38d93c65b3bf4e88ce89cc550dc90abf7 (diff)
drm/nv50: fix suspend/resume with DP outputs
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_encoder.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_reg.h1
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c33
-rw-r--r--drivers/gpu/drm/nouveau/nv50_sor.c15
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
786static void 786static void
787nv50_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
817static void
787nv50_display_unk20_handler(struct drm_device *dev) 818nv50_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;