Commit 7c936157 authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Sam Ravnborg

drm: bridge: adv7511: Implement bridge connector operations

Implement the bridge connector-related .get_edid(), .detect() and
.hpd_notify() operations, and report the related bridge capabilities.

Output status detection is implemented using the same backend as for the
DRM connector, but requires making mode retrieval at detection time
optional as no pointer to the connector is available to the bridge
.detect() operation. The reason for the need to retrieve modes at
detection time is unclear to me, and this may benefit from further
refactoring of hot plug handling code.

Hot plug detection is notified through the bridge HPD notification
framework when the bridge is used without creating a connector, and
falls back to the existing implementation otherwise. CEC handling of
disconnection is handled in the new .hpd_notify() operation in the new
code path.
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Acked-by: default avatarSam Ravnborg <sam@ravnborg.org>
Signed-off-by: default avatarSam Ravnborg <sam@ravnborg.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-4-laurent.pinchart+renesas@ideasonboard.com
parent c6533015
......@@ -443,9 +443,14 @@ static void adv7511_hpd_work(struct work_struct *work)
if (adv7511->connector.status != status) {
adv7511->connector.status = status;
if (status == connector_status_disconnected)
cec_phys_addr_invalidate(adv7511->cec_adap);
drm_kms_helper_hotplug_event(adv7511->connector.dev);
if (adv7511->connector.dev) {
if (status == connector_status_disconnected)
cec_phys_addr_invalidate(adv7511->cec_adap);
drm_kms_helper_hotplug_event(adv7511->connector.dev);
} else {
drm_bridge_hpd_notify(&adv7511->bridge, status);
}
}
}
......@@ -661,7 +666,8 @@ adv7511_detect(struct adv7511 *adv7511, struct drm_connector *connector)
if (status == connector_status_connected && hpd && adv7511->powered) {
regcache_mark_dirty(adv7511->regmap);
adv7511_power_on(adv7511);
adv7511_get_modes(adv7511, connector);
if (connector)
adv7511_get_modes(adv7511, connector);
if (adv7511->status == connector_status_connected)
status = connector_status_disconnected;
} else {
......@@ -917,11 +923,38 @@ static int adv7511_bridge_attach(struct drm_bridge *bridge,
return ret;
}
static enum drm_connector_status adv7511_bridge_detect(struct drm_bridge *bridge)
{
struct adv7511 *adv = bridge_to_adv7511(bridge);
return adv7511_detect(adv, NULL);
}
static struct edid *adv7511_bridge_get_edid(struct drm_bridge *bridge,
struct drm_connector *connector)
{
struct adv7511 *adv = bridge_to_adv7511(bridge);
return adv7511_get_edid(adv, connector);
}
static void adv7511_bridge_hpd_notify(struct drm_bridge *bridge,
enum drm_connector_status status)
{
struct adv7511 *adv = bridge_to_adv7511(bridge);
if (status == connector_status_disconnected)
cec_phys_addr_invalidate(adv->cec_adap);
}
static const struct drm_bridge_funcs adv7511_bridge_funcs = {
.enable = adv7511_bridge_enable,
.disable = adv7511_bridge_disable,
.mode_set = adv7511_bridge_mode_set,
.attach = adv7511_bridge_attach,
.detect = adv7511_bridge_detect,
.get_edid = adv7511_bridge_get_edid,
.hpd_notify = adv7511_bridge_hpd_notify,
};
/* -----------------------------------------------------------------------------
......@@ -1250,6 +1283,8 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
goto err_unregister_cec;
adv7511->bridge.funcs = &adv7511_bridge_funcs;
adv7511->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID
| DRM_BRIDGE_OP_HPD;
adv7511->bridge.of_node = dev->of_node;
drm_bridge_add(&adv7511->bridge);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment