Пример #1
0
int
nvkm_output_dp_train(struct nvkm_output *base, u32 datarate, bool wait)
{
	struct nvkm_output_dp *outp = (void *)base;
	bool retrain = true;
	u8 link[2], stat[3];
	u32 linkrate;
	int ret, i;

	/* check that the link is trained at a high enough rate */
	ret = nv_rdaux(outp->base.edid, DPCD_LC00_LINK_BW_SET, link, 2);
	if (ret) {
		DBG("failed to read link config, assuming no sink\n");
		goto done;
	}

	linkrate = link[0] * 27000 * (link[1] & DPCD_LC01_LANE_COUNT_SET);
	linkrate = (linkrate * 8) / 10; /* 8B/10B coding overhead */
	datarate = (datarate + 9) / 10; /* -> decakilobits */
	if (linkrate < datarate) {
		DBG("link not trained at sufficient rate\n");
		goto done;
	}

	/* check that link is still trained */
	ret = nv_rdaux(outp->base.edid, DPCD_LS02, stat, 3);
	if (ret) {
		DBG("failed to read link status, assuming no sink\n");
		goto done;
	}

	if (stat[2] & DPCD_LS04_INTERLANE_ALIGN_DONE) {
		for (i = 0; i < (link[1] & DPCD_LC01_LANE_COUNT_SET); i++) {
			u8 lane = (stat[i >> 1] >> ((i & 1) * 4)) & 0x0f;
			if (!(lane & DPCD_LS02_LANE0_CR_DONE) ||
			    !(lane & DPCD_LS02_LANE0_CHANNEL_EQ_DONE) ||
			    !(lane & DPCD_LS02_LANE0_SYMBOL_LOCKED)) {
				DBG("lane %d not equalised\n", lane);
				goto done;
			}
		}
		retrain = false;
	} else {
Пример #2
0
static void
nouveau_dp_probe_oui(struct drm_device *dev, struct nouveau_i2c_port *auxch,
		     u8 *dpcd)
{
	struct nouveau_drm *drm = nouveau_drm(dev);
	u8 buf[3];

	if (!(dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT))
		return;

	if (!nv_rdaux(auxch, DP_SINK_OUI, buf, 3))
		NV_DEBUG(drm, "Sink OUI: %02hx%02hx%02hx\n",
			     buf[0], buf[1], buf[2]);

	if (!nv_rdaux(auxch, DP_BRANCH_OUI, buf, 3))
		NV_DEBUG(drm, "Branch OUI: %02hx%02hx%02hx\n",
			     buf[0], buf[1], buf[2]);

}
Пример #3
0
static int
init_rdauxr(struct nvbios_init *init, u32 addr)
{
	struct nouveau_i2c_port *port = init_i2c(init, -2);
	u8 data;

	if (port && init_exec(init)) {
		int ret = nv_rdaux(port, addr, &data, 1);
		if (ret)
			return ret;
		return data;
	}

	return -ENODEV;
}
Пример #4
0
int
nouveau_dp_detect(struct nouveau_encoder *nv_encoder)
{
	struct drm_device *dev = nv_encoder->base.base.dev;
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nouveau_i2c_port *auxch;
	u8 *dpcd = nv_encoder->dp.dpcd;
	int ret;

	auxch = nv_encoder->i2c;
	if (!auxch)
		return -ENODEV;

	ret = nv_rdaux(auxch, DP_DPCD_REV, dpcd, 8);
	if (ret)
		return ret;

	nv_encoder->dp.link_bw = 27000 * dpcd[1];
	nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK;

	NV_DEBUG(drm, "display: %dx%d dpcd 0x%02x\n",
		     nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]);
	NV_DEBUG(drm, "encoder: %dx%d\n",
		     nv_encoder->dcb->dpconf.link_nr,
		     nv_encoder->dcb->dpconf.link_bw);

	if (nv_encoder->dcb->dpconf.link_nr < nv_encoder->dp.link_nr)
		nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr;
	if (nv_encoder->dcb->dpconf.link_bw < nv_encoder->dp.link_bw)
		nv_encoder->dp.link_bw = nv_encoder->dcb->dpconf.link_bw;

	NV_DEBUG(drm, "maximum: %dx%d\n",
		     nv_encoder->dp.link_nr, nv_encoder->dp.link_bw);

	nouveau_dp_probe_oui(dev, auxch, dpcd);
	return 0;
}