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

Commit 61f11699 authored by Keith Packard's avatar Keith Packard Committed by Dave Airlie
Browse files

drm: Eliminate magic I2C frobbing when reading EDID



This code depends on the underlying I2C adapter using the bit-banging algo,
which may not be the case. If specific encoders require this mechanism, they
should build a custom I2C algo that implements this workaround, rather than
having it in the general path.

Signed-off-by: default avatarKeith Packard <keithp@keithp.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 7ff14559
Loading
Loading
Loading
Loading
+1 −73
Original line number Diff line number Diff line
@@ -584,85 +584,13 @@ int drm_do_probe_ddc_edid(struct i2c_adapter *adapter,
}
EXPORT_SYMBOL(drm_do_probe_ddc_edid);

/**
 * Get EDID information.
 *
 * \param adapter : i2c device adaptor.
 * \param buf     : EDID data buffer to be filled
 * \param len     : EDID data buffer length
 * \return 0 on success or -1 on failure.
 *
 * Initialize DDC, then fetch EDID information
 * by calling drm_do_probe_ddc_edid function.
 */
static int drm_ddc_read(struct i2c_adapter *adapter,
			unsigned char *buf, int len)
{
	struct i2c_algo_bit_data *algo_data = adapter->algo_data;
	int i, j;
	int ret = -1;

	algo_data->setscl(algo_data->data, 1);

	for (i = 0; i < 1; i++) {
		/* For some old monitors we need the
		 * following process to initialize/stop DDC
		 */
		algo_data->setsda(algo_data->data, 1);
		msleep(13);

		algo_data->setscl(algo_data->data, 1);
		for (j = 0; j < 5; j++) {
			msleep(10);
			if (algo_data->getscl(algo_data->data))
				break;
		}
		if (j == 5)
			continue;

		algo_data->setsda(algo_data->data, 0);
		msleep(15);
		algo_data->setscl(algo_data->data, 0);
		msleep(15);
		algo_data->setsda(algo_data->data, 1);
		msleep(15);

		/* Do the real work */
		ret = drm_do_probe_ddc_edid(adapter, buf, len);
		algo_data->setsda(algo_data->data, 0);
		algo_data->setscl(algo_data->data, 0);
		msleep(15);

		algo_data->setscl(algo_data->data, 1);
		for (j = 0; j < 10; j++) {
			msleep(10);
			if (algo_data->getscl(algo_data->data))
				break;
		}

		algo_data->setsda(algo_data->data, 1);
		msleep(15);
		algo_data->setscl(algo_data->data, 0);
		algo_data->setsda(algo_data->data, 0);
		if (ret == 0)
			break;
	}
	/* Release the DDC lines when done or the Apple Cinema HD display
	 * will switch off
	 */
	algo_data->setsda(algo_data->data, 1);
	algo_data->setscl(algo_data->data, 1);

	return ret;
}

static int drm_ddc_read_edid(struct drm_connector *connector,
			     struct i2c_adapter *adapter,
			     char *buf, int len)
{
	int ret;

	ret = drm_ddc_read(adapter, buf, len);
	ret = drm_do_probe_ddc_edid(adapter, buf, len);
	if (ret != 0) {
		dev_info(&connector->dev->pdev->dev, "%s: no EDID data\n",
			 drm_get_connector_name(connector));