aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2014-06-10 23:06:48 -0400
committerBen Skeggs <bskeggs@redhat.com>2014-06-11 02:11:47 -0400
commit1ae5a62bb8b6b544bdfac7bdcb15c9eb22dd6620 (patch)
tree665fca654f1bc03b7009c2987ff737992303dfb3
parent8777c5c11764d8336d8270f96778158c34c92108 (diff)
drm/nouveau/disp/dp: fix tmds passthrough on dp connector
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.c38
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c26
2 files changed, 54 insertions, 10 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
index 90974cd087c1..1e85f36c705f 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
@@ -1171,7 +1171,7 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl,
1171 return NULL; 1171 return NULL;
1172} 1172}
1173 1173
1174static bool 1174static struct nvkm_output *
1175exec_script(struct nv50_disp_priv *priv, int head, int id) 1175exec_script(struct nv50_disp_priv *priv, int head, int id)
1176{ 1176{
1177 struct nouveau_bios *bios = nouveau_bios(priv); 1177 struct nouveau_bios *bios = nouveau_bios(priv);
@@ -1208,7 +1208,7 @@ exec_script(struct nv50_disp_priv *priv, int head, int id)
1208 } 1208 }
1209 1209
1210 if (!(ctrl & (1 << head))) 1210 if (!(ctrl & (1 << head)))
1211 return false; 1211 return NULL;
1212 i--; 1212 i--;
1213 1213
1214 outp = exec_lookup(priv, head, i, ctrl, &data, &ver, &hdr, &cnt, &len, &info); 1214 outp = exec_lookup(priv, head, i, ctrl, &data, &ver, &hdr, &cnt, &len, &info);
@@ -1222,10 +1222,10 @@ exec_script(struct nv50_disp_priv *priv, int head, int id)
1222 .execute = 1, 1222 .execute = 1,
1223 }; 1223 };
1224 1224
1225 return nvbios_exec(&init) == 0; 1225 nvbios_exec(&init);
1226 } 1226 }
1227 1227
1228 return false; 1228 return outp;
1229} 1229}
1230 1230
1231static struct nvkm_output * 1231static struct nvkm_output *
@@ -1325,7 +1325,35 @@ nv50_disp_intr_unk10_0(struct nv50_disp_priv *priv, int head)
1325static void 1325static void
1326nv50_disp_intr_unk20_0(struct nv50_disp_priv *priv, int head) 1326nv50_disp_intr_unk20_0(struct nv50_disp_priv *priv, int head)
1327{ 1327{
1328 exec_script(priv, head, 2); 1328 struct nvkm_output *outp = exec_script(priv, head, 2);
1329
1330 /* the binary driver does this outside of the supervisor handling
1331 * (after the third supervisor from a detach). we (currently?)
1332 * allow both detach/attach to happen in the same set of
1333 * supervisor interrupts, so it would make sense to execute this
1334 * (full power down?) script after all the detach phases of the
1335 * supervisor handling. like with training if needed from the
1336 * second supervisor, nvidia doesn't do this, so who knows if it's
1337 * entirely safe, but it does appear to work..
1338 *
1339 * without this script being run, on some configurations i've
1340 * seen, switching from DP to TMDS on a DP connector may result
1341 * in a blank screen (SOR_PWR off/on can restore it)
1342 */
1343 if (outp && outp->info.type == DCB_OUTPUT_DP) {
1344 struct nvkm_output_dp *outpdp = (void *)outp;
1345 struct nvbios_init init = {
1346 .subdev = nv_subdev(priv),
1347 .bios = nouveau_bios(priv),
1348 .outp = &outp->info,
1349 .crtc = head,
1350 .offset = outpdp->info.script[4],
1351 .execute = 1,
1352 };
1353
1354 nvbios_exec(&init);
1355 atomic_set(&outpdp->lt.done, 0);
1356 }
1329} 1357}
1330 1358
1331static void 1359static void
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
index b998040b5cca..48aa38a87e3f 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
@@ -962,7 +962,7 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl,
962 return NULL; 962 return NULL;
963} 963}
964 964
965static bool 965static struct nvkm_output *
966exec_script(struct nv50_disp_priv *priv, int head, int id) 966exec_script(struct nv50_disp_priv *priv, int head, int id)
967{ 967{
968 struct nouveau_bios *bios = nouveau_bios(priv); 968 struct nouveau_bios *bios = nouveau_bios(priv);
@@ -979,7 +979,7 @@ exec_script(struct nv50_disp_priv *priv, int head, int id)
979 } 979 }
980 980
981 if (or == 8) 981 if (or == 8)
982 return false; 982 return NULL;
983 983
984 outp = exec_lookup(priv, head, or, ctrl, &data, &ver, &hdr, &cnt, &len, &info); 984 outp = exec_lookup(priv, head, or, ctrl, &data, &ver, &hdr, &cnt, &len, &info);
985 if (outp) { 985 if (outp) {
@@ -992,10 +992,10 @@ exec_script(struct nv50_disp_priv *priv, int head, int id)
992 .execute = 1, 992 .execute = 1,
993 }; 993 };
994 994
995 return nvbios_exec(&init) == 0; 995 nvbios_exec(&init);
996 } 996 }
997 997
998 return false; 998 return outp;
999} 999}
1000 1000
1001static struct nvkm_output * 1001static struct nvkm_output *
@@ -1069,7 +1069,23 @@ nvd0_disp_intr_unk1_0(struct nv50_disp_priv *priv, int head)
1069static void 1069static void
1070nvd0_disp_intr_unk2_0(struct nv50_disp_priv *priv, int head) 1070nvd0_disp_intr_unk2_0(struct nv50_disp_priv *priv, int head)
1071{ 1071{
1072 exec_script(priv, head, 2); 1072 struct nvkm_output *outp = exec_script(priv, head, 2);
1073
1074 /* see note in nv50_disp_intr_unk20_0() */
1075 if (outp && outp->info.type == DCB_OUTPUT_DP) {
1076 struct nvkm_output_dp *outpdp = (void *)outp;
1077 struct nvbios_init init = {
1078 .subdev = nv_subdev(priv),
1079 .bios = nouveau_bios(priv),
1080 .outp = &outp->info,
1081 .crtc = head,
1082 .offset = outpdp->info.script[4],
1083 .execute = 1,
1084 };
1085
1086 nvbios_exec(&init);
1087 atomic_set(&outpdp->lt.done, 0);
1088 }
1073} 1089}
1074 1090
1075static void 1091static void