Commit 9793083f authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/disp: move LVDS protocol information into acquire

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
parent ea6143a8
......@@ -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);
......
......@@ -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;
......
......@@ -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];
......
......@@ -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
......@@ -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;
......
......@@ -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;
}
......
......@@ -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. */
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment