drm_simple_kms_helper.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * Copyright (C) 2016 Noralf Trønnes
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. */
  9. #include <drm/drmP.h>
  10. #include <drm/drm_atomic.h>
  11. #include <drm/drm_atomic_helper.h>
  12. #include <drm/drm_crtc_helper.h>
  13. #include <drm/drm_plane_helper.h>
  14. #include <drm/drm_simple_kms_helper.h>
  15. #include <linux/slab.h>
  16. /**
  17. * DOC: overview
  18. *
  19. * This helper library provides helpers for drivers for simple display
  20. * hardware.
  21. *
  22. * drm_simple_display_pipe_init() initializes a simple display pipeline
  23. * which has only one full-screen scanout buffer feeding one output. The
  24. * pipeline is represented by struct &drm_simple_display_pipe and binds
  25. * together &drm_plane, &drm_crtc and &drm_encoder structures into one fixed
  26. * entity. Some flexibility for code reuse is provided through a separately
  27. * allocated &drm_connector object and supporting optional &drm_bridge
  28. * encoder drivers.
  29. */
  30. static const struct drm_encoder_funcs drm_simple_kms_encoder_funcs = {
  31. .destroy = drm_encoder_cleanup,
  32. };
  33. static void drm_simple_kms_crtc_enable(struct drm_crtc *crtc)
  34. {
  35. struct drm_simple_display_pipe *pipe;
  36. pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
  37. if (!pipe->funcs || !pipe->funcs->enable)
  38. return;
  39. pipe->funcs->enable(pipe, crtc->state);
  40. }
  41. static void drm_simple_kms_crtc_disable(struct drm_crtc *crtc)
  42. {
  43. struct drm_simple_display_pipe *pipe;
  44. pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
  45. if (!pipe->funcs || !pipe->funcs->disable)
  46. return;
  47. pipe->funcs->disable(pipe);
  48. }
  49. static const struct drm_crtc_helper_funcs drm_simple_kms_crtc_helper_funcs = {
  50. .disable = drm_simple_kms_crtc_disable,
  51. .enable = drm_simple_kms_crtc_enable,
  52. };
  53. static const struct drm_crtc_funcs drm_simple_kms_crtc_funcs = {
  54. .reset = drm_atomic_helper_crtc_reset,
  55. .destroy = drm_crtc_cleanup,
  56. .set_config = drm_atomic_helper_set_config,
  57. .page_flip = drm_atomic_helper_page_flip,
  58. .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
  59. .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
  60. };
  61. static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane,
  62. struct drm_plane_state *plane_state)
  63. {
  64. struct drm_rect src = {
  65. .x1 = plane_state->src_x,
  66. .y1 = plane_state->src_y,
  67. .x2 = plane_state->src_x + plane_state->src_w,
  68. .y2 = plane_state->src_y + plane_state->src_h,
  69. };
  70. struct drm_rect dest = {
  71. .x1 = plane_state->crtc_x,
  72. .y1 = plane_state->crtc_y,
  73. .x2 = plane_state->crtc_x + plane_state->crtc_w,
  74. .y2 = plane_state->crtc_y + plane_state->crtc_h,
  75. };
  76. struct drm_rect clip = { 0 };
  77. struct drm_simple_display_pipe *pipe;
  78. struct drm_crtc_state *crtc_state;
  79. bool visible;
  80. int ret;
  81. pipe = container_of(plane, struct drm_simple_display_pipe, plane);
  82. crtc_state = drm_atomic_get_existing_crtc_state(plane_state->state,
  83. &pipe->crtc);
  84. if (crtc_state->enable != !!plane_state->crtc)
  85. return -EINVAL; /* plane must match crtc enable state */
  86. if (!crtc_state->enable)
  87. return 0; /* nothing to check when disabling or disabled */
  88. clip.x2 = crtc_state->adjusted_mode.hdisplay;
  89. clip.y2 = crtc_state->adjusted_mode.vdisplay;
  90. ret = drm_plane_helper_check_update(plane, &pipe->crtc,
  91. plane_state->fb,
  92. &src, &dest, &clip,
  93. plane_state->rotation,
  94. DRM_PLANE_HELPER_NO_SCALING,
  95. DRM_PLANE_HELPER_NO_SCALING,
  96. false, true, &visible);
  97. if (ret)
  98. return ret;
  99. if (!visible)
  100. return -EINVAL;
  101. if (!pipe->funcs || !pipe->funcs->check)
  102. return 0;
  103. return pipe->funcs->check(pipe, plane_state, crtc_state);
  104. }
  105. static void drm_simple_kms_plane_atomic_update(struct drm_plane *plane,
  106. struct drm_plane_state *pstate)
  107. {
  108. struct drm_simple_display_pipe *pipe;
  109. pipe = container_of(plane, struct drm_simple_display_pipe, plane);
  110. if (!pipe->funcs || !pipe->funcs->update)
  111. return;
  112. pipe->funcs->update(pipe, pstate);
  113. }
  114. static const struct drm_plane_helper_funcs drm_simple_kms_plane_helper_funcs = {
  115. .atomic_check = drm_simple_kms_plane_atomic_check,
  116. .atomic_update = drm_simple_kms_plane_atomic_update,
  117. };
  118. static const struct drm_plane_funcs drm_simple_kms_plane_funcs = {
  119. .update_plane = drm_atomic_helper_update_plane,
  120. .disable_plane = drm_atomic_helper_disable_plane,
  121. .destroy = drm_plane_cleanup,
  122. .reset = drm_atomic_helper_plane_reset,
  123. .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
  124. .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
  125. };
  126. /**
  127. * drm_simple_display_pipe_init - Initialize a simple display pipeline
  128. * @dev: DRM device
  129. * @pipe: simple display pipe object to initialize
  130. * @funcs: callbacks for the display pipe (optional)
  131. * @formats: array of supported formats (%DRM_FORMAT_*)
  132. * @format_count: number of elements in @formats
  133. * @connector: connector to attach and register
  134. *
  135. * Sets up a display pipeline which consist of a really simple
  136. * plane-crtc-encoder pipe coupled with the provided connector.
  137. * Teardown of a simple display pipe is all handled automatically by the drm
  138. * core through calling drm_mode_config_cleanup(). Drivers afterwards need to
  139. * release the memory for the structure themselves.
  140. *
  141. * Returns:
  142. * Zero on success, negative error code on failure.
  143. */
  144. int drm_simple_display_pipe_init(struct drm_device *dev,
  145. struct drm_simple_display_pipe *pipe,
  146. const struct drm_simple_display_pipe_funcs *funcs,
  147. const uint32_t *formats, unsigned int format_count,
  148. struct drm_connector *connector)
  149. {
  150. struct drm_encoder *encoder = &pipe->encoder;
  151. struct drm_plane *plane = &pipe->plane;
  152. struct drm_crtc *crtc = &pipe->crtc;
  153. int ret;
  154. pipe->connector = connector;
  155. pipe->funcs = funcs;
  156. drm_plane_helper_add(plane, &drm_simple_kms_plane_helper_funcs);
  157. ret = drm_universal_plane_init(dev, plane, 0,
  158. &drm_simple_kms_plane_funcs,
  159. formats, format_count,
  160. DRM_PLANE_TYPE_PRIMARY, NULL);
  161. if (ret)
  162. return ret;
  163. drm_crtc_helper_add(crtc, &drm_simple_kms_crtc_helper_funcs);
  164. ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL,
  165. &drm_simple_kms_crtc_funcs, NULL);
  166. if (ret)
  167. return ret;
  168. encoder->possible_crtcs = 1 << drm_crtc_index(crtc);
  169. ret = drm_encoder_init(dev, encoder, &drm_simple_kms_encoder_funcs,
  170. DRM_MODE_ENCODER_NONE, NULL);
  171. if (ret)
  172. return ret;
  173. return drm_mode_connector_attach_encoder(connector, encoder);
  174. }
  175. EXPORT_SYMBOL(drm_simple_display_pipe_init);
  176. MODULE_LICENSE("GPL");