diff options
Diffstat (limited to 'drivers/gpu/drm/drm_fb_helper.c')
-rw-r--r-- | drivers/gpu/drm/drm_fb_helper.c | 53 |
1 files changed, 42 insertions, 11 deletions
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 95072047396..140b9525b48 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c | |||
@@ -342,9 +342,22 @@ int drm_fb_helper_debug_leave(struct fb_info *info) | |||
342 | } | 342 | } |
343 | EXPORT_SYMBOL(drm_fb_helper_debug_leave); | 343 | EXPORT_SYMBOL(drm_fb_helper_debug_leave); |
344 | 344 | ||
345 | bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper) | ||
346 | { | ||
347 | bool error = false; | ||
348 | int i, ret; | ||
349 | for (i = 0; i < fb_helper->crtc_count; i++) { | ||
350 | struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; | ||
351 | ret = drm_crtc_helper_set_config(mode_set); | ||
352 | if (ret) | ||
353 | error = true; | ||
354 | } | ||
355 | return error; | ||
356 | } | ||
357 | EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode); | ||
358 | |||
345 | bool drm_fb_helper_force_kernel_mode(void) | 359 | bool drm_fb_helper_force_kernel_mode(void) |
346 | { | 360 | { |
347 | int i = 0; | ||
348 | bool ret, error = false; | 361 | bool ret, error = false; |
349 | struct drm_fb_helper *helper; | 362 | struct drm_fb_helper *helper; |
350 | 363 | ||
@@ -352,12 +365,12 @@ bool drm_fb_helper_force_kernel_mode(void) | |||
352 | return false; | 365 | return false; |
353 | 366 | ||
354 | list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) { | 367 | list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) { |
355 | for (i = 0; i < helper->crtc_count; i++) { | 368 | if (helper->dev->switch_power_state == DRM_SWITCH_POWER_OFF) |
356 | struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set; | 369 | continue; |
357 | ret = drm_crtc_helper_set_config(mode_set); | 370 | |
358 | if (ret) | 371 | ret = drm_fb_helper_restore_fbdev_mode(helper); |
359 | error = true; | 372 | if (ret) |
360 | } | 373 | error = true; |
361 | } | 374 | } |
362 | return error; | 375 | return error; |
363 | } | 376 | } |
@@ -1503,17 +1516,33 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) | |||
1503 | } | 1516 | } |
1504 | EXPORT_SYMBOL(drm_fb_helper_initial_config); | 1517 | EXPORT_SYMBOL(drm_fb_helper_initial_config); |
1505 | 1518 | ||
1506 | bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) | 1519 | /** |
1520 | * drm_fb_helper_hotplug_event - respond to a hotplug notification by | ||
1521 | * probing all the outputs attached to the fb. | ||
1522 | * @fb_helper: the drm_fb_helper | ||
1523 | * | ||
1524 | * LOCKING: | ||
1525 | * Called at runtime, must take mode config lock. | ||
1526 | * | ||
1527 | * Scan the connectors attached to the fb_helper and try to put together a | ||
1528 | * setup after *notification of a change in output configuration. | ||
1529 | * | ||
1530 | * RETURNS: | ||
1531 | * 0 on success and a non-zero error code otherwise. | ||
1532 | */ | ||
1533 | int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) | ||
1507 | { | 1534 | { |
1535 | struct drm_device *dev = fb_helper->dev; | ||
1508 | int count = 0; | 1536 | int count = 0; |
1509 | u32 max_width, max_height, bpp_sel; | 1537 | u32 max_width, max_height, bpp_sel; |
1510 | bool bound = false, crtcs_bound = false; | 1538 | bool bound = false, crtcs_bound = false; |
1511 | struct drm_crtc *crtc; | 1539 | struct drm_crtc *crtc; |
1512 | 1540 | ||
1513 | if (!fb_helper->fb) | 1541 | if (!fb_helper->fb) |
1514 | return false; | 1542 | return 0; |
1515 | 1543 | ||
1516 | list_for_each_entry(crtc, &fb_helper->dev->mode_config.crtc_list, head) { | 1544 | mutex_lock(&dev->mode_config.mutex); |
1545 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||
1517 | if (crtc->fb) | 1546 | if (crtc->fb) |
1518 | crtcs_bound = true; | 1547 | crtcs_bound = true; |
1519 | if (crtc->fb == fb_helper->fb) | 1548 | if (crtc->fb == fb_helper->fb) |
@@ -1522,7 +1551,8 @@ bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) | |||
1522 | 1551 | ||
1523 | if (!bound && crtcs_bound) { | 1552 | if (!bound && crtcs_bound) { |
1524 | fb_helper->delayed_hotplug = true; | 1553 | fb_helper->delayed_hotplug = true; |
1525 | return false; | 1554 | mutex_unlock(&dev->mode_config.mutex); |
1555 | return 0; | ||
1526 | } | 1556 | } |
1527 | DRM_DEBUG_KMS("\n"); | 1557 | DRM_DEBUG_KMS("\n"); |
1528 | 1558 | ||
@@ -1533,6 +1563,7 @@ bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) | |||
1533 | count = drm_fb_helper_probe_connector_modes(fb_helper, max_width, | 1563 | count = drm_fb_helper_probe_connector_modes(fb_helper, max_width, |
1534 | max_height); | 1564 | max_height); |
1535 | drm_setup_crtcs(fb_helper); | 1565 | drm_setup_crtcs(fb_helper); |
1566 | mutex_unlock(&dev->mode_config.mutex); | ||
1536 | 1567 | ||
1537 | return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel); | 1568 | return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel); |
1538 | } | 1569 | } |