drm/nouveau/dp: remove last bits of VBIOS parsing from DRM code
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
6c8e4633d3
commit
8f2abc2586
12 changed files with 111 additions and 121 deletions
|
@ -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]);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
Loading…
Reference in a new issue