From 20ea6adbf199097c4f5f591ffee088340630dae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Mon, 16 May 2022 23:40:32 +0200 Subject: bcm27xx: add support for linux v5.15 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Build system: x86_64 Build-tested: bcm2708, bcm2709, bcm2710, bcm2711 Run-tested: bcm2708/RPiB+, bcm2709/RPi3B, bcm2710/RPi3B, bcm2711/RPi4B Signed-off-by: Marty Jones Signed-off-by: Álvaro Fernández Rojas --- ...elper-Create-a-HPD-IRQ-event-helper-for-a.patch | 201 +++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 target/linux/bcm27xx/patches-5.15/950-0020-drm-probe-helper-Create-a-HPD-IRQ-event-helper-for-a.patch (limited to 'target/linux/bcm27xx/patches-5.15/950-0020-drm-probe-helper-Create-a-HPD-IRQ-event-helper-for-a.patch') diff --git a/target/linux/bcm27xx/patches-5.15/950-0020-drm-probe-helper-Create-a-HPD-IRQ-event-helper-for-a.patch b/target/linux/bcm27xx/patches-5.15/950-0020-drm-probe-helper-Create-a-HPD-IRQ-event-helper-for-a.patch new file mode 100644 index 0000000000..4e62405b5e --- /dev/null +++ b/target/linux/bcm27xx/patches-5.15/950-0020-drm-probe-helper-Create-a-HPD-IRQ-event-helper-for-a.patch @@ -0,0 +1,201 @@ +From 22ce134cee72bd9ef4b02c8769f868309f2ab8fd Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Thu, 19 Aug 2021 14:37:04 +0200 +Subject: [PATCH] drm/probe-helper: Create a HPD IRQ event helper for a + single connector + +The drm_helper_hpd_irq_event() function is iterating over all the +connectors when an hotplug event is detected. + +During that iteration, it will call each connector detect function and +figure out if its status changed. + +Finally, if any connector changed, it will notify the user-space and the +clients that something changed on the DRM device. + +This is supposed to be used for drivers that don't have a hotplug +interrupt for individual connectors. However, drivers that can use an +interrupt for a single connector are left in the dust and can either +reimplement the logic used during the iteration for each connector or +use that helper and iterate over all connectors all the time. + +Since both are suboptimal, let's create a helper that will only perform +the status detection on a single connector. + +Signed-off-by: Maxime Ripard + +--- + +Changes from v1: + - Rename the shared function + - Move the hotplug event notification out of the shared function + - Added missing locks + - Improve the documentation + - Switched to drm_dbg_kms +--- + drivers/gpu/drm/drm_probe_helper.c | 120 ++++++++++++++++++++--------- + include/drm/drm_probe_helper.h | 1 + + 2 files changed, 86 insertions(+), 35 deletions(-) + +--- a/drivers/gpu/drm/drm_probe_helper.c ++++ b/drivers/gpu/drm/drm_probe_helper.c +@@ -795,6 +795,86 @@ void drm_kms_helper_poll_fini(struct drm + } + EXPORT_SYMBOL(drm_kms_helper_poll_fini); + ++static bool check_connector_changed(struct drm_connector *connector) ++{ ++ struct drm_device *dev = connector->dev; ++ enum drm_connector_status old_status; ++ u64 old_epoch_counter; ++ bool changed = false; ++ ++ /* Only handle HPD capable connectors. */ ++ drm_WARN_ON(dev, !(connector->polled & DRM_CONNECTOR_POLL_HPD)); ++ ++ drm_WARN_ON(dev, !mutex_is_locked(&dev->mode_config.mutex)); ++ ++ old_status = connector->status; ++ old_epoch_counter = connector->epoch_counter; ++ ++ drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Old epoch counter %llu\n", ++ connector->base.id, ++ connector->name, ++ old_epoch_counter); ++ ++ connector->status = drm_helper_probe_detect(connector, NULL, false); ++ drm_dbg_kms(dev, "[CONNECTOR:%d:%s] status updated from %s to %s\n", ++ connector->base.id, ++ connector->name, ++ drm_get_connector_status_name(old_status), ++ drm_get_connector_status_name(connector->status)); ++ ++ drm_dbg_kms(dev, "[CONNECTOR:%d:%s] New epoch counter %llu\n", ++ connector->base.id, ++ connector->name, ++ connector->epoch_counter); ++ ++ /* ++ * Check if epoch counter had changed, meaning that we need ++ * to send a uevent. ++ */ ++ if (old_epoch_counter != connector->epoch_counter) ++ changed = true; ++ ++ return changed; ++} ++ ++/** ++ * drm_connector_helper_hpd_irq_event - hotplug processing ++ * @connector: drm_connector ++ * ++ * Drivers can use this helper function to run a detect cycle on a connector ++ * which has the DRM_CONNECTOR_POLL_HPD flag set in its &polled member. ++ * ++ * This helper function is useful for drivers which can track hotplug ++ * interrupts for a single connector. Drivers that want to send a ++ * hotplug event for all connectors or can't track hotplug interrupts ++ * per connector need to use drm_helper_hpd_irq_event(). ++ * ++ * This function must be called from process context with no mode ++ * setting locks held. ++ * ++ * Note that a connector can be both polled and probed from the hotplug ++ * handler, in case the hotplug interrupt is known to be unreliable. ++ */ ++bool drm_connector_helper_hpd_irq_event(struct drm_connector *connector) ++{ ++ struct drm_device *dev = connector->dev; ++ bool changed; ++ ++ mutex_lock(&dev->mode_config.mutex); ++ changed = check_connector_changed(connector); ++ mutex_unlock(&dev->mode_config.mutex); ++ ++ if (changed) { ++ drm_kms_helper_hotplug_event(dev); ++ drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Sent hotplug event\n", ++ connector->base.id, ++ connector->name); ++ } ++ ++ return changed; ++} ++EXPORT_SYMBOL(drm_connector_helper_hpd_irq_event); ++ + /** + * drm_helper_hpd_irq_event - hotplug processing + * @dev: drm_device +@@ -808,9 +888,10 @@ EXPORT_SYMBOL(drm_kms_helper_poll_fini); + * interrupts for each connector. + * + * Drivers which support hotplug interrupts for each connector individually and +- * which have a more fine-grained detect logic should bypass this code and +- * directly call drm_kms_helper_hotplug_event() in case the connector state +- * changed. ++ * which have a more fine-grained detect logic can use ++ * drm_connector_helper_hpd_irq_event(). Alternatively, they should bypass this ++ * code and directly call drm_kms_helper_hotplug_event() in case the connector ++ * state changed. + * + * This function must be called from process context with no mode + * setting locks held. +@@ -822,9 +903,7 @@ bool drm_helper_hpd_irq_event(struct drm + { + struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; +- enum drm_connector_status old_status; + bool changed = false; +- u64 old_epoch_counter; + + if (!dev->mode_config.poll_enabled) + return false; +@@ -832,37 +911,8 @@ bool drm_helper_hpd_irq_event(struct drm + mutex_lock(&dev->mode_config.mutex); + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { +- /* Only handle HPD capable connectors. */ +- if (!(connector->polled & DRM_CONNECTOR_POLL_HPD)) +- continue; +- +- old_status = connector->status; +- +- old_epoch_counter = connector->epoch_counter; +- +- DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Old epoch counter %llu\n", connector->base.id, +- connector->name, +- old_epoch_counter); +- +- connector->status = drm_helper_probe_detect(connector, NULL, false); +- DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n", +- connector->base.id, +- connector->name, +- drm_get_connector_status_name(old_status), +- drm_get_connector_status_name(connector->status)); +- +- DRM_DEBUG_KMS("[CONNECTOR:%d:%s] New epoch counter %llu\n", +- connector->base.id, +- connector->name, +- connector->epoch_counter); +- +- /* +- * Check if epoch counter had changed, meaning that we need +- * to send a uevent. +- */ +- if (old_epoch_counter != connector->epoch_counter) ++ if (check_connector_changed(connector)) + changed = true; +- + } + drm_connector_list_iter_end(&conn_iter); + mutex_unlock(&dev->mode_config.mutex); +--- a/include/drm/drm_probe_helper.h ++++ b/include/drm/drm_probe_helper.h +@@ -18,6 +18,7 @@ int drm_helper_probe_detect(struct drm_c + void drm_kms_helper_poll_init(struct drm_device *dev); + void drm_kms_helper_poll_fini(struct drm_device *dev); + bool drm_helper_hpd_irq_event(struct drm_device *dev); ++bool drm_connector_helper_hpd_irq_event(struct drm_connector *connector); + void drm_kms_helper_hotplug_event(struct drm_device *dev); + + void drm_kms_helper_poll_disable(struct drm_device *dev); -- cgit v1.2.3