2 * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com
3 * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net>
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.
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.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include <linux/kernel.h>
21 #include <linux/module.h>
22 #include <linux/kthread.h>
23 #include <linux/freezer.h>
25 #include <media/v4l2-ioctl.h>
26 #include <media/v4l2-common.h>
27 #include <media/videobuf-dma-sg.h>
30 #include "solo6010-tw28.h"
32 #define SOLO_HW_BPL 2048
33 #define SOLO_DISP_PIX_FIELD V4L2_FIELD_INTERLACED
35 /* Image size is two fields, SOLO_HW_BPL is one horizontal line */
36 #define solo_vlines(__solo) (__solo->video_vsize * 2)
37 #define solo_image_size(__solo) (solo_bytesperline(__solo) * \
39 #define solo_bytesperline(__solo) (__solo->video_hsize * 2)
41 #define MIN_VID_BUFFERS 4
43 /* Simple file handle */
44 struct solo_filehandle
{
45 struct solo6010_dev
*solo_dev
;
46 struct videobuf_queue vidq
;
47 struct task_struct
*kthread
;
50 struct list_head vidq_active
;
51 struct p2m_desc desc
[SOLO_NR_P2M_DESC
];
55 unsigned video_nr
= -1;
56 module_param(video_nr
, uint
, 0644);
57 MODULE_PARM_DESC(video_nr
, "videoX start number, -1 is autodetect (default)");
59 static void erase_on(struct solo6010_dev
*solo_dev
)
61 solo_reg_write(solo_dev
, SOLO_VO_DISP_ERASE
, SOLO_VO_DISP_ERASE_ON
);
62 solo_dev
->erasing
= 1;
63 solo_dev
->frame_blank
= 0;
66 static int erase_off(struct solo6010_dev
*solo_dev
)
68 if (!solo_dev
->erasing
)
71 /* First time around, assert erase off */
72 if (!solo_dev
->frame_blank
)
73 solo_reg_write(solo_dev
, SOLO_VO_DISP_ERASE
, 0);
74 /* Keep the erasing flag on for 8 frames minimum */
75 if (solo_dev
->frame_blank
++ >= 8)
76 solo_dev
->erasing
= 0;
81 void solo_video_in_isr(struct solo6010_dev
*solo_dev
)
83 solo_reg_write(solo_dev
, SOLO_IRQ_STAT
, SOLO_IRQ_VIDEO_IN
);
84 wake_up_interruptible(&solo_dev
->disp_thread_wait
);
87 static void solo_win_setup(struct solo6010_dev
*solo_dev
, u8 ch
,
88 int sx
, int sy
, int ex
, int ey
, int scale
)
90 if (ch
>= solo_dev
->nr_chans
)
93 /* Here, we just keep window/channel the same */
94 solo_reg_write(solo_dev
, SOLO_VI_WIN_CTRL0(ch
),
95 SOLO_VI_WIN_CHANNEL(ch
) |
98 SOLO_VI_WIN_SCALE(scale
));
100 solo_reg_write(solo_dev
, SOLO_VI_WIN_CTRL1(ch
),
105 static int solo_v4l2_ch_ext_4up(struct solo6010_dev
*solo_dev
, u8 idx
, int on
)
109 if (ch
>= solo_dev
->nr_chans
)
114 for (i
= ch
; i
< ch
+ 4; i
++)
115 solo_win_setup(solo_dev
, i
, solo_dev
->video_hsize
,
116 solo_vlines(solo_dev
),
117 solo_dev
->video_hsize
,
118 solo_vlines(solo_dev
), 0);
123 solo_win_setup(solo_dev
, ch
, 0, 0, solo_dev
->video_hsize
/ 2,
124 solo_vlines(solo_dev
) / 2, 3);
125 solo_win_setup(solo_dev
, ch
+ 1, solo_dev
->video_hsize
/ 2, 0,
126 solo_dev
->video_hsize
, solo_vlines(solo_dev
) / 2, 3);
128 solo_win_setup(solo_dev
, ch
+ 2, 0, solo_vlines(solo_dev
) / 2,
129 solo_dev
->video_hsize
/ 2, solo_vlines(solo_dev
), 3);
130 solo_win_setup(solo_dev
, ch
+ 3, solo_dev
->video_hsize
/ 2,
131 solo_vlines(solo_dev
) / 2, solo_dev
->video_hsize
,
132 solo_vlines(solo_dev
), 3);
137 static int solo_v4l2_ch_ext_16up(struct solo6010_dev
*solo_dev
, int on
)
139 int sy
, ysize
, hsize
, i
;
142 for (i
= 0; i
< 16; i
++)
143 solo_win_setup(solo_dev
, i
, solo_dev
->video_hsize
,
144 solo_vlines(solo_dev
),
145 solo_dev
->video_hsize
,
146 solo_vlines(solo_dev
), 0);
150 ysize
= solo_vlines(solo_dev
) / 4;
151 hsize
= solo_dev
->video_hsize
/ 4;
153 for (sy
= 0, i
= 0; i
< 4; i
++, sy
+= ysize
) {
154 solo_win_setup(solo_dev
, i
* 4, 0, sy
, hsize
,
156 solo_win_setup(solo_dev
, (i
* 4) + 1, hsize
, sy
,
157 hsize
* 2, sy
+ ysize
, 5);
158 solo_win_setup(solo_dev
, (i
* 4) + 2, hsize
* 2, sy
,
159 hsize
* 3, sy
+ ysize
, 5);
160 solo_win_setup(solo_dev
, (i
* 4) + 3, hsize
* 3, sy
,
161 solo_dev
->video_hsize
, sy
+ ysize
, 5);
167 static int solo_v4l2_ch(struct solo6010_dev
*solo_dev
, u8 ch
, int on
)
171 if (ch
< solo_dev
->nr_chans
) {
172 solo_win_setup(solo_dev
, ch
, on
? 0 : solo_dev
->video_hsize
,
173 on
? 0 : solo_vlines(solo_dev
),
174 solo_dev
->video_hsize
, solo_vlines(solo_dev
),
179 if (ch
>= solo_dev
->nr_chans
+ solo_dev
->nr_ext
)
182 ext_ch
= ch
- solo_dev
->nr_chans
;
186 return solo_v4l2_ch_ext_4up(solo_dev
, ext_ch
, on
);
188 /* Remaining case is 16up for 16-port */
189 return solo_v4l2_ch_ext_16up(solo_dev
, on
);
192 static int solo_v4l2_set_ch(struct solo6010_dev
*solo_dev
, u8 ch
)
194 if (ch
>= solo_dev
->nr_chans
+ solo_dev
->nr_ext
)
199 solo_v4l2_ch(solo_dev
, solo_dev
->cur_disp_ch
, 0);
200 solo_v4l2_ch(solo_dev
, ch
, 1);
202 solo_dev
->cur_disp_ch
= ch
;
207 static void disp_reset_desc(struct solo_filehandle
*fh
)
209 /* We use desc mode, which ignores desc 0 */
210 memset(fh
->desc
, 0, sizeof(*fh
->desc
));
214 static int disp_flush_descs(struct solo_filehandle
*fh
)
221 ret
= solo_p2m_dma_desc(fh
->solo_dev
, SOLO_P2M_DMA_ID_DISP
,
222 fh
->desc
, fh
->desc_idx
);
228 static int disp_push_desc(struct solo_filehandle
*fh
, dma_addr_t dma_addr
,
229 u32 ext_addr
, int size
, int repeat
, int ext_size
)
231 if (fh
->desc_idx
>= SOLO_NR_P2M_DESC
) {
232 int ret
= disp_flush_descs(fh
);
237 solo_p2m_push_desc(&fh
->desc
[fh
->desc_idx
], 0, dma_addr
, ext_addr
,
238 size
, repeat
, ext_size
);
244 static void solo_fillbuf(struct solo_filehandle
*fh
,
245 struct videobuf_buffer
*vb
)
247 struct solo6010_dev
*solo_dev
= fh
->solo_dev
;
248 struct videobuf_dmabuf
*vbuf
;
249 unsigned int fdma_addr
;
252 struct scatterlist
*sg
;
256 vbuf
= videobuf_to_dma(vb
);
260 if (erase_off(solo_dev
)) {
263 /* Just blit to the entire sg list, ignoring size */
264 for_each_sg(vbuf
->sglist
, sg
, vbuf
->sglen
, i
) {
265 void *p
= sg_virt(sg
);
266 size_t len
= sg_dma_len(sg
);
268 for (i
= 0; i
< len
; i
+= 2) {
270 ((u8
*)p
)[i
+ 1] = 0x00;
280 sg_dma
= sg_dma_address(sg
);
281 sg_size_left
= sg_dma_len(sg
);
283 fdma_addr
= SOLO_DISP_EXT_ADDR(solo_dev
) + (fh
->old_write
*
284 (SOLO_HW_BPL
* solo_vlines(solo_dev
)));
286 for (i
= 0; i
< solo_vlines(solo_dev
); i
++) {
287 int line_len
= solo_bytesperline(solo_dev
);
294 sg_dma
= sg_dma_address(sg
);
295 sg_size_left
= sg_dma_len(sg
);
298 /* No room for an entire line, so chunk it up */
299 if (sg_size_left
< line_len
) {
300 int this_addr
= fdma_addr
;
302 while (line_len
> 0) {
309 sg_dma
= sg_dma_address(sg
);
310 sg_size_left
= sg_dma_len(sg
);
313 this_write
= min(sg_size_left
, line_len
);
315 if (disp_push_desc(fh
, sg_dma
, this_addr
,
319 line_len
-= this_write
;
320 sg_size_left
-= this_write
;
321 sg_dma
+= this_write
;
322 this_addr
+= this_write
;
325 fdma_addr
+= SOLO_HW_BPL
;
329 /* Shove as many lines into a repeating descriptor as possible */
330 lines
= min(sg_size_left
/ line_len
,
331 solo_vlines(solo_dev
) - i
);
333 if (disp_push_desc(fh
, sg_dma
, fdma_addr
, line_len
,
334 lines
- 1, SOLO_HW_BPL
))
338 fdma_addr
+= SOLO_HW_BPL
* lines
;
339 sg_dma
+= lines
* line_len
;
340 sg_size_left
-= lines
* line_len
;
343 error
= disp_flush_descs(fh
);
347 vb
->state
= VIDEOBUF_ERROR
;
349 vb
->size
= solo_vlines(solo_dev
) * solo_bytesperline(solo_dev
);
350 vb
->state
= VIDEOBUF_DONE
;
352 do_gettimeofday(&vb
->ts
);
360 static void solo_thread_try(struct solo_filehandle
*fh
)
362 struct videobuf_buffer
*vb
;
363 unsigned int cur_write
;
366 spin_lock(&fh
->slock
);
368 if (list_empty(&fh
->vidq_active
))
371 vb
= list_first_entry(&fh
->vidq_active
, struct videobuf_buffer
,
374 if (!waitqueue_active(&vb
->done
))
377 cur_write
= SOLO_VI_STATUS0_PAGE(solo_reg_read(fh
->solo_dev
,
379 if (cur_write
== fh
->old_write
)
382 fh
->old_write
= cur_write
;
383 list_del(&vb
->queue
);
385 spin_unlock(&fh
->slock
);
387 solo_fillbuf(fh
, vb
);
390 assert_spin_locked(&fh
->slock
);
391 spin_unlock(&fh
->slock
);
394 static int solo_thread(void *data
)
396 struct solo_filehandle
*fh
= data
;
397 struct solo6010_dev
*solo_dev
= fh
->solo_dev
;
398 DECLARE_WAITQUEUE(wait
, current
);
401 add_wait_queue(&solo_dev
->disp_thread_wait
, &wait
);
404 long timeout
= schedule_timeout_interruptible(HZ
);
405 if (timeout
== -ERESTARTSYS
|| kthread_should_stop())
411 remove_wait_queue(&solo_dev
->disp_thread_wait
, &wait
);
416 static int solo_start_thread(struct solo_filehandle
*fh
)
418 fh
->kthread
= kthread_run(solo_thread
, fh
, SOLO6010_NAME
"_disp");
420 if (IS_ERR(fh
->kthread
))
421 return PTR_ERR(fh
->kthread
);
426 static void solo_stop_thread(struct solo_filehandle
*fh
)
429 kthread_stop(fh
->kthread
);
434 static int solo_buf_setup(struct videobuf_queue
*vq
, unsigned int *count
,
437 struct solo_filehandle
*fh
= vq
->priv_data
;
438 struct solo6010_dev
*solo_dev
= fh
->solo_dev
;
440 *size
= solo_image_size(solo_dev
);
442 if (*count
< MIN_VID_BUFFERS
)
443 *count
= MIN_VID_BUFFERS
;
448 static int solo_buf_prepare(struct videobuf_queue
*vq
,
449 struct videobuf_buffer
*vb
, enum v4l2_field field
)
451 struct solo_filehandle
*fh
= vq
->priv_data
;
452 struct solo6010_dev
*solo_dev
= fh
->solo_dev
;
454 vb
->size
= solo_image_size(solo_dev
);
455 if (vb
->baddr
!= 0 && vb
->bsize
< vb
->size
)
458 /* XXX: These properties only change when queue is idle */
459 vb
->width
= solo_dev
->video_hsize
;
460 vb
->height
= solo_vlines(solo_dev
);
461 vb
->bytesperline
= solo_bytesperline(solo_dev
);
464 if (vb
->state
== VIDEOBUF_NEEDS_INIT
) {
465 int rc
= videobuf_iolock(vq
, vb
, NULL
);
467 struct videobuf_dmabuf
*dma
= videobuf_to_dma(vb
);
468 videobuf_dma_unmap(vq
->dev
, dma
);
469 videobuf_dma_free(dma
);
470 vb
->state
= VIDEOBUF_NEEDS_INIT
;
474 vb
->state
= VIDEOBUF_PREPARED
;
479 static void solo_buf_queue(struct videobuf_queue
*vq
,
480 struct videobuf_buffer
*vb
)
482 struct solo_filehandle
*fh
= vq
->priv_data
;
483 struct solo6010_dev
*solo_dev
= fh
->solo_dev
;
485 vb
->state
= VIDEOBUF_QUEUED
;
486 list_add_tail(&vb
->queue
, &fh
->vidq_active
);
487 wake_up_interruptible(&solo_dev
->disp_thread_wait
);
490 static void solo_buf_release(struct videobuf_queue
*vq
,
491 struct videobuf_buffer
*vb
)
493 struct videobuf_dmabuf
*dma
= videobuf_to_dma(vb
);
495 videobuf_dma_unmap(vq
->dev
, dma
);
496 videobuf_dma_free(dma
);
497 vb
->state
= VIDEOBUF_NEEDS_INIT
;
500 static struct videobuf_queue_ops solo_video_qops
= {
501 .buf_setup
= solo_buf_setup
,
502 .buf_prepare
= solo_buf_prepare
,
503 .buf_queue
= solo_buf_queue
,
504 .buf_release
= solo_buf_release
,
507 static unsigned int solo_v4l2_poll(struct file
*file
,
508 struct poll_table_struct
*wait
)
510 struct solo_filehandle
*fh
= file
->private_data
;
512 return videobuf_poll_stream(file
, &fh
->vidq
, wait
);
515 static int solo_v4l2_mmap(struct file
*file
, struct vm_area_struct
*vma
)
517 struct solo_filehandle
*fh
= file
->private_data
;
519 return videobuf_mmap_mapper(&fh
->vidq
, vma
);
522 static int solo_v4l2_open(struct file
*file
)
524 struct solo6010_dev
*solo_dev
= video_drvdata(file
);
525 struct solo_filehandle
*fh
;
528 fh
= kzalloc(sizeof(*fh
), GFP_KERNEL
);
532 spin_lock_init(&fh
->slock
);
533 INIT_LIST_HEAD(&fh
->vidq_active
);
534 fh
->solo_dev
= solo_dev
;
535 file
->private_data
= fh
;
537 ret
= solo_start_thread(fh
);
543 videobuf_queue_sg_init(&fh
->vidq
, &solo_video_qops
,
544 &solo_dev
->pdev
->dev
, &fh
->slock
,
545 V4L2_BUF_TYPE_VIDEO_CAPTURE
,
547 sizeof(struct videobuf_buffer
), fh
, NULL
);
552 static ssize_t
solo_v4l2_read(struct file
*file
, char __user
*data
,
553 size_t count
, loff_t
*ppos
)
555 struct solo_filehandle
*fh
= file
->private_data
;
557 return videobuf_read_stream(&fh
->vidq
, data
, count
, ppos
, 0,
558 file
->f_flags
& O_NONBLOCK
);
561 static int solo_v4l2_release(struct file
*file
)
563 struct solo_filehandle
*fh
= file
->private_data
;
565 videobuf_stop(&fh
->vidq
);
566 videobuf_mmap_free(&fh
->vidq
);
567 solo_stop_thread(fh
);
573 static int solo_querycap(struct file
*file
, void *priv
,
574 struct v4l2_capability
*cap
)
576 struct solo_filehandle
*fh
= priv
;
577 struct solo6010_dev
*solo_dev
= fh
->solo_dev
;
579 strcpy(cap
->driver
, SOLO6010_NAME
);
580 strcpy(cap
->card
, "Softlogic 6010");
581 snprintf(cap
->bus_info
, sizeof(cap
->bus_info
), "PCI %s",
582 pci_name(solo_dev
->pdev
));
583 cap
->version
= SOLO6010_VER_NUM
;
584 cap
->capabilities
= V4L2_CAP_VIDEO_CAPTURE
|
590 static int solo_enum_ext_input(struct solo6010_dev
*solo_dev
,
591 struct v4l2_input
*input
)
593 static const char *dispnames_1
[] = { "4UP" };
594 static const char *dispnames_2
[] = { "4UP-1", "4UP-2" };
595 static const char *dispnames_5
[] = {
596 "4UP-1", "4UP-2", "4UP-3", "4UP-4", "16UP"
598 const char **dispnames
;
600 if (input
->index
>= (solo_dev
->nr_chans
+ solo_dev
->nr_ext
))
603 if (solo_dev
->nr_ext
== 5)
604 dispnames
= dispnames_5
;
605 else if (solo_dev
->nr_ext
== 2)
606 dispnames
= dispnames_2
;
608 dispnames
= dispnames_1
;
610 snprintf(input
->name
, sizeof(input
->name
), "Multi %s",
611 dispnames
[input
->index
- solo_dev
->nr_chans
]);
616 static int solo_enum_input(struct file
*file
, void *priv
,
617 struct v4l2_input
*input
)
619 struct solo_filehandle
*fh
= priv
;
620 struct solo6010_dev
*solo_dev
= fh
->solo_dev
;
622 if (input
->index
>= solo_dev
->nr_chans
) {
623 int ret
= solo_enum_ext_input(solo_dev
, input
);
627 snprintf(input
->name
, sizeof(input
->name
), "Camera %d",
630 /* We can only check this for normal inputs */
631 if (!tw28_get_video_status(solo_dev
, input
->index
))
632 input
->status
= V4L2_IN_ST_NO_SIGNAL
;
635 input
->type
= V4L2_INPUT_TYPE_CAMERA
;
637 if (solo_dev
->video_type
== SOLO_VO_FMT_TYPE_NTSC
)
638 input
->std
= V4L2_STD_NTSC_M
;
640 input
->std
= V4L2_STD_PAL_B
;
645 static int solo_set_input(struct file
*file
, void *priv
, unsigned int index
)
647 struct solo_filehandle
*fh
= priv
;
649 return solo_v4l2_set_ch(fh
->solo_dev
, index
);
652 static int solo_get_input(struct file
*file
, void *priv
, unsigned int *index
)
654 struct solo_filehandle
*fh
= priv
;
656 *index
= fh
->solo_dev
->cur_disp_ch
;
661 static int solo_enum_fmt_cap(struct file
*file
, void *priv
,
662 struct v4l2_fmtdesc
*f
)
667 f
->pixelformat
= V4L2_PIX_FMT_UYVY
;
668 strlcpy(f
->description
, "UYUV 4:2:2 Packed", sizeof(f
->description
));
673 static int solo_try_fmt_cap(struct file
*file
, void *priv
,
674 struct v4l2_format
*f
)
676 struct solo_filehandle
*fh
= priv
;
677 struct solo6010_dev
*solo_dev
= fh
->solo_dev
;
678 struct v4l2_pix_format
*pix
= &f
->fmt
.pix
;
679 int image_size
= solo_image_size(solo_dev
);
681 /* Check supported sizes */
682 if (pix
->width
!= solo_dev
->video_hsize
)
683 pix
->width
= solo_dev
->video_hsize
;
684 if (pix
->height
!= solo_vlines(solo_dev
))
685 pix
->height
= solo_vlines(solo_dev
);
686 if (pix
->sizeimage
!= image_size
)
687 pix
->sizeimage
= image_size
;
690 if (pix
->field
== V4L2_FIELD_ANY
)
691 pix
->field
= SOLO_DISP_PIX_FIELD
;
693 if (pix
->pixelformat
!= V4L2_PIX_FMT_UYVY
||
694 pix
->field
!= SOLO_DISP_PIX_FIELD
||
695 pix
->colorspace
!= V4L2_COLORSPACE_SMPTE170M
)
701 static int solo_set_fmt_cap(struct file
*file
, void *priv
,
702 struct v4l2_format
*f
)
704 struct solo_filehandle
*fh
= priv
;
706 if (videobuf_queue_is_busy(&fh
->vidq
))
709 /* For right now, if it doesn't match our running config,
711 return solo_try_fmt_cap(file
, priv
, f
);
714 static int solo_get_fmt_cap(struct file
*file
, void *priv
,
715 struct v4l2_format
*f
)
717 struct solo_filehandle
*fh
= priv
;
718 struct solo6010_dev
*solo_dev
= fh
->solo_dev
;
719 struct v4l2_pix_format
*pix
= &f
->fmt
.pix
;
721 pix
->width
= solo_dev
->video_hsize
;
722 pix
->height
= solo_vlines(solo_dev
);
723 pix
->pixelformat
= V4L2_PIX_FMT_UYVY
;
724 pix
->field
= SOLO_DISP_PIX_FIELD
;
725 pix
->sizeimage
= solo_image_size(solo_dev
);
726 pix
->colorspace
= V4L2_COLORSPACE_SMPTE170M
;
727 pix
->bytesperline
= solo_bytesperline(solo_dev
);
732 static int solo_reqbufs(struct file
*file
, void *priv
,
733 struct v4l2_requestbuffers
*req
)
735 struct solo_filehandle
*fh
= priv
;
737 return videobuf_reqbufs(&fh
->vidq
, req
);
740 static int solo_querybuf(struct file
*file
, void *priv
, struct v4l2_buffer
*buf
)
742 struct solo_filehandle
*fh
= priv
;
744 return videobuf_querybuf(&fh
->vidq
, buf
);
747 static int solo_qbuf(struct file
*file
, void *priv
, struct v4l2_buffer
*buf
)
749 struct solo_filehandle
*fh
= priv
;
751 return videobuf_qbuf(&fh
->vidq
, buf
);
754 static int solo_dqbuf(struct file
*file
, void *priv
, struct v4l2_buffer
*buf
)
756 struct solo_filehandle
*fh
= priv
;
758 return videobuf_dqbuf(&fh
->vidq
, buf
, file
->f_flags
& O_NONBLOCK
);
761 static int solo_streamon(struct file
*file
, void *priv
, enum v4l2_buf_type i
)
763 struct solo_filehandle
*fh
= priv
;
765 if (i
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
768 return videobuf_streamon(&fh
->vidq
);
771 static int solo_streamoff(struct file
*file
, void *priv
, enum v4l2_buf_type i
)
773 struct solo_filehandle
*fh
= priv
;
775 if (i
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
778 return videobuf_streamoff(&fh
->vidq
);
781 static int solo_s_std(struct file
*file
, void *priv
, v4l2_std_id
*i
)
786 static const u32 solo_motion_ctrls
[] = {
787 V4L2_CID_MOTION_TRACE
,
791 static const u32
*solo_ctrl_classes
[] = {
796 static int solo_disp_queryctrl(struct file
*file
, void *priv
,
797 struct v4l2_queryctrl
*qc
)
799 qc
->id
= v4l2_ctrl_next(solo_ctrl_classes
, qc
->id
);
805 case V4L2_CID_MOTION_TRACE
:
806 qc
->type
= V4L2_CTRL_TYPE_BOOLEAN
;
808 qc
->maximum
= qc
->step
= 1;
809 qc
->default_value
= 0;
810 strlcpy(qc
->name
, "Motion Detection Trace", sizeof(qc
->name
));
813 case V4L2_CID_MOTION_TRACE
:
814 return v4l2_ctrl_query_fill(qc
, 0, 1, 1, 0);
820 static int solo_disp_g_ctrl(struct file
*file
, void *priv
,
821 struct v4l2_control
*ctrl
)
823 struct solo_filehandle
*fh
= priv
;
824 struct solo6010_dev
*solo_dev
= fh
->solo_dev
;
827 case V4L2_CID_MOTION_TRACE
:
828 ctrl
->value
= solo_reg_read(solo_dev
, SOLO_VI_MOTION_BAR
)
835 static int solo_disp_s_ctrl(struct file
*file
, void *priv
,
836 struct v4l2_control
*ctrl
)
838 struct solo_filehandle
*fh
= priv
;
839 struct solo6010_dev
*solo_dev
= fh
->solo_dev
;
842 case V4L2_CID_MOTION_TRACE
:
844 solo_reg_write(solo_dev
, SOLO_VI_MOTION_BORDER
,
845 SOLO_VI_MOTION_Y_ADD
|
846 SOLO_VI_MOTION_Y_VALUE(0x20) |
847 SOLO_VI_MOTION_CB_VALUE(0x10) |
848 SOLO_VI_MOTION_CR_VALUE(0x10));
849 solo_reg_write(solo_dev
, SOLO_VI_MOTION_BAR
,
850 SOLO_VI_MOTION_CR_ADD
|
851 SOLO_VI_MOTION_Y_VALUE(0x10) |
852 SOLO_VI_MOTION_CB_VALUE(0x80) |
853 SOLO_VI_MOTION_CR_VALUE(0x10));
855 solo_reg_write(solo_dev
, SOLO_VI_MOTION_BORDER
, 0);
856 solo_reg_write(solo_dev
, SOLO_VI_MOTION_BAR
, 0);
863 static const struct v4l2_file_operations solo_v4l2_fops
= {
864 .owner
= THIS_MODULE
,
865 .open
= solo_v4l2_open
,
866 .release
= solo_v4l2_release
,
867 .read
= solo_v4l2_read
,
868 .poll
= solo_v4l2_poll
,
869 .mmap
= solo_v4l2_mmap
,
870 .ioctl
= video_ioctl2
,
873 static const struct v4l2_ioctl_ops solo_v4l2_ioctl_ops
= {
874 .vidioc_querycap
= solo_querycap
,
875 .vidioc_s_std
= solo_s_std
,
876 /* Input callbacks */
877 .vidioc_enum_input
= solo_enum_input
,
878 .vidioc_s_input
= solo_set_input
,
879 .vidioc_g_input
= solo_get_input
,
880 /* Video capture format callbacks */
881 .vidioc_enum_fmt_vid_cap
= solo_enum_fmt_cap
,
882 .vidioc_try_fmt_vid_cap
= solo_try_fmt_cap
,
883 .vidioc_s_fmt_vid_cap
= solo_set_fmt_cap
,
884 .vidioc_g_fmt_vid_cap
= solo_get_fmt_cap
,
886 .vidioc_reqbufs
= solo_reqbufs
,
887 .vidioc_querybuf
= solo_querybuf
,
888 .vidioc_qbuf
= solo_qbuf
,
889 .vidioc_dqbuf
= solo_dqbuf
,
890 .vidioc_streamon
= solo_streamon
,
891 .vidioc_streamoff
= solo_streamoff
,
893 .vidioc_queryctrl
= solo_disp_queryctrl
,
894 .vidioc_g_ctrl
= solo_disp_g_ctrl
,
895 .vidioc_s_ctrl
= solo_disp_s_ctrl
,
898 static struct video_device solo_v4l2_template
= {
899 .name
= SOLO6010_NAME
,
900 .fops
= &solo_v4l2_fops
,
901 .ioctl_ops
= &solo_v4l2_ioctl_ops
,
903 .release
= video_device_release
,
905 .tvnorms
= V4L2_STD_NTSC_M
| V4L2_STD_PAL_B
,
906 .current_norm
= V4L2_STD_NTSC_M
,
909 int solo_v4l2_init(struct solo6010_dev
*solo_dev
)
914 init_waitqueue_head(&solo_dev
->disp_thread_wait
);
916 solo_dev
->vfd
= video_device_alloc();
920 *solo_dev
->vfd
= solo_v4l2_template
;
921 solo_dev
->vfd
->parent
= &solo_dev
->pdev
->dev
;
923 ret
= video_register_device(solo_dev
->vfd
, VFL_TYPE_GRABBER
, video_nr
);
925 video_device_release(solo_dev
->vfd
);
926 solo_dev
->vfd
= NULL
;
930 video_set_drvdata(solo_dev
->vfd
, solo_dev
);
932 snprintf(solo_dev
->vfd
->name
, sizeof(solo_dev
->vfd
->name
), "%s (%i)",
933 SOLO6010_NAME
, solo_dev
->vfd
->num
);
938 dev_info(&solo_dev
->pdev
->dev
, "Display as /dev/video%d with "
939 "%d inputs (%d extended)\n", solo_dev
->vfd
->num
,
940 solo_dev
->nr_chans
, solo_dev
->nr_ext
);
942 /* Cycle all the channels and clear */
943 for (i
= 0; i
< solo_dev
->nr_chans
; i
++) {
944 solo_v4l2_set_ch(solo_dev
, i
);
945 while (erase_off(solo_dev
))
949 /* Set the default display channel */
950 solo_v4l2_set_ch(solo_dev
, 0);
951 while (erase_off(solo_dev
))
954 solo6010_irq_on(solo_dev
, SOLO_IRQ_VIDEO_IN
);
959 void solo_v4l2_exit(struct solo6010_dev
*solo_dev
)
961 solo6010_irq_off(solo_dev
, SOLO_IRQ_VIDEO_IN
);
963 video_unregister_device(solo_dev
->vfd
);
964 solo_dev
->vfd
= NULL
;