diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2014-06-10 23:06:48 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2014-06-11 02:11:47 -0400 |
commit | 1ae5a62bb8b6b544bdfac7bdcb15c9eb22dd6620 (patch) | |
tree | 665fca654f1bc03b7009c2987ff737992303dfb3 | |
parent | 8777c5c11764d8336d8270f96778158c34c92108 (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.c | 38 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c | 26 |
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 | ||
1174 | static bool | 1174 | static struct nvkm_output * |
1175 | exec_script(struct nv50_disp_priv *priv, int head, int id) | 1175 | exec_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 | ||
1231 | static struct nvkm_output * | 1231 | static struct nvkm_output * |
@@ -1325,7 +1325,35 @@ nv50_disp_intr_unk10_0(struct nv50_disp_priv *priv, int head) | |||
1325 | static void | 1325 | static void |
1326 | nv50_disp_intr_unk20_0(struct nv50_disp_priv *priv, int head) | 1326 | nv50_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 | ||
1331 | static void | 1359 | static 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 | ||
965 | static bool | 965 | static struct nvkm_output * |
966 | exec_script(struct nv50_disp_priv *priv, int head, int id) | 966 | exec_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 | ||
1001 | static struct nvkm_output * | 1001 | static struct nvkm_output * |
@@ -1069,7 +1069,23 @@ nvd0_disp_intr_unk1_0(struct nv50_disp_priv *priv, int head) | |||
1069 | static void | 1069 | static void |
1070 | nvd0_disp_intr_unk2_0(struct nv50_disp_priv *priv, int head) | 1070 | nvd0_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 | ||
1075 | static void | 1091 | static void |