vsp1_drm.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * vsp1_drm.c -- R-Car VSP1 DRM/KMS Interface
  4. *
  5. * Copyright (C) 2015 Renesas Electronics Corporation
  6. *
  7. * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  8. */
  9. #include <linux/device.h>
  10. #include <linux/dma-mapping.h>
  11. #include <linux/slab.h>
  12. #include <media/media-entity.h>
  13. #include <media/v4l2-subdev.h>
  14. #include <media/vsp1.h>
  15. #include "vsp1.h"
  16. #include "vsp1_brx.h"
  17. #include "vsp1_dl.h"
  18. #include "vsp1_drm.h"
  19. #include "vsp1_lif.h"
  20. #include "vsp1_pipe.h"
  21. #include "vsp1_rwpf.h"
  22. #include "vsp1_uif.h"
  23. #define BRX_NAME(e) (e)->type == VSP1_ENTITY_BRU ? "BRU" : "BRS"
  24. /* -----------------------------------------------------------------------------
  25. * Interrupt Handling
  26. */
  27. static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
  28. unsigned int completion)
  29. {
  30. struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
  31. bool complete = completion == VSP1_DL_FRAME_END_COMPLETED;
  32. if (drm_pipe->du_complete) {
  33. struct vsp1_entity *uif = drm_pipe->uif;
  34. u32 crc;
  35. crc = uif ? vsp1_uif_get_crc(to_uif(&uif->subdev)) : 0;
  36. drm_pipe->du_complete(drm_pipe->du_private, complete, crc);
  37. }
  38. if (completion & VSP1_DL_FRAME_END_INTERNAL) {
  39. drm_pipe->force_brx_release = false;
  40. wake_up(&drm_pipe->wait_queue);
  41. }
  42. }
  43. /* -----------------------------------------------------------------------------
  44. * Pipeline Configuration
  45. */
  46. /*
  47. * Insert the UIF in the pipeline between the prev and next entities. If no UIF
  48. * is available connect the two entities directly.
  49. */
  50. static int vsp1_du_insert_uif(struct vsp1_device *vsp1,
  51. struct vsp1_pipeline *pipe,
  52. struct vsp1_entity *uif,
  53. struct vsp1_entity *prev, unsigned int prev_pad,
  54. struct vsp1_entity *next, unsigned int next_pad)
  55. {
  56. struct v4l2_subdev_format format;
  57. int ret;
  58. if (!uif) {
  59. /*
  60. * If there's no UIF to be inserted, connect the previous and
  61. * next entities directly.
  62. */
  63. prev->sink = next;
  64. prev->sink_pad = next_pad;
  65. return 0;
  66. }
  67. prev->sink = uif;
  68. prev->sink_pad = UIF_PAD_SINK;
  69. memset(&format, 0, sizeof(format));
  70. format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
  71. format.pad = prev_pad;
  72. ret = v4l2_subdev_call(&prev->subdev, pad, get_fmt, NULL, &format);
  73. if (ret < 0)
  74. return ret;
  75. format.pad = UIF_PAD_SINK;
  76. ret = v4l2_subdev_call(&uif->subdev, pad, set_fmt, NULL, &format);
  77. if (ret < 0)
  78. return ret;
  79. dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on UIF sink\n",
  80. __func__, format.format.width, format.format.height,
  81. format.format.code);
  82. /*
  83. * The UIF doesn't mangle the format between its sink and source pads,
  84. * so there is no need to retrieve the format on its source pad.
  85. */
  86. uif->sink = next;
  87. uif->sink_pad = next_pad;
  88. return 0;
  89. }
  90. /* Setup one RPF and the connected BRx sink pad. */
  91. static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
  92. struct vsp1_pipeline *pipe,
  93. struct vsp1_rwpf *rpf,
  94. struct vsp1_entity *uif,
  95. unsigned int brx_input)
  96. {
  97. struct v4l2_subdev_selection sel;
  98. struct v4l2_subdev_format format;
  99. const struct v4l2_rect *crop;
  100. int ret;
  101. /*
  102. * Configure the format on the RPF sink pad and propagate it up to the
  103. * BRx sink pad.
  104. */
  105. crop = &vsp1->drm->inputs[rpf->entity.index].crop;
  106. memset(&format, 0, sizeof(format));
  107. format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
  108. format.pad = RWPF_PAD_SINK;
  109. format.format.width = crop->width + crop->left;
  110. format.format.height = crop->height + crop->top;
  111. format.format.code = rpf->fmtinfo->mbus;
  112. format.format.field = V4L2_FIELD_NONE;
  113. ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_fmt, NULL,
  114. &format);
  115. if (ret < 0)
  116. return ret;
  117. dev_dbg(vsp1->dev,
  118. "%s: set format %ux%u (%x) on RPF%u sink\n",
  119. __func__, format.format.width, format.format.height,
  120. format.format.code, rpf->entity.index);
  121. memset(&sel, 0, sizeof(sel));
  122. sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
  123. sel.pad = RWPF_PAD_SINK;
  124. sel.target = V4L2_SEL_TGT_CROP;
  125. sel.r = *crop;
  126. ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_selection, NULL,
  127. &sel);
  128. if (ret < 0)
  129. return ret;
  130. dev_dbg(vsp1->dev,
  131. "%s: set selection (%u,%u)/%ux%u on RPF%u sink\n",
  132. __func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
  133. rpf->entity.index);
  134. /*
  135. * RPF source, hardcode the format to ARGB8888 to turn on format
  136. * conversion if needed.
  137. */
  138. format.pad = RWPF_PAD_SOURCE;
  139. ret = v4l2_subdev_call(&rpf->entity.subdev, pad, get_fmt, NULL,
  140. &format);
  141. if (ret < 0)
  142. return ret;
  143. dev_dbg(vsp1->dev,
  144. "%s: got format %ux%u (%x) on RPF%u source\n",
  145. __func__, format.format.width, format.format.height,
  146. format.format.code, rpf->entity.index);
  147. format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
  148. ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_fmt, NULL,
  149. &format);
  150. if (ret < 0)
  151. return ret;
  152. /* Insert and configure the UIF if available. */
  153. ret = vsp1_du_insert_uif(vsp1, pipe, uif, &rpf->entity, RWPF_PAD_SOURCE,
  154. pipe->brx, brx_input);
  155. if (ret < 0)
  156. return ret;
  157. /* BRx sink, propagate the format from the RPF source. */
  158. format.pad = brx_input;
  159. ret = v4l2_subdev_call(&pipe->brx->subdev, pad, set_fmt, NULL,
  160. &format);
  161. if (ret < 0)
  162. return ret;
  163. dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
  164. __func__, format.format.width, format.format.height,
  165. format.format.code, BRX_NAME(pipe->brx), format.pad);
  166. sel.pad = brx_input;
  167. sel.target = V4L2_SEL_TGT_COMPOSE;
  168. sel.r = vsp1->drm->inputs[rpf->entity.index].compose;
  169. ret = v4l2_subdev_call(&pipe->brx->subdev, pad, set_selection, NULL,
  170. &sel);
  171. if (ret < 0)
  172. return ret;
  173. dev_dbg(vsp1->dev, "%s: set selection (%u,%u)/%ux%u on %s pad %u\n",
  174. __func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
  175. BRX_NAME(pipe->brx), sel.pad);
  176. return 0;
  177. }
  178. /* Setup the BRx source pad. */
  179. static int vsp1_du_pipeline_setup_inputs(struct vsp1_device *vsp1,
  180. struct vsp1_pipeline *pipe);
  181. static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe);
  182. static int vsp1_du_pipeline_setup_brx(struct vsp1_device *vsp1,
  183. struct vsp1_pipeline *pipe)
  184. {
  185. struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
  186. struct v4l2_subdev_format format = {
  187. .which = V4L2_SUBDEV_FORMAT_ACTIVE,
  188. };
  189. struct vsp1_entity *brx;
  190. int ret;
  191. /*
  192. * Pick a BRx:
  193. * - If we need more than two inputs, use the BRU.
  194. * - Otherwise, if we are not forced to release our BRx, keep it.
  195. * - Else, use any free BRx (randomly starting with the BRU).
  196. */
  197. if (pipe->num_inputs > 2)
  198. brx = &vsp1->bru->entity;
  199. else if (pipe->brx && !drm_pipe->force_brx_release)
  200. brx = pipe->brx;
  201. else if (vsp1_feature(vsp1, VSP1_HAS_BRU) && !vsp1->bru->entity.pipe)
  202. brx = &vsp1->bru->entity;
  203. else
  204. brx = &vsp1->brs->entity;
  205. /* Switch BRx if needed. */
  206. if (brx != pipe->brx) {
  207. struct vsp1_entity *released_brx = NULL;
  208. /* Release our BRx if we have one. */
  209. if (pipe->brx) {
  210. dev_dbg(vsp1->dev, "%s: pipe %u: releasing %s\n",
  211. __func__, pipe->lif->index,
  212. BRX_NAME(pipe->brx));
  213. /*
  214. * The BRx might be acquired by the other pipeline in
  215. * the next step. We must thus remove it from the list
  216. * of entities for this pipeline. The other pipeline's
  217. * hardware configuration will reconfigure the BRx
  218. * routing.
  219. *
  220. * However, if the other pipeline doesn't acquire our
  221. * BRx, we need to keep it in the list, otherwise the
  222. * hardware configuration step won't disconnect it from
  223. * the pipeline. To solve this, store the released BRx
  224. * pointer to add it back to the list of entities later
  225. * if it isn't acquired by the other pipeline.
  226. */
  227. released_brx = pipe->brx;
  228. list_del(&pipe->brx->list_pipe);
  229. pipe->brx->sink = NULL;
  230. pipe->brx->pipe = NULL;
  231. pipe->brx = NULL;
  232. }
  233. /*
  234. * If the BRx we need is in use, force the owner pipeline to
  235. * switch to the other BRx and wait until the switch completes.
  236. */
  237. if (brx->pipe) {
  238. struct vsp1_drm_pipeline *owner_pipe;
  239. dev_dbg(vsp1->dev, "%s: pipe %u: waiting for %s\n",
  240. __func__, pipe->lif->index, BRX_NAME(brx));
  241. owner_pipe = to_vsp1_drm_pipeline(brx->pipe);
  242. owner_pipe->force_brx_release = true;
  243. vsp1_du_pipeline_setup_inputs(vsp1, &owner_pipe->pipe);
  244. vsp1_du_pipeline_configure(&owner_pipe->pipe);
  245. ret = wait_event_timeout(owner_pipe->wait_queue,
  246. !owner_pipe->force_brx_release,
  247. msecs_to_jiffies(500));
  248. if (ret == 0)
  249. dev_warn(vsp1->dev,
  250. "DRM pipeline %u reconfiguration timeout\n",
  251. owner_pipe->pipe.lif->index);
  252. }
  253. /*
  254. * If the BRx we have released previously hasn't been acquired
  255. * by the other pipeline, add it back to the entities list (with
  256. * the pipe pointer NULL) to let vsp1_du_pipeline_configure()
  257. * disconnect it from the hardware pipeline.
  258. */
  259. if (released_brx && !released_brx->pipe)
  260. list_add_tail(&released_brx->list_pipe,
  261. &pipe->entities);
  262. /* Add the BRx to the pipeline. */
  263. dev_dbg(vsp1->dev, "%s: pipe %u: acquired %s\n",
  264. __func__, pipe->lif->index, BRX_NAME(brx));
  265. pipe->brx = brx;
  266. pipe->brx->pipe = pipe;
  267. pipe->brx->sink = &pipe->output->entity;
  268. pipe->brx->sink_pad = 0;
  269. list_add_tail(&pipe->brx->list_pipe, &pipe->entities);
  270. }
  271. /*
  272. * Configure the format on the BRx source and verify that it matches the
  273. * requested format. We don't set the media bus code as it is configured
  274. * on the BRx sink pad 0 and propagated inside the entity, not on the
  275. * source pad.
  276. */
  277. format.pad = pipe->brx->source_pad;
  278. format.format.width = drm_pipe->width;
  279. format.format.height = drm_pipe->height;
  280. format.format.field = V4L2_FIELD_NONE;
  281. ret = v4l2_subdev_call(&pipe->brx->subdev, pad, set_fmt, NULL,
  282. &format);
  283. if (ret < 0)
  284. return ret;
  285. dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
  286. __func__, format.format.width, format.format.height,
  287. format.format.code, BRX_NAME(pipe->brx), pipe->brx->source_pad);
  288. if (format.format.width != drm_pipe->width ||
  289. format.format.height != drm_pipe->height) {
  290. dev_dbg(vsp1->dev, "%s: format mismatch\n", __func__);
  291. return -EPIPE;
  292. }
  293. return 0;
  294. }
  295. static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf)
  296. {
  297. return vsp1->drm->inputs[rpf->entity.index].zpos;
  298. }
  299. /* Setup the input side of the pipeline (RPFs and BRx). */
  300. static int vsp1_du_pipeline_setup_inputs(struct vsp1_device *vsp1,
  301. struct vsp1_pipeline *pipe)
  302. {
  303. struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
  304. struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
  305. struct vsp1_entity *uif;
  306. bool use_uif = false;
  307. struct vsp1_brx *brx;
  308. unsigned int i;
  309. int ret;
  310. /* Count the number of enabled inputs and sort them by Z-order. */
  311. pipe->num_inputs = 0;
  312. for (i = 0; i < vsp1->info->rpf_count; ++i) {
  313. struct vsp1_rwpf *rpf = vsp1->rpf[i];
  314. unsigned int j;
  315. if (!pipe->inputs[i])
  316. continue;
  317. /* Insert the RPF in the sorted RPFs array. */
  318. for (j = pipe->num_inputs++; j > 0; --j) {
  319. if (rpf_zpos(vsp1, inputs[j-1]) <= rpf_zpos(vsp1, rpf))
  320. break;
  321. inputs[j] = inputs[j-1];
  322. }
  323. inputs[j] = rpf;
  324. }
  325. /*
  326. * Setup the BRx. This must be done before setting up the RPF input
  327. * pipelines as the BRx sink compose rectangles depend on the BRx source
  328. * format.
  329. */
  330. ret = vsp1_du_pipeline_setup_brx(vsp1, pipe);
  331. if (ret < 0) {
  332. dev_err(vsp1->dev, "%s: failed to setup %s source\n", __func__,
  333. BRX_NAME(pipe->brx));
  334. return ret;
  335. }
  336. brx = to_brx(&pipe->brx->subdev);
  337. /* Setup the RPF input pipeline for every enabled input. */
  338. for (i = 0; i < pipe->brx->source_pad; ++i) {
  339. struct vsp1_rwpf *rpf = inputs[i];
  340. if (!rpf) {
  341. brx->inputs[i].rpf = NULL;
  342. continue;
  343. }
  344. if (!rpf->entity.pipe) {
  345. rpf->entity.pipe = pipe;
  346. list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
  347. }
  348. brx->inputs[i].rpf = rpf;
  349. rpf->brx_input = i;
  350. rpf->entity.sink = pipe->brx;
  351. rpf->entity.sink_pad = i;
  352. dev_dbg(vsp1->dev, "%s: connecting RPF.%u to %s:%u\n",
  353. __func__, rpf->entity.index, BRX_NAME(pipe->brx), i);
  354. uif = drm_pipe->crc.source == VSP1_DU_CRC_PLANE &&
  355. drm_pipe->crc.index == i ? drm_pipe->uif : NULL;
  356. if (uif)
  357. use_uif = true;
  358. ret = vsp1_du_pipeline_setup_rpf(vsp1, pipe, rpf, uif, i);
  359. if (ret < 0) {
  360. dev_err(vsp1->dev,
  361. "%s: failed to setup RPF.%u\n",
  362. __func__, rpf->entity.index);
  363. return ret;
  364. }
  365. }
  366. /* Insert and configure the UIF at the BRx output if available. */
  367. uif = drm_pipe->crc.source == VSP1_DU_CRC_OUTPUT ? drm_pipe->uif : NULL;
  368. if (uif)
  369. use_uif = true;
  370. ret = vsp1_du_insert_uif(vsp1, pipe, uif,
  371. pipe->brx, pipe->brx->source_pad,
  372. &pipe->output->entity, 0);
  373. if (ret < 0)
  374. dev_err(vsp1->dev, "%s: failed to setup UIF after %s\n",
  375. __func__, BRX_NAME(pipe->brx));
  376. /*
  377. * If the UIF is not in use schedule it for removal by setting its pipe
  378. * pointer to NULL, vsp1_du_pipeline_configure() will remove it from the
  379. * hardware pipeline and from the pipeline's list of entities. Otherwise
  380. * make sure it is present in the pipeline's list of entities if it
  381. * wasn't already.
  382. */
  383. if (drm_pipe->uif && !use_uif) {
  384. drm_pipe->uif->pipe = NULL;
  385. } else if (drm_pipe->uif && !drm_pipe->uif->pipe) {
  386. drm_pipe->uif->pipe = pipe;
  387. list_add_tail(&drm_pipe->uif->list_pipe, &pipe->entities);
  388. }
  389. return 0;
  390. }
  391. /* Setup the output side of the pipeline (WPF and LIF). */
  392. static int vsp1_du_pipeline_setup_output(struct vsp1_device *vsp1,
  393. struct vsp1_pipeline *pipe)
  394. {
  395. struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
  396. struct v4l2_subdev_format format = { 0, };
  397. int ret;
  398. format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
  399. format.pad = RWPF_PAD_SINK;
  400. format.format.width = drm_pipe->width;
  401. format.format.height = drm_pipe->height;
  402. format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
  403. format.format.field = V4L2_FIELD_NONE;
  404. ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt, NULL,
  405. &format);
  406. if (ret < 0)
  407. return ret;
  408. dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on WPF%u sink\n",
  409. __func__, format.format.width, format.format.height,
  410. format.format.code, pipe->output->entity.index);
  411. format.pad = RWPF_PAD_SOURCE;
  412. ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, get_fmt, NULL,
  413. &format);
  414. if (ret < 0)
  415. return ret;
  416. dev_dbg(vsp1->dev, "%s: got format %ux%u (%x) on WPF%u source\n",
  417. __func__, format.format.width, format.format.height,
  418. format.format.code, pipe->output->entity.index);
  419. format.pad = LIF_PAD_SINK;
  420. ret = v4l2_subdev_call(&pipe->lif->subdev, pad, set_fmt, NULL,
  421. &format);
  422. if (ret < 0)
  423. return ret;
  424. dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on LIF%u sink\n",
  425. __func__, format.format.width, format.format.height,
  426. format.format.code, pipe->lif->index);
  427. /*
  428. * Verify that the format at the output of the pipeline matches the
  429. * requested frame size and media bus code.
  430. */
  431. if (format.format.width != drm_pipe->width ||
  432. format.format.height != drm_pipe->height ||
  433. format.format.code != MEDIA_BUS_FMT_ARGB8888_1X32) {
  434. dev_dbg(vsp1->dev, "%s: format mismatch on LIF%u\n", __func__,
  435. pipe->lif->index);
  436. return -EPIPE;
  437. }
  438. return 0;
  439. }
  440. /* Configure all entities in the pipeline. */
  441. static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
  442. {
  443. struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
  444. struct vsp1_entity *entity;
  445. struct vsp1_entity *next;
  446. struct vsp1_dl_list *dl;
  447. struct vsp1_dl_body *dlb;
  448. dl = vsp1_dl_list_get(pipe->output->dlm);
  449. dlb = vsp1_dl_list_get_body0(dl);
  450. list_for_each_entry_safe(entity, next, &pipe->entities, list_pipe) {
  451. /* Disconnect unused entities from the pipeline. */
  452. if (!entity->pipe) {
  453. vsp1_dl_body_write(dlb, entity->route->reg,
  454. VI6_DPR_NODE_UNUSED);
  455. entity->sink = NULL;
  456. list_del(&entity->list_pipe);
  457. continue;
  458. }
  459. vsp1_entity_route_setup(entity, pipe, dlb);
  460. vsp1_entity_configure_stream(entity, pipe, dlb);
  461. vsp1_entity_configure_frame(entity, pipe, dl, dlb);
  462. vsp1_entity_configure_partition(entity, pipe, dl, dlb);
  463. }
  464. vsp1_dl_list_commit(dl, drm_pipe->force_brx_release);
  465. }
  466. /* -----------------------------------------------------------------------------
  467. * DU Driver API
  468. */
  469. int vsp1_du_init(struct device *dev)
  470. {
  471. struct vsp1_device *vsp1 = dev_get_drvdata(dev);
  472. if (!vsp1)
  473. return -EPROBE_DEFER;
  474. return 0;
  475. }
  476. EXPORT_SYMBOL_GPL(vsp1_du_init);
  477. /**
  478. * vsp1_du_setup_lif - Setup the output part of the VSP pipeline
  479. * @dev: the VSP device
  480. * @pipe_index: the DRM pipeline index
  481. * @cfg: the LIF configuration
  482. *
  483. * Configure the output part of VSP DRM pipeline for the given frame @cfg.width
  484. * and @cfg.height. This sets up formats on the BRx source pad, the WPF sink and
  485. * source pads, and the LIF sink pad.
  486. *
  487. * The @pipe_index argument selects which DRM pipeline to setup. The number of
  488. * available pipelines depend on the VSP instance.
  489. *
  490. * As the media bus code on the blend unit source pad is conditioned by the
  491. * configuration of its sink 0 pad, we also set up the formats on all blend unit
  492. * sinks, even if the configuration will be overwritten later by
  493. * vsp1_du_setup_rpf(). This ensures that the blend unit configuration is set to
  494. * a well defined state.
  495. *
  496. * Return 0 on success or a negative error code on failure.
  497. */
  498. int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
  499. const struct vsp1_du_lif_config *cfg)
  500. {
  501. struct vsp1_device *vsp1 = dev_get_drvdata(dev);
  502. struct vsp1_drm_pipeline *drm_pipe;
  503. struct vsp1_pipeline *pipe;
  504. unsigned long flags;
  505. unsigned int i;
  506. int ret;
  507. if (pipe_index >= vsp1->info->lif_count)
  508. return -EINVAL;
  509. drm_pipe = &vsp1->drm->pipe[pipe_index];
  510. pipe = &drm_pipe->pipe;
  511. if (!cfg) {
  512. struct vsp1_brx *brx;
  513. mutex_lock(&vsp1->drm->lock);
  514. brx = to_brx(&pipe->brx->subdev);
  515. /*
  516. * NULL configuration means the CRTC is being disabled, stop
  517. * the pipeline and turn the light off.
  518. */
  519. ret = vsp1_pipeline_stop(pipe);
  520. if (ret == -ETIMEDOUT)
  521. dev_err(vsp1->dev, "DRM pipeline stop timeout\n");
  522. for (i = 0; i < ARRAY_SIZE(pipe->inputs); ++i) {
  523. struct vsp1_rwpf *rpf = pipe->inputs[i];
  524. if (!rpf)
  525. continue;
  526. /*
  527. * Remove the RPF from the pipe and the list of BRx
  528. * inputs.
  529. */
  530. WARN_ON(!rpf->entity.pipe);
  531. rpf->entity.pipe = NULL;
  532. list_del(&rpf->entity.list_pipe);
  533. pipe->inputs[i] = NULL;
  534. brx->inputs[rpf->brx_input].rpf = NULL;
  535. }
  536. drm_pipe->du_complete = NULL;
  537. pipe->num_inputs = 0;
  538. dev_dbg(vsp1->dev, "%s: pipe %u: releasing %s\n",
  539. __func__, pipe->lif->index,
  540. BRX_NAME(pipe->brx));
  541. list_del(&pipe->brx->list_pipe);
  542. pipe->brx->pipe = NULL;
  543. pipe->brx = NULL;
  544. mutex_unlock(&vsp1->drm->lock);
  545. vsp1_dlm_reset(pipe->output->dlm);
  546. vsp1_device_put(vsp1);
  547. dev_dbg(vsp1->dev, "%s: pipeline disabled\n", __func__);
  548. return 0;
  549. }
  550. drm_pipe->width = cfg->width;
  551. drm_pipe->height = cfg->height;
  552. pipe->interlaced = cfg->interlaced;
  553. dev_dbg(vsp1->dev, "%s: configuring LIF%u with format %ux%u%s\n",
  554. __func__, pipe_index, cfg->width, cfg->height,
  555. pipe->interlaced ? "i" : "");
  556. mutex_lock(&vsp1->drm->lock);
  557. /* Setup formats through the pipeline. */
  558. ret = vsp1_du_pipeline_setup_inputs(vsp1, pipe);
  559. if (ret < 0)
  560. goto unlock;
  561. ret = vsp1_du_pipeline_setup_output(vsp1, pipe);
  562. if (ret < 0)
  563. goto unlock;
  564. /* Enable the VSP1. */
  565. ret = vsp1_device_get(vsp1);
  566. if (ret < 0)
  567. goto unlock;
  568. /*
  569. * Register a callback to allow us to notify the DRM driver of frame
  570. * completion events.
  571. */
  572. drm_pipe->du_complete = cfg->callback;
  573. drm_pipe->du_private = cfg->callback_data;
  574. /* Disable the display interrupts. */
  575. vsp1_write(vsp1, VI6_DISP_IRQ_STA, 0);
  576. vsp1_write(vsp1, VI6_DISP_IRQ_ENB, 0);
  577. /* Configure all entities in the pipeline. */
  578. vsp1_du_pipeline_configure(pipe);
  579. unlock:
  580. mutex_unlock(&vsp1->drm->lock);
  581. if (ret < 0)
  582. return ret;
  583. /* Start the pipeline. */
  584. spin_lock_irqsave(&pipe->irqlock, flags);
  585. vsp1_pipeline_run(pipe);
  586. spin_unlock_irqrestore(&pipe->irqlock, flags);
  587. dev_dbg(vsp1->dev, "%s: pipeline enabled\n", __func__);
  588. return 0;
  589. }
  590. EXPORT_SYMBOL_GPL(vsp1_du_setup_lif);
  591. /**
  592. * vsp1_du_atomic_begin - Prepare for an atomic update
  593. * @dev: the VSP device
  594. * @pipe_index: the DRM pipeline index
  595. */
  596. void vsp1_du_atomic_begin(struct device *dev, unsigned int pipe_index)
  597. {
  598. }
  599. EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin);
  600. /**
  601. * vsp1_du_atomic_update - Setup one RPF input of the VSP pipeline
  602. * @dev: the VSP device
  603. * @pipe_index: the DRM pipeline index
  604. * @rpf_index: index of the RPF to setup (0-based)
  605. * @cfg: the RPF configuration
  606. *
  607. * Configure the VSP to perform image composition through RPF @rpf_index as
  608. * described by the @cfg configuration. The image to compose is referenced by
  609. * @cfg.mem and composed using the @cfg.src crop rectangle and the @cfg.dst
  610. * composition rectangle. The Z-order is configurable with higher @zpos values
  611. * displayed on top.
  612. *
  613. * If the @cfg configuration is NULL, the RPF will be disabled. Calling the
  614. * function on a disabled RPF is allowed.
  615. *
  616. * Image format as stored in memory is expressed as a V4L2 @cfg.pixelformat
  617. * value. The memory pitch is configurable to allow for padding at end of lines,
  618. * or simply for images that extend beyond the crop rectangle boundaries. The
  619. * @cfg.pitch value is expressed in bytes and applies to all planes for
  620. * multiplanar formats.
  621. *
  622. * The source memory buffer is referenced by the DMA address of its planes in
  623. * the @cfg.mem array. Up to two planes are supported. The second plane DMA
  624. * address is ignored for formats using a single plane.
  625. *
  626. * This function isn't reentrant, the caller needs to serialize calls.
  627. *
  628. * Return 0 on success or a negative error code on failure.
  629. */
  630. int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index,
  631. unsigned int rpf_index,
  632. const struct vsp1_du_atomic_config *cfg)
  633. {
  634. struct vsp1_device *vsp1 = dev_get_drvdata(dev);
  635. struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index];
  636. const struct vsp1_format_info *fmtinfo;
  637. unsigned int chroma_hsub;
  638. struct vsp1_rwpf *rpf;
  639. if (rpf_index >= vsp1->info->rpf_count)
  640. return -EINVAL;
  641. rpf = vsp1->rpf[rpf_index];
  642. if (!cfg) {
  643. dev_dbg(vsp1->dev, "%s: RPF%u: disable requested\n", __func__,
  644. rpf_index);
  645. /*
  646. * Remove the RPF from the pipeline's inputs. Keep it in the
  647. * pipeline's entity list to let vsp1_du_pipeline_configure()
  648. * remove it from the hardware pipeline.
  649. */
  650. rpf->entity.pipe = NULL;
  651. drm_pipe->pipe.inputs[rpf_index] = NULL;
  652. return 0;
  653. }
  654. dev_dbg(vsp1->dev,
  655. "%s: RPF%u: (%u,%u)/%ux%u -> (%u,%u)/%ux%u (%08x), pitch %u dma { %pad, %pad, %pad } zpos %u\n",
  656. __func__, rpf_index,
  657. cfg->src.left, cfg->src.top, cfg->src.width, cfg->src.height,
  658. cfg->dst.left, cfg->dst.top, cfg->dst.width, cfg->dst.height,
  659. cfg->pixelformat, cfg->pitch, &cfg->mem[0], &cfg->mem[1],
  660. &cfg->mem[2], cfg->zpos);
  661. /*
  662. * Store the format, stride, memory buffer address, crop and compose
  663. * rectangles and Z-order position and for the input.
  664. */
  665. fmtinfo = vsp1_get_format_info(vsp1, cfg->pixelformat);
  666. if (!fmtinfo) {
  667. dev_dbg(vsp1->dev, "Unsupported pixel format %08x for RPF\n",
  668. cfg->pixelformat);
  669. return -EINVAL;
  670. }
  671. /*
  672. * Only formats with three planes can affect the chroma planes pitch.
  673. * All formats with two planes have a horizontal subsampling value of 2,
  674. * but combine U and V in a single chroma plane, which thus results in
  675. * the luma plane and chroma plane having the same pitch.
  676. */
  677. chroma_hsub = (fmtinfo->planes == 3) ? fmtinfo->hsub : 1;
  678. rpf->fmtinfo = fmtinfo;
  679. rpf->format.num_planes = fmtinfo->planes;
  680. rpf->format.plane_fmt[0].bytesperline = cfg->pitch;
  681. rpf->format.plane_fmt[1].bytesperline = cfg->pitch / chroma_hsub;
  682. rpf->alpha = cfg->alpha;
  683. rpf->mem.addr[0] = cfg->mem[0];
  684. rpf->mem.addr[1] = cfg->mem[1];
  685. rpf->mem.addr[2] = cfg->mem[2];
  686. vsp1->drm->inputs[rpf_index].crop = cfg->src;
  687. vsp1->drm->inputs[rpf_index].compose = cfg->dst;
  688. vsp1->drm->inputs[rpf_index].zpos = cfg->zpos;
  689. drm_pipe->pipe.inputs[rpf_index] = rpf;
  690. return 0;
  691. }
  692. EXPORT_SYMBOL_GPL(vsp1_du_atomic_update);
  693. /**
  694. * vsp1_du_atomic_flush - Commit an atomic update
  695. * @dev: the VSP device
  696. * @pipe_index: the DRM pipeline index
  697. * @cfg: atomic pipe configuration
  698. */
  699. void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index,
  700. const struct vsp1_du_atomic_pipe_config *cfg)
  701. {
  702. struct vsp1_device *vsp1 = dev_get_drvdata(dev);
  703. struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index];
  704. struct vsp1_pipeline *pipe = &drm_pipe->pipe;
  705. drm_pipe->crc = cfg->crc;
  706. mutex_lock(&vsp1->drm->lock);
  707. vsp1_du_pipeline_setup_inputs(vsp1, pipe);
  708. vsp1_du_pipeline_configure(pipe);
  709. mutex_unlock(&vsp1->drm->lock);
  710. }
  711. EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush);
  712. int vsp1_du_map_sg(struct device *dev, struct sg_table *sgt)
  713. {
  714. struct vsp1_device *vsp1 = dev_get_drvdata(dev);
  715. /*
  716. * As all the buffers allocated by the DU driver are coherent, we can
  717. * skip cache sync. This will need to be revisited when support for
  718. * non-coherent buffers will be added to the DU driver.
  719. */
  720. return dma_map_sg_attrs(vsp1->bus_master, sgt->sgl, sgt->nents,
  721. DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC);
  722. }
  723. EXPORT_SYMBOL_GPL(vsp1_du_map_sg);
  724. void vsp1_du_unmap_sg(struct device *dev, struct sg_table *sgt)
  725. {
  726. struct vsp1_device *vsp1 = dev_get_drvdata(dev);
  727. dma_unmap_sg_attrs(vsp1->bus_master, sgt->sgl, sgt->nents,
  728. DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC);
  729. }
  730. EXPORT_SYMBOL_GPL(vsp1_du_unmap_sg);
  731. /* -----------------------------------------------------------------------------
  732. * Initialization
  733. */
  734. int vsp1_drm_init(struct vsp1_device *vsp1)
  735. {
  736. unsigned int i;
  737. vsp1->drm = devm_kzalloc(vsp1->dev, sizeof(*vsp1->drm), GFP_KERNEL);
  738. if (!vsp1->drm)
  739. return -ENOMEM;
  740. mutex_init(&vsp1->drm->lock);
  741. /* Create one DRM pipeline per LIF. */
  742. for (i = 0; i < vsp1->info->lif_count; ++i) {
  743. struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[i];
  744. struct vsp1_pipeline *pipe = &drm_pipe->pipe;
  745. init_waitqueue_head(&drm_pipe->wait_queue);
  746. vsp1_pipeline_init(pipe);
  747. pipe->frame_end = vsp1_du_pipeline_frame_end;
  748. /*
  749. * The output side of the DRM pipeline is static, add the
  750. * corresponding entities manually.
  751. */
  752. pipe->output = vsp1->wpf[i];
  753. pipe->lif = &vsp1->lif[i]->entity;
  754. pipe->output->entity.pipe = pipe;
  755. pipe->output->entity.sink = pipe->lif;
  756. pipe->output->entity.sink_pad = 0;
  757. list_add_tail(&pipe->output->entity.list_pipe, &pipe->entities);
  758. pipe->lif->pipe = pipe;
  759. list_add_tail(&pipe->lif->list_pipe, &pipe->entities);
  760. /*
  761. * CRC computation is initially disabled, don't add the UIF to
  762. * the pipeline.
  763. */
  764. if (i < vsp1->info->uif_count)
  765. drm_pipe->uif = &vsp1->uif[i]->entity;
  766. }
  767. /* Disable all RPFs initially. */
  768. for (i = 0; i < vsp1->info->rpf_count; ++i) {
  769. struct vsp1_rwpf *input = vsp1->rpf[i];
  770. INIT_LIST_HEAD(&input->entity.list_pipe);
  771. }
  772. return 0;
  773. }
  774. void vsp1_drm_cleanup(struct vsp1_device *vsp1)
  775. {
  776. mutex_destroy(&vsp1->drm->lock);
  777. }