[PATCH/RFC 4/5] drm/edid: Honour connector->force in drm_do_get_edid()
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Wed Aug 21 18:50:04 UTC 2019
The drm_get_edid() function skips EDID read when the connector is
disabled through connector->force. drm_do_get_edid(), which is supposed
to be used instead of drm_get_edid() for drivers that need to provide a
custom DDC read method, is missing the connector force checks. This
breaks the connector sysfs or command line force attribute.
Fix this by moving the the connector checks to drm_do_get_edid(). For
convenience, the existing drm_do_get_edid() function is renamed to
__drm_do_get_edid() and used in drm_do_get_edid().
While at it, remove the incorrect statement from the drm_get_edid()
documentation related to attaching the read EDID to the connector.
Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
---
drivers/gpu/drm/drm_edid.c | 80 +++++++++++++++++++++++---------------
1 file changed, 48 insertions(+), 32 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 541e50b858e3..4b28635f1050 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -5191,27 +5191,17 @@ int drm_add_override_edid_modes(struct drm_connector *connector)
}
EXPORT_SYMBOL(drm_add_override_edid_modes);
-/**
- * drm_do_get_edid - get EDID data using a custom EDID block read function
- * @connector: connector we're probing
- * @get_edid_block: EDID block read function
- * @data: private data passed to the block read function
- *
- * When the I2C adapter connected to the DDC bus is hidden behind a device that
- * exposes a different interface to read EDID blocks this function can be used
- * to get EDID data using a custom block read function.
- *
- * As in the general case the DDC bus is accessible by the kernel at the I2C
- * level, drivers must make all reasonable efforts to expose it as an I2C
- * adapter and use drm_get_edid() instead of abusing this function.
- *
- * The EDID may be overridden using debugfs override_edid or firmware EDID
- * (drm_load_edid_firmware() and drm.edid_firmware parameter), in this priority
- * order. Having either of them bypasses actual EDID reads.
- *
- * Return: Pointer to valid EDID or NULL if we couldn't find any.
- */
-struct edid *drm_do_get_edid(struct drm_connector *connector,
+static bool __drm_probe_ddc(int (*get_edid_block)(void *data, u8 *buf,
+ unsigned int block,
+ size_t len),
+ void *data)
+{
+ unsigned char out;
+
+ return (get_edid_block(data, &out, 0, 1) == 0);
+}
+
+static struct edid *__drm_do_get_edid(struct drm_connector *connector,
int (*get_edid_block)(void *data, u8 *buf, unsigned int block,
size_t len),
void *data)
@@ -5302,6 +5292,41 @@ struct edid *drm_do_get_edid(struct drm_connector *connector,
kfree(edid);
return NULL;
}
+
+/**
+ * drm_do_get_edid - get EDID data using a custom EDID block read function
+ * @connector: connector we're probing
+ * @get_edid_block: EDID block read function
+ * @data: private data passed to the block read function
+ *
+ * When the I2C adapter connected to the DDC bus is hidden behind a device that
+ * exposes a different interface to read EDID blocks this function can be used
+ * to get EDID data using a custom block read function.
+ *
+ * As in the general case the DDC bus is accessible by the kernel at the I2C
+ * level, drivers must make all reasonable efforts to expose it as an I2C
+ * adapter and use drm_get_edid() instead of abusing this function.
+ *
+ * The EDID may be overridden using debugfs override_edid or firmware EDID
+ * (drm_load_edid_firmware() and drm.edid_firmware parameter), in this priority
+ * order. Having either of them bypasses actual EDID reads.
+ *
+ * Return: Pointer to valid EDID or NULL if we couldn't find any.
+ */
+struct edid *drm_do_get_edid(struct drm_connector *connector,
+ int (*get_edid_block)(void *data, u8 *buf, unsigned int block,
+ size_t len),
+ void *data)
+{
+ if (connector->force == DRM_FORCE_OFF)
+ return NULL;
+
+ if (connector->force == DRM_FORCE_UNSPECIFIED &&
+ !__drm_probe_ddc(get_edid_block, data))
+ return NULL;
+
+ return __drm_do_get_edid(connector, get_edid_block, data);
+}
EXPORT_SYMBOL_GPL(drm_do_get_edid);
/**
@@ -5313,9 +5338,7 @@ EXPORT_SYMBOL_GPL(drm_do_get_edid);
bool
drm_probe_ddc(struct i2c_adapter *adapter)
{
- unsigned char out;
-
- return (drm_do_probe_ddc_edid(adapter, &out, 0, 1) == 0);
+ return __drm_probe_ddc(drm_do_probe_ddc_edid, adapter);
}
EXPORT_SYMBOL(drm_probe_ddc);
@@ -5324,20 +5347,13 @@ EXPORT_SYMBOL(drm_probe_ddc);
* @connector: connector we're probing
* @adapter: I2C adapter to use for DDC
*
- * Poke the given I2C channel to grab EDID data if possible. If found,
- * attach it to the connector.
+ * Poke the given I2C channel to grab EDID data if possible.
*
* Return: Pointer to valid EDID or NULL if we couldn't find any.
*/
struct edid *drm_get_edid(struct drm_connector *connector,
struct i2c_adapter *adapter)
{
- if (connector->force == DRM_FORCE_OFF)
- return NULL;
-
- if (connector->force == DRM_FORCE_UNSPECIFIED && !drm_probe_ddc(adapter))
- return NULL;
-
return drm_do_get_edid(connector, drm_do_probe_ddc_edid, adapter);
}
EXPORT_SYMBOL(drm_get_edid);
--
Regards,
Laurent Pinchart
More information about the dri-devel
mailing list