timblogiw.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894
  1. /*
  2. * timblogiw.c timberdale FPGA LogiWin Video In driver
  3. * Copyright (c) 2009-2010 Intel Corporation
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18. /* Supports:
  19. * Timberdale FPGA LogiWin Video In
  20. */
  21. #include <linux/version.h>
  22. #include <linux/platform_device.h>
  23. #include <linux/slab.h>
  24. #include <linux/dmaengine.h>
  25. #include <linux/mfd/core.h>
  26. #include <linux/scatterlist.h>
  27. #include <linux/interrupt.h>
  28. #include <linux/list.h>
  29. #include <linux/i2c.h>
  30. #include <media/v4l2-ioctl.h>
  31. #include <media/v4l2-device.h>
  32. #include <media/videobuf-dma-contig.h>
  33. #include <media/timb_video.h>
  34. #define DRIVER_NAME "timb-video"
  35. #define TIMBLOGIWIN_NAME "Timberdale Video-In"
  36. #define TIMBLOGIW_VERSION_CODE 0x04
  37. #define TIMBLOGIW_LINES_PER_DESC 44
  38. #define TIMBLOGIW_MAX_VIDEO_MEM 16
  39. #define TIMBLOGIW_HAS_DECODER(lw) (lw->pdata.encoder.module_name)
  40. struct timblogiw {
  41. struct video_device video_dev;
  42. struct v4l2_device v4l2_dev; /* mutual exclusion */
  43. struct mutex lock;
  44. struct device *dev;
  45. struct timb_video_platform_data pdata;
  46. struct v4l2_subdev *sd_enc; /* encoder */
  47. bool opened;
  48. };
  49. struct timblogiw_tvnorm {
  50. v4l2_std_id std;
  51. u16 width;
  52. u16 height;
  53. u8 fps;
  54. };
  55. struct timblogiw_fh {
  56. struct videobuf_queue vb_vidq;
  57. struct timblogiw_tvnorm const *cur_norm;
  58. struct list_head capture;
  59. struct dma_chan *chan;
  60. spinlock_t queue_lock; /* mutual exclusion */
  61. unsigned int frame_count;
  62. };
  63. struct timblogiw_buffer {
  64. /* common v4l buffer stuff -- must be first */
  65. struct videobuf_buffer vb;
  66. struct scatterlist sg[16];
  67. dma_cookie_t cookie;
  68. struct timblogiw_fh *fh;
  69. };
  70. const struct timblogiw_tvnorm timblogiw_tvnorms[] = {
  71. {
  72. .std = V4L2_STD_PAL,
  73. .width = 720,
  74. .height = 576,
  75. .fps = 25
  76. },
  77. {
  78. .std = V4L2_STD_NTSC,
  79. .width = 720,
  80. .height = 480,
  81. .fps = 30
  82. }
  83. };
  84. static int timblogiw_bytes_per_line(const struct timblogiw_tvnorm *norm)
  85. {
  86. return norm->width * 2;
  87. }
  88. static int timblogiw_frame_size(const struct timblogiw_tvnorm *norm)
  89. {
  90. return norm->height * timblogiw_bytes_per_line(norm);
  91. }
  92. static const struct timblogiw_tvnorm *timblogiw_get_norm(const v4l2_std_id std)
  93. {
  94. int i;
  95. for (i = 0; i < ARRAY_SIZE(timblogiw_tvnorms); i++)
  96. if (timblogiw_tvnorms[i].std & std)
  97. return timblogiw_tvnorms + i;
  98. /* default to first element */
  99. return timblogiw_tvnorms;
  100. }
  101. static void timblogiw_dma_cb(void *data)
  102. {
  103. struct timblogiw_buffer *buf = data;
  104. struct timblogiw_fh *fh = buf->fh;
  105. struct videobuf_buffer *vb = &buf->vb;
  106. spin_lock(&fh->queue_lock);
  107. /* mark the transfer done */
  108. buf->cookie = -1;
  109. fh->frame_count++;
  110. if (vb->state != VIDEOBUF_ERROR) {
  111. list_del(&vb->queue);
  112. do_gettimeofday(&vb->ts);
  113. vb->field_count = fh->frame_count * 2;
  114. vb->state = VIDEOBUF_DONE;
  115. wake_up(&vb->done);
  116. }
  117. if (!list_empty(&fh->capture)) {
  118. vb = list_entry(fh->capture.next, struct videobuf_buffer,
  119. queue);
  120. vb->state = VIDEOBUF_ACTIVE;
  121. }
  122. spin_unlock(&fh->queue_lock);
  123. }
  124. static bool timblogiw_dma_filter_fn(struct dma_chan *chan, void *filter_param)
  125. {
  126. return chan->chan_id == (uintptr_t)filter_param;
  127. }
  128. /* IOCTL functions */
  129. static int timblogiw_g_fmt(struct file *file, void *priv,
  130. struct v4l2_format *format)
  131. {
  132. struct video_device *vdev = video_devdata(file);
  133. struct timblogiw *lw = video_get_drvdata(vdev);
  134. struct timblogiw_fh *fh = priv;
  135. dev_dbg(&vdev->dev, "%s entry\n", __func__);
  136. if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
  137. return -EINVAL;
  138. mutex_lock(&lw->lock);
  139. format->fmt.pix.width = fh->cur_norm->width;
  140. format->fmt.pix.height = fh->cur_norm->height;
  141. format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
  142. format->fmt.pix.bytesperline = timblogiw_bytes_per_line(fh->cur_norm);
  143. format->fmt.pix.sizeimage = timblogiw_frame_size(fh->cur_norm);
  144. format->fmt.pix.field = V4L2_FIELD_NONE;
  145. mutex_unlock(&lw->lock);
  146. return 0;
  147. }
  148. static int timblogiw_try_fmt(struct file *file, void *priv,
  149. struct v4l2_format *format)
  150. {
  151. struct video_device *vdev = video_devdata(file);
  152. struct v4l2_pix_format *pix = &format->fmt.pix;
  153. dev_dbg(&vdev->dev,
  154. "%s - width=%d, height=%d, pixelformat=%d, field=%d\n"
  155. "bytes per line %d, size image: %d, colorspace: %d\n",
  156. __func__,
  157. pix->width, pix->height, pix->pixelformat, pix->field,
  158. pix->bytesperline, pix->sizeimage, pix->colorspace);
  159. if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
  160. return -EINVAL;
  161. if (pix->field != V4L2_FIELD_NONE)
  162. return -EINVAL;
  163. if (pix->pixelformat != V4L2_PIX_FMT_UYVY)
  164. return -EINVAL;
  165. return 0;
  166. }
  167. static int timblogiw_s_fmt(struct file *file, void *priv,
  168. struct v4l2_format *format)
  169. {
  170. struct video_device *vdev = video_devdata(file);
  171. struct timblogiw *lw = video_get_drvdata(vdev);
  172. struct timblogiw_fh *fh = priv;
  173. struct v4l2_pix_format *pix = &format->fmt.pix;
  174. int err;
  175. mutex_lock(&lw->lock);
  176. err = timblogiw_try_fmt(file, priv, format);
  177. if (err)
  178. goto out;
  179. if (videobuf_queue_is_busy(&fh->vb_vidq)) {
  180. dev_err(&vdev->dev, "%s queue busy\n", __func__);
  181. err = -EBUSY;
  182. goto out;
  183. }
  184. pix->width = fh->cur_norm->width;
  185. pix->height = fh->cur_norm->height;
  186. out:
  187. mutex_unlock(&lw->lock);
  188. return err;
  189. }
  190. static int timblogiw_querycap(struct file *file, void *priv,
  191. struct v4l2_capability *cap)
  192. {
  193. struct video_device *vdev = video_devdata(file);
  194. dev_dbg(&vdev->dev, "%s: Entry\n", __func__);
  195. memset(cap, 0, sizeof(*cap));
  196. strncpy(cap->card, TIMBLOGIWIN_NAME, sizeof(cap->card)-1);
  197. strncpy(cap->driver, DRIVER_NAME, sizeof(cap->driver) - 1);
  198. strlcpy(cap->bus_info, vdev->name, sizeof(cap->bus_info));
  199. cap->version = TIMBLOGIW_VERSION_CODE;
  200. cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
  201. V4L2_CAP_READWRITE;
  202. return 0;
  203. }
  204. static int timblogiw_enum_fmt(struct file *file, void *priv,
  205. struct v4l2_fmtdesc *fmt)
  206. {
  207. struct video_device *vdev = video_devdata(file);
  208. dev_dbg(&vdev->dev, "%s, index: %d\n", __func__, fmt->index);
  209. if (fmt->index != 0)
  210. return -EINVAL;
  211. memset(fmt, 0, sizeof(*fmt));
  212. fmt->index = 0;
  213. fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  214. strncpy(fmt->description, "4:2:2, packed, YUYV",
  215. sizeof(fmt->description)-1);
  216. fmt->pixelformat = V4L2_PIX_FMT_UYVY;
  217. return 0;
  218. }
  219. static int timblogiw_g_parm(struct file *file, void *priv,
  220. struct v4l2_streamparm *sp)
  221. {
  222. struct timblogiw_fh *fh = priv;
  223. struct v4l2_captureparm *cp = &sp->parm.capture;
  224. cp->capability = V4L2_CAP_TIMEPERFRAME;
  225. cp->timeperframe.numerator = 1;
  226. cp->timeperframe.denominator = fh->cur_norm->fps;
  227. return 0;
  228. }
  229. static int timblogiw_reqbufs(struct file *file, void *priv,
  230. struct v4l2_requestbuffers *rb)
  231. {
  232. struct video_device *vdev = video_devdata(file);
  233. struct timblogiw_fh *fh = priv;
  234. dev_dbg(&vdev->dev, "%s: entry\n", __func__);
  235. return videobuf_reqbufs(&fh->vb_vidq, rb);
  236. }
  237. static int timblogiw_querybuf(struct file *file, void *priv,
  238. struct v4l2_buffer *b)
  239. {
  240. struct video_device *vdev = video_devdata(file);
  241. struct timblogiw_fh *fh = priv;
  242. dev_dbg(&vdev->dev, "%s: entry\n", __func__);
  243. return videobuf_querybuf(&fh->vb_vidq, b);
  244. }
  245. static int timblogiw_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
  246. {
  247. struct video_device *vdev = video_devdata(file);
  248. struct timblogiw_fh *fh = priv;
  249. dev_dbg(&vdev->dev, "%s: entry\n", __func__);
  250. return videobuf_qbuf(&fh->vb_vidq, b);
  251. }
  252. static int timblogiw_dqbuf(struct file *file, void *priv,
  253. struct v4l2_buffer *b)
  254. {
  255. struct video_device *vdev = video_devdata(file);
  256. struct timblogiw_fh *fh = priv;
  257. dev_dbg(&vdev->dev, "%s: entry\n", __func__);
  258. return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
  259. }
  260. static int timblogiw_g_std(struct file *file, void *priv, v4l2_std_id *std)
  261. {
  262. struct video_device *vdev = video_devdata(file);
  263. struct timblogiw_fh *fh = priv;
  264. dev_dbg(&vdev->dev, "%s: entry\n", __func__);
  265. *std = fh->cur_norm->std;
  266. return 0;
  267. }
  268. static int timblogiw_s_std(struct file *file, void *priv, v4l2_std_id *std)
  269. {
  270. struct video_device *vdev = video_devdata(file);
  271. struct timblogiw *lw = video_get_drvdata(vdev);
  272. struct timblogiw_fh *fh = priv;
  273. int err = 0;
  274. dev_dbg(&vdev->dev, "%s: entry\n", __func__);
  275. mutex_lock(&lw->lock);
  276. if (TIMBLOGIW_HAS_DECODER(lw))
  277. err = v4l2_subdev_call(lw->sd_enc, core, s_std, *std);
  278. if (!err)
  279. fh->cur_norm = timblogiw_get_norm(*std);
  280. mutex_unlock(&lw->lock);
  281. return err;
  282. }
  283. static int timblogiw_enuminput(struct file *file, void *priv,
  284. struct v4l2_input *inp)
  285. {
  286. struct video_device *vdev = video_devdata(file);
  287. int i;
  288. dev_dbg(&vdev->dev, "%s: Entry\n", __func__);
  289. if (inp->index != 0)
  290. return -EINVAL;
  291. inp->index = 0;
  292. strncpy(inp->name, "Timb input 1", sizeof(inp->name) - 1);
  293. inp->type = V4L2_INPUT_TYPE_CAMERA;
  294. inp->std = 0;
  295. for (i = 0; i < ARRAY_SIZE(timblogiw_tvnorms); i++)
  296. inp->std |= timblogiw_tvnorms[i].std;
  297. return 0;
  298. }
  299. static int timblogiw_g_input(struct file *file, void *priv,
  300. unsigned int *input)
  301. {
  302. struct video_device *vdev = video_devdata(file);
  303. dev_dbg(&vdev->dev, "%s: Entry\n", __func__);
  304. *input = 0;
  305. return 0;
  306. }
  307. static int timblogiw_s_input(struct file *file, void *priv, unsigned int input)
  308. {
  309. struct video_device *vdev = video_devdata(file);
  310. dev_dbg(&vdev->dev, "%s: Entry\n", __func__);
  311. if (input != 0)
  312. return -EINVAL;
  313. return 0;
  314. }
  315. static int timblogiw_streamon(struct file *file, void *priv, unsigned int type)
  316. {
  317. struct video_device *vdev = video_devdata(file);
  318. struct timblogiw_fh *fh = priv;
  319. dev_dbg(&vdev->dev, "%s: entry\n", __func__);
  320. if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
  321. dev_dbg(&vdev->dev, "%s - No capture device\n", __func__);
  322. return -EINVAL;
  323. }
  324. fh->frame_count = 0;
  325. return videobuf_streamon(&fh->vb_vidq);
  326. }
  327. static int timblogiw_streamoff(struct file *file, void *priv,
  328. unsigned int type)
  329. {
  330. struct video_device *vdev = video_devdata(file);
  331. struct timblogiw_fh *fh = priv;
  332. dev_dbg(&vdev->dev, "%s entry\n", __func__);
  333. if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
  334. return -EINVAL;
  335. return videobuf_streamoff(&fh->vb_vidq);
  336. }
  337. static int timblogiw_querystd(struct file *file, void *priv, v4l2_std_id *std)
  338. {
  339. struct video_device *vdev = video_devdata(file);
  340. struct timblogiw *lw = video_get_drvdata(vdev);
  341. struct timblogiw_fh *fh = priv;
  342. dev_dbg(&vdev->dev, "%s entry\n", __func__);
  343. if (TIMBLOGIW_HAS_DECODER(lw))
  344. return v4l2_subdev_call(lw->sd_enc, video, querystd, std);
  345. else {
  346. *std = fh->cur_norm->std;
  347. return 0;
  348. }
  349. }
  350. static int timblogiw_enum_framesizes(struct file *file, void *priv,
  351. struct v4l2_frmsizeenum *fsize)
  352. {
  353. struct video_device *vdev = video_devdata(file);
  354. struct timblogiw_fh *fh = priv;
  355. dev_dbg(&vdev->dev, "%s - index: %d, format: %d\n", __func__,
  356. fsize->index, fsize->pixel_format);
  357. if ((fsize->index != 0) ||
  358. (fsize->pixel_format != V4L2_PIX_FMT_UYVY))
  359. return -EINVAL;
  360. fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
  361. fsize->discrete.width = fh->cur_norm->width;
  362. fsize->discrete.height = fh->cur_norm->height;
  363. return 0;
  364. }
  365. /* Video buffer functions */
  366. static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
  367. unsigned int *size)
  368. {
  369. struct timblogiw_fh *fh = vq->priv_data;
  370. *size = timblogiw_frame_size(fh->cur_norm);
  371. if (!*count)
  372. *count = 32;
  373. while (*size * *count > TIMBLOGIW_MAX_VIDEO_MEM * 1024 * 1024)
  374. (*count)--;
  375. return 0;
  376. }
  377. static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
  378. enum v4l2_field field)
  379. {
  380. struct timblogiw_fh *fh = vq->priv_data;
  381. struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer,
  382. vb);
  383. unsigned int data_size = timblogiw_frame_size(fh->cur_norm);
  384. int err = 0;
  385. if (vb->baddr && vb->bsize < data_size)
  386. /* User provided buffer, but it is too small */
  387. return -ENOMEM;
  388. vb->size = data_size;
  389. vb->width = fh->cur_norm->width;
  390. vb->height = fh->cur_norm->height;
  391. vb->field = field;
  392. if (vb->state == VIDEOBUF_NEEDS_INIT) {
  393. int i;
  394. unsigned int size;
  395. unsigned int bytes_per_desc = TIMBLOGIW_LINES_PER_DESC *
  396. timblogiw_bytes_per_line(fh->cur_norm);
  397. dma_addr_t addr;
  398. sg_init_table(buf->sg, ARRAY_SIZE(buf->sg));
  399. err = videobuf_iolock(vq, vb, NULL);
  400. if (err)
  401. goto err;
  402. addr = videobuf_to_dma_contig(vb);
  403. for (i = 0, size = 0; size < data_size; i++) {
  404. sg_dma_address(buf->sg + i) = addr + size;
  405. size += bytes_per_desc;
  406. sg_dma_len(buf->sg + i) = (size > data_size) ?
  407. (bytes_per_desc - (size - data_size)) :
  408. bytes_per_desc;
  409. }
  410. vb->state = VIDEOBUF_PREPARED;
  411. buf->cookie = -1;
  412. buf->fh = fh;
  413. }
  414. return 0;
  415. err:
  416. videobuf_dma_contig_free(vq, vb);
  417. vb->state = VIDEOBUF_NEEDS_INIT;
  418. return err;
  419. }
  420. static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
  421. {
  422. struct timblogiw_fh *fh = vq->priv_data;
  423. struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer,
  424. vb);
  425. struct dma_async_tx_descriptor *desc;
  426. int sg_elems;
  427. int bytes_per_desc = TIMBLOGIW_LINES_PER_DESC *
  428. timblogiw_bytes_per_line(fh->cur_norm);
  429. sg_elems = timblogiw_frame_size(fh->cur_norm) / bytes_per_desc;
  430. sg_elems +=
  431. (timblogiw_frame_size(fh->cur_norm) % bytes_per_desc) ? 1 : 0;
  432. if (list_empty(&fh->capture))
  433. vb->state = VIDEOBUF_ACTIVE;
  434. else
  435. vb->state = VIDEOBUF_QUEUED;
  436. list_add_tail(&vb->queue, &fh->capture);
  437. spin_unlock_irq(&fh->queue_lock);
  438. desc = fh->chan->device->device_prep_slave_sg(fh->chan,
  439. buf->sg, sg_elems, DMA_FROM_DEVICE,
  440. DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP);
  441. if (!desc) {
  442. spin_lock_irq(&fh->queue_lock);
  443. list_del_init(&vb->queue);
  444. vb->state = VIDEOBUF_PREPARED;
  445. return;
  446. }
  447. desc->callback_param = buf;
  448. desc->callback = timblogiw_dma_cb;
  449. buf->cookie = desc->tx_submit(desc);
  450. spin_lock_irq(&fh->queue_lock);
  451. }
  452. static void buffer_release(struct videobuf_queue *vq,
  453. struct videobuf_buffer *vb)
  454. {
  455. struct timblogiw_fh *fh = vq->priv_data;
  456. struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer,
  457. vb);
  458. videobuf_waiton(vq, vb, 0, 0);
  459. if (buf->cookie >= 0)
  460. dma_sync_wait(fh->chan, buf->cookie);
  461. videobuf_dma_contig_free(vq, vb);
  462. vb->state = VIDEOBUF_NEEDS_INIT;
  463. }
  464. static struct videobuf_queue_ops timblogiw_video_qops = {
  465. .buf_setup = buffer_setup,
  466. .buf_prepare = buffer_prepare,
  467. .buf_queue = buffer_queue,
  468. .buf_release = buffer_release,
  469. };
  470. /* Device Operations functions */
  471. static int timblogiw_open(struct file *file)
  472. {
  473. struct video_device *vdev = video_devdata(file);
  474. struct timblogiw *lw = video_get_drvdata(vdev);
  475. struct timblogiw_fh *fh;
  476. v4l2_std_id std;
  477. dma_cap_mask_t mask;
  478. int err = 0;
  479. dev_dbg(&vdev->dev, "%s: entry\n", __func__);
  480. mutex_lock(&lw->lock);
  481. if (lw->opened) {
  482. err = -EBUSY;
  483. goto out;
  484. }
  485. if (TIMBLOGIW_HAS_DECODER(lw) && !lw->sd_enc) {
  486. struct i2c_adapter *adapt;
  487. /* find the video decoder */
  488. adapt = i2c_get_adapter(lw->pdata.i2c_adapter);
  489. if (!adapt) {
  490. dev_err(&vdev->dev, "No I2C bus #%d\n",
  491. lw->pdata.i2c_adapter);
  492. err = -ENODEV;
  493. goto out;
  494. }
  495. /* now find the encoder */
  496. lw->sd_enc = v4l2_i2c_new_subdev_board(&lw->v4l2_dev, adapt,
  497. lw->pdata.encoder.info, NULL);
  498. i2c_put_adapter(adapt);
  499. if (!lw->sd_enc) {
  500. dev_err(&vdev->dev, "Failed to get encoder: %s\n",
  501. lw->pdata.encoder.module_name);
  502. err = -ENODEV;
  503. goto out;
  504. }
  505. }
  506. fh = kzalloc(sizeof(*fh), GFP_KERNEL);
  507. if (!fh) {
  508. err = -ENOMEM;
  509. goto out;
  510. }
  511. fh->cur_norm = timblogiw_tvnorms;
  512. timblogiw_querystd(file, fh, &std);
  513. fh->cur_norm = timblogiw_get_norm(std);
  514. INIT_LIST_HEAD(&fh->capture);
  515. spin_lock_init(&fh->queue_lock);
  516. dma_cap_zero(mask);
  517. dma_cap_set(DMA_SLAVE, mask);
  518. dma_cap_set(DMA_PRIVATE, mask);
  519. /* find the DMA channel */
  520. fh->chan = dma_request_channel(mask, timblogiw_dma_filter_fn,
  521. (void *)(uintptr_t)lw->pdata.dma_channel);
  522. if (!fh->chan) {
  523. dev_err(&vdev->dev, "Failed to get DMA channel\n");
  524. kfree(fh);
  525. err = -ENODEV;
  526. goto out;
  527. }
  528. file->private_data = fh;
  529. videobuf_queue_dma_contig_init(&fh->vb_vidq,
  530. &timblogiw_video_qops, lw->dev, &fh->queue_lock,
  531. V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
  532. sizeof(struct timblogiw_buffer), fh, NULL);
  533. lw->opened = true;
  534. out:
  535. mutex_unlock(&lw->lock);
  536. return err;
  537. }
  538. static int timblogiw_close(struct file *file)
  539. {
  540. struct video_device *vdev = video_devdata(file);
  541. struct timblogiw *lw = video_get_drvdata(vdev);
  542. struct timblogiw_fh *fh = file->private_data;
  543. dev_dbg(&vdev->dev, "%s: Entry\n", __func__);
  544. videobuf_stop(&fh->vb_vidq);
  545. videobuf_mmap_free(&fh->vb_vidq);
  546. dma_release_channel(fh->chan);
  547. kfree(fh);
  548. mutex_lock(&lw->lock);
  549. lw->opened = false;
  550. mutex_unlock(&lw->lock);
  551. return 0;
  552. }
  553. static ssize_t timblogiw_read(struct file *file, char __user *data,
  554. size_t count, loff_t *ppos)
  555. {
  556. struct video_device *vdev = video_devdata(file);
  557. struct timblogiw_fh *fh = file->private_data;
  558. dev_dbg(&vdev->dev, "%s: entry\n", __func__);
  559. return videobuf_read_stream(&fh->vb_vidq, data, count, ppos, 0,
  560. file->f_flags & O_NONBLOCK);
  561. }
  562. static unsigned int timblogiw_poll(struct file *file,
  563. struct poll_table_struct *wait)
  564. {
  565. struct video_device *vdev = video_devdata(file);
  566. struct timblogiw_fh *fh = file->private_data;
  567. dev_dbg(&vdev->dev, "%s: entry\n", __func__);
  568. return videobuf_poll_stream(file, &fh->vb_vidq, wait);
  569. }
  570. static int timblogiw_mmap(struct file *file, struct vm_area_struct *vma)
  571. {
  572. struct video_device *vdev = video_devdata(file);
  573. struct timblogiw_fh *fh = file->private_data;
  574. dev_dbg(&vdev->dev, "%s: entry\n", __func__);
  575. return videobuf_mmap_mapper(&fh->vb_vidq, vma);
  576. }
  577. /* Platform device functions */
  578. static __devinitconst struct v4l2_ioctl_ops timblogiw_ioctl_ops = {
  579. .vidioc_querycap = timblogiw_querycap,
  580. .vidioc_enum_fmt_vid_cap = timblogiw_enum_fmt,
  581. .vidioc_g_fmt_vid_cap = timblogiw_g_fmt,
  582. .vidioc_try_fmt_vid_cap = timblogiw_try_fmt,
  583. .vidioc_s_fmt_vid_cap = timblogiw_s_fmt,
  584. .vidioc_g_parm = timblogiw_g_parm,
  585. .vidioc_reqbufs = timblogiw_reqbufs,
  586. .vidioc_querybuf = timblogiw_querybuf,
  587. .vidioc_qbuf = timblogiw_qbuf,
  588. .vidioc_dqbuf = timblogiw_dqbuf,
  589. .vidioc_g_std = timblogiw_g_std,
  590. .vidioc_s_std = timblogiw_s_std,
  591. .vidioc_enum_input = timblogiw_enuminput,
  592. .vidioc_g_input = timblogiw_g_input,
  593. .vidioc_s_input = timblogiw_s_input,
  594. .vidioc_streamon = timblogiw_streamon,
  595. .vidioc_streamoff = timblogiw_streamoff,
  596. .vidioc_querystd = timblogiw_querystd,
  597. .vidioc_enum_framesizes = timblogiw_enum_framesizes,
  598. };
  599. static __devinitconst struct v4l2_file_operations timblogiw_fops = {
  600. .owner = THIS_MODULE,
  601. .open = timblogiw_open,
  602. .release = timblogiw_close,
  603. .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
  604. .mmap = timblogiw_mmap,
  605. .read = timblogiw_read,
  606. .poll = timblogiw_poll,
  607. };
  608. static __devinitconst struct video_device timblogiw_template = {
  609. .name = TIMBLOGIWIN_NAME,
  610. .fops = &timblogiw_fops,
  611. .ioctl_ops = &timblogiw_ioctl_ops,
  612. .release = video_device_release_empty,
  613. .minor = -1,
  614. .tvnorms = V4L2_STD_PAL | V4L2_STD_NTSC
  615. };
  616. static int __devinit timblogiw_probe(struct platform_device *pdev)
  617. {
  618. int err;
  619. struct timblogiw *lw = NULL;
  620. struct timb_video_platform_data *pdata = mfd_get_data(pdev);
  621. if (!pdata) {
  622. dev_err(&pdev->dev, "No platform data\n");
  623. err = -EINVAL;
  624. goto err;
  625. }
  626. if (!pdata->encoder.module_name)
  627. dev_info(&pdev->dev, "Running without decoder\n");
  628. lw = kzalloc(sizeof(*lw), GFP_KERNEL);
  629. if (!lw) {
  630. err = -ENOMEM;
  631. goto err;
  632. }
  633. if (pdev->dev.parent)
  634. lw->dev = pdev->dev.parent;
  635. else
  636. lw->dev = &pdev->dev;
  637. memcpy(&lw->pdata, pdata, sizeof(lw->pdata));
  638. mutex_init(&lw->lock);
  639. lw->video_dev = timblogiw_template;
  640. strlcpy(lw->v4l2_dev.name, DRIVER_NAME, sizeof(lw->v4l2_dev.name));
  641. err = v4l2_device_register(NULL, &lw->v4l2_dev);
  642. if (err)
  643. goto err_register;
  644. lw->video_dev.v4l2_dev = &lw->v4l2_dev;
  645. platform_set_drvdata(pdev, lw);
  646. video_set_drvdata(&lw->video_dev, lw);
  647. err = video_register_device(&lw->video_dev, VFL_TYPE_GRABBER, 0);
  648. if (err) {
  649. dev_err(&pdev->dev, "Error reg video: %d\n", err);
  650. goto err_request;
  651. }
  652. return 0;
  653. err_request:
  654. platform_set_drvdata(pdev, NULL);
  655. v4l2_device_unregister(&lw->v4l2_dev);
  656. err_register:
  657. kfree(lw);
  658. err:
  659. dev_err(&pdev->dev, "Failed to register: %d\n", err);
  660. return err;
  661. }
  662. static int __devexit timblogiw_remove(struct platform_device *pdev)
  663. {
  664. struct timblogiw *lw = platform_get_drvdata(pdev);
  665. video_unregister_device(&lw->video_dev);
  666. v4l2_device_unregister(&lw->v4l2_dev);
  667. kfree(lw);
  668. platform_set_drvdata(pdev, NULL);
  669. return 0;
  670. }
  671. static struct platform_driver timblogiw_platform_driver = {
  672. .driver = {
  673. .name = DRIVER_NAME,
  674. .owner = THIS_MODULE,
  675. },
  676. .probe = timblogiw_probe,
  677. .remove = __devexit_p(timblogiw_remove),
  678. };
  679. /* Module functions */
  680. static int __init timblogiw_init(void)
  681. {
  682. return platform_driver_register(&timblogiw_platform_driver);
  683. }
  684. static void __exit timblogiw_exit(void)
  685. {
  686. platform_driver_unregister(&timblogiw_platform_driver);
  687. }
  688. module_init(timblogiw_init);
  689. module_exit(timblogiw_exit);
  690. MODULE_DESCRIPTION(TIMBLOGIWIN_NAME);
  691. MODULE_AUTHOR("Pelagicore AB <info@pelagicore.com>");
  692. MODULE_LICENSE("GPL v2");
  693. MODULE_ALIAS("platform:"DRIVER_NAME);