drm_modeset_helper.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  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_modeset_helper.h>
  26. #include <drm/drm_plane_helper.h>
  27. #include <drm/drm_print.h>
  28. #include <drm/drm_probe_helper.h>
  29. /**
  30. * DOC: aux kms helpers
  31. *
  32. * This helper library contains various one-off functions which don't really fit
  33. * anywhere else in the DRM modeset helper library.
  34. */
  35. /**
  36. * drm_helper_move_panel_connectors_to_head() - move panels to the front in the
  37. * connector list
  38. * @dev: drm device to operate on
  39. *
  40. * Some userspace presumes that the first connected connector is the main
  41. * display, where it's supposed to display e.g. the login screen. For
  42. * laptops, this should be the main panel. Use this function to sort all
  43. * (eDP/LVDS/DSI) panels to the front of the connector list, instead of
  44. * painstakingly trying to initialize them in the right order.
  45. */
  46. void drm_helper_move_panel_connectors_to_head(struct drm_device *dev)
  47. {
  48. struct drm_connector *connector, *tmp;
  49. struct list_head panel_list;
  50. INIT_LIST_HEAD(&panel_list);
  51. spin_lock_irq(&dev->mode_config.connector_list_lock);
  52. list_for_each_entry_safe(connector, tmp,
  53. &dev->mode_config.connector_list, head) {
  54. if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
  55. connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
  56. connector->connector_type == DRM_MODE_CONNECTOR_DSI)
  57. list_move_tail(&connector->head, &panel_list);
  58. }
  59. list_splice(&panel_list, &dev->mode_config.connector_list);
  60. spin_unlock_irq(&dev->mode_config.connector_list_lock);
  61. }
  62. EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head);
  63. /**
  64. * drm_helper_mode_fill_fb_struct - fill out framebuffer metadata
  65. * @dev: DRM device
  66. * @fb: drm_framebuffer object to fill out
  67. * @mode_cmd: metadata from the userspace fb creation request
  68. *
  69. * This helper can be used in a drivers fb_create callback to pre-fill the fb's
  70. * metadata fields.
  71. */
  72. void drm_helper_mode_fill_fb_struct(struct drm_device *dev,
  73. struct drm_framebuffer *fb,
  74. const struct drm_mode_fb_cmd2 *mode_cmd)
  75. {
  76. int i;
  77. fb->dev = dev;
  78. fb->format = drm_get_format_info(dev, mode_cmd);
  79. fb->width = mode_cmd->width;
  80. fb->height = mode_cmd->height;
  81. for (i = 0; i < 4; i++) {
  82. fb->pitches[i] = mode_cmd->pitches[i];
  83. fb->offsets[i] = mode_cmd->offsets[i];
  84. }
  85. fb->modifier = mode_cmd->modifier[0];
  86. fb->flags = mode_cmd->flags;
  87. }
  88. EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
  89. /*
  90. * This is the minimal list of formats that seem to be safe for modeset use
  91. * with all current DRM drivers. Most hardware can actually support more
  92. * formats than this and drivers may specify a more accurate list when
  93. * creating the primary plane. However drivers that still call
  94. * drm_plane_init() will use this minimal format list as the default.
  95. */
  96. static const uint32_t safe_modeset_formats[] = {
  97. DRM_FORMAT_XRGB8888,
  98. DRM_FORMAT_ARGB8888,
  99. };
  100. static struct drm_plane *create_primary_plane(struct drm_device *dev)
  101. {
  102. struct drm_plane *primary;
  103. int ret;
  104. primary = kzalloc(sizeof(*primary), GFP_KERNEL);
  105. if (primary == NULL) {
  106. DRM_DEBUG_KMS("Failed to allocate primary plane\n");
  107. return NULL;
  108. }
  109. /*
  110. * Remove the format_default field from drm_plane when dropping
  111. * this helper.
  112. */
  113. primary->format_default = true;
  114. /* possible_crtc's will be filled in later by crtc_init */
  115. ret = drm_universal_plane_init(dev, primary, 0,
  116. &drm_primary_helper_funcs,
  117. safe_modeset_formats,
  118. ARRAY_SIZE(safe_modeset_formats),
  119. NULL,
  120. DRM_PLANE_TYPE_PRIMARY, NULL);
  121. if (ret) {
  122. kfree(primary);
  123. primary = NULL;
  124. }
  125. return primary;
  126. }
  127. /**
  128. * drm_crtc_init - Legacy CRTC initialization function
  129. * @dev: DRM device
  130. * @crtc: CRTC object to init
  131. * @funcs: callbacks for the new CRTC
  132. *
  133. * Initialize a CRTC object with a default helper-provided primary plane and no
  134. * cursor plane.
  135. *
  136. * Note that we make some assumptions about hardware limitations that may not be
  137. * true for all hardware:
  138. *
  139. * 1. Primary plane cannot be repositioned.
  140. * 2. Primary plane cannot be scaled.
  141. * 3. Primary plane must cover the entire CRTC.
  142. * 4. Subpixel positioning is not supported.
  143. * 5. The primary plane must always be on if the CRTC is enabled.
  144. *
  145. * This is purely a backwards compatibility helper for old drivers. Drivers
  146. * should instead implement their own primary plane. Atomic drivers must do so.
  147. * Drivers with the above hardware restriction can look into using &struct
  148. * drm_simple_display_pipe, which encapsulates the above limitations into a nice
  149. * interface.
  150. *
  151. * Returns:
  152. * Zero on success, error code on failure.
  153. */
  154. int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
  155. const struct drm_crtc_funcs *funcs)
  156. {
  157. struct drm_plane *primary;
  158. primary = create_primary_plane(dev);
  159. return drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs,
  160. NULL);
  161. }
  162. EXPORT_SYMBOL(drm_crtc_init);
  163. /**
  164. * drm_mode_config_helper_suspend - Modeset suspend helper
  165. * @dev: DRM device
  166. *
  167. * This helper function takes care of suspending the modeset side. It disables
  168. * output polling if initialized, suspends fbdev if used and finally calls
  169. * drm_atomic_helper_suspend().
  170. * If suspending fails, fbdev and polling is re-enabled.
  171. *
  172. * Returns:
  173. * Zero on success, negative error code on error.
  174. *
  175. * See also:
  176. * drm_kms_helper_poll_disable() and drm_fb_helper_set_suspend_unlocked().
  177. */
  178. int drm_mode_config_helper_suspend(struct drm_device *dev)
  179. {
  180. struct drm_atomic_state *state;
  181. if (!dev)
  182. return 0;
  183. drm_kms_helper_poll_disable(dev);
  184. drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 1);
  185. state = drm_atomic_helper_suspend(dev);
  186. if (IS_ERR(state)) {
  187. drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 0);
  188. drm_kms_helper_poll_enable(dev);
  189. return PTR_ERR(state);
  190. }
  191. dev->mode_config.suspend_state = state;
  192. return 0;
  193. }
  194. EXPORT_SYMBOL(drm_mode_config_helper_suspend);
  195. /**
  196. * drm_mode_config_helper_resume - Modeset resume helper
  197. * @dev: DRM device
  198. *
  199. * This helper function takes care of resuming the modeset side. It calls
  200. * drm_atomic_helper_resume(), resumes fbdev if used and enables output polling
  201. * if initiaized.
  202. *
  203. * Returns:
  204. * Zero on success, negative error code on error.
  205. *
  206. * See also:
  207. * drm_fb_helper_set_suspend_unlocked() and drm_kms_helper_poll_enable().
  208. */
  209. int drm_mode_config_helper_resume(struct drm_device *dev)
  210. {
  211. int ret;
  212. if (!dev)
  213. return 0;
  214. if (WARN_ON(!dev->mode_config.suspend_state))
  215. return -EINVAL;
  216. ret = drm_atomic_helper_resume(dev, dev->mode_config.suspend_state);
  217. if (ret)
  218. DRM_ERROR("Failed to resume (%d)\n", ret);
  219. dev->mode_config.suspend_state = NULL;
  220. drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 0);
  221. drm_kms_helper_poll_enable(dev);
  222. return ret;
  223. }
  224. EXPORT_SYMBOL(drm_mode_config_helper_resume);