diff options
author | Dave Airlie <airlied@redhat.com> | 2010-03-30 05:34:17 +0000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-04-07 10:29:52 +1000 |
commit | 5c4426a782bc9509573fc7958a786ebd14fafdf3 (patch) | |
tree | ce701b338b6cd84e07a6259b56dca9df9875aedb /drivers/gpu/drm/drm_fb_helper.c | |
parent | 19b4b44503ccdf834062d68e022dc1e2721695a5 (diff) | |
download | talos-op-linux-5c4426a782bc9509573fc7958a786ebd14fafdf3.tar.gz talos-op-linux-5c4426a782bc9509573fc7958a786ebd14fafdf3.zip |
drm/kms/fb: add polling support for when nothing is connected.
When we are running in a headless environment we have no idea what
output the user might plug in later, we only have hotplug detect
from the digital outputs. So if we detect no connected outputs at
initialisation, start a slow work operation to poll every 5 seconds
for an output.
this is only hooked up for radeon so far, on hw where we have full
hotplug detection there is no need for this.
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_fb_helper.c')
-rw-r--r-- | drivers/gpu/drm/drm_fb_helper.c | 82 |
1 files changed, 76 insertions, 6 deletions
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 6374e9b75d45..3312092f2c7e 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1308,9 +1308,14 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper) /* * we shouldn't end up with no modes here. */ - if (count == 0) - printk(KERN_INFO "No connectors reported connected with modes\n"); - + if (count == 0) { + if (fb_helper->poll_enabled) { + delayed_slow_work_enqueue(&fb_helper->output_poll_slow_work, + 5*HZ); + printk(KERN_INFO "No connectors reported connected with modes - started polling\n"); + } else + printk(KERN_INFO "No connectors reported connected with modes\n"); + } drm_setup_crtcs(fb_helper); return 0; @@ -1318,15 +1323,80 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper) EXPORT_SYMBOL(drm_fb_helper_initial_config); bool drm_helper_fb_hotplug_event(struct drm_fb_helper *fb_helper, - u32 max_width, u32 max_height) + u32 max_width, u32 max_height, bool polled) { + int count = 0; + int ret; DRM_DEBUG_KMS("\n"); - drm_fb_helper_probe_connector_modes(fb_helper, max_width, + count = drm_fb_helper_probe_connector_modes(fb_helper, max_width, max_height); - + if (fb_helper->poll_enabled && !polled) { + if (count) { + delayed_slow_work_cancel(&fb_helper->output_poll_slow_work); + } else { + ret = delayed_slow_work_enqueue(&fb_helper->output_poll_slow_work, 5*HZ); + } + } drm_setup_crtcs(fb_helper); return true; } EXPORT_SYMBOL(drm_helper_fb_hotplug_event); + +static void output_poll_execute(struct slow_work *work) +{ + struct delayed_slow_work *delayed_work = container_of(work, struct delayed_slow_work, work); + struct drm_fb_helper *fb_helper = container_of(delayed_work, struct drm_fb_helper, output_poll_slow_work); + struct drm_device *dev = fb_helper->dev; + struct drm_connector *connector; + enum drm_connector_status old_status, status; + bool repoll = true, changed = false; + int ret; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + old_status = connector->status; + status = connector->funcs->detect(connector); + if (old_status != status) { + changed = true; + /* something changed */ + } + if (status == connector_status_connected) { + DRM_DEBUG("%s is connected - stop polling\n", drm_get_connector_name(connector)); + repoll = false; + } + } + + if (repoll) { + ret = delayed_slow_work_enqueue(delayed_work, 5*HZ); + if (ret) + DRM_ERROR("delayed enqueue failed %d\n", ret); + } + + if (changed) { + if (fb_helper->fb_poll_changed) + fb_helper->fb_poll_changed(fb_helper); + } +} + +struct slow_work_ops output_poll_ops = { + .execute = output_poll_execute, +}; + +void drm_fb_helper_poll_init(struct drm_fb_helper *fb_helper) +{ + int ret; + + ret = slow_work_register_user(THIS_MODULE); + + delayed_slow_work_init(&fb_helper->output_poll_slow_work, &output_poll_ops); + fb_helper->poll_enabled = true; +} +EXPORT_SYMBOL(drm_fb_helper_poll_init); + +void drm_fb_helper_poll_fini(struct drm_fb_helper *fb_helper) +{ + delayed_slow_work_cancel(&fb_helper->output_poll_slow_work); + slow_work_unregister_user(THIS_MODULE); +} +EXPORT_SYMBOL(drm_fb_helper_poll_fini); |