aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2010-03-30 01:34:17 -0400
committerDave Airlie <airlied@redhat.com>2010-04-06 20:29:52 -0400
commit5c4426a782bc9509573fc7958a786ebd14fafdf3 (patch)
treece701b338b6cd84e07a6259b56dca9df9875aedb /drivers/gpu
parent19b4b44503ccdf834062d68e022dc1e2721695a5 (diff)
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')
-rw-r--r--drivers/gpu/drm/Kconfig1
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c82
-rw-r--r--drivers/gpu/drm/radeon/radeon_fb.c14
-rw-r--r--drivers/gpu/drm/radeon/radeon_irq_kms.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h2
5 files changed, 91 insertions, 10 deletions
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 305c59003963..be5aa7d5206b 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -23,6 +23,7 @@ config DRM_KMS_HELPER
23 depends on DRM 23 depends on DRM
24 select FB 24 select FB
25 select FRAMEBUFFER_CONSOLE if !EMBEDDED 25 select FRAMEBUFFER_CONSOLE if !EMBEDDED
26 select SLOW_WORK
26 help 27 help
27 FB and CRTC helpers for KMS drivers. 28 FB and CRTC helpers for KMS drivers.
28 29
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)
1308 /* 1308 /*
1309 * we shouldn't end up with no modes here. 1309 * we shouldn't end up with no modes here.
1310 */ 1310 */
1311 if (count == 0) 1311 if (count == 0) {
1312 printk(KERN_INFO "No connectors reported connected with modes\n"); 1312 if (fb_helper->poll_enabled) {
1313 1313 delayed_slow_work_enqueue(&fb_helper->output_poll_slow_work,
1314 5*HZ);
1315 printk(KERN_INFO "No connectors reported connected with modes - started polling\n");
1316 } else
1317 printk(KERN_INFO "No connectors reported connected with modes\n");
1318 }
1314 drm_setup_crtcs(fb_helper); 1319 drm_setup_crtcs(fb_helper);
1315 1320
1316 return 0; 1321 return 0;
@@ -1318,15 +1323,80 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper)
1318EXPORT_SYMBOL(drm_fb_helper_initial_config); 1323EXPORT_SYMBOL(drm_fb_helper_initial_config);
1319 1324
1320bool drm_helper_fb_hotplug_event(struct drm_fb_helper *fb_helper, 1325bool drm_helper_fb_hotplug_event(struct drm_fb_helper *fb_helper,
1321 u32 max_width, u32 max_height) 1326 u32 max_width, u32 max_height, bool polled)
1322{ 1327{
1328 int count = 0;
1329 int ret;
1323 DRM_DEBUG_KMS("\n"); 1330 DRM_DEBUG_KMS("\n");
1324 1331
1325 drm_fb_helper_probe_connector_modes(fb_helper, max_width, 1332 count = drm_fb_helper_probe_connector_modes(fb_helper, max_width,
1326 max_height); 1333 max_height);
1327 1334 if (fb_helper->poll_enabled && !polled) {
1335 if (count) {
1336 delayed_slow_work_cancel(&fb_helper->output_poll_slow_work);
1337 } else {
1338 ret = delayed_slow_work_enqueue(&fb_helper->output_poll_slow_work, 5*HZ);
1339 }
1340 }
1328 drm_setup_crtcs(fb_helper); 1341 drm_setup_crtcs(fb_helper);
1329 1342
1330 return true; 1343 return true;
1331} 1344}
1332EXPORT_SYMBOL(drm_helper_fb_hotplug_event); 1345EXPORT_SYMBOL(drm_helper_fb_hotplug_event);
1346
1347static void output_poll_execute(struct slow_work *work)
1348{
1349 struct delayed_slow_work *delayed_work = container_of(work, struct delayed_slow_work, work);
1350 struct drm_fb_helper *fb_helper = container_of(delayed_work, struct drm_fb_helper, output_poll_slow_work);
1351 struct drm_device *dev = fb_helper->dev;
1352 struct drm_connector *connector;
1353 enum drm_connector_status old_status, status;
1354 bool repoll = true, changed = false;
1355 int ret;
1356
1357 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
1358 old_status = connector->status;
1359 status = connector->funcs->detect(connector);
1360 if (old_status != status) {
1361 changed = true;
1362 /* something changed */
1363 }
1364 if (status == connector_status_connected) {
1365 DRM_DEBUG("%s is connected - stop polling\n", drm_get_connector_name(connector));
1366 repoll = false;
1367 }
1368 }
1369
1370 if (repoll) {
1371 ret = delayed_slow_work_enqueue(delayed_work, 5*HZ);
1372 if (ret)
1373 DRM_ERROR("delayed enqueue failed %d\n", ret);
1374 }
1375
1376 if (changed) {
1377 if (fb_helper->fb_poll_changed)
1378 fb_helper->fb_poll_changed(fb_helper);
1379 }
1380}
1381
1382struct slow_work_ops output_poll_ops = {
1383 .execute = output_poll_execute,
1384};
1385
1386void drm_fb_helper_poll_init(struct drm_fb_helper *fb_helper)
1387{
1388 int ret;
1389
1390 ret = slow_work_register_user(THIS_MODULE);
1391
1392 delayed_slow_work_init(&fb_helper->output_poll_slow_work, &output_poll_ops);
1393 fb_helper->poll_enabled = true;
1394}
1395EXPORT_SYMBOL(drm_fb_helper_poll_init);
1396
1397void drm_fb_helper_poll_fini(struct drm_fb_helper *fb_helper)
1398{
1399 delayed_slow_work_cancel(&fb_helper->output_poll_slow_work);
1400 slow_work_unregister_user(THIS_MODULE);
1401}
1402EXPORT_SYMBOL(drm_fb_helper_poll_fini);
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index 7275b2e09444..7913e50fe501 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -321,18 +321,23 @@ static int radeonfb_probe(struct radeon_fbdev *rfbdev)
321 return drm_fb_helper_single_fb_probe(&rfbdev->helper, bpp_sel); 321 return drm_fb_helper_single_fb_probe(&rfbdev->helper, bpp_sel);
322} 322}
323 323
324void radeonfb_hotplug(struct drm_device *dev) 324void radeonfb_hotplug(struct drm_device *dev, bool polled)
325{ 325{
326 struct radeon_device *rdev = dev->dev_private; 326 struct radeon_device *rdev = dev->dev_private;
327 int max_width, max_height; 327 int max_width, max_height;
328 328
329 max_width = rdev->mode_info.rfbdev->rfb.base.width; 329 max_width = rdev->mode_info.rfbdev->rfb.base.width;
330 max_height = rdev->mode_info.rfbdev->rfb.base.height; 330 max_height = rdev->mode_info.rfbdev->rfb.base.height;
331 drm_helper_fb_hotplug_event(&rdev->mode_info.rfbdev->helper, max_width, max_height); 331 drm_helper_fb_hotplug_event(&rdev->mode_info.rfbdev->helper, max_width, max_height, polled);
332 332
333 radeonfb_probe(rdev->mode_info.rfbdev); 333 radeonfb_probe(rdev->mode_info.rfbdev);
334} 334}
335 335
336static void radeon_fb_poll_changed(struct drm_fb_helper *fb_helper)
337{
338 radeonfb_hotplug(fb_helper->dev, true);
339}
340
336static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfbdev) 341static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfbdev)
337{ 342{
338 struct fb_info *info; 343 struct fb_info *info;
@@ -381,8 +386,12 @@ int radeon_fbdev_init(struct radeon_device *rdev)
381 386
382 drm_fb_helper_single_add_all_connectors(&rfbdev->helper); 387 drm_fb_helper_single_add_all_connectors(&rfbdev->helper);
383 388
389 rfbdev->helper.fb_poll_changed = radeon_fb_poll_changed;
390 drm_fb_helper_poll_init(&rfbdev->helper);
391
384 drm_fb_helper_initial_config(&rfbdev->helper); 392 drm_fb_helper_initial_config(&rfbdev->helper);
385 radeonfb_probe(rfbdev); 393 radeonfb_probe(rfbdev);
394
386 return 0; 395 return 0;
387 396
388} 397}
@@ -392,6 +401,7 @@ void radeon_fbdev_fini(struct radeon_device *rdev)
392 if (!rdev->mode_info.rfbdev) 401 if (!rdev->mode_info.rfbdev)
393 return; 402 return;
394 403
404 drm_fb_helper_poll_fini(&rdev->mode_info.rfbdev->helper);
395 radeon_fbdev_destroy(rdev->ddev, rdev->mode_info.rfbdev); 405 radeon_fbdev_destroy(rdev->ddev, rdev->mode_info.rfbdev);
396 kfree(rdev->mode_info.rfbdev); 406 kfree(rdev->mode_info.rfbdev);
397 rdev->mode_info.rfbdev = NULL; 407 rdev->mode_info.rfbdev = NULL;
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c
index e7afd80a3d69..a95907aa7eae 100644
--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c
@@ -55,7 +55,7 @@ static void radeon_hotplug_work_func(struct work_struct *work)
55 radeon_connector_hotplug(connector); 55 radeon_connector_hotplug(connector);
56 } 56 }
57 /* Just fire off a uevent and let userspace tell us what to do */ 57 /* Just fire off a uevent and let userspace tell us what to do */
58 radeonfb_hotplug(dev); 58 radeonfb_hotplug(dev, false);
59 59
60 drm_sysfs_hotplug_event(dev); 60 drm_sysfs_hotplug_event(dev);
61} 61}
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 165f6025a3bc..4a086c09e117 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -585,5 +585,5 @@ void radeon_fbdev_fini(struct radeon_device *rdev);
585void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state); 585void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state);
586int radeon_fbdev_total_size(struct radeon_device *rdev); 586int radeon_fbdev_total_size(struct radeon_device *rdev);
587bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj); 587bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj);
588void radeonfb_hotplug(struct drm_device *dev); 588void radeonfb_hotplug(struct drm_device *dev, bool polled);
589#endif 589#endif