vsp1_pipe.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. /*
  2. * vsp1_pipe.c -- R-Car VSP1 Pipeline
  3. *
  4. * Copyright (C) 2013-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/delay.h>
  14. #include <linux/list.h>
  15. #include <linux/sched.h>
  16. #include <linux/wait.h>
  17. #include <media/media-entity.h>
  18. #include <media/v4l2-subdev.h>
  19. #include "vsp1.h"
  20. #include "vsp1_bru.h"
  21. #include "vsp1_dl.h"
  22. #include "vsp1_entity.h"
  23. #include "vsp1_pipe.h"
  24. #include "vsp1_rwpf.h"
  25. #include "vsp1_uds.h"
  26. /* -----------------------------------------------------------------------------
  27. * Helper Functions
  28. */
  29. static const struct vsp1_format_info vsp1_video_formats[] = {
  30. { V4L2_PIX_FMT_RGB332, MEDIA_BUS_FMT_ARGB8888_1X32,
  31. VI6_FMT_RGB_332, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  32. VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
  33. 1, { 8, 0, 0 }, false, false, 1, 1, false },
  34. { V4L2_PIX_FMT_ARGB444, MEDIA_BUS_FMT_ARGB8888_1X32,
  35. VI6_FMT_ARGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  36. VI6_RPF_DSWAP_P_WDS,
  37. 1, { 16, 0, 0 }, false, false, 1, 1, true },
  38. { V4L2_PIX_FMT_XRGB444, MEDIA_BUS_FMT_ARGB8888_1X32,
  39. VI6_FMT_XRGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  40. VI6_RPF_DSWAP_P_WDS,
  41. 1, { 16, 0, 0 }, false, false, 1, 1, false },
  42. { V4L2_PIX_FMT_ARGB555, MEDIA_BUS_FMT_ARGB8888_1X32,
  43. VI6_FMT_ARGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  44. VI6_RPF_DSWAP_P_WDS,
  45. 1, { 16, 0, 0 }, false, false, 1, 1, true },
  46. { V4L2_PIX_FMT_XRGB555, MEDIA_BUS_FMT_ARGB8888_1X32,
  47. VI6_FMT_XRGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  48. VI6_RPF_DSWAP_P_WDS,
  49. 1, { 16, 0, 0 }, false, false, 1, 1, false },
  50. { V4L2_PIX_FMT_RGB565, MEDIA_BUS_FMT_ARGB8888_1X32,
  51. VI6_FMT_RGB_565, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  52. VI6_RPF_DSWAP_P_WDS,
  53. 1, { 16, 0, 0 }, false, false, 1, 1, false },
  54. { V4L2_PIX_FMT_BGR24, MEDIA_BUS_FMT_ARGB8888_1X32,
  55. VI6_FMT_BGR_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  56. VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
  57. 1, { 24, 0, 0 }, false, false, 1, 1, false },
  58. { V4L2_PIX_FMT_RGB24, MEDIA_BUS_FMT_ARGB8888_1X32,
  59. VI6_FMT_RGB_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  60. VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
  61. 1, { 24, 0, 0 }, false, false, 1, 1, false },
  62. { V4L2_PIX_FMT_ABGR32, MEDIA_BUS_FMT_ARGB8888_1X32,
  63. VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
  64. 1, { 32, 0, 0 }, false, false, 1, 1, true },
  65. { V4L2_PIX_FMT_XBGR32, MEDIA_BUS_FMT_ARGB8888_1X32,
  66. VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
  67. 1, { 32, 0, 0 }, false, false, 1, 1, false },
  68. { V4L2_PIX_FMT_ARGB32, MEDIA_BUS_FMT_ARGB8888_1X32,
  69. VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  70. VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
  71. 1, { 32, 0, 0 }, false, false, 1, 1, true },
  72. { V4L2_PIX_FMT_XRGB32, MEDIA_BUS_FMT_ARGB8888_1X32,
  73. VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  74. VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
  75. 1, { 32, 0, 0 }, false, false, 1, 1, false },
  76. { V4L2_PIX_FMT_HSV24, MEDIA_BUS_FMT_AHSV8888_1X32,
  77. VI6_FMT_RGB_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  78. VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
  79. 1, { 24, 0, 0 }, false, false, 1, 1, false },
  80. { V4L2_PIX_FMT_HSV32, MEDIA_BUS_FMT_AHSV8888_1X32,
  81. VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  82. VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
  83. 1, { 32, 0, 0 }, false, false, 1, 1, false },
  84. { V4L2_PIX_FMT_UYVY, MEDIA_BUS_FMT_AYUV8_1X32,
  85. VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  86. VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
  87. 1, { 16, 0, 0 }, false, false, 2, 1, false },
  88. { V4L2_PIX_FMT_VYUY, MEDIA_BUS_FMT_AYUV8_1X32,
  89. VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  90. VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
  91. 1, { 16, 0, 0 }, false, true, 2, 1, false },
  92. { V4L2_PIX_FMT_YUYV, MEDIA_BUS_FMT_AYUV8_1X32,
  93. VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  94. VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
  95. 1, { 16, 0, 0 }, true, false, 2, 1, false },
  96. { V4L2_PIX_FMT_YVYU, MEDIA_BUS_FMT_AYUV8_1X32,
  97. VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  98. VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
  99. 1, { 16, 0, 0 }, true, true, 2, 1, false },
  100. { V4L2_PIX_FMT_NV12M, MEDIA_BUS_FMT_AYUV8_1X32,
  101. VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  102. VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
  103. 2, { 8, 16, 0 }, false, false, 2, 2, false },
  104. { V4L2_PIX_FMT_NV21M, MEDIA_BUS_FMT_AYUV8_1X32,
  105. VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  106. VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
  107. 2, { 8, 16, 0 }, false, true, 2, 2, false },
  108. { V4L2_PIX_FMT_NV16M, MEDIA_BUS_FMT_AYUV8_1X32,
  109. VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  110. VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
  111. 2, { 8, 16, 0 }, false, false, 2, 1, false },
  112. { V4L2_PIX_FMT_NV61M, MEDIA_BUS_FMT_AYUV8_1X32,
  113. VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  114. VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
  115. 2, { 8, 16, 0 }, false, true, 2, 1, false },
  116. { V4L2_PIX_FMT_YUV420M, MEDIA_BUS_FMT_AYUV8_1X32,
  117. VI6_FMT_Y_U_V_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  118. VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
  119. 3, { 8, 8, 8 }, false, false, 2, 2, false },
  120. { V4L2_PIX_FMT_YVU420M, MEDIA_BUS_FMT_AYUV8_1X32,
  121. VI6_FMT_Y_U_V_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  122. VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
  123. 3, { 8, 8, 8 }, false, true, 2, 2, false },
  124. { V4L2_PIX_FMT_YUV422M, MEDIA_BUS_FMT_AYUV8_1X32,
  125. VI6_FMT_Y_U_V_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  126. VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
  127. 3, { 8, 8, 8 }, false, false, 2, 1, false },
  128. { V4L2_PIX_FMT_YVU422M, MEDIA_BUS_FMT_AYUV8_1X32,
  129. VI6_FMT_Y_U_V_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  130. VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
  131. 3, { 8, 8, 8 }, false, true, 2, 1, false },
  132. { V4L2_PIX_FMT_YUV444M, MEDIA_BUS_FMT_AYUV8_1X32,
  133. VI6_FMT_Y_U_V_444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  134. VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
  135. 3, { 8, 8, 8 }, false, false, 1, 1, false },
  136. { V4L2_PIX_FMT_YVU444M, MEDIA_BUS_FMT_AYUV8_1X32,
  137. VI6_FMT_Y_U_V_444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
  138. VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
  139. 3, { 8, 8, 8 }, false, true, 1, 1, false },
  140. };
  141. /**
  142. * vsp1_get_format_info - Retrieve format information for a 4CC
  143. * @vsp1: the VSP1 device
  144. * @fourcc: the format 4CC
  145. *
  146. * Return a pointer to the format information structure corresponding to the
  147. * given V4L2 format 4CC, or NULL if no corresponding format can be found.
  148. */
  149. const struct vsp1_format_info *vsp1_get_format_info(struct vsp1_device *vsp1,
  150. u32 fourcc)
  151. {
  152. unsigned int i;
  153. /* Special case, the VYUY format is supported on Gen2 only. */
  154. if (vsp1->info->gen != 2 && fourcc == V4L2_PIX_FMT_VYUY)
  155. return NULL;
  156. for (i = 0; i < ARRAY_SIZE(vsp1_video_formats); ++i) {
  157. const struct vsp1_format_info *info = &vsp1_video_formats[i];
  158. if (info->fourcc == fourcc)
  159. return info;
  160. }
  161. return NULL;
  162. }
  163. /* -----------------------------------------------------------------------------
  164. * Pipeline Management
  165. */
  166. void vsp1_pipeline_reset(struct vsp1_pipeline *pipe)
  167. {
  168. unsigned int i;
  169. if (pipe->bru) {
  170. struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
  171. for (i = 0; i < ARRAY_SIZE(bru->inputs); ++i)
  172. bru->inputs[i].rpf = NULL;
  173. }
  174. for (i = 0; i < ARRAY_SIZE(pipe->inputs); ++i) {
  175. if (pipe->inputs[i]) {
  176. pipe->inputs[i]->pipe = NULL;
  177. pipe->inputs[i] = NULL;
  178. }
  179. }
  180. if (pipe->output) {
  181. pipe->output->pipe = NULL;
  182. pipe->output = NULL;
  183. }
  184. INIT_LIST_HEAD(&pipe->entities);
  185. pipe->state = VSP1_PIPELINE_STOPPED;
  186. pipe->buffers_ready = 0;
  187. pipe->num_inputs = 0;
  188. pipe->bru = NULL;
  189. pipe->lif = NULL;
  190. pipe->uds = NULL;
  191. }
  192. void vsp1_pipeline_init(struct vsp1_pipeline *pipe)
  193. {
  194. mutex_init(&pipe->lock);
  195. spin_lock_init(&pipe->irqlock);
  196. init_waitqueue_head(&pipe->wq);
  197. kref_init(&pipe->kref);
  198. INIT_LIST_HEAD(&pipe->entities);
  199. pipe->state = VSP1_PIPELINE_STOPPED;
  200. }
  201. /* Must be called with the pipe irqlock held. */
  202. void vsp1_pipeline_run(struct vsp1_pipeline *pipe)
  203. {
  204. struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
  205. if (pipe->state == VSP1_PIPELINE_STOPPED) {
  206. vsp1_write(vsp1, VI6_CMD(pipe->output->entity.index),
  207. VI6_CMD_STRCMD);
  208. pipe->state = VSP1_PIPELINE_RUNNING;
  209. }
  210. pipe->buffers_ready = 0;
  211. }
  212. bool vsp1_pipeline_stopped(struct vsp1_pipeline *pipe)
  213. {
  214. unsigned long flags;
  215. bool stopped;
  216. spin_lock_irqsave(&pipe->irqlock, flags);
  217. stopped = pipe->state == VSP1_PIPELINE_STOPPED;
  218. spin_unlock_irqrestore(&pipe->irqlock, flags);
  219. return stopped;
  220. }
  221. int vsp1_pipeline_stop(struct vsp1_pipeline *pipe)
  222. {
  223. struct vsp1_entity *entity;
  224. unsigned long flags;
  225. int ret;
  226. if (pipe->lif) {
  227. /* When using display lists in continuous frame mode the only
  228. * way to stop the pipeline is to reset the hardware.
  229. */
  230. ret = vsp1_reset_wpf(pipe->output->entity.vsp1,
  231. pipe->output->entity.index);
  232. if (ret == 0) {
  233. spin_lock_irqsave(&pipe->irqlock, flags);
  234. pipe->state = VSP1_PIPELINE_STOPPED;
  235. spin_unlock_irqrestore(&pipe->irqlock, flags);
  236. }
  237. } else {
  238. /* Otherwise just request a stop and wait. */
  239. spin_lock_irqsave(&pipe->irqlock, flags);
  240. if (pipe->state == VSP1_PIPELINE_RUNNING)
  241. pipe->state = VSP1_PIPELINE_STOPPING;
  242. spin_unlock_irqrestore(&pipe->irqlock, flags);
  243. ret = wait_event_timeout(pipe->wq, vsp1_pipeline_stopped(pipe),
  244. msecs_to_jiffies(500));
  245. ret = ret == 0 ? -ETIMEDOUT : 0;
  246. }
  247. list_for_each_entry(entity, &pipe->entities, list_pipe) {
  248. if (entity->route && entity->route->reg)
  249. vsp1_write(entity->vsp1, entity->route->reg,
  250. VI6_DPR_NODE_UNUSED);
  251. }
  252. v4l2_subdev_call(&pipe->output->entity.subdev, video, s_stream, 0);
  253. return ret;
  254. }
  255. bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe)
  256. {
  257. unsigned int mask;
  258. mask = ((1 << pipe->num_inputs) - 1) << 1;
  259. if (!pipe->lif)
  260. mask |= 1 << 0;
  261. return pipe->buffers_ready == mask;
  262. }
  263. void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
  264. {
  265. if (pipe == NULL)
  266. return;
  267. vsp1_dlm_irq_frame_end(pipe->output->dlm);
  268. if (pipe->frame_end)
  269. pipe->frame_end(pipe);
  270. pipe->sequence++;
  271. }
  272. /*
  273. * Propagate the alpha value through the pipeline.
  274. *
  275. * As the UDS has restricted scaling capabilities when the alpha component needs
  276. * to be scaled, we disable alpha scaling when the UDS input has a fixed alpha
  277. * value. The UDS then outputs a fixed alpha value which needs to be programmed
  278. * from the input RPF alpha.
  279. */
  280. void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
  281. struct vsp1_dl_list *dl, unsigned int alpha)
  282. {
  283. if (!pipe->uds)
  284. return;
  285. /* The BRU background color has a fixed alpha value set to 255, the
  286. * output alpha value is thus always equal to 255.
  287. */
  288. if (pipe->uds_input->type == VSP1_ENTITY_BRU)
  289. alpha = 255;
  290. vsp1_uds_set_alpha(pipe->uds, dl, alpha);
  291. }
  292. void vsp1_pipelines_suspend(struct vsp1_device *vsp1)
  293. {
  294. unsigned long flags;
  295. unsigned int i;
  296. int ret;
  297. /* To avoid increasing the system suspend time needlessly, loop over the
  298. * pipelines twice, first to set them all to the stopping state, and
  299. * then to wait for the stop to complete.
  300. */
  301. for (i = 0; i < vsp1->info->wpf_count; ++i) {
  302. struct vsp1_rwpf *wpf = vsp1->wpf[i];
  303. struct vsp1_pipeline *pipe;
  304. if (wpf == NULL)
  305. continue;
  306. pipe = wpf->pipe;
  307. if (pipe == NULL)
  308. continue;
  309. spin_lock_irqsave(&pipe->irqlock, flags);
  310. if (pipe->state == VSP1_PIPELINE_RUNNING)
  311. pipe->state = VSP1_PIPELINE_STOPPING;
  312. spin_unlock_irqrestore(&pipe->irqlock, flags);
  313. }
  314. for (i = 0; i < vsp1->info->wpf_count; ++i) {
  315. struct vsp1_rwpf *wpf = vsp1->wpf[i];
  316. struct vsp1_pipeline *pipe;
  317. if (wpf == NULL)
  318. continue;
  319. pipe = wpf->pipe;
  320. if (pipe == NULL)
  321. continue;
  322. ret = wait_event_timeout(pipe->wq, vsp1_pipeline_stopped(pipe),
  323. msecs_to_jiffies(500));
  324. if (ret == 0)
  325. dev_warn(vsp1->dev, "pipeline %u stop timeout\n",
  326. wpf->entity.index);
  327. }
  328. }
  329. void vsp1_pipelines_resume(struct vsp1_device *vsp1)
  330. {
  331. unsigned long flags;
  332. unsigned int i;
  333. /* Resume all running pipelines. */
  334. for (i = 0; i < vsp1->info->wpf_count; ++i) {
  335. struct vsp1_rwpf *wpf = vsp1->wpf[i];
  336. struct vsp1_pipeline *pipe;
  337. if (wpf == NULL)
  338. continue;
  339. pipe = wpf->pipe;
  340. if (pipe == NULL)
  341. continue;
  342. spin_lock_irqsave(&pipe->irqlock, flags);
  343. if (vsp1_pipeline_ready(pipe))
  344. vsp1_pipeline_run(pipe);
  345. spin_unlock_irqrestore(&pipe->irqlock, flags);
  346. }
  347. }