aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_probe_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_probe_helper.c')
-rw-r--r--drivers/gpu/drm/drm_probe_helper.c85
1 files changed, 40 insertions, 45 deletions
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index cf8f0128c161..93381454bdf7 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -43,7 +43,7 @@
* DOC: output probing helper overview
*
* This library provides some helper code for output probing. It provides an
- * implementation of the core connector->fill_modes interface with
+ * implementation of the core &drm_connector_funcs.fill_modes interface with
* drm_helper_probe_single_connector_modes.
*
* It also provides support for polling connectors with a work item and for
@@ -55,7 +55,7 @@
* handling code to avoid probing unrelated outputs.
*
* The probe helpers share the function table structures with other display
- * helper libraries. See struct &drm_connector_helper_funcs for the details.
+ * helper libraries. See &struct drm_connector_helper_funcs for the details.
*/
static bool drm_kms_helper_poll = true;
@@ -115,32 +115,38 @@ static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector)
#define DRM_OUTPUT_POLL_PERIOD (10*HZ)
/**
- * drm_kms_helper_poll_enable_locked - re-enable output polling.
+ * drm_kms_helper_poll_enable - re-enable output polling.
* @dev: drm_device
*
- * This function re-enables the output polling work without
- * locking the mode_config mutex.
+ * This function re-enables the output polling work, after it has been
+ * temporarily disabled using drm_kms_helper_poll_disable(), for example over
+ * suspend/resume.
+ *
+ * Drivers can call this helper from their device resume implementation. It is
+ * an error to call this when the output polling support has not yet been set
+ * up.
*
- * This is like drm_kms_helper_poll_enable() however it is to be
- * called from a context where the mode_config mutex is locked
- * already.
+ * Note that calls to enable and disable polling must be strictly ordered, which
+ * is automatically the case when they're only call from suspend/resume
+ * callbacks.
*/
-void drm_kms_helper_poll_enable_locked(struct drm_device *dev)
+void drm_kms_helper_poll_enable(struct drm_device *dev)
{
bool poll = false;
struct drm_connector *connector;
+ struct drm_connector_list_iter conn_iter;
unsigned long delay = DRM_OUTPUT_POLL_PERIOD;
- WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
-
if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll)
return;
- drm_for_each_connector(connector, dev) {
+ drm_connector_list_iter_get(dev, &conn_iter);
+ drm_for_each_connector_iter(connector, &conn_iter) {
if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT |
DRM_CONNECTOR_POLL_DISCONNECT))
poll = true;
}
+ drm_connector_list_iter_put(&conn_iter);
if (dev->mode_config.delayed_event) {
/*
@@ -160,7 +166,7 @@ void drm_kms_helper_poll_enable_locked(struct drm_device *dev)
if (poll)
schedule_delayed_work(&dev->mode_config.output_poll_work, delay);
}
-EXPORT_SYMBOL(drm_kms_helper_poll_enable_locked);
+EXPORT_SYMBOL(drm_kms_helper_poll_enable);
static enum drm_connector_status
drm_connector_detect(struct drm_connector *connector, bool force)
@@ -181,9 +187,9 @@ drm_connector_detect(struct drm_connector *connector, bool force)
* be added to the connector's probed_modes list, then culled (based on validity
* and the @maxX, @maxY parameters) and put into the normal modes list.
*
- * Intended to be used as a generic implementation of the ->fill_modes()
- * @connector vfunc for drivers that use the CRTC helpers for output mode
- * filtering and detection.
+ * Intended to be used as a generic implementation of the
+ * &drm_connector_funcs.fill_modes() vfunc for drivers that use the CRTC helpers
+ * for output mode filtering and detection.
*
* The basic procedure is as follows
*
@@ -195,7 +201,7 @@ drm_connector_detect(struct drm_connector *connector, bool force)
*
* - debugfs 'override_edid' (used for testing only)
* - firmware EDID (drm_load_edid_firmware())
- * - connector helper ->get_modes() vfunc
+ * - &drm_connector_helper_funcs.get_modes vfunc
* - if the connector status is connector_status_connected, standard
* VESA DMT modes up to 1024x768 are automatically added
* (drm_add_modes_noedid())
@@ -216,8 +222,8 @@ drm_connector_detect(struct drm_connector *connector, bool force)
* (if specified)
* - drm_mode_validate_flag() checks the modes againt basic connector
* capabilites (interlace_allowed,doublescan_allowed,stereo_allowed)
- * - the optional connector ->mode_valid() helper can perform driver and/or
- * hardware specific checks
+ * - the optional &drm_connector_helper_funcs.mode_valid helper can perform
+ * driver and/or hardware specific checks
*
* 5. Any mode whose status is not OK is pruned from the connector's modes list,
* accompanied by a debug message indicating the reason for the mode's
@@ -287,7 +293,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
/* Re-enable polling in case the global poll config changed. */
if (drm_kms_helper_poll != dev->mode_config.poll_running)
- drm_kms_helper_poll_enable_locked(dev);
+ drm_kms_helper_poll_enable(dev);
dev->mode_config.poll_running = drm_kms_helper_poll;
@@ -392,6 +398,7 @@ static void output_poll_execute(struct work_struct *work)
struct delayed_work *delayed_work = to_delayed_work(work);
struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work);
struct drm_connector *connector;
+ struct drm_connector_list_iter conn_iter;
enum drm_connector_status old_status;
bool repoll = false, changed;
@@ -407,8 +414,8 @@ static void output_poll_execute(struct work_struct *work)
goto out;
}
- drm_for_each_connector(connector, dev) {
-
+ drm_connector_list_iter_get(dev, &conn_iter);
+ drm_for_each_connector_iter(connector, &conn_iter) {
/* Ignore forced connectors. */
if (connector->force)
continue;
@@ -461,6 +468,7 @@ static void output_poll_execute(struct work_struct *work)
changed = true;
}
}
+ drm_connector_list_iter_put(&conn_iter);
mutex_unlock(&dev->mode_config.mutex);
@@ -479,8 +487,12 @@ out:
* This function disables the output polling work.
*
* Drivers can call this helper from their device suspend implementation. It is
- * not an error to call this even when output polling isn't enabled or arlready
- * disabled.
+ * not an error to call this even when output polling isn't enabled or already
+ * disabled. Polling is re-enabled by calling drm_kms_helper_poll_enable().
+ *
+ * Note that calls to enable and disable polling must be strictly ordered, which
+ * is automatically the case when they're only call from suspend/resume
+ * callbacks.
*/
void drm_kms_helper_poll_disable(struct drm_device *dev)
{
@@ -491,24 +503,6 @@ void drm_kms_helper_poll_disable(struct drm_device *dev)
EXPORT_SYMBOL(drm_kms_helper_poll_disable);
/**
- * drm_kms_helper_poll_enable - re-enable output polling.
- * @dev: drm_device
- *
- * This function re-enables the output polling work.
- *
- * Drivers can call this helper from their device resume implementation. It is
- * an error to call this when the output polling support has not yet been set
- * up.
- */
-void drm_kms_helper_poll_enable(struct drm_device *dev)
-{
- mutex_lock(&dev->mode_config.mutex);
- drm_kms_helper_poll_enable_locked(dev);
- mutex_unlock(&dev->mode_config.mutex);
-}
-EXPORT_SYMBOL(drm_kms_helper_poll_enable);
-
-/**
* drm_kms_helper_poll_init - initialize and enable output polling
* @dev: drm_device
*
@@ -572,6 +566,7 @@ EXPORT_SYMBOL(drm_kms_helper_poll_fini);
bool drm_helper_hpd_irq_event(struct drm_device *dev)
{
struct drm_connector *connector;
+ struct drm_connector_list_iter conn_iter;
enum drm_connector_status old_status;
bool changed = false;
@@ -579,8 +574,8 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev)
return false;
mutex_lock(&dev->mode_config.mutex);
- drm_for_each_connector(connector, dev) {
-
+ drm_connector_list_iter_get(dev, &conn_iter);
+ drm_for_each_connector_iter(connector, &conn_iter) {
/* Only handle HPD capable connectors. */
if (!(connector->polled & DRM_CONNECTOR_POLL_HPD))
continue;
@@ -596,7 +591,7 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev)
if (old_status != connector->status)
changed = true;
}
-
+ drm_connector_list_iter_put(&conn_iter);
mutex_unlock(&dev->mode_config.mutex);
if (changed)