saa7146_video.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  1. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  2. #include <media/drv-intf/saa7146_vv.h>
  3. #include <media/v4l2-event.h>
  4. #include <media/v4l2-ctrls.h>
  5. #include <linux/module.h>
  6. #include <linux/kernel.h>
  7. /* format descriptions for capture and preview */
  8. static struct saa7146_format formats[] = {
  9. {
  10. .pixelformat = V4L2_PIX_FMT_RGB332,
  11. .trans = RGB08_COMPOSED,
  12. .depth = 8,
  13. .flags = 0,
  14. }, {
  15. .pixelformat = V4L2_PIX_FMT_RGB565,
  16. .trans = RGB16_COMPOSED,
  17. .depth = 16,
  18. .flags = 0,
  19. }, {
  20. .pixelformat = V4L2_PIX_FMT_BGR24,
  21. .trans = RGB24_COMPOSED,
  22. .depth = 24,
  23. .flags = 0,
  24. }, {
  25. .pixelformat = V4L2_PIX_FMT_BGR32,
  26. .trans = RGB32_COMPOSED,
  27. .depth = 32,
  28. .flags = 0,
  29. }, {
  30. .pixelformat = V4L2_PIX_FMT_RGB32,
  31. .trans = RGB32_COMPOSED,
  32. .depth = 32,
  33. .flags = 0,
  34. .swap = 0x2,
  35. }, {
  36. .pixelformat = V4L2_PIX_FMT_GREY,
  37. .trans = Y8,
  38. .depth = 8,
  39. .flags = 0,
  40. }, {
  41. .pixelformat = V4L2_PIX_FMT_YUV422P,
  42. .trans = YUV422_DECOMPOSED,
  43. .depth = 16,
  44. .flags = FORMAT_IS_PLANAR,
  45. }, {
  46. .pixelformat = V4L2_PIX_FMT_YVU420,
  47. .trans = YUV420_DECOMPOSED,
  48. .depth = 12,
  49. .flags = FORMAT_BYTE_SWAP|FORMAT_IS_PLANAR,
  50. }, {
  51. .pixelformat = V4L2_PIX_FMT_YUV420,
  52. .trans = YUV420_DECOMPOSED,
  53. .depth = 12,
  54. .flags = FORMAT_IS_PLANAR,
  55. }, {
  56. .pixelformat = V4L2_PIX_FMT_UYVY,
  57. .trans = YUV422_COMPOSED,
  58. .depth = 16,
  59. .flags = 0,
  60. }
  61. };
  62. /* unfortunately, the saa7146 contains a bug which prevents it from doing on-the-fly byte swaps.
  63. due to this, it's impossible to provide additional *packed* formats, which are simply byte swapped
  64. (like V4L2_PIX_FMT_YUYV) ... 8-( */
  65. struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fourcc)
  66. {
  67. int i;
  68. for (i = 0; i < ARRAY_SIZE(formats); i++) {
  69. if (formats[i].pixelformat == fourcc) {
  70. return formats+i;
  71. }
  72. }
  73. DEB_D("unknown pixelformat:'%4.4s'\n", (char *)&fourcc);
  74. return NULL;
  75. }
  76. /********************************************************************************/
  77. /* common pagetable functions */
  78. static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf)
  79. {
  80. struct saa7146_vv *vv = dev->vv_data;
  81. struct pci_dev *pci = dev->pci;
  82. struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb.vb2_buf, 0);
  83. struct scatterlist *list = sgt->sgl;
  84. int length = sgt->nents;
  85. struct v4l2_pix_format *pix = &vv->video_fmt;
  86. struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pix->pixelformat);
  87. DEB_EE("dev:%p, buf:%p, sg_len:%d\n", dev, buf, length);
  88. if( 0 != IS_PLANAR(sfmt->trans)) {
  89. struct saa7146_pgtable *pt1 = &buf->pt[0];
  90. struct saa7146_pgtable *pt2 = &buf->pt[1];
  91. struct saa7146_pgtable *pt3 = &buf->pt[2];
  92. struct sg_dma_page_iter dma_iter;
  93. __le32 *ptr1, *ptr2, *ptr3;
  94. __le32 fill;
  95. int size = pix->width * pix->height;
  96. int i, m1, m2, m3, o1, o2;
  97. switch( sfmt->depth ) {
  98. case 12: {
  99. /* create some offsets inside the page table */
  100. m1 = ((size + PAGE_SIZE) / PAGE_SIZE) - 1;
  101. m2 = ((size + (size / 4) + PAGE_SIZE) / PAGE_SIZE) - 1;
  102. m3 = ((size + (size / 2) + PAGE_SIZE) / PAGE_SIZE) - 1;
  103. o1 = size % PAGE_SIZE;
  104. o2 = (size + (size / 4)) % PAGE_SIZE;
  105. DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
  106. size, m1, m2, m3, o1, o2);
  107. break;
  108. }
  109. case 16: {
  110. /* create some offsets inside the page table */
  111. m1 = ((size + PAGE_SIZE) / PAGE_SIZE) - 1;
  112. m2 = ((size + (size / 2) + PAGE_SIZE) / PAGE_SIZE) - 1;
  113. m3 = ((2 * size + PAGE_SIZE) / PAGE_SIZE) - 1;
  114. o1 = size % PAGE_SIZE;
  115. o2 = (size + (size / 2)) % PAGE_SIZE;
  116. DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
  117. size, m1, m2, m3, o1, o2);
  118. break;
  119. }
  120. default: {
  121. return -1;
  122. }
  123. }
  124. ptr1 = pt1->cpu;
  125. ptr2 = pt2->cpu;
  126. ptr3 = pt3->cpu;
  127. for_each_sg_dma_page(list, &dma_iter, length, 0)
  128. *ptr1++ = cpu_to_le32(sg_page_iter_dma_address(&dma_iter) - list->offset);
  129. /* if we have a user buffer, the first page may not be
  130. aligned to a page boundary. */
  131. pt1->offset = sgt->sgl->offset;
  132. pt2->offset = pt1->offset + o1;
  133. pt3->offset = pt1->offset + o2;
  134. /* create video-dma2 page table */
  135. ptr1 = pt1->cpu;
  136. for (i = m1; i <= m2; i++, ptr2++)
  137. *ptr2 = ptr1[i];
  138. fill = *(ptr2 - 1);
  139. for (; i < 1024; i++, ptr2++)
  140. *ptr2 = fill;
  141. /* create video-dma3 page table */
  142. ptr1 = pt1->cpu;
  143. for (i = m2; i <= m3; i++, ptr3++)
  144. *ptr3 = ptr1[i];
  145. fill = *(ptr3 - 1);
  146. for (; i < 1024; i++, ptr3++)
  147. *ptr3 = fill;
  148. /* finally: finish up video-dma1 page table */
  149. ptr1 = pt1->cpu + m1;
  150. fill = pt1->cpu[m1];
  151. for (i = m1; i < 1024; i++, ptr1++)
  152. *ptr1 = fill;
  153. } else {
  154. struct saa7146_pgtable *pt = &buf->pt[0];
  155. return saa7146_pgtable_build_single(pci, pt, list, length);
  156. }
  157. return 0;
  158. }
  159. /********************************************************************************/
  160. /* file operations */
  161. static int video_begin(struct saa7146_dev *dev)
  162. {
  163. struct saa7146_vv *vv = dev->vv_data;
  164. struct saa7146_format *fmt = NULL;
  165. unsigned int resource;
  166. int ret = 0;
  167. DEB_EE("dev:%p\n", dev);
  168. fmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat);
  169. /* we need to have a valid format set here */
  170. if (!fmt)
  171. return -EINVAL;
  172. if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
  173. resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS;
  174. } else {
  175. resource = RESOURCE_DMA1_HPS;
  176. }
  177. ret = saa7146_res_get(dev, resource);
  178. if (0 == ret) {
  179. DEB_S("cannot get capture resource %d\n", resource);
  180. return -EBUSY;
  181. }
  182. /* clear out beginning of streaming bit (rps register 0)*/
  183. saa7146_write(dev, MC2, MASK_27 );
  184. /* enable rps0 irqs */
  185. SAA7146_IER_ENABLE(dev, MASK_27);
  186. return 0;
  187. }
  188. static void video_end(struct saa7146_dev *dev)
  189. {
  190. struct saa7146_vv *vv = dev->vv_data;
  191. struct saa7146_format *fmt = NULL;
  192. unsigned long flags;
  193. unsigned int resource;
  194. u32 dmas = 0;
  195. DEB_EE("dev:%p\n", dev);
  196. fmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat);
  197. /* we need to have a valid format set here */
  198. if (!fmt)
  199. return;
  200. if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
  201. resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS;
  202. dmas = MASK_22 | MASK_21 | MASK_20;
  203. } else {
  204. resource = RESOURCE_DMA1_HPS;
  205. dmas = MASK_22;
  206. }
  207. spin_lock_irqsave(&dev->slock,flags);
  208. /* disable rps0 */
  209. saa7146_write(dev, MC1, MASK_28);
  210. /* disable rps0 irqs */
  211. SAA7146_IER_DISABLE(dev, MASK_27);
  212. /* shut down all used video dma transfers */
  213. saa7146_write(dev, MC1, dmas);
  214. spin_unlock_irqrestore(&dev->slock, flags);
  215. saa7146_res_free(dev, resource);
  216. }
  217. static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
  218. {
  219. struct saa7146_dev *dev = video_drvdata(file);
  220. strscpy((char *)cap->driver, "saa7146 v4l2", sizeof(cap->driver));
  221. strscpy((char *)cap->card, dev->ext->name, sizeof(cap->card));
  222. cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
  223. V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
  224. V4L2_CAP_DEVICE_CAPS;
  225. cap->capabilities |= dev->ext_vv_data->capabilities;
  226. return 0;
  227. }
  228. static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f)
  229. {
  230. if (f->index >= ARRAY_SIZE(formats))
  231. return -EINVAL;
  232. f->pixelformat = formats[f->index].pixelformat;
  233. return 0;
  234. }
  235. int saa7146_s_ctrl(struct v4l2_ctrl *ctrl)
  236. {
  237. struct saa7146_dev *dev = container_of(ctrl->handler,
  238. struct saa7146_dev, ctrl_handler);
  239. struct saa7146_vv *vv = dev->vv_data;
  240. u32 val;
  241. switch (ctrl->id) {
  242. case V4L2_CID_BRIGHTNESS:
  243. val = saa7146_read(dev, BCS_CTRL);
  244. val &= 0x00ffffff;
  245. val |= (ctrl->val << 24);
  246. saa7146_write(dev, BCS_CTRL, val);
  247. saa7146_write(dev, MC2, MASK_22 | MASK_06);
  248. break;
  249. case V4L2_CID_CONTRAST:
  250. val = saa7146_read(dev, BCS_CTRL);
  251. val &= 0xff00ffff;
  252. val |= (ctrl->val << 16);
  253. saa7146_write(dev, BCS_CTRL, val);
  254. saa7146_write(dev, MC2, MASK_22 | MASK_06);
  255. break;
  256. case V4L2_CID_SATURATION:
  257. val = saa7146_read(dev, BCS_CTRL);
  258. val &= 0xffffff00;
  259. val |= (ctrl->val << 0);
  260. saa7146_write(dev, BCS_CTRL, val);
  261. saa7146_write(dev, MC2, MASK_22 | MASK_06);
  262. break;
  263. case V4L2_CID_HFLIP:
  264. /* fixme: we can support changing VFLIP and HFLIP here... */
  265. if (vb2_is_busy(&vv->video_dmaq.q))
  266. return -EBUSY;
  267. vv->hflip = ctrl->val;
  268. break;
  269. case V4L2_CID_VFLIP:
  270. if (vb2_is_busy(&vv->video_dmaq.q))
  271. return -EBUSY;
  272. vv->vflip = ctrl->val;
  273. break;
  274. default:
  275. return -EINVAL;
  276. }
  277. return 0;
  278. }
  279. static int vidioc_g_parm(struct file *file, void *fh,
  280. struct v4l2_streamparm *parm)
  281. {
  282. struct saa7146_dev *dev = video_drvdata(file);
  283. struct saa7146_vv *vv = dev->vv_data;
  284. if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
  285. return -EINVAL;
  286. parm->parm.capture.readbuffers = 1;
  287. v4l2_video_std_frame_period(vv->standard->id,
  288. &parm->parm.capture.timeperframe);
  289. return 0;
  290. }
  291. static int vidioc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
  292. {
  293. struct saa7146_dev *dev = video_drvdata(file);
  294. struct saa7146_vv *vv = dev->vv_data;
  295. f->fmt.pix = vv->video_fmt;
  296. return 0;
  297. }
  298. static int vidioc_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f)
  299. {
  300. struct saa7146_dev *dev = video_drvdata(file);
  301. struct saa7146_vv *vv = dev->vv_data;
  302. f->fmt.vbi = vv->vbi_fmt;
  303. return 0;
  304. }
  305. static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
  306. {
  307. struct saa7146_dev *dev = video_drvdata(file);
  308. struct saa7146_vv *vv = dev->vv_data;
  309. struct saa7146_format *fmt;
  310. enum v4l2_field field;
  311. int maxw, maxh;
  312. int calc_bpl;
  313. DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh);
  314. fmt = saa7146_format_by_fourcc(dev, f->fmt.pix.pixelformat);
  315. if (NULL == fmt)
  316. return -EINVAL;
  317. field = f->fmt.pix.field;
  318. maxw = vv->standard->h_max_out;
  319. maxh = vv->standard->v_max_out;
  320. if (V4L2_FIELD_ANY == field) {
  321. field = (f->fmt.pix.height > maxh / 2)
  322. ? V4L2_FIELD_INTERLACED
  323. : V4L2_FIELD_BOTTOM;
  324. }
  325. switch (field) {
  326. case V4L2_FIELD_ALTERNATE:
  327. case V4L2_FIELD_TOP:
  328. case V4L2_FIELD_BOTTOM:
  329. maxh = maxh / 2;
  330. break;
  331. default:
  332. field = V4L2_FIELD_INTERLACED;
  333. break;
  334. }
  335. f->fmt.pix.field = field;
  336. f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
  337. if (f->fmt.pix.width < 48)
  338. f->fmt.pix.width = 48;
  339. if (f->fmt.pix.height < 32)
  340. f->fmt.pix.height = 32;
  341. if (f->fmt.pix.width > maxw)
  342. f->fmt.pix.width = maxw;
  343. if (f->fmt.pix.height > maxh)
  344. f->fmt.pix.height = maxh;
  345. calc_bpl = (f->fmt.pix.width * fmt->depth) / 8;
  346. if (f->fmt.pix.bytesperline < calc_bpl)
  347. f->fmt.pix.bytesperline = calc_bpl;
  348. if (f->fmt.pix.bytesperline > (2 * PAGE_SIZE * fmt->depth) / 8) /* arbitrary constraint */
  349. f->fmt.pix.bytesperline = calc_bpl;
  350. f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
  351. DEB_D("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n",
  352. f->fmt.pix.width, f->fmt.pix.height,
  353. f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
  354. return 0;
  355. }
  356. static int vidioc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
  357. {
  358. struct saa7146_dev *dev = video_drvdata(file);
  359. struct saa7146_vv *vv = dev->vv_data;
  360. int err;
  361. DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p\n", dev);
  362. if (vb2_is_busy(&vv->video_dmaq.q)) {
  363. DEB_EE("streaming capture is active\n");
  364. return -EBUSY;
  365. }
  366. err = vidioc_try_fmt_vid_cap(file, fh, f);
  367. if (0 != err)
  368. return err;
  369. switch (f->fmt.pix.field) {
  370. case V4L2_FIELD_ALTERNATE:
  371. vv->last_field = V4L2_FIELD_TOP;
  372. break;
  373. default:
  374. vv->last_field = V4L2_FIELD_INTERLACED;
  375. break;
  376. }
  377. vv->video_fmt = f->fmt.pix;
  378. DEB_EE("set to pixelformat '%4.4s'\n",
  379. (char *)&vv->video_fmt.pixelformat);
  380. return 0;
  381. }
  382. static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm)
  383. {
  384. struct saa7146_dev *dev = video_drvdata(file);
  385. struct saa7146_vv *vv = dev->vv_data;
  386. *norm = vv->standard->id;
  387. return 0;
  388. }
  389. static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id id)
  390. {
  391. struct saa7146_dev *dev = video_drvdata(file);
  392. struct saa7146_vv *vv = dev->vv_data;
  393. int found = 0;
  394. int i;
  395. DEB_EE("VIDIOC_S_STD\n");
  396. for (i = 0; i < dev->ext_vv_data->num_stds; i++)
  397. if (id & dev->ext_vv_data->stds[i].id)
  398. break;
  399. if (i != dev->ext_vv_data->num_stds &&
  400. vv->standard == &dev->ext_vv_data->stds[i])
  401. return 0;
  402. if (vb2_is_busy(&vv->video_dmaq.q) || vb2_is_busy(&vv->vbi_dmaq.q)) {
  403. DEB_D("cannot change video standard while streaming capture is active\n");
  404. return -EBUSY;
  405. }
  406. if (i != dev->ext_vv_data->num_stds) {
  407. vv->standard = &dev->ext_vv_data->stds[i];
  408. if (NULL != dev->ext_vv_data->std_callback)
  409. dev->ext_vv_data->std_callback(dev, vv->standard);
  410. found = 1;
  411. }
  412. if (!found) {
  413. DEB_EE("VIDIOC_S_STD: standard not found\n");
  414. return -EINVAL;
  415. }
  416. DEB_EE("VIDIOC_S_STD: set to standard to '%s'\n", vv->standard->name);
  417. return 0;
  418. }
  419. const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = {
  420. .vidioc_querycap = vidioc_querycap,
  421. .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
  422. .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
  423. .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
  424. .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
  425. .vidioc_g_std = vidioc_g_std,
  426. .vidioc_s_std = vidioc_s_std,
  427. .vidioc_g_parm = vidioc_g_parm,
  428. .vidioc_reqbufs = vb2_ioctl_reqbufs,
  429. .vidioc_create_bufs = vb2_ioctl_create_bufs,
  430. .vidioc_querybuf = vb2_ioctl_querybuf,
  431. .vidioc_qbuf = vb2_ioctl_qbuf,
  432. .vidioc_dqbuf = vb2_ioctl_dqbuf,
  433. .vidioc_streamon = vb2_ioctl_streamon,
  434. .vidioc_streamoff = vb2_ioctl_streamoff,
  435. .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
  436. .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
  437. };
  438. const struct v4l2_ioctl_ops saa7146_vbi_ioctl_ops = {
  439. .vidioc_querycap = vidioc_querycap,
  440. .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
  441. .vidioc_try_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
  442. .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
  443. .vidioc_g_std = vidioc_g_std,
  444. .vidioc_s_std = vidioc_s_std,
  445. .vidioc_g_parm = vidioc_g_parm,
  446. .vidioc_reqbufs = vb2_ioctl_reqbufs,
  447. .vidioc_create_bufs = vb2_ioctl_create_bufs,
  448. .vidioc_querybuf = vb2_ioctl_querybuf,
  449. .vidioc_qbuf = vb2_ioctl_qbuf,
  450. .vidioc_dqbuf = vb2_ioctl_dqbuf,
  451. .vidioc_streamon = vb2_ioctl_streamon,
  452. .vidioc_streamoff = vb2_ioctl_streamoff,
  453. .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
  454. .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
  455. };
  456. /*********************************************************************************/
  457. /* buffer handling functions */
  458. static int buffer_activate (struct saa7146_dev *dev,
  459. struct saa7146_buf *buf,
  460. struct saa7146_buf *next)
  461. {
  462. struct saa7146_vv *vv = dev->vv_data;
  463. saa7146_set_capture(dev,buf,next);
  464. mod_timer(&vv->video_dmaq.timeout, jiffies+BUFFER_TIMEOUT);
  465. return 0;
  466. }
  467. static void release_all_pagetables(struct saa7146_dev *dev, struct saa7146_buf *buf)
  468. {
  469. saa7146_pgtable_free(dev->pci, &buf->pt[0]);
  470. saa7146_pgtable_free(dev->pci, &buf->pt[1]);
  471. saa7146_pgtable_free(dev->pci, &buf->pt[2]);
  472. }
  473. static int queue_setup(struct vb2_queue *q,
  474. unsigned int *num_buffers, unsigned int *num_planes,
  475. unsigned int sizes[], struct device *alloc_devs[])
  476. {
  477. struct saa7146_dev *dev = vb2_get_drv_priv(q);
  478. unsigned int size = dev->vv_data->video_fmt.sizeimage;
  479. if (*num_planes)
  480. return sizes[0] < size ? -EINVAL : 0;
  481. *num_planes = 1;
  482. sizes[0] = size;
  483. return 0;
  484. }
  485. static void buf_queue(struct vb2_buffer *vb)
  486. {
  487. struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
  488. struct vb2_queue *vq = vb->vb2_queue;
  489. struct saa7146_dev *dev = vb2_get_drv_priv(vq);
  490. struct saa7146_buf *buf = container_of(vbuf, struct saa7146_buf, vb);
  491. unsigned long flags;
  492. spin_lock_irqsave(&dev->slock, flags);
  493. saa7146_buffer_queue(dev, &dev->vv_data->video_dmaq, buf);
  494. spin_unlock_irqrestore(&dev->slock, flags);
  495. }
  496. static int buf_init(struct vb2_buffer *vb)
  497. {
  498. struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
  499. struct saa7146_buf *buf = container_of(vbuf, struct saa7146_buf, vb);
  500. struct vb2_queue *vq = vb->vb2_queue;
  501. struct saa7146_dev *dev = vb2_get_drv_priv(vq);
  502. struct saa7146_vv *vv = dev->vv_data;
  503. struct saa7146_format *sfmt;
  504. int ret;
  505. buf->activate = buffer_activate;
  506. sfmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat);
  507. if (IS_PLANAR(sfmt->trans)) {
  508. saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
  509. saa7146_pgtable_alloc(dev->pci, &buf->pt[1]);
  510. saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);
  511. } else {
  512. saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
  513. }
  514. ret = saa7146_pgtable_build(dev, buf);
  515. if (ret)
  516. release_all_pagetables(dev, buf);
  517. return ret;
  518. }
  519. static int buf_prepare(struct vb2_buffer *vb)
  520. {
  521. struct vb2_queue *vq = vb->vb2_queue;
  522. struct saa7146_dev *dev = vb2_get_drv_priv(vq);
  523. struct saa7146_vv *vv = dev->vv_data;
  524. unsigned int size = vv->video_fmt.sizeimage;
  525. if (vb2_plane_size(vb, 0) < size)
  526. return -EINVAL;
  527. vb2_set_plane_payload(vb, 0, size);
  528. return 0;
  529. }
  530. static void buf_cleanup(struct vb2_buffer *vb)
  531. {
  532. struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
  533. struct saa7146_buf *buf = container_of(vbuf, struct saa7146_buf, vb);
  534. struct vb2_queue *vq = vb->vb2_queue;
  535. struct saa7146_dev *dev = vb2_get_drv_priv(vq);
  536. release_all_pagetables(dev, buf);
  537. }
  538. static void return_buffers(struct vb2_queue *q, int state)
  539. {
  540. struct saa7146_dev *dev = vb2_get_drv_priv(q);
  541. struct saa7146_dmaqueue *dq = &dev->vv_data->video_dmaq;
  542. struct saa7146_buf *buf;
  543. if (dq->curr) {
  544. buf = dq->curr;
  545. dq->curr = NULL;
  546. vb2_buffer_done(&buf->vb.vb2_buf, state);
  547. }
  548. while (!list_empty(&dq->queue)) {
  549. buf = list_entry(dq->queue.next, struct saa7146_buf, list);
  550. list_del(&buf->list);
  551. vb2_buffer_done(&buf->vb.vb2_buf, state);
  552. }
  553. }
  554. static int start_streaming(struct vb2_queue *q, unsigned int count)
  555. {
  556. struct saa7146_dev *dev = vb2_get_drv_priv(q);
  557. int ret;
  558. if (!vb2_is_streaming(&dev->vv_data->video_dmaq.q))
  559. dev->vv_data->seqnr = 0;
  560. ret = video_begin(dev);
  561. if (ret)
  562. return_buffers(q, VB2_BUF_STATE_QUEUED);
  563. return ret;
  564. }
  565. static void stop_streaming(struct vb2_queue *q)
  566. {
  567. struct saa7146_dev *dev = vb2_get_drv_priv(q);
  568. struct saa7146_dmaqueue *dq = &dev->vv_data->video_dmaq;
  569. del_timer(&dq->timeout);
  570. video_end(dev);
  571. return_buffers(q, VB2_BUF_STATE_ERROR);
  572. }
  573. const struct vb2_ops video_qops = {
  574. .queue_setup = queue_setup,
  575. .buf_queue = buf_queue,
  576. .buf_init = buf_init,
  577. .buf_prepare = buf_prepare,
  578. .buf_cleanup = buf_cleanup,
  579. .start_streaming = start_streaming,
  580. .stop_streaming = stop_streaming,
  581. .wait_prepare = vb2_ops_wait_prepare,
  582. .wait_finish = vb2_ops_wait_finish,
  583. };
  584. /********************************************************************************/
  585. /* file operations */
  586. static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
  587. {
  588. INIT_LIST_HEAD(&vv->video_dmaq.queue);
  589. timer_setup(&vv->video_dmaq.timeout, saa7146_buffer_timeout, 0);
  590. vv->video_dmaq.dev = dev;
  591. /* set some default values */
  592. vv->standard = &dev->ext_vv_data->stds[0];
  593. /* FIXME: what's this? */
  594. vv->current_hps_source = SAA7146_HPS_SOURCE_PORT_A;
  595. vv->current_hps_sync = SAA7146_HPS_SYNC_PORT_A;
  596. }
  597. static void video_irq_done(struct saa7146_dev *dev, unsigned long st)
  598. {
  599. struct saa7146_vv *vv = dev->vv_data;
  600. struct saa7146_dmaqueue *q = &vv->video_dmaq;
  601. spin_lock(&dev->slock);
  602. DEB_CAP("called\n");
  603. /* only finish the buffer if we have one... */
  604. if (q->curr)
  605. saa7146_buffer_finish(dev, q, VB2_BUF_STATE_DONE);
  606. saa7146_buffer_next(dev,q,0);
  607. spin_unlock(&dev->slock);
  608. }
  609. const struct saa7146_use_ops saa7146_video_uops = {
  610. .init = video_init,
  611. .irq_done = video_irq_done,
  612. };