2008-10-01 04:51:53 -03:00
/*
* Driver for the po1030 sensor
*
2008-10-16 16:43:16 -03:00
* Copyright ( c ) 2008 Erik Andrén
2008-10-01 04:51:53 -03:00
* Copyright ( c ) 2007 Ilyes Gouta . Based on the m5603x Linux Driver Project .
* Copyright ( c ) 2005 m5603x Linux Driver Project < m5602 @ x3ng . com . br >
*
* Portions of code to USB interface and ALi driver software ,
* Copyright ( c ) 2006 Willem Duinker
* v4l2 interface modeled after the V4L2 driver
* for SN9C10x PC Camera Controllers
*
* 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 , version 2.
*
*/
# include "m5602_po1030.h"
2009-04-03 02:49:10 -03:00
static int po1030_get_exposure ( struct gspca_dev * gspca_dev , __s32 * val ) ;
static int po1030_set_exposure ( struct gspca_dev * gspca_dev , __s32 val ) ;
static int po1030_get_gain ( struct gspca_dev * gspca_dev , __s32 * val ) ;
static int po1030_set_gain ( struct gspca_dev * gspca_dev , __s32 val ) ;
static int po1030_get_red_balance ( struct gspca_dev * gspca_dev , __s32 * val ) ;
static int po1030_set_red_balance ( struct gspca_dev * gspca_dev , __s32 val ) ;
static int po1030_get_blue_balance ( struct gspca_dev * gspca_dev , __s32 * val ) ;
static int po1030_set_blue_balance ( struct gspca_dev * gspca_dev , __s32 val ) ;
2009-01-13 13:55:52 -03:00
static int po1030_get_green_balance ( struct gspca_dev * gspca_dev , __s32 * val ) ;
static int po1030_set_green_balance ( struct gspca_dev * gspca_dev , __s32 val ) ;
2009-04-03 02:49:10 -03:00
static int po1030_get_hflip ( struct gspca_dev * gspca_dev , __s32 * val ) ;
static int po1030_set_hflip ( struct gspca_dev * gspca_dev , __s32 val ) ;
static int po1030_get_vflip ( struct gspca_dev * gspca_dev , __s32 * val ) ;
static int po1030_set_vflip ( struct gspca_dev * gspca_dev , __s32 val ) ;
static int po1030_set_auto_white_balance ( struct gspca_dev * gspca_dev ,
__s32 val ) ;
static int po1030_get_auto_white_balance ( struct gspca_dev * gspca_dev ,
__s32 * val ) ;
2009-01-13 13:43:46 -03:00
static int po1030_set_auto_exposure ( struct gspca_dev * gspca_dev ,
__s32 val ) ;
static int po1030_get_auto_exposure ( struct gspca_dev * gspca_dev ,
__s32 * val ) ;
2009-04-03 02:49:10 -03:00
2008-12-30 16:48:42 -03:00
static struct v4l2_pix_format po1030_modes [ ] = {
{
640 ,
480 ,
V4L2_PIX_FMT_SBGGR8 ,
V4L2_FIELD_NONE ,
. sizeimage = 640 * 480 ,
. bytesperline = 640 ,
. colorspace = V4L2_COLORSPACE_SRGB ,
2009-01-15 14:05:35 -03:00
. priv = 2
2008-12-30 16:48:42 -03:00
}
} ;
2009-04-26 09:30:18 -03:00
static const struct ctrl po1030_ctrls [ ] = {
2009-01-06 06:39:11 -03:00
# define GAIN_IDX 0
2008-12-30 17:06:55 -03:00
{
{
2010-10-19 04:29:10 -03:00
. id = V4L2_CID_GAIN ,
. type = V4L2_CTRL_TYPE_INTEGER ,
. name = " gain " ,
. minimum = 0x00 ,
. maximum = 0x4f ,
. step = 0x1 ,
. default_value = PO1030_GLOBAL_GAIN_DEFAULT ,
. flags = V4L2_CTRL_FLAG_SLIDER
2008-12-30 17:06:55 -03:00
} ,
. set = po1030_set_gain ,
. get = po1030_get_gain
2009-01-06 06:39:11 -03:00
} ,
# define EXPOSURE_IDX 1
{
2008-12-30 17:06:55 -03:00
{
2010-10-19 04:29:10 -03:00
. id = V4L2_CID_EXPOSURE ,
. type = V4L2_CTRL_TYPE_INTEGER ,
. name = " exposure " ,
. minimum = 0x00 ,
. maximum = 0x02ff ,
. step = 0x1 ,
. default_value = PO1030_EXPOSURE_DEFAULT ,
. flags = V4L2_CTRL_FLAG_SLIDER
2008-12-30 17:06:55 -03:00
} ,
. set = po1030_set_exposure ,
. get = po1030_get_exposure
2009-01-06 06:39:11 -03:00
} ,
# define RED_BALANCE_IDX 2
{
2008-12-30 17:06:55 -03:00
{
2010-10-19 04:29:10 -03:00
. id = V4L2_CID_RED_BALANCE ,
. type = V4L2_CTRL_TYPE_INTEGER ,
. name = " red balance " ,
. minimum = 0x00 ,
. maximum = 0xff ,
. step = 0x1 ,
. default_value = PO1030_RED_GAIN_DEFAULT ,
. flags = V4L2_CTRL_FLAG_SLIDER
2008-12-30 17:06:55 -03:00
} ,
. set = po1030_set_red_balance ,
. get = po1030_get_red_balance
2009-01-06 06:39:11 -03:00
} ,
# define BLUE_BALANCE_IDX 3
{
2008-12-30 17:06:55 -03:00
{
2010-10-19 04:29:10 -03:00
. id = V4L2_CID_BLUE_BALANCE ,
. type = V4L2_CTRL_TYPE_INTEGER ,
. name = " blue balance " ,
. minimum = 0x00 ,
. maximum = 0xff ,
. step = 0x1 ,
. default_value = PO1030_BLUE_GAIN_DEFAULT ,
. flags = V4L2_CTRL_FLAG_SLIDER
2008-12-30 17:06:55 -03:00
} ,
. set = po1030_set_blue_balance ,
. get = po1030_get_blue_balance
2009-01-06 06:39:11 -03:00
} ,
# define HFLIP_IDX 4
{
2008-12-30 17:06:55 -03:00
{
2010-10-19 04:29:10 -03:00
. id = V4L2_CID_HFLIP ,
. type = V4L2_CTRL_TYPE_BOOLEAN ,
. name = " horizontal flip " ,
. minimum = 0 ,
. maximum = 1 ,
. step = 1 ,
. default_value = 0 ,
2008-12-30 17:06:55 -03:00
} ,
. set = po1030_set_hflip ,
. get = po1030_get_hflip
2009-01-06 06:39:11 -03:00
} ,
# define VFLIP_IDX 5
{
2008-12-30 17:06:55 -03:00
{
2010-10-19 04:29:10 -03:00
. id = V4L2_CID_VFLIP ,
. type = V4L2_CTRL_TYPE_BOOLEAN ,
. name = " vertical flip " ,
. minimum = 0 ,
. maximum = 1 ,
. step = 1 ,
. default_value = 0 ,
2008-12-30 17:06:55 -03:00
} ,
. set = po1030_set_vflip ,
. get = po1030_get_vflip
2009-01-08 03:53:50 -03:00
} ,
# define AUTO_WHITE_BALANCE_IDX 6
{
{
2010-10-19 04:29:10 -03:00
. id = V4L2_CID_AUTO_WHITE_BALANCE ,
. type = V4L2_CTRL_TYPE_BOOLEAN ,
. name = " auto white balance " ,
. minimum = 0 ,
. maximum = 1 ,
. step = 1 ,
. default_value = 0 ,
2009-01-08 03:53:50 -03:00
} ,
. set = po1030_set_auto_white_balance ,
. get = po1030_get_auto_white_balance
2009-01-13 13:43:46 -03:00
} ,
# define AUTO_EXPOSURE_IDX 7
{
{
2010-10-19 04:29:10 -03:00
. id = V4L2_CID_EXPOSURE_AUTO ,
. type = V4L2_CTRL_TYPE_BOOLEAN ,
. name = " auto exposure " ,
. minimum = 0 ,
. maximum = 1 ,
. step = 1 ,
. default_value = 0 ,
2009-01-13 13:43:46 -03:00
} ,
. set = po1030_set_auto_exposure ,
. get = po1030_get_auto_exposure
} ,
2009-01-13 13:55:52 -03:00
# define GREEN_BALANCE_IDX 8
{
{
2010-10-19 04:29:10 -03:00
. id = M5602_V4L2_CID_GREEN_BALANCE ,
. type = V4L2_CTRL_TYPE_INTEGER ,
. name = " green balance " ,
. minimum = 0x00 ,
. maximum = 0xff ,
. step = 0x1 ,
. default_value = PO1030_GREEN_GAIN_DEFAULT ,
. flags = V4L2_CTRL_FLAG_SLIDER
2009-01-13 13:55:52 -03:00
} ,
. set = po1030_set_green_balance ,
. get = po1030_get_green_balance
} ,
2008-12-30 17:06:55 -03:00
} ;
2008-11-24 14:21:29 -03:00
static void po1030_dump_registers ( struct sd * sd ) ;
2008-10-01 04:51:53 -03:00
int po1030_probe ( struct sd * sd )
{
2009-01-11 12:52:10 -03:00
u8 dev_id_h = 0 , i ;
2009-01-07 18:05:08 -03:00
s32 * sensor_settings ;
2008-10-01 04:51:53 -03:00
if ( force_sensor ) {
if ( force_sensor = = PO1030_SENSOR ) {
info ( " Forcing a %s sensor " , po1030 . name ) ;
goto sensor_found ;
}
/* If we want to force another sensor, don't try to probe this
* one */
return - ENODEV ;
}
2009-12-27 05:53:28 -03:00
PDEBUG ( D_PROBE , " Probing for a po1030 sensor " ) ;
2008-10-01 04:51:53 -03:00
/* Run the pre-init to actually probe the unit */
for ( i = 0 ; i < ARRAY_SIZE ( preinit_po1030 ) ; i + + ) {
u8 data = preinit_po1030 [ i ] [ 2 ] ;
if ( preinit_po1030 [ i ] [ 0 ] = = SENSOR )
2008-11-26 04:08:10 -03:00
m5602_write_sensor ( sd ,
2008-10-01 04:51:53 -03:00
preinit_po1030 [ i ] [ 1 ] , & data , 1 ) ;
else
m5602_write_bridge ( sd , preinit_po1030 [ i ] [ 1 ] , data ) ;
}
2009-01-08 04:04:19 -03:00
if ( m5602_read_sensor ( sd , PO1030_DEVID_H , & dev_id_h , 1 ) )
2008-10-01 04:51:53 -03:00
return - ENODEV ;
2009-01-11 12:52:10 -03:00
if ( dev_id_h = = 0x30 ) {
2008-10-01 04:51:53 -03:00
info ( " Detected a po1030 sensor " ) ;
goto sensor_found ;
}
return - ENODEV ;
sensor_found :
2009-01-06 06:39:11 -03:00
sensor_settings = kmalloc (
ARRAY_SIZE ( po1030_ctrls ) * sizeof ( s32 ) , GFP_KERNEL ) ;
if ( ! sensor_settings )
return - ENOMEM ;
2008-12-30 16:48:42 -03:00
sd - > gspca_dev . cam . cam_mode = po1030_modes ;
sd - > gspca_dev . cam . nmodes = ARRAY_SIZE ( po1030_modes ) ;
2008-12-30 17:06:55 -03:00
sd - > desc - > ctrls = po1030_ctrls ;
2008-12-30 15:27:17 -03:00
sd - > desc - > nctrls = ARRAY_SIZE ( po1030_ctrls ) ;
2009-01-06 06:39:11 -03:00
for ( i = 0 ; i < ARRAY_SIZE ( po1030_ctrls ) ; i + + )
sensor_settings [ i ] = po1030_ctrls [ i ] . qctrl . default_value ;
sd - > sensor_priv = sensor_settings ;
2009-01-07 18:05:08 -03:00
2008-10-01 04:51:53 -03:00
return 0 ;
}
int po1030_init ( struct sd * sd )
{
2009-01-07 18:05:08 -03:00
s32 * sensor_settings = sd - > sensor_priv ;
2008-10-01 04:51:53 -03:00
int i , err = 0 ;
/* Init the sensor */
2008-11-20 03:59:02 -03:00
for ( i = 0 ; i < ARRAY_SIZE ( init_po1030 ) & & ! err ; i + + ) {
2008-10-01 04:51:53 -03:00
u8 data [ 2 ] = { 0x00 , 0x00 } ;
switch ( init_po1030 [ i ] [ 0 ] ) {
case BRIDGE :
err = m5602_write_bridge ( sd ,
init_po1030 [ i ] [ 1 ] ,
init_po1030 [ i ] [ 2 ] ) ;
break ;
case SENSOR :
data [ 0 ] = init_po1030 [ i ] [ 2 ] ;
2008-11-26 04:08:10 -03:00
err = m5602_write_sensor ( sd ,
2008-10-01 04:51:53 -03:00
init_po1030 [ i ] [ 1 ] , data , 1 ) ;
break ;
default :
info ( " Invalid stream command, exiting init " ) ;
return - EINVAL ;
}
}
2009-01-07 18:05:08 -03:00
if ( err < 0 )
return err ;
2008-10-01 04:51:53 -03:00
2009-01-09 13:35:00 -03:00
if ( dump_sensor )
po1030_dump_registers ( sd ) ;
2009-01-07 18:05:08 -03:00
err = po1030_set_exposure ( & sd - > gspca_dev ,
sensor_settings [ EXPOSURE_IDX ] ) ;
if ( err < 0 )
return err ;
err = po1030_set_gain ( & sd - > gspca_dev , sensor_settings [ GAIN_IDX ] ) ;
if ( err < 0 )
return err ;
err = po1030_set_hflip ( & sd - > gspca_dev , sensor_settings [ HFLIP_IDX ] ) ;
if ( err < 0 )
return err ;
err = po1030_set_vflip ( & sd - > gspca_dev , sensor_settings [ VFLIP_IDX ] ) ;
if ( err < 0 )
return err ;
err = po1030_set_red_balance ( & sd - > gspca_dev ,
sensor_settings [ RED_BALANCE_IDX ] ) ;
if ( err < 0 )
return err ;
2008-10-01 04:51:53 -03:00
2009-01-11 15:23:46 -03:00
err = po1030_set_blue_balance ( & sd - > gspca_dev ,
2009-01-07 18:05:08 -03:00
sensor_settings [ BLUE_BALANCE_IDX ] ) ;
2009-01-08 03:53:50 -03:00
if ( err < 0 )
return err ;
2009-01-13 13:55:52 -03:00
err = po1030_set_green_balance ( & sd - > gspca_dev ,
sensor_settings [ GREEN_BALANCE_IDX ] ) ;
if ( err < 0 )
return err ;
2009-01-08 03:53:50 -03:00
err = po1030_set_auto_white_balance ( & sd - > gspca_dev ,
2009-01-13 13:43:46 -03:00
sensor_settings [ AUTO_WHITE_BALANCE_IDX ] ) ;
if ( err < 0 )
return err ;
err = po1030_set_auto_exposure ( & sd - > gspca_dev ,
sensor_settings [ AUTO_EXPOSURE_IDX ] ) ;
2008-11-20 03:59:02 -03:00
return err ;
2008-10-01 04:51:53 -03:00
}
2009-01-08 14:15:06 -03:00
int po1030_start ( struct sd * sd )
{
2009-01-15 13:39:39 -03:00
struct cam * cam = & sd - > gspca_dev . cam ;
2009-01-08 14:15:06 -03:00
int i , err = 0 ;
2009-01-15 13:39:39 -03:00
int width = cam - > cam_mode [ sd - > gspca_dev . curr_mode ] . width ;
int height = cam - > cam_mode [ sd - > gspca_dev . curr_mode ] . height ;
2009-01-15 14:05:35 -03:00
int ver_offs = cam - > cam_mode [ sd - > gspca_dev . curr_mode ] . priv ;
2009-01-15 13:39:39 -03:00
u8 data ;
switch ( width ) {
2009-01-15 14:18:36 -03:00
case 320 :
data = PO1030_SUBSAMPLING ;
err = m5602_write_sensor ( sd , PO1030_CONTROL3 , & data , 1 ) ;
if ( err < 0 )
return err ;
data = ( ( width + 3 ) > > 8 ) & 0xff ;
err = m5602_write_sensor ( sd , PO1030_WINDOWWIDTH_H , & data , 1 ) ;
if ( err < 0 )
return err ;
data = ( width + 3 ) & 0xff ;
err = m5602_write_sensor ( sd , PO1030_WINDOWWIDTH_L , & data , 1 ) ;
if ( err < 0 )
return err ;
data = ( ( height + 1 ) > > 8 ) & 0xff ;
err = m5602_write_sensor ( sd , PO1030_WINDOWHEIGHT_H , & data , 1 ) ;
if ( err < 0 )
return err ;
data = ( height + 1 ) & 0xff ;
err = m5602_write_sensor ( sd , PO1030_WINDOWHEIGHT_L , & data , 1 ) ;
height + = 6 ;
width - = 1 ;
break ;
2009-01-15 13:39:39 -03:00
case 640 :
2009-01-18 11:13:47 -03:00
data = 0 ;
err = m5602_write_sensor ( sd , PO1030_CONTROL3 , & data , 1 ) ;
if ( err < 0 )
return err ;
2009-01-15 13:39:39 -03:00
data = ( ( width + 7 ) > > 8 ) & 0xff ;
err = m5602_write_sensor ( sd , PO1030_WINDOWWIDTH_H , & data , 1 ) ;
if ( err < 0 )
return err ;
data = ( width + 7 ) & 0xff ;
err = m5602_write_sensor ( sd , PO1030_WINDOWWIDTH_L , & data , 1 ) ;
if ( err < 0 )
return err ;
data = ( ( height + 3 ) > > 8 ) & 0xff ;
err = m5602_write_sensor ( sd , PO1030_WINDOWHEIGHT_H , & data , 1 ) ;
if ( err < 0 )
return err ;
data = ( height + 3 ) & 0xff ;
err = m5602_write_sensor ( sd , PO1030_WINDOWHEIGHT_L , & data , 1 ) ;
2009-01-15 14:05:35 -03:00
height + = 12 ;
width - = 2 ;
2009-01-15 13:39:39 -03:00
break ;
}
2009-01-16 03:48:15 -03:00
err = m5602_write_bridge ( sd , M5602_XB_SENSOR_TYPE , 0x0c ) ;
if ( err < 0 )
return err ;
2009-01-15 13:39:39 -03:00
2009-01-15 14:05:35 -03:00
err = m5602_write_bridge ( sd , M5602_XB_LINE_OF_FRAME_H , 0x81 ) ;
if ( err < 0 )
return err ;
err = m5602_write_bridge ( sd , M5602_XB_PIX_OF_LINE_H , 0x82 ) ;
if ( err < 0 )
return err ;
2009-01-16 03:48:15 -03:00
err = m5602_write_bridge ( sd , M5602_XB_SIG_INI , 0x01 ) ;
if ( err < 0 )
return err ;
2009-01-15 14:05:35 -03:00
err = m5602_write_bridge ( sd , M5602_XB_VSYNC_PARA ,
( ( ver_offs > > 8 ) & 0xff ) ) ;
if ( err < 0 )
return err ;
err = m5602_write_bridge ( sd , M5602_XB_VSYNC_PARA , ( ver_offs & 0xff ) ) ;
if ( err < 0 )
return err ;
2009-01-16 03:48:15 -03:00
for ( i = 0 ; i < 2 & & ! err ; i + + )
err = m5602_write_bridge ( sd , M5602_XB_VSYNC_PARA , 0 ) ;
2009-01-15 14:05:35 -03:00
if ( err < 0 )
return err ;
err = m5602_write_bridge ( sd , M5602_XB_VSYNC_PARA , ( height > > 8 ) & 0xff ) ;
if ( err < 0 )
return err ;
err = m5602_write_bridge ( sd , M5602_XB_VSYNC_PARA , ( height & 0xff ) ) ;
if ( err < 0 )
return err ;
for ( i = 0 ; i < 2 & & ! err ; i + + )
err = m5602_write_bridge ( sd , M5602_XB_VSYNC_PARA , 0 ) ;
2009-01-16 03:48:15 -03:00
for ( i = 0 ; i < 2 & & ! err ; i + + )
err = m5602_write_bridge ( sd , M5602_XB_SIG_INI , 0 ) ;
2009-01-15 14:05:35 -03:00
for ( i = 0 ; i < 2 & & ! err ; i + + )
err = m5602_write_bridge ( sd , M5602_XB_HSYNC_PARA , 0 ) ;
if ( err < 0 )
return err ;
err = m5602_write_bridge ( sd , M5602_XB_HSYNC_PARA , ( width > > 8 ) & 0xff ) ;
if ( err < 0 )
return err ;
err = m5602_write_bridge ( sd , M5602_XB_HSYNC_PARA , ( width & 0xff ) ) ;
2009-01-16 03:48:15 -03:00
if ( err < 0 )
return err ;
err = m5602_write_bridge ( sd , M5602_XB_SIG_INI , 0 ) ;
2009-01-08 14:15:06 -03:00
return err ;
}
2009-04-03 02:49:10 -03:00
static int po1030_get_exposure ( struct gspca_dev * gspca_dev , __s32 * val )
2008-10-01 04:51:53 -03:00
{
struct sd * sd = ( struct sd * ) gspca_dev ;
2009-01-06 06:39:11 -03:00
s32 * sensor_settings = sd - > sensor_priv ;
2008-10-01 04:51:53 -03:00
2009-01-06 06:39:11 -03:00
* val = sensor_settings [ EXPOSURE_IDX ] ;
2008-10-16 16:46:07 -03:00
PDEBUG ( D_V4L2 , " Exposure read as %d " , * val ) ;
2009-01-06 06:39:11 -03:00
return 0 ;
2008-10-01 04:51:53 -03:00
}
2009-04-03 02:49:10 -03:00
static int po1030_set_exposure ( struct gspca_dev * gspca_dev , __s32 val )
2008-10-01 04:51:53 -03:00
{
struct sd * sd = ( struct sd * ) gspca_dev ;
2009-01-06 06:39:11 -03:00
s32 * sensor_settings = sd - > sensor_priv ;
2008-10-01 04:51:53 -03:00
u8 i2c_data ;
int err ;
2009-01-06 06:39:11 -03:00
sensor_settings [ EXPOSURE_IDX ] = val ;
2008-10-16 16:46:07 -03:00
PDEBUG ( D_V4L2 , " Set exposure to %d " , val & 0xffff ) ;
2008-10-01 04:51:53 -03:00
i2c_data = ( ( val & 0xff00 ) > > 8 ) ;
2008-10-16 16:46:07 -03:00
PDEBUG ( D_V4L2 , " Set exposure to high byte to 0x%x " ,
2008-10-01 04:51:53 -03:00
i2c_data ) ;
2009-01-07 13:54:13 -03:00
err = m5602_write_sensor ( sd , PO1030_INTEGLINES_H ,
2008-10-01 04:51:53 -03:00
& i2c_data , 1 ) ;
if ( err < 0 )
2008-12-27 12:28:00 -03:00
return err ;
2008-10-01 04:51:53 -03:00
i2c_data = ( val & 0xff ) ;
2008-10-16 16:46:07 -03:00
PDEBUG ( D_V4L2 , " Set exposure to low byte to 0x%x " ,
2008-10-01 04:51:53 -03:00
i2c_data ) ;
2009-01-07 13:54:13 -03:00
err = m5602_write_sensor ( sd , PO1030_INTEGLINES_M ,
2008-10-01 04:51:53 -03:00
& i2c_data , 1 ) ;
2008-11-20 03:59:02 -03:00
return err ;
2008-10-01 04:51:53 -03:00
}
2009-04-03 02:49:10 -03:00
static int po1030_get_gain ( struct gspca_dev * gspca_dev , __s32 * val )
2008-10-01 04:51:53 -03:00
{
struct sd * sd = ( struct sd * ) gspca_dev ;
2009-01-06 06:39:11 -03:00
s32 * sensor_settings = sd - > sensor_priv ;
2008-10-01 04:51:53 -03:00
2009-01-06 06:39:11 -03:00
* val = sensor_settings [ GAIN_IDX ] ;
2008-10-16 16:46:07 -03:00
PDEBUG ( D_V4L2 , " Read global gain %d " , * val ) ;
2009-01-06 06:39:11 -03:00
return 0 ;
2008-10-01 04:51:53 -03:00
}
2009-04-03 02:49:10 -03:00
static int po1030_set_gain ( struct gspca_dev * gspca_dev , __s32 val )
2008-10-16 16:49:17 -03:00
{
struct sd * sd = ( struct sd * ) gspca_dev ;
2009-01-06 06:39:11 -03:00
s32 * sensor_settings = sd - > sensor_priv ;
2008-10-16 16:49:17 -03:00
u8 i2c_data ;
int err ;
2009-01-06 06:39:11 -03:00
sensor_settings [ GAIN_IDX ] = val ;
i2c_data = val & 0xff ;
PDEBUG ( D_V4L2 , " Set global gain to %d " , i2c_data ) ;
2009-01-07 13:54:13 -03:00
err = m5602_write_sensor ( sd , PO1030_GLOBALGAIN ,
2008-10-16 16:49:17 -03:00
& i2c_data , 1 ) ;
2009-01-06 06:39:11 -03:00
return err ;
}
2008-10-16 16:49:17 -03:00
2009-04-03 02:49:10 -03:00
static int po1030_get_hflip ( struct gspca_dev * gspca_dev , __s32 * val )
2009-01-06 06:39:11 -03:00
{
struct sd * sd = ( struct sd * ) gspca_dev ;
s32 * sensor_settings = sd - > sensor_priv ;
2008-10-16 16:49:17 -03:00
2009-01-06 06:39:11 -03:00
* val = sensor_settings [ HFLIP_IDX ] ;
2008-10-16 16:49:17 -03:00
PDEBUG ( D_V4L2 , " Read hflip %d " , * val ) ;
2009-01-06 06:39:11 -03:00
return 0 ;
2008-10-16 16:49:17 -03:00
}
2009-04-03 02:49:10 -03:00
static int po1030_set_hflip ( struct gspca_dev * gspca_dev , __s32 val )
2008-10-16 16:49:17 -03:00
{
struct sd * sd = ( struct sd * ) gspca_dev ;
2009-01-06 06:39:11 -03:00
s32 * sensor_settings = sd - > sensor_priv ;
2008-10-16 16:49:17 -03:00
u8 i2c_data ;
int err ;
2009-01-06 06:39:11 -03:00
sensor_settings [ HFLIP_IDX ] = val ;
2008-10-16 16:49:17 -03:00
PDEBUG ( D_V4L2 , " Set hflip %d " , val ) ;
2009-01-07 13:54:13 -03:00
err = m5602_read_sensor ( sd , PO1030_CONTROL2 , & i2c_data , 1 ) ;
2008-11-27 14:07:24 -03:00
if ( err < 0 )
2008-12-27 12:28:00 -03:00
return err ;
2008-10-16 16:49:17 -03:00
2008-11-27 14:07:24 -03:00
i2c_data = ( 0x7f & i2c_data ) | ( ( val & 0x01 ) < < 7 ) ;
2008-10-16 16:49:17 -03:00
2009-01-07 13:54:13 -03:00
err = m5602_write_sensor ( sd , PO1030_CONTROL2 ,
2008-11-27 14:07:24 -03:00
& i2c_data , 1 ) ;
2008-10-16 16:49:17 -03:00
2008-11-20 03:59:02 -03:00
return err ;
2008-10-16 16:49:17 -03:00
}
2009-04-03 02:49:10 -03:00
static int po1030_get_vflip ( struct gspca_dev * gspca_dev , __s32 * val )
2008-10-16 16:49:17 -03:00
{
struct sd * sd = ( struct sd * ) gspca_dev ;
2009-01-06 06:39:11 -03:00
s32 * sensor_settings = sd - > sensor_priv ;
2008-10-16 16:49:17 -03:00
2009-01-07 17:41:47 -03:00
* val = sensor_settings [ VFLIP_IDX ] ;
2008-10-16 16:49:17 -03:00
PDEBUG ( D_V4L2 , " Read vflip %d " , * val ) ;
2009-01-06 06:39:11 -03:00
return 0 ;
2008-10-16 16:49:17 -03:00
}
2009-04-03 02:49:10 -03:00
static int po1030_set_vflip ( struct gspca_dev * gspca_dev , __s32 val )
2008-10-16 16:49:17 -03:00
{
struct sd * sd = ( struct sd * ) gspca_dev ;
2009-01-06 06:39:11 -03:00
s32 * sensor_settings = sd - > sensor_priv ;
2008-10-16 16:49:17 -03:00
u8 i2c_data ;
int err ;
2009-01-06 06:39:11 -03:00
sensor_settings [ VFLIP_IDX ] = val ;
2008-10-16 16:49:17 -03:00
PDEBUG ( D_V4L2 , " Set vflip %d " , val ) ;
2009-01-07 13:54:13 -03:00
err = m5602_read_sensor ( sd , PO1030_CONTROL2 , & i2c_data , 1 ) ;
2008-11-27 14:07:24 -03:00
if ( err < 0 )
2008-12-27 12:28:00 -03:00
return err ;
2008-10-16 16:49:17 -03:00
2008-11-27 14:07:24 -03:00
i2c_data = ( i2c_data & 0xbf ) | ( ( val & 0x01 ) < < 6 ) ;
2008-10-16 16:49:17 -03:00
2009-01-07 13:54:13 -03:00
err = m5602_write_sensor ( sd , PO1030_CONTROL2 ,
2008-11-27 14:07:24 -03:00
& i2c_data , 1 ) ;
2008-10-16 16:49:17 -03:00
2008-11-20 03:59:02 -03:00
return err ;
2008-10-16 16:49:17 -03:00
}
2009-04-03 02:49:10 -03:00
static int po1030_get_red_balance ( struct gspca_dev * gspca_dev , __s32 * val )
2008-10-01 04:51:53 -03:00
{
struct sd * sd = ( struct sd * ) gspca_dev ;
2009-01-06 06:39:11 -03:00
s32 * sensor_settings = sd - > sensor_priv ;
2008-10-01 04:51:53 -03:00
2009-01-06 06:39:11 -03:00
* val = sensor_settings [ RED_BALANCE_IDX ] ;
2008-10-16 16:46:07 -03:00
PDEBUG ( D_V4L2 , " Read red gain %d " , * val ) ;
2009-01-06 06:39:11 -03:00
return 0 ;
2008-10-01 04:51:53 -03:00
}
2009-04-03 02:49:10 -03:00
static int po1030_set_red_balance ( struct gspca_dev * gspca_dev , __s32 val )
2008-10-01 04:51:53 -03:00
{
struct sd * sd = ( struct sd * ) gspca_dev ;
2009-01-06 06:39:11 -03:00
s32 * sensor_settings = sd - > sensor_priv ;
2008-10-01 04:51:53 -03:00
u8 i2c_data ;
int err ;
2009-01-06 06:39:11 -03:00
sensor_settings [ RED_BALANCE_IDX ] = val ;
2008-10-01 04:51:53 -03:00
i2c_data = val & 0xff ;
2008-10-16 16:46:07 -03:00
PDEBUG ( D_V4L2 , " Set red gain to %d " , i2c_data ) ;
2009-01-07 13:54:13 -03:00
err = m5602_write_sensor ( sd , PO1030_RED_GAIN ,
2008-10-01 04:51:53 -03:00
& i2c_data , 1 ) ;
2008-11-20 03:59:02 -03:00
return err ;
2008-10-01 04:51:53 -03:00
}
2009-04-03 02:49:10 -03:00
static int po1030_get_blue_balance ( struct gspca_dev * gspca_dev , __s32 * val )
2008-10-01 04:51:53 -03:00
{
struct sd * sd = ( struct sd * ) gspca_dev ;
2009-01-06 06:39:11 -03:00
s32 * sensor_settings = sd - > sensor_priv ;
2008-10-01 04:51:53 -03:00
2009-01-06 06:39:11 -03:00
* val = sensor_settings [ BLUE_BALANCE_IDX ] ;
2008-10-16 16:46:07 -03:00
PDEBUG ( D_V4L2 , " Read blue gain %d " , * val ) ;
2008-10-01 04:51:53 -03:00
2009-01-06 06:39:11 -03:00
return 0 ;
2008-10-01 04:51:53 -03:00
}
2009-04-03 02:49:10 -03:00
static int po1030_set_blue_balance ( struct gspca_dev * gspca_dev , __s32 val )
2008-10-01 04:51:53 -03:00
{
struct sd * sd = ( struct sd * ) gspca_dev ;
2009-01-06 06:39:11 -03:00
s32 * sensor_settings = sd - > sensor_priv ;
2008-10-01 04:51:53 -03:00
u8 i2c_data ;
int err ;
2009-01-06 06:39:11 -03:00
sensor_settings [ BLUE_BALANCE_IDX ] = val ;
2008-10-01 04:51:53 -03:00
i2c_data = val & 0xff ;
2008-10-16 16:46:07 -03:00
PDEBUG ( D_V4L2 , " Set blue gain to %d " , i2c_data ) ;
2009-01-07 13:54:13 -03:00
err = m5602_write_sensor ( sd , PO1030_BLUE_GAIN ,
2008-10-01 04:51:53 -03:00
& i2c_data , 1 ) ;
2008-11-20 03:59:02 -03:00
return err ;
2008-10-01 04:51:53 -03:00
}
2009-01-13 13:55:52 -03:00
static int po1030_get_green_balance ( struct gspca_dev * gspca_dev , __s32 * val )
{
struct sd * sd = ( struct sd * ) gspca_dev ;
s32 * sensor_settings = sd - > sensor_priv ;
* val = sensor_settings [ GREEN_BALANCE_IDX ] ;
PDEBUG ( D_V4L2 , " Read green gain %d " , * val ) ;
return 0 ;
}
static int po1030_set_green_balance ( struct gspca_dev * gspca_dev , __s32 val )
{
struct sd * sd = ( struct sd * ) gspca_dev ;
s32 * sensor_settings = sd - > sensor_priv ;
u8 i2c_data ;
int err ;
sensor_settings [ GREEN_BALANCE_IDX ] = val ;
i2c_data = val & 0xff ;
PDEBUG ( D_V4L2 , " Set green gain to %d " , i2c_data ) ;
err = m5602_write_sensor ( sd , PO1030_GREEN_1_GAIN ,
& i2c_data , 1 ) ;
if ( err < 0 )
return err ;
return m5602_write_sensor ( sd , PO1030_GREEN_2_GAIN ,
& i2c_data , 1 ) ;
}
2009-04-03 02:49:10 -03:00
static int po1030_get_auto_white_balance ( struct gspca_dev * gspca_dev ,
__s32 * val )
2009-01-08 03:53:50 -03:00
{
struct sd * sd = ( struct sd * ) gspca_dev ;
s32 * sensor_settings = sd - > sensor_priv ;
* val = sensor_settings [ AUTO_WHITE_BALANCE_IDX ] ;
PDEBUG ( D_V4L2 , " Auto white balancing is %d " , * val ) ;
return 0 ;
}
2009-04-03 02:49:10 -03:00
static int po1030_set_auto_white_balance ( struct gspca_dev * gspca_dev ,
__s32 val )
2009-01-08 03:53:50 -03:00
{
struct sd * sd = ( struct sd * ) gspca_dev ;
s32 * sensor_settings = sd - > sensor_priv ;
u8 i2c_data ;
int err ;
sensor_settings [ AUTO_WHITE_BALANCE_IDX ] = val ;
err = m5602_read_sensor ( sd , PO1030_AUTOCTRL1 , & i2c_data , 1 ) ;
if ( err < 0 )
return err ;
2009-01-13 13:43:46 -03:00
PDEBUG ( D_V4L2 , " Set auto white balance to %d " , val ) ;
2009-01-08 03:53:50 -03:00
i2c_data = ( i2c_data & 0xfe ) | ( val & 0x01 ) ;
err = m5602_write_sensor ( sd , PO1030_AUTOCTRL1 , & i2c_data , 1 ) ;
return err ;
}
2009-01-13 13:43:46 -03:00
static int po1030_get_auto_exposure ( struct gspca_dev * gspca_dev ,
__s32 * val )
{
struct sd * sd = ( struct sd * ) gspca_dev ;
s32 * sensor_settings = sd - > sensor_priv ;
* val = sensor_settings [ AUTO_EXPOSURE_IDX ] ;
PDEBUG ( D_V4L2 , " Auto exposure is %d " , * val ) ;
return 0 ;
}
static int po1030_set_auto_exposure ( struct gspca_dev * gspca_dev ,
__s32 val )
{
struct sd * sd = ( struct sd * ) gspca_dev ;
s32 * sensor_settings = sd - > sensor_priv ;
u8 i2c_data ;
int err ;
sensor_settings [ AUTO_EXPOSURE_IDX ] = val ;
err = m5602_read_sensor ( sd , PO1030_AUTOCTRL1 , & i2c_data , 1 ) ;
if ( err < 0 )
return err ;
PDEBUG ( D_V4L2 , " Set auto exposure to %d " , val ) ;
i2c_data = ( i2c_data & 0xfd ) | ( ( val & 0x01 ) < < 1 ) ;
return m5602_write_sensor ( sd , PO1030_AUTOCTRL1 , & i2c_data , 1 ) ;
}
2009-01-06 06:39:11 -03:00
void po1030_disconnect ( struct sd * sd )
{
sd - > sensor = NULL ;
kfree ( sd - > sensor_priv ) ;
}
2008-11-24 14:21:29 -03:00
static void po1030_dump_registers ( struct sd * sd )
2008-10-01 04:51:53 -03:00
{
int address ;
u8 value = 0 ;
info ( " Dumping the po1030 sensor core registers " ) ;
for ( address = 0 ; address < 0x7f ; address + + ) {
2008-11-27 13:46:39 -03:00
m5602_read_sensor ( sd , address , & value , 1 ) ;
2008-10-01 04:51:53 -03:00
info ( " register 0x%x contains 0x%x " ,
address , value ) ;
}
info ( " po1030 register state dump complete " ) ;
info ( " Probing for which registers that are read/write " ) ;
for ( address = 0 ; address < 0xff ; address + + ) {
u8 old_value , ctrl_value ;
u8 test_value [ 2 ] = { 0xff , 0xff } ;
2008-11-27 13:46:39 -03:00
m5602_read_sensor ( sd , address , & old_value , 1 ) ;
2008-11-26 04:08:10 -03:00
m5602_write_sensor ( sd , address , test_value , 1 ) ;
2008-11-27 13:46:39 -03:00
m5602_read_sensor ( sd , address , & ctrl_value , 1 ) ;
2008-10-01 04:51:53 -03:00
if ( ctrl_value = = test_value [ 0 ] )
info ( " register 0x%x is writeable " , address ) ;
else
info ( " register 0x%x is read only " , address ) ;
/* Restore original value */
2008-11-26 04:08:10 -03:00
m5602_write_sensor ( sd , address , & old_value , 1 ) ;
2008-10-01 04:51:53 -03:00
}
}