2005-04-16 15:20:36 -07:00
/*
*
* ( c ) 2004 Gerd Knorr < kraxel @ bytesex . org > [ SuSE Labs ]
*
* 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 .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include <linux/init.h>
# include <linux/list.h>
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/delay.h>
2006-01-09 15:32:31 -02:00
# include <media/v4l2-common.h>
2013-12-14 08:28:28 -03:00
# include <media/v4l2-event.h>
# include "saa7134-reg.h"
# include "saa7134.h"
2005-04-16 15:20:36 -07:00
/* ------------------------------------------------------------------ */
MODULE_AUTHOR ( " Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] " ) ;
MODULE_LICENSE ( " GPL " ) ;
static unsigned int empress_nr [ ] = { [ 0 . . . ( SAA7134_MAXBOARDS - 1 ) ] = UNSET } ;
2005-12-12 00:37:28 -08:00
2005-04-16 15:20:36 -07:00
module_param_array ( empress_nr , int , NULL , 0444 ) ;
MODULE_PARM_DESC ( empress_nr , " ts device number " ) ;
2008-04-22 14:41:48 -03:00
static unsigned int debug ;
2005-04-16 15:20:36 -07:00
module_param ( debug , int , 0644 ) ;
MODULE_PARM_DESC ( debug , " enable debug messages " ) ;
# define dprintk(fmt, arg...) if (debug) \
printk ( KERN_DEBUG " %s/empress: " fmt , dev - > name , # # arg )
/* ------------------------------------------------------------------ */
2014-04-17 07:30:53 -03:00
static int start_streaming ( struct vb2_queue * vq , unsigned int count )
2005-04-16 15:20:36 -07:00
{
2014-04-17 07:30:53 -03:00
struct saa7134_dmaqueue * dmaq = vq - > drv_priv ;
struct saa7134_dev * dev = dmaq - > dev ;
2008-08-26 13:44:40 -03:00
u32 leading_null_bytes = 0 ;
2014-04-17 07:30:53 -03:00
int err ;
err = saa7134_ts_start_streaming ( vq , count ) ;
if ( err )
return err ;
2006-06-18 16:40:10 -03:00
2008-08-26 13:44:40 -03:00
/* If more cards start to need this, then this
should probably be added to the card definitions . */
switch ( dev - > board ) {
case SAA7134_BOARD_BEHOLD_M6 :
case SAA7134_BOARD_BEHOLD_M63 :
case SAA7134_BOARD_BEHOLD_M6_EXTRA :
leading_null_bytes = 1 ;
break ;
}
2009-01-17 12:17:14 -03:00
saa_call_all ( dev , core , init , leading_null_bytes ) ;
2014-04-17 07:30:53 -03:00
/* Unmute audio */
saa_writeb ( SAA7134_AUDIO_MUTE_CTRL ,
saa_readb ( SAA7134_AUDIO_MUTE_CTRL ) & ~ ( 1 < < 6 ) ) ;
2005-04-16 15:20:36 -07:00
dev - > empress_started = 1 ;
2005-11-08 21:37:43 -08:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
2014-04-17 07:30:53 -03:00
static void stop_streaming ( struct vb2_queue * vq )
2014-04-17 04:23:07 -03:00
{
2014-04-17 07:30:53 -03:00
struct saa7134_dmaqueue * dmaq = vq - > drv_priv ;
struct saa7134_dev * dev = dmaq - > dev ;
2014-04-17 04:23:07 -03:00
2014-04-17 07:30:53 -03:00
saa7134_ts_stop_streaming ( vq ) ;
2014-04-17 04:23:07 -03:00
saa_writeb ( SAA7134_SPECIAL_MODE , 0x00 ) ;
2014-04-17 07:30:53 -03:00
msleep ( 20 ) ;
2014-04-17 04:23:07 -03:00
saa_writeb ( SAA7134_SPECIAL_MODE , 0x01 ) ;
msleep ( 100 ) ;
2014-04-17 07:30:53 -03:00
/* Mute audio */
2007-06-20 05:37:27 -03:00
saa_writeb ( SAA7134_AUDIO_MUTE_CTRL ,
2014-04-17 07:30:53 -03:00
saa_readb ( SAA7134_AUDIO_MUTE_CTRL ) | ( 1 < < 6 ) ) ;
dev - > empress_started = 0 ;
2005-04-16 15:20:36 -07:00
}
2014-04-17 07:30:53 -03:00
static struct vb2_ops saa7134_empress_qops = {
. queue_setup = saa7134_ts_queue_setup ,
. buf_init = saa7134_ts_buffer_init ,
. buf_prepare = saa7134_ts_buffer_prepare ,
. buf_finish = saa7134_ts_buffer_finish ,
. buf_queue = saa7134_vb2_buffer_queue ,
. wait_prepare = vb2_ops_wait_prepare ,
. wait_finish = vb2_ops_wait_finish ,
. start_streaming = start_streaming ,
. stop_streaming = stop_streaming ,
} ;
2005-04-16 15:20:36 -07:00
2014-04-17 07:30:53 -03:00
/* ------------------------------------------------------------------ */
2005-04-16 15:20:36 -07:00
2008-05-28 12:16:41 -03:00
static int empress_enum_fmt_vid_cap ( struct file * file , void * priv ,
2007-12-11 12:56:23 -03:00
struct v4l2_fmtdesc * f )
{
if ( f - > index ! = 0 )
return - EINVAL ;
2005-04-16 15:20:36 -07:00
2007-12-11 12:56:23 -03:00
strlcpy ( f - > description , " MPEG TS " , sizeof ( f - > description ) ) ;
f - > pixelformat = V4L2_PIX_FMT_MPEG ;
2013-06-01 10:02:38 -03:00
f - > flags = V4L2_FMT_FLAG_COMPRESSED ;
2007-12-11 12:56:23 -03:00
return 0 ;
}
2005-04-16 15:20:36 -07:00
2008-05-28 12:16:41 -03:00
static int empress_g_fmt_vid_cap ( struct file * file , void * priv ,
2007-12-11 12:56:23 -03:00
struct v4l2_format * f )
{
2013-12-14 08:28:26 -03:00
struct saa7134_dev * dev = video_drvdata ( file ) ;
2010-05-09 09:41:41 -03:00
struct v4l2_mbus_framefmt mbus_fmt ;
2005-04-16 15:20:36 -07:00
2010-05-09 09:41:41 -03:00
saa_call_all ( dev , video , g_mbus_fmt , & mbus_fmt ) ;
2005-04-16 15:20:36 -07:00
2010-05-09 09:41:41 -03:00
v4l2_fill_pix_format ( & f - > fmt . pix , & mbus_fmt ) ;
2007-12-11 12:56:23 -03:00
f - > fmt . pix . pixelformat = V4L2_PIX_FMT_MPEG ;
f - > fmt . pix . sizeimage = TS_PACKET_SIZE * dev - > ts . nr_packets ;
2013-06-01 10:02:38 -03:00
f - > fmt . pix . bytesperline = 0 ;
2005-04-16 15:20:36 -07:00
2007-12-11 12:56:23 -03:00
return 0 ;
}
2005-04-16 15:20:36 -07:00
2008-05-28 12:16:41 -03:00
static int empress_s_fmt_vid_cap ( struct file * file , void * priv ,
2007-12-11 12:56:23 -03:00
struct v4l2_format * f )
{
2013-12-14 08:28:26 -03:00
struct saa7134_dev * dev = video_drvdata ( file ) ;
2010-05-09 09:41:41 -03:00
struct v4l2_mbus_framefmt mbus_fmt ;
2005-04-16 15:20:36 -07:00
2010-05-09 09:41:41 -03:00
v4l2_fill_mbus_format ( & mbus_fmt , & f - > fmt . pix , V4L2_MBUS_FMT_FIXED ) ;
saa_call_all ( dev , video , s_mbus_fmt , & mbus_fmt ) ;
v4l2_fill_pix_format ( & f - > fmt . pix , & mbus_fmt ) ;
2005-04-16 15:20:36 -07:00
2007-12-11 12:56:23 -03:00
f - > fmt . pix . pixelformat = V4L2_PIX_FMT_MPEG ;
f - > fmt . pix . sizeimage = TS_PACKET_SIZE * dev - > ts . nr_packets ;
2013-06-01 10:02:38 -03:00
f - > fmt . pix . bytesperline = 0 ;
2005-04-16 15:20:36 -07:00
2007-12-11 12:56:23 -03:00
return 0 ;
}
2009-05-28 01:58:57 -03:00
static int empress_try_fmt_vid_cap ( struct file * file , void * priv ,
struct v4l2_format * f )
{
2013-12-14 08:28:26 -03:00
struct saa7134_dev * dev = video_drvdata ( file ) ;
2013-06-01 10:02:38 -03:00
struct v4l2_mbus_framefmt mbus_fmt ;
v4l2_fill_mbus_format ( & mbus_fmt , & f - > fmt . pix , V4L2_MBUS_FMT_FIXED ) ;
saa_call_all ( dev , video , try_mbus_fmt , & mbus_fmt ) ;
v4l2_fill_pix_format ( & f - > fmt . pix , & mbus_fmt ) ;
2009-05-28 01:58:57 -03:00
f - > fmt . pix . pixelformat = V4L2_PIX_FMT_MPEG ;
f - > fmt . pix . sizeimage = TS_PACKET_SIZE * dev - > ts . nr_packets ;
2013-06-01 10:02:38 -03:00
f - > fmt . pix . bytesperline = 0 ;
2009-05-28 01:58:57 -03:00
return 0 ;
}
2007-12-11 12:56:23 -03:00
2008-12-30 06:58:20 -03:00
static const struct v4l2_file_operations ts_fops =
2005-04-16 15:20:36 -07:00
{
. owner = THIS_MODULE ,
2014-04-17 07:30:53 -03:00
. open = v4l2_fh_open ,
. release = vb2_fop_release ,
. read = vb2_fop_read ,
. poll = vb2_fop_poll ,
. mmap = vb2_fop_mmap ,
2014-06-16 04:32:37 -03:00
. unlocked_ioctl = video_ioctl2 ,
2005-04-16 15:20:36 -07:00
} ;
2008-07-21 02:57:38 -03:00
static const struct v4l2_ioctl_ops ts_ioctl_ops = {
2013-12-14 08:28:25 -03:00
. vidioc_querycap = saa7134_querycap ,
2008-05-28 12:16:41 -03:00
. vidioc_enum_fmt_vid_cap = empress_enum_fmt_vid_cap ,
2009-05-28 01:58:57 -03:00
. vidioc_try_fmt_vid_cap = empress_try_fmt_vid_cap ,
2008-05-28 12:16:41 -03:00
. vidioc_s_fmt_vid_cap = empress_s_fmt_vid_cap ,
. vidioc_g_fmt_vid_cap = empress_g_fmt_vid_cap ,
2014-04-17 07:30:53 -03:00
. vidioc_reqbufs = vb2_ioctl_reqbufs ,
. 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-12-14 08:28:25 -03:00
. vidioc_g_frequency = saa7134_g_frequency ,
. vidioc_s_frequency = saa7134_s_frequency ,
. vidioc_g_tuner = saa7134_g_tuner ,
. vidioc_s_tuner = saa7134_s_tuner ,
. vidioc_enum_input = saa7134_enum_input ,
. vidioc_g_input = saa7134_g_input ,
. vidioc_s_input = saa7134_s_input ,
. vidioc_s_std = saa7134_s_std ,
. vidioc_g_std = saa7134_g_std ,
2014-04-01 09:28:17 -03:00
. vidioc_querystd = saa7134_querystd ,
2013-12-14 08:28:28 -03:00
. vidioc_log_status = v4l2_ctrl_log_status ,
. vidioc_subscribe_event = v4l2_ctrl_subscribe_event ,
. vidioc_unsubscribe_event = v4l2_event_unsubscribe ,
2008-07-21 02:57:38 -03:00
} ;
/* ----------------------------------------------------------- */
static struct video_device saa7134_empress_template = {
. name = " saa7134-empress " ,
. fops = & ts_fops ,
. ioctl_ops = & ts_ioctl_ops ,
2007-12-11 12:56:23 -03:00
. tvnorms = SAA7134_NORMS ,
2005-04-16 15:20:36 -07:00
} ;
2006-11-22 14:57:56 +00:00
static void empress_signal_update ( struct work_struct * work )
2005-04-16 15:20:36 -07:00
{
2006-11-22 14:57:56 +00:00
struct saa7134_dev * dev =
container_of ( work , struct saa7134_dev , empress_workqueue ) ;
2005-04-16 15:20:36 -07:00
if ( dev - > nosignal ) {
dprintk ( " no video signal \n " ) ;
} else {
dprintk ( " video signal acquired \n " ) ;
}
}
static void empress_signal_change ( struct saa7134_dev * dev )
{
schedule_work ( & dev - > empress_workqueue ) ;
}
2013-12-14 08:28:24 -03:00
static bool empress_ctrl_filter ( const struct v4l2_ctrl * ctrl )
{
switch ( ctrl - > id ) {
case V4L2_CID_BRIGHTNESS :
case V4L2_CID_HUE :
case V4L2_CID_CONTRAST :
case V4L2_CID_SATURATION :
case V4L2_CID_AUDIO_MUTE :
case V4L2_CID_AUDIO_VOLUME :
case V4L2_CID_PRIVATE_INVERT :
case V4L2_CID_PRIVATE_AUTOMUTE :
return true ;
default :
return false ;
}
}
2005-04-16 15:20:36 -07:00
static int empress_init ( struct saa7134_dev * dev )
{
2013-12-14 08:28:24 -03:00
struct v4l2_ctrl_handler * hdl = & dev - > empress_ctrl_handler ;
2014-04-17 07:30:53 -03:00
struct vb2_queue * q ;
2005-04-16 15:20:36 -07:00
int err ;
2008-04-08 23:20:00 -03:00
dprintk ( " %s: %s \n " , dev - > name , __func__ ) ;
2005-04-16 15:20:36 -07:00
dev - > empress_dev = video_device_alloc ( ) ;
if ( NULL = = dev - > empress_dev )
return - ENOMEM ;
* ( dev - > empress_dev ) = saa7134_empress_template ;
2013-06-20 10:57:10 -03:00
dev - > empress_dev - > v4l2_dev = & dev - > v4l2_dev ;
2005-04-16 15:20:36 -07:00
dev - > empress_dev - > release = video_device_release ;
2014-04-17 07:30:53 -03:00
dev - > empress_dev - > lock = & dev - > lock ;
2005-04-16 15:20:36 -07:00
snprintf ( dev - > empress_dev - > name , sizeof ( dev - > empress_dev - > name ) ,
" %s empress (%s) " , dev - > name ,
saa7134_boards [ dev - > board ] . name ) ;
2013-12-14 08:28:24 -03:00
v4l2_ctrl_handler_init ( hdl , 21 ) ;
v4l2_ctrl_add_handler ( hdl , & dev - > ctrl_handler , empress_ctrl_filter ) ;
if ( dev - > empress_sd )
v4l2_ctrl_add_handler ( hdl , dev - > empress_sd - > ctrl_handler , NULL ) ;
if ( hdl - > error ) {
video_device_release ( dev - > empress_dev ) ;
return hdl - > error ;
}
dev - > empress_dev - > ctrl_handler = hdl ;
2005-04-16 15:20:36 -07:00
2006-11-22 14:57:56 +00:00
INIT_WORK ( & dev - > empress_workqueue , empress_signal_update ) ;
2005-04-16 15:20:36 -07:00
2014-04-17 07:30:53 -03:00
q = & dev - > empress_vbq ;
q - > type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
/*
* Do not add VB2_USERPTR : the saa7134 DMA engine cannot handle
* transfers that do not start at the beginning of a page . A USERPTR
* can start anywhere in a page , so USERPTR support is a no - go .
*/
q - > io_modes = VB2_MMAP | VB2_READ ;
q - > drv_priv = & dev - > ts_q ;
q - > ops = & saa7134_empress_qops ;
q - > gfp_flags = GFP_DMA32 ;
q - > mem_ops = & vb2_dma_sg_memops ;
q - > buf_struct_size = sizeof ( struct saa7134_buf ) ;
q - > timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC ;
q - > lock = & dev - > lock ;
err = vb2_queue_init ( q ) ;
if ( err )
return err ;
dev - > empress_dev - > queue = q ;
2009-12-10 11:44:04 -02:00
video_set_drvdata ( dev - > empress_dev , dev ) ;
2005-04-16 15:20:36 -07:00
err = video_register_device ( dev - > empress_dev , VFL_TYPE_GRABBER ,
empress_nr [ dev - > nr ] ) ;
if ( err < 0 ) {
printk ( KERN_INFO " %s: can't register video device \n " ,
dev - > name ) ;
video_device_release ( dev - > empress_dev ) ;
dev - > empress_dev = NULL ;
return err ;
}
2009-11-27 13:57:15 -03:00
printk ( KERN_INFO " %s: registered device %s [mpeg] \n " ,
dev - > name , video_device_node_name ( dev - > empress_dev ) ) ;
2005-04-16 15:20:36 -07:00
2006-11-22 14:57:56 +00:00
empress_signal_update ( & dev - > empress_workqueue ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
static int empress_fini ( struct saa7134_dev * dev )
{
2008-04-08 23:20:00 -03:00
dprintk ( " %s: %s \n " , dev - > name , __func__ ) ;
2005-04-16 15:20:36 -07:00
if ( NULL = = dev - > empress_dev )
return 0 ;
2012-08-20 14:51:24 -07:00
flush_work ( & dev - > empress_workqueue ) ;
2005-04-16 15:20:36 -07:00
video_unregister_device ( dev - > empress_dev ) ;
2014-04-17 07:30:53 -03:00
vb2_queue_release ( & dev - > empress_vbq ) ;
2013-12-14 08:28:24 -03:00
v4l2_ctrl_handler_free ( & dev - > empress_ctrl_handler ) ;
2005-04-16 15:20:36 -07:00
dev - > empress_dev = NULL ;
return 0 ;
}
static struct saa7134_mpeg_ops empress_ops = {
. type = SAA7134_MPEG_EMPRESS ,
. init = empress_init ,
. fini = empress_fini ,
. signal_change = empress_signal_change ,
} ;
static int __init empress_register ( void )
{
return saa7134_ts_register ( & empress_ops ) ;
}
static void __exit empress_unregister ( void )
{
saa7134_ts_unregister ( & empress_ops ) ;
}
module_init ( empress_register ) ;
module_exit ( empress_unregister ) ;