summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorMaxime Ripard <maxime@cerno.tech>2022-08-29 16:47:27 +0300
committerMaxime Ripard <maxime@cerno.tech>2022-09-13 18:24:57 +0300
commitc0895f80272cd4100a26129f4fb91a85bf6663a1 (patch)
treee0cae975fcfcfa2feae41c354fb5898f5ea51e45 /drivers/gpu
parentda94e9c64c19a7fb2caa896628cb501a06cc3e96 (diff)
downloadlinux-c0895f80272cd4100a26129f4fb91a85bf6663a1.tar.xz
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
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.c63
1 files changed, 41 insertions, 22 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 308f7440eb6a..93df3a8e6ed9 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -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;
- }
-
- 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;
+ status = 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)