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

Commit 72a5c970 authored by Alex Deucher's avatar Alex Deucher
Browse files

drm/radeon: restructure edid fetching



Split radeon_ddc_get_modes() and move it into
radeon_connectors.c since that is the only place
that uses it.

Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 88fd4789
Loading
Loading
Loading
Loading
+110 −52
Original line number Diff line number Diff line
@@ -262,6 +262,79 @@ static struct drm_encoder *radeon_find_encoder(struct drm_connector *connector,
	return NULL;
}

static void radeon_connector_get_edid(struct drm_connector *connector)
{
	struct drm_device *dev = connector->dev;
	struct radeon_device *rdev = dev->dev_private;
	struct radeon_connector *radeon_connector = to_radeon_connector(connector);

	if (radeon_connector->edid)
		return;

	/* on hw with routers, select right port */
	if (radeon_connector->router.ddc_valid)
		radeon_router_select_ddc_port(radeon_connector);

	if ((radeon_connector_encoder_get_dp_bridge_encoder_id(connector) !=
	     ENCODER_OBJECT_ID_NONE) &&
	    radeon_connector->ddc_bus->has_aux) {
		radeon_connector->edid = drm_get_edid(connector,
						      &radeon_connector->ddc_bus->aux.ddc);
	} else if ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
		   (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
		struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;

		if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
		     dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) &&
		    radeon_connector->ddc_bus->has_aux)
			radeon_connector->edid = drm_get_edid(&radeon_connector->base,
							      &radeon_connector->ddc_bus->aux.ddc);
		else if (radeon_connector->ddc_bus)
			radeon_connector->edid = drm_get_edid(&radeon_connector->base,
							      &radeon_connector->ddc_bus->adapter);
	} else if (radeon_connector->ddc_bus) {
		radeon_connector->edid = drm_get_edid(&radeon_connector->base,
						      &radeon_connector->ddc_bus->adapter);
	}

	if (!radeon_connector->edid) {
		if (rdev->is_atom_bios) {
			/* some laptops provide a hardcoded edid in rom for LCDs */
			if (((connector->connector_type == DRM_MODE_CONNECTOR_LVDS) ||
			     (connector->connector_type == DRM_MODE_CONNECTOR_eDP)))
				radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev);
		} else {
			/* some servers provide a hardcoded edid in rom for KVMs */
			radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev);
		}
	}
}

static void radeon_connector_free_edid(struct drm_connector *connector)
{
	struct radeon_connector *radeon_connector = to_radeon_connector(connector);

	if (radeon_connector->edid) {
		kfree(radeon_connector->edid);
		radeon_connector->edid = NULL;
	}
}

static int radeon_ddc_get_modes(struct drm_connector *connector)
{
	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
	int ret;

	if (radeon_connector->edid) {
		drm_mode_connector_update_edid_property(connector, radeon_connector->edid);
		ret = drm_add_edid_modes(connector, radeon_connector->edid);
		drm_edid_to_eld(connector, radeon_connector->edid);
		return ret;
	}
	drm_mode_connector_update_edid_property(connector, NULL);
	return 0;
}

static struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector)
{
	int enc_id = connector->encoder_ids[0];
@@ -661,13 +734,12 @@ static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,

static int radeon_lvds_get_modes(struct drm_connector *connector)
{
	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
	struct drm_encoder *encoder;
	int ret = 0;
	struct drm_display_mode *mode;

	if (radeon_connector->ddc_bus) {
		ret = radeon_ddc_get_modes(radeon_connector);
	radeon_connector_get_edid(connector);
	ret = radeon_ddc_get_modes(connector);
	if (ret > 0) {
		encoder = radeon_best_single_encoder(connector);
		if (encoder) {
@@ -677,7 +749,6 @@ static int radeon_lvds_get_modes(struct drm_connector *connector)
		}
		return ret;
	}
	}

	encoder = radeon_best_single_encoder(connector);
	if (!encoder)
@@ -751,16 +822,9 @@ radeon_lvds_detect(struct drm_connector *connector, bool force)
	}

	/* check for edid as well */
	radeon_connector_get_edid(connector);
	if (radeon_connector->edid)
		ret = connector_status_connected;
	else {
		if (radeon_connector->ddc_bus) {
			radeon_connector->edid = drm_get_edid(&radeon_connector->base,
							      &radeon_connector->ddc_bus->adapter);
			if (radeon_connector->edid)
				ret = connector_status_connected;
		}
	}
	/* check acpi lid status ??? */

	radeon_connector_update_scratch_regs(connector, ret);
@@ -773,8 +837,7 @@ static void radeon_connector_destroy(struct drm_connector *connector)
{
	struct radeon_connector *radeon_connector = to_radeon_connector(connector);

	if (radeon_connector->edid)
		kfree(radeon_connector->edid);
	radeon_connector_free_edid(connector);
	kfree(radeon_connector->con_priv);
	drm_connector_unregister(connector);
	drm_connector_cleanup(connector);
@@ -833,10 +896,10 @@ static const struct drm_connector_funcs radeon_lvds_connector_funcs = {

static int radeon_vga_get_modes(struct drm_connector *connector)
{
	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
	int ret;

	ret = radeon_ddc_get_modes(radeon_connector);
	radeon_connector_get_edid(connector);
	ret = radeon_ddc_get_modes(connector);

	radeon_get_native_mode(connector);

@@ -881,29 +944,27 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
		dret = radeon_ddc_probe(radeon_connector, false);
	if (dret) {
		radeon_connector->detected_by_load = false;
		if (radeon_connector->edid) {
			kfree(radeon_connector->edid);
			radeon_connector->edid = NULL;
		}
		radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
		radeon_connector_free_edid(connector);
		radeon_connector_get_edid(connector);

		if (!radeon_connector->edid) {
			DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",
					connector->name);
			ret = connector_status_connected;
		} else {
			radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
			radeon_connector->use_digital =
				!!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);

			/* some oems have boards with separate digital and analog connectors
			 * with a shared ddc line (often vga + hdmi)
			 */
			if (radeon_connector->use_digital && radeon_connector->shared_ddc) {
				kfree(radeon_connector->edid);
				radeon_connector->edid = NULL;
				radeon_connector_free_edid(connector);
				ret = connector_status_disconnected;
			} else
			} else {
				ret = connector_status_connected;
			}
		}
	} else {

		/* if we aren't forcing don't do destructive polling */
@@ -1094,18 +1155,16 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
		dret = radeon_ddc_probe(radeon_connector, false);
	if (dret) {
		radeon_connector->detected_by_load = false;
		if (radeon_connector->edid) {
			kfree(radeon_connector->edid);
			radeon_connector->edid = NULL;
		}
		radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
		radeon_connector_free_edid(connector);
		radeon_connector_get_edid(connector);

		if (!radeon_connector->edid) {
			DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",
					connector->name);
			/* rs690 seems to have a problem with connectors not existing and always
			 * return a block of 0's. If we see this just stop polling on this output */
			if ((rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) && radeon_connector->base.null_edid_counter) {
			if ((rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) &&
			    radeon_connector->base.null_edid_counter) {
				ret = connector_status_disconnected;
				DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n",
					  connector->name);
@@ -1115,18 +1174,18 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
				broken_edid = true; /* defer use_digital to later */
			}
		} else {
			radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
			radeon_connector->use_digital =
				!!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);

			/* some oems have boards with separate digital and analog connectors
			 * with a shared ddc line (often vga + hdmi)
			 */
			if ((!radeon_connector->use_digital) && radeon_connector->shared_ddc) {
				kfree(radeon_connector->edid);
				radeon_connector->edid = NULL;
				radeon_connector_free_edid(connector);
				ret = connector_status_disconnected;
			} else
			} else {
				ret = connector_status_connected;

			}
			/* This gets complicated.  We have boards with VGA + HDMI with a
			 * shared DDC line and we have boards with DVI-D + HDMI with a shared
			 * DDC line.  The latter is more complex because with DVI<->HDMI adapters
@@ -1146,8 +1205,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
						if (list_connector->connector_type != DRM_MODE_CONNECTOR_VGA) {
							/* hpd is our only option in this case */
							if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) {
								kfree(radeon_connector->edid);
								radeon_connector->edid = NULL;
								radeon_connector_free_edid(connector);
								ret = connector_status_disconnected;
							}
						}
@@ -1356,7 +1414,8 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
			if (!radeon_dig_connector->edp_on)
				atombios_set_edp_panel_power(connector,
							     ATOM_TRANSMITTER_ACTION_POWER_ON);
			ret = radeon_ddc_get_modes(radeon_connector);
			radeon_connector_get_edid(connector);
			ret = radeon_ddc_get_modes(connector);
			if (!radeon_dig_connector->edp_on)
				atombios_set_edp_panel_power(connector,
							     ATOM_TRANSMITTER_ACTION_POWER_OFF);
@@ -1367,7 +1426,8 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
				if (encoder)
					radeon_atom_ext_encoder_setup_ddc(encoder);
			}
			ret = radeon_ddc_get_modes(radeon_connector);
			radeon_connector_get_edid(connector);
			ret = radeon_ddc_get_modes(connector);
		}

		if (ret > 0) {
@@ -1400,7 +1460,8 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
			if (encoder)
				radeon_atom_ext_encoder_setup_ddc(encoder);
		}
		ret = radeon_ddc_get_modes(radeon_connector);
		radeon_connector_get_edid(connector);
		ret = radeon_ddc_get_modes(connector);

		radeon_get_native_mode(connector);
	}
@@ -1493,10 +1554,7 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
		goto out;
	}

	if (radeon_connector->edid) {
		kfree(radeon_connector->edid);
		radeon_connector->edid = NULL;
	}
	radeon_connector_free_edid(connector);

	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
	    (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
+0 −58
Original line number Diff line number Diff line
@@ -823,64 +823,6 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
	return ret;
}

int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
{
	struct drm_device *dev = radeon_connector->base.dev;
	struct radeon_device *rdev = dev->dev_private;
	int ret = 0;

	/* don't leak the edid if we already fetched it in detect() */
	if (radeon_connector->edid)
		goto got_edid;

	/* on hw with routers, select right port */
	if (radeon_connector->router.ddc_valid)
		radeon_router_select_ddc_port(radeon_connector);

	if (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) !=
	    ENCODER_OBJECT_ID_NONE) {
		if (radeon_connector->ddc_bus->has_aux)
			radeon_connector->edid = drm_get_edid(&radeon_connector->base,
							      &radeon_connector->ddc_bus->aux.ddc);
	} else if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
		   (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) {
		struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;

		if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
		     dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) &&
		    radeon_connector->ddc_bus->has_aux)
			radeon_connector->edid = drm_get_edid(&radeon_connector->base,
							      &radeon_connector->ddc_bus->aux.ddc);
		else if (radeon_connector->ddc_bus && !radeon_connector->edid)
			radeon_connector->edid = drm_get_edid(&radeon_connector->base,
							      &radeon_connector->ddc_bus->adapter);
	} else {
		if (radeon_connector->ddc_bus && !radeon_connector->edid)
			radeon_connector->edid = drm_get_edid(&radeon_connector->base,
							      &radeon_connector->ddc_bus->adapter);
	}

	if (!radeon_connector->edid) {
		if (rdev->is_atom_bios) {
			/* some laptops provide a hardcoded edid in rom for LCDs */
			if (((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_LVDS) ||
			     (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)))
				radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev);
		} else
			/* some servers provide a hardcoded edid in rom for KVMs */
			radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev);
	}
	if (radeon_connector->edid) {
got_edid:
		drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid);
		ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid);
		drm_edid_to_eld(&radeon_connector->base, radeon_connector->edid);
		return ret;
	}
	drm_mode_connector_update_edid_property(&radeon_connector->base, NULL);
	return 0;
}

/* avivo */

/**
+0 −1
Original line number Diff line number Diff line
@@ -738,7 +738,6 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux);
extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);

extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);