Commit 52e0d0ec authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/dp: enable down-spread if vbios and sink support it

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 28e2d124
...@@ -160,25 +160,6 @@ auxch_tx(struct drm_device *dev, int ch, u8 type, u32 addr, u8 *data, u8 size) ...@@ -160,25 +160,6 @@ auxch_tx(struct drm_device *dev, int ch, u8 type, u32 addr, u8 *data, u8 size)
return ret; return ret;
} }
static int
auxch_rd(struct drm_encoder *encoder, int address, uint8_t *buf, int size)
{
struct drm_device *dev = encoder->dev;
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nouveau_i2c_chan *auxch;
int ret;
auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
if (!auxch)
return -ENODEV;
ret = nouveau_dp_auxch(auxch, 9, address, buf, size);
if (ret)
return ret;
return 0;
}
static u32 static u32
dp_link_bw_get(struct drm_device *dev, int or, int link) dp_link_bw_get(struct drm_device *dev, int or, int link)
{ {
...@@ -298,7 +279,7 @@ struct dp_state { ...@@ -298,7 +279,7 @@ struct dp_state {
int crtc; int crtc;
int or; int or;
int link; int link;
int enh_frame; u8 *dpcd;
int link_nr; int link_nr;
u32 link_bw; u32 link_bw;
u8 stat[6]; u8 stat[6];
...@@ -343,7 +324,7 @@ dp_set_link_config(struct drm_device *dev, struct dp_state *dp) ...@@ -343,7 +324,7 @@ dp_set_link_config(struct drm_device *dev, struct dp_state *dp)
/* configure lane count on the source */ /* configure lane count on the source */
dp_ctrl = ((1 << dp->link_nr) - 1) << 16; dp_ctrl = ((1 << dp->link_nr) - 1) << 16;
sink[1] = dp->link_nr; sink[1] = dp->link_nr;
if (dp->enh_frame) { if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) {
dp_ctrl |= 0x00004000; dp_ctrl |= 0x00004000;
sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
} }
...@@ -505,7 +486,6 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) ...@@ -505,7 +486,6 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate)
const u32 *link_bw = bw_list; const u32 *link_bw = bw_list;
struct dp_state dp; struct dp_state dp;
u8 *bios, headerlen; u8 *bios, headerlen;
u16 script;
auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
if (!auxch) if (!auxch)
...@@ -520,7 +500,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) ...@@ -520,7 +500,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate)
dp.auxch = auxch->rd; dp.auxch = auxch->rd;
dp.or = nv_encoder->or; dp.or = nv_encoder->or;
dp.link = !(nv_encoder->dcb->sorconf.link & 1); dp.link = !(nv_encoder->dcb->sorconf.link & 1);
dp.enh_frame = nv_encoder->dp.enhanced_frame; dp.dpcd = nv_encoder->dp.dpcd;
/* some sinks toggle hotplug in response to some of the actions /* some sinks toggle hotplug in response to some of the actions
* we take during link training (DP_SET_POWER is one), we need * we take during link training (DP_SET_POWER is one), we need
...@@ -528,6 +508,15 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) ...@@ -528,6 +508,15 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate)
*/ */
pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false);
/* enable down-spreading, if possible */
if (headerlen >= 16) {
u16 script = ROM16(bios[14]);
if (nv_encoder->dp.dpcd[3] & 1)
script = ROM16(bios[12]);
nouveau_bios_run_init_table(dev, script, dp.dcb, dp.crtc);
}
/* execute pre-train script from vbios */ /* execute pre-train script from vbios */
nouveau_bios_run_init_table(dev, ROM16(bios[6]), dp.dcb, dp.crtc); nouveau_bios_run_init_table(dev, ROM16(bios[6]), dp.dcb, dp.crtc);
...@@ -575,17 +564,20 @@ nouveau_dp_detect(struct drm_encoder *encoder) ...@@ -575,17 +564,20 @@ nouveau_dp_detect(struct drm_encoder *encoder)
{ {
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
uint8_t dpcd[4]; struct nouveau_i2c_chan *auxch;
u8 *dpcd = nv_encoder->dp.dpcd;
int ret; int ret;
ret = auxch_rd(encoder, 0x0000, dpcd, 4); auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
if (!auxch)
return false;
ret = auxch_tx(dev, auxch->rd, 9, DP_DPCD_REV, dpcd, 8);
if (ret) if (ret)
return false; return false;
nv_encoder->dp.dpcd_version = dpcd[0];
nv_encoder->dp.link_bw = 27000 * dpcd[1]; nv_encoder->dp.link_bw = 27000 * dpcd[1];
nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK;
nv_encoder->dp.enhanced_frame = dpcd[2] & DP_ENHANCED_FRAME_CAP;
NV_DEBUG_KMS(dev, "display: %dx%d dpcd 0x%02x\n", NV_DEBUG_KMS(dev, "display: %dx%d dpcd 0x%02x\n",
nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]); nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]);
......
...@@ -49,10 +49,9 @@ struct nouveau_encoder { ...@@ -49,10 +49,9 @@ struct nouveau_encoder {
union { union {
struct { struct {
int dpcd_version; u8 dpcd[8];
int link_nr; int link_nr;
int link_bw; int link_bw;
bool enhanced_frame;
u32 datarate; u32 datarate;
} dp; } dp;
}; };
......
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