|
@@ -783,6 +783,37 @@ ack:
|
|
|
nv_wr32(dev, 0x610030, 0x80000000);
|
|
|
}
|
|
|
|
|
|
+static void
|
|
|
+nv50_display_unk20_dp_hack(struct drm_device *dev, struct dcb_entry *dcb)
|
|
|
+{
|
|
|
+ int or = ffs(dcb->or) - 1, link = !(dcb->dpconf.sor.link & 1);
|
|
|
+ struct drm_encoder *encoder;
|
|
|
+ uint32_t tmp, unk0 = 0, unk1 = 0;
|
|
|
+
|
|
|
+ if (dcb->type != OUTPUT_DP)
|
|
|
+ return;
|
|
|
+
|
|
|
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
|
|
+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
|
|
|
+
|
|
|
+ if (nv_encoder->dcb == dcb) {
|
|
|
+ unk0 = nv_encoder->dp.unk0;
|
|
|
+ unk1 = nv_encoder->dp.unk1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (unk0 || unk1) {
|
|
|
+ tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link));
|
|
|
+ tmp &= 0xfffffe03;
|
|
|
+ nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp | unk0);
|
|
|
+
|
|
|
+ tmp = nv_rd32(dev, NV50_SOR_DP_UNK128(or, link));
|
|
|
+ tmp &= 0xfef080c0;
|
|
|
+ nv_wr32(dev, NV50_SOR_DP_UNK128(or, link), tmp | unk1);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static void
|
|
|
nv50_display_unk20_handler(struct drm_device *dev)
|
|
|
{
|
|
@@ -806,6 +837,8 @@ nv50_display_unk20_handler(struct drm_device *dev)
|
|
|
|
|
|
nouveau_bios_run_display_table(dev, dcbent, script, pclk);
|
|
|
|
|
|
+ nv50_display_unk20_dp_hack(dev, dcbent);
|
|
|
+
|
|
|
tmp = nv_rd32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(head));
|
|
|
tmp &= ~0x000000f;
|
|
|
nv_wr32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(head), tmp);
|