drm_simple_kms_helper.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2016 Noralf Trønnes
  4. */
  5. #include <linux/module.h>
  6. #include <linux/slab.h>
  7. #include <drm/drm_atomic.h>
  8. #include <drm/drm_atomic_helper.h>
  9. #include <drm/drm_bridge.h>
  10. #include <drm/drm_drv.h>
  11. #include <drm/drm_gem_atomic_helper.h>
  12. #include <drm/drm_managed.h>
  13. #include <drm/drm_probe_helper.h>
  14. #include <drm/drm_simple_kms_helper.h>
  15. /**
  16. * DOC: overview
  17. *
  18. * This helper library provides helpers for drivers for simple display
  19. * hardware.
  20. *
  21. * drm_simple_display_pipe_init() initializes a simple display pipeline
  22. * which has only one full-screen scanout buffer feeding one output. The
  23. * pipeline is represented by &struct drm_simple_display_pipe and binds
  24. * together &drm_plane, &drm_crtc and &drm_encoder structures into one fixed
  25. * entity. Some flexibility for code reuse is provided through a separately
  26. * allocated &drm_connector object and supporting optional &drm_bridge
  27. * encoder drivers.
  28. *
  29. * Many drivers require only a very simple encoder that fulfills the minimum
  30. * requirements of the display pipeline and does not add additional
  31. * functionality. The function drm_simple_encoder_init() provides an
  32. * implementation of such an encoder.
  33. */
  34. static const struct drm_encoder_funcs drm_simple_encoder_funcs_cleanup = {
  35. .destroy = drm_encoder_cleanup,
  36. };
  37. /**
  38. * drm_simple_encoder_init - Initialize a preallocated encoder with
  39. * basic functionality.
  40. * @dev: drm device
  41. * @encoder: the encoder to initialize
  42. * @encoder_type: user visible type of the encoder
  43. *
  44. * Initialises a preallocated encoder that has no further functionality.
  45. * Settings for possible CRTC and clones are left to their initial values.
  46. * The encoder will be cleaned up automatically as part of the mode-setting
  47. * cleanup.
  48. *
  49. * The caller of drm_simple_encoder_init() is responsible for freeing
  50. * the encoder's memory after the encoder has been cleaned up. At the
  51. * moment this only works reliably if the encoder data structure is
  52. * stored in the device structure. Free the encoder's memory as part of
  53. * the device release function.
  54. *
  55. * Note: consider using drmm_simple_encoder_alloc() instead of
  56. * drm_simple_encoder_init() to let the DRM managed resource infrastructure
  57. * take care of cleanup and deallocation.
  58. *
  59. * Returns:
  60. * Zero on success, error code on failure.
  61. */
  62. int drm_simple_encoder_init(struct drm_device *dev,
  63. struct drm_encoder *encoder,
  64. int encoder_type)
  65. {
  66. return drm_encoder_init(dev, encoder,
  67. &drm_simple_encoder_funcs_cleanup,
  68. encoder_type, NULL);
  69. }
  70. EXPORT_SYMBOL(drm_simple_encoder_init);
  71. void *__drmm_simple_encoder_alloc(struct drm_device *dev, size_t size,
  72. size_t offset, int encoder_type)
  73. {
  74. return __drmm_encoder_alloc(dev, size, offset, NULL, encoder_type,
  75. NULL);
  76. }
  77. EXPORT_SYMBOL(__drmm_simple_encoder_alloc);
  78. static enum drm_mode_status
  79. drm_simple_kms_crtc_mode_valid(struct drm_crtc *crtc,
  80. const struct drm_display_mode *mode)
  81. {
  82. struct drm_simple_display_pipe *pipe;
  83. pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
  84. if (!pipe->funcs || !pipe->funcs->mode_valid)
  85. /* Anything goes */
  86. return MODE_OK;
  87. return pipe->funcs->mode_valid(pipe, mode);
  88. }
  89. static int drm_simple_kms_crtc_check(struct drm_crtc *crtc,
  90. struct drm_atomic_state *state)
  91. {
  92. struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
  93. int ret;
  94. if (!crtc_state->enable)
  95. goto out;
  96. ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state);
  97. if (ret)
  98. return ret;
  99. out:
  100. return drm_atomic_add_affected_planes(state, crtc);
  101. }
  102. static void drm_simple_kms_crtc_enable(struct drm_crtc *crtc,
  103. struct drm_atomic_state *state)
  104. {
  105. struct drm_plane *plane;
  106. struct drm_simple_display_pipe *pipe;
  107. pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
  108. if (!pipe->funcs || !pipe->funcs->enable)
  109. return;
  110. plane = &pipe->plane;
  111. pipe->funcs->enable(pipe, crtc->state, plane->state);
  112. }
  113. static void drm_simple_kms_crtc_disable(struct drm_crtc *crtc,
  114. struct drm_atomic_state *state)
  115. {
  116. struct drm_simple_display_pipe *pipe;
  117. pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
  118. if (!pipe->funcs || !pipe->funcs->disable)
  119. return;
  120. pipe->funcs->disable(pipe);
  121. }
  122. static const struct drm_crtc_helper_funcs drm_simple_kms_crtc_helper_funcs = {
  123. .mode_valid = drm_simple_kms_crtc_mode_valid,
  124. .atomic_check = drm_simple_kms_crtc_check,
  125. .atomic_enable = drm_simple_kms_crtc_enable,
  126. .atomic_disable = drm_simple_kms_crtc_disable,
  127. };
  128. static void drm_simple_kms_crtc_reset(struct drm_crtc *crtc)
  129. {
  130. struct drm_simple_display_pipe *pipe;
  131. pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
  132. if (!pipe->funcs || !pipe->funcs->reset_crtc)
  133. return drm_atomic_helper_crtc_reset(crtc);
  134. return pipe->funcs->reset_crtc(pipe);
  135. }
  136. static struct drm_crtc_state *drm_simple_kms_crtc_duplicate_state(struct drm_crtc *crtc)
  137. {
  138. struct drm_simple_display_pipe *pipe;
  139. pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
  140. if (!pipe->funcs || !pipe->funcs->duplicate_crtc_state)
  141. return drm_atomic_helper_crtc_duplicate_state(crtc);
  142. return pipe->funcs->duplicate_crtc_state(pipe);
  143. }
  144. static void drm_simple_kms_crtc_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state)
  145. {
  146. struct drm_simple_display_pipe *pipe;
  147. pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
  148. if (!pipe->funcs || !pipe->funcs->destroy_crtc_state)
  149. drm_atomic_helper_crtc_destroy_state(crtc, state);
  150. else
  151. pipe->funcs->destroy_crtc_state(pipe, state);
  152. }
  153. static int drm_simple_kms_crtc_enable_vblank(struct drm_crtc *crtc)
  154. {
  155. struct drm_simple_display_pipe *pipe;
  156. pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
  157. if (!pipe->funcs || !pipe->funcs->enable_vblank)
  158. return 0;
  159. return pipe->funcs->enable_vblank(pipe);
  160. }
  161. static void drm_simple_kms_crtc_disable_vblank(struct drm_crtc *crtc)
  162. {
  163. struct drm_simple_display_pipe *pipe;
  164. pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
  165. if (!pipe->funcs || !pipe->funcs->disable_vblank)
  166. return;
  167. pipe->funcs->disable_vblank(pipe);
  168. }
  169. static const struct drm_crtc_funcs drm_simple_kms_crtc_funcs = {
  170. .reset = drm_simple_kms_crtc_reset,
  171. .destroy = drm_crtc_cleanup,
  172. .set_config = drm_atomic_helper_set_config,
  173. .page_flip = drm_atomic_helper_page_flip,
  174. .atomic_duplicate_state = drm_simple_kms_crtc_duplicate_state,
  175. .atomic_destroy_state = drm_simple_kms_crtc_destroy_state,
  176. .enable_vblank = drm_simple_kms_crtc_enable_vblank,
  177. .disable_vblank = drm_simple_kms_crtc_disable_vblank,
  178. };
  179. static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane,
  180. struct drm_atomic_state *state)
  181. {
  182. struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state,
  183. plane);
  184. struct drm_simple_display_pipe *pipe;
  185. struct drm_crtc_state *crtc_state;
  186. int ret;
  187. pipe = container_of(plane, struct drm_simple_display_pipe, plane);
  188. crtc_state = drm_atomic_get_new_crtc_state(state,
  189. &pipe->crtc);
  190. ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state,
  191. DRM_PLANE_NO_SCALING,
  192. DRM_PLANE_NO_SCALING,
  193. false, false);
  194. if (ret)
  195. return ret;
  196. if (!plane_state->visible)
  197. return 0;
  198. if (!pipe->funcs || !pipe->funcs->check)
  199. return 0;
  200. return pipe->funcs->check(pipe, plane_state, crtc_state);
  201. }
  202. static void drm_simple_kms_plane_atomic_update(struct drm_plane *plane,
  203. struct drm_atomic_state *state)
  204. {
  205. struct drm_plane_state *old_pstate = drm_atomic_get_old_plane_state(state,
  206. plane);
  207. struct drm_simple_display_pipe *pipe;
  208. pipe = container_of(plane, struct drm_simple_display_pipe, plane);
  209. if (!pipe->funcs || !pipe->funcs->update)
  210. return;
  211. pipe->funcs->update(pipe, old_pstate);
  212. }
  213. static int drm_simple_kms_plane_prepare_fb(struct drm_plane *plane,
  214. struct drm_plane_state *state)
  215. {
  216. struct drm_simple_display_pipe *pipe;
  217. pipe = container_of(plane, struct drm_simple_display_pipe, plane);
  218. if (!pipe->funcs || !pipe->funcs->prepare_fb) {
  219. if (WARN_ON_ONCE(!drm_core_check_feature(plane->dev, DRIVER_GEM)))
  220. return 0;
  221. WARN_ON_ONCE(pipe->funcs && pipe->funcs->cleanup_fb);
  222. return drm_gem_plane_helper_prepare_fb(plane, state);
  223. }
  224. return pipe->funcs->prepare_fb(pipe, state);
  225. }
  226. static void drm_simple_kms_plane_cleanup_fb(struct drm_plane *plane,
  227. struct drm_plane_state *state)
  228. {
  229. struct drm_simple_display_pipe *pipe;
  230. pipe = container_of(plane, struct drm_simple_display_pipe, plane);
  231. if (!pipe->funcs || !pipe->funcs->cleanup_fb)
  232. return;
  233. pipe->funcs->cleanup_fb(pipe, state);
  234. }
  235. static int drm_simple_kms_plane_begin_fb_access(struct drm_plane *plane,
  236. struct drm_plane_state *new_plane_state)
  237. {
  238. struct drm_simple_display_pipe *pipe;
  239. pipe = container_of(plane, struct drm_simple_display_pipe, plane);
  240. if (!pipe->funcs || !pipe->funcs->begin_fb_access)
  241. return 0;
  242. return pipe->funcs->begin_fb_access(pipe, new_plane_state);
  243. }
  244. static void drm_simple_kms_plane_end_fb_access(struct drm_plane *plane,
  245. struct drm_plane_state *new_plane_state)
  246. {
  247. struct drm_simple_display_pipe *pipe;
  248. pipe = container_of(plane, struct drm_simple_display_pipe, plane);
  249. if (!pipe->funcs || !pipe->funcs->end_fb_access)
  250. return;
  251. pipe->funcs->end_fb_access(pipe, new_plane_state);
  252. }
  253. static bool drm_simple_kms_format_mod_supported(struct drm_plane *plane,
  254. uint32_t format,
  255. uint64_t modifier)
  256. {
  257. return modifier == DRM_FORMAT_MOD_LINEAR;
  258. }
  259. static const struct drm_plane_helper_funcs drm_simple_kms_plane_helper_funcs = {
  260. .prepare_fb = drm_simple_kms_plane_prepare_fb,
  261. .cleanup_fb = drm_simple_kms_plane_cleanup_fb,
  262. .begin_fb_access = drm_simple_kms_plane_begin_fb_access,
  263. .end_fb_access = drm_simple_kms_plane_end_fb_access,
  264. .atomic_check = drm_simple_kms_plane_atomic_check,
  265. .atomic_update = drm_simple_kms_plane_atomic_update,
  266. };
  267. static void drm_simple_kms_plane_reset(struct drm_plane *plane)
  268. {
  269. struct drm_simple_display_pipe *pipe;
  270. pipe = container_of(plane, struct drm_simple_display_pipe, plane);
  271. if (!pipe->funcs || !pipe->funcs->reset_plane)
  272. return drm_atomic_helper_plane_reset(plane);
  273. return pipe->funcs->reset_plane(pipe);
  274. }
  275. static struct drm_plane_state *drm_simple_kms_plane_duplicate_state(struct drm_plane *plane)
  276. {
  277. struct drm_simple_display_pipe *pipe;
  278. pipe = container_of(plane, struct drm_simple_display_pipe, plane);
  279. if (!pipe->funcs || !pipe->funcs->duplicate_plane_state)
  280. return drm_atomic_helper_plane_duplicate_state(plane);
  281. return pipe->funcs->duplicate_plane_state(pipe);
  282. }
  283. static void drm_simple_kms_plane_destroy_state(struct drm_plane *plane,
  284. struct drm_plane_state *state)
  285. {
  286. struct drm_simple_display_pipe *pipe;
  287. pipe = container_of(plane, struct drm_simple_display_pipe, plane);
  288. if (!pipe->funcs || !pipe->funcs->destroy_plane_state)
  289. drm_atomic_helper_plane_destroy_state(plane, state);
  290. else
  291. pipe->funcs->destroy_plane_state(pipe, state);
  292. }
  293. static const struct drm_plane_funcs drm_simple_kms_plane_funcs = {
  294. .update_plane = drm_atomic_helper_update_plane,
  295. .disable_plane = drm_atomic_helper_disable_plane,
  296. .destroy = drm_plane_cleanup,
  297. .reset = drm_simple_kms_plane_reset,
  298. .atomic_duplicate_state = drm_simple_kms_plane_duplicate_state,
  299. .atomic_destroy_state = drm_simple_kms_plane_destroy_state,
  300. .format_mod_supported = drm_simple_kms_format_mod_supported,
  301. };
  302. /**
  303. * drm_simple_display_pipe_attach_bridge - Attach a bridge to the display pipe
  304. * @pipe: simple display pipe object
  305. * @bridge: bridge to attach
  306. *
  307. * Makes it possible to still use the drm_simple_display_pipe helpers when
  308. * a DRM bridge has to be used.
  309. *
  310. * Note that you probably want to initialize the pipe by passing a NULL
  311. * connector to drm_simple_display_pipe_init().
  312. *
  313. * Returns:
  314. * Zero on success, negative error code on failure.
  315. */
  316. int drm_simple_display_pipe_attach_bridge(struct drm_simple_display_pipe *pipe,
  317. struct drm_bridge *bridge)
  318. {
  319. return drm_bridge_attach(&pipe->encoder, bridge, NULL, 0);
  320. }
  321. EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge);
  322. /**
  323. * drm_simple_display_pipe_init - Initialize a simple display pipeline
  324. * @dev: DRM device
  325. * @pipe: simple display pipe object to initialize
  326. * @funcs: callbacks for the display pipe (optional)
  327. * @formats: array of supported formats (DRM_FORMAT\_\*)
  328. * @format_count: number of elements in @formats
  329. * @format_modifiers: array of formats modifiers
  330. * @connector: connector to attach and register (optional)
  331. *
  332. * Sets up a display pipeline which consist of a really simple
  333. * plane-crtc-encoder pipe.
  334. *
  335. * If a connector is supplied, the pipe will be coupled with the provided
  336. * connector. You may supply a NULL connector when using drm bridges, that
  337. * handle connectors themselves (see drm_simple_display_pipe_attach_bridge()).
  338. *
  339. * Teardown of a simple display pipe is all handled automatically by the drm
  340. * core through calling drm_mode_config_cleanup(). Drivers afterwards need to
  341. * release the memory for the structure themselves.
  342. *
  343. * Returns:
  344. * Zero on success, negative error code on failure.
  345. */
  346. int drm_simple_display_pipe_init(struct drm_device *dev,
  347. struct drm_simple_display_pipe *pipe,
  348. const struct drm_simple_display_pipe_funcs *funcs,
  349. const uint32_t *formats, unsigned int format_count,
  350. const uint64_t *format_modifiers,
  351. struct drm_connector *connector)
  352. {
  353. struct drm_encoder *encoder = &pipe->encoder;
  354. struct drm_plane *plane = &pipe->plane;
  355. struct drm_crtc *crtc = &pipe->crtc;
  356. int ret;
  357. pipe->connector = connector;
  358. pipe->funcs = funcs;
  359. drm_plane_helper_add(plane, &drm_simple_kms_plane_helper_funcs);
  360. ret = drm_universal_plane_init(dev, plane, 0,
  361. &drm_simple_kms_plane_funcs,
  362. formats, format_count,
  363. format_modifiers,
  364. DRM_PLANE_TYPE_PRIMARY, NULL);
  365. if (ret)
  366. return ret;
  367. drm_crtc_helper_add(crtc, &drm_simple_kms_crtc_helper_funcs);
  368. ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL,
  369. &drm_simple_kms_crtc_funcs, NULL);
  370. if (ret)
  371. return ret;
  372. encoder->possible_crtcs = drm_crtc_mask(crtc);
  373. ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_NONE);
  374. if (ret || !connector)
  375. return ret;
  376. return drm_connector_attach_encoder(connector, encoder);
  377. }
  378. EXPORT_SYMBOL(drm_simple_display_pipe_init);
  379. MODULE_DESCRIPTION("Helpers for drivers for simple display hardware");
  380. MODULE_LICENSE("GPL");