vsp1_drm.c 23 KB

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