From 254d6dfe7d33606ea67eb3ed11d2c1f570c980b6 Mon Sep 17 00:00:00 2001 From: jsg Date: Thu, 4 Apr 2024 07:35:50 +0000 Subject: [PATCH] drm/bridge: add ->edid_read hook and drm_bridge_edid_read() From Jani Nikula 2b6aaf7b193be2bfa4e1af90c0d96e78a80aef69 in linux-6.6.y/6.6.24 d807ad80d811ba0c22adfd871e2a46491f80d6e2 in mainline linux --- sys/dev/pci/drm/drm_bridge.c | 46 +++++++++++++++++++++++- sys/dev/pci/drm/include/drm/drm_bridge.h | 33 +++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/sys/dev/pci/drm/drm_bridge.c b/sys/dev/pci/drm/drm_bridge.c index 0ad7e775a1e..ce490620986 100644 --- a/sys/dev/pci/drm/drm_bridge.c +++ b/sys/dev/pci/drm/drm_bridge.c @@ -27,8 +27,9 @@ #include #include -#include #include +#include +#include #include #include #include @@ -1213,6 +1214,47 @@ int drm_bridge_get_modes(struct drm_bridge *bridge, } EXPORT_SYMBOL_GPL(drm_bridge_get_modes); +/** + * drm_bridge_edid_read - read the EDID data of the connected display + * @bridge: bridge control structure + * @connector: the connector to read EDID for + * + * If the bridge supports output EDID retrieval, as reported by the + * DRM_BRIDGE_OP_EDID bridge ops flag, call &drm_bridge_funcs.edid_read to get + * the EDID and return it. Otherwise return NULL. + * + * If &drm_bridge_funcs.edid_read is not set, fall back to using + * drm_bridge_get_edid() and wrapping it in struct drm_edid. + * + * RETURNS: + * The retrieved EDID on success, or NULL otherwise. + */ +const struct drm_edid *drm_bridge_edid_read(struct drm_bridge *bridge, + struct drm_connector *connector) +{ + if (!(bridge->ops & DRM_BRIDGE_OP_EDID)) + return NULL; + + /* Transitional: Fall back to ->get_edid. */ + if (!bridge->funcs->edid_read) { + const struct drm_edid *drm_edid; + struct edid *edid; + + edid = drm_bridge_get_edid(bridge, connector); + if (!edid) + return NULL; + + drm_edid = drm_edid_alloc(edid, (edid->extensions + 1) * EDID_LENGTH); + + kfree(edid); + + return drm_edid; + } + + return bridge->funcs->edid_read(bridge, connector); +} +EXPORT_SYMBOL_GPL(drm_bridge_edid_read); + /** * drm_bridge_get_edid - get the EDID data of the connected display * @bridge: bridge control structure @@ -1222,6 +1264,8 @@ EXPORT_SYMBOL_GPL(drm_bridge_get_modes); * DRM_BRIDGE_OP_EDID bridge ops flag, call &drm_bridge_funcs.get_edid to * get the EDID and return it. Otherwise return NULL. * + * Deprecated. Prefer using drm_bridge_edid_read(). + * * RETURNS: * The retrieved EDID on success, or NULL otherwise. */ diff --git a/sys/dev/pci/drm/include/drm/drm_bridge.h b/sys/dev/pci/drm/include/drm/drm_bridge.h index 1482d6d8084..a696bb9f78a 100644 --- a/sys/dev/pci/drm/include/drm/drm_bridge.h +++ b/sys/dev/pci/drm/include/drm/drm_bridge.h @@ -555,6 +555,37 @@ struct drm_bridge_funcs { int (*get_modes)(struct drm_bridge *bridge, struct drm_connector *connector); + /** + * @edid_read: + * + * Read the EDID data of the connected display. + * + * The @edid_read callback is the preferred way of reporting mode + * information for a display connected to the bridge output. Bridges + * that support reading EDID shall implement this callback and leave + * the @get_modes callback unimplemented. + * + * The caller of this operation shall first verify the output + * connection status and refrain from reading EDID from a disconnected + * output. + * + * This callback is optional. Bridges that implement it shall set the + * DRM_BRIDGE_OP_EDID flag in their &drm_bridge->ops. + * + * The connector parameter shall be used for the sole purpose of EDID + * retrieval, and shall not be stored internally by bridge drivers for + * future usage. + * + * RETURNS: + * + * An edid structure newly allocated with drm_edid_alloc() or returned + * from drm_edid_read() family of functions on success, or NULL + * otherwise. The caller is responsible for freeing the returned edid + * structure with drm_edid_free(). + */ + const struct drm_edid *(*edid_read)(struct drm_bridge *bridge, + struct drm_connector *connector); + /** * @get_edid: * @@ -888,6 +919,8 @@ drm_atomic_helper_bridge_propagate_bus_fmt(struct drm_bridge *bridge, enum drm_connector_status drm_bridge_detect(struct drm_bridge *bridge); int drm_bridge_get_modes(struct drm_bridge *bridge, struct drm_connector *connector); +const struct drm_edid *drm_bridge_edid_read(struct drm_bridge *bridge, + struct drm_connector *connector); struct edid *drm_bridge_get_edid(struct drm_bridge *bridge, struct drm_connector *connector); void drm_bridge_hpd_enable(struct drm_bridge *bridge, -- 2.20.1