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: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220829134731.213478-5-maxime@cerno.tech
This commit is contained in:
parent
da94e9c64c
commit
c0895f8027
@ -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);
|
||||
pm_runtime_put(&vc4_hdmi->pdev->dev);
|
||||
return connector_status_connected;
|
||||
}
|
||||
|
||||
cec_phys_addr_invalidate(vc4_hdmi->cec_adap);
|
||||
vc4_hdmi_handle_hotplug(vc4_hdmi, status);
|
||||
pm_runtime_put(&vc4_hdmi->pdev->dev);
|
||||
return connector_status_disconnected;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
|
||||
|
Loading…
Reference in New Issue
Block a user