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