camss-video.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * camss-video.c
  4. *
  5. * Qualcomm MSM Camera Subsystem - V4L2 device node
  6. *
  7. * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  8. * Copyright (C) 2015-2018 Linaro Ltd.
  9. */
  10. #include <linux/slab.h>
  11. #include <media/media-entity.h>
  12. #include <media/v4l2-dev.h>
  13. #include <media/v4l2-device.h>
  14. #include <media/v4l2-ioctl.h>
  15. #include <media/v4l2-mc.h>
  16. #include <media/videobuf2-dma-sg.h>
  17. #include "camss-video.h"
  18. #include "camss.h"
  19. struct fract {
  20. u8 numerator;
  21. u8 denominator;
  22. };
  23. /*
  24. * struct camss_format_info - ISP media bus format information
  25. * @code: V4L2 media bus format code
  26. * @pixelformat: V4L2 pixel format FCC identifier
  27. * @planes: Number of planes
  28. * @hsub: Horizontal subsampling (for each plane)
  29. * @vsub: Vertical subsampling (for each plane)
  30. * @bpp: Bits per pixel when stored in memory (for each plane)
  31. */
  32. struct camss_format_info {
  33. u32 code;
  34. u32 pixelformat;
  35. u8 planes;
  36. struct fract hsub[3];
  37. struct fract vsub[3];
  38. unsigned int bpp[3];
  39. };
  40. static const struct camss_format_info formats_rdi_8x16[] = {
  41. { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_UYVY, 1,
  42. { { 1, 1 } }, { { 1, 1 } }, { 16 } },
  43. { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_VYUY, 1,
  44. { { 1, 1 } }, { { 1, 1 } }, { 16 } },
  45. { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_YUYV, 1,
  46. { { 1, 1 } }, { { 1, 1 } }, { 16 } },
  47. { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_PIX_FMT_YVYU, 1,
  48. { { 1, 1 } }, { { 1, 1 } }, { 16 } },
  49. { MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_PIX_FMT_SBGGR8, 1,
  50. { { 1, 1 } }, { { 1, 1 } }, { 8 } },
  51. { MEDIA_BUS_FMT_SGBRG8_1X8, V4L2_PIX_FMT_SGBRG8, 1,
  52. { { 1, 1 } }, { { 1, 1 } }, { 8 } },
  53. { MEDIA_BUS_FMT_SGRBG8_1X8, V4L2_PIX_FMT_SGRBG8, 1,
  54. { { 1, 1 } }, { { 1, 1 } }, { 8 } },
  55. { MEDIA_BUS_FMT_SRGGB8_1X8, V4L2_PIX_FMT_SRGGB8, 1,
  56. { { 1, 1 } }, { { 1, 1 } }, { 8 } },
  57. { MEDIA_BUS_FMT_SBGGR10_1X10, V4L2_PIX_FMT_SBGGR10P, 1,
  58. { { 1, 1 } }, { { 1, 1 } }, { 10 } },
  59. { MEDIA_BUS_FMT_SGBRG10_1X10, V4L2_PIX_FMT_SGBRG10P, 1,
  60. { { 1, 1 } }, { { 1, 1 } }, { 10 } },
  61. { MEDIA_BUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10P, 1,
  62. { { 1, 1 } }, { { 1, 1 } }, { 10 } },
  63. { MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_PIX_FMT_SRGGB10P, 1,
  64. { { 1, 1 } }, { { 1, 1 } }, { 10 } },
  65. { MEDIA_BUS_FMT_SBGGR12_1X12, V4L2_PIX_FMT_SBGGR12P, 1,
  66. { { 1, 1 } }, { { 1, 1 } }, { 12 } },
  67. { MEDIA_BUS_FMT_SGBRG12_1X12, V4L2_PIX_FMT_SGBRG12P, 1,
  68. { { 1, 1 } }, { { 1, 1 } }, { 12 } },
  69. { MEDIA_BUS_FMT_SGRBG12_1X12, V4L2_PIX_FMT_SGRBG12P, 1,
  70. { { 1, 1 } }, { { 1, 1 } }, { 12 } },
  71. { MEDIA_BUS_FMT_SRGGB12_1X12, V4L2_PIX_FMT_SRGGB12P, 1,
  72. { { 1, 1 } }, { { 1, 1 } }, { 12 } },
  73. { MEDIA_BUS_FMT_Y10_1X10, V4L2_PIX_FMT_Y10P, 1,
  74. { { 1, 1 } }, { { 1, 1 } }, { 10 } },
  75. };
  76. static const struct camss_format_info formats_rdi_8x96[] = {
  77. { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_UYVY, 1,
  78. { { 1, 1 } }, { { 1, 1 } }, { 16 } },
  79. { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_VYUY, 1,
  80. { { 1, 1 } }, { { 1, 1 } }, { 16 } },
  81. { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_YUYV, 1,
  82. { { 1, 1 } }, { { 1, 1 } }, { 16 } },
  83. { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_PIX_FMT_YVYU, 1,
  84. { { 1, 1 } }, { { 1, 1 } }, { 16 } },
  85. { MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_PIX_FMT_SBGGR8, 1,
  86. { { 1, 1 } }, { { 1, 1 } }, { 8 } },
  87. { MEDIA_BUS_FMT_SGBRG8_1X8, V4L2_PIX_FMT_SGBRG8, 1,
  88. { { 1, 1 } }, { { 1, 1 } }, { 8 } },
  89. { MEDIA_BUS_FMT_SGRBG8_1X8, V4L2_PIX_FMT_SGRBG8, 1,
  90. { { 1, 1 } }, { { 1, 1 } }, { 8 } },
  91. { MEDIA_BUS_FMT_SRGGB8_1X8, V4L2_PIX_FMT_SRGGB8, 1,
  92. { { 1, 1 } }, { { 1, 1 } }, { 8 } },
  93. { MEDIA_BUS_FMT_SBGGR10_1X10, V4L2_PIX_FMT_SBGGR10P, 1,
  94. { { 1, 1 } }, { { 1, 1 } }, { 10 } },
  95. { MEDIA_BUS_FMT_SGBRG10_1X10, V4L2_PIX_FMT_SGBRG10P, 1,
  96. { { 1, 1 } }, { { 1, 1 } }, { 10 } },
  97. { MEDIA_BUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10P, 1,
  98. { { 1, 1 } }, { { 1, 1 } }, { 10 } },
  99. { MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_PIX_FMT_SRGGB10P, 1,
  100. { { 1, 1 } }, { { 1, 1 } }, { 10 } },
  101. { MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_PIX_FMT_SBGGR10, 1,
  102. { { 1, 1 } }, { { 1, 1 } }, { 16 } },
  103. { MEDIA_BUS_FMT_SBGGR12_1X12, V4L2_PIX_FMT_SBGGR12P, 1,
  104. { { 1, 1 } }, { { 1, 1 } }, { 12 } },
  105. { MEDIA_BUS_FMT_SGBRG12_1X12, V4L2_PIX_FMT_SGBRG12P, 1,
  106. { { 1, 1 } }, { { 1, 1 } }, { 12 } },
  107. { MEDIA_BUS_FMT_SGRBG12_1X12, V4L2_PIX_FMT_SGRBG12P, 1,
  108. { { 1, 1 } }, { { 1, 1 } }, { 12 } },
  109. { MEDIA_BUS_FMT_SRGGB12_1X12, V4L2_PIX_FMT_SRGGB12P, 1,
  110. { { 1, 1 } }, { { 1, 1 } }, { 12 } },
  111. { MEDIA_BUS_FMT_SBGGR14_1X14, V4L2_PIX_FMT_SBGGR14P, 1,
  112. { { 1, 1 } }, { { 1, 1 } }, { 14 } },
  113. { MEDIA_BUS_FMT_SGBRG14_1X14, V4L2_PIX_FMT_SGBRG14P, 1,
  114. { { 1, 1 } }, { { 1, 1 } }, { 14 } },
  115. { MEDIA_BUS_FMT_SGRBG14_1X14, V4L2_PIX_FMT_SGRBG14P, 1,
  116. { { 1, 1 } }, { { 1, 1 } }, { 14 } },
  117. { MEDIA_BUS_FMT_SRGGB14_1X14, V4L2_PIX_FMT_SRGGB14P, 1,
  118. { { 1, 1 } }, { { 1, 1 } }, { 14 } },
  119. { MEDIA_BUS_FMT_Y10_1X10, V4L2_PIX_FMT_Y10P, 1,
  120. { { 1, 1 } }, { { 1, 1 } }, { 10 } },
  121. { MEDIA_BUS_FMT_Y10_2X8_PADHI_LE, V4L2_PIX_FMT_Y10, 1,
  122. { { 1, 1 } }, { { 1, 1 } }, { 16 } },
  123. };
  124. static const struct camss_format_info formats_pix_8x16[] = {
  125. { MEDIA_BUS_FMT_YUYV8_1_5X8, V4L2_PIX_FMT_NV12, 1,
  126. { { 1, 1 } }, { { 2, 3 } }, { 8 } },
  127. { MEDIA_BUS_FMT_YVYU8_1_5X8, V4L2_PIX_FMT_NV12, 1,
  128. { { 1, 1 } }, { { 2, 3 } }, { 8 } },
  129. { MEDIA_BUS_FMT_UYVY8_1_5X8, V4L2_PIX_FMT_NV12, 1,
  130. { { 1, 1 } }, { { 2, 3 } }, { 8 } },
  131. { MEDIA_BUS_FMT_VYUY8_1_5X8, V4L2_PIX_FMT_NV12, 1,
  132. { { 1, 1 } }, { { 2, 3 } }, { 8 } },
  133. { MEDIA_BUS_FMT_YUYV8_1_5X8, V4L2_PIX_FMT_NV21, 1,
  134. { { 1, 1 } }, { { 2, 3 } }, { 8 } },
  135. { MEDIA_BUS_FMT_YVYU8_1_5X8, V4L2_PIX_FMT_NV21, 1,
  136. { { 1, 1 } }, { { 2, 3 } }, { 8 } },
  137. { MEDIA_BUS_FMT_UYVY8_1_5X8, V4L2_PIX_FMT_NV21, 1,
  138. { { 1, 1 } }, { { 2, 3 } }, { 8 } },
  139. { MEDIA_BUS_FMT_VYUY8_1_5X8, V4L2_PIX_FMT_NV21, 1,
  140. { { 1, 1 } }, { { 2, 3 } }, { 8 } },
  141. { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_NV16, 1,
  142. { { 1, 1 } }, { { 1, 2 } }, { 8 } },
  143. { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_PIX_FMT_NV16, 1,
  144. { { 1, 1 } }, { { 1, 2 } }, { 8 } },
  145. { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_NV16, 1,
  146. { { 1, 1 } }, { { 1, 2 } }, { 8 } },
  147. { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_NV16, 1,
  148. { { 1, 1 } }, { { 1, 2 } }, { 8 } },
  149. { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_NV61, 1,
  150. { { 1, 1 } }, { { 1, 2 } }, { 8 } },
  151. { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_PIX_FMT_NV61, 1,
  152. { { 1, 1 } }, { { 1, 2 } }, { 8 } },
  153. { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_NV61, 1,
  154. { { 1, 1 } }, { { 1, 2 } }, { 8 } },
  155. { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_NV61, 1,
  156. { { 1, 1 } }, { { 1, 2 } }, { 8 } },
  157. };
  158. static const struct camss_format_info formats_pix_8x96[] = {
  159. { MEDIA_BUS_FMT_YUYV8_1_5X8, V4L2_PIX_FMT_NV12, 1,
  160. { { 1, 1 } }, { { 2, 3 } }, { 8 } },
  161. { MEDIA_BUS_FMT_YVYU8_1_5X8, V4L2_PIX_FMT_NV12, 1,
  162. { { 1, 1 } }, { { 2, 3 } }, { 8 } },
  163. { MEDIA_BUS_FMT_UYVY8_1_5X8, V4L2_PIX_FMT_NV12, 1,
  164. { { 1, 1 } }, { { 2, 3 } }, { 8 } },
  165. { MEDIA_BUS_FMT_VYUY8_1_5X8, V4L2_PIX_FMT_NV12, 1,
  166. { { 1, 1 } }, { { 2, 3 } }, { 8 } },
  167. { MEDIA_BUS_FMT_YUYV8_1_5X8, V4L2_PIX_FMT_NV21, 1,
  168. { { 1, 1 } }, { { 2, 3 } }, { 8 } },
  169. { MEDIA_BUS_FMT_YVYU8_1_5X8, V4L2_PIX_FMT_NV21, 1,
  170. { { 1, 1 } }, { { 2, 3 } }, { 8 } },
  171. { MEDIA_BUS_FMT_UYVY8_1_5X8, V4L2_PIX_FMT_NV21, 1,
  172. { { 1, 1 } }, { { 2, 3 } }, { 8 } },
  173. { MEDIA_BUS_FMT_VYUY8_1_5X8, V4L2_PIX_FMT_NV21, 1,
  174. { { 1, 1 } }, { { 2, 3 } }, { 8 } },
  175. { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_NV16, 1,
  176. { { 1, 1 } }, { { 1, 2 } }, { 8 } },
  177. { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_PIX_FMT_NV16, 1,
  178. { { 1, 1 } }, { { 1, 2 } }, { 8 } },
  179. { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_NV16, 1,
  180. { { 1, 1 } }, { { 1, 2 } }, { 8 } },
  181. { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_NV16, 1,
  182. { { 1, 1 } }, { { 1, 2 } }, { 8 } },
  183. { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_NV61, 1,
  184. { { 1, 1 } }, { { 1, 2 } }, { 8 } },
  185. { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_PIX_FMT_NV61, 1,
  186. { { 1, 1 } }, { { 1, 2 } }, { 8 } },
  187. { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_NV61, 1,
  188. { { 1, 1 } }, { { 1, 2 } }, { 8 } },
  189. { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_NV61, 1,
  190. { { 1, 1 } }, { { 1, 2 } }, { 8 } },
  191. { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_UYVY, 1,
  192. { { 1, 1 } }, { { 1, 1 } }, { 16 } },
  193. { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_VYUY, 1,
  194. { { 1, 1 } }, { { 1, 1 } }, { 16 } },
  195. { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_YUYV, 1,
  196. { { 1, 1 } }, { { 1, 1 } }, { 16 } },
  197. { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_PIX_FMT_YVYU, 1,
  198. { { 1, 1 } }, { { 1, 1 } }, { 16 } },
  199. };
  200. /* -----------------------------------------------------------------------------
  201. * Helper functions
  202. */
  203. static int video_find_format(u32 code, u32 pixelformat,
  204. const struct camss_format_info *formats,
  205. unsigned int nformats)
  206. {
  207. int i;
  208. for (i = 0; i < nformats; i++) {
  209. if (formats[i].code == code &&
  210. formats[i].pixelformat == pixelformat)
  211. return i;
  212. }
  213. for (i = 0; i < nformats; i++)
  214. if (formats[i].code == code)
  215. return i;
  216. WARN_ON(1);
  217. return -EINVAL;
  218. }
  219. /*
  220. * video_mbus_to_pix_mp - Convert v4l2_mbus_framefmt to v4l2_pix_format_mplane
  221. * @mbus: v4l2_mbus_framefmt format (input)
  222. * @pix: v4l2_pix_format_mplane format (output)
  223. * @f: a pointer to formats array element to be used for the conversion
  224. * @alignment: bytesperline alignment value
  225. *
  226. * Fill the output pix structure with information from the input mbus format.
  227. *
  228. * Return 0 on success or a negative error code otherwise
  229. */
  230. static int video_mbus_to_pix_mp(const struct v4l2_mbus_framefmt *mbus,
  231. struct v4l2_pix_format_mplane *pix,
  232. const struct camss_format_info *f,
  233. unsigned int alignment)
  234. {
  235. unsigned int i;
  236. u32 bytesperline;
  237. memset(pix, 0, sizeof(*pix));
  238. v4l2_fill_pix_format_mplane(pix, mbus);
  239. pix->pixelformat = f->pixelformat;
  240. pix->num_planes = f->planes;
  241. for (i = 0; i < pix->num_planes; i++) {
  242. bytesperline = pix->width / f->hsub[i].numerator *
  243. f->hsub[i].denominator * f->bpp[i] / 8;
  244. bytesperline = ALIGN(bytesperline, alignment);
  245. pix->plane_fmt[i].bytesperline = bytesperline;
  246. pix->plane_fmt[i].sizeimage = pix->height /
  247. f->vsub[i].numerator * f->vsub[i].denominator *
  248. bytesperline;
  249. }
  250. return 0;
  251. }
  252. static struct v4l2_subdev *video_remote_subdev(struct camss_video *video,
  253. u32 *pad)
  254. {
  255. struct media_pad *remote;
  256. remote = media_entity_remote_pad(&video->pad);
  257. if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
  258. return NULL;
  259. if (pad)
  260. *pad = remote->index;
  261. return media_entity_to_v4l2_subdev(remote->entity);
  262. }
  263. static int video_get_subdev_format(struct camss_video *video,
  264. struct v4l2_format *format)
  265. {
  266. struct v4l2_subdev_format fmt;
  267. struct v4l2_subdev *subdev;
  268. u32 pad;
  269. int ret;
  270. subdev = video_remote_subdev(video, &pad);
  271. if (subdev == NULL)
  272. return -EPIPE;
  273. fmt.pad = pad;
  274. fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
  275. ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
  276. if (ret)
  277. return ret;
  278. ret = video_find_format(fmt.format.code,
  279. format->fmt.pix_mp.pixelformat,
  280. video->formats, video->nformats);
  281. if (ret < 0)
  282. return ret;
  283. format->type = video->type;
  284. return video_mbus_to_pix_mp(&fmt.format, &format->fmt.pix_mp,
  285. &video->formats[ret], video->bpl_alignment);
  286. }
  287. /* -----------------------------------------------------------------------------
  288. * Video queue operations
  289. */
  290. static int video_queue_setup(struct vb2_queue *q,
  291. unsigned int *num_buffers, unsigned int *num_planes,
  292. unsigned int sizes[], struct device *alloc_devs[])
  293. {
  294. struct camss_video *video = vb2_get_drv_priv(q);
  295. const struct v4l2_pix_format_mplane *format =
  296. &video->active_fmt.fmt.pix_mp;
  297. unsigned int i;
  298. if (*num_planes) {
  299. if (*num_planes != format->num_planes)
  300. return -EINVAL;
  301. for (i = 0; i < *num_planes; i++)
  302. if (sizes[i] < format->plane_fmt[i].sizeimage)
  303. return -EINVAL;
  304. return 0;
  305. }
  306. *num_planes = format->num_planes;
  307. for (i = 0; i < *num_planes; i++)
  308. sizes[i] = format->plane_fmt[i].sizeimage;
  309. return 0;
  310. }
  311. static int video_buf_init(struct vb2_buffer *vb)
  312. {
  313. struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
  314. struct camss_video *video = vb2_get_drv_priv(vb->vb2_queue);
  315. struct camss_buffer *buffer = container_of(vbuf, struct camss_buffer,
  316. vb);
  317. const struct v4l2_pix_format_mplane *format =
  318. &video->active_fmt.fmt.pix_mp;
  319. struct sg_table *sgt;
  320. unsigned int i;
  321. for (i = 0; i < format->num_planes; i++) {
  322. sgt = vb2_dma_sg_plane_desc(vb, i);
  323. if (!sgt)
  324. return -EFAULT;
  325. buffer->addr[i] = sg_dma_address(sgt->sgl);
  326. }
  327. if (format->pixelformat == V4L2_PIX_FMT_NV12 ||
  328. format->pixelformat == V4L2_PIX_FMT_NV21 ||
  329. format->pixelformat == V4L2_PIX_FMT_NV16 ||
  330. format->pixelformat == V4L2_PIX_FMT_NV61)
  331. buffer->addr[1] = buffer->addr[0] +
  332. format->plane_fmt[0].bytesperline *
  333. format->height;
  334. return 0;
  335. }
  336. static int video_buf_prepare(struct vb2_buffer *vb)
  337. {
  338. struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
  339. struct camss_video *video = vb2_get_drv_priv(vb->vb2_queue);
  340. const struct v4l2_pix_format_mplane *format =
  341. &video->active_fmt.fmt.pix_mp;
  342. unsigned int i;
  343. for (i = 0; i < format->num_planes; i++) {
  344. if (format->plane_fmt[i].sizeimage > vb2_plane_size(vb, i))
  345. return -EINVAL;
  346. vb2_set_plane_payload(vb, i, format->plane_fmt[i].sizeimage);
  347. }
  348. vbuf->field = V4L2_FIELD_NONE;
  349. return 0;
  350. }
  351. static void video_buf_queue(struct vb2_buffer *vb)
  352. {
  353. struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
  354. struct camss_video *video = vb2_get_drv_priv(vb->vb2_queue);
  355. struct camss_buffer *buffer = container_of(vbuf, struct camss_buffer,
  356. vb);
  357. video->ops->queue_buffer(video, buffer);
  358. }
  359. static int video_check_format(struct camss_video *video)
  360. {
  361. struct v4l2_pix_format_mplane *pix = &video->active_fmt.fmt.pix_mp;
  362. struct v4l2_format format;
  363. struct v4l2_pix_format_mplane *sd_pix = &format.fmt.pix_mp;
  364. int ret;
  365. sd_pix->pixelformat = pix->pixelformat;
  366. ret = video_get_subdev_format(video, &format);
  367. if (ret < 0)
  368. return ret;
  369. if (pix->pixelformat != sd_pix->pixelformat ||
  370. pix->height != sd_pix->height ||
  371. pix->width != sd_pix->width ||
  372. pix->num_planes != sd_pix->num_planes ||
  373. pix->field != format.fmt.pix_mp.field)
  374. return -EPIPE;
  375. return 0;
  376. }
  377. static int video_start_streaming(struct vb2_queue *q, unsigned int count)
  378. {
  379. struct camss_video *video = vb2_get_drv_priv(q);
  380. struct video_device *vdev = &video->vdev;
  381. struct media_entity *entity;
  382. struct media_pad *pad;
  383. struct v4l2_subdev *subdev;
  384. int ret;
  385. ret = media_pipeline_start(&vdev->entity, &video->pipe);
  386. if (ret < 0)
  387. return ret;
  388. ret = video_check_format(video);
  389. if (ret < 0)
  390. goto error;
  391. entity = &vdev->entity;
  392. while (1) {
  393. pad = &entity->pads[0];
  394. if (!(pad->flags & MEDIA_PAD_FL_SINK))
  395. break;
  396. pad = media_entity_remote_pad(pad);
  397. if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
  398. break;
  399. entity = pad->entity;
  400. subdev = media_entity_to_v4l2_subdev(entity);
  401. ret = v4l2_subdev_call(subdev, video, s_stream, 1);
  402. if (ret < 0 && ret != -ENOIOCTLCMD)
  403. goto error;
  404. }
  405. return 0;
  406. error:
  407. media_pipeline_stop(&vdev->entity);
  408. video->ops->flush_buffers(video, VB2_BUF_STATE_QUEUED);
  409. return ret;
  410. }
  411. static void video_stop_streaming(struct vb2_queue *q)
  412. {
  413. struct camss_video *video = vb2_get_drv_priv(q);
  414. struct video_device *vdev = &video->vdev;
  415. struct media_entity *entity;
  416. struct media_pad *pad;
  417. struct v4l2_subdev *subdev;
  418. entity = &vdev->entity;
  419. while (1) {
  420. pad = &entity->pads[0];
  421. if (!(pad->flags & MEDIA_PAD_FL_SINK))
  422. break;
  423. pad = media_entity_remote_pad(pad);
  424. if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
  425. break;
  426. entity = pad->entity;
  427. subdev = media_entity_to_v4l2_subdev(entity);
  428. v4l2_subdev_call(subdev, video, s_stream, 0);
  429. }
  430. media_pipeline_stop(&vdev->entity);
  431. video->ops->flush_buffers(video, VB2_BUF_STATE_ERROR);
  432. }
  433. static const struct vb2_ops msm_video_vb2_q_ops = {
  434. .queue_setup = video_queue_setup,
  435. .wait_prepare = vb2_ops_wait_prepare,
  436. .wait_finish = vb2_ops_wait_finish,
  437. .buf_init = video_buf_init,
  438. .buf_prepare = video_buf_prepare,
  439. .buf_queue = video_buf_queue,
  440. .start_streaming = video_start_streaming,
  441. .stop_streaming = video_stop_streaming,
  442. };
  443. /* -----------------------------------------------------------------------------
  444. * V4L2 ioctls
  445. */
  446. static int video_querycap(struct file *file, void *fh,
  447. struct v4l2_capability *cap)
  448. {
  449. struct camss_video *video = video_drvdata(file);
  450. strlcpy(cap->driver, "qcom-camss", sizeof(cap->driver));
  451. strlcpy(cap->card, "Qualcomm Camera Subsystem", sizeof(cap->card));
  452. snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
  453. dev_name(video->camss->dev));
  454. return 0;
  455. }
  456. static int video_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f)
  457. {
  458. struct camss_video *video = video_drvdata(file);
  459. int i, j, k;
  460. if (f->type != video->type)
  461. return -EINVAL;
  462. if (f->index >= video->nformats)
  463. return -EINVAL;
  464. /* find index "i" of "k"th unique pixelformat in formats array */
  465. k = -1;
  466. for (i = 0; i < video->nformats; i++) {
  467. for (j = 0; j < i; j++) {
  468. if (video->formats[i].pixelformat ==
  469. video->formats[j].pixelformat)
  470. break;
  471. }
  472. if (j == i)
  473. k++;
  474. if (k == f->index)
  475. break;
  476. }
  477. if (k < f->index)
  478. return -EINVAL;
  479. f->pixelformat = video->formats[i].pixelformat;
  480. return 0;
  481. }
  482. static int video_g_fmt(struct file *file, void *fh, struct v4l2_format *f)
  483. {
  484. struct camss_video *video = video_drvdata(file);
  485. *f = video->active_fmt;
  486. return 0;
  487. }
  488. static int __video_try_fmt(struct camss_video *video, struct v4l2_format *f)
  489. {
  490. struct v4l2_pix_format_mplane *pix_mp;
  491. const struct camss_format_info *fi;
  492. struct v4l2_plane_pix_format *p;
  493. u32 bytesperline[3] = { 0 };
  494. u32 sizeimage[3] = { 0 };
  495. u32 width, height;
  496. u32 bpl, lines;
  497. int i, j;
  498. pix_mp = &f->fmt.pix_mp;
  499. if (video->line_based)
  500. for (i = 0; i < pix_mp->num_planes && i < 3; i++) {
  501. p = &pix_mp->plane_fmt[i];
  502. bytesperline[i] = clamp_t(u32, p->bytesperline,
  503. 1, 65528);
  504. sizeimage[i] = clamp_t(u32, p->sizeimage,
  505. bytesperline[i],
  506. bytesperline[i] * 4096);
  507. }
  508. for (j = 0; j < video->nformats; j++)
  509. if (pix_mp->pixelformat == video->formats[j].pixelformat)
  510. break;
  511. if (j == video->nformats)
  512. j = 0; /* default format */
  513. fi = &video->formats[j];
  514. width = pix_mp->width;
  515. height = pix_mp->height;
  516. memset(pix_mp, 0, sizeof(*pix_mp));
  517. pix_mp->pixelformat = fi->pixelformat;
  518. pix_mp->width = clamp_t(u32, width, 1, 8191);
  519. pix_mp->height = clamp_t(u32, height, 1, 8191);
  520. pix_mp->num_planes = fi->planes;
  521. for (i = 0; i < pix_mp->num_planes; i++) {
  522. bpl = pix_mp->width / fi->hsub[i].numerator *
  523. fi->hsub[i].denominator * fi->bpp[i] / 8;
  524. bpl = ALIGN(bpl, video->bpl_alignment);
  525. pix_mp->plane_fmt[i].bytesperline = bpl;
  526. pix_mp->plane_fmt[i].sizeimage = pix_mp->height /
  527. fi->vsub[i].numerator * fi->vsub[i].denominator * bpl;
  528. }
  529. pix_mp->field = V4L2_FIELD_NONE;
  530. pix_mp->colorspace = V4L2_COLORSPACE_SRGB;
  531. pix_mp->flags = 0;
  532. pix_mp->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(pix_mp->colorspace);
  533. pix_mp->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true,
  534. pix_mp->colorspace, pix_mp->ycbcr_enc);
  535. pix_mp->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(pix_mp->colorspace);
  536. if (video->line_based)
  537. for (i = 0; i < pix_mp->num_planes; i++) {
  538. p = &pix_mp->plane_fmt[i];
  539. p->bytesperline = clamp_t(u32, p->bytesperline,
  540. 1, 65528);
  541. p->sizeimage = clamp_t(u32, p->sizeimage,
  542. p->bytesperline,
  543. p->bytesperline * 4096);
  544. lines = p->sizeimage / p->bytesperline;
  545. if (p->bytesperline < bytesperline[i])
  546. p->bytesperline = ALIGN(bytesperline[i], 8);
  547. if (p->sizeimage < p->bytesperline * lines)
  548. p->sizeimage = p->bytesperline * lines;
  549. if (p->sizeimage < sizeimage[i])
  550. p->sizeimage = sizeimage[i];
  551. }
  552. return 0;
  553. }
  554. static int video_try_fmt(struct file *file, void *fh, struct v4l2_format *f)
  555. {
  556. struct camss_video *video = video_drvdata(file);
  557. return __video_try_fmt(video, f);
  558. }
  559. static int video_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
  560. {
  561. struct camss_video *video = video_drvdata(file);
  562. int ret;
  563. if (vb2_is_busy(&video->vb2_q))
  564. return -EBUSY;
  565. ret = __video_try_fmt(video, f);
  566. if (ret < 0)
  567. return ret;
  568. video->active_fmt = *f;
  569. return 0;
  570. }
  571. static int video_enum_input(struct file *file, void *fh,
  572. struct v4l2_input *input)
  573. {
  574. if (input->index > 0)
  575. return -EINVAL;
  576. strlcpy(input->name, "camera", sizeof(input->name));
  577. input->type = V4L2_INPUT_TYPE_CAMERA;
  578. return 0;
  579. }
  580. static int video_g_input(struct file *file, void *fh, unsigned int *input)
  581. {
  582. *input = 0;
  583. return 0;
  584. }
  585. static int video_s_input(struct file *file, void *fh, unsigned int input)
  586. {
  587. return input == 0 ? 0 : -EINVAL;
  588. }
  589. static const struct v4l2_ioctl_ops msm_vid_ioctl_ops = {
  590. .vidioc_querycap = video_querycap,
  591. .vidioc_enum_fmt_vid_cap_mplane = video_enum_fmt,
  592. .vidioc_g_fmt_vid_cap_mplane = video_g_fmt,
  593. .vidioc_s_fmt_vid_cap_mplane = video_s_fmt,
  594. .vidioc_try_fmt_vid_cap_mplane = video_try_fmt,
  595. .vidioc_reqbufs = vb2_ioctl_reqbufs,
  596. .vidioc_querybuf = vb2_ioctl_querybuf,
  597. .vidioc_qbuf = vb2_ioctl_qbuf,
  598. .vidioc_expbuf = vb2_ioctl_expbuf,
  599. .vidioc_dqbuf = vb2_ioctl_dqbuf,
  600. .vidioc_create_bufs = vb2_ioctl_create_bufs,
  601. .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
  602. .vidioc_streamon = vb2_ioctl_streamon,
  603. .vidioc_streamoff = vb2_ioctl_streamoff,
  604. .vidioc_enum_input = video_enum_input,
  605. .vidioc_g_input = video_g_input,
  606. .vidioc_s_input = video_s_input,
  607. };
  608. /* -----------------------------------------------------------------------------
  609. * V4L2 file operations
  610. */
  611. static int video_open(struct file *file)
  612. {
  613. struct video_device *vdev = video_devdata(file);
  614. struct camss_video *video = video_drvdata(file);
  615. struct v4l2_fh *vfh;
  616. int ret;
  617. mutex_lock(&video->lock);
  618. vfh = kzalloc(sizeof(*vfh), GFP_KERNEL);
  619. if (vfh == NULL) {
  620. ret = -ENOMEM;
  621. goto error_alloc;
  622. }
  623. v4l2_fh_init(vfh, vdev);
  624. v4l2_fh_add(vfh);
  625. file->private_data = vfh;
  626. ret = v4l2_pipeline_pm_use(&vdev->entity, 1);
  627. if (ret < 0) {
  628. dev_err(video->camss->dev, "Failed to power up pipeline: %d\n",
  629. ret);
  630. goto error_pm_use;
  631. }
  632. mutex_unlock(&video->lock);
  633. return 0;
  634. error_pm_use:
  635. v4l2_fh_release(file);
  636. error_alloc:
  637. mutex_unlock(&video->lock);
  638. return ret;
  639. }
  640. static int video_release(struct file *file)
  641. {
  642. struct video_device *vdev = video_devdata(file);
  643. vb2_fop_release(file);
  644. v4l2_pipeline_pm_use(&vdev->entity, 0);
  645. file->private_data = NULL;
  646. return 0;
  647. }
  648. static const struct v4l2_file_operations msm_vid_fops = {
  649. .owner = THIS_MODULE,
  650. .unlocked_ioctl = video_ioctl2,
  651. .open = video_open,
  652. .release = video_release,
  653. .poll = vb2_fop_poll,
  654. .mmap = vb2_fop_mmap,
  655. .read = vb2_fop_read,
  656. };
  657. /* -----------------------------------------------------------------------------
  658. * CAMSS video core
  659. */
  660. static void msm_video_release(struct video_device *vdev)
  661. {
  662. struct camss_video *video = video_get_drvdata(vdev);
  663. media_entity_cleanup(&vdev->entity);
  664. mutex_destroy(&video->q_lock);
  665. mutex_destroy(&video->lock);
  666. if (atomic_dec_and_test(&video->camss->ref_count))
  667. camss_delete(video->camss);
  668. }
  669. /*
  670. * msm_video_init_format - Helper function to initialize format
  671. * @video: struct camss_video
  672. *
  673. * Initialize pad format with default value.
  674. *
  675. * Return 0 on success or a negative error code otherwise
  676. */
  677. static int msm_video_init_format(struct camss_video *video)
  678. {
  679. int ret;
  680. struct v4l2_format format = {
  681. .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
  682. .fmt.pix_mp = {
  683. .width = 1920,
  684. .height = 1080,
  685. .pixelformat = video->formats[0].pixelformat,
  686. },
  687. };
  688. ret = __video_try_fmt(video, &format);
  689. if (ret < 0)
  690. return ret;
  691. video->active_fmt = format;
  692. return 0;
  693. }
  694. /*
  695. * msm_video_register - Register a video device node
  696. * @video: struct camss_video
  697. * @v4l2_dev: V4L2 device
  698. * @name: name to be used for the video device node
  699. *
  700. * Initialize and register a video device node to a V4L2 device. Also
  701. * initialize the vb2 queue.
  702. *
  703. * Return 0 on success or a negative error code otherwise
  704. */
  705. int msm_video_register(struct camss_video *video, struct v4l2_device *v4l2_dev,
  706. const char *name, int is_pix)
  707. {
  708. struct media_pad *pad = &video->pad;
  709. struct video_device *vdev;
  710. struct vb2_queue *q;
  711. int ret;
  712. vdev = &video->vdev;
  713. mutex_init(&video->q_lock);
  714. q = &video->vb2_q;
  715. q->drv_priv = video;
  716. q->mem_ops = &vb2_dma_sg_memops;
  717. q->ops = &msm_video_vb2_q_ops;
  718. q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
  719. q->io_modes = VB2_DMABUF | VB2_MMAP | VB2_READ;
  720. q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
  721. q->buf_struct_size = sizeof(struct camss_buffer);
  722. q->dev = video->camss->dev;
  723. q->lock = &video->q_lock;
  724. ret = vb2_queue_init(q);
  725. if (ret < 0) {
  726. dev_err(v4l2_dev->dev, "Failed to init vb2 queue: %d\n", ret);
  727. goto error_vb2_init;
  728. }
  729. pad->flags = MEDIA_PAD_FL_SINK;
  730. ret = media_entity_pads_init(&vdev->entity, 1, pad);
  731. if (ret < 0) {
  732. dev_err(v4l2_dev->dev, "Failed to init video entity: %d\n",
  733. ret);
  734. goto error_media_init;
  735. }
  736. mutex_init(&video->lock);
  737. if (video->camss->version == CAMSS_8x16) {
  738. if (is_pix) {
  739. video->formats = formats_pix_8x16;
  740. video->nformats = ARRAY_SIZE(formats_pix_8x16);
  741. } else {
  742. video->formats = formats_rdi_8x16;
  743. video->nformats = ARRAY_SIZE(formats_rdi_8x16);
  744. }
  745. } else if (video->camss->version == CAMSS_8x96) {
  746. if (is_pix) {
  747. video->formats = formats_pix_8x96;
  748. video->nformats = ARRAY_SIZE(formats_pix_8x96);
  749. } else {
  750. video->formats = formats_rdi_8x96;
  751. video->nformats = ARRAY_SIZE(formats_rdi_8x96);
  752. }
  753. } else {
  754. goto error_video_register;
  755. }
  756. ret = msm_video_init_format(video);
  757. if (ret < 0) {
  758. dev_err(v4l2_dev->dev, "Failed to init format: %d\n", ret);
  759. goto error_video_register;
  760. }
  761. vdev->fops = &msm_vid_fops;
  762. vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING |
  763. V4L2_CAP_READWRITE;
  764. vdev->ioctl_ops = &msm_vid_ioctl_ops;
  765. vdev->release = msm_video_release;
  766. vdev->v4l2_dev = v4l2_dev;
  767. vdev->vfl_dir = VFL_DIR_RX;
  768. vdev->queue = &video->vb2_q;
  769. vdev->lock = &video->lock;
  770. strlcpy(vdev->name, name, sizeof(vdev->name));
  771. ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
  772. if (ret < 0) {
  773. dev_err(v4l2_dev->dev, "Failed to register video device: %d\n",
  774. ret);
  775. goto error_video_register;
  776. }
  777. video_set_drvdata(vdev, video);
  778. atomic_inc(&video->camss->ref_count);
  779. return 0;
  780. error_video_register:
  781. media_entity_cleanup(&vdev->entity);
  782. mutex_destroy(&video->lock);
  783. error_media_init:
  784. vb2_queue_release(&video->vb2_q);
  785. error_vb2_init:
  786. mutex_destroy(&video->q_lock);
  787. return ret;
  788. }
  789. void msm_video_stop_streaming(struct camss_video *video)
  790. {
  791. if (vb2_is_streaming(&video->vb2_q))
  792. vb2_queue_release(&video->vb2_q);
  793. }
  794. void msm_video_unregister(struct camss_video *video)
  795. {
  796. atomic_inc(&video->camss->ref_count);
  797. video_unregister_device(&video->vdev);
  798. atomic_dec(&video->camss->ref_count);
  799. }