sun4i_backend.c 28 KB

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