2 * Driver for the Conexant CX25821 PCIe bridge
4 * Copyright (C) 2009 Conexant Systems Inc.
5 * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
6 * Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "cx25821-video.h"
26 static void buffer_queue(struct videobuf_queue
*vq
, struct videobuf_buffer
*vb
)
28 struct cx25821_buffer
*buf
=
29 container_of(vb
, struct cx25821_buffer
, vb
);
30 struct cx25821_buffer
*prev
;
31 struct cx25821_fh
*fh
= vq
->priv_data
;
32 struct cx25821_dev
*dev
= fh
->dev
;
33 struct cx25821_dmaqueue
*q
= &dev
->vidq
[VIDEO_IOCTL_CH
];
35 /* add jump to stopper */
36 buf
->risc
.jmp
[0] = cpu_to_le32(RISC_JUMP
| RISC_IRQ1
| RISC_CNT_INC
);
37 buf
->risc
.jmp
[1] = cpu_to_le32(q
->stopper
.dma
);
38 buf
->risc
.jmp
[2] = cpu_to_le32(0); /* bits 63-32 */
40 dprintk(2, "jmp to stopper (0x%x)\n", buf
->risc
.jmp
[1]);
42 if (!list_empty(&q
->queued
)) {
43 list_add_tail(&buf
->vb
.queue
, &q
->queued
);
44 buf
->vb
.state
= VIDEOBUF_QUEUED
;
45 dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf
,
48 } else if (list_empty(&q
->active
)) {
49 list_add_tail(&buf
->vb
.queue
, &q
->active
);
50 cx25821_start_video_dma(dev
, q
, buf
,
51 &dev
->sram_channels
[VIDEO_IOCTL_CH
]);
52 buf
->vb
.state
= VIDEOBUF_ACTIVE
;
53 buf
->count
= q
->count
++;
54 mod_timer(&q
->timeout
, jiffies
+ BUFFER_TIMEOUT
);
56 "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
57 buf
, buf
->vb
.i
, buf
->count
, q
->count
);
60 list_entry(q
->active
.prev
, struct cx25821_buffer
, vb
.queue
);
61 if (prev
->vb
.width
== buf
->vb
.width
62 && prev
->vb
.height
== buf
->vb
.height
63 && prev
->fmt
== buf
->fmt
) {
64 list_add_tail(&buf
->vb
.queue
, &q
->active
);
65 buf
->vb
.state
= VIDEOBUF_ACTIVE
;
66 buf
->count
= q
->count
++;
67 prev
->risc
.jmp
[1] = cpu_to_le32(buf
->risc
.dma
);
69 /* 64 bit bits 63-32 */
70 prev
->risc
.jmp
[2] = cpu_to_le32(0);
72 "[%p/%d] buffer_queue - append to active, buf->count=%d\n",
73 buf
, buf
->vb
.i
, buf
->count
);
76 list_add_tail(&buf
->vb
.queue
, &q
->queued
);
77 buf
->vb
.state
= VIDEOBUF_QUEUED
;
78 dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf
,
83 if (list_empty(&q
->active
)) {
84 dprintk(2, "active queue empty!\n");
88 static struct videobuf_queue_ops cx25821_video_qops
= {
89 .buf_setup
= buffer_setup
,
90 .buf_prepare
= buffer_prepare
,
91 .buf_queue
= buffer_queue
,
92 .buf_release
= buffer_release
,
95 static int video_open(struct file
*file
)
97 int minor
= video_devdata(file
)->minor
;
98 struct cx25821_dev
*h
, *dev
= NULL
;
99 struct cx25821_fh
*fh
;
100 struct list_head
*list
;
101 enum v4l2_buf_type type
= 0;
105 list_for_each(list
, &cx25821_devlist
) {
106 h
= list_entry(list
, struct cx25821_dev
, devlist
);
108 if (h
->ioctl_dev
&& h
->ioctl_dev
->minor
== minor
) {
110 type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
119 printk("open minor=%d type=%s\n", minor
, v4l2_type_names
[type
]);
121 /* allocate + initialize per filehandle data */
122 fh
= kzalloc(sizeof(*fh
), GFP_KERNEL
);
128 file
->private_data
= fh
;
133 if (dev
->tvnorm
& V4L2_STD_PAL_BG
|| dev
->tvnorm
& V4L2_STD_PAL_DK
)
138 dev
->channel_opened
= VIDEO_IOCTL_CH
;
139 pix_format
= V4L2_PIX_FMT_YUYV
;
140 fh
->fmt
= format_by_fourcc(pix_format
);
142 v4l2_prio_open(&dev
->prio
, &fh
->prio
);
144 videobuf_queue_sg_init(&fh
->vidq
, &cx25821_video_qops
,
145 &dev
->pci
->dev
, &dev
->slock
,
146 V4L2_BUF_TYPE_VIDEO_CAPTURE
,
147 V4L2_FIELD_INTERLACED
,
148 sizeof(struct cx25821_buffer
), fh
);
150 dprintk(1, "post videobuf_queue_init()\n");
156 static ssize_t
video_read(struct file
*file
, char __user
* data
, size_t count
,
159 struct cx25821_fh
*fh
= file
->private_data
;
162 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
163 if (res_locked(fh
->dev
, RESOURCE_VIDEO_IOCTL
))
166 return videobuf_read_one(&fh
->vidq
, data
, count
, ppos
,
167 file
->f_flags
& O_NONBLOCK
);
175 static unsigned int video_poll(struct file
*file
,
176 struct poll_table_struct
*wait
)
178 struct cx25821_fh
*fh
= file
->private_data
;
179 struct cx25821_buffer
*buf
;
181 if (res_check(fh
, RESOURCE_VIDEO_IOCTL
)) {
182 /* streaming capture */
183 if (list_empty(&fh
->vidq
.stream
))
185 buf
= list_entry(fh
->vidq
.stream
.next
,
186 struct cx25821_buffer
, vb
.stream
);
189 buf
= (struct cx25821_buffer
*)fh
->vidq
.read_buf
;
194 poll_wait(file
, &buf
->vb
.done
, wait
);
195 if (buf
->vb
.state
== VIDEOBUF_DONE
|| buf
->vb
.state
== VIDEOBUF_ERROR
)
196 return POLLIN
| POLLRDNORM
;
201 static int video_release(struct file
*file
)
203 struct cx25821_fh
*fh
= file
->private_data
;
204 struct cx25821_dev
*dev
= fh
->dev
;
206 /* stop video capture */
207 if (res_check(fh
, RESOURCE_VIDEO_IOCTL
)) {
208 videobuf_queue_cancel(&fh
->vidq
);
209 res_free(dev
, fh
, RESOURCE_VIDEO_IOCTL
);
212 if (fh
->vidq
.read_buf
) {
213 buffer_release(&fh
->vidq
, fh
->vidq
.read_buf
);
214 kfree(fh
->vidq
.read_buf
);
217 videobuf_mmap_free(&fh
->vidq
);
219 v4l2_prio_close(&dev
->prio
, &fh
->prio
);
221 file
->private_data
= NULL
;
227 static int vidioc_streamon(struct file
*file
, void *priv
, enum v4l2_buf_type i
)
229 struct cx25821_fh
*fh
= priv
;
230 struct cx25821_dev
*dev
= fh
->dev
;
232 if (unlikely(fh
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)) {
236 if (unlikely(i
!= fh
->type
)) {
240 if (unlikely(!res_get(dev
, fh
, get_resource(fh
, RESOURCE_VIDEO_IOCTL
)))) {
244 return videobuf_streamon(get_queue(fh
));
247 static int vidioc_streamoff(struct file
*file
, void *priv
, enum v4l2_buf_type i
)
249 struct cx25821_fh
*fh
= priv
;
250 struct cx25821_dev
*dev
= fh
->dev
;
253 if (fh
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
258 res
= get_resource(fh
, RESOURCE_VIDEO_IOCTL
);
259 err
= videobuf_streamoff(get_queue(fh
));
262 res_free(dev
, fh
, res
);
266 static int vidioc_s_fmt_vid_cap(struct file
*file
, void *priv
,
267 struct v4l2_format
*f
)
269 struct cx25821_fh
*fh
= priv
;
270 struct cx25821_dev
*dev
= ((struct cx25821_fh
*)priv
)->dev
;
274 err
= v4l2_prio_check(&dev
->prio
, &fh
->prio
);
279 dprintk(2, "%s()\n", __func__
);
280 err
= vidioc_try_fmt_vid_cap(file
, priv
, f
);
284 fh
->fmt
= format_by_fourcc(f
->fmt
.pix
.pixelformat
);
285 fh
->width
= f
->fmt
.pix
.width
;
286 fh
->height
= f
->fmt
.pix
.height
;
287 fh
->vidq
.field
= f
->fmt
.pix
.field
;
288 dprintk(2, "%s() width=%d height=%d field=%d\n", __func__
, fh
->width
,
289 fh
->height
, fh
->vidq
.field
);
290 cx25821_call_all(dev
, video
, s_fmt
, f
);
294 static int vidioc_dqbuf(struct file
*file
, void *priv
, struct v4l2_buffer
*p
)
296 struct cx25821_fh
*fh
= priv
;
297 return videobuf_dqbuf(get_queue(fh
), p
, file
->f_flags
& O_NONBLOCK
);
300 static long video_ioctl_set(struct file
*file
, unsigned int cmd
,
303 struct cx25821_fh
*fh
= file
->private_data
;
304 struct cx25821_dev
*dev
= fh
->dev
;
305 struct downstream_user_struct
*data_from_user
;
308 int selected_channel
= 0, pix_format
= 0, i
= 0;
309 int cif_enable
= 0, cif_width
= 0;
312 data_from_user
= (struct downstream_user_struct
*)arg
;
314 if (!data_from_user
) {
315 printk("cx25821 in %s(): User data is INVALID. Returning.\n",
320 command
= data_from_user
->command
;
322 if (command
!= SET_VIDEO_STD
&& command
!= SET_PIXEL_FORMAT
323 && command
!= ENABLE_CIF_RESOLUTION
&& command
!= REG_READ
324 && command
!= REG_WRITE
&& command
!= MEDUSA_READ
325 && command
!= MEDUSA_WRITE
) {
332 !strcmp(data_from_user
->vid_stdname
,
333 "PAL") ? V4L2_STD_PAL_BG
: V4L2_STD_NTSC_M
;
334 medusa_set_videostandard(dev
);
337 case SET_PIXEL_FORMAT
:
338 selected_channel
= data_from_user
->decoder_select
;
339 pix_format
= data_from_user
->pixel_format
;
341 if (!(selected_channel
<= 7 && selected_channel
>= 0)) {
342 selected_channel
-= 4;
343 selected_channel
= selected_channel
% 8;
346 if (selected_channel
>= 0)
347 cx25821_set_pixel_format(dev
, selected_channel
,
352 case ENABLE_CIF_RESOLUTION
:
353 selected_channel
= data_from_user
->decoder_select
;
354 cif_enable
= data_from_user
->cif_resolution_enable
;
355 cif_width
= data_from_user
->cif_width
;
358 if (dev
->tvnorm
& V4L2_STD_PAL_BG
359 || dev
->tvnorm
& V4L2_STD_PAL_DK
)
362 width
= (cif_width
== 320
363 || cif_width
== 352) ? cif_width
: 320;
366 if (!(selected_channel
<= 7 && selected_channel
>= 0)) {
367 selected_channel
-= 4;
368 selected_channel
= selected_channel
% 8;
371 if (selected_channel
<= 7 && selected_channel
>= 0) {
372 dev
->use_cif_resolution
[selected_channel
] = cif_enable
;
373 dev
->cif_width
[selected_channel
] = width
;
375 for (i
= 0; i
< VID_CHANNEL_NUM
; i
++) {
376 dev
->use_cif_resolution
[i
] = cif_enable
;
377 dev
->cif_width
[i
] = width
;
381 medusa_set_resolution(dev
, width
, selected_channel
);
384 data_from_user
->reg_data
= cx_read(data_from_user
->reg_address
);
387 cx_write(data_from_user
->reg_address
, data_from_user
->reg_data
);
391 cx25821_i2c_read(&dev
->i2c_bus
[0],
392 (u16
) data_from_user
->reg_address
,
393 &data_from_user
->reg_data
);
396 cx25821_i2c_write(&dev
->i2c_bus
[0],
397 (u16
) data_from_user
->reg_address
,
398 data_from_user
->reg_data
);
405 static int vidioc_log_status(struct file
*file
, void *priv
)
407 struct cx25821_dev
*dev
= ((struct cx25821_fh
*)priv
)->dev
;
410 snprintf(name
, sizeof(name
), "%s/2", dev
->name
);
411 printk(KERN_INFO
"%s/2: ============ START LOG STATUS ============\n",
413 cx25821_call_all(dev
, core
, log_status
);
414 printk(KERN_INFO
"%s/2: ============= END LOG STATUS =============\n",
419 static int vidioc_s_ctrl(struct file
*file
, void *priv
,
420 struct v4l2_control
*ctl
)
422 struct cx25821_fh
*fh
= priv
;
423 struct cx25821_dev
*dev
= ((struct cx25821_fh
*)priv
)->dev
;
427 err
= v4l2_prio_check(&dev
->prio
, &fh
->prio
);
436 static const struct v4l2_file_operations video_fops
= {
437 .owner
= THIS_MODULE
,
439 .release
= video_release
,
443 .ioctl
= video_ioctl_set
,
446 static const struct v4l2_ioctl_ops video_ioctl_ops
= {
447 .vidioc_querycap
= vidioc_querycap
,
448 .vidioc_enum_fmt_vid_cap
= vidioc_enum_fmt_vid_cap
,
449 .vidioc_g_fmt_vid_cap
= vidioc_g_fmt_vid_cap
,
450 .vidioc_try_fmt_vid_cap
= vidioc_try_fmt_vid_cap
,
451 .vidioc_s_fmt_vid_cap
= vidioc_s_fmt_vid_cap
,
452 .vidioc_reqbufs
= vidioc_reqbufs
,
453 .vidioc_querybuf
= vidioc_querybuf
,
454 .vidioc_qbuf
= vidioc_qbuf
,
455 .vidioc_dqbuf
= vidioc_dqbuf
,
457 .vidioc_s_std
= vidioc_s_std
,
458 .vidioc_querystd
= vidioc_querystd
,
460 .vidioc_cropcap
= vidioc_cropcap
,
461 .vidioc_s_crop
= vidioc_s_crop
,
462 .vidioc_g_crop
= vidioc_g_crop
,
463 .vidioc_enum_input
= vidioc_enum_input
,
464 .vidioc_g_input
= vidioc_g_input
,
465 .vidioc_s_input
= vidioc_s_input
,
466 .vidioc_g_ctrl
= vidioc_g_ctrl
,
467 .vidioc_s_ctrl
= vidioc_s_ctrl
,
468 .vidioc_queryctrl
= vidioc_queryctrl
,
469 .vidioc_streamon
= vidioc_streamon
,
470 .vidioc_streamoff
= vidioc_streamoff
,
471 .vidioc_log_status
= vidioc_log_status
,
472 .vidioc_g_priority
= vidioc_g_priority
,
473 .vidioc_s_priority
= vidioc_s_priority
,
474 #ifdef CONFIG_VIDEO_V4L1_COMPAT
475 .vidiocgmbuf
= vidiocgmbuf
,
478 .vidioc_g_tuner
= vidioc_g_tuner
,
479 .vidioc_s_tuner
= vidioc_s_tuner
,
480 .vidioc_g_frequency
= vidioc_g_frequency
,
481 .vidioc_s_frequency
= vidioc_s_frequency
,
483 #ifdef CONFIG_VIDEO_ADV_DEBUG
484 .vidioc_g_register
= vidioc_g_register
,
485 .vidioc_s_register
= vidioc_s_register
,
489 struct video_device cx25821_videoioctl_template
= {
490 .name
= "cx25821-videoioctl",
493 .ioctl_ops
= &video_ioctl_ops
,
494 .tvnorms
= CX25821_NORMS
,
495 .current_norm
= V4L2_STD_NTSC_M
,