diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 093321a93046..0a8404686f16 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1635,15 +1635,6 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta struct nv50_head_atom *asyh = nv50_head_atom(drm_atomic_get_new_crtc_state(state, &nv_crtc->base)); struct drm_display_mode *mode = &asyh->state.adjusted_mode; - struct { - struct nv50_disp_mthd_v1 base; - struct nv50_disp_sor_lvds_script_v0 lvds; - } lvds = { - .base.version = 1, - .base.method = NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT, - .base.hasht = nv_encoder->dcb->hasht, - .base.hashm = nv_encoder->dcb->hashm, - }; struct nv50_disp *disp = nv50_disp(encoder->dev); struct drm_device *dev = encoder->dev; struct nouveau_drm *drm = nouveau_drm(dev); @@ -1652,7 +1643,7 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta struct nouveau_backlight *backlight; #endif struct nvbios *bios = &drm->vbios; - bool hda = false; + bool lvds_dual = false, lvds_8bpc = false, hda = false; u8 proto = NV507D_SOR_SET_CONTROL_PROTOCOL_CUSTOM; u8 depth = NV837D_SOR_SET_CONTROL_PIXEL_DEPTH_DEFAULT; @@ -1689,33 +1680,30 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta proto = NV507D_SOR_SET_CONTROL_PROTOCOL_LVDS_CUSTOM; if (bios->fp_no_ddc) { - if (bios->fp.dual_link) - lvds.lvds.script |= 0x0100; - if (bios->fp.if_is_24bit) - lvds.lvds.script |= 0x0200; + lvds_dual = bios->fp.dual_link; + lvds_8bpc = bios->fp.if_is_24bit; } else { if (nv_connector->type == DCB_CONNECTOR_LVDS_SPWG) { if (((u8 *)nv_connector->edid)[121] == 2) - lvds.lvds.script |= 0x0100; + lvds_dual = true; } else if (mode->clock >= bios->fp.duallink_transition_clk) { - lvds.lvds.script |= 0x0100; + lvds_dual = true; } - if (lvds.lvds.script & 0x0100) { + if (lvds_dual) { if (bios->fp.strapless_is_24bit & 2) - lvds.lvds.script |= 0x0200; + lvds_8bpc = true; } else { if (bios->fp.strapless_is_24bit & 1) - lvds.lvds.script |= 0x0200; + lvds_8bpc = true; } if (asyh->or.bpc == 8) - lvds.lvds.script |= 0x0200; + lvds_8bpc = true; } - nvif_outp_acquire_lvds(&nv_encoder->outp); - nvif_mthd(&disp->disp->object, 0, &lvds, sizeof(lvds)); + nvif_outp_acquire_lvds(&nv_encoder->outp, lvds_dual, lvds_8bpc); break; case DCB_OUTPUT_DP: nvif_outp_acquire_dp(&nv_encoder->outp, hda); diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h index 37e669b9c4dc..f371fc7a1d10 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h @@ -30,7 +30,6 @@ struct nv50_disp_mthd_v1 { __u8 version; #define NV50_DISP_MTHD_V1_SOR_HDA_ELD 0x21 #define NV50_DISP_MTHD_V1_SOR_HDMI_PWR 0x22 -#define NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT 0x23 #define NV50_DISP_MTHD_V1_SOR_DP_MST_LINK 0x25 #define NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI 0x26 __u8 method; @@ -58,13 +57,6 @@ struct nv50_disp_sor_hdmi_pwr_v0 { __u8 pad07[1]; }; -struct nv50_disp_sor_lvds_script_v0 { - __u8 version; - __u8 pad01[1]; - __u16 script; - __u8 pad04[4]; -}; - struct nv50_disp_sor_dp_mst_link_v0 { __u8 version; __u8 state; diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h b/drivers/gpu/drm/nouveau/include/nvif/if0012.h index 8bc00a8c525a..4fcb9e4f5d76 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h +++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h @@ -40,6 +40,11 @@ union nvif_outp_acquire_args { __u8 hda; __u8 pad01[7]; } tmds; + struct { + __u8 dual; + __u8 bpc8; + __u8 pad02[6]; + } lvds; struct { __u8 hda; __u8 pad01[7]; diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h b/drivers/gpu/drm/nouveau/include/nvif/outp.h index 2a45b57b1f75..e247d441afc1 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/outp.h +++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h @@ -18,7 +18,7 @@ void nvif_outp_dtor(struct nvif_outp *); int nvif_outp_load_detect(struct nvif_outp *, u32 loadval); int nvif_outp_acquire_rgb_crt(struct nvif_outp *); int nvif_outp_acquire_tmds(struct nvif_outp *, bool hda); -int nvif_outp_acquire_lvds(struct nvif_outp *); +int nvif_outp_acquire_lvds(struct nvif_outp *, bool dual, bool bpc8); int nvif_outp_acquire_dp(struct nvif_outp *, bool hda); void nvif_outp_release(struct nvif_outp *); #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h index 8b5d8a434be8..eaf10f5d505e 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h @@ -31,13 +31,7 @@ struct nvkm_disp { struct { unsigned long mask; int nr; - } wndw, head, dac; - - struct { - unsigned long mask; - int nr; - u32 lvdsconf; - } sor; + } wndw, head, dac, sor; struct { unsigned long mask; diff --git a/drivers/gpu/drm/nouveau/nvif/outp.c b/drivers/gpu/drm/nouveau/nvif/outp.c index bd20f75045dc..58cd629657fb 100644 --- a/drivers/gpu/drm/nouveau/nvif/outp.c +++ b/drivers/gpu/drm/nouveau/nvif/outp.c @@ -66,13 +66,18 @@ nvif_outp_acquire_dp(struct nvif_outp *outp, bool hda) } int -nvif_outp_acquire_lvds(struct nvif_outp *outp) +nvif_outp_acquire_lvds(struct nvif_outp *outp, bool dual, bool bpc8) { struct nvif_outp_acquire_v0 args; int ret; + args.lvds.dual = dual; + args.lvds.bpc8 = bpc8; + ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_LVDS, &args); - NVIF_ERRON(ret, &outp->object, "[ACQUIRE proto:LVDS] or:%d link:%d", args.or, args.link); + NVIF_ERRON(ret, &outp->object, + "[ACQUIRE proto:LVDS dual:%d 8bpc:%d] or:%d link:%d", + args.lvds.dual, args.lvds.bpc8, args.or, args.link); return ret; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c index a46e13cc9ff1..55ac6d70e950 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c @@ -1238,6 +1238,8 @@ nv50_disp_super_2_2(struct nvkm_disp *disp, struct nvkm_head *head) if (!ior) return; + outp = ior->asy.outp; + /* For some reason, NVIDIA decided not to: * * A) Give dual-link LVDS a separate EVO protocol, like for TMDS. @@ -1247,13 +1249,13 @@ nv50_disp_super_2_2(struct nvkm_disp *disp, struct nvkm_head *head) * Override the values we usually read from HW with the same * data we pass though an ioctl instead. */ - if (ior->type == SOR && ior->asy.proto == LVDS) { - head->asy.or.depth = (disp->sor.lvdsconf & 0x0200) ? 24 : 18; - ior->asy.link = (disp->sor.lvdsconf & 0x0100) ? 3 : 1; + if (outp && ior->type == SOR && ior->asy.proto == LVDS) { + head->asy.or.depth = outp->lvds.bpc8 ? 24 : 18; + ior->asy.link = outp->lvds.dual ? 3 : 1; } /* Handle any link training, etc. */ - if ((outp = ior->asy.outp) && outp->func->acquire) + if (outp && outp->func->acquire) outp->func->acquire(outp); /* Execute OnInt2 IED script. */ diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h index 3f3924c41957..16aadcedcbda 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h @@ -27,6 +27,11 @@ struct nvkm_outp { struct nvkm_ior *ior; union { + struct { + bool dual; + bool bpc8; + } lvds; + struct { struct nvbios_dpout info; u8 version; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c index 341f244cddb7..f028ab17f8cf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c @@ -169,22 +169,6 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) return 0; } break; - case NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT: { - union { - struct nv50_disp_sor_lvds_script_v0 v0; - } *args = data; - int ret = -ENOSYS; - nvif_ioctl(object, "disp sor lvds script size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(object, "disp sor lvds script " - "vers %d name %04x\n", - args->v0.version, args->v0.script); - disp->sor.lvdsconf = args->v0.script; - return 0; - } else - return ret; - } - break; case NV50_DISP_MTHD_V1_SOR_DP_MST_LINK: { union { struct nv50_disp_sor_dp_mst_link_v0 v0; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c index edbed699ade2..7e0cef0f80a9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c @@ -37,6 +37,18 @@ nvkm_uoutp_mthd_release(struct nvkm_outp *outp, void *argv, u32 argc) return 0; } +static int +nvkm_uoutp_mthd_acquire_lvds(struct nvkm_outp *outp, bool dual, bool bpc8) +{ + if (outp->info.type != DCB_OUTPUT_LVDS) + return -EINVAL; + + outp->lvds.dual = dual; + outp->lvds.bpc8 = bpc8; + + return nvkm_outp_acquire(outp, NVKM_OUTP_USER, false); +} + static int nvkm_uoutp_mthd_acquire(struct nvkm_outp *outp, void *argv, u32 argc) { @@ -48,13 +60,15 @@ nvkm_uoutp_mthd_acquire(struct nvkm_outp *outp, void *argv, u32 argc) switch (args->v0.proto) { case NVIF_OUTP_ACQUIRE_V0_RGB_CRT: - case NVIF_OUTP_ACQUIRE_V0_LVDS: ret = nvkm_outp_acquire(outp, NVKM_OUTP_USER, false); break; case NVIF_OUTP_ACQUIRE_V0_TMDS: case NVIF_OUTP_ACQUIRE_V0_DP: ret = nvkm_outp_acquire(outp, NVKM_OUTP_USER, args->v0.dp.hda); break; + case NVIF_OUTP_ACQUIRE_V0_LVDS: + ret = nvkm_uoutp_mthd_acquire_lvds(outp, args->v0.lvds.dual, args->v0.lvds.bpc8); + break; default: ret = -EINVAL; break;