diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-08 12:52:16 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-08 12:52:16 -0400 |
commit | e9f37d3a8d126e73f5737ef548cdf6f618e295e4 (patch) | |
tree | 831eb4952637828a7bbafa361185e0ca57aa86ed /drivers/gpu/drm/drm_crtc_helper.c | |
parent | 5fb6b953bb7aa86a9c8ea760934982cedc45c52b (diff) | |
parent | c39b06951f1dc2e384650288676c5b7dcc0ec92c (diff) |
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie:
"Highlights:
- drm:
Generic display port aux features, primary plane support, drm
master management fixes, logging cleanups, enforced locking checks
(instead of docs), documentation improvements, minor number
handling cleanup, pseudofs for shared inodes.
- ttm:
add ability to allocate from both ends
- i915:
broadwell features, power domain and runtime pm, per-process
address space infrastructure (not enabled)
- msm:
power management, hdmi audio support
- nouveau:
ongoing GPU fault recovery, initial maxwell support, random fixes
- exynos:
refactored driver to clean up a lot of abstraction, DP support
moved into drm, LVDS bridge support added, parallel panel support
- gma500:
SGX MMU support, SGX irq handling, asle irq work fixes
- radeon:
video engine bringup, ring handling fixes, use dp aux helpers
- vmwgfx:
add rendernode support"
* 'drm-next' of git://people.freedesktop.org/~airlied/linux: (849 commits)
DRM: armada: fix corruption while loading cursors
drm/dp_helper: don't return EPROTO for defers (v2)
drm/bridge: export ptn3460_init function
drm/exynos: remove MODULE_DEVICE_TABLE definitions
ARM: dts: exynos4412-trats2: enable exynos/fimd node
ARM: dts: exynos4210-trats: enable exynos/fimd node
ARM: dts: exynos4412-trats2: add panel node
ARM: dts: exynos4210-trats: add panel node
ARM: dts: exynos4: add MIPI DSI Master node
drm/panel: add S6E8AA0 driver
ARM: dts: exynos4210-universal_c210: add proper panel node
drm/panel: add ld9040 driver
panel/ld9040: add DT bindings
panel/s6e8aa0: add DT bindings
drm/exynos: add DSIM driver
exynos/dsim: add DT bindings
drm/exynos: disallow fbdev initialization if no device is connected
drm/mipi_dsi: create dsi devices only for nodes with reg property
drm/mipi_dsi: add flags to DSI messages
Skip intel_crt_init for Dell XPS 8700
...
Diffstat (limited to 'drivers/gpu/drm/drm_crtc_helper.c')
-rw-r--r-- | drivers/gpu/drm/drm_crtc_helper.c | 245 |
1 files changed, 181 insertions, 64 deletions
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index f7a81209beb3..c43825e8f5c1 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
@@ -105,9 +105,6 @@ static void drm_mode_validate_flag(struct drm_connector *connector, | |||
105 | * @maxX: max width for modes | 105 | * @maxX: max width for modes |
106 | * @maxY: max height for modes | 106 | * @maxY: max height for modes |
107 | * | 107 | * |
108 | * LOCKING: | ||
109 | * Caller must hold mode config lock. | ||
110 | * | ||
111 | * Based on the helper callbacks implemented by @connector try to detect all | 108 | * Based on the helper callbacks implemented by @connector try to detect all |
112 | * valid modes. Modes will first be added to the connector's probed_modes list, | 109 | * valid modes. Modes will first be added to the connector's probed_modes list, |
113 | * then culled (based on validity and the @maxX, @maxY parameters) and put into | 110 | * then culled (based on validity and the @maxX, @maxY parameters) and put into |
@@ -117,8 +114,8 @@ static void drm_mode_validate_flag(struct drm_connector *connector, | |||
117 | * @connector vfunc for drivers that use the crtc helpers for output mode | 114 | * @connector vfunc for drivers that use the crtc helpers for output mode |
118 | * filtering and detection. | 115 | * filtering and detection. |
119 | * | 116 | * |
120 | * RETURNS: | 117 | * Returns: |
121 | * Number of modes found on @connector. | 118 | * The number of modes found on @connector. |
122 | */ | 119 | */ |
123 | int drm_helper_probe_single_connector_modes(struct drm_connector *connector, | 120 | int drm_helper_probe_single_connector_modes(struct drm_connector *connector, |
124 | uint32_t maxX, uint32_t maxY) | 121 | uint32_t maxX, uint32_t maxY) |
@@ -131,6 +128,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, | |||
131 | int mode_flags = 0; | 128 | int mode_flags = 0; |
132 | bool verbose_prune = true; | 129 | bool verbose_prune = true; |
133 | 130 | ||
131 | WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); | ||
132 | |||
134 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, | 133 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, |
135 | drm_get_connector_name(connector)); | 134 | drm_get_connector_name(connector)); |
136 | /* set all modes to the unverified state */ | 135 | /* set all modes to the unverified state */ |
@@ -176,8 +175,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, | |||
176 | drm_mode_connector_list_update(connector); | 175 | drm_mode_connector_list_update(connector); |
177 | 176 | ||
178 | if (maxX && maxY) | 177 | if (maxX && maxY) |
179 | drm_mode_validate_size(dev, &connector->modes, maxX, | 178 | drm_mode_validate_size(dev, &connector->modes, maxX, maxY); |
180 | maxY, 0); | ||
181 | 179 | ||
182 | if (connector->interlace_allowed) | 180 | if (connector->interlace_allowed) |
183 | mode_flags |= DRM_MODE_FLAG_INTERLACE; | 181 | mode_flags |= DRM_MODE_FLAG_INTERLACE; |
@@ -219,18 +217,19 @@ EXPORT_SYMBOL(drm_helper_probe_single_connector_modes); | |||
219 | * drm_helper_encoder_in_use - check if a given encoder is in use | 217 | * drm_helper_encoder_in_use - check if a given encoder is in use |
220 | * @encoder: encoder to check | 218 | * @encoder: encoder to check |
221 | * | 219 | * |
222 | * LOCKING: | 220 | * Checks whether @encoder is with the current mode setting output configuration |
223 | * Caller must hold mode config lock. | 221 | * in use by any connector. This doesn't mean that it is actually enabled since |
224 | * | 222 | * the DPMS state is tracked separately. |
225 | * Walk @encoders's DRM device's mode_config and see if it's in use. | ||
226 | * | 223 | * |
227 | * RETURNS: | 224 | * Returns: |
228 | * True if @encoder is part of the mode_config, false otherwise. | 225 | * True if @encoder is used, false otherwise. |
229 | */ | 226 | */ |
230 | bool drm_helper_encoder_in_use(struct drm_encoder *encoder) | 227 | bool drm_helper_encoder_in_use(struct drm_encoder *encoder) |
231 | { | 228 | { |
232 | struct drm_connector *connector; | 229 | struct drm_connector *connector; |
233 | struct drm_device *dev = encoder->dev; | 230 | struct drm_device *dev = encoder->dev; |
231 | |||
232 | WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); | ||
234 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) | 233 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) |
235 | if (connector->encoder == encoder) | 234 | if (connector->encoder == encoder) |
236 | return true; | 235 | return true; |
@@ -242,19 +241,19 @@ EXPORT_SYMBOL(drm_helper_encoder_in_use); | |||
242 | * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config | 241 | * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config |
243 | * @crtc: CRTC to check | 242 | * @crtc: CRTC to check |
244 | * | 243 | * |
245 | * LOCKING: | 244 | * Checks whether @crtc is with the current mode setting output configuration |
246 | * Caller must hold mode config lock. | 245 | * in use by any connector. This doesn't mean that it is actually enabled since |
247 | * | 246 | * the DPMS state is tracked separately. |
248 | * Walk @crtc's DRM device's mode_config and see if it's in use. | ||
249 | * | 247 | * |
250 | * RETURNS: | 248 | * Returns: |
251 | * True if @crtc is part of the mode_config, false otherwise. | 249 | * True if @crtc is used, false otherwise. |
252 | */ | 250 | */ |
253 | bool drm_helper_crtc_in_use(struct drm_crtc *crtc) | 251 | bool drm_helper_crtc_in_use(struct drm_crtc *crtc) |
254 | { | 252 | { |
255 | struct drm_encoder *encoder; | 253 | struct drm_encoder *encoder; |
256 | struct drm_device *dev = crtc->dev; | 254 | struct drm_device *dev = crtc->dev; |
257 | /* FIXME: Locking around list access? */ | 255 | |
256 | WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); | ||
258 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) | 257 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) |
259 | if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder)) | 258 | if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder)) |
260 | return true; | 259 | return true; |
@@ -279,27 +278,17 @@ drm_encoder_disable(struct drm_encoder *encoder) | |||
279 | encoder->bridge->funcs->post_disable(encoder->bridge); | 278 | encoder->bridge->funcs->post_disable(encoder->bridge); |
280 | } | 279 | } |
281 | 280 | ||
282 | /** | 281 | static void __drm_helper_disable_unused_functions(struct drm_device *dev) |
283 | * drm_helper_disable_unused_functions - disable unused objects | ||
284 | * @dev: DRM device | ||
285 | * | ||
286 | * LOCKING: | ||
287 | * Caller must hold mode config lock. | ||
288 | * | ||
289 | * If an connector or CRTC isn't part of @dev's mode_config, it can be disabled | ||
290 | * by calling its dpms function, which should power it off. | ||
291 | */ | ||
292 | void drm_helper_disable_unused_functions(struct drm_device *dev) | ||
293 | { | 282 | { |
294 | struct drm_encoder *encoder; | 283 | struct drm_encoder *encoder; |
295 | struct drm_connector *connector; | 284 | struct drm_connector *connector; |
296 | struct drm_crtc *crtc; | 285 | struct drm_crtc *crtc; |
297 | 286 | ||
287 | drm_warn_on_modeset_not_all_locked(dev); | ||
288 | |||
298 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 289 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
299 | if (!connector->encoder) | 290 | if (!connector->encoder) |
300 | continue; | 291 | continue; |
301 | if (connector->status == connector_status_disconnected) | ||
302 | connector->encoder = NULL; | ||
303 | } | 292 | } |
304 | 293 | ||
305 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 294 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
@@ -318,10 +307,27 @@ void drm_helper_disable_unused_functions(struct drm_device *dev) | |||
318 | (*crtc_funcs->disable)(crtc); | 307 | (*crtc_funcs->disable)(crtc); |
319 | else | 308 | else |
320 | (*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF); | 309 | (*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF); |
321 | crtc->fb = NULL; | 310 | crtc->primary->fb = NULL; |
322 | } | 311 | } |
323 | } | 312 | } |
324 | } | 313 | } |
314 | |||
315 | /** | ||
316 | * drm_helper_disable_unused_functions - disable unused objects | ||
317 | * @dev: DRM device | ||
318 | * | ||
319 | * This function walks through the entire mode setting configuration of @dev. It | ||
320 | * will remove any crtc links of unused encoders and encoder links of | ||
321 | * disconnected connectors. Then it will disable all unused encoders and crtcs | ||
322 | * either by calling their disable callback if available or by calling their | ||
323 | * dpms callback with DRM_MODE_DPMS_OFF. | ||
324 | */ | ||
325 | void drm_helper_disable_unused_functions(struct drm_device *dev) | ||
326 | { | ||
327 | drm_modeset_lock_all(dev); | ||
328 | __drm_helper_disable_unused_functions(dev); | ||
329 | drm_modeset_unlock_all(dev); | ||
330 | } | ||
325 | EXPORT_SYMBOL(drm_helper_disable_unused_functions); | 331 | EXPORT_SYMBOL(drm_helper_disable_unused_functions); |
326 | 332 | ||
327 | /* | 333 | /* |
@@ -355,9 +361,6 @@ drm_crtc_prepare_encoders(struct drm_device *dev) | |||
355 | * @y: vertical offset into the surface | 361 | * @y: vertical offset into the surface |
356 | * @old_fb: old framebuffer, for cleanup | 362 | * @old_fb: old framebuffer, for cleanup |
357 | * | 363 | * |
358 | * LOCKING: | ||
359 | * Caller must hold mode config lock. | ||
360 | * | ||
361 | * Try to set @mode on @crtc. Give @crtc and its associated connectors a chance | 364 | * Try to set @mode on @crtc. Give @crtc and its associated connectors a chance |
362 | * to fixup or reject the mode prior to trying to set it. This is an internal | 365 | * to fixup or reject the mode prior to trying to set it. This is an internal |
363 | * helper that drivers could e.g. use to update properties that require the | 366 | * helper that drivers could e.g. use to update properties that require the |
@@ -367,8 +370,8 @@ drm_crtc_prepare_encoders(struct drm_device *dev) | |||
367 | * drm_crtc_helper_set_config() helper function to drive the mode setting | 370 | * drm_crtc_helper_set_config() helper function to drive the mode setting |
368 | * sequence. | 371 | * sequence. |
369 | * | 372 | * |
370 | * RETURNS: | 373 | * Returns: |
371 | * True if the mode was set successfully, or false otherwise. | 374 | * True if the mode was set successfully, false otherwise. |
372 | */ | 375 | */ |
373 | bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, | 376 | bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, |
374 | struct drm_display_mode *mode, | 377 | struct drm_display_mode *mode, |
@@ -384,6 +387,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, | |||
384 | struct drm_encoder *encoder; | 387 | struct drm_encoder *encoder; |
385 | bool ret = true; | 388 | bool ret = true; |
386 | 389 | ||
390 | drm_warn_on_modeset_not_all_locked(dev); | ||
391 | |||
387 | saved_enabled = crtc->enabled; | 392 | saved_enabled = crtc->enabled; |
388 | crtc->enabled = drm_helper_crtc_in_use(crtc); | 393 | crtc->enabled = drm_helper_crtc_in_use(crtc); |
389 | if (!crtc->enabled) | 394 | if (!crtc->enabled) |
@@ -552,7 +557,7 @@ drm_crtc_helper_disable(struct drm_crtc *crtc) | |||
552 | } | 557 | } |
553 | } | 558 | } |
554 | 559 | ||
555 | drm_helper_disable_unused_functions(dev); | 560 | __drm_helper_disable_unused_functions(dev); |
556 | return 0; | 561 | return 0; |
557 | } | 562 | } |
558 | 563 | ||
@@ -560,17 +565,14 @@ drm_crtc_helper_disable(struct drm_crtc *crtc) | |||
560 | * drm_crtc_helper_set_config - set a new config from userspace | 565 | * drm_crtc_helper_set_config - set a new config from userspace |
561 | * @set: mode set configuration | 566 | * @set: mode set configuration |
562 | * | 567 | * |
563 | * LOCKING: | ||
564 | * Caller must hold mode config lock. | ||
565 | * | ||
566 | * Setup a new configuration, provided by the upper layers (either an ioctl call | 568 | * Setup a new configuration, provided by the upper layers (either an ioctl call |
567 | * from userspace or internally e.g. from the fbdev support code) in @set, and | 569 | * from userspace or internally e.g. from the fbdev support code) in @set, and |
568 | * enable it. This is the main helper functions for drivers that implement | 570 | * enable it. This is the main helper functions for drivers that implement |
569 | * kernel mode setting with the crtc helper functions and the assorted | 571 | * kernel mode setting with the crtc helper functions and the assorted |
570 | * ->prepare(), ->modeset() and ->commit() helper callbacks. | 572 | * ->prepare(), ->modeset() and ->commit() helper callbacks. |
571 | * | 573 | * |
572 | * RETURNS: | 574 | * Returns: |
573 | * Returns 0 on success, -ERRNO on failure. | 575 | * Returns 0 on success, negative errno numbers on failure. |
574 | */ | 576 | */ |
575 | int drm_crtc_helper_set_config(struct drm_mode_set *set) | 577 | int drm_crtc_helper_set_config(struct drm_mode_set *set) |
576 | { | 578 | { |
@@ -612,6 +614,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
612 | 614 | ||
613 | dev = set->crtc->dev; | 615 | dev = set->crtc->dev; |
614 | 616 | ||
617 | drm_warn_on_modeset_not_all_locked(dev); | ||
618 | |||
615 | /* | 619 | /* |
616 | * Allocate space for the backup of all (non-pointer) encoder and | 620 | * Allocate space for the backup of all (non-pointer) encoder and |
617 | * connector data. | 621 | * connector data. |
@@ -647,19 +651,19 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
647 | save_set.mode = &set->crtc->mode; | 651 | save_set.mode = &set->crtc->mode; |
648 | save_set.x = set->crtc->x; | 652 | save_set.x = set->crtc->x; |
649 | save_set.y = set->crtc->y; | 653 | save_set.y = set->crtc->y; |
650 | save_set.fb = set->crtc->fb; | 654 | save_set.fb = set->crtc->primary->fb; |
651 | 655 | ||
652 | /* We should be able to check here if the fb has the same properties | 656 | /* We should be able to check here if the fb has the same properties |
653 | * and then just flip_or_move it */ | 657 | * and then just flip_or_move it */ |
654 | if (set->crtc->fb != set->fb) { | 658 | if (set->crtc->primary->fb != set->fb) { |
655 | /* If we have no fb then treat it as a full mode set */ | 659 | /* If we have no fb then treat it as a full mode set */ |
656 | if (set->crtc->fb == NULL) { | 660 | if (set->crtc->primary->fb == NULL) { |
657 | DRM_DEBUG_KMS("crtc has no fb, full mode set\n"); | 661 | DRM_DEBUG_KMS("crtc has no fb, full mode set\n"); |
658 | mode_changed = true; | 662 | mode_changed = true; |
659 | } else if (set->fb == NULL) { | 663 | } else if (set->fb == NULL) { |
660 | mode_changed = true; | 664 | mode_changed = true; |
661 | } else if (set->fb->pixel_format != | 665 | } else if (set->fb->pixel_format != |
662 | set->crtc->fb->pixel_format) { | 666 | set->crtc->primary->fb->pixel_format) { |
663 | mode_changed = true; | 667 | mode_changed = true; |
664 | } else | 668 | } else |
665 | fb_changed = true; | 669 | fb_changed = true; |
@@ -689,12 +693,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
689 | if (new_encoder == NULL) | 693 | if (new_encoder == NULL) |
690 | /* don't break so fail path works correct */ | 694 | /* don't break so fail path works correct */ |
691 | fail = 1; | 695 | fail = 1; |
692 | break; | ||
693 | 696 | ||
694 | if (connector->dpms != DRM_MODE_DPMS_ON) { | 697 | if (connector->dpms != DRM_MODE_DPMS_ON) { |
695 | DRM_DEBUG_KMS("connector dpms not on, full mode switch\n"); | 698 | DRM_DEBUG_KMS("connector dpms not on, full mode switch\n"); |
696 | mode_changed = true; | 699 | mode_changed = true; |
697 | } | 700 | } |
701 | |||
702 | break; | ||
698 | } | 703 | } |
699 | } | 704 | } |
700 | 705 | ||
@@ -760,13 +765,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
760 | DRM_DEBUG_KMS("attempting to set mode from" | 765 | DRM_DEBUG_KMS("attempting to set mode from" |
761 | " userspace\n"); | 766 | " userspace\n"); |
762 | drm_mode_debug_printmodeline(set->mode); | 767 | drm_mode_debug_printmodeline(set->mode); |
763 | set->crtc->fb = set->fb; | 768 | set->crtc->primary->fb = set->fb; |
764 | if (!drm_crtc_helper_set_mode(set->crtc, set->mode, | 769 | if (!drm_crtc_helper_set_mode(set->crtc, set->mode, |
765 | set->x, set->y, | 770 | set->x, set->y, |
766 | save_set.fb)) { | 771 | save_set.fb)) { |
767 | DRM_ERROR("failed to set mode on [CRTC:%d]\n", | 772 | DRM_ERROR("failed to set mode on [CRTC:%d]\n", |
768 | set->crtc->base.id); | 773 | set->crtc->base.id); |
769 | set->crtc->fb = save_set.fb; | 774 | set->crtc->primary->fb = save_set.fb; |
770 | ret = -EINVAL; | 775 | ret = -EINVAL; |
771 | goto fail; | 776 | goto fail; |
772 | } | 777 | } |
@@ -777,17 +782,17 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
777 | set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON); | 782 | set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON); |
778 | } | 783 | } |
779 | } | 784 | } |
780 | drm_helper_disable_unused_functions(dev); | 785 | __drm_helper_disable_unused_functions(dev); |
781 | } else if (fb_changed) { | 786 | } else if (fb_changed) { |
782 | set->crtc->x = set->x; | 787 | set->crtc->x = set->x; |
783 | set->crtc->y = set->y; | 788 | set->crtc->y = set->y; |
784 | set->crtc->fb = set->fb; | 789 | set->crtc->primary->fb = set->fb; |
785 | ret = crtc_funcs->mode_set_base(set->crtc, | 790 | ret = crtc_funcs->mode_set_base(set->crtc, |
786 | set->x, set->y, save_set.fb); | 791 | set->x, set->y, save_set.fb); |
787 | if (ret != 0) { | 792 | if (ret != 0) { |
788 | set->crtc->x = save_set.x; | 793 | set->crtc->x = save_set.x; |
789 | set->crtc->y = save_set.y; | 794 | set->crtc->y = save_set.y; |
790 | set->crtc->fb = save_set.fb; | 795 | set->crtc->primary->fb = save_set.fb; |
791 | goto fail; | 796 | goto fail; |
792 | } | 797 | } |
793 | } | 798 | } |
@@ -924,8 +929,16 @@ void drm_helper_connector_dpms(struct drm_connector *connector, int mode) | |||
924 | } | 929 | } |
925 | EXPORT_SYMBOL(drm_helper_connector_dpms); | 930 | EXPORT_SYMBOL(drm_helper_connector_dpms); |
926 | 931 | ||
927 | int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, | 932 | /** |
928 | struct drm_mode_fb_cmd2 *mode_cmd) | 933 | * drm_helper_mode_fill_fb_struct - fill out framebuffer metadata |
934 | * @fb: drm_framebuffer object to fill out | ||
935 | * @mode_cmd: metadata from the userspace fb creation request | ||
936 | * | ||
937 | * This helper can be used in a drivers fb_create callback to pre-fill the fb's | ||
938 | * metadata fields. | ||
939 | */ | ||
940 | void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, | ||
941 | struct drm_mode_fb_cmd2 *mode_cmd) | ||
929 | { | 942 | { |
930 | int i; | 943 | int i; |
931 | 944 | ||
@@ -938,26 +951,47 @@ int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, | |||
938 | drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth, | 951 | drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth, |
939 | &fb->bits_per_pixel); | 952 | &fb->bits_per_pixel); |
940 | fb->pixel_format = mode_cmd->pixel_format; | 953 | fb->pixel_format = mode_cmd->pixel_format; |
941 | |||
942 | return 0; | ||
943 | } | 954 | } |
944 | EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct); | 955 | EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct); |
945 | 956 | ||
946 | int drm_helper_resume_force_mode(struct drm_device *dev) | 957 | /** |
958 | * drm_helper_resume_force_mode - force-restore mode setting configuration | ||
959 | * @dev: drm_device which should be restored | ||
960 | * | ||
961 | * Drivers which use the mode setting helpers can use this function to | ||
962 | * force-restore the mode setting configuration e.g. on resume or when something | ||
963 | * else might have trampled over the hw state (like some overzealous old BIOSen | ||
964 | * tended to do). | ||
965 | * | ||
966 | * This helper doesn't provide a error return value since restoring the old | ||
967 | * config should never fail due to resource allocation issues since the driver | ||
968 | * has successfully set the restored configuration already. Hence this should | ||
969 | * boil down to the equivalent of a few dpms on calls, which also don't provide | ||
970 | * an error code. | ||
971 | * | ||
972 | * Drivers where simply restoring an old configuration again might fail (e.g. | ||
973 | * due to slight differences in allocating shared resources when the | ||
974 | * configuration is restored in a different order than when userspace set it up) | ||
975 | * need to use their own restore logic. | ||
976 | */ | ||
977 | void drm_helper_resume_force_mode(struct drm_device *dev) | ||
947 | { | 978 | { |
948 | struct drm_crtc *crtc; | 979 | struct drm_crtc *crtc; |
949 | struct drm_encoder *encoder; | 980 | struct drm_encoder *encoder; |
950 | struct drm_crtc_helper_funcs *crtc_funcs; | 981 | struct drm_crtc_helper_funcs *crtc_funcs; |
951 | int ret, encoder_dpms; | 982 | int encoder_dpms; |
983 | bool ret; | ||
952 | 984 | ||
985 | drm_modeset_lock_all(dev); | ||
953 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 986 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
954 | 987 | ||
955 | if (!crtc->enabled) | 988 | if (!crtc->enabled) |
956 | continue; | 989 | continue; |
957 | 990 | ||
958 | ret = drm_crtc_helper_set_mode(crtc, &crtc->mode, | 991 | ret = drm_crtc_helper_set_mode(crtc, &crtc->mode, |
959 | crtc->x, crtc->y, crtc->fb); | 992 | crtc->x, crtc->y, crtc->primary->fb); |
960 | 993 | ||
994 | /* Restoring the old config should never fail! */ | ||
961 | if (ret == false) | 995 | if (ret == false) |
962 | DRM_ERROR("failed to set mode on crtc %p\n", crtc); | 996 | DRM_ERROR("failed to set mode on crtc %p\n", crtc); |
963 | 997 | ||
@@ -980,12 +1014,29 @@ int drm_helper_resume_force_mode(struct drm_device *dev) | |||
980 | drm_helper_choose_crtc_dpms(crtc)); | 1014 | drm_helper_choose_crtc_dpms(crtc)); |
981 | } | 1015 | } |
982 | } | 1016 | } |
1017 | |||
983 | /* disable the unused connectors while restoring the modesetting */ | 1018 | /* disable the unused connectors while restoring the modesetting */ |
984 | drm_helper_disable_unused_functions(dev); | 1019 | __drm_helper_disable_unused_functions(dev); |
985 | return 0; | 1020 | drm_modeset_unlock_all(dev); |
986 | } | 1021 | } |
987 | EXPORT_SYMBOL(drm_helper_resume_force_mode); | 1022 | EXPORT_SYMBOL(drm_helper_resume_force_mode); |
988 | 1023 | ||
1024 | /** | ||
1025 | * drm_kms_helper_hotplug_event - fire off KMS hotplug events | ||
1026 | * @dev: drm_device whose connector state changed | ||
1027 | * | ||
1028 | * This function fires off the uevent for userspace and also calls the | ||
1029 | * output_poll_changed function, which is most commonly used to inform the fbdev | ||
1030 | * emulation code and allow it to update the fbcon output configuration. | ||
1031 | * | ||
1032 | * Drivers should call this from their hotplug handling code when a change is | ||
1033 | * detected. Note that this function does not do any output detection of its | ||
1034 | * own, like drm_helper_hpd_irq_event() does - this is assumed to be done by the | ||
1035 | * driver already. | ||
1036 | * | ||
1037 | * This function must be called from process context with no mode | ||
1038 | * setting locks held. | ||
1039 | */ | ||
989 | void drm_kms_helper_hotplug_event(struct drm_device *dev) | 1040 | void drm_kms_helper_hotplug_event(struct drm_device *dev) |
990 | { | 1041 | { |
991 | /* send a uevent + call fbdev */ | 1042 | /* send a uevent + call fbdev */ |
@@ -1054,6 +1105,16 @@ static void output_poll_execute(struct work_struct *work) | |||
1054 | schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD); | 1105 | schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD); |
1055 | } | 1106 | } |
1056 | 1107 | ||
1108 | /** | ||
1109 | * drm_kms_helper_poll_disable - disable output polling | ||
1110 | * @dev: drm_device | ||
1111 | * | ||
1112 | * This function disables the output polling work. | ||
1113 | * | ||
1114 | * Drivers can call this helper from their device suspend implementation. It is | ||
1115 | * not an error to call this even when output polling isn't enabled or arlready | ||
1116 | * disabled. | ||
1117 | */ | ||
1057 | void drm_kms_helper_poll_disable(struct drm_device *dev) | 1118 | void drm_kms_helper_poll_disable(struct drm_device *dev) |
1058 | { | 1119 | { |
1059 | if (!dev->mode_config.poll_enabled) | 1120 | if (!dev->mode_config.poll_enabled) |
@@ -1062,6 +1123,16 @@ void drm_kms_helper_poll_disable(struct drm_device *dev) | |||
1062 | } | 1123 | } |
1063 | EXPORT_SYMBOL(drm_kms_helper_poll_disable); | 1124 | EXPORT_SYMBOL(drm_kms_helper_poll_disable); |
1064 | 1125 | ||
1126 | /** | ||
1127 | * drm_kms_helper_poll_enable - re-enable output polling. | ||
1128 | * @dev: drm_device | ||
1129 | * | ||
1130 | * This function re-enables the output polling work. | ||
1131 | * | ||
1132 | * Drivers can call this helper from their device resume implementation. It is | ||
1133 | * an error to call this when the output polling support has not yet been set | ||
1134 | * up. | ||
1135 | */ | ||
1065 | void drm_kms_helper_poll_enable(struct drm_device *dev) | 1136 | void drm_kms_helper_poll_enable(struct drm_device *dev) |
1066 | { | 1137 | { |
1067 | bool poll = false; | 1138 | bool poll = false; |
@@ -1081,6 +1152,25 @@ void drm_kms_helper_poll_enable(struct drm_device *dev) | |||
1081 | } | 1152 | } |
1082 | EXPORT_SYMBOL(drm_kms_helper_poll_enable); | 1153 | EXPORT_SYMBOL(drm_kms_helper_poll_enable); |
1083 | 1154 | ||
1155 | /** | ||
1156 | * drm_kms_helper_poll_init - initialize and enable output polling | ||
1157 | * @dev: drm_device | ||
1158 | * | ||
1159 | * This function intializes and then also enables output polling support for | ||
1160 | * @dev. Drivers which do not have reliable hotplug support in hardware can use | ||
1161 | * this helper infrastructure to regularly poll such connectors for changes in | ||
1162 | * their connection state. | ||
1163 | * | ||
1164 | * Drivers can control which connectors are polled by setting the | ||
1165 | * DRM_CONNECTOR_POLL_CONNECT and DRM_CONNECTOR_POLL_DISCONNECT flags. On | ||
1166 | * connectors where probing live outputs can result in visual distortion drivers | ||
1167 | * should not set the DRM_CONNECTOR_POLL_DISCONNECT flag to avoid this. | ||
1168 | * Connectors which have no flag or only DRM_CONNECTOR_POLL_HPD set are | ||
1169 | * completely ignored by the polling logic. | ||
1170 | * | ||
1171 | * Note that a connector can be both polled and probed from the hotplug handler, | ||
1172 | * in case the hotplug interrupt is known to be unreliable. | ||
1173 | */ | ||
1084 | void drm_kms_helper_poll_init(struct drm_device *dev) | 1174 | void drm_kms_helper_poll_init(struct drm_device *dev) |
1085 | { | 1175 | { |
1086 | INIT_DELAYED_WORK(&dev->mode_config.output_poll_work, output_poll_execute); | 1176 | INIT_DELAYED_WORK(&dev->mode_config.output_poll_work, output_poll_execute); |
@@ -1090,12 +1180,39 @@ void drm_kms_helper_poll_init(struct drm_device *dev) | |||
1090 | } | 1180 | } |
1091 | EXPORT_SYMBOL(drm_kms_helper_poll_init); | 1181 | EXPORT_SYMBOL(drm_kms_helper_poll_init); |
1092 | 1182 | ||
1183 | /** | ||
1184 | * drm_kms_helper_poll_fini - disable output polling and clean it up | ||
1185 | * @dev: drm_device | ||
1186 | */ | ||
1093 | void drm_kms_helper_poll_fini(struct drm_device *dev) | 1187 | void drm_kms_helper_poll_fini(struct drm_device *dev) |
1094 | { | 1188 | { |
1095 | drm_kms_helper_poll_disable(dev); | 1189 | drm_kms_helper_poll_disable(dev); |
1096 | } | 1190 | } |
1097 | EXPORT_SYMBOL(drm_kms_helper_poll_fini); | 1191 | EXPORT_SYMBOL(drm_kms_helper_poll_fini); |
1098 | 1192 | ||
1193 | /** | ||
1194 | * drm_helper_hpd_irq_event - hotplug processing | ||
1195 | * @dev: drm_device | ||
1196 | * | ||
1197 | * Drivers can use this helper function to run a detect cycle on all connectors | ||
1198 | * which have the DRM_CONNECTOR_POLL_HPD flag set in their &polled member. All | ||
1199 | * other connectors are ignored, which is useful to avoid reprobing fixed | ||
1200 | * panels. | ||
1201 | * | ||
1202 | * This helper function is useful for drivers which can't or don't track hotplug | ||
1203 | * interrupts for each connector. | ||
1204 | * | ||
1205 | * Drivers which support hotplug interrupts for each connector individually and | ||
1206 | * which have a more fine-grained detect logic should bypass this code and | ||
1207 | * directly call drm_kms_helper_hotplug_event() in case the connector state | ||
1208 | * changed. | ||
1209 | * | ||
1210 | * This function must be called from process context with no mode | ||
1211 | * setting locks held. | ||
1212 | * | ||
1213 | * Note that a connector can be both polled and probed from the hotplug handler, | ||
1214 | * in case the hotplug interrupt is known to be unreliable. | ||
1215 | */ | ||
1099 | bool drm_helper_hpd_irq_event(struct drm_device *dev) | 1216 | bool drm_helper_hpd_irq_event(struct drm_device *dev) |
1100 | { | 1217 | { |
1101 | struct drm_connector *connector; | 1218 | struct drm_connector *connector; |