aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-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