drm: Add an HPD poll helper to reschedule the poll work
Add a helper to reschedule drm_mode_config::output_poll_work after
polling has been enabled for a connector (and needing a reschedule,
since previously polling was disabled for all connectors and hence
output_poll_work was not running).
This is needed by the next patch fixing HPD polling on i915.
CC: stable@vger.kernel.org # 6.4+
Cc: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Jouni Högander <jouni.hogander@intel.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230822113015.41224-1-imre.deak@intel.com
(cherry picked from commit fe2352fd64
)
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
This commit is contained in:
parent
e0d25c591a
commit
a94e7ccfc4
2 changed files with 47 additions and 22 deletions
|
@ -262,6 +262,26 @@ static bool drm_kms_helper_enable_hpd(struct drm_device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DRM_OUTPUT_POLL_PERIOD (10*HZ)
|
#define DRM_OUTPUT_POLL_PERIOD (10*HZ)
|
||||||
|
static void reschedule_output_poll_work(struct drm_device *dev)
|
||||||
|
{
|
||||||
|
unsigned long delay = DRM_OUTPUT_POLL_PERIOD;
|
||||||
|
|
||||||
|
if (dev->mode_config.delayed_event)
|
||||||
|
/*
|
||||||
|
* FIXME:
|
||||||
|
*
|
||||||
|
* Use short (1s) delay to handle the initial delayed event.
|
||||||
|
* This delay should not be needed, but Optimus/nouveau will
|
||||||
|
* fail in a mysterious way if the delayed event is handled as
|
||||||
|
* soon as possible like it is done in
|
||||||
|
* drm_helper_probe_single_connector_modes() in case the poll
|
||||||
|
* was enabled before.
|
||||||
|
*/
|
||||||
|
delay = HZ;
|
||||||
|
|
||||||
|
schedule_delayed_work(&dev->mode_config.output_poll_work, delay);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_kms_helper_poll_enable - re-enable output polling.
|
* drm_kms_helper_poll_enable - re-enable output polling.
|
||||||
* @dev: drm_device
|
* @dev: drm_device
|
||||||
|
@ -279,37 +299,41 @@ static bool drm_kms_helper_enable_hpd(struct drm_device *dev)
|
||||||
*/
|
*/
|
||||||
void drm_kms_helper_poll_enable(struct drm_device *dev)
|
void drm_kms_helper_poll_enable(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
bool poll = false;
|
|
||||||
unsigned long delay = DRM_OUTPUT_POLL_PERIOD;
|
|
||||||
|
|
||||||
if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll ||
|
if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll ||
|
||||||
dev->mode_config.poll_running)
|
dev->mode_config.poll_running)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
poll = drm_kms_helper_enable_hpd(dev);
|
if (drm_kms_helper_enable_hpd(dev) ||
|
||||||
|
dev->mode_config.delayed_event)
|
||||||
if (dev->mode_config.delayed_event) {
|
reschedule_output_poll_work(dev);
|
||||||
/*
|
|
||||||
* FIXME:
|
|
||||||
*
|
|
||||||
* Use short (1s) delay to handle the initial delayed event.
|
|
||||||
* This delay should not be needed, but Optimus/nouveau will
|
|
||||||
* fail in a mysterious way if the delayed event is handled as
|
|
||||||
* soon as possible like it is done in
|
|
||||||
* drm_helper_probe_single_connector_modes() in case the poll
|
|
||||||
* was enabled before.
|
|
||||||
*/
|
|
||||||
poll = true;
|
|
||||||
delay = HZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (poll)
|
|
||||||
schedule_delayed_work(&dev->mode_config.output_poll_work, delay);
|
|
||||||
|
|
||||||
dev->mode_config.poll_running = true;
|
dev->mode_config.poll_running = true;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_kms_helper_poll_enable);
|
EXPORT_SYMBOL(drm_kms_helper_poll_enable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_kms_helper_poll_reschedule - reschedule the output polling work
|
||||||
|
* @dev: drm_device
|
||||||
|
*
|
||||||
|
* This function reschedules the output polling work, after polling for a
|
||||||
|
* connector has been enabled.
|
||||||
|
*
|
||||||
|
* Drivers must call this helper after enabling polling for a connector by
|
||||||
|
* setting %DRM_CONNECTOR_POLL_CONNECT / %DRM_CONNECTOR_POLL_DISCONNECT flags
|
||||||
|
* in drm_connector::polled. Note that after disabling polling by clearing these
|
||||||
|
* flags for a connector will stop the output polling work automatically if
|
||||||
|
* the polling is disabled for all other connectors as well.
|
||||||
|
*
|
||||||
|
* The function can be called only after polling has been enabled by calling
|
||||||
|
* drm_kms_helper_poll_init() / drm_kms_helper_poll_enable().
|
||||||
|
*/
|
||||||
|
void drm_kms_helper_poll_reschedule(struct drm_device *dev)
|
||||||
|
{
|
||||||
|
if (dev->mode_config.poll_running)
|
||||||
|
reschedule_output_poll_work(dev);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_kms_helper_poll_reschedule);
|
||||||
|
|
||||||
static enum drm_connector_status
|
static enum drm_connector_status
|
||||||
drm_helper_probe_detect_ctx(struct drm_connector *connector, bool force)
|
drm_helper_probe_detect_ctx(struct drm_connector *connector, bool force)
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,6 +25,7 @@ void drm_kms_helper_connector_hotplug_event(struct drm_connector *connector);
|
||||||
|
|
||||||
void drm_kms_helper_poll_disable(struct drm_device *dev);
|
void drm_kms_helper_poll_disable(struct drm_device *dev);
|
||||||
void drm_kms_helper_poll_enable(struct drm_device *dev);
|
void drm_kms_helper_poll_enable(struct drm_device *dev);
|
||||||
|
void drm_kms_helper_poll_reschedule(struct drm_device *dev);
|
||||||
bool drm_kms_helper_is_poll_worker(void);
|
bool drm_kms_helper_is_poll_worker(void);
|
||||||
|
|
||||||
enum drm_mode_status drm_crtc_helper_mode_valid_fixed(struct drm_crtc *crtc,
|
enum drm_mode_status drm_crtc_helper_mode_valid_fixed(struct drm_crtc *crtc,
|
||||||
|
|
Loading…
Add table
Reference in a new issue