diff options
| -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 |
