diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/Kconfig | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_fb_helper.c | 82 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_fb.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_irq_kms.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_mode.h | 2 |
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) | |||
1318 | EXPORT_SYMBOL(drm_fb_helper_initial_config); | 1323 | EXPORT_SYMBOL(drm_fb_helper_initial_config); |
1319 | 1324 | ||
1320 | bool drm_helper_fb_hotplug_event(struct drm_fb_helper *fb_helper, | 1325 | bool 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 | } |
1332 | EXPORT_SYMBOL(drm_helper_fb_hotplug_event); | 1345 | EXPORT_SYMBOL(drm_helper_fb_hotplug_event); |
1346 | |||
1347 | static 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 | |||
1382 | struct slow_work_ops output_poll_ops = { | ||
1383 | .execute = output_poll_execute, | ||
1384 | }; | ||
1385 | |||
1386 | void 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 | } | ||
1395 | EXPORT_SYMBOL(drm_fb_helper_poll_init); | ||
1396 | |||
1397 | void 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 | } | ||
1402 | EXPORT_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 | ||
324 | void radeonfb_hotplug(struct drm_device *dev) | 324 | void 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 | ||
336 | static void radeon_fb_poll_changed(struct drm_fb_helper *fb_helper) | ||
337 | { | ||
338 | radeonfb_hotplug(fb_helper->dev, true); | ||
339 | } | ||
340 | |||
336 | static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfbdev) | 341 | static 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); | |||
585 | void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state); | 585 | void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state); |
586 | int radeon_fbdev_total_size(struct radeon_device *rdev); | 586 | int radeon_fbdev_total_size(struct radeon_device *rdev); |
587 | bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj); | 587 | bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj); |
588 | void radeonfb_hotplug(struct drm_device *dev); | 588 | void radeonfb_hotplug(struct drm_device *dev, bool polled); |
589 | #endif | 589 | #endif |