Skip to content

Commit e63c3d6

Browse files
mripardpopcornmix
authored andcommitted
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 <maxime@cerno.tech>
1 parent eac9f97 commit e63c3d6

File tree

2 files changed

+82
-32
lines changed

2 files changed

+82
-32
lines changed

drivers/gpu/drm/drm_probe_helper.c

Lines changed: 81 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,85 @@ void drm_kms_helper_poll_fini(struct drm_device *dev)
795795
}
796796
EXPORT_SYMBOL(drm_kms_helper_poll_fini);
797797

798+
static bool
799+
_drm_connector_helper_hpd_irq_event(struct drm_connector *connector,
800+
bool notify)
801+
{
802+
struct drm_device *dev = connector->dev;
803+
enum drm_connector_status old_status;
804+
u64 old_epoch_counter;
805+
bool changed = false;
806+
807+
/* Only handle HPD capable connectors. */
808+
drm_WARN_ON(dev, !(connector->polled & DRM_CONNECTOR_POLL_HPD));
809+
810+
drm_WARN_ON(dev, !mutex_is_locked(&dev->mode_config.mutex));
811+
812+
old_status = connector->status;
813+
old_epoch_counter = connector->epoch_counter;
814+
815+
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Old epoch counter %llu\n",
816+
connector->base.id,
817+
connector->name,
818+
old_epoch_counter);
819+
820+
connector->status = drm_helper_probe_detect(connector, NULL,
821+
false);
822+
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
823+
connector->base.id,
824+
connector->name,
825+
drm_get_connector_status_name(old_status),
826+
drm_get_connector_status_name(connector->status));
827+
828+
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] New epoch counter %llu\n",
829+
connector->base.id,
830+
connector->name,
831+
connector->epoch_counter);
832+
833+
/*
834+
* Check if epoch counter had changed, meaning that we need
835+
* to send a uevent.
836+
*/
837+
if (old_epoch_counter != connector->epoch_counter)
838+
changed = true;
839+
840+
if (changed && notify) {
841+
drm_kms_helper_hotplug_event(dev);
842+
DRM_DEBUG_KMS("Sent hotplug event\n");
843+
}
844+
845+
return changed;
846+
}
847+
848+
/**
849+
* drm_connector_helper_hpd_irq_event - hotplug processing
850+
* @connector: drm_connector
851+
*
852+
* Drivers can use this helper function to run a detect cycle on a connector
853+
* which has the DRM_CONNECTOR_POLL_HPD flag set in its &polled member.
854+
*
855+
* This helper function is useful for drivers which can track hotplug
856+
* interrupts for a single connector.
857+
*
858+
* This function must be called from process context with no mode
859+
* setting locks held.
860+
*
861+
* Note that a connector can be both polled and probed from the hotplug
862+
* handler, in case the hotplug interrupt is known to be unreliable.
863+
*/
864+
bool drm_connector_helper_hpd_irq_event(struct drm_connector *connector)
865+
{
866+
struct drm_device *dev = connector->dev;
867+
bool changed;
868+
869+
mutex_lock(&dev->mode_config.mutex);
870+
changed = _drm_connector_helper_hpd_irq_event(connector, true);
871+
mutex_unlock(&dev->mode_config.mutex);
872+
873+
return changed;
874+
}
875+
EXPORT_SYMBOL(drm_connector_helper_hpd_irq_event);
876+
798877
/**
799878
* drm_helper_hpd_irq_event - hotplug processing
800879
* @dev: drm_device
@@ -822,47 +901,17 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev)
822901
{
823902
struct drm_connector *connector;
824903
struct drm_connector_list_iter conn_iter;
825-
enum drm_connector_status old_status;
826904
bool changed = false;
827-
u64 old_epoch_counter;
828905

829906
if (!dev->mode_config.poll_enabled)
830907
return false;
831908

832909
mutex_lock(&dev->mode_config.mutex);
833910
drm_connector_list_iter_begin(dev, &conn_iter);
834911
drm_for_each_connector_iter(connector, &conn_iter) {
835-
/* Only handle HPD capable connectors. */
836-
if (!(connector->polled & DRM_CONNECTOR_POLL_HPD))
837-
continue;
838-
839-
old_status = connector->status;
840-
841-
old_epoch_counter = connector->epoch_counter;
842-
843-
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Old epoch counter %llu\n", connector->base.id,
844-
connector->name,
845-
old_epoch_counter);
846-
847-
connector->status = drm_helper_probe_detect(connector, NULL, false);
848-
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
849-
connector->base.id,
850-
connector->name,
851-
drm_get_connector_status_name(old_status),
852-
drm_get_connector_status_name(connector->status));
853-
854-
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] New epoch counter %llu\n",
855-
connector->base.id,
856-
connector->name,
857-
connector->epoch_counter);
858-
859-
/*
860-
* Check if epoch counter had changed, meaning that we need
861-
* to send a uevent.
862-
*/
863-
if (old_epoch_counter != connector->epoch_counter)
912+
if (_drm_connector_helper_hpd_irq_event(connector,
913+
false))
864914
changed = true;
865-
866915
}
867916
drm_connector_list_iter_end(&conn_iter);
868917
mutex_unlock(&dev->mode_config.mutex);

include/drm/drm_probe_helper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ int drm_helper_probe_detect(struct drm_connector *connector,
1818
void drm_kms_helper_poll_init(struct drm_device *dev);
1919
void drm_kms_helper_poll_fini(struct drm_device *dev);
2020
bool drm_helper_hpd_irq_event(struct drm_device *dev);
21+
bool drm_connector_helper_hpd_irq_event(struct drm_connector *connector);
2122
void drm_kms_helper_hotplug_event(struct drm_device *dev);
2223

2324
void drm_kms_helper_poll_disable(struct drm_device *dev);

0 commit comments

Comments
 (0)