2009-09-27 05:50:44 +04:00
/*
* Driver for the Conexant CX23885 / 7 / 8 PCIe bridge
*
* Various common ioctl ( ) support functions
*
2010-05-24 01:53:35 +04:00
* Copyright ( c ) 2009 Andy Walls < awalls @ md . metrocast . net >
2009-09-27 05:50:44 +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 .
*
* 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 "cx23885.h"
# include <media/v4l2-chip-ident.h>
int cx23885_g_chip_ident ( struct file * file , void * fh ,
struct v4l2_dbg_chip_ident * chip )
{
struct cx23885_dev * dev = ( ( struct cx23885_fh * ) fh ) - > dev ;
int err = 0 ;
u8 rev ;
chip - > ident = V4L2_IDENT_NONE ;
chip - > revision = 0 ;
switch ( chip - > match . type ) {
case V4L2_CHIP_MATCH_HOST :
switch ( chip - > match . addr ) {
case 0 :
rev = cx_read ( RDR_CFG2 ) & 0xff ;
switch ( dev - > pci - > device ) {
case 0x8852 :
/* rev 0x04 could be '885 or '888. Pick '888. */
if ( rev = = 0x04 )
chip - > ident = V4L2_IDENT_CX23888 ;
else
chip - > ident = V4L2_IDENT_CX23885 ;
break ;
case 0x8880 :
if ( rev = = 0x0e | | rev = = 0x0f )
chip - > ident = V4L2_IDENT_CX23887 ;
else
chip - > ident = V4L2_IDENT_CX23888 ;
break ;
default :
chip - > ident = V4L2_IDENT_UNKNOWN ;
break ;
}
chip - > revision = ( dev - > pci - > device < < 16 ) | ( rev < < 8 ) |
( dev - > hwrevision & 0xff ) ;
break ;
case 1 :
if ( dev - > v4l_device ! = NULL ) {
chip - > ident = V4L2_IDENT_CX23417 ;
chip - > revision = 0 ;
}
break ;
2009-09-27 06:17:30 +04:00
case 2 :
/*
* The integrated IR controller on the CX23888 is
* host chip 2. It may not be used / initialized or sd_ir
* may be pointing at the cx25840 subdevice for the
* IR controller on the CX23885 . Thus we find it
* without using the dev - > sd_ir pointer .
*/
call_hw ( dev , CX23885_HW_888_IR , core , g_chip_ident ,
chip ) ;
break ;
2009-09-27 05:50:44 +04:00
default :
err = - EINVAL ; /* per V4L2 spec */
break ;
}
break ;
case V4L2_CHIP_MATCH_I2C_DRIVER :
/* If needed, returns V4L2_IDENT_AMBIGUOUS without extra work */
call_all ( dev , core , g_chip_ident , chip ) ;
break ;
case V4L2_CHIP_MATCH_I2C_ADDR :
/*
* We could return V4L2_IDENT_UNKNOWN , but we don ' t do the work
* to look if a chip is at the address with no driver . That ' s a
* dangerous thing to do with EEPROMs anyway .
*/
call_all ( dev , core , g_chip_ident , chip ) ;
break ;
default :
err = - EINVAL ;
break ;
}
return err ;
}
# ifdef CONFIG_VIDEO_ADV_DEBUG
static int cx23885_g_host_register ( struct cx23885_dev * dev ,
struct v4l2_dbg_register * reg )
{
if ( ( reg - > reg & 0x3 ) ! = 0 | | reg - > reg > = pci_resource_len ( dev - > pci , 0 ) )
return - EINVAL ;
reg - > size = 4 ;
reg - > val = cx_read ( reg - > reg ) ;
return 0 ;
}
static int cx23417_g_register ( struct cx23885_dev * dev ,
struct v4l2_dbg_register * reg )
{
u32 value ;
if ( dev - > v4l_device = = NULL )
return - EINVAL ;
if ( ( reg - > reg & 0x3 ) ! = 0 | | reg - > reg > = 0x10000 )
return - EINVAL ;
if ( mc417_register_read ( dev , ( u16 ) reg - > reg , & value ) )
return - EINVAL ; /* V4L2 spec, but -EREMOTEIO really */
reg - > size = 4 ;
reg - > val = value ;
return 0 ;
}
int cx23885_g_register ( struct file * file , void * fh ,
struct v4l2_dbg_register * reg )
{
struct cx23885_dev * dev = ( ( struct cx23885_fh * ) fh ) - > dev ;
if ( ! capable ( CAP_SYS_ADMIN ) )
return - EPERM ;
if ( reg - > match . type = = V4L2_CHIP_MATCH_HOST ) {
switch ( reg - > match . addr ) {
case 0 :
return cx23885_g_host_register ( dev , reg ) ;
case 1 :
return cx23417_g_register ( dev , reg ) ;
default :
break ;
}
}
/* FIXME - any error returns should not be ignored */
call_all ( dev , core , g_register , reg ) ;
return 0 ;
}
static int cx23885_s_host_register ( struct cx23885_dev * dev ,
struct v4l2_dbg_register * reg )
{
if ( ( reg - > reg & 0x3 ) ! = 0 | | reg - > reg > = pci_resource_len ( dev - > pci , 0 ) )
return - EINVAL ;
reg - > size = 4 ;
cx_write ( reg - > reg , reg - > val ) ;
return 0 ;
}
static int cx23417_s_register ( struct cx23885_dev * dev ,
struct v4l2_dbg_register * reg )
{
if ( dev - > v4l_device = = NULL )
return - EINVAL ;
if ( ( reg - > reg & 0x3 ) ! = 0 | | reg - > reg > = 0x10000 )
return - EINVAL ;
if ( mc417_register_write ( dev , ( u16 ) reg - > reg , ( u32 ) reg - > val ) )
return - EINVAL ; /* V4L2 spec, but -EREMOTEIO really */
reg - > size = 4 ;
return 0 ;
}
int cx23885_s_register ( struct file * file , void * fh ,
struct v4l2_dbg_register * reg )
{
struct cx23885_dev * dev = ( ( struct cx23885_fh * ) fh ) - > dev ;
if ( ! capable ( CAP_SYS_ADMIN ) )
return - EPERM ;
if ( reg - > match . type = = V4L2_CHIP_MATCH_HOST ) {
switch ( reg - > match . addr ) {
case 0 :
return cx23885_s_host_register ( dev , reg ) ;
case 1 :
return cx23417_s_register ( dev , reg ) ;
default :
break ;
}
}
/* FIXME - any error returns should not be ignored */
call_all ( dev , core , s_register , reg ) ;
return 0 ;
}
# endif