sun4i_backend.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993
  1. /*
  2. * Copyright (C) 2015 Free Electrons
  3. * Copyright (C) 2015 NextThing Co
  4. *
  5. * Maxime Ripard <maxime.ripard@free-electrons.com>
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. */
  12. #include <drm/drmP.h>
  13. #include <drm/drm_atomic.h>
  14. #include <drm/drm_atomic_helper.h>
  15. #include <drm/drm_crtc.h>
  16. #include <drm/drm_crtc_helper.h>
  17. #include <drm/drm_fb_cma_helper.h>
  18. #include <drm/drm_gem_cma_helper.h>
  19. #include <drm/drm_plane_helper.h>
  20. #include <linux/component.h>
  21. #include <linux/list.h>
  22. #include <linux/of_device.h>
  23. #include <linux/of_graph.h>
  24. #include <linux/reset.h>
  25. #include "sun4i_backend.h"
  26. #include "sun4i_drv.h"
  27. #include "sun4i_frontend.h"
  28. #include "sun4i_layer.h"
  29. #include "sunxi_engine.h"
  30. struct sun4i_backend_quirks {
  31. /* backend <-> TCON muxing selection done in backend */
  32. bool needs_output_muxing;
  33. };
  34. static const u32 sunxi_rgb2yuv_coef[12] = {
  35. 0x00000107, 0x00000204, 0x00000064, 0x00000108,
  36. 0x00003f69, 0x00003ed6, 0x000001c1, 0x00000808,
  37. 0x000001c1, 0x00003e88, 0x00003fb8, 0x00000808
  38. };
  39. /*
  40. * These coefficients are taken from the A33 BSP from Allwinner.
  41. *
  42. * The formula is for each component, each coefficient being multiplied by
  43. * 1024 and each constant being multiplied by 16:
  44. * G = 1.164 * Y - 0.391 * U - 0.813 * V + 135
  45. * R = 1.164 * Y + 1.596 * V - 222
  46. * B = 1.164 * Y + 2.018 * U + 276
  47. *
  48. * This seems to be a conversion from Y[16:235] UV[16:240] to RGB[0:255],
  49. * following the BT601 spec.
  50. */
  51. static const u32 sunxi_bt601_yuv2rgb_coef[12] = {
  52. 0x000004a7, 0x00001e6f, 0x00001cbf, 0x00000877,
  53. 0x000004a7, 0x00000000, 0x00000662, 0x00003211,
  54. 0x000004a7, 0x00000812, 0x00000000, 0x00002eb1,
  55. };
  56. static inline bool sun4i_backend_format_is_planar_yuv(uint32_t format)
  57. {
  58. switch (format) {
  59. case DRM_FORMAT_YUV411:
  60. case DRM_FORMAT_YUV422:
  61. case DRM_FORMAT_YUV444:
  62. return true;
  63. default:
  64. return false;
  65. }
  66. }
  67. static inline bool sun4i_backend_format_is_packed_yuv422(uint32_t format)
  68. {
  69. switch (format) {
  70. case DRM_FORMAT_YUYV:
  71. case DRM_FORMAT_YVYU:
  72. case DRM_FORMAT_UYVY:
  73. case DRM_FORMAT_VYUY:
  74. return true;
  75. default:
  76. return false;
  77. }
  78. }
  79. static inline bool sun4i_backend_format_is_yuv(uint32_t format)
  80. {
  81. return sun4i_backend_format_is_planar_yuv(format) ||
  82. sun4i_backend_format_is_packed_yuv422(format);
  83. }
  84. static void sun4i_backend_apply_color_correction(struct sunxi_engine *engine)
  85. {
  86. int i;
  87. DRM_DEBUG_DRIVER("Applying RGB to YUV color correction\n");
  88. /* Set color correction */
  89. regmap_write(engine->regs, SUN4I_BACKEND_OCCTL_REG,
  90. SUN4I_BACKEND_OCCTL_ENABLE);
  91. for (i = 0; i < 12; i++)
  92. regmap_write(engine->regs, SUN4I_BACKEND_OCRCOEF_REG(i),
  93. sunxi_rgb2yuv_coef[i]);
  94. }
  95. static void sun4i_backend_disable_color_correction(struct sunxi_engine *engine)
  96. {
  97. DRM_DEBUG_DRIVER("Disabling color correction\n");
  98. /* Disable color correction */
  99. regmap_update_bits(engine->regs, SUN4I_BACKEND_OCCTL_REG,
  100. SUN4I_BACKEND_OCCTL_ENABLE, 0);
  101. }
  102. static void sun4i_backend_commit(struct sunxi_engine *engine)
  103. {
  104. DRM_DEBUG_DRIVER("Committing changes\n");
  105. regmap_write(engine->regs, SUN4I_BACKEND_REGBUFFCTL_REG,
  106. SUN4I_BACKEND_REGBUFFCTL_AUTOLOAD_DIS |
  107. SUN4I_BACKEND_REGBUFFCTL_LOADCTL);
  108. }
  109. void sun4i_backend_layer_enable(struct sun4i_backend *backend,
  110. int layer, bool enable)
  111. {
  112. u32 val;
  113. DRM_DEBUG_DRIVER("%sabling layer %d\n", enable ? "En" : "Dis",
  114. layer);
  115. if (enable)
  116. val = SUN4I_BACKEND_MODCTL_LAY_EN(layer);
  117. else
  118. val = 0;
  119. regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_MODCTL_REG,
  120. SUN4I_BACKEND_MODCTL_LAY_EN(layer), val);
  121. }
  122. static int sun4i_backend_drm_format_to_layer(u32 format, u32 *mode)
  123. {
  124. switch (format) {
  125. case DRM_FORMAT_ARGB8888:
  126. *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB8888;
  127. break;
  128. case DRM_FORMAT_ARGB4444:
  129. *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB4444;
  130. break;
  131. case DRM_FORMAT_ARGB1555:
  132. *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB1555;
  133. break;
  134. case DRM_FORMAT_RGBA5551:
  135. *mode = SUN4I_BACKEND_LAY_FBFMT_RGBA5551;
  136. break;
  137. case DRM_FORMAT_RGBA4444:
  138. *mode = SUN4I_BACKEND_LAY_FBFMT_RGBA4444;
  139. break;
  140. case DRM_FORMAT_XRGB8888:
  141. *mode = SUN4I_BACKEND_LAY_FBFMT_XRGB8888;
  142. break;
  143. case DRM_FORMAT_RGB888:
  144. *mode = SUN4I_BACKEND_LAY_FBFMT_RGB888;
  145. break;
  146. case DRM_FORMAT_RGB565:
  147. *mode = SUN4I_BACKEND_LAY_FBFMT_RGB565;
  148. break;
  149. default:
  150. return -EINVAL;
  151. }
  152. return 0;
  153. }
  154. int sun4i_backend_update_layer_coord(struct sun4i_backend *backend,
  155. int layer, struct drm_plane *plane)
  156. {
  157. struct drm_plane_state *state = plane->state;
  158. DRM_DEBUG_DRIVER("Updating layer %d\n", layer);
  159. if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
  160. DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n",
  161. state->crtc_w, state->crtc_h);
  162. regmap_write(backend->engine.regs, SUN4I_BACKEND_DISSIZE_REG,
  163. SUN4I_BACKEND_DISSIZE(state->crtc_w,
  164. state->crtc_h));
  165. }
  166. /* Set height and width */
  167. DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n",
  168. state->crtc_w, state->crtc_h);
  169. regmap_write(backend->engine.regs, SUN4I_BACKEND_LAYSIZE_REG(layer),
  170. SUN4I_BACKEND_LAYSIZE(state->crtc_w,
  171. state->crtc_h));
  172. /* Set base coordinates */
  173. DRM_DEBUG_DRIVER("Layer coordinates X: %d Y: %d\n",
  174. state->crtc_x, state->crtc_y);
  175. regmap_write(backend->engine.regs, SUN4I_BACKEND_LAYCOOR_REG(layer),
  176. SUN4I_BACKEND_LAYCOOR(state->crtc_x,
  177. state->crtc_y));
  178. return 0;
  179. }
  180. static int sun4i_backend_update_yuv_format(struct sun4i_backend *backend,
  181. int layer, struct drm_plane *plane)
  182. {
  183. struct drm_plane_state *state = plane->state;
  184. struct drm_framebuffer *fb = state->fb;
  185. uint32_t format = fb->format->format;
  186. u32 val = SUN4I_BACKEND_IYUVCTL_EN;
  187. int i;
  188. for (i = 0; i < ARRAY_SIZE(sunxi_bt601_yuv2rgb_coef); i++)
  189. regmap_write(backend->engine.regs,
  190. SUN4I_BACKEND_YGCOEF_REG(i),
  191. sunxi_bt601_yuv2rgb_coef[i]);
  192. /*
  193. * We should do that only for a single plane, but the
  194. * framebuffer's atomic_check has our back on this.
  195. */
  196. regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_ATTCTL_REG0(layer),
  197. SUN4I_BACKEND_ATTCTL_REG0_LAY_YUVEN,
  198. SUN4I_BACKEND_ATTCTL_REG0_LAY_YUVEN);
  199. /* TODO: Add support for the multi-planar YUV formats */
  200. if (sun4i_backend_format_is_packed_yuv422(format))
  201. val |= SUN4I_BACKEND_IYUVCTL_FBFMT_PACKED_YUV422;
  202. else
  203. DRM_DEBUG_DRIVER("Unsupported YUV format (0x%x)\n", format);
  204. /*
  205. * Allwinner seems to list the pixel sequence from right to left, while
  206. * DRM lists it from left to right.
  207. */
  208. switch (format) {
  209. case DRM_FORMAT_YUYV:
  210. val |= SUN4I_BACKEND_IYUVCTL_FBPS_VYUY;
  211. break;
  212. case DRM_FORMAT_YVYU:
  213. val |= SUN4I_BACKEND_IYUVCTL_FBPS_UYVY;
  214. break;
  215. case DRM_FORMAT_UYVY:
  216. val |= SUN4I_BACKEND_IYUVCTL_FBPS_YVYU;
  217. break;
  218. case DRM_FORMAT_VYUY:
  219. val |= SUN4I_BACKEND_IYUVCTL_FBPS_YUYV;
  220. break;
  221. default:
  222. DRM_DEBUG_DRIVER("Unsupported YUV pixel sequence (0x%x)\n",
  223. format);
  224. }
  225. regmap_write(backend->engine.regs, SUN4I_BACKEND_IYUVCTL_REG, val);
  226. return 0;
  227. }
  228. int sun4i_backend_update_layer_formats(struct sun4i_backend *backend,
  229. int layer, struct drm_plane *plane)
  230. {
  231. struct drm_plane_state *state = plane->state;
  232. struct drm_framebuffer *fb = state->fb;
  233. bool interlaced = false;
  234. u32 val;
  235. int ret;
  236. /* Clear the YUV mode */
  237. regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_ATTCTL_REG0(layer),
  238. SUN4I_BACKEND_ATTCTL_REG0_LAY_YUVEN, 0);
  239. if (plane->state->crtc)
  240. interlaced = plane->state->crtc->state->adjusted_mode.flags
  241. & DRM_MODE_FLAG_INTERLACE;
  242. regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_MODCTL_REG,
  243. SUN4I_BACKEND_MODCTL_ITLMOD_EN,
  244. interlaced ? SUN4I_BACKEND_MODCTL_ITLMOD_EN : 0);
  245. DRM_DEBUG_DRIVER("Switching display backend interlaced mode %s\n",
  246. interlaced ? "on" : "off");
  247. val = SUN4I_BACKEND_ATTCTL_REG0_LAY_GLBALPHA(state->alpha >> 8);
  248. if (state->alpha != DRM_BLEND_ALPHA_OPAQUE)
  249. val |= SUN4I_BACKEND_ATTCTL_REG0_LAY_GLBALPHA_EN;
  250. regmap_update_bits(backend->engine.regs,
  251. SUN4I_BACKEND_ATTCTL_REG0(layer),
  252. SUN4I_BACKEND_ATTCTL_REG0_LAY_GLBALPHA_MASK |
  253. SUN4I_BACKEND_ATTCTL_REG0_LAY_GLBALPHA_EN,
  254. val);
  255. if (sun4i_backend_format_is_yuv(fb->format->format))
  256. return sun4i_backend_update_yuv_format(backend, layer, plane);
  257. ret = sun4i_backend_drm_format_to_layer(fb->format->format, &val);
  258. if (ret) {
  259. DRM_DEBUG_DRIVER("Invalid format\n");
  260. return ret;
  261. }
  262. regmap_update_bits(backend->engine.regs,
  263. SUN4I_BACKEND_ATTCTL_REG1(layer),
  264. SUN4I_BACKEND_ATTCTL_REG1_LAY_FBFMT, val);
  265. return 0;
  266. }
  267. int sun4i_backend_update_layer_frontend(struct sun4i_backend *backend,
  268. int layer, uint32_t fmt)
  269. {
  270. u32 val;
  271. int ret;
  272. ret = sun4i_backend_drm_format_to_layer(fmt, &val);
  273. if (ret) {
  274. DRM_DEBUG_DRIVER("Invalid format\n");
  275. return ret;
  276. }
  277. regmap_update_bits(backend->engine.regs,
  278. SUN4I_BACKEND_ATTCTL_REG0(layer),
  279. SUN4I_BACKEND_ATTCTL_REG0_LAY_VDOEN,
  280. SUN4I_BACKEND_ATTCTL_REG0_LAY_VDOEN);
  281. regmap_update_bits(backend->engine.regs,
  282. SUN4I_BACKEND_ATTCTL_REG1(layer),
  283. SUN4I_BACKEND_ATTCTL_REG1_LAY_FBFMT, val);
  284. return 0;
  285. }
  286. static int sun4i_backend_update_yuv_buffer(struct sun4i_backend *backend,
  287. struct drm_framebuffer *fb,
  288. dma_addr_t paddr)
  289. {
  290. /* TODO: Add support for the multi-planar YUV formats */
  291. DRM_DEBUG_DRIVER("Setting packed YUV buffer address to %pad\n", &paddr);
  292. regmap_write(backend->engine.regs, SUN4I_BACKEND_IYUVADD_REG(0), paddr);
  293. DRM_DEBUG_DRIVER("Layer line width: %d bits\n", fb->pitches[0] * 8);
  294. regmap_write(backend->engine.regs, SUN4I_BACKEND_IYUVLINEWIDTH_REG(0),
  295. fb->pitches[0] * 8);
  296. return 0;
  297. }
  298. int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend,
  299. int layer, struct drm_plane *plane)
  300. {
  301. struct drm_plane_state *state = plane->state;
  302. struct drm_framebuffer *fb = state->fb;
  303. u32 lo_paddr, hi_paddr;
  304. dma_addr_t paddr;
  305. /* Set the line width */
  306. DRM_DEBUG_DRIVER("Layer line width: %d bits\n", fb->pitches[0] * 8);
  307. regmap_write(backend->engine.regs,
  308. SUN4I_BACKEND_LAYLINEWIDTH_REG(layer),
  309. fb->pitches[0] * 8);
  310. /* Get the start of the displayed memory */
  311. paddr = drm_fb_cma_get_gem_addr(fb, state, 0);
  312. DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
  313. /*
  314. * backend DMA accesses DRAM directly, bypassing the system
  315. * bus. As such, the address range is different and the buffer
  316. * address needs to be corrected.
  317. */
  318. paddr -= PHYS_OFFSET;
  319. if (sun4i_backend_format_is_yuv(fb->format->format))
  320. return sun4i_backend_update_yuv_buffer(backend, fb, paddr);
  321. /* Write the 32 lower bits of the address (in bits) */
  322. lo_paddr = paddr << 3;
  323. DRM_DEBUG_DRIVER("Setting address lower bits to 0x%x\n", lo_paddr);
  324. regmap_write(backend->engine.regs,
  325. SUN4I_BACKEND_LAYFB_L32ADD_REG(layer),
  326. lo_paddr);
  327. /* And the upper bits */
  328. hi_paddr = paddr >> 29;
  329. DRM_DEBUG_DRIVER("Setting address high bits to 0x%x\n", hi_paddr);
  330. regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_LAYFB_H4ADD_REG,
  331. SUN4I_BACKEND_LAYFB_H4ADD_MSK(layer),
  332. SUN4I_BACKEND_LAYFB_H4ADD(layer, hi_paddr));
  333. return 0;
  334. }
  335. int sun4i_backend_update_layer_zpos(struct sun4i_backend *backend, int layer,
  336. struct drm_plane *plane)
  337. {
  338. struct drm_plane_state *state = plane->state;
  339. struct sun4i_layer_state *p_state = state_to_sun4i_layer_state(state);
  340. unsigned int priority = state->normalized_zpos;
  341. unsigned int pipe = p_state->pipe;
  342. DRM_DEBUG_DRIVER("Setting layer %d's priority to %d and pipe %d\n",
  343. layer, priority, pipe);
  344. regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_ATTCTL_REG0(layer),
  345. SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL_MASK |
  346. SUN4I_BACKEND_ATTCTL_REG0_LAY_PRISEL_MASK,
  347. SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(p_state->pipe) |
  348. SUN4I_BACKEND_ATTCTL_REG0_LAY_PRISEL(priority));
  349. return 0;
  350. }
  351. static bool sun4i_backend_plane_uses_scaler(struct drm_plane_state *state)
  352. {
  353. u16 src_h = state->src_h >> 16;
  354. u16 src_w = state->src_w >> 16;
  355. DRM_DEBUG_DRIVER("Input size %dx%d, output size %dx%d\n",
  356. src_w, src_h, state->crtc_w, state->crtc_h);
  357. if ((state->crtc_h != src_h) || (state->crtc_w != src_w))
  358. return true;
  359. return false;
  360. }
  361. static bool sun4i_backend_plane_uses_frontend(struct drm_plane_state *state)
  362. {
  363. struct sun4i_layer *layer = plane_to_sun4i_layer(state->plane);
  364. struct sun4i_backend *backend = layer->backend;
  365. if (IS_ERR(backend->frontend))
  366. return false;
  367. return sun4i_backend_plane_uses_scaler(state);
  368. }
  369. static void sun4i_backend_atomic_begin(struct sunxi_engine *engine,
  370. struct drm_crtc_state *old_state)
  371. {
  372. u32 val;
  373. WARN_ON(regmap_read_poll_timeout(engine->regs,
  374. SUN4I_BACKEND_REGBUFFCTL_REG,
  375. val, !(val & SUN4I_BACKEND_REGBUFFCTL_LOADCTL),
  376. 100, 50000));
  377. }
  378. static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
  379. struct drm_crtc_state *crtc_state)
  380. {
  381. struct drm_plane_state *plane_states[SUN4I_BACKEND_NUM_LAYERS] = { 0 };
  382. struct drm_atomic_state *state = crtc_state->state;
  383. struct drm_device *drm = state->dev;
  384. struct drm_plane *plane;
  385. unsigned int num_planes = 0;
  386. unsigned int num_alpha_planes = 0;
  387. unsigned int num_frontend_planes = 0;
  388. unsigned int num_yuv_planes = 0;
  389. unsigned int current_pipe = 0;
  390. unsigned int i;
  391. DRM_DEBUG_DRIVER("Starting checking our planes\n");
  392. if (!crtc_state->planes_changed)
  393. return 0;
  394. drm_for_each_plane_mask(plane, drm, crtc_state->plane_mask) {
  395. struct drm_plane_state *plane_state =
  396. drm_atomic_get_plane_state(state, plane);
  397. struct sun4i_layer_state *layer_state =
  398. state_to_sun4i_layer_state(plane_state);
  399. struct drm_framebuffer *fb = plane_state->fb;
  400. struct drm_format_name_buf format_name;
  401. if (sun4i_backend_plane_uses_frontend(plane_state)) {
  402. DRM_DEBUG_DRIVER("Using the frontend for plane %d\n",
  403. plane->index);
  404. layer_state->uses_frontend = true;
  405. num_frontend_planes++;
  406. } else {
  407. layer_state->uses_frontend = false;
  408. }
  409. DRM_DEBUG_DRIVER("Plane FB format is %s\n",
  410. drm_get_format_name(fb->format->format,
  411. &format_name));
  412. if (fb->format->has_alpha || (plane_state->alpha != DRM_BLEND_ALPHA_OPAQUE))
  413. num_alpha_planes++;
  414. if (sun4i_backend_format_is_yuv(fb->format->format)) {
  415. DRM_DEBUG_DRIVER("Plane FB format is YUV\n");
  416. num_yuv_planes++;
  417. }
  418. DRM_DEBUG_DRIVER("Plane zpos is %d\n",
  419. plane_state->normalized_zpos);
  420. /* Sort our planes by Zpos */
  421. plane_states[plane_state->normalized_zpos] = plane_state;
  422. num_planes++;
  423. }
  424. /* All our planes were disabled, bail out */
  425. if (!num_planes)
  426. return 0;
  427. /*
  428. * The hardware is a bit unusual here.
  429. *
  430. * Even though it supports 4 layers, it does the composition
  431. * in two separate steps.
  432. *
  433. * The first one is assigning a layer to one of its two
  434. * pipes. If more that 1 layer is assigned to the same pipe,
  435. * and if pixels overlaps, the pipe will take the pixel from
  436. * the layer with the highest priority.
  437. *
  438. * The second step is the actual alpha blending, that takes
  439. * the two pipes as input, and uses the eventual alpha
  440. * component to do the transparency between the two.
  441. *
  442. * This two steps scenario makes us unable to guarantee a
  443. * robust alpha blending between the 4 layers in all
  444. * situations, since this means that we need to have one layer
  445. * with alpha at the lowest position of our two pipes.
  446. *
  447. * However, we cannot even do that, since the hardware has a
  448. * bug where the lowest plane of the lowest pipe (pipe 0,
  449. * priority 0), if it has any alpha, will discard the pixel
  450. * entirely and just display the pixels in the background
  451. * color (black by default).
  452. *
  453. * This means that we effectively have only three valid
  454. * configurations with alpha, all of them with the alpha being
  455. * on pipe1 with the lowest position, which can be 1, 2 or 3
  456. * depending on the number of planes and their zpos.
  457. */
  458. if (num_alpha_planes > SUN4I_BACKEND_NUM_ALPHA_LAYERS) {
  459. DRM_DEBUG_DRIVER("Too many planes with alpha, rejecting...\n");
  460. return -EINVAL;
  461. }
  462. /* We can't have an alpha plane at the lowest position */
  463. if (plane_states[0]->fb->format->has_alpha ||
  464. (plane_states[0]->alpha != DRM_BLEND_ALPHA_OPAQUE))
  465. return -EINVAL;
  466. for (i = 1; i < num_planes; i++) {
  467. struct drm_plane_state *p_state = plane_states[i];
  468. struct drm_framebuffer *fb = p_state->fb;
  469. struct sun4i_layer_state *s_state = state_to_sun4i_layer_state(p_state);
  470. /*
  471. * The only alpha position is the lowest plane of the
  472. * second pipe.
  473. */
  474. if (fb->format->has_alpha || (p_state->alpha != DRM_BLEND_ALPHA_OPAQUE))
  475. current_pipe++;
  476. s_state->pipe = current_pipe;
  477. }
  478. /* We can only have a single YUV plane at a time */
  479. if (num_yuv_planes > SUN4I_BACKEND_NUM_YUV_PLANES) {
  480. DRM_DEBUG_DRIVER("Too many planes with YUV, rejecting...\n");
  481. return -EINVAL;
  482. }
  483. if (num_frontend_planes > SUN4I_BACKEND_NUM_FRONTEND_LAYERS) {
  484. DRM_DEBUG_DRIVER("Too many planes going through the frontend, rejecting\n");
  485. return -EINVAL;
  486. }
  487. DRM_DEBUG_DRIVER("State valid with %u planes, %u alpha, %u video, %u YUV\n",
  488. num_planes, num_alpha_planes, num_frontend_planes,
  489. num_yuv_planes);
  490. return 0;
  491. }
  492. static void sun4i_backend_vblank_quirk(struct sunxi_engine *engine)
  493. {
  494. struct sun4i_backend *backend = engine_to_sun4i_backend(engine);
  495. struct sun4i_frontend *frontend = backend->frontend;
  496. if (!frontend)
  497. return;
  498. /*
  499. * In a teardown scenario with the frontend involved, we have
  500. * to keep the frontend enabled until the next vblank, and
  501. * only then disable it.
  502. *
  503. * This is due to the fact that the backend will not take into
  504. * account the new configuration (with the plane that used to
  505. * be fed by the frontend now disabled) until we write to the
  506. * commit bit and the hardware fetches the new configuration
  507. * during the next vblank.
  508. *
  509. * So we keep the frontend around in order to prevent any
  510. * visual artifacts.
  511. */
  512. spin_lock(&backend->frontend_lock);
  513. if (backend->frontend_teardown) {
  514. sun4i_frontend_exit(frontend);
  515. backend->frontend_teardown = false;
  516. }
  517. spin_unlock(&backend->frontend_lock);
  518. };
  519. static int sun4i_backend_init_sat(struct device *dev) {
  520. struct sun4i_backend *backend = dev_get_drvdata(dev);
  521. int ret;
  522. backend->sat_reset = devm_reset_control_get(dev, "sat");
  523. if (IS_ERR(backend->sat_reset)) {
  524. dev_err(dev, "Couldn't get the SAT reset line\n");
  525. return PTR_ERR(backend->sat_reset);
  526. }
  527. ret = reset_control_deassert(backend->sat_reset);
  528. if (ret) {
  529. dev_err(dev, "Couldn't deassert the SAT reset line\n");
  530. return ret;
  531. }
  532. backend->sat_clk = devm_clk_get(dev, "sat");
  533. if (IS_ERR(backend->sat_clk)) {
  534. dev_err(dev, "Couldn't get our SAT clock\n");
  535. ret = PTR_ERR(backend->sat_clk);
  536. goto err_assert_reset;
  537. }
  538. ret = clk_prepare_enable(backend->sat_clk);
  539. if (ret) {
  540. dev_err(dev, "Couldn't enable the SAT clock\n");
  541. return ret;
  542. }
  543. return 0;
  544. err_assert_reset:
  545. reset_control_assert(backend->sat_reset);
  546. return ret;
  547. }
  548. static int sun4i_backend_free_sat(struct device *dev) {
  549. struct sun4i_backend *backend = dev_get_drvdata(dev);
  550. clk_disable_unprepare(backend->sat_clk);
  551. reset_control_assert(backend->sat_reset);
  552. return 0;
  553. }
  554. /*
  555. * The display backend can take video output from the display frontend, or
  556. * the display enhancement unit on the A80, as input for one it its layers.
  557. * This relationship within the display pipeline is encoded in the device
  558. * tree with of_graph, and we use it here to figure out which backend, if
  559. * there are 2 or more, we are currently probing. The number would be in
  560. * the "reg" property of the upstream output port endpoint.
  561. */
  562. static int sun4i_backend_of_get_id(struct device_node *node)
  563. {
  564. struct device_node *port, *ep;
  565. int ret = -EINVAL;
  566. /* input is port 0 */
  567. port = of_graph_get_port_by_id(node, 0);
  568. if (!port)
  569. return -EINVAL;
  570. /* try finding an upstream endpoint */
  571. for_each_available_child_of_node(port, ep) {
  572. struct device_node *remote;
  573. u32 reg;
  574. remote = of_graph_get_remote_endpoint(ep);
  575. if (!remote)
  576. continue;
  577. ret = of_property_read_u32(remote, "reg", &reg);
  578. if (ret)
  579. continue;
  580. ret = reg;
  581. }
  582. of_node_put(port);
  583. return ret;
  584. }
  585. /* TODO: This needs to take multiple pipelines into account */
  586. static struct sun4i_frontend *sun4i_backend_find_frontend(struct sun4i_drv *drv,
  587. struct device_node *node)
  588. {
  589. struct device_node *port, *ep, *remote;
  590. struct sun4i_frontend *frontend;
  591. port = of_graph_get_port_by_id(node, 0);
  592. if (!port)
  593. return ERR_PTR(-EINVAL);
  594. for_each_available_child_of_node(port, ep) {
  595. remote = of_graph_get_remote_port_parent(ep);
  596. if (!remote)
  597. continue;
  598. /* does this node match any registered engines? */
  599. list_for_each_entry(frontend, &drv->frontend_list, list) {
  600. if (remote == frontend->node) {
  601. of_node_put(remote);
  602. of_node_put(port);
  603. return frontend;
  604. }
  605. }
  606. }
  607. return ERR_PTR(-EINVAL);
  608. }
  609. static const struct sunxi_engine_ops sun4i_backend_engine_ops = {
  610. .atomic_begin = sun4i_backend_atomic_begin,
  611. .atomic_check = sun4i_backend_atomic_check,
  612. .commit = sun4i_backend_commit,
  613. .layers_init = sun4i_layers_init,
  614. .apply_color_correction = sun4i_backend_apply_color_correction,
  615. .disable_color_correction = sun4i_backend_disable_color_correction,
  616. .vblank_quirk = sun4i_backend_vblank_quirk,
  617. };
  618. static struct regmap_config sun4i_backend_regmap_config = {
  619. .reg_bits = 32,
  620. .val_bits = 32,
  621. .reg_stride = 4,
  622. .max_register = 0x5800,
  623. };
  624. static int sun4i_backend_bind(struct device *dev, struct device *master,
  625. void *data)
  626. {
  627. struct platform_device *pdev = to_platform_device(dev);
  628. struct drm_device *drm = data;
  629. struct sun4i_drv *drv = drm->dev_private;
  630. struct sun4i_backend *backend;
  631. const struct sun4i_backend_quirks *quirks;
  632. struct resource *res;
  633. void __iomem *regs;
  634. int i, ret;
  635. backend = devm_kzalloc(dev, sizeof(*backend), GFP_KERNEL);
  636. if (!backend)
  637. return -ENOMEM;
  638. dev_set_drvdata(dev, backend);
  639. spin_lock_init(&backend->frontend_lock);
  640. backend->engine.node = dev->of_node;
  641. backend->engine.ops = &sun4i_backend_engine_ops;
  642. backend->engine.id = sun4i_backend_of_get_id(dev->of_node);
  643. if (backend->engine.id < 0)
  644. return backend->engine.id;
  645. backend->frontend = sun4i_backend_find_frontend(drv, dev->of_node);
  646. if (IS_ERR(backend->frontend))
  647. dev_warn(dev, "Couldn't find matching frontend, frontend features disabled\n");
  648. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  649. regs = devm_ioremap_resource(dev, res);
  650. if (IS_ERR(regs))
  651. return PTR_ERR(regs);
  652. backend->reset = devm_reset_control_get(dev, NULL);
  653. if (IS_ERR(backend->reset)) {
  654. dev_err(dev, "Couldn't get our reset line\n");
  655. return PTR_ERR(backend->reset);
  656. }
  657. ret = reset_control_deassert(backend->reset);
  658. if (ret) {
  659. dev_err(dev, "Couldn't deassert our reset line\n");
  660. return ret;
  661. }
  662. backend->bus_clk = devm_clk_get(dev, "ahb");
  663. if (IS_ERR(backend->bus_clk)) {
  664. dev_err(dev, "Couldn't get the backend bus clock\n");
  665. ret = PTR_ERR(backend->bus_clk);
  666. goto err_assert_reset;
  667. }
  668. clk_prepare_enable(backend->bus_clk);
  669. backend->mod_clk = devm_clk_get(dev, "mod");
  670. if (IS_ERR(backend->mod_clk)) {
  671. dev_err(dev, "Couldn't get the backend module clock\n");
  672. ret = PTR_ERR(backend->mod_clk);
  673. goto err_disable_bus_clk;
  674. }
  675. clk_prepare_enable(backend->mod_clk);
  676. backend->ram_clk = devm_clk_get(dev, "ram");
  677. if (IS_ERR(backend->ram_clk)) {
  678. dev_err(dev, "Couldn't get the backend RAM clock\n");
  679. ret = PTR_ERR(backend->ram_clk);
  680. goto err_disable_mod_clk;
  681. }
  682. clk_prepare_enable(backend->ram_clk);
  683. if (of_device_is_compatible(dev->of_node,
  684. "allwinner,sun8i-a33-display-backend")) {
  685. ret = sun4i_backend_init_sat(dev);
  686. if (ret) {
  687. dev_err(dev, "Couldn't init SAT resources\n");
  688. goto err_disable_ram_clk;
  689. }
  690. }
  691. backend->engine.regs = devm_regmap_init_mmio(dev, regs,
  692. &sun4i_backend_regmap_config);
  693. if (IS_ERR(backend->engine.regs)) {
  694. dev_err(dev, "Couldn't create the backend regmap\n");
  695. return PTR_ERR(backend->engine.regs);
  696. }
  697. list_add_tail(&backend->engine.list, &drv->engine_list);
  698. /*
  699. * Many of the backend's layer configuration registers have
  700. * undefined default values. This poses a risk as we use
  701. * regmap_update_bits in some places, and don't overwrite
  702. * the whole register.
  703. *
  704. * Clear the registers here to have something predictable.
  705. */
  706. for (i = 0x800; i < 0x1000; i += 4)
  707. regmap_write(backend->engine.regs, i, 0);
  708. /* Disable registers autoloading */
  709. regmap_write(backend->engine.regs, SUN4I_BACKEND_REGBUFFCTL_REG,
  710. SUN4I_BACKEND_REGBUFFCTL_AUTOLOAD_DIS);
  711. /* Enable the backend */
  712. regmap_write(backend->engine.regs, SUN4I_BACKEND_MODCTL_REG,
  713. SUN4I_BACKEND_MODCTL_DEBE_EN |
  714. SUN4I_BACKEND_MODCTL_START_CTL);
  715. /* Set output selection if needed */
  716. quirks = of_device_get_match_data(dev);
  717. if (quirks->needs_output_muxing) {
  718. /*
  719. * We assume there is no dynamic muxing of backends
  720. * and TCONs, so we select the backend with same ID.
  721. *
  722. * While dynamic selection might be interesting, since
  723. * the CRTC is tied to the TCON, while the layers are
  724. * tied to the backends, this means, we will need to
  725. * switch between groups of layers. There might not be
  726. * a way to represent this constraint in DRM.
  727. */
  728. regmap_update_bits(backend->engine.regs,
  729. SUN4I_BACKEND_MODCTL_REG,
  730. SUN4I_BACKEND_MODCTL_OUT_SEL,
  731. (backend->engine.id
  732. ? SUN4I_BACKEND_MODCTL_OUT_LCD1
  733. : SUN4I_BACKEND_MODCTL_OUT_LCD0));
  734. }
  735. return 0;
  736. err_disable_ram_clk:
  737. clk_disable_unprepare(backend->ram_clk);
  738. err_disable_mod_clk:
  739. clk_disable_unprepare(backend->mod_clk);
  740. err_disable_bus_clk:
  741. clk_disable_unprepare(backend->bus_clk);
  742. err_assert_reset:
  743. reset_control_assert(backend->reset);
  744. return ret;
  745. }
  746. static void sun4i_backend_unbind(struct device *dev, struct device *master,
  747. void *data)
  748. {
  749. struct sun4i_backend *backend = dev_get_drvdata(dev);
  750. list_del(&backend->engine.list);
  751. if (of_device_is_compatible(dev->of_node,
  752. "allwinner,sun8i-a33-display-backend"))
  753. sun4i_backend_free_sat(dev);
  754. clk_disable_unprepare(backend->ram_clk);
  755. clk_disable_unprepare(backend->mod_clk);
  756. clk_disable_unprepare(backend->bus_clk);
  757. reset_control_assert(backend->reset);
  758. }
  759. static const struct component_ops sun4i_backend_ops = {
  760. .bind = sun4i_backend_bind,
  761. .unbind = sun4i_backend_unbind,
  762. };
  763. static int sun4i_backend_probe(struct platform_device *pdev)
  764. {
  765. return component_add(&pdev->dev, &sun4i_backend_ops);
  766. }
  767. static int sun4i_backend_remove(struct platform_device *pdev)
  768. {
  769. component_del(&pdev->dev, &sun4i_backend_ops);
  770. return 0;
  771. }
  772. static const struct sun4i_backend_quirks sun4i_backend_quirks = {
  773. .needs_output_muxing = true,
  774. };
  775. static const struct sun4i_backend_quirks sun5i_backend_quirks = {
  776. };
  777. static const struct sun4i_backend_quirks sun6i_backend_quirks = {
  778. };
  779. static const struct sun4i_backend_quirks sun7i_backend_quirks = {
  780. .needs_output_muxing = true,
  781. };
  782. static const struct sun4i_backend_quirks sun8i_a33_backend_quirks = {
  783. };
  784. static const struct sun4i_backend_quirks sun9i_backend_quirks = {
  785. };
  786. static const struct of_device_id sun4i_backend_of_table[] = {
  787. {
  788. .compatible = "allwinner,sun4i-a10-display-backend",
  789. .data = &sun4i_backend_quirks,
  790. },
  791. {
  792. .compatible = "allwinner,sun5i-a13-display-backend",
  793. .data = &sun5i_backend_quirks,
  794. },
  795. {
  796. .compatible = "allwinner,sun6i-a31-display-backend",
  797. .data = &sun6i_backend_quirks,
  798. },
  799. {
  800. .compatible = "allwinner,sun7i-a20-display-backend",
  801. .data = &sun7i_backend_quirks,
  802. },
  803. {
  804. .compatible = "allwinner,sun8i-a33-display-backend",
  805. .data = &sun8i_a33_backend_quirks,
  806. },
  807. {
  808. .compatible = "allwinner,sun9i-a80-display-backend",
  809. .data = &sun9i_backend_quirks,
  810. },
  811. { }
  812. };
  813. MODULE_DEVICE_TABLE(of, sun4i_backend_of_table);
  814. static struct platform_driver sun4i_backend_platform_driver = {
  815. .probe = sun4i_backend_probe,
  816. .remove = sun4i_backend_remove,
  817. .driver = {
  818. .name = "sun4i-backend",
  819. .of_match_table = sun4i_backend_of_table,
  820. },
  821. };
  822. module_platform_driver(sun4i_backend_platform_driver);
  823. MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
  824. MODULE_DESCRIPTION("Allwinner A10 Display Backend Driver");
  825. MODULE_LICENSE("GPL");