Commit c0895f80 authored by Maxime Ripard's avatar Maxime Ripard

drm/vc4: hdmi: Simplify the hotplug handling

Our detect callback has a bunch of operations to perform depending on
the current and last status of the connector, such a setting the CEC
physical address or enabling the scrambling again.

This is currently dealt with a bunch of if / else statetements that make
it fairly difficult to read and extend.

Let's move all that logic to a function of its own.
Reviewed-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
Link: https://lore.kernel.org/r/20220829134731.213478-5-maxime@cerno.tech
parent da94e9c6
......@@ -273,17 +273,50 @@ static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) {}
static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder);
static void vc4_hdmi_handle_hotplug(struct vc4_hdmi *vc4_hdmi,
enum drm_connector_status status)
{
struct drm_connector *connector = &vc4_hdmi->connector;
struct edid *edid;
/*
* NOTE: This function should really be called with
* vc4_hdmi->mutex held, but doing so results in reentrancy
* issues since cec_s_phys_addr_from_edid might call
* .adap_enable, which leads to that funtion being called with
* our mutex held.
*
* Concurrency isn't an issue at the moment since we don't share
* any state with any of the other frameworks so we can ignore
* the lock for now.
*/
if (status == connector_status_disconnected) {
cec_phys_addr_invalidate(vc4_hdmi->cec_adap);
return;
}
edid = drm_get_edid(connector, vc4_hdmi->ddc);
if (!edid)
return;
cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid);
kfree(edid);
vc4_hdmi_enable_scrambling(&vc4_hdmi->encoder.base.base);
}
static enum drm_connector_status
vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
{
struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
bool connected = false;
enum drm_connector_status status = connector_status_disconnected;
/*
* NOTE: This function should really take vc4_hdmi->mutex, but
* doing so results in reentrancy issues since
* cec_s_phys_addr_from_edid might call .adap_enable, which
* leads to that funtion being called with our mutex held.
* vc4_hdmi_handle_hotplug() can call into other functions that
* would take the mutex while it's held here.
*
* Concurrency isn't an issue at the moment since we don't share
* any state with any of the other frameworks so we can ignore
......@@ -294,31 +327,17 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
if (vc4_hdmi->hpd_gpio) {
if (gpiod_get_value_cansleep(vc4_hdmi->hpd_gpio))
connected = true;
status = connector_status_connected;
} else {
if (vc4_hdmi->variant->hp_detect &&
vc4_hdmi->variant->hp_detect(vc4_hdmi))
connected = true;
status = connector_status_connected;
}
if (connected) {
if (connector->status != connector_status_connected) {
struct edid *edid = drm_get_edid(connector, vc4_hdmi->ddc);
if (edid) {
cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid);
kfree(edid);
}
}
vc4_hdmi_enable_scrambling(&vc4_hdmi->encoder.base);
vc4_hdmi_handle_hotplug(vc4_hdmi, status);
pm_runtime_put(&vc4_hdmi->pdev->dev);
return connector_status_connected;
}
cec_phys_addr_invalidate(vc4_hdmi->cec_adap);
pm_runtime_put(&vc4_hdmi->pdev->dev);
return connector_status_disconnected;
return status;
}
static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
......
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