Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8777c5c1 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/dp: probe dpcd to determine connectedness



Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent efa366fd
Loading
Loading
Loading
Loading
+19 −29
Original line number Diff line number Diff line
@@ -111,15 +111,15 @@ nouveau_connector_destroy(struct drm_connector *connector)
	kfree(connector);
}

static struct nouveau_i2c_port *
nouveau_connector_ddc_detect(struct drm_connector *connector,
			     struct nouveau_encoder **pnv_encoder)
static struct nouveau_encoder *
nouveau_connector_ddc_detect(struct drm_connector *connector)
{
	struct drm_device *dev = connector->dev;
	struct nouveau_connector *nv_connector = nouveau_connector(connector);
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
	struct nouveau_i2c_port *port = NULL;
	struct nouveau_encoder *nv_encoder;
	struct drm_mode_object *obj;
	int i, panel = -ENODEV;

	/* eDP panels need powering on by us (if the VBIOS doesn't default it
@@ -134,13 +134,9 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,
		}
	}

	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
		struct nouveau_encoder *nv_encoder;
		struct drm_mode_object *obj;
		int id;

		id = connector->encoder_ids[i];
		if (!id)
	for (i = 0; nv_encoder = NULL, i < DRM_CONNECTOR_MAX_ENCODER; i++) {
		int id = connector->encoder_ids[i];
		if (id == 0)
			break;

		obj = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER);
@@ -148,22 +144,24 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,
			continue;
		nv_encoder = nouveau_encoder(obj_to_encoder(obj));

		port = nv_encoder->i2c;
		if (port && nv_probe_i2c(port, 0x50)) {
			*pnv_encoder = nv_encoder;
		if (nv_encoder->dcb->type == DCB_OUTPUT_DP) {
			int ret = nouveau_dp_detect(nv_encoder);
			if (ret == 0)
				break;
		} else
		if (nv_encoder->i2c) {
			if (nv_probe_i2c(nv_encoder->i2c, 0x50))
				break;
		}

		port = NULL;
	}

	/* eDP panel not detected, restore panel power GPIO to previous
	 * state to avoid confusing the SOR for other output types.
	 */
	if (!port && panel == 0)
	if (!nv_encoder && panel == 0)
		gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, panel);

	return port;
	return nv_encoder;
}

static struct nouveau_encoder *
@@ -262,8 +260,8 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
	if (ret < 0 && ret != -EACCES)
		return conn_status;

	i2c = nouveau_connector_ddc_detect(connector, &nv_encoder);
	if (i2c) {
	nv_encoder = nouveau_connector_ddc_detect(connector);
	if (nv_encoder && (i2c = nv_encoder->i2c) != NULL) {
		nv_connector->edid = drm_get_edid(connector, &i2c->adapter);
		drm_mode_connector_update_edid_property(connector,
							nv_connector->edid);
@@ -273,14 +271,6 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
			goto detect_analog;
		}

		if (nv_encoder->dcb->type == DCB_OUTPUT_DP &&
		    !nouveau_dp_detect(to_drm_encoder(nv_encoder))) {
			NV_ERROR(drm, "Detected %s, but failed init\n",
				 connector->name);
			conn_status = connector_status_disconnected;
			goto out;
		}

		/* Override encoder type for DVI-I based on whether EDID
		 * says the display is digital or analog, both use the
		 * same i2c channel so the value returned from ddc_detect
+6 −8
Original line number Diff line number Diff line
@@ -55,11 +55,10 @@ nouveau_dp_probe_oui(struct drm_device *dev, struct nouveau_i2c_port *auxch,

}

bool
nouveau_dp_detect(struct drm_encoder *encoder)
int
nouveau_dp_detect(struct nouveau_encoder *nv_encoder)
{
	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
	struct drm_device *dev = encoder->dev;
	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;
@@ -67,11 +66,11 @@ nouveau_dp_detect(struct drm_encoder *encoder)

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

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

	nv_encoder->dp.link_bw = 27000 * dpcd[1];
	nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK;
@@ -91,6 +90,5 @@ nouveau_dp_detect(struct drm_encoder *encoder)
		     nv_encoder->dp.link_nr, nv_encoder->dp.link_bw);

	nouveau_dp_probe_oui(dev, auxch, dpcd);

	return true;
	return 0;
}
+1 −3
Original line number Diff line number Diff line
@@ -85,9 +85,7 @@ get_slave_funcs(struct drm_encoder *enc)
}

/* nouveau_dp.c */
bool nouveau_dp_detect(struct drm_encoder *);
void nouveau_dp_dpms(struct drm_encoder *, int mode, u32 datarate,
		     struct nouveau_object *);
int nouveau_dp_detect(struct nouveau_encoder *);

struct nouveau_connector *
nouveau_encoder_connector_get(struct nouveau_encoder *encoder);