dt3155.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. /***************************************************************************
  2. * Copyright (C) 2006-2010 by Marin Mitov *
  3. * mitov@issp.bas.bg *
  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 as published by *
  7. * the Free Software Foundation; either version 2 of the License, or *
  8. * (at your option) any later version. *
  9. * *
  10. * This program is distributed in the hope that it will be useful, *
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  13. * GNU General Public License for more details. *
  14. * *
  15. ***************************************************************************/
  16. #include <linux/module.h>
  17. #include <linux/stringify.h>
  18. #include <linux/delay.h>
  19. #include <linux/kthread.h>
  20. #include <linux/slab.h>
  21. #include <media/v4l2-dev.h>
  22. #include <media/v4l2-ioctl.h>
  23. #include <media/v4l2-common.h>
  24. #include <media/videobuf2-dma-contig.h>
  25. #include "dt3155.h"
  26. #define DT3155_DEVICE_ID 0x1223
  27. /**
  28. * read_i2c_reg - reads an internal i2c register
  29. *
  30. * @addr: dt3155 mmio base address
  31. * @index: index (internal address) of register to read
  32. * @data: pointer to byte the read data will be placed in
  33. *
  34. * returns: zero on success or error code
  35. *
  36. * This function starts reading the specified (by index) register
  37. * and busy waits for the process to finish. The result is placed
  38. * in a byte pointed by data.
  39. */
  40. static int read_i2c_reg(void __iomem *addr, u8 index, u8 *data)
  41. {
  42. u32 tmp = index;
  43. iowrite32((tmp << 17) | IIC_READ, addr + IIC_CSR2);
  44. mmiowb();
  45. udelay(45); /* wait at least 43 usec for NEW_CYCLE to clear */
  46. if (ioread32(addr + IIC_CSR2) & NEW_CYCLE)
  47. return -EIO; /* error: NEW_CYCLE not cleared */
  48. tmp = ioread32(addr + IIC_CSR1);
  49. if (tmp & DIRECT_ABORT) {
  50. /* reset DIRECT_ABORT bit */
  51. iowrite32(DIRECT_ABORT, addr + IIC_CSR1);
  52. return -EIO; /* error: DIRECT_ABORT set */
  53. }
  54. *data = tmp >> 24;
  55. return 0;
  56. }
  57. /**
  58. * write_i2c_reg - writes to an internal i2c register
  59. *
  60. * @addr: dt3155 mmio base address
  61. * @index: index (internal address) of register to read
  62. * @data: data to be written
  63. *
  64. * returns: zero on success or error code
  65. *
  66. * This function starts writing the specified (by index) register
  67. * and busy waits for the process to finish.
  68. */
  69. static int write_i2c_reg(void __iomem *addr, u8 index, u8 data)
  70. {
  71. u32 tmp = index;
  72. iowrite32((tmp << 17) | IIC_WRITE | data, addr + IIC_CSR2);
  73. mmiowb();
  74. udelay(65); /* wait at least 63 usec for NEW_CYCLE to clear */
  75. if (ioread32(addr + IIC_CSR2) & NEW_CYCLE)
  76. return -EIO; /* error: NEW_CYCLE not cleared */
  77. if (ioread32(addr + IIC_CSR1) & DIRECT_ABORT) {
  78. /* reset DIRECT_ABORT bit */
  79. iowrite32(DIRECT_ABORT, addr + IIC_CSR1);
  80. return -EIO; /* error: DIRECT_ABORT set */
  81. }
  82. return 0;
  83. }
  84. /**
  85. * write_i2c_reg_nowait - writes to an internal i2c register
  86. *
  87. * @addr: dt3155 mmio base address
  88. * @index: index (internal address) of register to read
  89. * @data: data to be written
  90. *
  91. * This function starts writing the specified (by index) register
  92. * and then returns.
  93. */
  94. static void write_i2c_reg_nowait(void __iomem *addr, u8 index, u8 data)
  95. {
  96. u32 tmp = index;
  97. iowrite32((tmp << 17) | IIC_WRITE | data, addr + IIC_CSR2);
  98. mmiowb();
  99. }
  100. /**
  101. * wait_i2c_reg - waits the read/write to finish
  102. *
  103. * @addr: dt3155 mmio base address
  104. *
  105. * returns: zero on success or error code
  106. *
  107. * This function waits reading/writing to finish.
  108. */
  109. static int wait_i2c_reg(void __iomem *addr)
  110. {
  111. if (ioread32(addr + IIC_CSR2) & NEW_CYCLE)
  112. udelay(65); /* wait at least 63 usec for NEW_CYCLE to clear */
  113. if (ioread32(addr + IIC_CSR2) & NEW_CYCLE)
  114. return -EIO; /* error: NEW_CYCLE not cleared */
  115. if (ioread32(addr + IIC_CSR1) & DIRECT_ABORT) {
  116. /* reset DIRECT_ABORT bit */
  117. iowrite32(DIRECT_ABORT, addr + IIC_CSR1);
  118. return -EIO; /* error: DIRECT_ABORT set */
  119. }
  120. return 0;
  121. }
  122. static int
  123. dt3155_queue_setup(struct vb2_queue *vq, const void *parg,
  124. unsigned int *nbuffers, unsigned int *num_planes,
  125. unsigned int sizes[], void *alloc_ctxs[])
  126. {
  127. const struct v4l2_format *fmt = parg;
  128. struct dt3155_priv *pd = vb2_get_drv_priv(vq);
  129. unsigned size = pd->width * pd->height;
  130. if (vq->num_buffers + *nbuffers < 2)
  131. *nbuffers = 2 - vq->num_buffers;
  132. if (fmt && fmt->fmt.pix.sizeimage < size)
  133. return -EINVAL;
  134. *num_planes = 1;
  135. sizes[0] = fmt ? fmt->fmt.pix.sizeimage : size;
  136. alloc_ctxs[0] = pd->alloc_ctx;
  137. return 0;
  138. }
  139. static int dt3155_buf_prepare(struct vb2_buffer *vb)
  140. {
  141. struct dt3155_priv *pd = vb2_get_drv_priv(vb->vb2_queue);
  142. vb2_set_plane_payload(vb, 0, pd->width * pd->height);
  143. return 0;
  144. }
  145. static int dt3155_start_streaming(struct vb2_queue *q, unsigned count)
  146. {
  147. struct dt3155_priv *pd = vb2_get_drv_priv(q);
  148. struct vb2_buffer *vb = &pd->curr_buf->vb2_buf;
  149. dma_addr_t dma_addr;
  150. pd->sequence = 0;
  151. dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
  152. iowrite32(dma_addr, pd->regs + EVEN_DMA_START);
  153. iowrite32(dma_addr + pd->width, pd->regs + ODD_DMA_START);
  154. iowrite32(pd->width, pd->regs + EVEN_DMA_STRIDE);
  155. iowrite32(pd->width, pd->regs + ODD_DMA_STRIDE);
  156. /* enable interrupts, clear all irq flags */
  157. iowrite32(FLD_START_EN | FLD_END_ODD_EN | FLD_START |
  158. FLD_END_EVEN | FLD_END_ODD, pd->regs + INT_CSR);
  159. iowrite32(FIFO_EN | SRST | FLD_CRPT_ODD | FLD_CRPT_EVEN |
  160. FLD_DN_ODD | FLD_DN_EVEN | CAP_CONT_EVEN | CAP_CONT_ODD,
  161. pd->regs + CSR1);
  162. wait_i2c_reg(pd->regs);
  163. write_i2c_reg(pd->regs, CONFIG, pd->config);
  164. write_i2c_reg(pd->regs, EVEN_CSR, CSR_ERROR | CSR_DONE);
  165. write_i2c_reg(pd->regs, ODD_CSR, CSR_ERROR | CSR_DONE);
  166. /* start the board */
  167. write_i2c_reg(pd->regs, CSR2, pd->csr2 | BUSY_EVEN | BUSY_ODD);
  168. return 0;
  169. }
  170. static void dt3155_stop_streaming(struct vb2_queue *q)
  171. {
  172. struct dt3155_priv *pd = vb2_get_drv_priv(q);
  173. struct vb2_buffer *vb;
  174. spin_lock_irq(&pd->lock);
  175. /* stop the board */
  176. write_i2c_reg_nowait(pd->regs, CSR2, pd->csr2);
  177. iowrite32(FIFO_EN | SRST | FLD_CRPT_ODD | FLD_CRPT_EVEN |
  178. FLD_DN_ODD | FLD_DN_EVEN, pd->regs + CSR1);
  179. /* disable interrupts, clear all irq flags */
  180. iowrite32(FLD_START | FLD_END_EVEN | FLD_END_ODD, pd->regs + INT_CSR);
  181. spin_unlock_irq(&pd->lock);
  182. /*
  183. * It is not clear whether the DMA stops at once or whether it
  184. * will finish the current frame or field first. To be on the
  185. * safe side we wait a bit.
  186. */
  187. msleep(45);
  188. spin_lock_irq(&pd->lock);
  189. if (pd->curr_buf) {
  190. vb2_buffer_done(&pd->curr_buf->vb2_buf, VB2_BUF_STATE_ERROR);
  191. pd->curr_buf = NULL;
  192. }
  193. while (!list_empty(&pd->dmaq)) {
  194. vb = list_first_entry(&pd->dmaq, typeof(*vb), done_entry);
  195. list_del(&vb->done_entry);
  196. vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
  197. }
  198. spin_unlock_irq(&pd->lock);
  199. }
  200. static void dt3155_buf_queue(struct vb2_buffer *vb)
  201. {
  202. struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
  203. struct dt3155_priv *pd = vb2_get_drv_priv(vb->vb2_queue);
  204. /* pd->vidq.streaming = 1 when dt3155_buf_queue() is invoked */
  205. spin_lock_irq(&pd->lock);
  206. if (pd->curr_buf)
  207. list_add_tail(&vb->done_entry, &pd->dmaq);
  208. else
  209. pd->curr_buf = vbuf;
  210. spin_unlock_irq(&pd->lock);
  211. }
  212. static const struct vb2_ops q_ops = {
  213. .queue_setup = dt3155_queue_setup,
  214. .wait_prepare = vb2_ops_wait_prepare,
  215. .wait_finish = vb2_ops_wait_finish,
  216. .buf_prepare = dt3155_buf_prepare,
  217. .start_streaming = dt3155_start_streaming,
  218. .stop_streaming = dt3155_stop_streaming,
  219. .buf_queue = dt3155_buf_queue,
  220. };
  221. static irqreturn_t dt3155_irq_handler_even(int irq, void *dev_id)
  222. {
  223. struct dt3155_priv *ipd = dev_id;
  224. struct vb2_buffer *ivb;
  225. dma_addr_t dma_addr;
  226. u32 tmp;
  227. tmp = ioread32(ipd->regs + INT_CSR) & (FLD_START | FLD_END_ODD);
  228. if (!tmp)
  229. return IRQ_NONE; /* not our irq */
  230. if ((tmp & FLD_START) && !(tmp & FLD_END_ODD)) {
  231. iowrite32(FLD_START_EN | FLD_END_ODD_EN | FLD_START,
  232. ipd->regs + INT_CSR);
  233. return IRQ_HANDLED; /* start of field irq */
  234. }
  235. tmp = ioread32(ipd->regs + CSR1) & (FLD_CRPT_EVEN | FLD_CRPT_ODD);
  236. if (tmp) {
  237. iowrite32(FIFO_EN | SRST | FLD_CRPT_ODD | FLD_CRPT_EVEN |
  238. FLD_DN_ODD | FLD_DN_EVEN |
  239. CAP_CONT_EVEN | CAP_CONT_ODD,
  240. ipd->regs + CSR1);
  241. mmiowb();
  242. }
  243. spin_lock(&ipd->lock);
  244. if (ipd->curr_buf && !list_empty(&ipd->dmaq)) {
  245. v4l2_get_timestamp(&ipd->curr_buf->timestamp);
  246. ipd->curr_buf->sequence = ipd->sequence++;
  247. ipd->curr_buf->field = V4L2_FIELD_NONE;
  248. vb2_buffer_done(&ipd->curr_buf->vb2_buf, VB2_BUF_STATE_DONE);
  249. ivb = list_first_entry(&ipd->dmaq, typeof(*ivb), done_entry);
  250. list_del(&ivb->done_entry);
  251. ipd->curr_buf = to_vb2_v4l2_buffer(ivb);
  252. dma_addr = vb2_dma_contig_plane_dma_addr(ivb, 0);
  253. iowrite32(dma_addr, ipd->regs + EVEN_DMA_START);
  254. iowrite32(dma_addr + ipd->width, ipd->regs + ODD_DMA_START);
  255. iowrite32(ipd->width, ipd->regs + EVEN_DMA_STRIDE);
  256. iowrite32(ipd->width, ipd->regs + ODD_DMA_STRIDE);
  257. mmiowb();
  258. }
  259. /* enable interrupts, clear all irq flags */
  260. iowrite32(FLD_START_EN | FLD_END_ODD_EN | FLD_START |
  261. FLD_END_EVEN | FLD_END_ODD, ipd->regs + INT_CSR);
  262. spin_unlock(&ipd->lock);
  263. return IRQ_HANDLED;
  264. }
  265. static const struct v4l2_file_operations dt3155_fops = {
  266. .owner = THIS_MODULE,
  267. .open = v4l2_fh_open,
  268. .release = vb2_fop_release,
  269. .unlocked_ioctl = video_ioctl2,
  270. .read = vb2_fop_read,
  271. .mmap = vb2_fop_mmap,
  272. .poll = vb2_fop_poll
  273. };
  274. static int dt3155_querycap(struct file *filp, void *p,
  275. struct v4l2_capability *cap)
  276. {
  277. struct dt3155_priv *pd = video_drvdata(filp);
  278. strcpy(cap->driver, DT3155_NAME);
  279. strcpy(cap->card, DT3155_NAME " frame grabber");
  280. sprintf(cap->bus_info, "PCI:%s", pci_name(pd->pdev));
  281. cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
  282. V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
  283. cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
  284. return 0;
  285. }
  286. static int dt3155_enum_fmt_vid_cap(struct file *filp,
  287. void *p, struct v4l2_fmtdesc *f)
  288. {
  289. if (f->index)
  290. return -EINVAL;
  291. f->pixelformat = V4L2_PIX_FMT_GREY;
  292. strcpy(f->description, "8-bit Greyscale");
  293. return 0;
  294. }
  295. static int dt3155_fmt_vid_cap(struct file *filp, void *p, struct v4l2_format *f)
  296. {
  297. struct dt3155_priv *pd = video_drvdata(filp);
  298. f->fmt.pix.width = pd->width;
  299. f->fmt.pix.height = pd->height;
  300. f->fmt.pix.pixelformat = V4L2_PIX_FMT_GREY;
  301. f->fmt.pix.field = V4L2_FIELD_NONE;
  302. f->fmt.pix.bytesperline = f->fmt.pix.width;
  303. f->fmt.pix.sizeimage = f->fmt.pix.width * f->fmt.pix.height;
  304. f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
  305. return 0;
  306. }
  307. static int dt3155_g_std(struct file *filp, void *p, v4l2_std_id *norm)
  308. {
  309. struct dt3155_priv *pd = video_drvdata(filp);
  310. *norm = pd->std;
  311. return 0;
  312. }
  313. static int dt3155_s_std(struct file *filp, void *p, v4l2_std_id norm)
  314. {
  315. struct dt3155_priv *pd = video_drvdata(filp);
  316. if (pd->std == norm)
  317. return 0;
  318. if (vb2_is_busy(&pd->vidq))
  319. return -EBUSY;
  320. pd->std = norm;
  321. if (pd->std & V4L2_STD_525_60) {
  322. pd->csr2 = VT_60HZ;
  323. pd->width = 640;
  324. pd->height = 480;
  325. } else {
  326. pd->csr2 = VT_50HZ;
  327. pd->width = 768;
  328. pd->height = 576;
  329. }
  330. return 0;
  331. }
  332. static int dt3155_enum_input(struct file *filp, void *p,
  333. struct v4l2_input *input)
  334. {
  335. if (input->index > 3)
  336. return -EINVAL;
  337. if (input->index)
  338. snprintf(input->name, sizeof(input->name), "VID%d",
  339. input->index);
  340. else
  341. strlcpy(input->name, "J2/VID0", sizeof(input->name));
  342. input->type = V4L2_INPUT_TYPE_CAMERA;
  343. input->std = V4L2_STD_ALL;
  344. input->status = 0;
  345. return 0;
  346. }
  347. static int dt3155_g_input(struct file *filp, void *p, unsigned int *i)
  348. {
  349. struct dt3155_priv *pd = video_drvdata(filp);
  350. *i = pd->input;
  351. return 0;
  352. }
  353. static int dt3155_s_input(struct file *filp, void *p, unsigned int i)
  354. {
  355. struct dt3155_priv *pd = video_drvdata(filp);
  356. if (i > 3)
  357. return -EINVAL;
  358. pd->input = i;
  359. write_i2c_reg(pd->regs, AD_ADDR, AD_CMD_REG);
  360. write_i2c_reg(pd->regs, AD_CMD, (i << 6) | (i << 4) | SYNC_LVL_3);
  361. return 0;
  362. }
  363. static const struct v4l2_ioctl_ops dt3155_ioctl_ops = {
  364. .vidioc_querycap = dt3155_querycap,
  365. .vidioc_enum_fmt_vid_cap = dt3155_enum_fmt_vid_cap,
  366. .vidioc_try_fmt_vid_cap = dt3155_fmt_vid_cap,
  367. .vidioc_g_fmt_vid_cap = dt3155_fmt_vid_cap,
  368. .vidioc_s_fmt_vid_cap = dt3155_fmt_vid_cap,
  369. .vidioc_reqbufs = vb2_ioctl_reqbufs,
  370. .vidioc_create_bufs = vb2_ioctl_create_bufs,
  371. .vidioc_querybuf = vb2_ioctl_querybuf,
  372. .vidioc_expbuf = vb2_ioctl_expbuf,
  373. .vidioc_qbuf = vb2_ioctl_qbuf,
  374. .vidioc_dqbuf = vb2_ioctl_dqbuf,
  375. .vidioc_streamon = vb2_ioctl_streamon,
  376. .vidioc_streamoff = vb2_ioctl_streamoff,
  377. .vidioc_g_std = dt3155_g_std,
  378. .vidioc_s_std = dt3155_s_std,
  379. .vidioc_enum_input = dt3155_enum_input,
  380. .vidioc_g_input = dt3155_g_input,
  381. .vidioc_s_input = dt3155_s_input,
  382. };
  383. static int dt3155_init_board(struct dt3155_priv *pd)
  384. {
  385. struct pci_dev *pdev = pd->pdev;
  386. int i;
  387. u8 tmp = 0;
  388. pci_set_master(pdev); /* dt3155 needs it */
  389. /* resetting the adapter */
  390. iowrite32(ADDR_ERR_ODD | ADDR_ERR_EVEN | FLD_CRPT_ODD | FLD_CRPT_EVEN |
  391. FLD_DN_ODD | FLD_DN_EVEN, pd->regs + CSR1);
  392. mmiowb();
  393. msleep(20);
  394. /* initializing adapter registers */
  395. iowrite32(FIFO_EN | SRST, pd->regs + CSR1);
  396. mmiowb();
  397. iowrite32(0xEEEEEE01, pd->regs + EVEN_PIXEL_FMT);
  398. iowrite32(0xEEEEEE01, pd->regs + ODD_PIXEL_FMT);
  399. iowrite32(0x00000020, pd->regs + FIFO_TRIGER);
  400. iowrite32(0x00000103, pd->regs + XFER_MODE);
  401. iowrite32(0, pd->regs + RETRY_WAIT_CNT);
  402. iowrite32(0, pd->regs + INT_CSR);
  403. iowrite32(1, pd->regs + EVEN_FLD_MASK);
  404. iowrite32(1, pd->regs + ODD_FLD_MASK);
  405. iowrite32(0, pd->regs + MASK_LENGTH);
  406. iowrite32(0x0005007C, pd->regs + FIFO_FLAG_CNT);
  407. iowrite32(0x01010101, pd->regs + IIC_CLK_DUR);
  408. mmiowb();
  409. /* verifying that we have a DT3155 board (not just a SAA7116 chip) */
  410. read_i2c_reg(pd->regs, DT_ID, &tmp);
  411. if (tmp != DT3155_ID)
  412. return -ENODEV;
  413. /* initialize AD LUT */
  414. write_i2c_reg(pd->regs, AD_ADDR, 0);
  415. for (i = 0; i < 256; i++)
  416. write_i2c_reg(pd->regs, AD_LUT, i);
  417. /* initialize ADC references */
  418. /* FIXME: pos_ref & neg_ref depend on VT_50HZ */
  419. write_i2c_reg(pd->regs, AD_ADDR, AD_CMD_REG);
  420. write_i2c_reg(pd->regs, AD_CMD, VIDEO_CNL_1 | SYNC_CNL_1 | SYNC_LVL_3);
  421. write_i2c_reg(pd->regs, AD_ADDR, AD_POS_REF);
  422. write_i2c_reg(pd->regs, AD_CMD, 34);
  423. write_i2c_reg(pd->regs, AD_ADDR, AD_NEG_REF);
  424. write_i2c_reg(pd->regs, AD_CMD, 0);
  425. /* initialize PM LUT */
  426. write_i2c_reg(pd->regs, CONFIG, pd->config | PM_LUT_PGM);
  427. for (i = 0; i < 256; i++) {
  428. write_i2c_reg(pd->regs, PM_LUT_ADDR, i);
  429. write_i2c_reg(pd->regs, PM_LUT_DATA, i);
  430. }
  431. write_i2c_reg(pd->regs, CONFIG, pd->config | PM_LUT_PGM | PM_LUT_SEL);
  432. for (i = 0; i < 256; i++) {
  433. write_i2c_reg(pd->regs, PM_LUT_ADDR, i);
  434. write_i2c_reg(pd->regs, PM_LUT_DATA, i);
  435. }
  436. write_i2c_reg(pd->regs, CONFIG, pd->config); /* ACQ_MODE_EVEN */
  437. /* select channel 1 for input and set sync level */
  438. write_i2c_reg(pd->regs, AD_ADDR, AD_CMD_REG);
  439. write_i2c_reg(pd->regs, AD_CMD, VIDEO_CNL_1 | SYNC_CNL_1 | SYNC_LVL_3);
  440. /* disable all irqs, clear all irq flags */
  441. iowrite32(FLD_START | FLD_END_EVEN | FLD_END_ODD,
  442. pd->regs + INT_CSR);
  443. return 0;
  444. }
  445. static struct video_device dt3155_vdev = {
  446. .name = DT3155_NAME,
  447. .fops = &dt3155_fops,
  448. .ioctl_ops = &dt3155_ioctl_ops,
  449. .minor = -1,
  450. .release = video_device_release_empty,
  451. .tvnorms = V4L2_STD_ALL,
  452. };
  453. static int dt3155_probe(struct pci_dev *pdev, const struct pci_device_id *id)
  454. {
  455. int err;
  456. struct dt3155_priv *pd;
  457. err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
  458. if (err)
  459. return -ENODEV;
  460. pd = devm_kzalloc(&pdev->dev, sizeof(*pd), GFP_KERNEL);
  461. if (!pd)
  462. return -ENOMEM;
  463. err = v4l2_device_register(&pdev->dev, &pd->v4l2_dev);
  464. if (err)
  465. return err;
  466. pd->vdev = dt3155_vdev;
  467. pd->vdev.v4l2_dev = &pd->v4l2_dev;
  468. video_set_drvdata(&pd->vdev, pd); /* for use in video_fops */
  469. pd->pdev = pdev;
  470. pd->std = V4L2_STD_625_50;
  471. pd->csr2 = VT_50HZ;
  472. pd->width = 768;
  473. pd->height = 576;
  474. INIT_LIST_HEAD(&pd->dmaq);
  475. mutex_init(&pd->mux);
  476. pd->vdev.lock = &pd->mux; /* for locking v4l2_file_operations */
  477. pd->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  478. pd->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
  479. pd->vidq.io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;
  480. pd->vidq.ops = &q_ops;
  481. pd->vidq.mem_ops = &vb2_dma_contig_memops;
  482. pd->vidq.drv_priv = pd;
  483. pd->vidq.min_buffers_needed = 2;
  484. pd->vidq.gfp_flags = GFP_DMA32;
  485. pd->vidq.lock = &pd->mux; /* for locking v4l2_file_operations */
  486. pd->vdev.queue = &pd->vidq;
  487. err = vb2_queue_init(&pd->vidq);
  488. if (err < 0)
  489. goto err_v4l2_dev_unreg;
  490. pd->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
  491. if (IS_ERR(pd->alloc_ctx)) {
  492. dev_err(&pdev->dev, "Can't allocate buffer context");
  493. err = PTR_ERR(pd->alloc_ctx);
  494. goto err_v4l2_dev_unreg;
  495. }
  496. spin_lock_init(&pd->lock);
  497. pd->config = ACQ_MODE_EVEN;
  498. err = pci_enable_device(pdev);
  499. if (err)
  500. goto err_free_ctx;
  501. err = pci_request_region(pdev, 0, pci_name(pdev));
  502. if (err)
  503. goto err_pci_disable;
  504. pd->regs = pci_iomap(pdev, 0, pci_resource_len(pd->pdev, 0));
  505. if (!pd->regs) {
  506. err = -ENOMEM;
  507. goto err_free_reg;
  508. }
  509. err = dt3155_init_board(pd);
  510. if (err)
  511. goto err_iounmap;
  512. err = request_irq(pd->pdev->irq, dt3155_irq_handler_even,
  513. IRQF_SHARED, DT3155_NAME, pd);
  514. if (err)
  515. goto err_iounmap;
  516. err = video_register_device(&pd->vdev, VFL_TYPE_GRABBER, -1);
  517. if (err)
  518. goto err_free_irq;
  519. dev_info(&pdev->dev, "/dev/video%i is ready\n", pd->vdev.minor);
  520. return 0; /* success */
  521. err_free_irq:
  522. free_irq(pd->pdev->irq, pd);
  523. err_iounmap:
  524. pci_iounmap(pdev, pd->regs);
  525. err_free_reg:
  526. pci_release_region(pdev, 0);
  527. err_pci_disable:
  528. pci_disable_device(pdev);
  529. err_free_ctx:
  530. vb2_dma_contig_cleanup_ctx(pd->alloc_ctx);
  531. err_v4l2_dev_unreg:
  532. v4l2_device_unregister(&pd->v4l2_dev);
  533. return err;
  534. }
  535. static void dt3155_remove(struct pci_dev *pdev)
  536. {
  537. struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev);
  538. struct dt3155_priv *pd = container_of(v4l2_dev, struct dt3155_priv,
  539. v4l2_dev);
  540. video_unregister_device(&pd->vdev);
  541. free_irq(pd->pdev->irq, pd);
  542. vb2_queue_release(&pd->vidq);
  543. v4l2_device_unregister(&pd->v4l2_dev);
  544. pci_iounmap(pdev, pd->regs);
  545. pci_release_region(pdev, 0);
  546. pci_disable_device(pdev);
  547. vb2_dma_contig_cleanup_ctx(pd->alloc_ctx);
  548. }
  549. static const struct pci_device_id pci_ids[] = {
  550. { PCI_DEVICE(PCI_VENDOR_ID_INTEL, DT3155_DEVICE_ID) },
  551. { 0, /* zero marks the end */ },
  552. };
  553. MODULE_DEVICE_TABLE(pci, pci_ids);
  554. static struct pci_driver pci_driver = {
  555. .name = DT3155_NAME,
  556. .id_table = pci_ids,
  557. .probe = dt3155_probe,
  558. .remove = dt3155_remove,
  559. };
  560. module_pci_driver(pci_driver);
  561. MODULE_DESCRIPTION("video4linux pci-driver for dt3155 frame grabber");
  562. MODULE_AUTHOR("Marin Mitov <mitov@issp.bas.bg>");
  563. MODULE_VERSION(DT3155_VERSION);
  564. MODULE_LICENSE("GPL");