2009-09-15 18:33:54 +04:00
/*
* Driver for the Conexant CX25821 PCIe bridge
*
2009-09-13 18:25:45 +04:00
* Copyright ( C ) 2009 Conexant Systems Inc .
2009-09-15 18:33:54 +04:00
* Authors < shu . lin @ conexant . com > , < hiep . huynh @ conexant . com >
2014-12-12 16:27:58 +03:00
* Based on Steven Toth < stoth @ linuxtv . org > cx25821 driver
2010-07-04 21:15:38 +04:00
* Parts adapted / taken from Eduardo Moscoso Rubino
* Copyright ( C ) 2009 Eduardo Moscoso Rubino < moscoso @ TopoLogica . com >
*
2009-09-15 18:33:54 +04:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
*
* GNU General Public License for more details .
*/
2010-11-07 23:48:21 +03:00
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2009-09-15 18:33:54 +04:00
# include "cx25821-video.h"
MODULE_DESCRIPTION ( " v4l2 driver module for cx25821 based TV cards " ) ;
2010-07-04 21:15:38 +04:00
MODULE_AUTHOR ( " Hiep Huynh <hiep.huynh@conexant.com> " ) ;
2009-09-15 18:33:54 +04:00
MODULE_LICENSE ( " GPL " ) ;
2009-09-13 18:39:12 +04:00
static unsigned int video_nr [ ] = { [ 0 . . . ( CX25821_MAXBOARDS - 1 ) ] = UNSET } ;
2009-09-15 18:33:54 +04:00
module_param_array ( video_nr , int , NULL , 0444 ) ;
MODULE_PARM_DESC ( video_nr , " video device numbers " ) ;
2009-09-13 18:30:11 +04:00
static unsigned int video_debug = VIDEO_DEBUG ;
2009-09-15 18:33:54 +04:00
module_param ( video_debug , int , 0644 ) ;
MODULE_PARM_DESC ( video_debug , " enable debug messages [video] " ) ;
static unsigned int irq_debug ;
module_param ( irq_debug , int , 0644 ) ;
MODULE_PARM_DESC ( irq_debug , " enable debug messages [IRQ handler] " ) ;
# define FORMAT_FLAGS_PACKED 0x01
2013-04-13 14:41:29 +04:00
static const struct cx25821_fmt formats [ ] = {
2009-09-13 18:30:11 +04:00
{
2010-03-24 20:23:25 +03:00
. name = " 4:1:1, packed, Y41P " ,
. fourcc = V4L2_PIX_FMT_Y41P ,
. depth = 12 ,
. flags = FORMAT_FLAGS_PACKED ,
} , {
. name = " 4:2:2, packed, YUYV " ,
. fourcc = V4L2_PIX_FMT_YUYV ,
. depth = 16 ,
. flags = FORMAT_FLAGS_PACKED ,
} ,
2009-09-15 18:33:54 +04:00
} ;
2013-04-13 14:41:29 +04:00
static const struct cx25821_fmt * cx25821_format_by_fourcc ( unsigned int fourcc )
2009-09-15 18:33:54 +04:00
{
2009-09-13 18:30:11 +04:00
unsigned int i ;
2009-09-15 18:33:54 +04:00
2009-09-13 18:30:11 +04:00
for ( i = 0 ; i < ARRAY_SIZE ( formats ) ; i + + )
if ( formats [ i ] . fourcc = = fourcc )
return formats + i ;
return NULL ;
2009-09-15 18:33:54 +04:00
}
int cx25821_start_video_dma ( struct cx25821_dev * dev ,
2009-09-13 18:30:11 +04:00
struct cx25821_dmaqueue * q ,
struct cx25821_buffer * buf ,
2013-04-13 13:28:54 +04:00
const struct sram_channel * channel )
2009-09-15 18:33:54 +04:00
{
2009-09-13 18:30:11 +04:00
int tmp = 0 ;
2009-09-15 18:33:54 +04:00
2009-09-13 18:30:11 +04:00
/* setup fifo + format */
cx25821_sram_channel_setup ( dev , channel , buf - > bpl , buf - > risc . dma ) ;
2009-09-15 18:33:54 +04:00
2009-09-13 18:30:11 +04:00
/* reset counter */
cx_write ( channel - > gpcnt_ctl , 3 ) ;
2009-09-15 18:33:54 +04:00
2009-09-13 18:30:11 +04:00
/* enable irq */
cx_set ( PCI_INT_MSK , cx_read ( PCI_INT_MSK ) | ( 1 < < channel - > i ) ) ;
cx_set ( channel - > int_msk , 0x11 ) ;
2009-09-15 18:33:54 +04:00
2009-09-13 18:30:11 +04:00
/* start dma */
cx_write ( channel - > dma_ctl , 0x11 ) ; /* FIFO and RISC enable */
2009-09-15 18:33:54 +04:00
2009-09-13 18:30:11 +04:00
/* make sure upstream setting if any is reversed */
tmp = cx_read ( VID_CH_MODE_SEL ) ;
cx_write ( VID_CH_MODE_SEL , tmp & 0xFFFFFE00 ) ;
2009-09-15 18:33:54 +04:00
2009-09-13 18:30:11 +04:00
return 0 ;
2009-09-15 18:33:54 +04:00
}
int cx25821_video_irq ( struct cx25821_dev * dev , int chan_num , u32 status )
{
2009-09-13 18:30:11 +04:00
int handled = 0 ;
u32 mask ;
2013-04-13 13:28:54 +04:00
const struct sram_channel * channel = dev - > channels [ chan_num ] . sram_channels ;
2009-09-13 18:30:11 +04:00
mask = cx_read ( channel - > int_msk ) ;
if ( 0 = = ( status & mask ) )
return handled ;
cx_write ( channel - > int_stat , status ) ;
/* risc op code error */
if ( status & ( 1 < < 16 ) ) {
2010-11-07 23:48:21 +03:00
pr_warn ( " %s, %s: video risc op code error \n " ,
dev - > name , channel - > name ) ;
2009-09-13 18:30:11 +04:00
cx_clear ( channel - > dma_ctl , 0x11 ) ;
cx25821_sram_channel_dump ( dev , channel ) ;
}
2009-09-15 18:33:54 +04:00
2009-09-13 18:30:11 +04:00
/* risc1 y */
if ( status & FLD_VID_DST_RISC1 ) {
2014-12-12 16:27:58 +03:00
struct cx25821_dmaqueue * dmaq =
& dev - > channels [ channel - > i ] . dma_vidq ;
struct cx25821_buffer * buf ;
2009-09-15 18:33:54 +04:00
2009-09-13 18:30:11 +04:00
spin_lock ( & dev - > slock ) ;
2014-12-12 16:27:58 +03:00
if ( ! list_empty ( & dmaq - > active ) ) {
buf = list_entry ( dmaq - > active . next ,
struct cx25821_buffer , queue ) ;
2015-11-03 13:16:37 +03:00
buf - > vb . vb2_buf . timestamp = ktime_get_ns ( ) ;
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
buf - > vb . sequence = dmaq - > count + + ;
2014-12-12 16:27:58 +03:00
list_del ( & buf - > queue ) ;
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
vb2_buffer_done ( & buf - > vb . vb2_buf , VB2_BUF_STATE_DONE ) ;
2014-12-12 16:27:58 +03:00
}
2009-09-13 18:30:11 +04:00
spin_unlock ( & dev - > slock ) ;
handled + + ;
}
return handled ;
2009-09-15 18:33:54 +04:00
}
2015-10-28 05:50:37 +03:00
static int cx25821_queue_setup ( struct vb2_queue * q ,
2014-12-12 16:27:58 +03:00
unsigned int * num_buffers , unsigned int * num_planes ,
2016-04-15 15:15:05 +03:00
unsigned int sizes [ ] , struct device * alloc_devs [ ] )
2009-09-15 18:33:54 +04:00
{
2014-12-12 16:27:58 +03:00
struct cx25821_channel * chan = q - > drv_priv ;
2014-12-12 16:27:59 +03:00
unsigned size = ( chan - > fmt - > depth * chan - > width * chan - > height ) > > 3 ;
2015-10-28 05:50:37 +03:00
if ( * num_planes )
return sizes [ 0 ] < size ? - EINVAL : 0 ;
2009-09-15 18:33:54 +04:00
2014-12-12 16:27:58 +03:00
* num_planes = 1 ;
2015-10-28 05:50:37 +03:00
sizes [ 0 ] = size ;
2009-09-13 18:30:11 +04:00
return 0 ;
2009-09-15 18:33:54 +04:00
}
2014-12-12 16:27:58 +03:00
static int cx25821_buffer_prepare ( struct vb2_buffer * vb )
2009-09-15 18:33:54 +04:00
{
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
struct vb2_v4l2_buffer * vbuf = to_vb2_v4l2_buffer ( vb ) ;
2014-12-12 16:27:58 +03:00
struct cx25821_channel * chan = vb - > vb2_queue - > drv_priv ;
2013-04-13 17:00:52 +04:00
struct cx25821_dev * dev = chan - > dev ;
2009-09-13 18:30:11 +04:00
struct cx25821_buffer * buf =
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
container_of ( vbuf , struct cx25821_buffer , vb ) ;
2014-12-12 16:27:58 +03:00
struct sg_table * sgt = vb2_dma_sg_plane_desc ( vb , 0 ) ;
2012-04-20 13:26:19 +04:00
u32 line0_offset ;
2009-09-13 18:30:11 +04:00
int bpl_local = LINE_SIZE_D1 ;
2014-12-12 16:27:58 +03:00
int ret ;
2009-09-13 18:30:11 +04:00
2014-12-12 16:27:58 +03:00
if ( chan - > pixel_formats = = PIXEL_FRMT_411 )
buf - > bpl = ( chan - > fmt - > depth * chan - > width ) > > 3 ;
else
buf - > bpl = ( chan - > fmt - > depth > > 3 ) * chan - > width ;
2009-09-13 18:25:45 +04:00
2014-12-12 16:27:58 +03:00
if ( vb2_plane_size ( vb , 0 ) < chan - > height * buf - > bpl )
2009-09-13 18:30:11 +04:00
return - EINVAL ;
2014-12-12 16:27:58 +03:00
vb2_set_plane_payload ( vb , 0 , chan - > height * buf - > bpl ) ;
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
buf - > vb . field = chan - > field ;
2009-09-13 18:25:45 +04:00
2014-12-12 16:27:58 +03:00
if ( chan - > pixel_formats = = PIXEL_FRMT_411 ) {
bpl_local = buf - > bpl ;
} else {
bpl_local = buf - > bpl ; /* Default */
2009-09-13 18:30:11 +04:00
2014-12-12 16:27:58 +03:00
if ( chan - > use_cif_resolution ) {
if ( dev - > tvnorm & V4L2_STD_625_50 )
bpl_local = 352 < < 1 ;
else
bpl_local = chan - > cif_width < < 1 ;
2009-09-13 18:25:45 +04:00
}
}
2014-12-12 16:27:58 +03:00
switch ( chan - > field ) {
case V4L2_FIELD_TOP :
ret = cx25821_risc_buffer ( dev - > pci , & buf - > risc ,
sgt - > sgl , 0 , UNSET ,
buf - > bpl , 0 , chan - > height ) ;
break ;
case V4L2_FIELD_BOTTOM :
ret = cx25821_risc_buffer ( dev - > pci , & buf - > risc ,
sgt - > sgl , UNSET , 0 ,
buf - > bpl , 0 , chan - > height ) ;
break ;
case V4L2_FIELD_INTERLACED :
/* All other formats are top field first */
line0_offset = 0 ;
dprintk ( 1 , " top field first \n " ) ;
ret = cx25821_risc_buffer ( dev - > pci , & buf - > risc ,
sgt - > sgl , line0_offset ,
bpl_local , bpl_local , bpl_local ,
chan - > height > > 1 ) ;
break ;
case V4L2_FIELD_SEQ_TB :
ret = cx25821_risc_buffer ( dev - > pci , & buf - > risc ,
sgt - > sgl ,
0 , buf - > bpl * ( chan - > height > > 1 ) ,
buf - > bpl , 0 , chan - > height > > 1 ) ;
break ;
case V4L2_FIELD_SEQ_BT :
ret = cx25821_risc_buffer ( dev - > pci , & buf - > risc ,
sgt - > sgl ,
buf - > bpl * ( chan - > height > > 1 ) , 0 ,
buf - > bpl , 0 , chan - > height > > 1 ) ;
break ;
default :
WARN_ON ( 1 ) ;
ret = - EINVAL ;
break ;
2009-09-13 18:25:45 +04:00
}
2009-09-15 18:33:54 +04:00
2009-09-13 18:30:11 +04:00
dprintk ( 2 , " [%p/%d] buffer_prep - %dx%d %dbpp \" %s \" - dma=0x%08lx \n " ,
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
buf , buf - > vb . vb2_buf . index , chan - > width , chan - > height ,
2014-12-12 16:27:58 +03:00
chan - > fmt - > depth , chan - > fmt - > name ,
( unsigned long ) buf - > risc . dma ) ;
2009-09-15 18:33:54 +04:00
2014-12-12 16:27:58 +03:00
return ret ;
2009-09-15 18:33:54 +04:00
}
2014-12-12 16:27:58 +03:00
static void cx25821_buffer_finish ( struct vb2_buffer * vb )
2009-09-15 18:33:54 +04:00
{
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
struct vb2_v4l2_buffer * vbuf = to_vb2_v4l2_buffer ( vb ) ;
2009-09-13 18:30:11 +04:00
struct cx25821_buffer * buf =
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
container_of ( vbuf , struct cx25821_buffer , vb ) ;
2014-12-12 16:27:58 +03:00
struct cx25821_channel * chan = vb - > vb2_queue - > drv_priv ;
struct cx25821_dev * dev = chan - > dev ;
2009-09-15 18:33:54 +04:00
2014-12-12 16:27:58 +03:00
cx25821_free_buffer ( dev , buf ) ;
2009-09-15 18:33:54 +04:00
}
2014-12-12 16:27:58 +03:00
static void cx25821_buffer_queue ( struct vb2_buffer * vb )
2010-07-04 21:15:38 +04:00
{
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
struct vb2_v4l2_buffer * vbuf = to_vb2_v4l2_buffer ( vb ) ;
2011-09-16 10:14:43 +04:00
struct cx25821_buffer * buf =
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
container_of ( vbuf , struct cx25821_buffer , vb ) ;
2014-12-12 16:27:58 +03:00
struct cx25821_channel * chan = vb - > vb2_queue - > drv_priv ;
2013-04-13 17:00:52 +04:00
struct cx25821_dev * dev = chan - > dev ;
2014-12-12 16:27:58 +03:00
struct cx25821_buffer * prev ;
2013-04-13 17:00:52 +04:00
struct cx25821_dmaqueue * q = & dev - > channels [ chan - > id ] . dma_vidq ;
2011-09-16 10:14:44 +04:00
2014-12-12 16:27:58 +03:00
buf - > risc . cpu [ 1 ] = cpu_to_le32 ( buf - > risc . dma + 12 ) ;
buf - > risc . jmp [ 0 ] = cpu_to_le32 ( RISC_JUMP | RISC_CNT_INC ) ;
buf - > risc . jmp [ 1 ] = cpu_to_le32 ( buf - > risc . dma + 12 ) ;
buf - > risc . jmp [ 2 ] = cpu_to_le32 ( 0 ) ; /* bits 63-32 */
if ( list_empty ( & q - > active ) ) {
list_add_tail ( & buf - > queue , & q - > active ) ;
2011-09-16 10:14:44 +04:00
} else {
2014-12-12 16:27:58 +03:00
buf - > risc . cpu [ 0 ] | = cpu_to_le32 ( RISC_IRQ1 ) ;
2011-09-16 10:14:44 +04:00
prev = list_entry ( q - > active . prev , struct cx25821_buffer ,
2014-12-12 16:27:58 +03:00
queue ) ;
list_add_tail ( & buf - > queue , & q - > active ) ;
prev - > risc . jmp [ 1 ] = cpu_to_le32 ( buf - > risc . dma ) ;
2011-09-16 10:14:45 +04:00
}
2010-07-04 21:15:38 +04:00
}
2014-12-12 16:27:58 +03:00
static int cx25821_start_streaming ( struct vb2_queue * q , unsigned int count )
2010-07-04 21:15:38 +04:00
{
2014-12-12 16:27:58 +03:00
struct cx25821_channel * chan = q - > drv_priv ;
2013-04-14 18:57:18 +04:00
struct cx25821_dev * dev = chan - > dev ;
2014-12-12 16:27:58 +03:00
struct cx25821_dmaqueue * dmaq = & dev - > channels [ chan - > id ] . dma_vidq ;
struct cx25821_buffer * buf = list_entry ( dmaq - > active . next ,
struct cx25821_buffer , queue ) ;
2013-04-14 18:56:39 +04:00
2014-12-12 16:27:58 +03:00
dmaq - > count = 0 ;
cx25821_start_video_dma ( dev , dmaq , buf , chan - > sram_channels ) ;
return 0 ;
2010-07-04 21:15:38 +04:00
}
2014-12-12 16:27:58 +03:00
static void cx25821_stop_streaming ( struct vb2_queue * q )
2010-07-04 21:15:38 +04:00
{
2014-12-12 16:27:58 +03:00
struct cx25821_channel * chan = q - > drv_priv ;
2013-04-13 17:00:52 +04:00
struct cx25821_dev * dev = chan - > dev ;
2014-12-12 16:27:58 +03:00
struct cx25821_dmaqueue * dmaq = & dev - > channels [ chan - > id ] . dma_vidq ;
unsigned long flags ;
2010-07-04 21:15:38 +04:00
2014-12-12 16:27:58 +03:00
cx_write ( chan - > sram_channels - > dma_ctl , 0 ) ; /* FIFO and RISC disable */
spin_lock_irqsave ( & dev - > slock , flags ) ;
while ( ! list_empty ( & dmaq - > active ) ) {
struct cx25821_buffer * buf = list_entry ( dmaq - > active . next ,
struct cx25821_buffer , queue ) ;
2010-07-04 21:15:38 +04:00
2014-12-12 16:27:58 +03:00
list_del ( & buf - > queue ) ;
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
vb2_buffer_done ( & buf - > vb . vb2_buf , VB2_BUF_STATE_ERROR ) ;
2011-09-16 10:14:51 +04:00
}
2014-12-12 16:27:58 +03:00
spin_unlock_irqrestore ( & dev - > slock , flags ) ;
2010-07-04 21:15:38 +04:00
}
2016-09-09 02:59:18 +03:00
static const struct vb2_ops cx25821_video_qops = {
2014-12-12 16:27:58 +03:00
. queue_setup = cx25821_queue_setup ,
. buf_prepare = cx25821_buffer_prepare ,
. buf_finish = cx25821_buffer_finish ,
. buf_queue = cx25821_buffer_queue ,
. wait_prepare = vb2_ops_wait_prepare ,
. wait_finish = vb2_ops_wait_finish ,
. start_streaming = cx25821_start_streaming ,
. stop_streaming = cx25821_stop_streaming ,
} ;
2013-04-13 14:41:29 +04:00
/* VIDEO IOCTLS */
2013-04-14 14:13:02 +04:00
static int cx25821_vidioc_enum_fmt_vid_cap ( struct file * file , void * priv ,
struct v4l2_fmtdesc * f )
{
if ( unlikely ( f - > index > = ARRAY_SIZE ( formats ) ) )
return - EINVAL ;
strlcpy ( f - > description , formats [ f - > index ] . name , sizeof ( f - > description ) ) ;
f - > pixelformat = formats [ f - > index ] . fourcc ;
return 0 ;
}
2013-04-13 14:41:29 +04:00
static int cx25821_vidioc_g_fmt_vid_cap ( struct file * file , void * priv ,
struct v4l2_format * f )
{
2013-04-13 17:00:52 +04:00
struct cx25821_channel * chan = video_drvdata ( file ) ;
2013-04-13 14:41:29 +04:00
2013-04-13 17:00:52 +04:00
f - > fmt . pix . width = chan - > width ;
f - > fmt . pix . height = chan - > height ;
2014-12-12 16:27:58 +03:00
f - > fmt . pix . field = chan - > field ;
2013-04-13 17:00:52 +04:00
f - > fmt . pix . pixelformat = chan - > fmt - > fourcc ;
2013-04-13 20:06:00 +04:00
f - > fmt . pix . bytesperline = ( chan - > width * chan - > fmt - > depth ) > > 3 ;
f - > fmt . pix . sizeimage = chan - > height * f - > fmt . pix . bytesperline ;
f - > fmt . pix . colorspace = V4L2_COLORSPACE_SMPTE170M ;
2013-04-13 14:41:29 +04:00
return 0 ;
}
static int cx25821_vidioc_try_fmt_vid_cap ( struct file * file , void * priv ,
struct v4l2_format * f )
{
2013-04-13 20:06:00 +04:00
struct cx25821_channel * chan = video_drvdata ( file ) ;
struct cx25821_dev * dev = chan - > dev ;
2013-04-13 14:41:29 +04:00
const struct cx25821_fmt * fmt ;
2013-04-13 20:06:00 +04:00
enum v4l2_field field = f - > fmt . pix . field ;
2013-04-25 22:46:36 +04:00
unsigned int maxh ;
2013-04-13 20:06:00 +04:00
unsigned w ;
2013-04-13 14:41:29 +04:00
fmt = cx25821_format_by_fourcc ( f - > fmt . pix . pixelformat ) ;
if ( NULL = = fmt )
return - EINVAL ;
2013-04-13 20:06:00 +04:00
maxh = ( dev - > tvnorm & V4L2_STD_625_50 ) ? 576 : 480 ;
w = f - > fmt . pix . width ;
if ( field ! = V4L2_FIELD_BOTTOM )
field = V4L2_FIELD_TOP ;
if ( w < 352 ) {
w = 176 ;
f - > fmt . pix . height = maxh / 4 ;
} else if ( w < 720 ) {
w = 352 ;
f - > fmt . pix . height = maxh / 2 ;
} else {
w = 720 ;
f - > fmt . pix . height = maxh ;
field = V4L2_FIELD_INTERLACED ;
2013-04-13 14:41:29 +04:00
}
f - > fmt . pix . field = field ;
2013-04-13 20:06:00 +04:00
f - > fmt . pix . width = w ;
2013-04-13 14:41:29 +04:00
f - > fmt . pix . bytesperline = ( f - > fmt . pix . width * fmt - > depth ) > > 3 ;
f - > fmt . pix . sizeimage = f - > fmt . pix . height * f - > fmt . pix . bytesperline ;
2013-04-13 20:06:00 +04:00
f - > fmt . pix . colorspace = V4L2_COLORSPACE_SMPTE170M ;
2013-04-13 14:41:29 +04:00
return 0 ;
}
2010-07-04 21:15:38 +04:00
static int vidioc_s_fmt_vid_cap ( struct file * file , void * priv ,
2011-09-16 10:14:35 +04:00
struct v4l2_format * f )
2010-07-04 21:15:38 +04:00
{
2013-04-13 17:00:52 +04:00
struct cx25821_channel * chan = video_drvdata ( file ) ;
2013-04-14 18:57:18 +04:00
struct cx25821_dev * dev = chan - > dev ;
2011-09-16 10:14:54 +04:00
int pix_format = PIXEL_FRMT_422 ;
2013-04-13 20:34:34 +04:00
int err ;
2011-09-16 10:14:54 +04:00
2011-09-16 10:14:55 +04:00
err = cx25821_vidioc_try_fmt_vid_cap ( file , priv , f ) ;
2010-07-04 21:15:38 +04:00
2011-09-16 10:14:55 +04:00
if ( 0 ! = err )
return err ;
2010-07-04 21:15:38 +04:00
2013-04-13 17:00:52 +04:00
chan - > fmt = cx25821_format_by_fourcc ( f - > fmt . pix . pixelformat ) ;
2014-12-12 16:27:58 +03:00
chan - > field = f - > fmt . pix . field ;
2013-04-13 20:06:00 +04:00
chan - > width = f - > fmt . pix . width ;
chan - > height = f - > fmt . pix . height ;
2010-07-04 21:15:38 +04:00
2011-09-16 10:14:56 +04:00
if ( f - > fmt . pix . pixelformat = = V4L2_PIX_FMT_Y41P )
pix_format = PIXEL_FRMT_411 ;
else
2013-04-13 20:06:00 +04:00
pix_format = PIXEL_FRMT_422 ;
2010-07-04 21:15:38 +04:00
2011-09-16 10:14:56 +04:00
cx25821_set_pixel_format ( dev , SRAM_CH00 , pix_format ) ;
2010-07-04 21:15:38 +04:00
2011-09-16 10:14:56 +04:00
/* check if cif resolution */
2013-04-13 17:00:52 +04:00
if ( chan - > width = = 320 | | chan - > width = = 352 )
chan - > use_cif_resolution = 1 ;
2011-09-16 10:14:56 +04:00
else
2013-04-13 17:00:52 +04:00
chan - > use_cif_resolution = 0 ;
2010-07-04 21:15:38 +04:00
2013-04-13 17:00:52 +04:00
chan - > cif_width = chan - > width ;
medusa_set_resolution ( dev , chan - > width , SRAM_CH00 ) ;
2011-09-16 10:14:56 +04:00
return 0 ;
2010-07-04 21:15:38 +04:00
}
static int vidioc_log_status ( struct file * file , void * priv )
{
2013-04-14 18:57:18 +04:00
struct cx25821_channel * chan = video_drvdata ( file ) ;
struct cx25821_dev * dev = chan - > dev ;
const struct sram_channel * sram_ch = chan - > sram_channels ;
2011-09-16 10:14:57 +04:00
u32 tmp = 0 ;
2010-07-04 21:15:38 +04:00
2011-09-16 10:14:57 +04:00
tmp = cx_read ( sram_ch - > dma_ctl ) ;
2010-11-07 23:48:21 +03:00
pr_info ( " Video input 0 is %s \n " ,
( tmp & 0x11 ) ? " streaming " : " stopped " ) ;
2011-09-16 10:14:57 +04:00
return 0 ;
2010-07-04 21:15:38 +04:00
}
2009-09-15 18:33:54 +04:00
2013-04-13 14:41:29 +04:00
static int cx25821_vidioc_querycap ( struct file * file , void * priv ,
2011-09-16 10:14:35 +04:00
struct v4l2_capability * cap )
2009-09-15 18:33:54 +04:00
{
2013-04-14 18:57:18 +04:00
struct cx25821_channel * chan = video_drvdata ( file ) ;
struct cx25821_dev * dev = chan - > dev ;
2013-04-13 13:06:18 +04:00
const u32 cap_input = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_READWRITE | V4L2_CAP_STREAMING ;
2013-04-14 14:14:42 +04:00
const u32 cap_output = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_READWRITE ;
2009-09-13 18:30:11 +04:00
strcpy ( cap - > driver , " cx25821 " ) ;
strlcpy ( cap - > card , cx25821_boards [ dev - > board ] . name , sizeof ( cap - > card ) ) ;
sprintf ( cap - > bus_info , " PCIe:%s " , pci_name ( dev - > pci ) ) ;
2013-04-14 18:57:18 +04:00
if ( chan - > id > = VID_CHANNEL_NUM )
2013-04-13 13:06:18 +04:00
cap - > device_caps = cap_output ;
else
cap - > device_caps = cap_input ;
2013-04-14 14:14:42 +04:00
cap - > capabilities = cap_input | cap_output | V4L2_CAP_DEVICE_CAPS ;
2009-09-13 18:30:11 +04:00
return 0 ;
2009-09-15 18:33:54 +04:00
}
2013-04-13 14:41:29 +04:00
static int cx25821_vidioc_g_std ( struct file * file , void * priv , v4l2_std_id * tvnorms )
2013-04-13 12:50:18 +04:00
{
2013-04-14 18:57:18 +04:00
struct cx25821_channel * chan = video_drvdata ( file ) ;
2013-04-13 12:50:18 +04:00
2013-04-14 18:57:18 +04:00
* tvnorms = chan - > dev - > tvnorm ;
2013-04-13 12:50:18 +04:00
return 0 ;
}
2013-04-25 22:49:33 +04:00
static int cx25821_vidioc_s_std ( struct file * file , void * priv ,
v4l2_std_id tvnorms )
2009-09-15 18:33:54 +04:00
{
2013-04-14 18:57:18 +04:00
struct cx25821_channel * chan = video_drvdata ( file ) ;
struct cx25821_dev * dev = chan - > dev ;
2009-09-15 18:33:54 +04:00
2013-03-15 13:10:40 +04:00
if ( dev - > tvnorm = = tvnorms )
2009-09-13 18:30:11 +04:00
return 0 ;
2009-09-15 18:33:54 +04:00
2013-04-13 20:34:34 +04:00
dev - > tvnorm = tvnorms ;
2013-04-13 20:06:00 +04:00
chan - > width = 720 ;
chan - > height = ( dev - > tvnorm & V4L2_STD_625_50 ) ? 576 : 480 ;
2009-09-15 18:33:54 +04:00
2009-09-13 18:30:11 +04:00
medusa_set_videostandard ( dev ) ;
2009-09-15 18:33:54 +04:00
2009-09-13 18:30:11 +04:00
return 0 ;
2009-09-15 18:33:54 +04:00
}
2013-04-13 14:41:29 +04:00
static int cx25821_vidioc_enum_input ( struct file * file , void * priv ,
struct v4l2_input * i )
2009-09-15 18:33:54 +04:00
{
2013-04-13 20:34:34 +04:00
if ( i - > index )
2009-09-13 18:30:11 +04:00
return - EINVAL ;
2009-09-15 18:33:54 +04:00
2009-09-13 18:30:11 +04:00
i - > type = V4L2_INPUT_TYPE_CAMERA ;
i - > std = CX25821_NORMS ;
2013-04-13 20:34:34 +04:00
strcpy ( i - > name , " Composite " ) ;
2009-09-13 18:30:11 +04:00
return 0 ;
2009-09-15 18:33:54 +04:00
}
2013-04-13 14:41:29 +04:00
static int cx25821_vidioc_g_input ( struct file * file , void * priv , unsigned int * i )
2009-09-13 18:25:45 +04:00
{
2013-04-13 20:34:34 +04:00
* i = 0 ;
2009-09-13 18:30:11 +04:00
return 0 ;
2009-09-15 18:33:54 +04:00
}
2013-04-13 14:41:29 +04:00
static int cx25821_vidioc_s_input ( struct file * file , void * priv , unsigned int i )
2009-09-15 18:33:54 +04:00
{
2013-04-13 20:34:34 +04:00
return i ? - EINVAL : 0 ;
2009-09-15 18:33:54 +04:00
}
2013-04-13 15:38:14 +04:00
static int cx25821_s_ctrl ( struct v4l2_ctrl * ctrl )
2009-09-15 18:33:54 +04:00
{
2013-04-13 15:38:14 +04:00
struct cx25821_channel * chan =
container_of ( ctrl - > handler , struct cx25821_channel , hdl ) ;
struct cx25821_dev * dev = chan - > dev ;
2009-09-15 18:33:54 +04:00
2013-04-13 15:38:14 +04:00
switch ( ctrl - > id ) {
2009-09-13 18:30:11 +04:00
case V4L2_CID_BRIGHTNESS :
2013-04-13 15:38:14 +04:00
medusa_set_brightness ( dev , ctrl - > val , chan - > id ) ;
2009-09-15 18:33:54 +04:00
break ;
2009-09-13 18:30:11 +04:00
case V4L2_CID_HUE :
2013-04-13 15:38:14 +04:00
medusa_set_hue ( dev , ctrl - > val , chan - > id ) ;
2009-09-15 18:33:54 +04:00
break ;
2009-09-13 18:30:11 +04:00
case V4L2_CID_CONTRAST :
2013-04-13 15:38:14 +04:00
medusa_set_contrast ( dev , ctrl - > val , chan - > id ) ;
2009-09-15 18:33:54 +04:00
break ;
2009-09-13 18:30:11 +04:00
case V4L2_CID_SATURATION :
2013-04-13 15:38:14 +04:00
medusa_set_saturation ( dev , ctrl - > val , chan - > id ) ;
2009-09-15 18:33:54 +04:00
break ;
2009-09-13 18:30:11 +04:00
default :
2013-04-13 15:38:14 +04:00
return - EINVAL ;
2009-09-15 18:33:54 +04:00
}
2013-04-13 15:38:14 +04:00
return 0 ;
2009-09-15 18:33:54 +04:00
}
2013-04-14 19:07:13 +04:00
static int cx25821_vidioc_enum_output ( struct file * file , void * priv ,
struct v4l2_output * o )
2010-07-04 21:15:38 +04:00
{
2013-04-14 19:07:13 +04:00
if ( o - > index )
return - EINVAL ;
2010-07-04 21:15:38 +04:00
2013-04-14 19:07:13 +04:00
o - > type = V4L2_INPUT_TYPE_CAMERA ;
o - > std = CX25821_NORMS ;
strcpy ( o - > name , " Composite " ) ;
2011-09-16 10:15:03 +04:00
return 0 ;
2010-07-04 21:15:38 +04:00
}
2013-04-14 19:07:13 +04:00
static int cx25821_vidioc_g_output ( struct file * file , void * priv , unsigned int * o )
2010-07-04 21:15:38 +04:00
{
2013-04-14 19:07:13 +04:00
* o = 0 ;
2011-09-16 10:15:05 +04:00
return 0 ;
2010-07-04 21:15:38 +04:00
}
2013-04-14 19:07:13 +04:00
static int cx25821_vidioc_s_output ( struct file * file , void * priv , unsigned int o )
2010-07-04 21:15:38 +04:00
{
2013-04-14 19:07:13 +04:00
return o ? - EINVAL : 0 ;
2010-07-04 21:15:38 +04:00
}
2013-04-14 18:40:26 +04:00
static int cx25821_vidioc_try_fmt_vid_out ( struct file * file , void * priv ,
struct v4l2_format * f )
{
struct cx25821_channel * chan = video_drvdata ( file ) ;
struct cx25821_dev * dev = chan - > dev ;
const struct cx25821_fmt * fmt ;
fmt = cx25821_format_by_fourcc ( f - > fmt . pix . pixelformat ) ;
if ( NULL = = fmt )
return - EINVAL ;
f - > fmt . pix . width = 720 ;
f - > fmt . pix . height = ( dev - > tvnorm & V4L2_STD_625_50 ) ? 576 : 480 ;
f - > fmt . pix . field = V4L2_FIELD_INTERLACED ;
f - > fmt . pix . bytesperline = ( f - > fmt . pix . width * fmt - > depth ) > > 3 ;
f - > fmt . pix . sizeimage = f - > fmt . pix . height * f - > fmt . pix . bytesperline ;
f - > fmt . pix . colorspace = V4L2_COLORSPACE_SMPTE170M ;
return 0 ;
}
static int vidioc_s_fmt_vid_out ( struct file * file , void * priv ,
struct v4l2_format * f )
{
struct cx25821_channel * chan = video_drvdata ( file ) ;
int err ;
err = cx25821_vidioc_try_fmt_vid_out ( file , priv , f ) ;
if ( 0 ! = err )
return err ;
chan - > fmt = cx25821_format_by_fourcc ( f - > fmt . pix . pixelformat ) ;
2014-12-12 16:27:58 +03:00
chan - > field = f - > fmt . pix . field ;
2013-04-14 18:40:26 +04:00
chan - > width = f - > fmt . pix . width ;
chan - > height = f - > fmt . pix . height ;
if ( f - > fmt . pix . pixelformat = = V4L2_PIX_FMT_Y41P )
chan - > pixel_formats = PIXEL_FRMT_411 ;
else
chan - > pixel_formats = PIXEL_FRMT_422 ;
return 0 ;
}
2013-04-13 15:38:14 +04:00
static const struct v4l2_ctrl_ops cx25821_ctrl_ops = {
. s_ctrl = cx25821_s_ctrl ,
} ;
2010-07-04 21:15:38 +04:00
static const struct v4l2_file_operations video_fops = {
2011-09-16 10:15:11 +04:00
. owner = THIS_MODULE ,
2013-04-14 18:57:18 +04:00
. open = v4l2_fh_open ,
2014-12-12 16:27:58 +03:00
. release = vb2_fop_release ,
. read = vb2_fop_read ,
. poll = vb2_fop_poll ,
2013-04-14 19:07:13 +04:00
. unlocked_ioctl = video_ioctl2 ,
2014-12-12 16:27:58 +03:00
. mmap = vb2_fop_mmap ,
2010-07-04 21:15:38 +04:00
} ;
static const struct v4l2_ioctl_ops video_ioctl_ops = {
2011-09-16 10:15:11 +04:00
. vidioc_querycap = cx25821_vidioc_querycap ,
. vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap ,
. vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap ,
. vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap ,
. vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap ,
2014-12-12 16:27:58 +03:00
. vidioc_reqbufs = vb2_ioctl_reqbufs ,
. vidioc_prepare_buf = vb2_ioctl_prepare_buf ,
2014-12-12 16:27:59 +03:00
. vidioc_create_bufs = vb2_ioctl_create_bufs ,
2014-12-12 16:27:58 +03:00
. vidioc_querybuf = vb2_ioctl_querybuf ,
. vidioc_qbuf = vb2_ioctl_qbuf ,
. vidioc_dqbuf = vb2_ioctl_dqbuf ,
. vidioc_streamon = vb2_ioctl_streamon ,
. vidioc_streamoff = vb2_ioctl_streamoff ,
2013-04-13 12:50:18 +04:00
. vidioc_g_std = cx25821_vidioc_g_std ,
2011-09-16 10:15:11 +04:00
. vidioc_s_std = cx25821_vidioc_s_std ,
. vidioc_enum_input = cx25821_vidioc_enum_input ,
. vidioc_g_input = cx25821_vidioc_g_input ,
. vidioc_s_input = cx25821_vidioc_s_input ,
. vidioc_log_status = vidioc_log_status ,
2013-04-14 18:57:18 +04:00
. vidioc_subscribe_event = v4l2_ctrl_subscribe_event ,
. vidioc_unsubscribe_event = v4l2_event_unsubscribe ,
2010-07-04 21:15:38 +04:00
} ;
2013-04-13 12:30:48 +04:00
static const struct video_device cx25821_video_device = {
. name = " cx25821-video " ,
2011-09-16 10:15:12 +04:00
. fops = & video_fops ,
2013-04-13 15:18:00 +04:00
. release = video_device_release_empty ,
2013-04-13 12:30:48 +04:00
. minor = - 1 ,
2011-09-16 10:15:12 +04:00
. ioctl_ops = & video_ioctl_ops ,
. tvnorms = CX25821_NORMS ,
2010-07-04 21:15:38 +04:00
} ;
2013-04-13 12:30:48 +04:00
2013-04-14 19:07:13 +04:00
static const struct v4l2_file_operations video_out_fops = {
. owner = THIS_MODULE ,
. open = v4l2_fh_open ,
2014-12-12 16:27:58 +03:00
. release = vb2_fop_release ,
. write = vb2_fop_write ,
. poll = vb2_fop_poll ,
2013-04-14 19:07:13 +04:00
. unlocked_ioctl = video_ioctl2 ,
2014-12-12 16:27:58 +03:00
. mmap = vb2_fop_mmap ,
2013-04-14 19:07:13 +04:00
} ;
static const struct v4l2_ioctl_ops video_out_ioctl_ops = {
. vidioc_querycap = cx25821_vidioc_querycap ,
2013-04-14 18:40:26 +04:00
. vidioc_enum_fmt_vid_out = cx25821_vidioc_enum_fmt_vid_cap ,
. vidioc_g_fmt_vid_out = cx25821_vidioc_g_fmt_vid_cap ,
. vidioc_try_fmt_vid_out = cx25821_vidioc_try_fmt_vid_out ,
. vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out ,
2013-04-14 19:07:13 +04:00
. vidioc_g_std = cx25821_vidioc_g_std ,
. vidioc_s_std = cx25821_vidioc_s_std ,
. vidioc_enum_output = cx25821_vidioc_enum_output ,
. vidioc_g_output = cx25821_vidioc_g_output ,
. vidioc_s_output = cx25821_vidioc_s_output ,
. vidioc_log_status = vidioc_log_status ,
} ;
static const struct video_device cx25821_video_out_device = {
. name = " cx25821-video " ,
. fops = & video_out_fops ,
. release = video_device_release_empty ,
. minor = - 1 ,
. ioctl_ops = & video_out_ioctl_ops ,
. tvnorms = CX25821_NORMS ,
} ;
2013-04-13 12:30:48 +04:00
void cx25821_video_unregister ( struct cx25821_dev * dev , int chan_num )
{
cx_clear ( PCI_INT_MSK , 1 ) ;
2013-04-13 15:18:00 +04:00
if ( video_is_registered ( & dev - > channels [ chan_num ] . vdev ) ) {
video_unregister_device ( & dev - > channels [ chan_num ] . vdev ) ;
2013-04-13 15:38:14 +04:00
v4l2_ctrl_handler_free ( & dev - > channels [ chan_num ] . hdl ) ;
2013-04-13 12:30:48 +04:00
}
}
int cx25821_video_register ( struct cx25821_dev * dev )
{
int err ;
int i ;
2013-04-14 18:53:35 +04:00
/* initial device configuration */
2013-04-13 20:34:34 +04:00
dev - > tvnorm = V4L2_STD_NTSC_M ;
2013-04-14 18:53:35 +04:00
2013-04-13 12:30:48 +04:00
spin_lock_init ( & dev - > slock ) ;
2014-12-12 16:28:00 +03:00
for ( i = 0 ; i < MAX_VID_CAP_CHANNEL_NUM - 1 ; + + i ) {
2013-04-13 17:00:52 +04:00
struct cx25821_channel * chan = & dev - > channels [ i ] ;
struct video_device * vdev = & chan - > vdev ;
struct v4l2_ctrl_handler * hdl = & chan - > hdl ;
2014-12-12 16:27:58 +03:00
struct vb2_queue * q ;
2013-04-14 19:07:13 +04:00
bool is_output = i > SRAM_CH08 ;
2013-04-13 15:18:00 +04:00
2013-04-13 12:30:48 +04:00
if ( i = = SRAM_CH08 ) /* audio channel */
continue ;
2013-04-14 19:07:13 +04:00
if ( ! is_output ) {
v4l2_ctrl_handler_init ( hdl , 4 ) ;
v4l2_ctrl_new_std ( hdl , & cx25821_ctrl_ops ,
V4L2_CID_BRIGHTNESS , 0 , 10000 , 1 , 6200 ) ;
v4l2_ctrl_new_std ( hdl , & cx25821_ctrl_ops ,
V4L2_CID_CONTRAST , 0 , 10000 , 1 , 5000 ) ;
v4l2_ctrl_new_std ( hdl , & cx25821_ctrl_ops ,
V4L2_CID_SATURATION , 0 , 10000 , 1 , 5000 ) ;
v4l2_ctrl_new_std ( hdl , & cx25821_ctrl_ops ,
V4L2_CID_HUE , 0 , 10000 , 1 , 5000 ) ;
if ( hdl - > error ) {
err = hdl - > error ;
goto fail_unreg ;
}
err = v4l2_ctrl_handler_setup ( hdl ) ;
if ( err )
goto fail_unreg ;
2013-04-14 19:10:32 +04:00
} else {
chan - > out = & dev - > vid_out_data [ i - SRAM_CH09 ] ;
chan - > out - > chan = chan ;
2013-04-13 15:38:14 +04:00
}
2013-04-13 12:30:48 +04:00
2013-04-13 17:00:52 +04:00
chan - > sram_channels = & cx25821_sram_channels [ i ] ;
chan - > width = 720 ;
2014-12-12 16:27:58 +03:00
chan - > field = V4L2_FIELD_INTERLACED ;
2013-04-13 17:00:52 +04:00
if ( dev - > tvnorm & V4L2_STD_625_50 )
chan - > height = 576 ;
else
chan - > height = 480 ;
2013-04-13 12:30:48 +04:00
2013-04-13 17:00:52 +04:00
if ( chan - > pixel_formats = = PIXEL_FRMT_411 )
chan - > fmt = cx25821_format_by_fourcc ( V4L2_PIX_FMT_Y41P ) ;
else
chan - > fmt = cx25821_format_by_fourcc ( V4L2_PIX_FMT_YUYV ) ;
2013-04-13 12:30:48 +04:00
2013-04-13 17:00:52 +04:00
cx_write ( chan - > sram_channels - > int_stat , 0xffffffff ) ;
2013-04-13 12:30:48 +04:00
2013-04-13 17:00:52 +04:00
INIT_LIST_HEAD ( & chan - > dma_vidq . active ) ;
2014-12-12 16:27:58 +03:00
q = & chan - > vidq ;
q - > type = is_output ? V4L2_BUF_TYPE_VIDEO_OUTPUT :
V4L2_BUF_TYPE_VIDEO_CAPTURE ;
q - > io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF ;
q - > io_modes | = is_output ? VB2_WRITE : VB2_READ ;
q - > gfp_flags = GFP_DMA32 ;
q - > min_buffers_needed = 2 ;
q - > drv_priv = chan ;
q - > buf_struct_size = sizeof ( struct cx25821_buffer ) ;
q - > ops = & cx25821_video_qops ;
q - > mem_ops = & vb2_dma_sg_memops ;
q - > timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC ;
q - > lock = & dev - > lock ;
2016-02-15 17:37:15 +03:00
q - > dev = & dev - > pci - > dev ;
2013-04-13 17:00:52 +04:00
2014-12-12 16:27:58 +03:00
if ( ! is_output ) {
err = vb2_queue_init ( q ) ;
if ( err < 0 )
goto fail_unreg ;
}
2013-04-13 12:30:48 +04:00
/* register v4l devices */
2013-04-14 19:07:13 +04:00
* vdev = is_output ? cx25821_video_out_device : cx25821_video_device ;
2013-04-13 15:18:00 +04:00
vdev - > v4l2_dev = & dev - > v4l2_dev ;
2013-04-14 19:07:13 +04:00
if ( ! is_output )
vdev - > ctrl_handler = hdl ;
else
vdev - > vfl_dir = VFL_DIR_TX ;
2013-04-14 18:53:35 +04:00
vdev - > lock = & dev - > lock ;
2014-12-12 16:27:58 +03:00
vdev - > queue = q ;
2013-04-13 15:18:00 +04:00
snprintf ( vdev - > name , sizeof ( vdev - > name ) , " %s #%d " , dev - > name , i ) ;
2013-04-13 17:00:52 +04:00
video_set_drvdata ( vdev , chan ) ;
2013-04-13 12:30:48 +04:00
2013-04-13 15:18:00 +04:00
err = video_register_device ( vdev , VFL_TYPE_GRABBER ,
video_nr [ dev - > nr ] ) ;
2013-04-13 12:30:48 +04:00
if ( err < 0 )
goto fail_unreg ;
}
/* set PCI interrupt */
cx_set ( PCI_INT_MSK , 0xff ) ;
return 0 ;
fail_unreg :
2013-04-13 15:18:00 +04:00
while ( i > = 0 )
cx25821_video_unregister ( dev , i - - ) ;
2013-04-13 12:30:48 +04:00
return err ;
}