Rev 3051 | Rev 3243 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3051 | Rev 3192 | ||
---|---|---|---|
Line 37... | Line 37... | ||
37 | #include |
37 | #include |
38 | #include |
38 | #include |
39 | #include |
39 | #include |
40 | #include |
40 | #include |
Line -... | Line 41... | ||
- | 41 | ||
- | 42 | /** |
|
- | 43 | * drm_helper_move_panel_connectors_to_head() - move panels to the front in the |
|
- | 44 | * connector list |
|
- | 45 | * @dev: drm device to operate on |
|
- | 46 | * |
|
- | 47 | * Some userspace presumes that the first connected connector is the main |
|
- | 48 | * display, where it's supposed to display e.g. the login screen. For |
|
- | 49 | * laptops, this should be the main panel. Use this function to sort all |
|
- | 50 | * (eDP/LVDS) panels to the front of the connector list, instead of |
|
- | 51 | * painstakingly trying to initialize them in the right order. |
|
- | 52 | */ |
|
- | 53 | void drm_helper_move_panel_connectors_to_head(struct drm_device *dev) |
|
- | 54 | { |
|
- | 55 | struct drm_connector *connector, *tmp; |
|
- | 56 | struct list_head panel_list; |
|
- | 57 | ||
- | 58 | INIT_LIST_HEAD(&panel_list); |
|
- | 59 | ||
- | 60 | list_for_each_entry_safe(connector, tmp, |
|
- | 61 | &dev->mode_config.connector_list, head) { |
|
- | 62 | if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS || |
|
- | 63 | connector->connector_type == DRM_MODE_CONNECTOR_eDP) |
|
- | 64 | list_move_tail(&connector->head, &panel_list); |
|
- | 65 | } |
|
- | 66 | ||
- | 67 | list_splice(&panel_list, &dev->mode_config.connector_list); |
|
- | 68 | } |
|
- | 69 | EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head); |
|
41 | 70 | ||
Line 42... | Line 71... | ||
42 | static bool drm_kms_helper_poll = true; |
71 | static bool drm_kms_helper_poll = true; |
43 | 72 | ||
44 | static void drm_mode_validate_flag(struct drm_connector *connector, |
73 | static void drm_mode_validate_flag(struct drm_connector *connector, |
Line 61... | Line 90... | ||
61 | return; |
90 | return; |
62 | } |
91 | } |
Line 63... | Line 92... | ||
63 | 92 | ||
64 | /** |
93 | /** |
65 | * drm_helper_probe_single_connector_modes - get complete set of display modes |
94 | * drm_helper_probe_single_connector_modes - get complete set of display modes |
66 | * @dev: DRM device |
95 | * @connector: connector to probe |
67 | * @maxX: max width for modes |
96 | * @maxX: max width for modes |
68 | * @maxY: max height for modes |
97 | * @maxY: max height for modes |
69 | * |
98 | * |
70 | * LOCKING: |
99 | * LOCKING: |
71 | * Caller must hold mode config lock. |
100 | * Caller must hold mode config lock. |
72 | * |
101 | * |
73 | * Based on @dev's mode_config layout, scan all the connectors and try to detect |
102 | * Based on the helper callbacks implemented by @connector try to detect all |
74 | * modes on them. Modes will first be added to the connector's probed_modes |
103 | * valid modes. Modes will first be added to the connector's probed_modes list, |
75 | * list, then culled (based on validity and the @maxX, @maxY parameters) and |
104 | * then culled (based on validity and the @maxX, @maxY parameters) and put into |
76 | * put into the normal modes list. |
105 | * the normal modes list. |
77 | * |
106 | * |
78 | * Intended to be used either at bootup time or when major configuration |
107 | * Intended to be use as a generic implementation of the ->probe() @connector |
79 | * changes have occurred. |
- | |
80 | * |
108 | * callback for drivers that use the crtc helpers for output mode filtering and |
81 | * FIXME: take into account monitor limits |
109 | * detection. |
82 | * |
110 | * |
83 | * RETURNS: |
111 | * RETURNS: |
84 | * Number of modes found on @connector. |
112 | * Number of modes found on @connector. |
85 | */ |
113 | */ |
Line 323... | Line 351... | ||
323 | drm_encoder_disable(encoder); |
351 | drm_encoder_disable(encoder); |
324 | } |
352 | } |
325 | } |
353 | } |
Line 326... | Line 354... | ||
326 | 354 | ||
327 | /** |
355 | /** |
328 | * drm_crtc_set_mode - set a mode |
356 | * drm_crtc_helper_set_mode - internal helper to set a mode |
329 | * @crtc: CRTC to program |
357 | * @crtc: CRTC to program |
330 | * @mode: mode to use |
358 | * @mode: mode to use |
331 | * @x: width of mode |
359 | * @x: horizontal offset into the surface |
- | 360 | * @y: vertical offset into the surface |
|
332 | * @y: height of mode |
361 | * @old_fb: old framebuffer, for cleanup |
333 | * |
362 | * |
334 | * LOCKING: |
363 | * LOCKING: |
335 | * Caller must hold mode config lock. |
364 | * Caller must hold mode config lock. |
336 | * |
365 | * |
337 | * Try to set @mode on @crtc. Give @crtc and its associated connectors a chance |
366 | * Try to set @mode on @crtc. Give @crtc and its associated connectors a chance |
- | 367 | * to fixup or reject the mode prior to trying to set it. This is an internal |
|
- | 368 | * helper that drivers could e.g. use to update properties that require the |
|
- | 369 | * entire output pipe to be disabled and re-enabled in a new configuration. For |
|
- | 370 | * example for changing whether audio is enabled on a hdmi link or for changing |
|
- | 371 | * panel fitter or dither attributes. It is also called by the |
|
- | 372 | * drm_crtc_helper_set_config() helper function to drive the mode setting |
|
338 | * to fixup or reject the mode prior to trying to set it. |
373 | * sequence. |
339 | * |
374 | * |
340 | * RETURNS: |
375 | * RETURNS: |
341 | * True if the mode was set successfully, or false otherwise. |
376 | * True if the mode was set successfully, or false otherwise. |
342 | */ |
377 | */ |
Line 355... | Line 390... | ||
355 | 390 | ||
356 | crtc->enabled = drm_helper_crtc_in_use(crtc); |
391 | crtc->enabled = drm_helper_crtc_in_use(crtc); |
357 | if (!crtc->enabled) |
392 | if (!crtc->enabled) |
Line 358... | Line -... | ||
358 | return true; |
- | |
359 | - | ||
360 | printf("crtc->enabled\n"); |
393 | return true; |
361 | 394 | ||
362 | adjusted_mode = drm_mode_duplicate(dev, mode); |
395 | adjusted_mode = drm_mode_duplicate(dev, mode); |
Line 363... | Line -... | ||
363 | if (!adjusted_mode) |
- | |
364 | return false; |
- | |
365 | 396 | if (!adjusted_mode) |
|
366 | printf("adjusted_mode\n"); |
397 | return false; |
367 | 398 | ||
368 | saved_hwmode = crtc->hwmode; |
399 | saved_hwmode = crtc->hwmode; |
Line 391... | Line 422... | ||
391 | DRM_DEBUG_KMS("Encoder fixup failed\n"); |
422 | DRM_DEBUG_KMS("Encoder fixup failed\n"); |
392 | goto done; |
423 | goto done; |
393 | } |
424 | } |
394 | } |
425 | } |
Line 395... | Line -... | ||
395 | - | ||
396 | printf("list_for_each_entry\n"); |
- | |
397 | printf("mode_fixup %x\n", crtc_funcs->mode_fixup); |
- | |
398 | 426 | ||
399 | if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) { |
427 | if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) { |
400 | DRM_DEBUG_KMS("CRTC fixup failed\n"); |
428 | DRM_DEBUG_KMS("CRTC fixup failed\n"); |
401 | goto done; |
429 | goto done; |
402 | } |
430 | } |
Line 496... | Line 524... | ||
496 | return 0; |
524 | return 0; |
497 | } |
525 | } |
Line 498... | Line 526... | ||
498 | 526 | ||
499 | /** |
527 | /** |
500 | * drm_crtc_helper_set_config - set a new config from userspace |
- | |
501 | * @crtc: CRTC to setup |
528 | * drm_crtc_helper_set_config - set a new config from userspace |
502 | * @crtc_info: user provided configuration |
- | |
503 | * @new_mode: new mode to set |
- | |
504 | * @connector_set: set of connectors for the new config |
- | |
505 | * @fb: new framebuffer |
529 | * @set: mode set configuration |
506 | * |
530 | * |
507 | * LOCKING: |
531 | * LOCKING: |
508 | * Caller must hold mode config lock. |
532 | * Caller must hold mode config lock. |
509 | * |
533 | * |
- | 534 | * Setup a new configuration, provided by the upper layers (either an ioctl call |
|
- | 535 | * from userspace or internally e.g. from the fbdev suppport code) in @set, and |
|
- | 536 | * enable it. This is the main helper functions for drivers that implement |
|
510 | * Setup a new configuration, provided by the user in @crtc_info, and enable |
537 | * kernel mode setting with the crtc helper functions and the assorted |
511 | * it. |
538 | * ->prepare(), ->modeset() and ->commit() helper callbacks. |
512 | * |
539 | * |
513 | * RETURNS: |
540 | * RETURNS: |
514 | * Zero. (FIXME) |
541 | * Returns 0 on success, -ERRNO on failure. |
515 | */ |
542 | */ |
516 | int drm_crtc_helper_set_config(struct drm_mode_set *set) |
543 | int drm_crtc_helper_set_config(struct drm_mode_set *set) |
517 | { |
544 | { |
518 | struct drm_device *dev; |
545 | struct drm_device *dev; |
Line 805... | Line 832... | ||
805 | dpms = connector->dpms; |
832 | dpms = connector->dpms; |
806 | return dpms; |
833 | return dpms; |
807 | } |
834 | } |
Line 808... | Line 835... | ||
808 | 835 | ||
809 | /** |
836 | /** |
810 | * drm_helper_connector_dpms |
837 | * drm_helper_connector_dpms() - connector dpms helper implementation |
811 | * @connector affected connector |
838 | * @connector: affected connector |
812 | * @mode DPMS mode |
839 | * @mode: DPMS mode |
- | 840 | * |
|
813 | * |
841 | * This is the main helper function provided by the crtc helper framework for |
814 | * Calls the low-level connector DPMS function, then |
842 | * implementing the DPMS connector attribute. It computes the new desired DPMS |
- | 843 | * state for all encoders and crtcs in the output mesh and calls the ->dpms() |
|
815 | * calls appropriate encoder and crtc DPMS functions as well |
844 | * callback provided by the driver appropriately. |
816 | */ |
845 | */ |
817 | void drm_helper_connector_dpms(struct drm_connector *connector, int mode) |
846 | void drm_helper_connector_dpms(struct drm_connector *connector, int mode) |
818 | { |
847 | { |
819 | struct drm_encoder *encoder = connector->encoder; |
848 | struct drm_encoder *encoder = connector->encoder; |
Line 940... | Line 969... | ||
940 | return; |
969 | return; |
Line 941... | Line 970... | ||
941 | 970 | ||
942 | mutex_lock(&dev->mode_config.mutex); |
971 | mutex_lock(&dev->mode_config.mutex); |
Line 943... | Line -... | ||
943 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
- | |
944 | 972 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
|
945 | /* if this is HPD or polled don't check it - |
973 | |
- | 974 | /* Ignore forced connectors. */ |
|
- | 975 | if (connector->force) |
|
- | 976 | continue; |
|
- | 977 | ||
- | 978 | /* Ignore HPD capable connectors and connectors where we don't |
|
946 | TV out for instance */ |
979 | * want any hotplug detection at all for polling. */ |
Line 947... | Line -... | ||
947 | if (!connector->polled) |
- | |
948 | continue; |
980 | if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD) |
Line 949... | Line 981... | ||
949 | 981 | continue; |
|
950 | else if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT)) |
982 | |
951 | repoll = true; |
983 | repoll = true; |
952 | 984 | ||
953 | old_status = connector->status; |
985 | old_status = connector->status; |
954 | /* if we are connected and don't want to poll for disconnect |
- | |
955 | skip it */ |
986 | /* if we are connected and don't want to poll for disconnect |
Line 956... | Line 987... | ||
956 | if (old_status == connector_status_connected && |
987 | skip it */ |
957 | !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT) && |
988 | if (old_status == connector_status_connected && |
958 | !(connector->polled & DRM_CONNECTOR_POLL_HPD)) |
989 | !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT)) |
Line 967... | Line 998... | ||
967 | changed = true; |
998 | changed = true; |
968 | } |
999 | } |
Line 969... | Line 1000... | ||
969 | 1000 | ||
Line 970... | Line 1001... | ||
970 | mutex_unlock(&dev->mode_config.mutex); |
1001 | mutex_unlock(&dev->mode_config.mutex); |
971 | - | ||
972 | if (changed) { |
1002 | |
973 | /* send a uevent + call fbdev */ |
- | |
974 | drm_sysfs_hotplug_event(dev); |
- | |
975 | if (dev->mode_config.funcs->output_poll_changed) |
- | |
Line 976... | Line 1003... | ||
976 | dev->mode_config.funcs->output_poll_changed(dev); |
1003 | if (changed) |
977 | } |
1004 | drm_kms_helper_hotplug_event(dev); |
978 | 1005 | ||
Line 995... | Line 1022... | ||
995 | 1022 | ||
996 | if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll) |
1023 | if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll) |
Line 997... | Line 1024... | ||
997 | return; |
1024 | return; |
998 | 1025 | ||
- | 1026 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
|
999 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
1027 | if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | |
1000 | if (connector->polled) |
1028 | DRM_CONNECTOR_POLL_DISCONNECT)) |
Line 1001... | Line 1029... | ||
1001 | poll = true; |
1029 | poll = true; |
1002 | } |
1030 | } |
Line 1021... | Line 1049... | ||
1021 | } |
1049 | } |
1022 | EXPORT_SYMBOL(drm_kms_helper_poll_fini); |
1050 | EXPORT_SYMBOL(drm_kms_helper_poll_fini); |
Line 1023... | Line 1051... | ||
1023 | 1051 | ||
1024 | void drm_helper_hpd_irq_event(struct drm_device *dev) |
1052 | void drm_helper_hpd_irq_event(struct drm_device *dev) |
- | 1053 | { |
|
- | 1054 | struct drm_connector *connector; |
|
- | 1055 | enum drm_connector_status old_status; |
|
- | 1056 | bool changed = false; |
|
1025 | { |
1057 | |
1026 | if (!dev->mode_config.poll_enabled) |
1058 | if (!dev->mode_config.poll_enabled) |
Line -... | Line 1059... | ||
- | 1059 | return; |
|
- | 1060 | ||
- | 1061 | mutex_lock(&dev->mode_config.mutex); |
|
1027 | return; |
1062 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
- | 1063 | ||
- | 1064 | /* Only handle HPD capable connectors. */ |
|
- | 1065 | if (!(connector->polled & DRM_CONNECTOR_POLL_HPD)) |
|
- | 1066 | continue; |
|
- | 1067 | ||
1028 | 1068 | old_status = connector->status; |
|
- | 1069 | ||
- | 1070 | connector->status = connector->funcs->detect(connector, false); |
|
- | 1071 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n", |
|
- | 1072 | connector->base.id, |
|
1029 | /* kill timer and schedule immediate execution, this doesn't block */ |
1073 | drm_get_connector_name(connector), |
- | 1074 | old_status, connector->status); |
|
- | 1075 | if (old_status != connector->status) |
|
- | 1076 | changed = true; |
|
1030 | cancel_delayed_work(&dev->mode_config.output_poll_work); |
1077 | } |
- | 1078 | ||
- | 1079 | mutex_unlock(&dev->mode_config.mutex); |
|
- | 1080 | ||
1031 | if (drm_kms_helper_poll) |
1081 | if (changed) |
1032 | schedule_delayed_work(&dev->mode_config.output_poll_work, 0); |
1082 | drm_kms_helper_hotplug_event(dev); |
Line 1033... | Line 1083... | ||
1033 | } |
1083 | } |