2019-05-27 09:55:06 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2006-02-27 06:09:05 +03:00
/****************************************************************************
*
* Filename : cpia2_core . c
*
* Copyright 2001 , STMicrolectronics , Inc .
* Contact : steve . miller @ st . com
*
* Description :
* This is a USB driver for CPia2 based video cameras .
* The infrastructure of this driver is based on the cpia usb driver by
* Jochen Scharrlach and Johannes Erdfeldt .
*
* Stripped of 2.4 stuff ready for main kernel submit by
2008-10-27 21:13:47 +03:00
* Alan Cox < alan @ lxorguk . ukuu . org . uk >
2006-02-27 06:09:05 +03:00
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "cpia2.h"
2012-08-03 20:39:28 +04:00
# include <linux/module.h>
2006-02-27 06:09:05 +03:00
# include <linux/slab.h>
2008-07-25 14:39:54 +04:00
# include <linux/mm.h>
2006-02-27 06:09:05 +03:00
# include <linux/vmalloc.h>
2008-06-23 14:36:23 +04:00
# include <linux/firmware.h>
2017-02-02 21:15:33 +03:00
# include <linux/sched/signal.h>
2006-02-27 06:09:05 +03:00
2012-08-03 20:39:28 +04:00
# define FIRMWARE "cpia2 / stv0672_vp4.bin"
MODULE_FIRMWARE ( FIRMWARE ) ;
2008-04-22 21:41:48 +04:00
/* #define _CPIA2_DEBUG_ */
2006-02-27 06:09:05 +03:00
# ifdef _CPIA2_DEBUG_
static const char * block_name [ ] = {
" System " ,
" VC " ,
" VP " ,
" IDATA "
} ;
# endif
2008-04-22 21:41:48 +04:00
static unsigned int debugs_on ; /* default 0 - DEBUG_REG */
2006-02-27 06:09:05 +03:00
/******************************************************************************
*
* Forward Declarations
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int apply_vp_patch ( struct camera_data * cam ) ;
static int set_default_user_mode ( struct camera_data * cam ) ;
static int set_vw_size ( struct camera_data * cam , int size ) ;
static int configure_sensor ( struct camera_data * cam ,
int reqwidth , int reqheight ) ;
static int config_sensor_410 ( struct camera_data * cam ,
int reqwidth , int reqheight ) ;
static int config_sensor_500 ( struct camera_data * cam ,
int reqwidth , int reqheight ) ;
static int set_all_properties ( struct camera_data * cam ) ;
static void wake_system ( struct camera_data * cam ) ;
static void set_lowlight_boost ( struct camera_data * cam ) ;
static void reset_camera_struct ( struct camera_data * cam ) ;
static int cpia2_set_high_power ( struct camera_data * cam ) ;
/* Here we want the physical address of the memory.
* This is used when initializing the contents of the
* area and marking the pages as reserved .
*/
static inline unsigned long kvirt_to_pa ( unsigned long adr )
{
unsigned long kva , ret ;
kva = ( unsigned long ) page_address ( vmalloc_to_page ( ( void * ) adr ) ) ;
kva | = adr & ( PAGE_SIZE - 1 ) ; /* restore the offset */
ret = __pa ( kva ) ;
return ret ;
}
static void * rvmalloc ( unsigned long size )
{
void * mem ;
unsigned long adr ;
/* Round it off to PAGE_SIZE */
size = PAGE_ALIGN ( size ) ;
mem = vmalloc_32 ( size ) ;
if ( ! mem )
return NULL ;
memset ( mem , 0 , size ) ; /* Clear the ram out, no junk to the user */
adr = ( unsigned long ) mem ;
while ( ( long ) size > 0 ) {
SetPageReserved ( vmalloc_to_page ( ( void * ) adr ) ) ;
adr + = PAGE_SIZE ;
size - = PAGE_SIZE ;
}
return mem ;
}
static void rvfree ( void * mem , unsigned long size )
{
unsigned long adr ;
if ( ! mem )
return ;
size = PAGE_ALIGN ( size ) ;
adr = ( unsigned long ) mem ;
while ( ( long ) size > 0 ) {
ClearPageReserved ( vmalloc_to_page ( ( void * ) adr ) ) ;
adr + = PAGE_SIZE ;
size - = PAGE_SIZE ;
}
vfree ( mem ) ;
}
/******************************************************************************
*
* cpia2_do_command
*
* Send an arbitrary command to the camera . For commands that read from
* the camera , copy the buffers into the proper param structures .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int cpia2_do_command ( struct camera_data * cam ,
u32 command , u8 direction , u8 param )
{
int retval = 0 ;
struct cpia2_command cmd ;
unsigned int device = cam - > params . pnp_id . device_type ;
cmd . command = command ;
cmd . reg_count = 2 ; /* default */
cmd . direction = direction ;
/***
* Set up the command .
* * */
switch ( command ) {
case CPIA2_CMD_GET_VERSION :
cmd . req_mode =
CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM ;
cmd . start = CPIA2_SYSTEM_DEVICE_HI ;
break ;
case CPIA2_CMD_GET_PNP_ID :
cmd . req_mode =
CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM ;
cmd . reg_count = 8 ;
cmd . start = CPIA2_SYSTEM_DESCRIP_VID_HI ;
break ;
case CPIA2_CMD_GET_ASIC_TYPE :
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC ;
cmd . start = CPIA2_VC_ASIC_ID ;
break ;
case CPIA2_CMD_GET_SENSOR :
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP ;
cmd . start = CPIA2_VP_SENSOR_FLAGS ;
break ;
case CPIA2_CMD_GET_VP_DEVICE :
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP ;
cmd . start = CPIA2_VP_DEVICEH ;
break ;
case CPIA2_CMD_SET_VP_BRIGHTNESS :
2017-05-18 14:13:28 +03:00
cmd . buffer . block_data [ 0 ] = param ;
2020-08-24 01:36:59 +03:00
fallthrough ;
2006-02-27 06:09:05 +03:00
case CPIA2_CMD_GET_VP_BRIGHTNESS :
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP ;
cmd . reg_count = 1 ;
if ( device = = DEVICE_STV_672 )
cmd . start = CPIA2_VP4_EXPOSURE_TARGET ;
else
cmd . start = CPIA2_VP5_EXPOSURE_TARGET ;
break ;
case CPIA2_CMD_SET_CONTRAST :
2017-05-18 14:13:28 +03:00
cmd . buffer . block_data [ 0 ] = param ;
2020-08-24 01:36:59 +03:00
fallthrough ;
2006-02-27 06:09:05 +03:00
case CPIA2_CMD_GET_CONTRAST :
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP ;
cmd . reg_count = 1 ;
cmd . start = CPIA2_VP_YRANGE ;
break ;
case CPIA2_CMD_SET_VP_SATURATION :
2017-05-18 14:13:28 +03:00
cmd . buffer . block_data [ 0 ] = param ;
2020-08-24 01:36:59 +03:00
fallthrough ;
2006-02-27 06:09:05 +03:00
case CPIA2_CMD_GET_VP_SATURATION :
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP ;
cmd . reg_count = 1 ;
if ( device = = DEVICE_STV_672 )
cmd . start = CPIA2_VP_SATURATION ;
else
cmd . start = CPIA2_VP5_MCUVSATURATION ;
break ;
case CPIA2_CMD_SET_VP_GPIO_DATA :
2017-05-18 14:13:28 +03:00
cmd . buffer . block_data [ 0 ] = param ;
2020-08-24 01:36:59 +03:00
fallthrough ;
2006-02-27 06:09:05 +03:00
case CPIA2_CMD_GET_VP_GPIO_DATA :
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP ;
cmd . reg_count = 1 ;
cmd . start = CPIA2_VP_GPIO_DATA ;
break ;
case CPIA2_CMD_SET_VP_GPIO_DIRECTION :
2017-05-18 14:13:28 +03:00
cmd . buffer . block_data [ 0 ] = param ;
2020-08-24 01:36:59 +03:00
fallthrough ;
2006-02-27 06:09:05 +03:00
case CPIA2_CMD_GET_VP_GPIO_DIRECTION :
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP ;
cmd . reg_count = 1 ;
cmd . start = CPIA2_VP_GPIO_DIRECTION ;
break ;
case CPIA2_CMD_SET_VC_MP_GPIO_DATA :
2017-05-18 14:13:28 +03:00
cmd . buffer . block_data [ 0 ] = param ;
2020-08-24 01:36:59 +03:00
fallthrough ;
2006-02-27 06:09:05 +03:00
case CPIA2_CMD_GET_VC_MP_GPIO_DATA :
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC ;
cmd . reg_count = 1 ;
cmd . start = CPIA2_VC_MP_DATA ;
break ;
case CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION :
2017-05-18 14:13:28 +03:00
cmd . buffer . block_data [ 0 ] = param ;
2020-08-24 01:36:59 +03:00
fallthrough ;
2006-02-27 06:09:05 +03:00
case CPIA2_CMD_GET_VC_MP_GPIO_DIRECTION :
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC ;
cmd . reg_count = 1 ;
cmd . start = CPIA2_VC_MP_DIR ;
break ;
case CPIA2_CMD_ENABLE_PACKET_CTRL :
cmd . req_mode =
CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM ;
cmd . start = CPIA2_SYSTEM_INT_PACKET_CTRL ;
cmd . reg_count = 1 ;
cmd . buffer . block_data [ 0 ] = param ;
break ;
case CPIA2_CMD_SET_FLICKER_MODES :
2017-05-18 14:13:28 +03:00
cmd . buffer . block_data [ 0 ] = param ;
2020-08-24 01:36:59 +03:00
fallthrough ;
2006-02-27 06:09:05 +03:00
case CPIA2_CMD_GET_FLICKER_MODES :
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP ;
cmd . reg_count = 1 ;
cmd . start = CPIA2_VP_FLICKER_MODES ;
break ;
case CPIA2_CMD_RESET_FIFO : /* clear fifo and enable stream block */
cmd . req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC ;
cmd . reg_count = 2 ;
cmd . start = 0 ;
cmd . buffer . registers [ 0 ] . index = CPIA2_VC_ST_CTRL ;
cmd . buffer . registers [ 0 ] . value = CPIA2_VC_ST_CTRL_SRC_VC |
CPIA2_VC_ST_CTRL_DST_USB | CPIA2_VC_ST_CTRL_EOF_DETECT ;
cmd . buffer . registers [ 1 ] . index = CPIA2_VC_ST_CTRL ;
cmd . buffer . registers [ 1 ] . value = CPIA2_VC_ST_CTRL_SRC_VC |
CPIA2_VC_ST_CTRL_DST_USB |
CPIA2_VC_ST_CTRL_EOF_DETECT |
CPIA2_VC_ST_CTRL_FIFO_ENABLE ;
break ;
case CPIA2_CMD_SET_HI_POWER :
cmd . req_mode =
CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_SYSTEM ;
cmd . reg_count = 2 ;
cmd . buffer . registers [ 0 ] . index =
CPIA2_SYSTEM_SYSTEM_CONTROL ;
cmd . buffer . registers [ 1 ] . index =
CPIA2_SYSTEM_SYSTEM_CONTROL ;
cmd . buffer . registers [ 0 ] . value = CPIA2_SYSTEM_CONTROL_CLEAR_ERR ;
cmd . buffer . registers [ 1 ] . value =
CPIA2_SYSTEM_CONTROL_HIGH_POWER ;
break ;
case CPIA2_CMD_SET_LOW_POWER :
cmd . req_mode =
CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM ;
cmd . reg_count = 1 ;
cmd . start = CPIA2_SYSTEM_SYSTEM_CONTROL ;
cmd . buffer . block_data [ 0 ] = 0 ;
break ;
case CPIA2_CMD_CLEAR_V2W_ERR :
cmd . req_mode =
CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM ;
cmd . reg_count = 1 ;
cmd . start = CPIA2_SYSTEM_SYSTEM_CONTROL ;
cmd . buffer . block_data [ 0 ] = CPIA2_SYSTEM_CONTROL_CLEAR_ERR ;
break ;
2017-05-18 14:13:28 +03:00
case CPIA2_CMD_SET_USER_MODE :
2006-02-27 06:09:05 +03:00
cmd . buffer . block_data [ 0 ] = param ;
2020-08-24 01:36:59 +03:00
fallthrough ;
2006-02-27 06:09:05 +03:00
case CPIA2_CMD_GET_USER_MODE :
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP ;
cmd . reg_count = 1 ;
if ( device = = DEVICE_STV_672 )
cmd . start = CPIA2_VP4_USER_MODE ;
else
cmd . start = CPIA2_VP5_USER_MODE ;
break ;
case CPIA2_CMD_FRAMERATE_REQ :
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP ;
cmd . reg_count = 1 ;
if ( device = = DEVICE_STV_672 )
cmd . start = CPIA2_VP4_FRAMERATE_REQUEST ;
else
cmd . start = CPIA2_VP5_FRAMERATE_REQUEST ;
cmd . buffer . block_data [ 0 ] = param ;
break ;
case CPIA2_CMD_SET_WAKEUP :
2017-05-18 14:13:28 +03:00
cmd . buffer . block_data [ 0 ] = param ;
2020-08-24 01:36:59 +03:00
fallthrough ;
2006-02-27 06:09:05 +03:00
case CPIA2_CMD_GET_WAKEUP :
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC ;
cmd . reg_count = 1 ;
cmd . start = CPIA2_VC_WAKEUP ;
break ;
case CPIA2_CMD_SET_PW_CONTROL :
2017-05-18 14:13:28 +03:00
cmd . buffer . block_data [ 0 ] = param ;
2020-08-24 01:36:59 +03:00
fallthrough ;
2006-02-27 06:09:05 +03:00
case CPIA2_CMD_GET_PW_CONTROL :
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC ;
cmd . reg_count = 1 ;
cmd . start = CPIA2_VC_PW_CTRL ;
break ;
case CPIA2_CMD_GET_VP_SYSTEM_STATE :
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP ;
cmd . reg_count = 1 ;
cmd . start = CPIA2_VP_SYSTEMSTATE ;
break ;
case CPIA2_CMD_SET_SYSTEM_CTRL :
2017-05-18 14:13:28 +03:00
cmd . buffer . block_data [ 0 ] = param ;
2020-08-24 01:36:59 +03:00
fallthrough ;
2006-02-27 06:09:05 +03:00
case CPIA2_CMD_GET_SYSTEM_CTRL :
cmd . req_mode =
CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM ;
cmd . reg_count = 1 ;
cmd . start = CPIA2_SYSTEM_SYSTEM_CONTROL ;
break ;
case CPIA2_CMD_SET_VP_SYSTEM_CTRL :
2017-05-18 14:13:28 +03:00
cmd . buffer . block_data [ 0 ] = param ;
2020-08-24 01:36:59 +03:00
fallthrough ;
2006-02-27 06:09:05 +03:00
case CPIA2_CMD_GET_VP_SYSTEM_CTRL :
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP ;
cmd . reg_count = 1 ;
cmd . start = CPIA2_VP_SYSTEMCTRL ;
break ;
case CPIA2_CMD_SET_VP_EXP_MODES :
2017-05-18 14:13:28 +03:00
cmd . buffer . block_data [ 0 ] = param ;
2020-08-24 01:36:59 +03:00
fallthrough ;
2006-02-27 06:09:05 +03:00
case CPIA2_CMD_GET_VP_EXP_MODES :
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP ;
cmd . reg_count = 1 ;
cmd . start = CPIA2_VP_EXPOSURE_MODES ;
break ;
case CPIA2_CMD_SET_DEVICE_CONFIG :
2017-05-18 14:13:28 +03:00
cmd . buffer . block_data [ 0 ] = param ;
2020-08-24 01:36:59 +03:00
fallthrough ;
2006-02-27 06:09:05 +03:00
case CPIA2_CMD_GET_DEVICE_CONFIG :
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP ;
cmd . reg_count = 1 ;
cmd . start = CPIA2_VP_DEVICE_CONFIG ;
break ;
case CPIA2_CMD_SET_SERIAL_ADDR :
cmd . buffer . block_data [ 0 ] = param ;
cmd . req_mode =
CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM ;
cmd . reg_count = 1 ;
cmd . start = CPIA2_SYSTEM_VP_SERIAL_ADDR ;
break ;
case CPIA2_CMD_SET_SENSOR_CR1 :
cmd . buffer . block_data [ 0 ] = param ;
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP ;
cmd . reg_count = 1 ;
cmd . start = CPIA2_SENSOR_CR1 ;
break ;
case CPIA2_CMD_SET_VC_CONTROL :
2017-05-18 14:13:28 +03:00
cmd . buffer . block_data [ 0 ] = param ;
2020-08-24 01:36:59 +03:00
fallthrough ;
2006-02-27 06:09:05 +03:00
case CPIA2_CMD_GET_VC_CONTROL :
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC ;
cmd . reg_count = 1 ;
cmd . start = CPIA2_VC_VC_CTRL ;
break ;
case CPIA2_CMD_SET_TARGET_KB :
cmd . req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC ;
cmd . reg_count = 1 ;
cmd . buffer . registers [ 0 ] . index = CPIA2_VC_VC_TARGET_KB ;
cmd . buffer . registers [ 0 ] . value = param ;
break ;
case CPIA2_CMD_SET_DEF_JPEG_OPT :
cmd . req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC ;
cmd . reg_count = 4 ;
cmd . buffer . registers [ 0 ] . index = CPIA2_VC_VC_JPEG_OPT ;
cmd . buffer . registers [ 0 ] . value =
CPIA2_VC_VC_JPEG_OPT_DOUBLE_SQUEEZE ;
cmd . buffer . registers [ 1 ] . index = CPIA2_VC_VC_USER_SQUEEZE ;
cmd . buffer . registers [ 1 ] . value = 20 ;
cmd . buffer . registers [ 2 ] . index = CPIA2_VC_VC_CREEP_PERIOD ;
cmd . buffer . registers [ 2 ] . value = 2 ;
cmd . buffer . registers [ 3 ] . index = CPIA2_VC_VC_JPEG_OPT ;
cmd . buffer . registers [ 3 ] . value = CPIA2_VC_VC_JPEG_OPT_DEFAULT ;
break ;
case CPIA2_CMD_REHASH_VP4 :
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP ;
cmd . reg_count = 1 ;
cmd . start = CPIA2_VP_REHASH_VALUES ;
cmd . buffer . block_data [ 0 ] = param ;
break ;
case CPIA2_CMD_SET_USER_EFFECTS : /* Note: Be careful with this as
this register can also affect
flicker modes */
2017-05-18 14:13:28 +03:00
cmd . buffer . block_data [ 0 ] = param ;
2020-08-24 01:36:59 +03:00
fallthrough ;
2006-02-27 06:09:05 +03:00
case CPIA2_CMD_GET_USER_EFFECTS :
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP ;
cmd . reg_count = 1 ;
if ( device = = DEVICE_STV_672 )
cmd . start = CPIA2_VP4_USER_EFFECTS ;
else
cmd . start = CPIA2_VP5_USER_EFFECTS ;
break ;
default :
LOG ( " DoCommand received invalid command \n " ) ;
return - EINVAL ;
}
retval = cpia2_send_command ( cam , & cmd ) ;
if ( retval ) {
return retval ;
}
/***
* Now copy any results from a read into the appropriate param struct .
* * */
switch ( command ) {
case CPIA2_CMD_GET_VERSION :
cam - > params . version . firmware_revision_hi =
cmd . buffer . block_data [ 0 ] ;
cam - > params . version . firmware_revision_lo =
cmd . buffer . block_data [ 1 ] ;
break ;
case CPIA2_CMD_GET_PNP_ID :
cam - > params . pnp_id . vendor = ( cmd . buffer . block_data [ 0 ] < < 8 ) |
cmd . buffer . block_data [ 1 ] ;
cam - > params . pnp_id . product = ( cmd . buffer . block_data [ 2 ] < < 8 ) |
cmd . buffer . block_data [ 3 ] ;
cam - > params . pnp_id . device_revision =
( cmd . buffer . block_data [ 4 ] < < 8 ) |
cmd . buffer . block_data [ 5 ] ;
if ( cam - > params . pnp_id . vendor = = 0x553 ) {
if ( cam - > params . pnp_id . product = = 0x100 ) {
cam - > params . pnp_id . device_type = DEVICE_STV_672 ;
} else if ( cam - > params . pnp_id . product = = 0x140 | |
cam - > params . pnp_id . product = = 0x151 ) {
cam - > params . pnp_id . device_type = DEVICE_STV_676 ;
}
}
break ;
case CPIA2_CMD_GET_ASIC_TYPE :
cam - > params . version . asic_id = cmd . buffer . block_data [ 0 ] ;
cam - > params . version . asic_rev = cmd . buffer . block_data [ 1 ] ;
break ;
case CPIA2_CMD_GET_SENSOR :
cam - > params . version . sensor_flags = cmd . buffer . block_data [ 0 ] ;
cam - > params . version . sensor_rev = cmd . buffer . block_data [ 1 ] ;
break ;
case CPIA2_CMD_GET_VP_DEVICE :
cam - > params . version . vp_device_hi = cmd . buffer . block_data [ 0 ] ;
cam - > params . version . vp_device_lo = cmd . buffer . block_data [ 1 ] ;
break ;
case CPIA2_CMD_GET_VP_GPIO_DATA :
cam - > params . vp_params . gpio_data = cmd . buffer . block_data [ 0 ] ;
break ;
case CPIA2_CMD_GET_VP_GPIO_DIRECTION :
cam - > params . vp_params . gpio_direction = cmd . buffer . block_data [ 0 ] ;
break ;
case CPIA2_CMD_GET_VC_MP_GPIO_DIRECTION :
cam - > params . vc_params . vc_mp_direction = cmd . buffer . block_data [ 0 ] ;
break ;
case CPIA2_CMD_GET_VC_MP_GPIO_DATA :
cam - > params . vc_params . vc_mp_data = cmd . buffer . block_data [ 0 ] ;
break ;
case CPIA2_CMD_GET_FLICKER_MODES :
cam - > params . flicker_control . cam_register =
cmd . buffer . block_data [ 0 ] ;
break ;
case CPIA2_CMD_GET_WAKEUP :
cam - > params . vc_params . wakeup = cmd . buffer . block_data [ 0 ] ;
break ;
case CPIA2_CMD_GET_PW_CONTROL :
cam - > params . vc_params . pw_control = cmd . buffer . block_data [ 0 ] ;
break ;
case CPIA2_CMD_GET_SYSTEM_CTRL :
cam - > params . camera_state . system_ctrl = cmd . buffer . block_data [ 0 ] ;
break ;
case CPIA2_CMD_GET_VP_SYSTEM_STATE :
cam - > params . vp_params . system_state = cmd . buffer . block_data [ 0 ] ;
break ;
case CPIA2_CMD_GET_VP_SYSTEM_CTRL :
cam - > params . vp_params . system_ctrl = cmd . buffer . block_data [ 0 ] ;
break ;
case CPIA2_CMD_GET_VP_EXP_MODES :
cam - > params . vp_params . exposure_modes = cmd . buffer . block_data [ 0 ] ;
break ;
case CPIA2_CMD_GET_DEVICE_CONFIG :
cam - > params . vp_params . device_config = cmd . buffer . block_data [ 0 ] ;
break ;
case CPIA2_CMD_GET_VC_CONTROL :
cam - > params . vc_params . vc_control = cmd . buffer . block_data [ 0 ] ;
break ;
case CPIA2_CMD_GET_USER_MODE :
cam - > params . vp_params . video_mode = cmd . buffer . block_data [ 0 ] ;
break ;
case CPIA2_CMD_GET_USER_EFFECTS :
cam - > params . vp_params . user_effects = cmd . buffer . block_data [ 0 ] ;
break ;
default :
break ;
}
return retval ;
}
/******************************************************************************
*
* cpia2_send_command
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-03-11 23:00:01 +03:00
# define DIR(cmd) ((cmd->direction == TRANSFER_WRITE) ? "Write" : "Read")
# define BINDEX(cmd) (cmd->req_mode & 0x03)
2006-02-27 06:09:05 +03:00
int cpia2_send_command ( struct camera_data * cam , struct cpia2_command * cmd )
{
u8 count ;
u8 start ;
u8 * buffer ;
int retval ;
switch ( cmd - > req_mode & 0x0c ) {
case CAMERAACCESS_TYPE_RANDOM :
count = cmd - > reg_count * sizeof ( struct cpia2_register ) ;
start = 0 ;
buffer = ( u8 * ) & cmd - > buffer ;
if ( debugs_on & DEBUG_REG )
2011-03-11 23:00:01 +03:00
DBG ( " %s Random: Register block %s \n " , DIR ( cmd ) ,
block_name [ BINDEX ( cmd ) ] ) ;
2006-02-27 06:09:05 +03:00
break ;
case CAMERAACCESS_TYPE_BLOCK :
count = cmd - > reg_count ;
start = cmd - > start ;
buffer = cmd - > buffer . block_data ;
if ( debugs_on & DEBUG_REG )
2011-03-11 23:00:01 +03:00
DBG ( " %s Block: Register block %s \n " , DIR ( cmd ) ,
block_name [ BINDEX ( cmd ) ] ) ;
2006-02-27 06:09:05 +03:00
break ;
case CAMERAACCESS_TYPE_MASK :
count = cmd - > reg_count * sizeof ( struct cpia2_reg_mask ) ;
start = 0 ;
buffer = ( u8 * ) & cmd - > buffer ;
if ( debugs_on & DEBUG_REG )
2011-03-11 23:00:01 +03:00
DBG ( " %s Mask: Register block %s \n " , DIR ( cmd ) ,
block_name [ BINDEX ( cmd ) ] ) ;
2006-02-27 06:09:05 +03:00
break ;
case CAMERAACCESS_TYPE_REPEAT : /* For patch blocks only */
count = cmd - > reg_count ;
start = cmd - > start ;
buffer = cmd - > buffer . block_data ;
if ( debugs_on & DEBUG_REG )
2011-03-11 23:00:01 +03:00
DBG ( " %s Repeat: Register block %s \n " , DIR ( cmd ) ,
block_name [ BINDEX ( cmd ) ] ) ;
2006-02-27 06:09:05 +03:00
break ;
default :
2008-04-09 06:20:00 +04:00
LOG ( " %s: invalid request mode \n " , __func__ ) ;
2006-02-27 06:09:05 +03:00
return - EINVAL ;
}
retval = cpia2_usb_transfer_cmd ( cam ,
buffer ,
cmd - > req_mode ,
start , count , cmd - > direction ) ;
# ifdef _CPIA2_DEBUG_
if ( debugs_on & DEBUG_REG ) {
int i ;
for ( i = 0 ; i < cmd - > reg_count ; i + + ) {
if ( ( cmd - > req_mode & 0x0c ) = = CAMERAACCESS_TYPE_BLOCK )
KINFO ( " %s Block: [0x%02X] = 0x%02X \n " ,
2011-03-11 23:00:01 +03:00
DIR ( cmd ) , start + i , buffer [ i ] ) ;
2006-02-27 06:09:05 +03:00
if ( ( cmd - > req_mode & 0x0c ) = = CAMERAACCESS_TYPE_RANDOM )
KINFO ( " %s Random: [0x%02X] = 0x%02X \n " ,
2011-03-11 23:00:01 +03:00
DIR ( cmd ) , cmd - > buffer . registers [ i ] . index ,
2006-02-27 06:09:05 +03:00
cmd - > buffer . registers [ i ] . value ) ;
}
}
# endif
return retval ;
} ;
/*************
* Functions to implement camera functionality
* * * * * * * * * * * * */
/******************************************************************************
*
* cpia2_get_version_info
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void cpia2_get_version_info ( struct camera_data * cam )
{
cpia2_do_command ( cam , CPIA2_CMD_GET_VERSION , TRANSFER_READ , 0 ) ;
cpia2_do_command ( cam , CPIA2_CMD_GET_PNP_ID , TRANSFER_READ , 0 ) ;
cpia2_do_command ( cam , CPIA2_CMD_GET_ASIC_TYPE , TRANSFER_READ , 0 ) ;
cpia2_do_command ( cam , CPIA2_CMD_GET_SENSOR , TRANSFER_READ , 0 ) ;
cpia2_do_command ( cam , CPIA2_CMD_GET_VP_DEVICE , TRANSFER_READ , 0 ) ;
}
/******************************************************************************
*
* cpia2_reset_camera
*
* Called at least during the open process , sets up initial params .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int cpia2_reset_camera ( struct camera_data * cam )
{
u8 tmp_reg ;
int retval = 0 ;
2012-04-29 15:44:44 +04:00
int target_kb ;
2006-02-27 06:09:05 +03:00
int i ;
struct cpia2_command cmd ;
/***
* VC setup
* * */
retval = configure_sensor ( cam ,
cam - > params . roi . width ,
cam - > params . roi . height ) ;
if ( retval < 0 ) {
ERR ( " Couldn't configure sensor, error=%d \n " , retval ) ;
return retval ;
}
/* Clear FIFO and route/enable stream block */
cmd . req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC ;
cmd . direction = TRANSFER_WRITE ;
cmd . reg_count = 2 ;
cmd . buffer . registers [ 0 ] . index = CPIA2_VC_ST_CTRL ;
cmd . buffer . registers [ 0 ] . value = CPIA2_VC_ST_CTRL_SRC_VC |
CPIA2_VC_ST_CTRL_DST_USB | CPIA2_VC_ST_CTRL_EOF_DETECT ;
cmd . buffer . registers [ 1 ] . index = CPIA2_VC_ST_CTRL ;
cmd . buffer . registers [ 1 ] . value = CPIA2_VC_ST_CTRL_SRC_VC |
CPIA2_VC_ST_CTRL_DST_USB |
CPIA2_VC_ST_CTRL_EOF_DETECT | CPIA2_VC_ST_CTRL_FIFO_ENABLE ;
cpia2_send_command ( cam , & cmd ) ;
cpia2_set_high_power ( cam ) ;
if ( cam - > params . pnp_id . device_type = = DEVICE_STV_672 ) {
/* Enable button notification */
cmd . req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_SYSTEM ;
cmd . buffer . registers [ 0 ] . index = CPIA2_SYSTEM_INT_PACKET_CTRL ;
cmd . buffer . registers [ 0 ] . value =
CPIA2_SYSTEM_INT_PACKET_CTRL_ENABLE_SW_XX ;
cmd . reg_count = 1 ;
cpia2_send_command ( cam , & cmd ) ;
}
2007-07-16 17:47:51 +04:00
schedule_timeout_interruptible ( msecs_to_jiffies ( 100 ) ) ;
2006-02-27 06:09:05 +03:00
if ( cam - > params . pnp_id . device_type = = DEVICE_STV_672 )
retval = apply_vp_patch ( cam ) ;
/* wait for vp to go to sleep */
2007-07-16 17:47:51 +04:00
schedule_timeout_interruptible ( msecs_to_jiffies ( 100 ) ) ;
2006-02-27 06:09:05 +03:00
/***
* If this is a 676 , apply VP5 fixes before we start streaming
* * */
if ( cam - > params . pnp_id . device_type = = DEVICE_STV_676 ) {
cmd . req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VP ;
/* The following writes improve the picture */
cmd . buffer . registers [ 0 ] . index = CPIA2_VP5_MYBLACK_LEVEL ;
cmd . buffer . registers [ 0 ] . value = 0 ; /* reduce from the default
* rec 601 pedestal of 16 */
cmd . buffer . registers [ 1 ] . index = CPIA2_VP5_MCYRANGE ;
cmd . buffer . registers [ 1 ] . value = 0x92 ; /* increase from 100% to
* ( 256 / 256 - 31 ) to fill
* available range */
cmd . buffer . registers [ 2 ] . index = CPIA2_VP5_MYCEILING ;
cmd . buffer . registers [ 2 ] . value = 0xFF ; /* Increase from the
* default rec 601 ceiling
* of 240 */
cmd . buffer . registers [ 3 ] . index = CPIA2_VP5_MCUVSATURATION ;
cmd . buffer . registers [ 3 ] . value = 0xFF ; /* Increase from the rec
* 601 100 % level ( 128 )
* to 145 - 192 */
cmd . buffer . registers [ 4 ] . index = CPIA2_VP5_ANTIFLKRSETUP ;
cmd . buffer . registers [ 4 ] . value = 0x80 ; /* Inhibit the
* anti - flicker */
/* The following 4 writes are a fix to allow QVGA to work at 30 fps */
cmd . buffer . registers [ 5 ] . index = CPIA2_VP_RAM_ADDR_H ;
cmd . buffer . registers [ 5 ] . value = 0x01 ;
cmd . buffer . registers [ 6 ] . index = CPIA2_VP_RAM_ADDR_L ;
cmd . buffer . registers [ 6 ] . value = 0xE3 ;
cmd . buffer . registers [ 7 ] . index = CPIA2_VP_RAM_DATA ;
cmd . buffer . registers [ 7 ] . value = 0x02 ;
cmd . buffer . registers [ 8 ] . index = CPIA2_VP_RAM_DATA ;
cmd . buffer . registers [ 8 ] . value = 0xFC ;
cmd . direction = TRANSFER_WRITE ;
cmd . reg_count = 9 ;
cpia2_send_command ( cam , & cmd ) ;
}
/* Activate all settings and start the data stream */
/* Set user mode */
set_default_user_mode ( cam ) ;
/* Give VP time to wake up */
2007-07-16 17:47:51 +04:00
schedule_timeout_interruptible ( msecs_to_jiffies ( 100 ) ) ;
2006-02-27 06:09:05 +03:00
set_all_properties ( cam ) ;
cpia2_do_command ( cam , CPIA2_CMD_GET_USER_MODE , TRANSFER_READ , 0 ) ;
DBG ( " After SetAllProperties(cam), user mode is 0x%0X \n " ,
cam - > params . vp_params . video_mode ) ;
/***
* Set audio regulator off . This and the code to set the compresison
* state are too complex to form a CPIA2_CMD_ , and seem to be somewhat
* intertwined . This stuff came straight from the windows driver .
* * */
/* Turn AutoExposure off in VP and enable the serial bridge to the sensor */
cpia2_do_command ( cam , CPIA2_CMD_GET_VP_SYSTEM_CTRL , TRANSFER_READ , 0 ) ;
tmp_reg = cam - > params . vp_params . system_ctrl ;
cmd . buffer . registers [ 0 ] . value = tmp_reg &
( tmp_reg & ( CPIA2_VP_SYSTEMCTRL_HK_CONTROL ^ 0xFF ) ) ;
cpia2_do_command ( cam , CPIA2_CMD_GET_DEVICE_CONFIG , TRANSFER_READ , 0 ) ;
cmd . buffer . registers [ 1 ] . value = cam - > params . vp_params . device_config |
CPIA2_VP_DEVICE_CONFIG_SERIAL_BRIDGE ;
cmd . buffer . registers [ 0 ] . index = CPIA2_VP_SYSTEMCTRL ;
cmd . buffer . registers [ 1 ] . index = CPIA2_VP_DEVICE_CONFIG ;
cmd . req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VP ;
cmd . reg_count = 2 ;
cmd . direction = TRANSFER_WRITE ;
cmd . start = 0 ;
cpia2_send_command ( cam , & cmd ) ;
/* Set the correct I2C address in the CPiA-2 system register */
cpia2_do_command ( cam ,
CPIA2_CMD_SET_SERIAL_ADDR ,
TRANSFER_WRITE ,
CPIA2_SYSTEM_VP_SERIAL_ADDR_SENSOR ) ;
/* Now have sensor access - set bit to turn the audio regulator off */
cpia2_do_command ( cam ,
CPIA2_CMD_SET_SENSOR_CR1 ,
TRANSFER_WRITE , CPIA2_SENSOR_CR1_DOWN_AUDIO_REGULATOR ) ;
/* Set the correct I2C address in the CPiA-2 system register */
if ( cam - > params . pnp_id . device_type = = DEVICE_STV_672 )
cpia2_do_command ( cam ,
CPIA2_CMD_SET_SERIAL_ADDR ,
TRANSFER_WRITE ,
CPIA2_SYSTEM_VP_SERIAL_ADDR_VP ) ; // 0x88
else
cpia2_do_command ( cam ,
CPIA2_CMD_SET_SERIAL_ADDR ,
TRANSFER_WRITE ,
CPIA2_SYSTEM_VP_SERIAL_ADDR_676_VP ) ; // 0x8a
/* increase signal drive strength */
if ( cam - > params . pnp_id . device_type = = DEVICE_STV_676 )
cpia2_do_command ( cam ,
CPIA2_CMD_SET_VP_EXP_MODES ,
TRANSFER_WRITE ,
CPIA2_VP_EXPOSURE_MODES_COMPILE_EXP ) ;
/* Start autoexposure */
cpia2_do_command ( cam , CPIA2_CMD_GET_DEVICE_CONFIG , TRANSFER_READ , 0 ) ;
cmd . buffer . registers [ 0 ] . value = cam - > params . vp_params . device_config &
( CPIA2_VP_DEVICE_CONFIG_SERIAL_BRIDGE ^ 0xFF ) ;
cpia2_do_command ( cam , CPIA2_CMD_GET_VP_SYSTEM_CTRL , TRANSFER_READ , 0 ) ;
cmd . buffer . registers [ 1 ] . value =
cam - > params . vp_params . system_ctrl | CPIA2_VP_SYSTEMCTRL_HK_CONTROL ;
cmd . buffer . registers [ 0 ] . index = CPIA2_VP_DEVICE_CONFIG ;
cmd . buffer . registers [ 1 ] . index = CPIA2_VP_SYSTEMCTRL ;
cmd . req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VP ;
cmd . reg_count = 2 ;
cmd . direction = TRANSFER_WRITE ;
cpia2_send_command ( cam , & cmd ) ;
/* Set compression state */
cpia2_do_command ( cam , CPIA2_CMD_GET_VC_CONTROL , TRANSFER_READ , 0 ) ;
if ( cam - > params . compression . inhibit_htables ) {
tmp_reg = cam - > params . vc_params . vc_control |
CPIA2_VC_VC_CTRL_INHIBIT_H_TABLES ;
} else {
tmp_reg = cam - > params . vc_params . vc_control &
~ CPIA2_VC_VC_CTRL_INHIBIT_H_TABLES ;
}
cpia2_do_command ( cam , CPIA2_CMD_SET_VC_CONTROL , TRANSFER_WRITE , tmp_reg ) ;
2012-04-29 15:44:44 +04:00
/* Set target size (kb) on vc
This is a heuristic based on the quality parameter and the raw
framesize in kB divided by 16 ( the compression factor when the
quality is 100 % ) */
target_kb = ( cam - > width * cam - > height * 2 / 16384 ) *
cam - > params . vc_params . quality / 100 ;
if ( target_kb < 1 )
target_kb = 1 ;
2006-02-27 06:09:05 +03:00
cpia2_do_command ( cam , CPIA2_CMD_SET_TARGET_KB ,
2012-04-29 15:44:44 +04:00
TRANSFER_WRITE , target_kb ) ;
2006-02-27 06:09:05 +03:00
/* Wiggle VC Reset */
/***
* First read and wait a bit .
* * */
for ( i = 0 ; i < 50 ; i + + ) {
cpia2_do_command ( cam , CPIA2_CMD_GET_PW_CONTROL ,
TRANSFER_READ , 0 ) ;
}
tmp_reg = cam - > params . vc_params . pw_control ;
tmp_reg & = ~ CPIA2_VC_PW_CTRL_VC_RESET_N ;
cpia2_do_command ( cam , CPIA2_CMD_SET_PW_CONTROL , TRANSFER_WRITE , tmp_reg ) ;
tmp_reg | = CPIA2_VC_PW_CTRL_VC_RESET_N ;
cpia2_do_command ( cam , CPIA2_CMD_SET_PW_CONTROL , TRANSFER_WRITE , tmp_reg ) ;
cpia2_do_command ( cam , CPIA2_CMD_SET_DEF_JPEG_OPT , TRANSFER_WRITE , 0 ) ;
cpia2_do_command ( cam , CPIA2_CMD_GET_USER_MODE , TRANSFER_READ , 0 ) ;
DBG ( " After VC RESET, user mode is 0x%0X \n " ,
cam - > params . vp_params . video_mode ) ;
return retval ;
}
/******************************************************************************
*
* cpia2_set_high_power
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int cpia2_set_high_power ( struct camera_data * cam )
{
int i ;
for ( i = 0 ; i < = 50 ; i + + ) {
/* Read system status */
cpia2_do_command ( cam , CPIA2_CMD_GET_SYSTEM_CTRL , TRANSFER_READ , 0 ) ;
/* If there is an error, clear it */
if ( cam - > params . camera_state . system_ctrl &
CPIA2_SYSTEM_CONTROL_V2W_ERR )
cpia2_do_command ( cam , CPIA2_CMD_CLEAR_V2W_ERR ,
TRANSFER_WRITE , 0 ) ;
/* Try to set high power mode */
cpia2_do_command ( cam , CPIA2_CMD_SET_SYSTEM_CTRL ,
TRANSFER_WRITE , 1 ) ;
/* Try to read something in VP to check if everything is awake */
cpia2_do_command ( cam , CPIA2_CMD_GET_VP_SYSTEM_STATE ,
TRANSFER_READ , 0 ) ;
if ( cam - > params . vp_params . system_state &
CPIA2_VP_SYSTEMSTATE_HK_ALIVE ) {
break ;
} else if ( i = = 50 ) {
cam - > params . camera_state . power_mode = LO_POWER_MODE ;
ERR ( " Camera did not wake up \n " ) ;
return - EIO ;
}
}
DBG ( " System now in high power state \n " ) ;
cam - > params . camera_state . power_mode = HI_POWER_MODE ;
return 0 ;
}
/******************************************************************************
*
* cpia2_set_low_power
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int cpia2_set_low_power ( struct camera_data * cam )
{
cam - > params . camera_state . power_mode = LO_POWER_MODE ;
cpia2_do_command ( cam , CPIA2_CMD_SET_SYSTEM_CTRL , TRANSFER_WRITE , 0 ) ;
return 0 ;
}
/******************************************************************************
*
* apply_vp_patch
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-06-23 14:36:23 +04:00
static int cpia2_send_onebyte_command ( struct camera_data * cam ,
struct cpia2_command * cmd ,
u8 start , u8 datum )
{
cmd - > buffer . block_data [ 0 ] = datum ;
cmd - > start = start ;
cmd - > reg_count = 1 ;
return cpia2_send_command ( cam , cmd ) ;
}
2006-02-27 06:09:05 +03:00
static int apply_vp_patch ( struct camera_data * cam )
{
2008-06-23 14:36:23 +04:00
const struct firmware * fw ;
2012-08-03 20:39:28 +04:00
const char fw_name [ ] = FIRMWARE ;
2008-06-23 14:36:23 +04:00
int i , ret ;
2006-02-27 06:09:05 +03:00
struct cpia2_command cmd ;
2008-06-23 14:36:23 +04:00
ret = request_firmware ( & fw , fw_name , & cam - > dev - > dev ) ;
if ( ret ) {
printk ( KERN_ERR " cpia2: failed to load VP patch \" %s \" \n " ,
fw_name ) ;
return ret ;
}
2006-02-27 06:09:05 +03:00
cmd . req_mode = CAMERAACCESS_TYPE_REPEAT | CAMERAACCESS_VP ;
cmd . direction = TRANSFER_WRITE ;
2008-06-23 14:36:23 +04:00
/* First send the start address... */
cpia2_send_onebyte_command ( cam , & cmd , 0x0A , fw - > data [ 0 ] ) ; /* hi */
cpia2_send_onebyte_command ( cam , & cmd , 0x0B , fw - > data [ 1 ] ) ; /* lo */
2006-02-27 06:09:05 +03:00
2008-06-23 14:36:23 +04:00
/* ... followed by the data payload */
for ( i = 2 ; i < fw - > size ; i + = 64 ) {
cmd . start = 0x0C ; /* Data */
2016-02-09 14:14:12 +03:00
cmd . reg_count = min_t ( uint , 64 , fw - > size - i ) ;
2008-06-23 14:36:23 +04:00
memcpy ( cmd . buffer . block_data , & fw - > data [ i ] , cmd . reg_count ) ;
2006-02-27 06:09:05 +03:00
cpia2_send_command ( cam , & cmd ) ;
}
2008-06-23 14:36:23 +04:00
/* Next send the start address... */
cpia2_send_onebyte_command ( cam , & cmd , 0x0A , fw - > data [ 0 ] ) ; /* hi */
cpia2_send_onebyte_command ( cam , & cmd , 0x0B , fw - > data [ 1 ] ) ; /* lo */
/* ... followed by the 'goto' command */
cpia2_send_onebyte_command ( cam , & cmd , 0x0D , 1 ) ;
release_firmware ( fw ) ;
2006-02-27 06:09:05 +03:00
return 0 ;
}
/******************************************************************************
*
* set_default_user_mode
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int set_default_user_mode ( struct camera_data * cam )
{
unsigned char user_mode ;
unsigned char frame_rate ;
int width = cam - > params . roi . width ;
int height = cam - > params . roi . height ;
switch ( cam - > params . version . sensor_flags ) {
case CPIA2_VP_SENSOR_FLAGS_404 :
case CPIA2_VP_SENSOR_FLAGS_407 :
case CPIA2_VP_SENSOR_FLAGS_409 :
case CPIA2_VP_SENSOR_FLAGS_410 :
if ( ( width > STV_IMAGE_QCIF_COLS )
| | ( height > STV_IMAGE_QCIF_ROWS ) ) {
user_mode = CPIA2_VP_USER_MODE_CIF ;
} else {
user_mode = CPIA2_VP_USER_MODE_QCIFDS ;
}
frame_rate = CPIA2_VP_FRAMERATE_30 ;
break ;
case CPIA2_VP_SENSOR_FLAGS_500 :
if ( ( width > STV_IMAGE_CIF_COLS )
| | ( height > STV_IMAGE_CIF_ROWS ) ) {
user_mode = CPIA2_VP_USER_MODE_VGA ;
} else {
user_mode = CPIA2_VP_USER_MODE_QVGADS ;
}
if ( cam - > params . pnp_id . device_type = = DEVICE_STV_672 )
frame_rate = CPIA2_VP_FRAMERATE_15 ;
else
frame_rate = CPIA2_VP_FRAMERATE_30 ;
break ;
default :
2008-04-09 06:20:00 +04:00
LOG ( " %s: Invalid sensor flag value 0x%0X \n " , __func__ ,
2006-02-27 06:09:05 +03:00
cam - > params . version . sensor_flags ) ;
return - EINVAL ;
}
DBG ( " Sensor flag = 0x%0x, user mode = 0x%0x, frame rate = 0x%X \n " ,
cam - > params . version . sensor_flags , user_mode , frame_rate ) ;
cpia2_do_command ( cam , CPIA2_CMD_SET_USER_MODE , TRANSFER_WRITE ,
user_mode ) ;
if ( cam - > params . vp_params . frame_rate > 0 & &
frame_rate > cam - > params . vp_params . frame_rate )
frame_rate = cam - > params . vp_params . frame_rate ;
cpia2_set_fps ( cam , frame_rate ) ;
// if (cam->params.pnp_id.device_type == DEVICE_STV_676)
// cpia2_do_command(cam,
// CPIA2_CMD_SET_VP_SYSTEM_CTRL,
// TRANSFER_WRITE,
// CPIA2_VP_SYSTEMCTRL_HK_CONTROL |
// CPIA2_VP_SYSTEMCTRL_POWER_CONTROL);
return 0 ;
}
/******************************************************************************
*
* cpia2_match_video_size
*
* return the best match , where ' best ' is as always
* the largest that is not bigger than what is requested .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int cpia2_match_video_size ( int width , int height )
{
if ( width > = STV_IMAGE_VGA_COLS & & height > = STV_IMAGE_VGA_ROWS )
return VIDEOSIZE_VGA ;
if ( width > = STV_IMAGE_CIF_COLS & & height > = STV_IMAGE_CIF_ROWS )
return VIDEOSIZE_CIF ;
if ( width > = STV_IMAGE_QVGA_COLS & & height > = STV_IMAGE_QVGA_ROWS )
return VIDEOSIZE_QVGA ;
if ( width > = 288 & & height > = 216 )
return VIDEOSIZE_288_216 ;
if ( width > = 256 & & height > = 192 )
return VIDEOSIZE_256_192 ;
if ( width > = 224 & & height > = 168 )
return VIDEOSIZE_224_168 ;
if ( width > = 192 & & height > = 144 )
return VIDEOSIZE_192_144 ;
if ( width > = STV_IMAGE_QCIF_COLS & & height > = STV_IMAGE_QCIF_ROWS )
return VIDEOSIZE_QCIF ;
return - 1 ;
}
/******************************************************************************
*
* SetVideoSize
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int set_vw_size ( struct camera_data * cam , int size )
{
int retval = 0 ;
cam - > params . vp_params . video_size = size ;
switch ( size ) {
case VIDEOSIZE_VGA :
DBG ( " Setting size to VGA \n " ) ;
cam - > params . roi . width = STV_IMAGE_VGA_COLS ;
cam - > params . roi . height = STV_IMAGE_VGA_ROWS ;
2010-09-19 13:00:54 +04:00
cam - > width = STV_IMAGE_VGA_COLS ;
cam - > height = STV_IMAGE_VGA_ROWS ;
2006-02-27 06:09:05 +03:00
break ;
case VIDEOSIZE_CIF :
DBG ( " Setting size to CIF \n " ) ;
cam - > params . roi . width = STV_IMAGE_CIF_COLS ;
cam - > params . roi . height = STV_IMAGE_CIF_ROWS ;
2010-09-19 13:00:54 +04:00
cam - > width = STV_IMAGE_CIF_COLS ;
cam - > height = STV_IMAGE_CIF_ROWS ;
2006-02-27 06:09:05 +03:00
break ;
case VIDEOSIZE_QVGA :
DBG ( " Setting size to QVGA \n " ) ;
cam - > params . roi . width = STV_IMAGE_QVGA_COLS ;
cam - > params . roi . height = STV_IMAGE_QVGA_ROWS ;
2010-09-19 13:00:54 +04:00
cam - > width = STV_IMAGE_QVGA_COLS ;
cam - > height = STV_IMAGE_QVGA_ROWS ;
2006-02-27 06:09:05 +03:00
break ;
case VIDEOSIZE_288_216 :
cam - > params . roi . width = 288 ;
cam - > params . roi . height = 216 ;
2010-09-19 13:00:54 +04:00
cam - > width = 288 ;
cam - > height = 216 ;
2006-02-27 06:09:05 +03:00
break ;
case VIDEOSIZE_256_192 :
2010-09-19 13:00:54 +04:00
cam - > width = 256 ;
cam - > height = 192 ;
2006-02-27 06:09:05 +03:00
cam - > params . roi . width = 256 ;
cam - > params . roi . height = 192 ;
break ;
case VIDEOSIZE_224_168 :
2010-09-19 13:00:54 +04:00
cam - > width = 224 ;
cam - > height = 168 ;
2006-02-27 06:09:05 +03:00
cam - > params . roi . width = 224 ;
cam - > params . roi . height = 168 ;
break ;
case VIDEOSIZE_192_144 :
2010-09-19 13:00:54 +04:00
cam - > width = 192 ;
cam - > height = 144 ;
2006-02-27 06:09:05 +03:00
cam - > params . roi . width = 192 ;
cam - > params . roi . height = 144 ;
break ;
case VIDEOSIZE_QCIF :
DBG ( " Setting size to QCIF \n " ) ;
cam - > params . roi . width = STV_IMAGE_QCIF_COLS ;
cam - > params . roi . height = STV_IMAGE_QCIF_ROWS ;
2010-09-19 13:00:54 +04:00
cam - > width = STV_IMAGE_QCIF_COLS ;
cam - > height = STV_IMAGE_QCIF_ROWS ;
2006-02-27 06:09:05 +03:00
break ;
default :
retval = - EINVAL ;
}
return retval ;
}
/******************************************************************************
*
* configure_sensor
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int configure_sensor ( struct camera_data * cam ,
int req_width , int req_height )
{
int retval ;
switch ( cam - > params . version . sensor_flags ) {
case CPIA2_VP_SENSOR_FLAGS_404 :
case CPIA2_VP_SENSOR_FLAGS_407 :
case CPIA2_VP_SENSOR_FLAGS_409 :
case CPIA2_VP_SENSOR_FLAGS_410 :
retval = config_sensor_410 ( cam , req_width , req_height ) ;
break ;
case CPIA2_VP_SENSOR_FLAGS_500 :
retval = config_sensor_500 ( cam , req_width , req_height ) ;
break ;
default :
return - EINVAL ;
}
return retval ;
}
/******************************************************************************
*
* config_sensor_410
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int config_sensor_410 ( struct camera_data * cam ,
int req_width , int req_height )
{
struct cpia2_command cmd ;
int i = 0 ;
int image_size ;
int image_type ;
int width = req_width ;
int height = req_height ;
/***
* Make sure size doesn ' t exceed CIF .
* * */
if ( width > STV_IMAGE_CIF_COLS )
width = STV_IMAGE_CIF_COLS ;
if ( height > STV_IMAGE_CIF_ROWS )
height = STV_IMAGE_CIF_ROWS ;
image_size = cpia2_match_video_size ( width , height ) ;
DBG ( " Config 410: width = %d, height = %d \n " , width , height ) ;
DBG ( " Image size returned is %d \n " , image_size ) ;
if ( image_size > = 0 ) {
set_vw_size ( cam , image_size ) ;
width = cam - > params . roi . width ;
height = cam - > params . roi . height ;
DBG ( " After set_vw_size(), width = %d, height = %d \n " ,
width , height ) ;
if ( width < = 176 & & height < = 144 ) {
DBG ( " image type = VIDEOSIZE_QCIF \n " ) ;
image_type = VIDEOSIZE_QCIF ;
}
else if ( width < = 320 & & height < = 240 ) {
DBG ( " image type = VIDEOSIZE_QVGA \n " ) ;
image_type = VIDEOSIZE_QVGA ;
}
else {
DBG ( " image type = VIDEOSIZE_CIF \n " ) ;
image_type = VIDEOSIZE_CIF ;
}
} else {
ERR ( " ConfigSensor410 failed \n " ) ;
return - EINVAL ;
}
cmd . req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC ;
cmd . direction = TRANSFER_WRITE ;
/* VC Format */
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_FORMAT ;
if ( image_type = = VIDEOSIZE_CIF ) {
cmd . buffer . registers [ i + + ] . value =
( u8 ) ( CPIA2_VC_VC_FORMAT_UFIRST |
CPIA2_VC_VC_FORMAT_SHORTLINE ) ;
} else {
cmd . buffer . registers [ i + + ] . value =
( u8 ) CPIA2_VC_VC_FORMAT_UFIRST ;
}
/* VC Clocks */
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_CLOCKS ;
if ( image_type = = VIDEOSIZE_QCIF ) {
if ( cam - > params . pnp_id . device_type = = DEVICE_STV_672 ) {
cmd . buffer . registers [ i + + ] . value =
( u8 ) ( CPIA2_VC_VC_672_CLOCKS_CIF_DIV_BY_3 |
CPIA2_VC_VC_672_CLOCKS_SCALING |
CPIA2_VC_VC_CLOCKS_LOGDIV2 ) ;
DBG ( " VC_Clocks (0xc4) should be B \n " ) ;
}
else {
cmd . buffer . registers [ i + + ] . value =
( u8 ) ( CPIA2_VC_VC_676_CLOCKS_CIF_DIV_BY_3 |
CPIA2_VC_VC_CLOCKS_LOGDIV2 ) ;
}
} else {
if ( cam - > params . pnp_id . device_type = = DEVICE_STV_672 ) {
cmd . buffer . registers [ i + + ] . value =
( u8 ) ( CPIA2_VC_VC_672_CLOCKS_CIF_DIV_BY_3 |
CPIA2_VC_VC_CLOCKS_LOGDIV0 ) ;
}
else {
cmd . buffer . registers [ i + + ] . value =
( u8 ) ( CPIA2_VC_VC_676_CLOCKS_CIF_DIV_BY_3 |
CPIA2_VC_VC_676_CLOCKS_SCALING |
CPIA2_VC_VC_CLOCKS_LOGDIV0 ) ;
}
}
DBG ( " VC_Clocks (0xc4) = 0x%0X \n " , cmd . buffer . registers [ i - 1 ] . value ) ;
/* Input reqWidth from VC */
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_IHSIZE_LO ;
if ( image_type = = VIDEOSIZE_QCIF )
cmd . buffer . registers [ i + + ] . value =
( u8 ) ( STV_IMAGE_QCIF_COLS / 4 ) ;
else
cmd . buffer . registers [ i + + ] . value =
( u8 ) ( STV_IMAGE_CIF_COLS / 4 ) ;
/* Timings */
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_XLIM_HI ;
if ( image_type = = VIDEOSIZE_QCIF )
cmd . buffer . registers [ i + + ] . value = ( u8 ) 0 ;
else
cmd . buffer . registers [ i + + ] . value = ( u8 ) 1 ;
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_XLIM_LO ;
if ( image_type = = VIDEOSIZE_QCIF )
cmd . buffer . registers [ i + + ] . value = ( u8 ) 208 ;
else
cmd . buffer . registers [ i + + ] . value = ( u8 ) 160 ;
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_YLIM_HI ;
if ( image_type = = VIDEOSIZE_QCIF )
cmd . buffer . registers [ i + + ] . value = ( u8 ) 0 ;
else
cmd . buffer . registers [ i + + ] . value = ( u8 ) 1 ;
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_YLIM_LO ;
if ( image_type = = VIDEOSIZE_QCIF )
cmd . buffer . registers [ i + + ] . value = ( u8 ) 160 ;
else
cmd . buffer . registers [ i + + ] . value = ( u8 ) 64 ;
/* Output Image Size */
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_OHSIZE ;
cmd . buffer . registers [ i + + ] . value = cam - > params . roi . width / 4 ;
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_OVSIZE ;
cmd . buffer . registers [ i + + ] . value = cam - > params . roi . height / 4 ;
/* Cropping */
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_HCROP ;
if ( image_type = = VIDEOSIZE_QCIF )
cmd . buffer . registers [ i + + ] . value =
( u8 ) ( ( ( STV_IMAGE_QCIF_COLS / 4 ) - ( width / 4 ) ) / 2 ) ;
else
cmd . buffer . registers [ i + + ] . value =
( u8 ) ( ( ( STV_IMAGE_CIF_COLS / 4 ) - ( width / 4 ) ) / 2 ) ;
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_VCROP ;
if ( image_type = = VIDEOSIZE_QCIF )
cmd . buffer . registers [ i + + ] . value =
( u8 ) ( ( ( STV_IMAGE_QCIF_ROWS / 4 ) - ( height / 4 ) ) / 2 ) ;
else
cmd . buffer . registers [ i + + ] . value =
( u8 ) ( ( ( STV_IMAGE_CIF_ROWS / 4 ) - ( height / 4 ) ) / 2 ) ;
/* Scaling registers (defaults) */
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_HPHASE ;
cmd . buffer . registers [ i + + ] . value = ( u8 ) 0 ;
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_VPHASE ;
cmd . buffer . registers [ i + + ] . value = ( u8 ) 0 ;
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_HISPAN ;
cmd . buffer . registers [ i + + ] . value = ( u8 ) 31 ;
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_VISPAN ;
cmd . buffer . registers [ i + + ] . value = ( u8 ) 31 ;
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_HICROP ;
cmd . buffer . registers [ i + + ] . value = ( u8 ) 0 ;
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_VICROP ;
cmd . buffer . registers [ i + + ] . value = ( u8 ) 0 ;
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_HFRACT ;
cmd . buffer . registers [ i + + ] . value = ( u8 ) 0x81 ; /* = 8/1 = 8 (HIBYTE/LOBYTE) */
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_VFRACT ;
cmd . buffer . registers [ i + + ] . value = ( u8 ) 0x81 ; /* = 8/1 = 8 (HIBYTE/LOBYTE) */
cmd . reg_count = i ;
cpia2_send_command ( cam , & cmd ) ;
return i ;
}
/******************************************************************************
*
* config_sensor_500 ( cam )
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int config_sensor_500 ( struct camera_data * cam ,
int req_width , int req_height )
{
struct cpia2_command cmd ;
int i = 0 ;
int image_size = VIDEOSIZE_CIF ;
int image_type = VIDEOSIZE_VGA ;
int width = req_width ;
int height = req_height ;
unsigned int device = cam - > params . pnp_id . device_type ;
image_size = cpia2_match_video_size ( width , height ) ;
if ( width > STV_IMAGE_CIF_COLS | | height > STV_IMAGE_CIF_ROWS )
image_type = VIDEOSIZE_VGA ;
else if ( width > STV_IMAGE_QVGA_COLS | | height > STV_IMAGE_QVGA_ROWS )
image_type = VIDEOSIZE_CIF ;
else if ( width > STV_IMAGE_QCIF_COLS | | height > STV_IMAGE_QCIF_ROWS )
image_type = VIDEOSIZE_QVGA ;
else
image_type = VIDEOSIZE_QCIF ;
if ( image_size > = 0 ) {
set_vw_size ( cam , image_size ) ;
width = cam - > params . roi . width ;
height = cam - > params . roi . height ;
} else {
ERR ( " ConfigSensor500 failed \n " ) ;
return - EINVAL ;
}
DBG ( " image_size = %d, width = %d, height = %d, type = %d \n " ,
image_size , width , height , image_type ) ;
cmd . req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC ;
cmd . direction = TRANSFER_WRITE ;
i = 0 ;
/* VC Format */
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_FORMAT ;
cmd . buffer . registers [ i ] . value = ( u8 ) CPIA2_VC_VC_FORMAT_UFIRST ;
if ( image_type = = VIDEOSIZE_QCIF )
cmd . buffer . registers [ i ] . value | = ( u8 ) CPIA2_VC_VC_FORMAT_DECIMATING ;
i + + ;
/* VC Clocks */
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_CLOCKS ;
if ( device = = DEVICE_STV_672 ) {
if ( image_type = = VIDEOSIZE_VGA )
cmd . buffer . registers [ i ] . value =
( u8 ) CPIA2_VC_VC_CLOCKS_LOGDIV1 ;
else
cmd . buffer . registers [ i ] . value =
( u8 ) ( CPIA2_VC_VC_672_CLOCKS_SCALING |
CPIA2_VC_VC_CLOCKS_LOGDIV3 ) ;
} else {
if ( image_type = = VIDEOSIZE_VGA )
cmd . buffer . registers [ i ] . value =
( u8 ) CPIA2_VC_VC_CLOCKS_LOGDIV0 ;
else
cmd . buffer . registers [ i ] . value =
( u8 ) ( CPIA2_VC_VC_676_CLOCKS_SCALING |
CPIA2_VC_VC_CLOCKS_LOGDIV2 ) ;
}
i + + ;
DBG ( " VC_CLOCKS = 0x%X \n " , cmd . buffer . registers [ i - 1 ] . value ) ;
/* Input width from VP */
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_IHSIZE_LO ;
if ( image_type = = VIDEOSIZE_VGA )
cmd . buffer . registers [ i ] . value =
( u8 ) ( STV_IMAGE_VGA_COLS / 4 ) ;
else
cmd . buffer . registers [ i ] . value =
( u8 ) ( STV_IMAGE_QVGA_COLS / 4 ) ;
i + + ;
DBG ( " Input width = %d \n " , cmd . buffer . registers [ i - 1 ] . value ) ;
/* Timings */
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_XLIM_HI ;
if ( image_type = = VIDEOSIZE_VGA )
cmd . buffer . registers [ i + + ] . value = ( u8 ) 2 ;
else
cmd . buffer . registers [ i + + ] . value = ( u8 ) 1 ;
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_XLIM_LO ;
if ( image_type = = VIDEOSIZE_VGA )
cmd . buffer . registers [ i + + ] . value = ( u8 ) 250 ;
else if ( image_type = = VIDEOSIZE_QVGA )
cmd . buffer . registers [ i + + ] . value = ( u8 ) 125 ;
else
cmd . buffer . registers [ i + + ] . value = ( u8 ) 160 ;
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_YLIM_HI ;
if ( image_type = = VIDEOSIZE_VGA )
cmd . buffer . registers [ i + + ] . value = ( u8 ) 2 ;
else
cmd . buffer . registers [ i + + ] . value = ( u8 ) 1 ;
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_YLIM_LO ;
if ( image_type = = VIDEOSIZE_VGA )
cmd . buffer . registers [ i + + ] . value = ( u8 ) 12 ;
else if ( image_type = = VIDEOSIZE_QVGA )
cmd . buffer . registers [ i + + ] . value = ( u8 ) 64 ;
else
cmd . buffer . registers [ i + + ] . value = ( u8 ) 6 ;
/* Output Image Size */
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_OHSIZE ;
if ( image_type = = VIDEOSIZE_QCIF )
cmd . buffer . registers [ i + + ] . value = STV_IMAGE_CIF_COLS / 4 ;
else
cmd . buffer . registers [ i + + ] . value = width / 4 ;
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_OVSIZE ;
if ( image_type = = VIDEOSIZE_QCIF )
cmd . buffer . registers [ i + + ] . value = STV_IMAGE_CIF_ROWS / 4 ;
else
cmd . buffer . registers [ i + + ] . value = height / 4 ;
/* Cropping */
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_HCROP ;
if ( image_type = = VIDEOSIZE_VGA )
cmd . buffer . registers [ i + + ] . value =
( u8 ) ( ( ( STV_IMAGE_VGA_COLS / 4 ) - ( width / 4 ) ) / 2 ) ;
else if ( image_type = = VIDEOSIZE_QVGA )
cmd . buffer . registers [ i + + ] . value =
( u8 ) ( ( ( STV_IMAGE_QVGA_COLS / 4 ) - ( width / 4 ) ) / 2 ) ;
else if ( image_type = = VIDEOSIZE_CIF )
cmd . buffer . registers [ i + + ] . value =
( u8 ) ( ( ( STV_IMAGE_CIF_COLS / 4 ) - ( width / 4 ) ) / 2 ) ;
else /*if (image_type == VIDEOSIZE_QCIF)*/
cmd . buffer . registers [ i + + ] . value =
( u8 ) ( ( ( STV_IMAGE_QCIF_COLS / 4 ) - ( width / 4 ) ) / 2 ) ;
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_VCROP ;
if ( image_type = = VIDEOSIZE_VGA )
cmd . buffer . registers [ i + + ] . value =
( u8 ) ( ( ( STV_IMAGE_VGA_ROWS / 4 ) - ( height / 4 ) ) / 2 ) ;
else if ( image_type = = VIDEOSIZE_QVGA )
cmd . buffer . registers [ i + + ] . value =
( u8 ) ( ( ( STV_IMAGE_QVGA_ROWS / 4 ) - ( height / 4 ) ) / 2 ) ;
else if ( image_type = = VIDEOSIZE_CIF )
cmd . buffer . registers [ i + + ] . value =
( u8 ) ( ( ( STV_IMAGE_CIF_ROWS / 4 ) - ( height / 4 ) ) / 2 ) ;
else /*if (image_type == VIDEOSIZE_QCIF)*/
cmd . buffer . registers [ i + + ] . value =
( u8 ) ( ( ( STV_IMAGE_QCIF_ROWS / 4 ) - ( height / 4 ) ) / 2 ) ;
/* Scaling registers (defaults) */
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_HPHASE ;
if ( image_type = = VIDEOSIZE_CIF | | image_type = = VIDEOSIZE_QCIF )
cmd . buffer . registers [ i + + ] . value = ( u8 ) 36 ;
else
cmd . buffer . registers [ i + + ] . value = ( u8 ) 0 ;
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_VPHASE ;
if ( image_type = = VIDEOSIZE_CIF | | image_type = = VIDEOSIZE_QCIF )
cmd . buffer . registers [ i + + ] . value = ( u8 ) 32 ;
else
cmd . buffer . registers [ i + + ] . value = ( u8 ) 0 ;
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_HISPAN ;
if ( image_type = = VIDEOSIZE_CIF | | image_type = = VIDEOSIZE_QCIF )
cmd . buffer . registers [ i + + ] . value = ( u8 ) 26 ;
else
cmd . buffer . registers [ i + + ] . value = ( u8 ) 31 ;
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_VISPAN ;
if ( image_type = = VIDEOSIZE_CIF | | image_type = = VIDEOSIZE_QCIF )
cmd . buffer . registers [ i + + ] . value = ( u8 ) 21 ;
else
cmd . buffer . registers [ i + + ] . value = ( u8 ) 31 ;
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_HICROP ;
cmd . buffer . registers [ i + + ] . value = ( u8 ) 0 ;
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_VICROP ;
cmd . buffer . registers [ i + + ] . value = ( u8 ) 0 ;
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_HFRACT ;
if ( image_type = = VIDEOSIZE_CIF | | image_type = = VIDEOSIZE_QCIF )
cmd . buffer . registers [ i + + ] . value = ( u8 ) 0x2B ; /* 2/11 */
else
cmd . buffer . registers [ i + + ] . value = ( u8 ) 0x81 ; /* 8/1 */
cmd . buffer . registers [ i ] . index = CPIA2_VC_VC_VFRACT ;
if ( image_type = = VIDEOSIZE_CIF | | image_type = = VIDEOSIZE_QCIF )
cmd . buffer . registers [ i + + ] . value = ( u8 ) 0x13 ; /* 1/3 */
else
cmd . buffer . registers [ i + + ] . value = ( u8 ) 0x81 ; /* 8/1 */
cmd . reg_count = i ;
cpia2_send_command ( cam , & cmd ) ;
return i ;
}
/******************************************************************************
*
* setallproperties
*
* This sets all user changeable properties to the values in cam - > params .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-09-04 10:33:43 +04:00
static int set_all_properties ( struct camera_data * cam )
2006-02-27 06:09:05 +03:00
{
/**
* Don ' t set target_kb here , it will be set later .
* framerate and user_mode were already set ( set_default_user_mode ) .
* */
cpia2_usb_change_streaming_alternate ( cam ,
cam - > params . camera_state . stream_mode ) ;
cpia2_do_command ( cam ,
CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION ,
TRANSFER_WRITE , cam - > params . vp_params . gpio_direction ) ;
cpia2_do_command ( cam , CPIA2_CMD_SET_VC_MP_GPIO_DATA , TRANSFER_WRITE ,
cam - > params . vp_params . gpio_data ) ;
2012-04-29 15:44:44 +04:00
v4l2_ctrl_handler_setup ( & cam - > hdl ) ;
2006-02-27 06:09:05 +03:00
wake_system ( cam ) ;
set_lowlight_boost ( cam ) ;
return 0 ;
}
/******************************************************************************
*
* cpia2_save_camera_state
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void cpia2_save_camera_state ( struct camera_data * cam )
{
cpia2_do_command ( cam , CPIA2_CMD_GET_USER_EFFECTS , TRANSFER_READ , 0 ) ;
cpia2_do_command ( cam , CPIA2_CMD_GET_VC_MP_GPIO_DIRECTION , TRANSFER_READ ,
0 ) ;
cpia2_do_command ( cam , CPIA2_CMD_GET_VC_MP_GPIO_DATA , TRANSFER_READ , 0 ) ;
/* Don't get framerate or target_kb. Trust the values we already have */
}
/******************************************************************************
*
* cpia2_set_flicker_mode
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int cpia2_set_flicker_mode ( struct camera_data * cam , int mode )
{
unsigned char cam_reg ;
int err = 0 ;
if ( cam - > params . pnp_id . device_type ! = DEVICE_STV_672 )
return - EINVAL ;
/* Set the appropriate bits in FLICKER_MODES, preserving the rest */
if ( ( err = cpia2_do_command ( cam , CPIA2_CMD_GET_FLICKER_MODES ,
TRANSFER_READ , 0 ) ) )
return err ;
cam_reg = cam - > params . flicker_control . cam_register ;
switch ( mode ) {
case NEVER_FLICKER :
cam_reg | = CPIA2_VP_FLICKER_MODES_NEVER_FLICKER ;
cam_reg & = ~ CPIA2_VP_FLICKER_MODES_50HZ ;
break ;
case FLICKER_60 :
cam_reg & = ~ CPIA2_VP_FLICKER_MODES_NEVER_FLICKER ;
cam_reg & = ~ CPIA2_VP_FLICKER_MODES_50HZ ;
break ;
case FLICKER_50 :
cam_reg & = ~ CPIA2_VP_FLICKER_MODES_NEVER_FLICKER ;
cam_reg | = CPIA2_VP_FLICKER_MODES_50HZ ;
break ;
default :
return - EINVAL ;
}
if ( ( err = cpia2_do_command ( cam , CPIA2_CMD_SET_FLICKER_MODES ,
TRANSFER_WRITE , cam_reg ) ) )
return err ;
/* Set the appropriate bits in EXP_MODES, preserving the rest */
if ( ( err = cpia2_do_command ( cam , CPIA2_CMD_GET_VP_EXP_MODES ,
TRANSFER_READ , 0 ) ) )
return err ;
cam_reg = cam - > params . vp_params . exposure_modes ;
if ( mode = = NEVER_FLICKER ) {
cam_reg | = CPIA2_VP_EXPOSURE_MODES_INHIBIT_FLICKER ;
} else {
cam_reg & = ~ CPIA2_VP_EXPOSURE_MODES_INHIBIT_FLICKER ;
}
if ( ( err = cpia2_do_command ( cam , CPIA2_CMD_SET_VP_EXP_MODES ,
TRANSFER_WRITE , cam_reg ) ) )
return err ;
if ( ( err = cpia2_do_command ( cam , CPIA2_CMD_REHASH_VP4 ,
TRANSFER_WRITE , 1 ) ) )
return err ;
switch ( mode ) {
case NEVER_FLICKER :
case FLICKER_60 :
case FLICKER_50 :
cam - > params . flicker_control . flicker_mode_req = mode ;
break ;
default :
err = - EINVAL ;
}
return err ;
}
/******************************************************************************
*
* cpia2_set_property_flip
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void cpia2_set_property_flip ( struct camera_data * cam , int prop_val )
{
unsigned char cam_reg ;
cpia2_do_command ( cam , CPIA2_CMD_GET_USER_EFFECTS , TRANSFER_READ , 0 ) ;
cam_reg = cam - > params . vp_params . user_effects ;
if ( prop_val )
{
cam_reg | = CPIA2_VP_USER_EFFECTS_FLIP ;
}
else
{
cam_reg & = ~ CPIA2_VP_USER_EFFECTS_FLIP ;
}
2012-04-29 15:44:44 +04:00
cam - > params . vp_params . user_effects = cam_reg ;
2006-02-27 06:09:05 +03:00
cpia2_do_command ( cam , CPIA2_CMD_SET_USER_EFFECTS , TRANSFER_WRITE ,
cam_reg ) ;
}
/******************************************************************************
*
* cpia2_set_property_mirror
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void cpia2_set_property_mirror ( struct camera_data * cam , int prop_val )
{
unsigned char cam_reg ;
cpia2_do_command ( cam , CPIA2_CMD_GET_USER_EFFECTS , TRANSFER_READ , 0 ) ;
cam_reg = cam - > params . vp_params . user_effects ;
if ( prop_val )
{
cam_reg | = CPIA2_VP_USER_EFFECTS_MIRROR ;
}
else
{
cam_reg & = ~ CPIA2_VP_USER_EFFECTS_MIRROR ;
}
2012-04-29 15:44:44 +04:00
cam - > params . vp_params . user_effects = cam_reg ;
2006-02-27 06:09:05 +03:00
cpia2_do_command ( cam , CPIA2_CMD_SET_USER_EFFECTS , TRANSFER_WRITE ,
cam_reg ) ;
}
/******************************************************************************
*
* cpia2_set_gpio
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int cpia2_set_gpio ( struct camera_data * cam , unsigned char setting )
{
int ret ;
/* Set the microport direction (register 0x90, should be defined
* already ) to 1 ( user output ) , and set the microport data ( 0x91 ) to
* the value in the ioctl argument .
*/
ret = cpia2_do_command ( cam ,
CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION ,
CPIA2_VC_MP_DIR_OUTPUT ,
255 ) ;
if ( ret < 0 )
return ret ;
cam - > params . vp_params . gpio_direction = 255 ;
ret = cpia2_do_command ( cam ,
CPIA2_CMD_SET_VC_MP_GPIO_DATA ,
CPIA2_VC_MP_DIR_OUTPUT ,
setting ) ;
if ( ret < 0 )
return ret ;
cam - > params . vp_params . gpio_data = setting ;
return 0 ;
}
/******************************************************************************
*
* cpia2_set_fps
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int cpia2_set_fps ( struct camera_data * cam , int framerate )
{
int retval ;
switch ( framerate ) {
case CPIA2_VP_FRAMERATE_30 :
case CPIA2_VP_FRAMERATE_25 :
if ( cam - > params . pnp_id . device_type = = DEVICE_STV_672 & &
cam - > params . version . sensor_flags = =
CPIA2_VP_SENSOR_FLAGS_500 ) {
return - EINVAL ;
}
2020-08-24 01:36:59 +03:00
fallthrough ;
2006-02-27 06:09:05 +03:00
case CPIA2_VP_FRAMERATE_15 :
case CPIA2_VP_FRAMERATE_12_5 :
case CPIA2_VP_FRAMERATE_7_5 :
case CPIA2_VP_FRAMERATE_6_25 :
break ;
default :
return - EINVAL ;
}
if ( cam - > params . pnp_id . device_type = = DEVICE_STV_672 & &
framerate = = CPIA2_VP_FRAMERATE_15 )
framerate = 0 ; /* Work around bug in VP4 */
retval = cpia2_do_command ( cam ,
CPIA2_CMD_FRAMERATE_REQ ,
TRANSFER_WRITE ,
framerate ) ;
if ( retval = = 0 )
cam - > params . vp_params . frame_rate = framerate ;
return retval ;
}
/******************************************************************************
*
* cpia2_set_brightness
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void cpia2_set_brightness ( struct camera_data * cam , unsigned char value )
{
/***
* Don ' t let the register be set to zero - bug in VP4 - flash of full
* brightness
* * */
if ( cam - > params . pnp_id . device_type = = DEVICE_STV_672 & & value = = 0 )
value + + ;
DBG ( " Setting brightness to %d (0x%0x) \n " , value , value ) ;
2012-04-29 15:44:44 +04:00
cpia2_do_command ( cam , CPIA2_CMD_SET_VP_BRIGHTNESS , TRANSFER_WRITE , value ) ;
2006-02-27 06:09:05 +03:00
}
/******************************************************************************
*
* cpia2_set_contrast
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void cpia2_set_contrast ( struct camera_data * cam , unsigned char value )
{
DBG ( " Setting contrast to %d (0x%0x) \n " , value , value ) ;
cpia2_do_command ( cam , CPIA2_CMD_SET_CONTRAST , TRANSFER_WRITE , value ) ;
}
/******************************************************************************
*
* cpia2_set_saturation
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void cpia2_set_saturation ( struct camera_data * cam , unsigned char value )
{
DBG ( " Setting saturation to %d (0x%0x) \n " , value , value ) ;
cpia2_do_command ( cam , CPIA2_CMD_SET_VP_SATURATION , TRANSFER_WRITE , value ) ;
}
/******************************************************************************
*
* wake_system
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-09-04 10:33:43 +04:00
static void wake_system ( struct camera_data * cam )
2006-02-27 06:09:05 +03:00
{
cpia2_do_command ( cam , CPIA2_CMD_SET_WAKEUP , TRANSFER_WRITE , 0 ) ;
}
/******************************************************************************
*
* set_lowlight_boost
*
* Valid for STV500 sensor only
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-09-04 10:33:43 +04:00
static void set_lowlight_boost ( struct camera_data * cam )
2006-02-27 06:09:05 +03:00
{
struct cpia2_command cmd ;
if ( cam - > params . pnp_id . device_type ! = DEVICE_STV_672 | |
cam - > params . version . sensor_flags ! = CPIA2_VP_SENSOR_FLAGS_500 )
return ;
cmd . direction = TRANSFER_WRITE ;
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP ;
cmd . reg_count = 3 ;
cmd . start = CPIA2_VP_RAM_ADDR_H ;
cmd . buffer . block_data [ 0 ] = 0 ; /* High byte of address to write to */
cmd . buffer . block_data [ 1 ] = 0x59 ; /* Low byte of address to write to */
cmd . buffer . block_data [ 2 ] = 0 ; /* High byte of data to write */
cpia2_send_command ( cam , & cmd ) ;
if ( cam - > params . vp_params . lowlight_boost ) {
cmd . buffer . block_data [ 0 ] = 0x02 ; /* Low byte data to write */
} else {
cmd . buffer . block_data [ 0 ] = 0x06 ;
}
cmd . start = CPIA2_VP_RAM_DATA ;
cmd . reg_count = 1 ;
cpia2_send_command ( cam , & cmd ) ;
/* Rehash the VP4 values */
cpia2_do_command ( cam , CPIA2_CMD_REHASH_VP4 , TRANSFER_WRITE , 1 ) ;
}
/******************************************************************************
*
* cpia2_set_format
*
* Assumes that new size is already set in param struct .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void cpia2_set_format ( struct camera_data * cam )
{
cam - > flush = true ;
cpia2_usb_stream_pause ( cam ) ;
/* reset camera to new size */
cpia2_set_low_power ( cam ) ;
cpia2_reset_camera ( cam ) ;
cam - > flush = false ;
cpia2_dbg_dump_registers ( cam ) ;
cpia2_usb_stream_resume ( cam ) ;
}
/******************************************************************************
*
* cpia2_dbg_dump_registers
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void cpia2_dbg_dump_registers ( struct camera_data * cam )
{
# ifdef _CPIA2_DEBUG_
struct cpia2_command cmd ;
if ( ! ( debugs_on & DEBUG_DUMP_REGS ) )
return ;
cmd . direction = TRANSFER_READ ;
/* Start with bank 0 (SYSTEM) */
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM ;
cmd . reg_count = 3 ;
cmd . start = 0 ;
cpia2_send_command ( cam , & cmd ) ;
printk ( KERN_DEBUG " System Device Hi = 0x%X \n " ,
cmd . buffer . block_data [ 0 ] ) ;
printk ( KERN_DEBUG " System Device Lo = 0x%X \n " ,
cmd . buffer . block_data [ 1 ] ) ;
printk ( KERN_DEBUG " System_system control = 0x%X \n " ,
cmd . buffer . block_data [ 2 ] ) ;
/* Bank 1 (VC) */
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC ;
cmd . reg_count = 4 ;
cmd . start = 0x80 ;
cpia2_send_command ( cam , & cmd ) ;
printk ( KERN_DEBUG " ASIC_ID = 0x%X \n " ,
cmd . buffer . block_data [ 0 ] ) ;
printk ( KERN_DEBUG " ASIC_REV = 0x%X \n " ,
cmd . buffer . block_data [ 1 ] ) ;
printk ( KERN_DEBUG " PW_CONTRL = 0x%X \n " ,
cmd . buffer . block_data [ 2 ] ) ;
printk ( KERN_DEBUG " WAKEUP = 0x%X \n " ,
cmd . buffer . block_data [ 3 ] ) ;
cmd . start = 0xA0 ; /* ST_CTRL */
cmd . reg_count = 1 ;
cpia2_send_command ( cam , & cmd ) ;
printk ( KERN_DEBUG " Stream ctrl = 0x%X \n " ,
cmd . buffer . block_data [ 0 ] ) ;
cmd . start = 0xA4 ; /* Stream status */
cpia2_send_command ( cam , & cmd ) ;
printk ( KERN_DEBUG " Stream status = 0x%X \n " ,
cmd . buffer . block_data [ 0 ] ) ;
cmd . start = 0xA8 ; /* USB status */
cmd . reg_count = 3 ;
cpia2_send_command ( cam , & cmd ) ;
printk ( KERN_DEBUG " USB_CTRL = 0x%X \n " ,
cmd . buffer . block_data [ 0 ] ) ;
printk ( KERN_DEBUG " USB_STRM = 0x%X \n " ,
cmd . buffer . block_data [ 1 ] ) ;
printk ( KERN_DEBUG " USB_STATUS = 0x%X \n " ,
cmd . buffer . block_data [ 2 ] ) ;
cmd . start = 0xAF ; /* USB settings */
cmd . reg_count = 1 ;
cpia2_send_command ( cam , & cmd ) ;
printk ( KERN_DEBUG " USB settings = 0x%X \n " ,
cmd . buffer . block_data [ 0 ] ) ;
cmd . start = 0xC0 ; /* VC stuff */
cmd . reg_count = 26 ;
cpia2_send_command ( cam , & cmd ) ;
printk ( KERN_DEBUG " VC Control = 0x%0X \n " ,
cmd . buffer . block_data [ 0 ] ) ;
printk ( KERN_DEBUG " VC Format = 0x%0X \n " ,
cmd . buffer . block_data [ 3 ] ) ;
printk ( KERN_DEBUG " VC Clocks = 0x%0X \n " ,
cmd . buffer . block_data [ 4 ] ) ;
printk ( KERN_DEBUG " VC IHSize = 0x%0X \n " ,
cmd . buffer . block_data [ 5 ] ) ;
printk ( KERN_DEBUG " VC Xlim Hi = 0x%0X \n " ,
cmd . buffer . block_data [ 6 ] ) ;
printk ( KERN_DEBUG " VC XLim Lo = 0x%0X \n " ,
cmd . buffer . block_data [ 7 ] ) ;
printk ( KERN_DEBUG " VC YLim Hi = 0x%0X \n " ,
cmd . buffer . block_data [ 8 ] ) ;
printk ( KERN_DEBUG " VC YLim Lo = 0x%0X \n " ,
cmd . buffer . block_data [ 9 ] ) ;
printk ( KERN_DEBUG " VC OHSize = 0x%0X \n " ,
cmd . buffer . block_data [ 10 ] ) ;
printk ( KERN_DEBUG " VC OVSize = 0x%0X \n " ,
cmd . buffer . block_data [ 11 ] ) ;
printk ( KERN_DEBUG " VC HCrop = 0x%0X \n " ,
cmd . buffer . block_data [ 12 ] ) ;
printk ( KERN_DEBUG " VC VCrop = 0x%0X \n " ,
cmd . buffer . block_data [ 13 ] ) ;
printk ( KERN_DEBUG " VC HPhase = 0x%0X \n " ,
cmd . buffer . block_data [ 14 ] ) ;
printk ( KERN_DEBUG " VC VPhase = 0x%0X \n " ,
cmd . buffer . block_data [ 15 ] ) ;
printk ( KERN_DEBUG " VC HIspan = 0x%0X \n " ,
cmd . buffer . block_data [ 16 ] ) ;
printk ( KERN_DEBUG " VC VIspan = 0x%0X \n " ,
cmd . buffer . block_data [ 17 ] ) ;
printk ( KERN_DEBUG " VC HiCrop = 0x%0X \n " ,
cmd . buffer . block_data [ 18 ] ) ;
printk ( KERN_DEBUG " VC ViCrop = 0x%0X \n " ,
cmd . buffer . block_data [ 19 ] ) ;
printk ( KERN_DEBUG " VC HiFract = 0x%0X \n " ,
cmd . buffer . block_data [ 20 ] ) ;
printk ( KERN_DEBUG " VC ViFract = 0x%0X \n " ,
cmd . buffer . block_data [ 21 ] ) ;
printk ( KERN_DEBUG " VC JPeg Opt = 0x%0X \n " ,
cmd . buffer . block_data [ 22 ] ) ;
printk ( KERN_DEBUG " VC Creep Per = 0x%0X \n " ,
cmd . buffer . block_data [ 23 ] ) ;
printk ( KERN_DEBUG " VC User Sq. = 0x%0X \n " ,
cmd . buffer . block_data [ 24 ] ) ;
printk ( KERN_DEBUG " VC Target KB = 0x%0X \n " ,
cmd . buffer . block_data [ 25 ] ) ;
/*** VP ***/
cmd . req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP ;
cmd . reg_count = 14 ;
cmd . start = 0 ;
cpia2_send_command ( cam , & cmd ) ;
printk ( KERN_DEBUG " VP Dev Hi = 0x%0X \n " ,
cmd . buffer . block_data [ 0 ] ) ;
printk ( KERN_DEBUG " VP Dev Lo = 0x%0X \n " ,
cmd . buffer . block_data [ 1 ] ) ;
printk ( KERN_DEBUG " VP Sys State = 0x%0X \n " ,
cmd . buffer . block_data [ 2 ] ) ;
printk ( KERN_DEBUG " VP Sys Ctrl = 0x%0X \n " ,
cmd . buffer . block_data [ 3 ] ) ;
printk ( KERN_DEBUG " VP Sensor flg = 0x%0X \n " ,
cmd . buffer . block_data [ 5 ] ) ;
printk ( KERN_DEBUG " VP Sensor Rev = 0x%0X \n " ,
cmd . buffer . block_data [ 6 ] ) ;
printk ( KERN_DEBUG " VP Dev Config = 0x%0X \n " ,
cmd . buffer . block_data [ 7 ] ) ;
printk ( KERN_DEBUG " VP GPIO_DIR = 0x%0X \n " ,
cmd . buffer . block_data [ 8 ] ) ;
printk ( KERN_DEBUG " VP GPIO_DATA = 0x%0X \n " ,
cmd . buffer . block_data [ 9 ] ) ;
printk ( KERN_DEBUG " VP Ram ADDR H = 0x%0X \n " ,
cmd . buffer . block_data [ 10 ] ) ;
printk ( KERN_DEBUG " VP Ram ADDR L = 0x%0X \n " ,
cmd . buffer . block_data [ 11 ] ) ;
printk ( KERN_DEBUG " VP RAM Data = 0x%0X \n " ,
cmd . buffer . block_data [ 12 ] ) ;
printk ( KERN_DEBUG " Do Call = 0x%0X \n " ,
cmd . buffer . block_data [ 13 ] ) ;
if ( cam - > params . pnp_id . device_type = = DEVICE_STV_672 ) {
cmd . reg_count = 9 ;
cmd . start = 0x0E ;
cpia2_send_command ( cam , & cmd ) ;
printk ( KERN_DEBUG " VP Clock Ctrl = 0x%0X \n " ,
cmd . buffer . block_data [ 0 ] ) ;
printk ( KERN_DEBUG " VP Patch Rev = 0x%0X \n " ,
cmd . buffer . block_data [ 1 ] ) ;
printk ( KERN_DEBUG " VP Vid Mode = 0x%0X \n " ,
cmd . buffer . block_data [ 2 ] ) ;
printk ( KERN_DEBUG " VP Framerate = 0x%0X \n " ,
cmd . buffer . block_data [ 3 ] ) ;
printk ( KERN_DEBUG " VP UserEffect = 0x%0X \n " ,
cmd . buffer . block_data [ 4 ] ) ;
printk ( KERN_DEBUG " VP White Bal = 0x%0X \n " ,
cmd . buffer . block_data [ 5 ] ) ;
printk ( KERN_DEBUG " VP WB thresh = 0x%0X \n " ,
cmd . buffer . block_data [ 6 ] ) ;
printk ( KERN_DEBUG " VP Exp Modes = 0x%0X \n " ,
cmd . buffer . block_data [ 7 ] ) ;
printk ( KERN_DEBUG " VP Exp Target = 0x%0X \n " ,
cmd . buffer . block_data [ 8 ] ) ;
cmd . reg_count = 1 ;
cmd . start = 0x1B ;
cpia2_send_command ( cam , & cmd ) ;
printk ( KERN_DEBUG " VP FlickerMds = 0x%0X \n " ,
cmd . buffer . block_data [ 0 ] ) ;
} else {
cmd . reg_count = 8 ;
cmd . start = 0x0E ;
cpia2_send_command ( cam , & cmd ) ;
printk ( KERN_DEBUG " VP Clock Ctrl = 0x%0X \n " ,
cmd . buffer . block_data [ 0 ] ) ;
printk ( KERN_DEBUG " VP Patch Rev = 0x%0X \n " ,
cmd . buffer . block_data [ 1 ] ) ;
printk ( KERN_DEBUG " VP Vid Mode = 0x%0X \n " ,
cmd . buffer . block_data [ 5 ] ) ;
printk ( KERN_DEBUG " VP Framerate = 0x%0X \n " ,
cmd . buffer . block_data [ 6 ] ) ;
printk ( KERN_DEBUG " VP UserEffect = 0x%0X \n " ,
cmd . buffer . block_data [ 7 ] ) ;
cmd . reg_count = 1 ;
cmd . start = CPIA2_VP5_EXPOSURE_TARGET ;
cpia2_send_command ( cam , & cmd ) ;
printk ( KERN_DEBUG " VP5 Exp Target= 0x%0X \n " ,
cmd . buffer . block_data [ 0 ] ) ;
cmd . reg_count = 4 ;
cmd . start = 0x3A ;
cpia2_send_command ( cam , & cmd ) ;
printk ( KERN_DEBUG " VP5 MY Black = 0x%0X \n " ,
cmd . buffer . block_data [ 0 ] ) ;
printk ( KERN_DEBUG " VP5 MCY Range = 0x%0X \n " ,
cmd . buffer . block_data [ 1 ] ) ;
printk ( KERN_DEBUG " VP5 MYCEILING = 0x%0X \n " ,
cmd . buffer . block_data [ 2 ] ) ;
printk ( KERN_DEBUG " VP5 MCUV Sat = 0x%0X \n " ,
cmd . buffer . block_data [ 3 ] ) ;
}
# endif
}
/******************************************************************************
*
* reset_camera_struct
*
* Sets all values to the defaults
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-09-04 10:33:43 +04:00
static void reset_camera_struct ( struct camera_data * cam )
2006-02-27 06:09:05 +03:00
{
/***
* The following parameter values are the defaults from the register map .
* * */
cam - > params . vp_params . lowlight_boost = 0 ;
/* FlickerModes */
cam - > params . flicker_control . flicker_mode_req = NEVER_FLICKER ;
/* jpeg params */
cam - > params . compression . jpeg_options = CPIA2_VC_VC_JPEG_OPT_DEFAULT ;
cam - > params . compression . creep_period = 2 ;
cam - > params . compression . user_squeeze = 20 ;
cam - > params . compression . inhibit_htables = false ;
/* gpio params */
cam - > params . vp_params . gpio_direction = 0 ; /* write, the default safe mode */
cam - > params . vp_params . gpio_data = 0 ;
/* Target kb params */
2012-04-29 15:44:44 +04:00
cam - > params . vc_params . quality = 100 ;
2006-02-27 06:09:05 +03:00
/***
* Set Sensor FPS as fast as possible .
* * */
if ( cam - > params . pnp_id . device_type = = DEVICE_STV_672 ) {
if ( cam - > params . version . sensor_flags = = CPIA2_VP_SENSOR_FLAGS_500 )
cam - > params . vp_params . frame_rate = CPIA2_VP_FRAMERATE_15 ;
else
cam - > params . vp_params . frame_rate = CPIA2_VP_FRAMERATE_30 ;
} else {
cam - > params . vp_params . frame_rate = CPIA2_VP_FRAMERATE_30 ;
}
/***
* Set default video mode as large as possible :
* for vga sensor set to vga , for cif sensor set to CIF .
* * */
if ( cam - > params . version . sensor_flags = = CPIA2_VP_SENSOR_FLAGS_500 ) {
cam - > sensor_type = CPIA2_SENSOR_500 ;
cam - > video_size = VIDEOSIZE_VGA ;
cam - > params . roi . width = STV_IMAGE_VGA_COLS ;
cam - > params . roi . height = STV_IMAGE_VGA_ROWS ;
} else {
cam - > sensor_type = CPIA2_SENSOR_410 ;
cam - > video_size = VIDEOSIZE_CIF ;
cam - > params . roi . width = STV_IMAGE_CIF_COLS ;
cam - > params . roi . height = STV_IMAGE_CIF_ROWS ;
}
2010-09-19 13:00:54 +04:00
cam - > width = cam - > params . roi . width ;
cam - > height = cam - > params . roi . height ;
2006-02-27 06:09:05 +03:00
}
2021-04-21 22:43:45 +03:00
/******************************************************************************
*
* cpia2_init_camera_struct
*
* Deinitialize camera struct
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void cpia2_deinit_camera_struct ( struct camera_data * cam , struct usb_interface * intf )
{
v4l2_device_unregister ( & cam - > v4l2_dev ) ;
kfree ( cam ) ;
}
2006-02-27 06:09:05 +03:00
/******************************************************************************
*
* cpia2_init_camera_struct
*
* Initializes camera struct , does not call reset to fill in defaults .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-04-29 15:44:44 +04:00
struct camera_data * cpia2_init_camera_struct ( struct usb_interface * intf )
2006-02-27 06:09:05 +03:00
{
struct camera_data * cam ;
some kmalloc/memset ->kzalloc (tree wide)
Transform some calls to kmalloc/memset to a single kzalloc (or kcalloc).
Here is a short excerpt of the semantic patch performing
this transformation:
@@
type T2;
expression x;
identifier f,fld;
expression E;
expression E1,E2;
expression e1,e2,e3,y;
statement S;
@@
x =
- kmalloc
+ kzalloc
(E1,E2)
... when != \(x->fld=E;\|y=f(...,x,...);\|f(...,x,...);\|x=E;\|while(...) S\|for(e1;e2;e3) S\)
- memset((T2)x,0,E1);
@@
expression E1,E2,E3;
@@
- kzalloc(E1 * E2,E3)
+ kcalloc(E1,E2,E3)
[akpm@linux-foundation.org: get kcalloc args the right way around]
Signed-off-by: Yoann Padioleau <padator@wanadoo.fr>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Acked-by: Russell King <rmk@arm.linux.org.uk>
Cc: Bryan Wu <bryan.wu@analog.com>
Acked-by: Jiri Slaby <jirislaby@gmail.com>
Cc: Dave Airlie <airlied@linux.ie>
Acked-by: Roland Dreier <rolandd@cisco.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Acked-by: Dmitry Torokhov <dtor@mail.ru>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Acked-by: Pierre Ossman <drzeus-list@drzeus.cx>
Cc: Jeff Garzik <jeff@garzik.org>
Cc: "David S. Miller" <davem@davemloft.net>
Acked-by: Greg KH <greg@kroah.com>
Cc: James Bottomley <James.Bottomley@steeleye.com>
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-19 12:49:03 +04:00
cam = kzalloc ( sizeof ( * cam ) , GFP_KERNEL ) ;
2006-02-27 06:09:05 +03:00
if ( ! cam ) {
ERR ( " couldn't kmalloc cpia2 struct \n " ) ;
return NULL ;
}
2012-04-29 15:44:44 +04:00
cam - > v4l2_dev . release = cpia2_camera_release ;
if ( v4l2_device_register ( & intf - > dev , & cam - > v4l2_dev ) < 0 ) {
v4l2_err ( & cam - > v4l2_dev , " couldn't register v4l2_device \n " ) ;
kfree ( cam ) ;
return NULL ;
}
2006-02-27 06:09:05 +03:00
2010-12-18 15:50:43 +03:00
mutex_init ( & cam - > v4l2_lock ) ;
2006-02-27 06:09:05 +03:00
init_waitqueue_head ( & cam - > wq_stream ) ;
return cam ;
}
/******************************************************************************
*
* cpia2_init_camera
*
* Initializes camera .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int cpia2_init_camera ( struct camera_data * cam )
{
DBG ( " Start \n " ) ;
cam - > mmapped = false ;
/* Get sensor and asic types before reset. */
cpia2_set_high_power ( cam ) ;
cpia2_get_version_info ( cam ) ;
if ( cam - > params . version . asic_id ! = CPIA2_ASIC_672 ) {
ERR ( " Device IO error (asicID has incorrect value of 0x%X \n " ,
cam - > params . version . asic_id ) ;
return - ENODEV ;
}
/* Set GPIO direction and data to a safe state. */
cpia2_do_command ( cam , CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION ,
TRANSFER_WRITE , 0 ) ;
cpia2_do_command ( cam , CPIA2_CMD_SET_VC_MP_GPIO_DATA ,
TRANSFER_WRITE , 0 ) ;
/* resetting struct requires version info for sensor and asic types */
reset_camera_struct ( cam ) ;
cpia2_set_low_power ( cam ) ;
DBG ( " End \n " ) ;
return 0 ;
}
/******************************************************************************
*
* cpia2_allocate_buffers
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int cpia2_allocate_buffers ( struct camera_data * cam )
{
int i ;
if ( ! cam - > buffers ) {
u32 size = cam - > num_frames * sizeof ( struct framebuf ) ;
cam - > buffers = kmalloc ( size , GFP_KERNEL ) ;
if ( ! cam - > buffers ) {
ERR ( " couldn't kmalloc frame buffer structures \n " ) ;
return - ENOMEM ;
}
}
if ( ! cam - > frame_buffer ) {
cam - > frame_buffer = rvmalloc ( cam - > frame_size * cam - > num_frames ) ;
if ( ! cam - > frame_buffer ) {
ERR ( " couldn't vmalloc frame buffer data area \n " ) ;
kfree ( cam - > buffers ) ;
cam - > buffers = NULL ;
return - ENOMEM ;
}
}
for ( i = 0 ; i < cam - > num_frames - 1 ; + + i ) {
cam - > buffers [ i ] . next = & cam - > buffers [ i + 1 ] ;
cam - > buffers [ i ] . data = cam - > frame_buffer + i * cam - > frame_size ;
cam - > buffers [ i ] . status = FRAME_EMPTY ;
cam - > buffers [ i ] . length = 0 ;
cam - > buffers [ i ] . max_length = 0 ;
cam - > buffers [ i ] . num = i ;
}
cam - > buffers [ i ] . next = cam - > buffers ;
cam - > buffers [ i ] . data = cam - > frame_buffer + i * cam - > frame_size ;
cam - > buffers [ i ] . status = FRAME_EMPTY ;
cam - > buffers [ i ] . length = 0 ;
cam - > buffers [ i ] . max_length = 0 ;
cam - > buffers [ i ] . num = i ;
cam - > curbuff = cam - > buffers ;
cam - > workbuff = cam - > curbuff - > next ;
DBG ( " buffers=%p, curbuff=%p, workbuff=%p \n " , cam - > buffers , cam - > curbuff ,
cam - > workbuff ) ;
return 0 ;
}
/******************************************************************************
*
* cpia2_free_buffers
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void cpia2_free_buffers ( struct camera_data * cam )
{
if ( cam - > buffers ) {
kfree ( cam - > buffers ) ;
cam - > buffers = NULL ;
}
if ( cam - > frame_buffer ) {
rvfree ( cam - > frame_buffer , cam - > frame_size * cam - > num_frames ) ;
cam - > frame_buffer = NULL ;
}
}
/******************************************************************************
*
* cpia2_read
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
long cpia2_read ( struct camera_data * cam ,
char __user * buf , unsigned long count , int noblock )
{
struct framebuf * frame ;
2010-12-18 15:50:43 +03:00
if ( ! count )
2006-02-27 06:09:05 +03:00
return 0 ;
if ( ! buf ) {
2008-04-09 06:20:00 +04:00
ERR ( " %s: buffer NULL \n " , __func__ ) ;
2006-02-27 06:09:05 +03:00
return - EINVAL ;
}
if ( ! cam ) {
2008-04-09 06:20:00 +04:00
ERR ( " %s: Internal error, camera_data NULL! \n " , __func__ ) ;
2006-02-27 06:09:05 +03:00
return - EINVAL ;
}
2010-12-18 15:50:43 +03:00
if ( ! cam - > streaming ) {
2006-02-27 06:09:05 +03:00
/* Start streaming */
cpia2_usb_stream_start ( cam ,
cam - > params . camera_state . stream_mode ) ;
}
/* Copy cam->curbuff in case it changes while we're processing */
frame = cam - > curbuff ;
if ( noblock & & frame - > status ! = FRAME_READY ) {
return - EAGAIN ;
}
2010-12-18 15:50:43 +03:00
if ( frame - > status ! = FRAME_READY ) {
mutex_unlock ( & cam - > v4l2_lock ) ;
2006-02-27 06:09:05 +03:00
wait_event_interruptible ( cam - > wq_stream ,
2012-04-29 15:44:44 +04:00
! video_is_registered ( & cam - > vdev ) | |
2006-02-27 06:09:05 +03:00
( frame = cam - > curbuff ) - > status = = FRAME_READY ) ;
2010-12-18 15:50:43 +03:00
mutex_lock ( & cam - > v4l2_lock ) ;
2006-02-27 06:09:05 +03:00
if ( signal_pending ( current ) )
return - ERESTARTSYS ;
2012-04-29 15:44:44 +04:00
if ( ! video_is_registered ( & cam - > vdev ) )
2006-02-27 06:09:05 +03:00
return 0 ;
}
/* copy data to user space */
2010-12-18 15:50:43 +03:00
if ( frame - > length > count )
2006-02-27 06:09:05 +03:00
return - EFAULT ;
2010-12-18 15:50:43 +03:00
if ( copy_to_user ( buf , frame - > data , frame - > length ) )
2006-02-27 06:09:05 +03:00
return - EFAULT ;
count = frame - > length ;
frame - > status = FRAME_EMPTY ;
return count ;
}
/******************************************************************************
*
* cpia2_poll
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2017-07-03 10:02:56 +03:00
__poll_t cpia2_poll ( struct camera_data * cam , struct file * filp ,
2006-02-27 06:09:05 +03:00
poll_table * wait )
{
2017-07-03 10:02:56 +03:00
__poll_t status = v4l2_ctrl_poll ( filp , wait ) ;
2006-02-27 06:09:05 +03:00
2018-02-12 01:34:03 +03:00
if ( ( poll_requested_events ( wait ) & ( EPOLLIN | EPOLLRDNORM ) ) & &
2012-04-29 15:44:44 +04:00
! cam - > streaming ) {
2006-02-27 06:09:05 +03:00
/* Start streaming */
cpia2_usb_stream_start ( cam ,
cam - > params . camera_state . stream_mode ) ;
}
poll_wait ( filp , & cam - > wq_stream , wait ) ;
2012-04-29 15:44:44 +04:00
if ( cam - > curbuff - > status = = FRAME_READY )
2018-02-12 01:34:03 +03:00
status | = EPOLLIN | EPOLLRDNORM ;
2006-02-27 06:09:05 +03:00
return status ;
}
/******************************************************************************
*
* cpia2_remap_buffer
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int cpia2_remap_buffer ( struct camera_data * cam , struct vm_area_struct * vma )
{
const char * adr = ( const char * ) vma - > vm_start ;
unsigned long size = vma - > vm_end - vma - > vm_start ;
unsigned long start_offset = vma - > vm_pgoff < < PAGE_SHIFT ;
unsigned long start = ( unsigned long ) adr ;
unsigned long page , pos ;
DBG ( " mmap offset:%ld size:%ld \n " , start_offset , size ) ;
2012-04-29 15:44:44 +04:00
if ( ! video_is_registered ( & cam - > vdev ) )
2006-02-27 06:09:05 +03:00
return - ENODEV ;
if ( size > cam - > frame_size * cam - > num_frames | |
( start_offset % cam - > frame_size ) ! = 0 | |
2010-12-18 15:50:43 +03:00
( start_offset + size > cam - > frame_size * cam - > num_frames ) )
2006-02-27 06:09:05 +03:00
return - EINVAL ;
pos = ( ( unsigned long ) ( cam - > frame_buffer ) ) + start_offset ;
while ( size > 0 ) {
page = kvirt_to_pa ( pos ) ;
2010-12-18 15:50:43 +03:00
if ( remap_pfn_range ( vma , start , page > > PAGE_SHIFT , PAGE_SIZE , PAGE_SHARED ) )
2006-02-27 06:09:05 +03:00
return - EAGAIN ;
start + = PAGE_SIZE ;
pos + = PAGE_SIZE ;
if ( size > PAGE_SIZE )
size - = PAGE_SIZE ;
else
size = 0 ;
}
cam - > mmapped = true ;
return 0 ;
}