Commit 8f2abc25 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/dp: remove last bits of VBIOS parsing from DRM code


Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 6c8e4633
......@@ -26,6 +26,12 @@ struct nv50_disp_priv {
int (*power)(struct nv50_disp_priv *, int sor, u32 data);
int (*hda_eld)(struct nv50_disp_priv *, int sor, u8 *, u32);
int (*hdmi)(struct nv50_disp_priv *, int head, int sor, u32);
int (*dp_train_init)(struct nv50_disp_priv *, int sor, int link,
int head, u16 type, u16 mask, u32 data,
struct dcb_output *);
int (*dp_train_fini)(struct nv50_disp_priv *, int sor, int link,
int head, u16 type, u16 mask, u32 data,
struct dcb_output *);
int (*dp_train)(struct nv50_disp_priv *, int sor, int link,
u16 type, u16 mask, u32 data,
struct dcb_output *);
......@@ -57,6 +63,10 @@ int nvd0_hdmi_ctrl(struct nv50_disp_priv *, int, int, u32);
int nv50_sor_mthd(struct nouveau_object *, u32, void *, u32);
int nv50_sor_power(struct nv50_disp_priv *, int, u32);
int nv94_sor_dp_train_init(struct nv50_disp_priv *, int, int, int, u16, u16,
u32, struct dcb_output *);
int nv94_sor_dp_train_fini(struct nv50_disp_priv *, int, int, int, u16, u16,
u32, struct dcb_output *);
int nv94_sor_dp_train(struct nv50_disp_priv *, int, int, u16, u16, u32,
struct dcb_output *);
int nv94_sor_dp_lnkctl(struct nv50_disp_priv *, int, int, int, u16, u16, u32,
......
......@@ -87,6 +87,8 @@ nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
priv->sor.power = nv50_sor_power;
priv->sor.hdmi = nv84_hdmi_ctrl;
priv->sor.dp_train = nv94_sor_dp_train;
priv->sor.dp_train_init = nv94_sor_dp_train_init;
priv->sor.dp_train_fini = nv94_sor_dp_train_fini;
priv->sor.dp_lnkctl = nv94_sor_dp_lnkctl;
priv->sor.dp_drvctl = nv94_sor_dp_drvctl;
......
......@@ -89,6 +89,8 @@ nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
priv->sor.hda_eld = nva3_hda_eld;
priv->sor.hdmi = nva3_hdmi_ctrl;
priv->sor.dp_train = nv94_sor_dp_train;
priv->sor.dp_train_init = nv94_sor_dp_train_init;
priv->sor.dp_train_fini = nv94_sor_dp_train_fini;
priv->sor.dp_lnkctl = nv94_sor_dp_lnkctl;
priv->sor.dp_drvctl = nv94_sor_dp_drvctl;
......
......@@ -951,6 +951,8 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
priv->sor.hda_eld = nvd0_hda_eld;
priv->sor.hdmi = nvd0_hdmi_ctrl;
priv->sor.dp_train = nvd0_sor_dp_train;
priv->sor.dp_train_init = nv94_sor_dp_train_init;
priv->sor.dp_train_fini = nv94_sor_dp_train_fini;
priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl;
priv->sor.dp_drvctl = nvd0_sor_dp_drvctl;
......
......@@ -72,6 +72,8 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
priv->sor.hda_eld = nvd0_hda_eld;
priv->sor.hdmi = nvd0_hdmi_ctrl;
priv->sor.dp_train = nvd0_sor_dp_train;
priv->sor.dp_train_init = nv94_sor_dp_train_init;
priv->sor.dp_train_fini = nv94_sor_dp_train_fini;
priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl;
priv->sor.dp_drvctl = nvd0_sor_dp_drvctl;
......
......@@ -80,7 +80,19 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
ret = 0;
break;
case NV94_DISP_SOR_DP_TRAIN:
ret = priv->sor.dp_train(priv, or, link, type, mask, data, &outp);
switch (data & NV94_DISP_SOR_DP_TRAIN_OP) {
case NV94_DISP_SOR_DP_TRAIN_OP_PATTERN:
ret = priv->sor.dp_train(priv, or, link, type, mask, data, &outp);
break;
case NV94_DISP_SOR_DP_TRAIN_OP_INIT:
ret = priv->sor.dp_train_init(priv, or, link, head, type, mask, data, &outp);
break;
case NV94_DISP_SOR_DP_TRAIN_OP_FINI:
ret = priv->sor.dp_train_fini(priv, or, link, head, type, mask, data, &outp);
break;
default:
break;
}
break;
case NV94_DISP_SOR_DP_LNKCTL:
ret = priv->sor.dp_lnkctl(priv, or, link, head, type, mask, data, &outp);
......
......@@ -42,6 +42,64 @@ nv94_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane)
return nv94[lane];
}
int
nv94_sor_dp_train_init(struct nv50_disp_priv *priv, int or, int link, int head,
u16 type, u16 mask, u32 data, struct dcb_output *dcbo)
{
struct nouveau_bios *bios = nouveau_bios(priv);
struct nvbios_dpout info;
u8 ver, hdr, cnt, len;
u16 outp;
outp = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &info);
if (outp) {
struct nvbios_init init = {
.subdev = nv_subdev(priv),
.bios = bios,
.outp = dcbo,
.crtc = head,
.execute = 1,
};
if (data & NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_ON)
init.offset = info.script[2];
else
init.offset = info.script[3];
nvbios_exec(&init);
init.offset = info.script[0];
nvbios_exec(&init);
}
return 0;
}
int
nv94_sor_dp_train_fini(struct nv50_disp_priv *priv, int or, int link, int head,
u16 type, u16 mask, u32 data, struct dcb_output *dcbo)
{
struct nouveau_bios *bios = nouveau_bios(priv);
struct nvbios_dpout info;
u8 ver, hdr, cnt, len;
u16 outp;
outp = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &info);
if (outp) {
struct nvbios_init init = {
.subdev = nv_subdev(priv),
.bios = bios,
.offset = info.script[1],
.outp = dcbo,
.crtc = head,
.execute = 1,
};
nvbios_exec(&init);
}
return 0;
}
int
nv94_sor_dp_train(struct nv50_disp_priv *priv, int or, int link,
u16 type, u16 mask, u32 data, struct dcb_output *info)
......
......@@ -191,6 +191,13 @@ struct nve0_channel_ind_class {
#define NV50_DISP_SOR_LVDS_SCRIPT 0x00013000
#define NV50_DISP_SOR_LVDS_SCRIPT_ID 0x0000ffff
#define NV94_DISP_SOR_DP_TRAIN 0x00016000
#define NV94_DISP_SOR_DP_TRAIN_OP 0xf0000000
#define NV94_DISP_SOR_DP_TRAIN_OP_PATTERN 0x00000000
#define NV94_DISP_SOR_DP_TRAIN_OP_INIT 0x10000000
#define NV94_DISP_SOR_DP_TRAIN_OP_FINI 0x20000000
#define NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD 0x00000001
#define NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_OFF 0x00000000
#define NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_ON 0x00000001
#define NV94_DISP_SOR_DP_TRAIN_PATTERN 0x00000003
#define NV94_DISP_SOR_DP_TRAIN_PATTERN_DISABLED 0x00000000
#define NV94_DISP_SOR_DP_LNKCTL 0x00016040
......
......@@ -624,34 +624,6 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b
return 0;
}
/* BIT 'U'/'d' table encoder subtables have hashes matching them to
* a particular set of encoders.
*
* This function returns true if a particular DCB entry matches.
*/
bool
bios_encoder_match(struct dcb_output *dcb, u32 hash)
{
if ((hash & 0x000000f0) != (dcb->location << 4))
return false;
if ((hash & 0x0000000f) != dcb->type)
return false;
if (!(hash & (dcb->or << 16)))
return false;
switch (dcb->type) {
case DCB_OUTPUT_TMDS:
case DCB_OUTPUT_LVDS:
case DCB_OUTPUT_DP:
if (hash & 0x00c00000) {
if (!(hash & (dcb->sorconf.link << 22)))
return false;
}
default:
return true;
}
}
int run_tmds_table(struct drm_device *dev, struct dcb_output *dcbent, int head, int pxclk)
{
/*
......
......@@ -187,6 +187,5 @@ int run_tmds_table(struct drm_device *, struct dcb_output *,
int head, int pxclk);
int call_lvds_script(struct drm_device *, struct dcb_output *, int head,
enum LVDS_script, int pxclk);
bool bios_encoder_match(struct dcb_output *, u32 hash);
#endif
......@@ -35,51 +35,6 @@
#include <subdev/gpio.h>
#include <subdev/i2c.h>
u8 *
nouveau_dp_bios_data(struct drm_device *dev, struct dcb_output *dcb, u8 **entry)
{
struct nouveau_drm *drm = nouveau_drm(dev);
struct bit_entry d;
u8 *table;
int i;
if (bit_table(dev, 'd', &d)) {
NV_ERROR(drm, "BIT 'd' table not found\n");
return NULL;
}
if (d.version != 1) {
NV_ERROR(drm, "BIT 'd' table version %d unknown\n", d.version);
return NULL;
}
table = ROMPTR(dev, d.data[0]);
if (!table) {
NV_ERROR(drm, "displayport table pointer invalid\n");
return NULL;
}
switch (table[0]) {
case 0x20:
case 0x21:
case 0x30:
case 0x40:
break;
default:
NV_ERROR(drm, "displayport table 0x%02x unknown\n", table[0]);
return NULL;
}
for (i = 0; i < table[3]; i++) {
*entry = ROMPTR(dev, table[table[1] + (i * table[2])]);
if (*entry && bios_encoder_match(dcb, ROM32((*entry)[0])))
return table;
}
NV_ERROR(drm, "displayport encoder table not found\n");
return NULL;
}
/******************************************************************************
* link training
*****************************************************************************/
......@@ -250,54 +205,27 @@ dp_link_train_eq(struct drm_device *dev, struct dp_state *dp)
}
static void
dp_set_downspread(struct drm_device *dev, struct dp_state *dp, bool enable)
dp_link_train_init(struct drm_device *dev, struct dp_state *dp, bool spread)
{
u16 script = 0x0000;
u8 *entry, *table = nouveau_dp_bios_data(dev, dp->dcb, &entry);
if (table) {
if (table[0] >= 0x20 && table[0] <= 0x30) {
if (enable) script = ROM16(entry[12]);
else script = ROM16(entry[14]);
} else
if (table[0] == 0x40) {
if (enable) script = ROM16(entry[11]);
else script = ROM16(entry[13]);
}
}
nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc);
}
static void
dp_link_train_init(struct drm_device *dev, struct dp_state *dp)
{
u16 script = 0x0000;
u8 *entry, *table = nouveau_dp_bios_data(dev, dp->dcb, &entry);
if (table) {
if (table[0] >= 0x20 && table[0] <= 0x30)
script = ROM16(entry[6]);
else
if (table[0] == 0x40)
script = ROM16(entry[5]);
}
struct dcb_output *dcb = dp->dcb;
const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1);
const u32 moff = (dp->crtc << 3) | (link << 2) | or;
nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc);
nv_call(dp->core, NV94_DISP_SOR_DP_TRAIN + moff, (spread ?
NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_ON :
NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_OFF) |
NV94_DISP_SOR_DP_TRAIN_OP_INIT);
}
static void
dp_link_train_fini(struct drm_device *dev, struct dp_state *dp)
{
u16 script = 0x0000;
u8 *entry, *table = nouveau_dp_bios_data(dev, dp->dcb, &entry);
if (table) {
if (table[0] >= 0x20 && table[0] <= 0x30)
script = ROM16(entry[8]);
else
if (table[0] == 0x40)
script = ROM16(entry[7]);
}
struct dcb_output *dcb = dp->dcb;
const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1);
const u32 moff = (dp->crtc << 3) | (link << 2) | or;
nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc);
nv_call(dp->core, NV94_DISP_SOR_DP_TRAIN + moff,
NV94_DISP_SOR_DP_TRAIN_OP_FINI);
}
static bool
......@@ -334,11 +262,8 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate,
*/
gpio->irq(gpio, 0, nv_connector->hpd, 0xff, false);
/* enable down-spreading, if possible */
dp_set_downspread(dev, &dp, nv_encoder->dp.dpcd[3] & 1);
/* execute pre-train script from vbios */
dp_link_train_init(dev, &dp);
/* enable down-spreading and execute pre-train script from vbios */
dp_link_train_init(dev, &dp, nv_encoder->dp.dpcd[3] & 1);
/* start off at highest link rate supported by encoder and display */
while (*link_bw > nv_encoder->dp.link_bw)
......
......@@ -94,7 +94,6 @@ get_slave_funcs(struct drm_encoder *enc)
bool nouveau_dp_detect(struct drm_encoder *);
void nouveau_dp_dpms(struct drm_encoder *, int mode, u32 datarate,
struct nouveau_object *);
u8 *nouveau_dp_bios_data(struct drm_device *, struct dcb_output *, u8 **);
struct nouveau_connector *
nouveau_encoder_connector_get(struct nouveau_encoder *encoder);
......
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