drm_modeset_helper.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /*
  2. * Copyright (c) 2016 Intel Corporation
  3. *
  4. * Permission to use, copy, modify, distribute, and sell this software and its
  5. * documentation for any purpose is hereby granted without fee, provided that
  6. * the above copyright notice appear in all copies and that both that copyright
  7. * notice and this permission notice appear in supporting documentation, and
  8. * that the name of the copyright holders not be used in advertising or
  9. * publicity pertaining to distribution of the software without specific,
  10. * written prior permission. The copyright holders make no representations
  11. * about the suitability of this software for any purpose. It is provided "as
  12. * is" without express or implied warranty.
  13. *
  14. * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15. * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  16. * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17. * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18. * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  19. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  20. * OF THIS SOFTWARE.
  21. */
  22. #include <drm/drm_atomic_helper.h>
  23. #include <drm/drm_fb_helper.h>
  24. #include <drm/drm_fourcc.h>
  25. #include <drm/drm_framebuffer.h>
  26. #include <drm/drm_modeset_helper.h>
  27. #include <drm/drm_plane_helper.h>
  28. #include <drm/drm_print.h>
  29. #include <drm/drm_probe_helper.h>
  30. /**
  31. * DOC: aux kms helpers
  32. *
  33. * This helper library contains various one-off functions which don't really fit
  34. * anywhere else in the DRM modeset helper library.
  35. */
  36. /**
  37. * drm_helper_move_panel_connectors_to_head() - move panels to the front in the
  38. * connector list
  39. * @dev: drm device to operate on
  40. *
  41. * Some userspace presumes that the first connected connector is the main
  42. * display, where it's supposed to display e.g. the login screen. For
  43. * laptops, this should be the main panel. Use this function to sort all
  44. * (eDP/LVDS/DSI) panels to the front of the connector list, instead of
  45. * painstakingly trying to initialize them in the right order.
  46. */
  47. void drm_helper_move_panel_connectors_to_head(struct drm_device *dev)
  48. {
  49. struct drm_connector *connector, *tmp;
  50. struct list_head panel_list;
  51. INIT_LIST_HEAD(&panel_list);
  52. spin_lock_irq(&dev->mode_config.connector_list_lock);
  53. list_for_each_entry_safe(connector, tmp,
  54. &dev->mode_config.connector_list, head) {
  55. if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
  56. connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
  57. connector->connector_type == DRM_MODE_CONNECTOR_DSI)
  58. list_move_tail(&connector->head, &panel_list);
  59. }
  60. list_splice(&panel_list, &dev->mode_config.connector_list);
  61. spin_unlock_irq(&dev->mode_config.connector_list_lock);
  62. }
  63. EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head);
  64. /**
  65. * drm_helper_mode_fill_fb_struct - fill out framebuffer metadata
  66. * @dev: DRM device
  67. * @fb: drm_framebuffer object to fill out
  68. * @mode_cmd: metadata from the userspace fb creation request
  69. *
  70. * This helper can be used in a drivers fb_create callback to pre-fill the fb's
  71. * metadata fields.
  72. */
  73. void drm_helper_mode_fill_fb_struct(struct drm_device *dev,
  74. struct drm_framebuffer *fb,
  75. const struct drm_mode_fb_cmd2 *mode_cmd)
  76. {
  77. int i;
  78. fb->dev = dev;
  79. fb->format = drm_get_format_info(dev, mode_cmd);
  80. fb->width = mode_cmd->width;
  81. fb->height = mode_cmd->height;
  82. for (i = 0; i < 4; i++) {
  83. fb->pitches[i] = mode_cmd->pitches[i];
  84. fb->offsets[i] = mode_cmd->offsets[i];
  85. }
  86. fb->modifier = mode_cmd->modifier[0];
  87. fb->flags = mode_cmd->flags;
  88. }
  89. EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
  90. /*
  91. * This is the minimal list of formats that seem to be safe for modeset use
  92. * with all current DRM drivers. Most hardware can actually support more
  93. * formats than this and drivers may specify a more accurate list when
  94. * creating the primary plane.
  95. */
  96. static const uint32_t safe_modeset_formats[] = {
  97. DRM_FORMAT_XRGB8888,
  98. DRM_FORMAT_ARGB8888,
  99. };
  100. static const struct drm_plane_funcs primary_plane_funcs = {
  101. DRM_PLANE_NON_ATOMIC_FUNCS,
  102. };
  103. /**
  104. * drm_crtc_init - Legacy CRTC initialization function
  105. * @dev: DRM device
  106. * @crtc: CRTC object to init
  107. * @funcs: callbacks for the new CRTC
  108. *
  109. * Initialize a CRTC object with a default helper-provided primary plane and no
  110. * cursor plane.
  111. *
  112. * Note that we make some assumptions about hardware limitations that may not be
  113. * true for all hardware:
  114. *
  115. * 1. Primary plane cannot be repositioned.
  116. * 2. Primary plane cannot be scaled.
  117. * 3. Primary plane must cover the entire CRTC.
  118. * 4. Subpixel positioning is not supported.
  119. * 5. The primary plane must always be on if the CRTC is enabled.
  120. *
  121. * This is purely a backwards compatibility helper for old drivers. Drivers
  122. * should instead implement their own primary plane. Atomic drivers must do so.
  123. * Drivers with the above hardware restriction can look into using &struct
  124. * drm_simple_display_pipe, which encapsulates the above limitations into a nice
  125. * interface.
  126. *
  127. * Returns:
  128. * Zero on success, error code on failure.
  129. */
  130. int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
  131. const struct drm_crtc_funcs *funcs)
  132. {
  133. struct drm_plane *primary;
  134. int ret;
  135. /* possible_crtc's will be filled in later by crtc_init */
  136. primary = __drm_universal_plane_alloc(dev, sizeof(*primary), 0, 0,
  137. &primary_plane_funcs,
  138. safe_modeset_formats,
  139. ARRAY_SIZE(safe_modeset_formats),
  140. NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
  141. if (IS_ERR(primary))
  142. return PTR_ERR(primary);
  143. /*
  144. * Remove the format_default field from drm_plane when dropping
  145. * this helper.
  146. */
  147. primary->format_default = true;
  148. ret = drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs, NULL);
  149. if (ret)
  150. goto err_drm_plane_cleanup;
  151. return 0;
  152. err_drm_plane_cleanup:
  153. drm_plane_cleanup(primary);
  154. kfree(primary);
  155. return ret;
  156. }
  157. EXPORT_SYMBOL(drm_crtc_init);
  158. /**
  159. * drm_mode_config_helper_suspend - Modeset suspend helper
  160. * @dev: DRM device
  161. *
  162. * This helper function takes care of suspending the modeset side. It disables
  163. * output polling if initialized, suspends fbdev if used and finally calls
  164. * drm_atomic_helper_suspend().
  165. * If suspending fails, fbdev and polling is re-enabled.
  166. *
  167. * Returns:
  168. * Zero on success, negative error code on error.
  169. *
  170. * See also:
  171. * drm_kms_helper_poll_disable() and drm_fb_helper_set_suspend_unlocked().
  172. */
  173. int drm_mode_config_helper_suspend(struct drm_device *dev)
  174. {
  175. struct drm_atomic_state *state;
  176. if (!dev)
  177. return 0;
  178. drm_kms_helper_poll_disable(dev);
  179. drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 1);
  180. state = drm_atomic_helper_suspend(dev);
  181. if (IS_ERR(state)) {
  182. drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 0);
  183. drm_kms_helper_poll_enable(dev);
  184. return PTR_ERR(state);
  185. }
  186. dev->mode_config.suspend_state = state;
  187. return 0;
  188. }
  189. EXPORT_SYMBOL(drm_mode_config_helper_suspend);
  190. /**
  191. * drm_mode_config_helper_resume - Modeset resume helper
  192. * @dev: DRM device
  193. *
  194. * This helper function takes care of resuming the modeset side. It calls
  195. * drm_atomic_helper_resume(), resumes fbdev if used and enables output polling
  196. * if initiaized.
  197. *
  198. * Returns:
  199. * Zero on success, negative error code on error.
  200. *
  201. * See also:
  202. * drm_fb_helper_set_suspend_unlocked() and drm_kms_helper_poll_enable().
  203. */
  204. int drm_mode_config_helper_resume(struct drm_device *dev)
  205. {
  206. int ret;
  207. if (!dev)
  208. return 0;
  209. if (WARN_ON(!dev->mode_config.suspend_state))
  210. return -EINVAL;
  211. ret = drm_atomic_helper_resume(dev, dev->mode_config.suspend_state);
  212. if (ret)
  213. DRM_ERROR("Failed to resume (%d)\n", ret);
  214. dev->mode_config.suspend_state = NULL;
  215. drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 0);
  216. drm_kms_helper_poll_enable(dev);
  217. return ret;
  218. }
  219. EXPORT_SYMBOL(drm_mode_config_helper_resume);