Commit a3761fa2 authored by Ben Skeggs's avatar Ben Skeggs

drm/nv50-/disp: audit and version LVDS_SCRIPT method

The full object interfaces are about to be exposed to userspace, so we
need to check for any security-related issues and version the structs
to make it easier to handle any changes we may need in the future.
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent e00f2235
...@@ -913,6 +913,21 @@ nv50_disp_base_mthd(struct nouveau_object *object, u32 mthd, ...@@ -913,6 +913,21 @@ nv50_disp_base_mthd(struct nouveau_object *object, u32 mthd,
if (!priv->sor.hdmi) if (!priv->sor.hdmi)
return -ENODEV; return -ENODEV;
return priv->sor.hdmi(object, priv, data, size, head, outp); return priv->sor.hdmi(object, priv, data, size, head, outp);
case NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT: {
union {
struct nv50_disp_sor_lvds_script_v0 v0;
} *args = data;
nv_ioctl(object, "disp sor lvds script size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(object, "disp sor lvds script "
"vers %d name %04x\n",
args->v0.version, args->v0.script);
priv->sor.lvdsconf = args->v0.script;
return 0;
} else
return ret;
}
break;
default: default:
break; break;
} }
...@@ -1041,7 +1056,6 @@ nv50_disp_base_ofuncs = { ...@@ -1041,7 +1056,6 @@ nv50_disp_base_ofuncs = {
static struct nouveau_omthds static struct nouveau_omthds
nv50_disp_base_omthds[] = { nv50_disp_base_omthds[] = {
{ HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos }, { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd }, { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd }, { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
......
...@@ -215,7 +215,6 @@ nv84_disp_sclass[] = { ...@@ -215,7 +215,6 @@ nv84_disp_sclass[] = {
struct nouveau_omthds struct nouveau_omthds
nv84_disp_base_omthds[] = { nv84_disp_base_omthds[] = {
{ HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos }, { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd }, { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd }, { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
......
...@@ -74,7 +74,6 @@ nv94_disp_sclass[] = { ...@@ -74,7 +74,6 @@ nv94_disp_sclass[] = {
static struct nouveau_omthds static struct nouveau_omthds
nv94_disp_base_omthds[] = { nv94_disp_base_omthds[] = {
{ HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos }, { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
{ SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd }, { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd }, { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
......
...@@ -46,7 +46,6 @@ nva3_disp_sclass[] = { ...@@ -46,7 +46,6 @@ nva3_disp_sclass[] = {
static struct nouveau_omthds static struct nouveau_omthds
nva3_disp_base_omthds[] = { nva3_disp_base_omthds[] = {
{ HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos }, { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
{ SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd }, { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd }, { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
......
...@@ -712,7 +712,6 @@ nvd0_disp_base_ofuncs = { ...@@ -712,7 +712,6 @@ nvd0_disp_base_ofuncs = {
struct nouveau_omthds struct nouveau_omthds
nvd0_disp_base_omthds[] = { nvd0_disp_base_omthds[] = {
{ HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nvd0_disp_base_scanoutpos }, { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nvd0_disp_base_scanoutpos },
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
{ SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd }, { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd }, { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
......
...@@ -84,10 +84,6 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size) ...@@ -84,10 +84,6 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
} }
switch (mthd & ~0x3f) { switch (mthd & ~0x3f) {
case NV50_DISP_SOR_LVDS_SCRIPT:
priv->sor.lvdsconf = data & NV50_DISP_SOR_LVDS_SCRIPT_ID;
ret = 0;
break;
case NV94_DISP_SOR_DP_PWR: case NV94_DISP_SOR_DP_PWR:
if (outp) { if (outp) {
struct nvkm_output_dp *outpdp = (void *)outp; struct nvkm_output_dp *outpdp = (void *)outp;
......
...@@ -59,8 +59,6 @@ struct nv04_display_scanoutpos { ...@@ -59,8 +59,6 @@ struct nv04_display_scanoutpos {
#define NV50_DISP_SOR_MTHD_LINK 0x00000004 #define NV50_DISP_SOR_MTHD_LINK 0x00000004
#define NV50_DISP_SOR_MTHD_OR 0x00000003 #define NV50_DISP_SOR_MTHD_OR 0x00000003
#define NV50_DISP_SOR_LVDS_SCRIPT 0x00013000
#define NV50_DISP_SOR_LVDS_SCRIPT_ID 0x0000ffff
#define NV94_DISP_SOR_DP_PWR 0x00016000 #define NV94_DISP_SOR_DP_PWR 0x00016000
#define NV94_DISP_SOR_DP_PWR_STATE 0x00000001 #define NV94_DISP_SOR_DP_PWR_STATE 0x00000001
#define NV94_DISP_SOR_DP_PWR_STATE_OFF 0x00000000 #define NV94_DISP_SOR_DP_PWR_STATE_OFF 0x00000000
......
...@@ -1882,15 +1882,24 @@ static void ...@@ -1882,15 +1882,24 @@ static void
nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
struct drm_display_mode *mode) struct drm_display_mode *mode)
{ {
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
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 nv50_disp *disp = nv50_disp(encoder->dev);
struct nv50_mast *mast = nv50_mast(encoder->dev); struct nv50_mast *mast = nv50_mast(encoder->dev);
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
struct nouveau_connector *nv_connector; struct nouveau_connector *nv_connector;
struct nvbios *bios = &drm->vbios; struct nvbios *bios = &drm->vbios;
u32 lvds = 0, mask, ctrl; u32 mask, ctrl;
u8 owner = 1 << nv_crtc->index; u8 owner = 1 << nv_crtc->index;
u8 proto = 0xf; u8 proto = 0xf;
u8 depth = 0x0; u8 depth = 0x0;
...@@ -1916,31 +1925,31 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, ...@@ -1916,31 +1925,31 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
if (bios->fp_no_ddc) { if (bios->fp_no_ddc) {
if (bios->fp.dual_link) if (bios->fp.dual_link)
lvds |= 0x0100; lvds.lvds.script |= 0x0100;
if (bios->fp.if_is_24bit) if (bios->fp.if_is_24bit)
lvds |= 0x0200; lvds.lvds.script |= 0x0200;
} else { } else {
if (nv_connector->type == DCB_CONNECTOR_LVDS_SPWG) { if (nv_connector->type == DCB_CONNECTOR_LVDS_SPWG) {
if (((u8 *)nv_connector->edid)[121] == 2) if (((u8 *)nv_connector->edid)[121] == 2)
lvds |= 0x0100; lvds.lvds.script |= 0x0100;
} else } else
if (mode->clock >= bios->fp.duallink_transition_clk) { if (mode->clock >= bios->fp.duallink_transition_clk) {
lvds |= 0x0100; lvds.lvds.script |= 0x0100;
} }
if (lvds & 0x0100) { if (lvds.lvds.script & 0x0100) {
if (bios->fp.strapless_is_24bit & 2) if (bios->fp.strapless_is_24bit & 2)
lvds |= 0x0200; lvds.lvds.script |= 0x0200;
} else { } else {
if (bios->fp.strapless_is_24bit & 1) if (bios->fp.strapless_is_24bit & 1)
lvds |= 0x0200; lvds.lvds.script |= 0x0200;
} }
if (nv_connector->base.display_info.bpc == 8) if (nv_connector->base.display_info.bpc == 8)
lvds |= 0x0200; lvds.lvds.script |= 0x0200;
} }
nvif_exec(disp->disp, NV50_DISP_SOR_LVDS_SCRIPT + nv_encoder->or, &lvds, sizeof(lvds)); nvif_mthd(disp->disp, 0, &lvds, sizeof(lvds));
break; break;
case DCB_OUTPUT_DP: case DCB_OUTPUT_DP:
if (nv_connector->base.display_info.bpc == 6) { if (nv_connector->base.display_info.bpc == 6) {
......
...@@ -360,4 +360,11 @@ struct nv50_disp_sor_hdmi_pwr_v0 { ...@@ -360,4 +360,11 @@ struct nv50_disp_sor_hdmi_pwr_v0 {
__u8 pad04[4]; __u8 pad04[4];
}; };
struct nv50_disp_sor_lvds_script_v0 {
__u8 version;
__u8 pad01[1];
__u16 script;
__u8 pad04[4];
};
#endif #endif
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