2009-03-03 20:37:50 +03:00
/*
2009-03-03 19:31:36 +03:00
cx231xx_avcore . c - driver for Conexant Cx23100 / 101 / 102
USB video capture devices
2009-03-03 20:37:50 +03:00
Copyright ( C ) 2008 < srinivasa . deevi at conexant dot com >
This program contains the specific code to control the avdecoder chip and
other related usb control functions for cx231xx based chipset .
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include <linux/init.h>
# include <linux/list.h>
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/bitmap.h>
# include <linux/usb.h>
# include <linux/i2c.h>
# include <linux/mm.h>
# include <linux/mutex.h>
# include <media/v4l2-common.h>
# include <media/v4l2-ioctl.h>
# include <media/v4l2-chip-ident.h>
# include "cx231xx.h"
2009-03-03 19:31:36 +03:00
/******************************************************************************
2009-03-22 04:00:20 +03:00
- : BLOCK ARRANGEMENT : -
I2S block - - - - - - - - - - - - - - - - - - - - - - |
[ I2S audio ] |
|
Analog Front End - - > Direct IF - | - > Cx25840 - - > Audio
[ video & audio ] | [ Audio ]
|
| - > Cx25840 - - > Video
[ Video ]
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/******************************************************************************
* A F E - B L O C K C O N T R O L functions *
* [ ANALOG FRONT END ] *
2009-03-11 03:16:26 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-03-22 04:00:20 +03:00
static int afe_write_byte ( struct cx231xx * dev , u16 saddr , u8 data )
{
return cx231xx_write_i2c_data ( dev , AFE_DEVICE_ADDRESS ,
saddr , 2 , data , 1 ) ;
}
static int afe_read_byte ( struct cx231xx * dev , u16 saddr , u8 * data )
{
int status ;
u32 temp = 0 ;
status = cx231xx_read_i2c_data ( dev , AFE_DEVICE_ADDRESS ,
saddr , 2 , & temp , 1 ) ;
* data = ( u8 ) temp ;
return status ;
}
int cx231xx_afe_init_super_block ( struct cx231xx * dev , u32 ref_count )
2009-03-03 20:37:50 +03:00
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
u8 temp = 0 ;
2009-03-22 04:00:20 +03:00
u8 afe_power_status = 0 ;
2009-03-03 12:14:34 +03:00
int i = 0 ;
/* super block initialize */
temp = ( u8 ) ( ref_count & 0xff ) ;
2009-03-22 04:00:20 +03:00
status = afe_write_byte ( dev , SUP_BLK_TUNE2 , temp ) ;
2009-03-11 03:16:26 +03:00
if ( status < 0 )
return status ;
2009-03-03 12:14:34 +03:00
2009-03-22 04:00:20 +03:00
status = afe_read_byte ( dev , SUP_BLK_TUNE2 , & afe_power_status ) ;
2009-03-11 03:16:26 +03:00
if ( status < 0 )
return status ;
2009-03-03 12:14:34 +03:00
temp = ( u8 ) ( ( ref_count & 0x300 ) > > 8 ) ;
temp | = 0x40 ;
2009-03-22 04:00:20 +03:00
status = afe_write_byte ( dev , SUP_BLK_TUNE1 , temp ) ;
2009-03-11 03:16:26 +03:00
if ( status < 0 )
return status ;
2009-03-22 04:00:20 +03:00
status = afe_write_byte ( dev , SUP_BLK_PLL2 , 0x0f ) ;
2009-03-11 03:16:26 +03:00
if ( status < 0 )
return status ;
2009-03-03 12:14:34 +03:00
/* enable pll */
2009-03-22 04:00:20 +03:00
while ( afe_power_status ! = 0x18 ) {
status = afe_write_byte ( dev , SUP_BLK_PWRDN , 0x18 ) ;
2009-03-11 03:16:26 +03:00
if ( status < 0 ) {
cx231xx_info (
" : Init Super Block failed in send cmd \n " ) ;
break ;
}
2009-03-22 04:00:20 +03:00
status = afe_read_byte ( dev , SUP_BLK_PWRDN , & afe_power_status ) ;
afe_power_status & = 0xff ;
2009-03-03 12:14:34 +03:00
if ( status < 0 ) {
2009-03-04 23:49:01 +03:00
cx231xx_info (
2009-03-11 03:16:26 +03:00
" : Init Super Block failed in receive cmd \n " ) ;
2009-03-03 12:14:34 +03:00
break ;
}
i + + ;
if ( i = = 10 ) {
2009-03-04 23:49:01 +03:00
cx231xx_info (
" : Init Super Block force break in loop !!!! \n " ) ;
2009-03-03 12:14:34 +03:00
status = - 1 ;
break ;
}
}
if ( status < 0 )
return status ;
/* start tuning filter */
2009-03-22 04:00:20 +03:00
status = afe_write_byte ( dev , SUP_BLK_TUNE3 , 0x40 ) ;
2009-03-11 03:16:26 +03:00
if ( status < 0 )
return status ;
2009-03-03 12:14:34 +03:00
msleep ( 5 ) ;
/* exit tuning */
2009-03-22 04:00:20 +03:00
status = afe_write_byte ( dev , SUP_BLK_TUNE3 , 0x00 ) ;
2009-03-03 12:14:34 +03:00
return status ;
2009-03-03 20:37:50 +03:00
}
2009-03-22 04:00:20 +03:00
int cx231xx_afe_init_channels ( struct cx231xx * dev )
2009-03-03 20:37:50 +03:00
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
/* power up all 3 channels, clear pd_buffer */
2009-03-22 04:00:20 +03:00
status = afe_write_byte ( dev , ADC_PWRDN_CLAMP_CH1 , 0x00 ) ;
status = afe_write_byte ( dev , ADC_PWRDN_CLAMP_CH2 , 0x00 ) ;
status = afe_write_byte ( dev , ADC_PWRDN_CLAMP_CH3 , 0x00 ) ;
2009-03-03 12:14:34 +03:00
/* Enable quantizer calibration */
2009-03-22 04:00:20 +03:00
status = afe_write_byte ( dev , ADC_COM_QUANT , 0x02 ) ;
2009-03-03 12:14:34 +03:00
/* channel initialize, force modulator (fb) reset */
2009-03-22 04:00:20 +03:00
status = afe_write_byte ( dev , ADC_FB_FRCRST_CH1 , 0x17 ) ;
status = afe_write_byte ( dev , ADC_FB_FRCRST_CH2 , 0x17 ) ;
status = afe_write_byte ( dev , ADC_FB_FRCRST_CH3 , 0x17 ) ;
2009-03-03 12:14:34 +03:00
/* start quantilizer calibration */
2009-03-22 04:00:20 +03:00
status = afe_write_byte ( dev , ADC_CAL_ATEST_CH1 , 0x10 ) ;
status = afe_write_byte ( dev , ADC_CAL_ATEST_CH2 , 0x10 ) ;
status = afe_write_byte ( dev , ADC_CAL_ATEST_CH3 , 0x10 ) ;
2009-03-03 12:14:34 +03:00
msleep ( 5 ) ;
/* exit modulator (fb) reset */
2009-03-22 04:00:20 +03:00
status = afe_write_byte ( dev , ADC_FB_FRCRST_CH1 , 0x07 ) ;
status = afe_write_byte ( dev , ADC_FB_FRCRST_CH2 , 0x07 ) ;
status = afe_write_byte ( dev , ADC_FB_FRCRST_CH3 , 0x07 ) ;
2009-03-03 12:14:34 +03:00
/* enable the pre_clamp in each channel for single-ended input */
2009-03-22 04:00:20 +03:00
status = afe_write_byte ( dev , ADC_NTF_PRECLMP_EN_CH1 , 0xf0 ) ;
status = afe_write_byte ( dev , ADC_NTF_PRECLMP_EN_CH2 , 0xf0 ) ;
status = afe_write_byte ( dev , ADC_NTF_PRECLMP_EN_CH3 , 0xf0 ) ;
2009-03-03 12:14:34 +03:00
/* use diode instead of resistor, so set term_en to 0, res_en to 0 */
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , AFE_DEVICE_ADDRESS , 8 ,
2009-03-03 12:14:34 +03:00
ADC_QGAIN_RES_TRM_CH1 , 3 , 7 , 0x00 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , AFE_DEVICE_ADDRESS , 8 ,
2009-03-03 12:14:34 +03:00
ADC_QGAIN_RES_TRM_CH2 , 3 , 7 , 0x00 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , AFE_DEVICE_ADDRESS , 8 ,
2009-03-03 12:14:34 +03:00
ADC_QGAIN_RES_TRM_CH3 , 3 , 7 , 0x00 ) ;
/* dynamic element matching off */
2009-03-22 04:00:20 +03:00
status = afe_write_byte ( dev , ADC_DCSERVO_DEM_CH1 , 0x03 ) ;
status = afe_write_byte ( dev , ADC_DCSERVO_DEM_CH2 , 0x03 ) ;
status = afe_write_byte ( dev , ADC_DCSERVO_DEM_CH3 , 0x03 ) ;
2009-03-03 12:14:34 +03:00
return status ;
2009-03-03 20:37:50 +03:00
}
2009-03-22 04:00:20 +03:00
int cx231xx_afe_setup_AFE_for_baseband ( struct cx231xx * dev )
2009-03-03 20:37:50 +03:00
{
2009-03-22 04:00:20 +03:00
u8 c_value = 0 ;
2009-03-03 12:14:34 +03:00
int status = 0 ;
2009-03-03 20:37:50 +03:00
2009-03-22 04:00:20 +03:00
status = afe_read_byte ( dev , ADC_PWRDN_CLAMP_CH2 , & c_value ) ;
2009-03-03 12:14:34 +03:00
c_value & = ( ~ ( 0x50 ) ) ;
2009-03-22 04:00:20 +03:00
status = afe_write_byte ( dev , ADC_PWRDN_CLAMP_CH2 , c_value ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
return status ;
2009-03-03 20:37:50 +03:00
}
/*
2009-03-11 03:16:26 +03:00
The Analog Front End in Cx231xx has 3 channels . These
channels are used to share between different inputs
like tuner , s - video and composite inputs .
2009-03-03 20:37:50 +03:00
channel 1 - - - - - pin 1 to pin4 ( in reg is 1 - 4 )
channel 2 - - - - - pin 5 to pin8 ( in reg is 5 - 8 )
channel 3 - - - - - pin 9 to pin 12 ( in reg is 9 - 11 )
*/
2009-03-22 04:00:20 +03:00
int cx231xx_afe_set_input_mux ( struct cx231xx * dev , u32 input_mux )
2009-03-03 20:37:50 +03:00
{
2009-03-03 12:14:34 +03:00
u8 ch1_setting = ( u8 ) input_mux ;
u8 ch2_setting = ( u8 ) ( input_mux > > 8 ) ;
u8 ch3_setting = ( u8 ) ( input_mux > > 16 ) ;
int status = 0 ;
2009-03-22 04:00:20 +03:00
u8 value = 0 ;
2009-03-03 12:14:34 +03:00
if ( ch1_setting ! = 0 ) {
2009-03-22 04:00:20 +03:00
status = afe_read_byte ( dev , ADC_INPUT_CH1 , & value ) ;
2009-03-03 12:14:34 +03:00
value & = ( ! INPUT_SEL_MASK ) ;
value | = ( ch1_setting - 1 ) < < 4 ;
value & = 0xff ;
2009-03-22 04:00:20 +03:00
status = afe_write_byte ( dev , ADC_INPUT_CH1 , value ) ;
2009-03-03 12:14:34 +03:00
}
if ( ch2_setting ! = 0 ) {
2009-03-22 04:00:20 +03:00
status = afe_read_byte ( dev , ADC_INPUT_CH2 , & value ) ;
2009-03-03 12:14:34 +03:00
value & = ( ! INPUT_SEL_MASK ) ;
value | = ( ch2_setting - 1 ) < < 4 ;
value & = 0xff ;
2009-03-22 04:00:20 +03:00
status = afe_write_byte ( dev , ADC_INPUT_CH2 , value ) ;
2009-03-03 12:14:34 +03:00
}
2009-03-03 19:31:36 +03:00
/* For ch3_setting, the value to put in the register is
7 less than the input number */
2009-03-03 12:14:34 +03:00
if ( ch3_setting ! = 0 ) {
2009-03-22 04:00:20 +03:00
status = afe_read_byte ( dev , ADC_INPUT_CH3 , & value ) ;
2009-03-03 12:14:34 +03:00
value & = ( ! INPUT_SEL_MASK ) ;
value | = ( ch3_setting - 1 ) < < 4 ;
value & = 0xff ;
2009-03-22 04:00:20 +03:00
status = afe_write_byte ( dev , ADC_INPUT_CH3 , value ) ;
2009-03-03 12:14:34 +03:00
}
return status ;
2009-03-03 20:37:50 +03:00
}
2009-03-22 04:00:20 +03:00
int cx231xx_afe_set_mode ( struct cx231xx * dev , enum AFE_MODE mode )
2009-03-03 20:37:50 +03:00
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
2009-03-11 03:16:26 +03:00
/*
* FIXME : We need to implement the AFE code for LOW IF and for HI IF .
* Currently , only baseband works .
*/
2009-03-03 12:14:34 +03:00
switch ( mode ) {
case AFE_MODE_LOW_IF :
/* SetupAFEforLowIF(); */
break ;
case AFE_MODE_BASEBAND :
2009-03-22 04:00:20 +03:00
status = cx231xx_afe_setup_AFE_for_baseband ( dev ) ;
2009-03-03 12:14:34 +03:00
break ;
case AFE_MODE_EU_HI_IF :
/* SetupAFEforEuHiIF(); */
break ;
case AFE_MODE_US_HI_IF :
/* SetupAFEforUsHiIF(); */
break ;
case AFE_MODE_JAPAN_HI_IF :
/* SetupAFEforJapanHiIF(); */
break ;
}
2009-03-22 04:00:20 +03:00
if ( ( mode ! = dev - > afe_mode ) & &
2009-03-04 23:49:01 +03:00
( dev - > video_input = = CX231XX_VMUX_TELEVISION ) )
2009-03-22 04:00:20 +03:00
status = cx231xx_afe_adjust_ref_count ( dev ,
2009-03-03 12:14:34 +03:00
CX231XX_VMUX_TELEVISION ) ;
2009-03-22 04:00:20 +03:00
dev - > afe_mode = mode ;
2009-03-03 12:14:34 +03:00
return status ;
2009-03-03 20:37:50 +03:00
}
2009-03-22 04:00:20 +03:00
int cx231xx_afe_update_power_control ( struct cx231xx * dev ,
2009-03-11 03:16:26 +03:00
enum AV_MODE avmode )
2009-03-03 20:37:50 +03:00
{
2009-03-22 04:00:20 +03:00
u8 afe_power_status = 0 ;
2009-03-03 12:14:34 +03:00
int status = 0 ;
switch ( dev - > model ) {
case CX231XX_BOARD_CNXT_RDE_250 :
case CX231XX_BOARD_CNXT_RDU_250 :
if ( avmode = = POLARIS_AVMODE_ANALOGT_TV ) {
2009-03-22 04:00:20 +03:00
while ( afe_power_status ! = ( FLD_PWRDN_TUNING_BIAS |
2009-03-11 03:16:26 +03:00
FLD_PWRDN_ENABLE_PLL ) ) {
2009-03-22 04:00:20 +03:00
status = afe_write_byte ( dev , SUP_BLK_PWRDN ,
2009-03-11 03:16:26 +03:00
FLD_PWRDN_TUNING_BIAS |
2009-03-22 04:00:20 +03:00
FLD_PWRDN_ENABLE_PLL ) ;
status | = afe_read_byte ( dev , SUP_BLK_PWRDN ,
& afe_power_status ) ;
2009-03-03 12:14:34 +03:00
if ( status < 0 )
break ;
}
2009-03-22 04:00:20 +03:00
status = afe_write_byte ( dev , ADC_PWRDN_CLAMP_CH1 ,
0x00 ) ;
status | = afe_write_byte ( dev , ADC_PWRDN_CLAMP_CH2 ,
0x00 ) ;
status | = afe_write_byte ( dev , ADC_PWRDN_CLAMP_CH3 ,
0x00 ) ;
2009-03-03 12:14:34 +03:00
} else if ( avmode = = POLARIS_AVMODE_DIGITAL ) {
2009-03-22 04:00:20 +03:00
status = afe_write_byte ( dev , ADC_PWRDN_CLAMP_CH1 ,
0x70 ) ;
status | = afe_write_byte ( dev , ADC_PWRDN_CLAMP_CH2 ,
0x70 ) ;
status | = afe_write_byte ( dev , ADC_PWRDN_CLAMP_CH3 ,
0x70 ) ;
status | = afe_read_byte ( dev , SUP_BLK_PWRDN ,
& afe_power_status ) ;
afe_power_status | = FLD_PWRDN_PD_BANDGAP |
2009-03-11 03:16:26 +03:00
FLD_PWRDN_PD_BIAS |
FLD_PWRDN_PD_TUNECK ;
2009-03-22 04:00:20 +03:00
status | = afe_write_byte ( dev , SUP_BLK_PWRDN ,
afe_power_status ) ;
2009-03-03 12:14:34 +03:00
} else if ( avmode = = POLARIS_AVMODE_ENXTERNAL_AV ) {
2009-03-22 04:00:20 +03:00
while ( afe_power_status ! = ( FLD_PWRDN_TUNING_BIAS |
2009-03-11 03:16:26 +03:00
FLD_PWRDN_ENABLE_PLL ) ) {
2009-03-22 04:00:20 +03:00
status = afe_write_byte ( dev , SUP_BLK_PWRDN ,
2009-03-11 03:16:26 +03:00
FLD_PWRDN_TUNING_BIAS |
2009-03-22 04:00:20 +03:00
FLD_PWRDN_ENABLE_PLL ) ;
status | = afe_read_byte ( dev , SUP_BLK_PWRDN ,
& afe_power_status ) ;
2009-03-03 12:14:34 +03:00
if ( status < 0 )
break ;
}
2009-03-22 04:00:20 +03:00
status | = afe_write_byte ( dev , ADC_PWRDN_CLAMP_CH1 ,
0x00 ) ;
status | = afe_write_byte ( dev , ADC_PWRDN_CLAMP_CH2 ,
0x00 ) ;
status | = afe_write_byte ( dev , ADC_PWRDN_CLAMP_CH3 ,
0x00 ) ;
2009-03-03 12:14:34 +03:00
} else {
cx231xx_info ( " Invalid AV mode input \n " ) ;
status = - 1 ;
}
break ;
default :
if ( avmode = = POLARIS_AVMODE_ANALOGT_TV ) {
2009-03-22 04:00:20 +03:00
while ( afe_power_status ! = ( FLD_PWRDN_TUNING_BIAS |
2009-03-11 03:16:26 +03:00
FLD_PWRDN_ENABLE_PLL ) ) {
2009-03-22 04:00:20 +03:00
status = afe_write_byte ( dev , SUP_BLK_PWRDN ,
2009-03-11 03:16:26 +03:00
FLD_PWRDN_TUNING_BIAS |
2009-03-22 04:00:20 +03:00
FLD_PWRDN_ENABLE_PLL ) ;
status | = afe_read_byte ( dev , SUP_BLK_PWRDN ,
& afe_power_status ) ;
2009-03-03 12:14:34 +03:00
if ( status < 0 )
break ;
}
2009-03-22 04:00:20 +03:00
status | = afe_write_byte ( dev , ADC_PWRDN_CLAMP_CH1 ,
0x40 ) ;
status | = afe_write_byte ( dev , ADC_PWRDN_CLAMP_CH2 ,
0x40 ) ;
status | = afe_write_byte ( dev , ADC_PWRDN_CLAMP_CH3 ,
0x00 ) ;
2009-03-03 12:14:34 +03:00
} else if ( avmode = = POLARIS_AVMODE_DIGITAL ) {
2009-03-22 04:00:20 +03:00
status = afe_write_byte ( dev , ADC_PWRDN_CLAMP_CH1 ,
0x70 ) ;
status | = afe_write_byte ( dev , ADC_PWRDN_CLAMP_CH2 ,
0x70 ) ;
status | = afe_write_byte ( dev , ADC_PWRDN_CLAMP_CH3 ,
0x70 ) ;
status | = afe_read_byte ( dev , SUP_BLK_PWRDN ,
& afe_power_status ) ;
afe_power_status | = FLD_PWRDN_PD_BANDGAP |
2009-03-11 03:16:26 +03:00
FLD_PWRDN_PD_BIAS |
FLD_PWRDN_PD_TUNECK ;
2009-03-22 04:00:20 +03:00
status | = afe_write_byte ( dev , SUP_BLK_PWRDN ,
afe_power_status ) ;
2009-03-03 12:14:34 +03:00
} else if ( avmode = = POLARIS_AVMODE_ENXTERNAL_AV ) {
2009-03-22 04:00:20 +03:00
while ( afe_power_status ! = ( FLD_PWRDN_TUNING_BIAS |
2009-03-11 03:16:26 +03:00
FLD_PWRDN_ENABLE_PLL ) ) {
2009-03-22 04:00:20 +03:00
status = afe_write_byte ( dev , SUP_BLK_PWRDN ,
2009-03-11 03:16:26 +03:00
FLD_PWRDN_TUNING_BIAS |
2009-03-22 04:00:20 +03:00
FLD_PWRDN_ENABLE_PLL ) ;
status | = afe_read_byte ( dev , SUP_BLK_PWRDN ,
& afe_power_status ) ;
2009-03-03 12:14:34 +03:00
if ( status < 0 )
break ;
}
2009-03-22 04:00:20 +03:00
status | = afe_write_byte ( dev , ADC_PWRDN_CLAMP_CH1 ,
0x00 ) ;
status | = afe_write_byte ( dev , ADC_PWRDN_CLAMP_CH2 ,
0x00 ) ;
status | = afe_write_byte ( dev , ADC_PWRDN_CLAMP_CH3 ,
0x40 ) ;
2009-03-03 12:14:34 +03:00
} else {
cx231xx_info ( " Invalid AV mode input \n " ) ;
status = - 1 ;
}
} /* switch */
return status ;
2009-03-03 20:37:50 +03:00
}
2009-03-22 04:00:20 +03:00
int cx231xx_afe_adjust_ref_count ( struct cx231xx * dev , u32 video_input )
2009-03-03 20:37:50 +03:00
{
2009-03-22 04:00:20 +03:00
u8 input_mode = 0 ;
u8 ntf_mode = 0 ;
2009-03-03 12:14:34 +03:00
int status = 0 ;
dev - > video_input = video_input ;
if ( video_input = = CX231XX_VMUX_TELEVISION ) {
2009-03-22 04:00:20 +03:00
status = afe_read_byte ( dev , ADC_INPUT_CH3 , & input_mode ) ;
status = afe_read_byte ( dev , ADC_NTF_PRECLMP_EN_CH3 ,
& ntf_mode ) ;
2009-03-03 12:14:34 +03:00
} else {
2009-03-22 04:00:20 +03:00
status = afe_read_byte ( dev , ADC_INPUT_CH1 , & input_mode ) ;
status = afe_read_byte ( dev , ADC_NTF_PRECLMP_EN_CH1 ,
& ntf_mode ) ;
2009-03-03 12:14:34 +03:00
}
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
input_mode = ( ntf_mode & 0x3 ) | ( ( input_mode & 0x6 ) < < 1 ) ;
switch ( input_mode ) {
case SINGLE_ENDED :
2009-03-22 04:00:20 +03:00
dev - > afe_ref_count = 0x23C ;
2009-03-03 12:14:34 +03:00
break ;
case LOW_IF :
2009-03-22 04:00:20 +03:00
dev - > afe_ref_count = 0x24C ;
2009-03-03 12:14:34 +03:00
break ;
case EU_IF :
2009-03-22 04:00:20 +03:00
dev - > afe_ref_count = 0x258 ;
2009-03-03 12:14:34 +03:00
break ;
case US_IF :
2009-03-22 04:00:20 +03:00
dev - > afe_ref_count = 0x260 ;
2009-03-03 12:14:34 +03:00
break ;
default :
break ;
}
2009-03-22 04:00:20 +03:00
status = cx231xx_afe_init_super_block ( dev , dev - > afe_ref_count ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
return status ;
}
2009-03-03 20:37:50 +03:00
2009-03-03 19:31:36 +03:00
/******************************************************************************
* V I D E O / A U D I O D E C O D E R C O N T R O L functions *
2009-03-11 03:16:26 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-03-22 04:00:20 +03:00
static int vid_blk_write_byte ( struct cx231xx * dev , u16 saddr , u8 data )
{
return cx231xx_write_i2c_data ( dev , VID_BLK_I2C_ADDRESS ,
saddr , 2 , data , 1 ) ;
}
static int vid_blk_read_byte ( struct cx231xx * dev , u16 saddr , u8 * data )
{
int status ;
u32 temp = 0 ;
status = cx231xx_read_i2c_data ( dev , VID_BLK_I2C_ADDRESS ,
saddr , 2 , & temp , 1 ) ;
* data = ( u8 ) temp ;
return status ;
}
static int vid_blk_write_word ( struct cx231xx * dev , u16 saddr , u32 data )
{
return cx231xx_write_i2c_data ( dev , VID_BLK_I2C_ADDRESS ,
saddr , 2 , data , 4 ) ;
}
static int vid_blk_read_word ( struct cx231xx * dev , u16 saddr , u32 * data )
{
return cx231xx_read_i2c_data ( dev , VID_BLK_I2C_ADDRESS ,
saddr , 2 , data , 4 ) ;
}
2009-03-03 20:37:50 +03:00
int cx231xx_set_video_input_mux ( struct cx231xx * dev , u8 input )
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
switch ( INPUT ( input ) - > type ) {
case CX231XX_VMUX_COMPOSITE1 :
case CX231XX_VMUX_SVIDEO :
if ( ( dev - > current_pcb_config . type = = USB_BUS_POWER ) & &
( dev - > power_mode ! = POLARIS_AVMODE_ENXTERNAL_AV ) ) {
2009-03-03 19:31:36 +03:00
/* External AV */
status = cx231xx_set_power_mode ( dev ,
POLARIS_AVMODE_ENXTERNAL_AV ) ;
2009-03-03 12:14:34 +03:00
if ( status < 0 ) {
2009-03-04 23:49:01 +03:00
cx231xx_errdev ( " %s: set_power_mode : Failed to "
" set Power - errCode [%d]! \n " ,
__func__ , status ) ;
2009-03-03 12:14:34 +03:00
return status ;
}
}
2009-03-03 19:31:36 +03:00
status = cx231xx_set_decoder_video_input ( dev ,
INPUT ( input ) - > type ,
INPUT ( input ) - > vmux ) ;
2009-03-03 12:14:34 +03:00
break ;
case CX231XX_VMUX_TELEVISION :
case CX231XX_VMUX_CABLE :
if ( ( dev - > current_pcb_config . type = = USB_BUS_POWER ) & &
( dev - > power_mode ! = POLARIS_AVMODE_ANALOGT_TV ) ) {
2009-03-03 19:31:36 +03:00
/* Tuner */
status = cx231xx_set_power_mode ( dev ,
POLARIS_AVMODE_ANALOGT_TV ) ;
2009-03-03 12:14:34 +03:00
if ( status < 0 ) {
2009-03-04 23:49:01 +03:00
cx231xx_errdev ( " %s: set_power_mode:Failed "
" to set Power - errCode [%d]! \n " ,
__func__ , status ) ;
2009-03-03 12:14:34 +03:00
return status ;
}
}
2009-03-03 19:31:36 +03:00
status = cx231xx_set_decoder_video_input ( dev ,
CX231XX_VMUX_COMPOSITE1 ,
INPUT ( input ) - > vmux ) ;
2009-03-03 12:14:34 +03:00
break ;
default :
2009-03-04 23:49:01 +03:00
cx231xx_errdev ( " %s: set_power_mode : Unknown Input %d ! \n " ,
2009-03-03 12:14:34 +03:00
__func__ , INPUT ( input ) - > type ) ;
break ;
}
/* save the selection */
dev - > video_input = input ;
return status ;
2009-03-03 20:37:50 +03:00
}
2009-03-04 23:49:01 +03:00
int cx231xx_set_decoder_video_input ( struct cx231xx * dev ,
u8 pin_type , u8 input )
2009-03-03 20:37:50 +03:00
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
u32 value = 0 ;
if ( pin_type ! = dev - > video_input ) {
2009-03-22 04:00:20 +03:00
status = cx231xx_afe_adjust_ref_count ( dev , pin_type ) ;
2009-03-03 12:14:34 +03:00
if ( status < 0 ) {
2009-03-04 23:49:01 +03:00
cx231xx_errdev ( " %s: adjust_ref_count :Failed to set "
2009-03-22 04:00:20 +03:00
" AFE input mux - errCode [%d]! \n " ,
2009-03-04 23:49:01 +03:00
__func__ , status ) ;
2009-03-03 12:14:34 +03:00
return status ;
}
}
2009-03-03 20:37:50 +03:00
2009-03-22 04:00:20 +03:00
/* call afe block to set video inputs */
status = cx231xx_afe_set_input_mux ( dev , input ) ;
2009-03-03 12:14:34 +03:00
if ( status < 0 ) {
2009-03-04 23:49:01 +03:00
cx231xx_errdev ( " %s: set_input_mux :Failed to set "
2009-03-22 04:00:20 +03:00
" AFE input mux - errCode [%d]! \n " ,
2009-03-04 23:49:01 +03:00
__func__ , status ) ;
2009-03-03 12:14:34 +03:00
return status ;
}
switch ( pin_type ) {
case CX231XX_VMUX_COMPOSITE1 :
2009-03-22 04:00:20 +03:00
status = vid_blk_read_word ( dev , AFE_CTRL , & value ) ;
2009-03-03 19:31:36 +03:00
value | = ( 0 < < 13 ) | ( 1 < < 4 ) ;
value & = ~ ( 1 < < 5 ) ;
2009-03-04 23:49:01 +03:00
/* set [24:23] [22:15] to 0 */
value & = ( ~ ( 0x1ff8000 ) ) ;
/* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */
value | = 0x1000000 ;
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , AFE_CTRL , value ) ;
2009-03-03 19:31:36 +03:00
2009-03-22 04:00:20 +03:00
status = vid_blk_read_word ( dev , OUT_CTRL1 , & value ) ;
2009-03-03 19:31:36 +03:00
value | = ( 1 < < 7 ) ;
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , OUT_CTRL1 , value ) ;
2009-03-03 19:31:36 +03:00
/* Set vip 1.1 output mode */
status = cx231xx_read_modify_write_i2c_dword ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS ,
2009-03-03 19:31:36 +03:00
OUT_CTRL1 ,
FLD_OUT_MODE ,
OUT_MODE_VIP11 ) ;
/* Tell DIF object to go to baseband mode */
status = cx231xx_dif_set_standard ( dev , DIF_USE_BASEBAND ) ;
if ( status < 0 ) {
2009-03-04 23:49:01 +03:00
cx231xx_errdev ( " %s: cx231xx_dif set to By pass "
" mode- errCode [%d]! \n " ,
2009-03-03 19:31:36 +03:00
__func__ , status ) ;
return status ;
}
/* Read the DFE_CTRL1 register */
2009-03-22 04:00:20 +03:00
status = vid_blk_read_word ( dev , DFE_CTRL1 , & value ) ;
2009-03-03 19:31:36 +03:00
/* enable the VBI_GATE_EN */
value | = FLD_VBI_GATE_EN ;
/* Enable the auto-VGA enable */
value | = FLD_VGA_AUTO_EN ;
/* Write it back */
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , DFE_CTRL1 , value ) ;
2009-03-03 19:31:36 +03:00
/* Disable auto config of registers */
status = cx231xx_read_modify_write_i2c_dword ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS ,
2009-03-03 19:31:36 +03:00
MODE_CTRL , FLD_ACFG_DIS ,
cx231xx_set_field ( FLD_ACFG_DIS , 1 ) ) ;
/* Set CVBS input mode */
status = cx231xx_read_modify_write_i2c_dword ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS ,
2009-03-03 19:31:36 +03:00
MODE_CTRL , FLD_INPUT_MODE ,
cx231xx_set_field ( FLD_INPUT_MODE , INPUT_MODE_CVBS_0 ) ) ;
break ;
case CX231XX_VMUX_SVIDEO :
/* Disable the use of DIF */
2009-03-22 04:00:20 +03:00
status = vid_blk_read_word ( dev , AFE_CTRL , & value ) ;
2009-03-03 19:31:36 +03:00
2009-03-04 23:49:01 +03:00
/* set [24:23] [22:15] to 0 */
value & = ( ~ ( 0x1ff8000 ) ) ;
/* set FUNC_MODE[24:23] = 2
IF_MOD [ 22 : 15 ] = 0 DCR_BYP_CH2 [ 4 : 4 ] = 1 ; */
value | = 0x1000010 ;
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , AFE_CTRL , value ) ;
2009-03-03 19:31:36 +03:00
/* Tell DIF object to go to baseband mode */
status = cx231xx_dif_set_standard ( dev , DIF_USE_BASEBAND ) ;
if ( status < 0 ) {
2009-03-04 23:49:01 +03:00
cx231xx_errdev ( " %s: cx231xx_dif set to By pass "
" mode- errCode [%d]! \n " ,
2009-03-03 19:31:36 +03:00
__func__ , status ) ;
return status ;
}
/* Read the DFE_CTRL1 register */
2009-03-22 04:00:20 +03:00
status = vid_blk_read_word ( dev , DFE_CTRL1 , & value ) ;
2009-03-03 19:31:36 +03:00
/* enable the VBI_GATE_EN */
value | = FLD_VBI_GATE_EN ;
/* Enable the auto-VGA enable */
value | = FLD_VGA_AUTO_EN ;
/* Write it back */
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , DFE_CTRL1 , value ) ;
2009-03-03 19:31:36 +03:00
/* Disable auto config of registers */
status = cx231xx_read_modify_write_i2c_dword ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS ,
2009-03-03 19:31:36 +03:00
MODE_CTRL , FLD_ACFG_DIS ,
cx231xx_set_field ( FLD_ACFG_DIS , 1 ) ) ;
/* Set YC input mode */
status = cx231xx_read_modify_write_i2c_dword ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS ,
2009-03-03 19:31:36 +03:00
MODE_CTRL ,
FLD_INPUT_MODE ,
cx231xx_set_field ( FLD_INPUT_MODE , INPUT_MODE_YC_1 ) ) ;
/* Chroma to ADC2 */
2009-03-22 04:00:20 +03:00
status = vid_blk_read_word ( dev , AFE_CTRL , & value ) ;
2009-03-03 19:31:36 +03:00
value | = FLD_CHROMA_IN_SEL ; /* set the chroma in select */
/* Clear VGA_SEL_CH2 and VGA_SEL_CH3 (bits 7 and 8)
This sets them to use video
rather than audio . Only one of the two will be in use . */
value & = ~ ( FLD_VGA_SEL_CH2 | FLD_VGA_SEL_CH3 ) ;
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , AFE_CTRL , value ) ;
2009-03-03 19:31:36 +03:00
2009-03-22 04:00:20 +03:00
status = cx231xx_afe_set_mode ( dev , AFE_MODE_BASEBAND ) ;
2009-03-03 19:31:36 +03:00
break ;
case CX231XX_VMUX_TELEVISION :
case CX231XX_VMUX_CABLE :
default :
switch ( dev - > model ) {
case CX231XX_BOARD_CNXT_RDE_250 :
case CX231XX_BOARD_CNXT_RDU_250 :
/* Disable the use of DIF */
2009-03-22 04:00:20 +03:00
status = vid_blk_read_word ( dev , AFE_CTRL , & value ) ;
2009-03-03 12:14:34 +03:00
value | = ( 0 < < 13 ) | ( 1 < < 4 ) ;
value & = ~ ( 1 < < 5 ) ;
2009-03-04 23:49:01 +03:00
/* set [24:23] [22:15] to 0 */
value & = ( ~ ( 0x1FF8000 ) ) ;
/* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */
value | = 0x1000000 ;
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , AFE_CTRL , value ) ;
status = vid_blk_read_word ( dev , OUT_CTRL1 , & value ) ;
2009-03-03 12:14:34 +03:00
value | = ( 1 < < 7 ) ;
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , OUT_CTRL1 , value ) ;
2009-03-03 12:14:34 +03:00
/* Set vip 1.1 output mode */
2009-03-03 19:31:36 +03:00
status = cx231xx_read_modify_write_i2c_dword ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS ,
2009-03-03 19:31:36 +03:00
OUT_CTRL1 , FLD_OUT_MODE ,
OUT_MODE_VIP11 ) ;
2009-03-03 12:14:34 +03:00
2009-03-03 19:31:36 +03:00
/* Tell DIF object to go to baseband mode */
status = cx231xx_dif_set_standard ( dev ,
DIF_USE_BASEBAND ) ;
2009-03-03 12:14:34 +03:00
if ( status < 0 ) {
2009-03-04 23:49:01 +03:00
cx231xx_errdev ( " %s: cx231xx_dif set to By pass "
" mode- errCode [%d]! \n " ,
__func__ , status ) ;
2009-03-03 12:14:34 +03:00
return status ;
}
/* Read the DFE_CTRL1 register */
2009-03-22 04:00:20 +03:00
status = vid_blk_read_word ( dev , DFE_CTRL1 , & value ) ;
2009-03-03 12:14:34 +03:00
/* enable the VBI_GATE_EN */
value | = FLD_VBI_GATE_EN ;
/* Enable the auto-VGA enable */
value | = FLD_VGA_AUTO_EN ;
/* Write it back */
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , DFE_CTRL1 , value ) ;
2009-03-03 12:14:34 +03:00
/* Disable auto config of registers */
2009-03-03 19:31:36 +03:00
status = cx231xx_read_modify_write_i2c_dword ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS ,
2009-03-03 19:31:36 +03:00
MODE_CTRL , FLD_ACFG_DIS ,
cx231xx_set_field ( FLD_ACFG_DIS , 1 ) ) ;
2009-03-03 12:14:34 +03:00
/* Set CVBS input mode */
2009-03-03 19:31:36 +03:00
status = cx231xx_read_modify_write_i2c_dword ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS ,
2009-03-03 19:31:36 +03:00
MODE_CTRL , FLD_INPUT_MODE ,
2009-03-04 23:49:01 +03:00
cx231xx_set_field ( FLD_INPUT_MODE ,
INPUT_MODE_CVBS_0 ) ) ;
2009-03-03 19:31:36 +03:00
break ;
default :
/* Enable the DIF for the tuner */
2009-03-03 12:14:34 +03:00
2009-03-03 19:31:36 +03:00
/* Reinitialize the DIF */
status = cx231xx_dif_set_standard ( dev , dev - > norm ) ;
2009-03-03 12:14:34 +03:00
if ( status < 0 ) {
2009-03-04 23:49:01 +03:00
cx231xx_errdev ( " %s: cx231xx_dif set to By pass "
" mode- errCode [%d]! \n " ,
__func__ , status ) ;
2009-03-03 12:14:34 +03:00
return status ;
}
2009-03-03 19:31:36 +03:00
/* Make sure bypass is cleared */
2009-03-22 04:00:20 +03:00
status = vid_blk_read_word ( dev , DIF_MISC_CTRL , & value ) ;
2009-03-03 19:31:36 +03:00
/* Clear the bypass bit */
value & = ~ FLD_DIF_DIF_BYPASS ;
/* Enable the use of the DIF block */
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , DIF_MISC_CTRL , value ) ;
2009-03-03 19:31:36 +03:00
2009-03-03 12:14:34 +03:00
/* Read the DFE_CTRL1 register */
2009-03-22 04:00:20 +03:00
status = vid_blk_read_word ( dev , DFE_CTRL1 , & value ) ;
2009-03-03 12:14:34 +03:00
2009-03-03 19:31:36 +03:00
/* Disable the VBI_GATE_EN */
value & = ~ FLD_VBI_GATE_EN ;
2009-03-03 12:14:34 +03:00
2009-03-03 19:31:36 +03:00
/* Enable the auto-VGA enable, AGC, and
set the skip count to 2 */
value | = FLD_VGA_AUTO_EN | FLD_AGC_AUTO_EN | 0x00200000 ;
2009-03-03 12:14:34 +03:00
/* Write it back */
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , DFE_CTRL1 , value ) ;
2009-03-03 12:14:34 +03:00
2009-03-11 03:16:26 +03:00
/* Wait until AGC locks up */
2009-03-03 19:31:36 +03:00
msleep ( 1 ) ;
2009-03-03 12:14:34 +03:00
2009-03-03 19:31:36 +03:00
/* Disable the auto-VGA enable AGC */
value & = ~ ( FLD_VGA_AUTO_EN ) ;
2009-03-03 12:14:34 +03:00
2009-03-03 19:31:36 +03:00
/* Write it back */
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , DFE_CTRL1 , value ) ;
2009-03-03 12:14:34 +03:00
2009-03-03 19:31:36 +03:00
/* Enable Polaris B0 AGC output */
2009-03-22 04:00:20 +03:00
status = vid_blk_read_word ( dev , PIN_CTRL , & value ) ;
2009-03-03 19:31:36 +03:00
value | = ( FLD_OEF_AGC_RF ) |
( FLD_OEF_AGC_IFVGA ) |
( FLD_OEF_AGC_IF ) ;
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , PIN_CTRL , value ) ;
2009-03-03 19:31:36 +03:00
/* Set vip 1.1 output mode */
status = cx231xx_read_modify_write_i2c_dword ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS ,
2009-03-03 19:31:36 +03:00
OUT_CTRL1 , FLD_OUT_MODE ,
OUT_MODE_VIP11 ) ;
/* Disable auto config of registers */
status = cx231xx_read_modify_write_i2c_dword ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS ,
2009-03-03 19:31:36 +03:00
MODE_CTRL , FLD_ACFG_DIS ,
cx231xx_set_field ( FLD_ACFG_DIS , 1 ) ) ;
/* Set CVBS input mode */
status = cx231xx_read_modify_write_i2c_dword ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS ,
2009-03-03 19:31:36 +03:00
MODE_CTRL , FLD_INPUT_MODE ,
2009-03-04 23:49:01 +03:00
cx231xx_set_field ( FLD_INPUT_MODE ,
INPUT_MODE_CVBS_0 ) ) ;
2009-03-03 19:31:36 +03:00
2009-03-04 23:49:01 +03:00
/* Set some bits in AFE_CTRL so that channel 2 or 3
* is ready to receive audio */
2009-03-03 19:31:36 +03:00
/* Clear clamp for channels 2 and 3 (bit 16-17) */
/* Clear droop comp (bit 19-20) */
/* Set VGA_SEL (for audio control) (bit 7-8) */
2009-03-22 04:00:20 +03:00
status = vid_blk_read_word ( dev , AFE_CTRL , & value ) ;
2009-03-03 19:31:36 +03:00
value | = FLD_VGA_SEL_CH3 | FLD_VGA_SEL_CH2 ;
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , AFE_CTRL , value ) ;
2009-03-03 19:31:36 +03:00
break ;
2009-03-03 12:14:34 +03:00
}
break ;
}
/* Set raw VBI mode */
2009-03-03 19:31:36 +03:00
status = cx231xx_read_modify_write_i2c_dword ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS ,
2009-03-03 19:31:36 +03:00
OUT_CTRL1 , FLD_VBIHACTRAW_EN ,
cx231xx_set_field ( FLD_VBIHACTRAW_EN , 1 ) ) ;
2009-03-03 12:14:34 +03:00
2009-03-22 04:00:20 +03:00
status = vid_blk_read_word ( dev , OUT_CTRL1 , & value ) ;
2009-03-03 12:14:34 +03:00
if ( value & 0x02 ) {
value | = ( 1 < < 19 ) ;
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , OUT_CTRL1 , value ) ;
2009-03-03 12:14:34 +03:00
}
return status ;
2009-03-03 20:37:50 +03:00
}
/*
2009-03-04 23:49:01 +03:00
* Handle any video - mode specific overrides that are different
* on a per video standards basis after touching the MODE_CTRL
* register which resets many values for autodetect
2009-03-03 20:37:50 +03:00
*/
int cx231xx_do_mode_ctrl_overrides ( struct cx231xx * dev )
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
cx231xx_info ( " do_mode_ctrl_overrides : 0x%x \n " ,
( unsigned int ) dev - > norm ) ;
/* Change the DFE_CTRL3 bp_percent to fix flagging */
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , DFE_CTRL3 , 0xCD3F0280 ) ;
2009-03-03 12:14:34 +03:00
2009-03-11 03:16:26 +03:00
if ( dev - > norm & ( V4L2_STD_NTSC | V4L2_STD_PAL_M ) ) {
2009-03-03 12:14:34 +03:00
cx231xx_info ( " do_mode_ctrl_overrides NTSC \n " ) ;
2009-03-03 19:31:36 +03:00
/* Move the close caption lines out of active video,
adjust the active video start point */
status = cx231xx_read_modify_write_i2c_dword ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS ,
2009-03-03 12:14:34 +03:00
VERT_TIM_CTRL ,
FLD_VBLANK_CNT , 0x18 ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_read_modify_write_i2c_dword ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS ,
2009-03-03 12:14:34 +03:00
VERT_TIM_CTRL ,
FLD_VACTIVE_CNT ,
0x1E6000 ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_read_modify_write_i2c_dword ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS ,
2009-03-03 12:14:34 +03:00
VERT_TIM_CTRL ,
FLD_V656BLANK_CNT ,
0x1E000000 ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_read_modify_write_i2c_dword ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS ,
2009-03-03 12:14:34 +03:00
HORIZ_TIM_CTRL ,
FLD_HBLANK_CNT ,
cx231xx_set_field
( FLD_HBLANK_CNT , 0x79 ) ) ;
2009-03-11 03:16:26 +03:00
} else if ( dev - > norm & V4L2_STD_SECAM ) {
cx231xx_info ( " do_mode_ctrl_overrides SECAM \n " ) ;
status = cx231xx_read_modify_write_i2c_dword ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS ,
2009-03-03 12:14:34 +03:00
VERT_TIM_CTRL ,
FLD_VBLANK_CNT , 0x24 ) ;
/* Adjust the active video horizontal start point */
2009-03-03 19:31:36 +03:00
status = cx231xx_read_modify_write_i2c_dword ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS ,
2009-03-03 12:14:34 +03:00
HORIZ_TIM_CTRL ,
FLD_HBLANK_CNT ,
cx231xx_set_field
( FLD_HBLANK_CNT , 0x85 ) ) ;
2009-03-11 03:16:26 +03:00
} else {
cx231xx_info ( " do_mode_ctrl_overrides PAL \n " ) ;
status = cx231xx_read_modify_write_i2c_dword ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS ,
2009-03-03 12:14:34 +03:00
VERT_TIM_CTRL ,
FLD_VBLANK_CNT , 0x24 ) ;
/* Adjust the active video horizontal start point */
2009-03-03 19:31:36 +03:00
status = cx231xx_read_modify_write_i2c_dword ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS ,
2009-03-03 12:14:34 +03:00
HORIZ_TIM_CTRL ,
FLD_HBLANK_CNT ,
cx231xx_set_field
( FLD_HBLANK_CNT , 0x85 ) ) ;
}
return status ;
2009-03-03 20:37:50 +03:00
}
int cx231xx_set_audio_input ( struct cx231xx * dev , u8 input )
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
enum AUDIO_INPUT ainput = AUDIO_INPUT_LINE ;
switch ( INPUT ( input ) - > amux ) {
case CX231XX_AMUX_VIDEO :
ainput = AUDIO_INPUT_TUNER_TV ;
break ;
case CX231XX_AMUX_LINE_IN :
2009-03-22 04:00:20 +03:00
status = cx231xx_i2s_blk_set_audio_input ( dev , input ) ;
2009-03-03 12:14:34 +03:00
ainput = AUDIO_INPUT_LINE ;
break ;
default :
break ;
}
status = cx231xx_set_audio_decoder_input ( dev , ainput ) ;
return status ;
2009-03-03 20:37:50 +03:00
}
2009-03-03 12:14:34 +03:00
int cx231xx_set_audio_decoder_input ( struct cx231xx * dev ,
enum AUDIO_INPUT audio_input )
2009-03-03 20:37:50 +03:00
{
2009-03-03 12:14:34 +03:00
u32 dwval ;
int status ;
2009-03-22 04:00:20 +03:00
u8 gen_ctrl ;
2009-03-03 12:14:34 +03:00
u32 value = 0 ;
/* Put it in soft reset */
2009-03-22 04:00:20 +03:00
status = vid_blk_read_byte ( dev , GENERAL_CTL , & gen_ctrl ) ;
2009-03-03 12:14:34 +03:00
gen_ctrl | = 1 ;
2009-03-22 04:00:20 +03:00
status = vid_blk_write_byte ( dev , GENERAL_CTL , gen_ctrl ) ;
2009-03-03 12:14:34 +03:00
switch ( audio_input ) {
case AUDIO_INPUT_LINE :
/* setup AUD_IO control from Merlin paralle output */
2009-03-03 19:31:36 +03:00
value = cx231xx_set_field ( FLD_AUD_CHAN1_SRC ,
AUD_CHAN_SRC_PARALLEL ) ;
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , AUD_IO_CTRL , value ) ;
2009-03-03 12:14:34 +03:00
/* setup input to Merlin, SRC2 connect to AC97
bypass upsample - by - 2 , slave mode , sony mode , left justify
adr 091 c , dat 01000000 */
2009-03-22 04:00:20 +03:00
status = vid_blk_read_word ( dev , AC97_CTL , & dwval ) ;
2009-03-03 12:14:34 +03:00
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , AC97_CTL ,
( dwval | FLD_AC97_UP2X_BYPASS ) ) ;
2009-03-03 12:14:34 +03:00
/* select the parallel1 and SRC3 */
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , BAND_OUT_SEL ,
2009-03-03 19:31:36 +03:00
cx231xx_set_field ( FLD_SRC3_IN_SEL , 0x0 ) |
cx231xx_set_field ( FLD_SRC3_CLK_SEL , 0x0 ) |
2009-03-22 04:00:20 +03:00
cx231xx_set_field ( FLD_PARALLEL1_SRC_SEL , 0x0 ) ) ;
2009-03-03 12:14:34 +03:00
/* unmute all, AC97 in, independence mode
adr 08 d0 , data 0x00063073 */
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , PATH1_CTL1 , 0x00063073 ) ;
2009-03-03 12:14:34 +03:00
/* set AVC maximum threshold, adr 08d4, dat ffff0024 */
2009-03-22 04:00:20 +03:00
status = vid_blk_read_word ( dev , PATH1_VOL_CTL , & dwval ) ;
status = vid_blk_write_word ( dev , PATH1_VOL_CTL ,
( dwval | FLD_PATH1_AVC_THRESHOLD ) ) ;
2009-03-03 12:14:34 +03:00
/* set SC maximum threshold, adr 08ec, dat ffffb3a3 */
2009-03-22 04:00:20 +03:00
status = vid_blk_read_word ( dev , PATH1_SC_CTL , & dwval ) ;
status = vid_blk_write_word ( dev , PATH1_SC_CTL ,
( dwval | FLD_PATH1_SC_THRESHOLD ) ) ;
2009-03-03 12:14:34 +03:00
break ;
case AUDIO_INPUT_TUNER_TV :
default :
/* Setup SRC sources and clocks */
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , BAND_OUT_SEL ,
2009-03-03 19:31:36 +03:00
cx231xx_set_field ( FLD_SRC6_IN_SEL , 0x00 ) |
cx231xx_set_field ( FLD_SRC6_CLK_SEL , 0x01 ) |
cx231xx_set_field ( FLD_SRC5_IN_SEL , 0x00 ) |
cx231xx_set_field ( FLD_SRC5_CLK_SEL , 0x02 ) |
cx231xx_set_field ( FLD_SRC4_IN_SEL , 0x02 ) |
cx231xx_set_field ( FLD_SRC4_CLK_SEL , 0x03 ) |
cx231xx_set_field ( FLD_SRC3_IN_SEL , 0x00 ) |
cx231xx_set_field ( FLD_SRC3_CLK_SEL , 0x00 ) |
cx231xx_set_field ( FLD_BASEBAND_BYPASS_CTL , 0x00 ) |
cx231xx_set_field ( FLD_AC97_SRC_SEL , 0x03 ) |
cx231xx_set_field ( FLD_I2S_SRC_SEL , 0x00 ) |
cx231xx_set_field ( FLD_PARALLEL2_SRC_SEL , 0x02 ) |
2009-03-22 04:00:20 +03:00
cx231xx_set_field ( FLD_PARALLEL1_SRC_SEL , 0x01 ) ) ;
2009-03-03 12:14:34 +03:00
/* Setup the AUD_IO control */
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , AUD_IO_CTRL ,
2009-03-03 19:31:36 +03:00
cx231xx_set_field ( FLD_I2S_PORT_DIR , 0x00 ) |
cx231xx_set_field ( FLD_I2S_OUT_SRC , 0x00 ) |
cx231xx_set_field ( FLD_AUD_CHAN3_SRC , 0x00 ) |
cx231xx_set_field ( FLD_AUD_CHAN2_SRC , 0x00 ) |
2009-03-22 04:00:20 +03:00
cx231xx_set_field ( FLD_AUD_CHAN1_SRC , 0x03 ) ) ;
2009-03-03 12:14:34 +03:00
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , PATH1_CTL1 , 0x1F063870 ) ;
2009-03-03 12:14:34 +03:00
/* setAudioStandard(_audio_standard); */
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , PATH1_CTL1 , 0x00063870 ) ;
2009-03-03 12:14:34 +03:00
switch ( dev - > model ) {
case CX231XX_BOARD_CNXT_RDE_250 :
case CX231XX_BOARD_CNXT_RDU_250 :
2009-03-03 19:31:36 +03:00
status = cx231xx_read_modify_write_i2c_dword ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS ,
2009-03-03 19:31:36 +03:00
CHIP_CTRL ,
FLD_SIF_EN ,
cx231xx_set_field ( FLD_SIF_EN , 1 ) ) ;
2009-03-03 12:14:34 +03:00
break ;
default :
break ;
}
break ;
case AUDIO_INPUT_TUNER_FM :
/* use SIF for FM radio
setupFM ( ) ;
setAudioStandard ( _audio_standard ) ;
*/
break ;
case AUDIO_INPUT_MUTE :
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , PATH1_CTL1 , 0x1F011012 ) ;
2009-03-03 12:14:34 +03:00
break ;
}
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
/* Take it out of soft reset */
2009-03-22 04:00:20 +03:00
status = vid_blk_read_byte ( dev , GENERAL_CTL , & gen_ctrl ) ;
2009-03-03 12:14:34 +03:00
gen_ctrl & = ~ 1 ;
2009-03-22 04:00:20 +03:00
status = vid_blk_write_byte ( dev , GENERAL_CTL , gen_ctrl ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
return status ;
}
2009-03-03 20:37:50 +03:00
/* Set resolution of the video */
int cx231xx_resolution_set ( struct cx231xx * dev )
{
int width , height ;
2009-03-03 12:14:34 +03:00
u32 hscale , vscale ;
int status = 0 ;
2009-03-03 20:37:50 +03:00
width = dev - > width ;
height = dev - > height ;
2009-03-03 12:14:34 +03:00
get_scale ( dev , width , height , & hscale , & vscale ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
/* set horzontal scale */
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , HSCALE_CTRL , hscale ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
/* set vertical scale */
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , VSCALE_CTRL , vscale ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
return status ;
2009-03-03 20:37:50 +03:00
}
2009-03-03 19:31:36 +03:00
/******************************************************************************
* C H I P Specific C O N T R O L functions *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-03-03 20:37:50 +03:00
int cx231xx_init_ctrl_pin_status ( struct cx231xx * dev )
{
2009-03-03 12:14:34 +03:00
u32 value ;
int status = 0 ;
2009-03-03 20:37:50 +03:00
2009-03-22 04:00:20 +03:00
status = vid_blk_read_word ( dev , PIN_CTRL , & value ) ;
2009-03-03 12:14:34 +03:00
value | = ( ~ dev - > board . ctl_pin_status_mask ) ;
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , PIN_CTRL , value ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
return status ;
2009-03-03 20:37:50 +03:00
}
2009-03-03 12:14:34 +03:00
int cx231xx_set_agc_analog_digital_mux_select ( struct cx231xx * dev ,
u8 analog_or_digital )
2009-03-03 20:37:50 +03:00
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
/* first set the direction to output */
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_direction ( dev ,
dev - > board .
agc_analog_digital_select_gpio , 1 ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
/* 0 - demod ; 1 - Analog mode */
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_value ( dev ,
2009-03-03 12:14:34 +03:00
dev - > board . agc_analog_digital_select_gpio ,
analog_or_digital ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
return status ;
2009-03-03 20:37:50 +03:00
}
int cx231xx_enable_i2c_for_tuner ( struct cx231xx * dev , u8 I2CIndex )
{
2009-03-03 12:14:34 +03:00
u8 value [ 4 ] = { 0 , 0 , 0 , 0 } ;
int status = 0 ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
cx231xx_info ( " Changing the i2c port for tuner to %d \n " , I2CIndex ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 19:31:36 +03:00
status = cx231xx_read_ctrl_reg ( dev , VRT_GET_REGISTER ,
PWR_CTL_EN , value , 4 ) ;
2009-03-03 12:14:34 +03:00
if ( status < 0 )
return status ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
if ( I2CIndex = = I2C_1 ) {
if ( value [ 0 ] & I2C_DEMOD_EN ) {
value [ 0 ] & = ~ I2C_DEMOD_EN ;
2009-03-03 19:31:36 +03:00
status = cx231xx_write_ctrl_reg ( dev , VRT_SET_REGISTER ,
2009-03-03 12:14:34 +03:00
PWR_CTL_EN , value , 4 ) ;
}
} else {
if ( ! ( value [ 0 ] & I2C_DEMOD_EN ) ) {
value [ 0 ] | = I2C_DEMOD_EN ;
2009-03-03 19:31:36 +03:00
status = cx231xx_write_ctrl_reg ( dev , VRT_SET_REGISTER ,
2009-03-03 12:14:34 +03:00
PWR_CTL_EN , value , 4 ) ;
}
}
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
return status ;
2009-03-03 20:37:50 +03:00
}
2009-03-03 19:31:36 +03:00
/******************************************************************************
* D I F - B L O C K C O N T R O L functions *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-03-03 20:37:50 +03:00
int cx231xx_dif_configure_C2HH_for_low_IF ( struct cx231xx * dev , u32 mode ,
2009-03-03 12:14:34 +03:00
u32 function_mode , u32 standard )
2009-03-03 20:37:50 +03:00
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
if ( mode = = V4L2_TUNER_RADIO ) {
/* C2HH */
2009-03-04 23:49:01 +03:00
/* lo if big signal */
status = cx231xx_reg_mask_write ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS , 32 ,
2009-03-04 23:49:01 +03:00
AFE_CTRL_C2HH_SRC_CTRL , 30 , 31 , 0x1 ) ;
/* FUNC_MODE = DIF */
status = cx231xx_reg_mask_write ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS , 32 ,
2009-03-04 23:49:01 +03:00
AFE_CTRL_C2HH_SRC_CTRL , 23 , 24 , function_mode ) ;
/* IF_MODE */
status = cx231xx_reg_mask_write ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS , 32 ,
2009-03-04 23:49:01 +03:00
AFE_CTRL_C2HH_SRC_CTRL , 15 , 22 , 0xFF ) ;
/* no inv */
status = cx231xx_reg_mask_write ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS , 32 ,
2009-03-04 23:49:01 +03:00
AFE_CTRL_C2HH_SRC_CTRL , 9 , 9 , 0x1 ) ;
2009-03-11 03:16:26 +03:00
} else if ( standard ! = DIF_USE_BASEBAND ) {
if ( standard & V4L2_STD_MN ) {
2009-03-04 23:49:01 +03:00
/* lo if big signal */
2009-03-03 19:31:36 +03:00
status = cx231xx_reg_mask_write ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS , 32 ,
2009-03-04 23:49:01 +03:00
AFE_CTRL_C2HH_SRC_CTRL , 30 , 31 , 0x1 ) ;
/* FUNC_MODE = DIF */
2009-03-03 19:31:36 +03:00
status = cx231xx_reg_mask_write ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 19:31:36 +03:00
AFE_CTRL_C2HH_SRC_CTRL , 23 , 24 ,
2009-03-04 23:49:01 +03:00
function_mode ) ;
/* IF_MODE */
2009-03-03 19:31:36 +03:00
status = cx231xx_reg_mask_write ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS , 32 ,
2009-03-04 23:49:01 +03:00
AFE_CTRL_C2HH_SRC_CTRL , 15 , 22 , 0xb ) ;
/* no inv */
2009-03-03 19:31:36 +03:00
status = cx231xx_reg_mask_write ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS , 32 ,
2009-03-04 23:49:01 +03:00
AFE_CTRL_C2HH_SRC_CTRL , 9 , 9 , 0x1 ) ;
/* 0x124, AUD_CHAN1_SRC = 0x3 */
2009-03-03 19:31:36 +03:00
status = cx231xx_reg_mask_write ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS , 32 ,
2009-03-04 23:49:01 +03:00
AUD_IO_CTRL , 0 , 31 , 0x00000003 ) ;
2009-03-11 03:16:26 +03:00
} else if ( ( standard = = V4L2_STD_PAL_I ) |
( standard & V4L2_STD_SECAM ) ) {
2009-03-03 12:14:34 +03:00
/* C2HH setup */
2009-03-04 23:49:01 +03:00
/* lo if big signal */
2009-03-03 19:31:36 +03:00
status = cx231xx_reg_mask_write ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS , 32 ,
2009-03-04 23:49:01 +03:00
AFE_CTRL_C2HH_SRC_CTRL , 30 , 31 , 0x1 ) ;
/* FUNC_MODE = DIF */
2009-03-03 19:31:36 +03:00
status = cx231xx_reg_mask_write ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 19:31:36 +03:00
AFE_CTRL_C2HH_SRC_CTRL , 23 , 24 ,
2009-03-04 23:49:01 +03:00
function_mode ) ;
/* IF_MODE */
2009-03-03 19:31:36 +03:00
status = cx231xx_reg_mask_write ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS , 32 ,
2009-03-11 03:16:26 +03:00
AFE_CTRL_C2HH_SRC_CTRL , 15 , 22 , 0xF ) ;
2009-03-04 23:49:01 +03:00
/* no inv */
2009-03-03 19:31:36 +03:00
status = cx231xx_reg_mask_write ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS , 32 ,
2009-03-04 23:49:01 +03:00
AFE_CTRL_C2HH_SRC_CTRL , 9 , 9 , 0x1 ) ;
2009-03-11 03:16:26 +03:00
} else {
/* default PAL BG */
2009-03-03 12:14:34 +03:00
/* C2HH setup */
2009-03-04 23:49:01 +03:00
/* lo if big signal */
2009-03-03 19:31:36 +03:00
status = cx231xx_reg_mask_write ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS , 32 ,
2009-03-04 23:49:01 +03:00
AFE_CTRL_C2HH_SRC_CTRL , 30 , 31 , 0x1 ) ;
/* FUNC_MODE = DIF */
2009-03-03 19:31:36 +03:00
status = cx231xx_reg_mask_write ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 19:31:36 +03:00
AFE_CTRL_C2HH_SRC_CTRL , 23 , 24 ,
2009-03-04 23:49:01 +03:00
function_mode ) ;
/* IF_MODE */
2009-03-03 19:31:36 +03:00
status = cx231xx_reg_mask_write ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS , 32 ,
2009-03-11 03:16:26 +03:00
AFE_CTRL_C2HH_SRC_CTRL , 15 , 22 , 0xE ) ;
2009-03-04 23:49:01 +03:00
/* no inv */
2009-03-03 19:31:36 +03:00
status = cx231xx_reg_mask_write ( dev ,
2009-03-22 04:00:20 +03:00
VID_BLK_I2C_ADDRESS , 32 ,
2009-03-04 23:49:01 +03:00
AFE_CTRL_C2HH_SRC_CTRL , 9 , 9 , 0x1 ) ;
2009-03-03 12:14:34 +03:00
}
}
return status ;
2009-03-03 20:37:50 +03:00
}
int cx231xx_dif_set_standard ( struct cx231xx * dev , u32 standard )
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
u32 dif_misc_ctrl_value = 0 ;
u32 func_mode = 0 ;
cx231xx_info ( " %s: setStandard to %x \n " , __func__ , standard ) ;
2009-03-22 04:00:20 +03:00
status = vid_blk_read_word ( dev , DIF_MISC_CTRL , & dif_misc_ctrl_value ) ;
2009-03-03 12:14:34 +03:00
if ( standard ! = DIF_USE_BASEBAND )
dev - > norm = standard ;
switch ( dev - > model ) {
case CX231XX_BOARD_CNXT_RDE_250 :
case CX231XX_BOARD_CNXT_RDU_250 :
func_mode = 0x03 ;
break ;
default :
func_mode = 0x01 ;
}
2009-03-03 19:31:36 +03:00
status = cx231xx_dif_configure_C2HH_for_low_IF ( dev , dev - > active_mode ,
2009-03-03 12:14:34 +03:00
func_mode , standard ) ;
if ( standard = = DIF_USE_BASEBAND ) { /* base band */
2009-03-03 19:31:36 +03:00
/* There is a different SRC_PHASE_INC value
for baseband vs . DIF */
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , DIF_SRC_PHASE_INC , 0xDF7DF83 ) ;
status = vid_blk_read_word ( dev , DIF_MISC_CTRL ,
& dif_misc_ctrl_value ) ;
2009-03-03 12:14:34 +03:00
dif_misc_ctrl_value | = FLD_DIF_DIF_BYPASS ;
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , DIF_MISC_CTRL ,
dif_misc_ctrl_value ) ;
2009-03-03 12:14:34 +03:00
} else if ( standard & V4L2_STD_PAL_D ) {
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_PLL_CTRL , 0 , 31 , 0x6503bc0c ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_PLL_CTRL1 , 0 , 31 , 0xbd038c85 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_PLL_CTRL2 , 0 , 31 , 0x1db4640a ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_PLL_CTRL3 , 0 , 31 , 0x00008800 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AGC_IF_REF , 0 , 31 , 0x444C1380 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AGC_CTRL_IF , 0 , 31 , 0xDA302600 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AGC_CTRL_INT , 0 , 31 , 0xDA261700 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AGC_CTRL_RF , 0 , 31 , 0xDA262600 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AGC_IF_INT_CURRENT , 0 , 31 ,
0x26001700 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AGC_RF_CURRENT , 0 , 31 ,
0x00002660 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_VIDEO_AGC_CTRL , 0 , 31 ,
0x72500800 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_VID_AUD_OVERRIDE , 0 , 31 ,
0x27000100 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AV_SEP_CTRL , 0 , 31 , 0x3F3934EA ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_COMP_FLT_CTRL , 0 , 31 ,
0x00000000 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_SRC_PHASE_INC , 0 , 31 ,
0x1befbf06 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_SRC_GAIN_CONTROL , 0 , 31 ,
0x000035e8 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_RPT_VARIANCE , 0 , 31 , 0x00000000 ) ;
/* Save the Spec Inversion value */
dif_misc_ctrl_value & = FLD_DIF_SPEC_INV ;
dif_misc_ctrl_value | = 0x3a023F11 ;
} else if ( standard & V4L2_STD_PAL_I ) {
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_PLL_CTRL , 0 , 31 , 0x6503bc0c ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_PLL_CTRL1 , 0 , 31 , 0xbd038c85 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_PLL_CTRL2 , 0 , 31 , 0x1db4640a ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_PLL_CTRL3 , 0 , 31 , 0x00008800 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AGC_IF_REF , 0 , 31 , 0x444C1380 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AGC_CTRL_IF , 0 , 31 , 0xDA302600 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AGC_CTRL_INT , 0 , 31 , 0xDA261700 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AGC_CTRL_RF , 0 , 31 , 0xDA262600 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AGC_IF_INT_CURRENT , 0 , 31 ,
0x26001700 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AGC_RF_CURRENT , 0 , 31 ,
0x00002660 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_VIDEO_AGC_CTRL , 0 , 31 ,
0x72500800 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_VID_AUD_OVERRIDE , 0 , 31 ,
0x27000100 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AV_SEP_CTRL , 0 , 31 , 0x5F39A934 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_COMP_FLT_CTRL , 0 , 31 ,
0x00000000 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_SRC_PHASE_INC , 0 , 31 ,
0x1befbf06 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_SRC_GAIN_CONTROL , 0 , 31 ,
0x000035e8 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_RPT_VARIANCE , 0 , 31 , 0x00000000 ) ;
/* Save the Spec Inversion value */
dif_misc_ctrl_value & = FLD_DIF_SPEC_INV ;
dif_misc_ctrl_value | = 0x3a033F11 ;
} else if ( standard & V4L2_STD_PAL_M ) {
/* improved Low Frequency Phase Noise */
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , DIF_PLL_CTRL , 0xFF01FF0C ) ;
status = vid_blk_write_word ( dev , DIF_PLL_CTRL1 , 0xbd038c85 ) ;
status = vid_blk_write_word ( dev , DIF_PLL_CTRL2 , 0x1db4640a ) ;
status = vid_blk_write_word ( dev , DIF_PLL_CTRL3 , 0x00008800 ) ;
status = vid_blk_write_word ( dev , DIF_AGC_IF_REF , 0x444C1380 ) ;
status = vid_blk_write_word ( dev , DIF_AGC_IF_INT_CURRENT ,
0x26001700 ) ;
status = vid_blk_write_word ( dev , DIF_AGC_RF_CURRENT ,
0x00002660 ) ;
status = vid_blk_write_word ( dev , DIF_VIDEO_AGC_CTRL ,
0x72500800 ) ;
status = vid_blk_write_word ( dev , DIF_VID_AUD_OVERRIDE ,
0x27000100 ) ;
status = vid_blk_write_word ( dev , DIF_AV_SEP_CTRL , 0x012c405d ) ;
status = vid_blk_write_word ( dev , DIF_COMP_FLT_CTRL ,
0x009f50c1 ) ;
status = vid_blk_write_word ( dev , DIF_SRC_PHASE_INC ,
0x1befbf06 ) ;
status = vid_blk_write_word ( dev , DIF_SRC_GAIN_CONTROL ,
0x000035e8 ) ;
status = vid_blk_write_word ( dev , DIF_SOFT_RST_CTRL_REVB ,
0x00000000 ) ;
2009-03-03 12:14:34 +03:00
/* Save the Spec Inversion value */
dif_misc_ctrl_value & = FLD_DIF_SPEC_INV ;
dif_misc_ctrl_value | = 0x3A0A3F10 ;
} else if ( standard & ( V4L2_STD_PAL_N | V4L2_STD_PAL_Nc ) ) {
/* improved Low Frequency Phase Noise */
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , DIF_PLL_CTRL , 0xFF01FF0C ) ;
status = vid_blk_write_word ( dev , DIF_PLL_CTRL1 , 0xbd038c85 ) ;
status = vid_blk_write_word ( dev , DIF_PLL_CTRL2 , 0x1db4640a ) ;
status = vid_blk_write_word ( dev , DIF_PLL_CTRL3 , 0x00008800 ) ;
status = vid_blk_write_word ( dev , DIF_AGC_IF_REF , 0x444C1380 ) ;
status = vid_blk_write_word ( dev , DIF_AGC_IF_INT_CURRENT ,
0x26001700 ) ;
status = vid_blk_write_word ( dev , DIF_AGC_RF_CURRENT ,
0x00002660 ) ;
status = vid_blk_write_word ( dev , DIF_VIDEO_AGC_CTRL ,
0x72500800 ) ;
status = vid_blk_write_word ( dev , DIF_VID_AUD_OVERRIDE ,
0x27000100 ) ;
status = vid_blk_write_word ( dev , DIF_AV_SEP_CTRL ,
0x012c405d ) ;
status = vid_blk_write_word ( dev , DIF_COMP_FLT_CTRL ,
0x009f50c1 ) ;
status = vid_blk_write_word ( dev , DIF_SRC_PHASE_INC ,
0x1befbf06 ) ;
status = vid_blk_write_word ( dev , DIF_SRC_GAIN_CONTROL ,
0x000035e8 ) ;
status = vid_blk_write_word ( dev , DIF_SOFT_RST_CTRL_REVB ,
0x00000000 ) ;
2009-03-03 12:14:34 +03:00
/* Save the Spec Inversion value */
dif_misc_ctrl_value & = FLD_DIF_SPEC_INV ;
dif_misc_ctrl_value = 0x3A093F10 ;
} else if ( standard &
2009-03-11 03:16:26 +03:00
( V4L2_STD_SECAM_B | V4L2_STD_SECAM_D | V4L2_STD_SECAM_G |
V4L2_STD_SECAM_K | V4L2_STD_SECAM_K1 ) ) {
2009-03-03 12:14:34 +03:00
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_PLL_CTRL , 0 , 31 , 0x6503bc0c ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_PLL_CTRL1 , 0 , 31 , 0xbd038c85 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_PLL_CTRL2 , 0 , 31 , 0x1db4640a ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_PLL_CTRL3 , 0 , 31 , 0x00008800 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AGC_IF_REF , 0 , 31 , 0x888C0380 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AGC_CTRL_IF , 0 , 31 , 0xe0262600 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AGC_CTRL_INT , 0 , 31 , 0xc2171700 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AGC_CTRL_RF , 0 , 31 , 0xc2262600 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AGC_IF_INT_CURRENT , 0 , 31 ,
0x26001700 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AGC_RF_CURRENT , 0 , 31 ,
0x00002660 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_VID_AUD_OVERRIDE , 0 , 31 ,
0x27000100 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AV_SEP_CTRL , 0 , 31 , 0x3F3530ec ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_COMP_FLT_CTRL , 0 , 31 ,
0x00000000 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_SRC_PHASE_INC , 0 , 31 ,
0x1befbf06 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_SRC_GAIN_CONTROL , 0 , 31 ,
0x000035e8 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_RPT_VARIANCE , 0 , 31 , 0x00000000 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_VIDEO_AGC_CTRL , 0 , 31 ,
0xf4000000 ) ;
/* Save the Spec Inversion value */
dif_misc_ctrl_value & = FLD_DIF_SPEC_INV ;
dif_misc_ctrl_value | = 0x3a023F11 ;
} else if ( standard & ( V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC ) ) {
/* Is it SECAM_L1? */
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_PLL_CTRL , 0 , 31 , 0x6503bc0c ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_PLL_CTRL1 , 0 , 31 , 0xbd038c85 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_PLL_CTRL2 , 0 , 31 , 0x1db4640a ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_PLL_CTRL3 , 0 , 31 , 0x00008800 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AGC_IF_REF , 0 , 31 , 0x888C0380 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AGC_CTRL_IF , 0 , 31 , 0xe0262600 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AGC_CTRL_INT , 0 , 31 , 0xc2171700 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AGC_CTRL_RF , 0 , 31 , 0xc2262600 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AGC_IF_INT_CURRENT , 0 , 31 ,
0x26001700 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AGC_RF_CURRENT , 0 , 31 ,
0x00002660 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_VID_AUD_OVERRIDE , 0 , 31 ,
0x27000100 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_AV_SEP_CTRL , 0 , 31 , 0x3F3530ec ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_COMP_FLT_CTRL , 0 , 31 ,
0x00000000 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_SRC_PHASE_INC , 0 , 31 ,
0x1befbf06 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_SRC_GAIN_CONTROL , 0 , 31 ,
0x000035e8 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_RPT_VARIANCE , 0 , 31 , 0x00000000 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-03 12:14:34 +03:00
DIF_VIDEO_AGC_CTRL , 0 , 31 ,
0xf2560000 ) ;
/* Save the Spec Inversion value */
dif_misc_ctrl_value & = FLD_DIF_SPEC_INV ;
dif_misc_ctrl_value | = 0x3a023F11 ;
2009-03-11 03:16:26 +03:00
} else if ( standard & V4L2_STD_NTSC_M ) {
2009-03-03 19:31:36 +03:00
/* V4L2_STD_NTSC_M (75 IRE Setup) Or
V4L2_STD_NTSC_M_JP ( Japan , 0 IRE Setup ) */
2009-03-03 12:14:34 +03:00
2009-03-03 19:31:36 +03:00
/* For NTSC the centre frequency of video coming out of
sidewinder is around 7.1 MHz or 3.6 MHz depending on the
spectral inversion . so for a non spectrally inverted channel
the pll freq word is 0x03420c49
2009-03-03 12:14:34 +03:00
*/
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , DIF_PLL_CTRL , 0x6503BC0C ) ;
status = vid_blk_write_word ( dev , DIF_PLL_CTRL1 , 0xBD038C85 ) ;
status = vid_blk_write_word ( dev , DIF_PLL_CTRL2 , 0x1DB4640A ) ;
status = vid_blk_write_word ( dev , DIF_PLL_CTRL3 , 0x00008800 ) ;
status = vid_blk_write_word ( dev , DIF_AGC_IF_REF , 0x444C0380 ) ;
status = vid_blk_write_word ( dev , DIF_AGC_IF_INT_CURRENT ,
0x26001700 ) ;
status = vid_blk_write_word ( dev , DIF_AGC_RF_CURRENT ,
0x00002660 ) ;
status = vid_blk_write_word ( dev , DIF_VIDEO_AGC_CTRL ,
0x04000800 ) ;
status = vid_blk_write_word ( dev , DIF_VID_AUD_OVERRIDE ,
0x27000100 ) ;
status = vid_blk_write_word ( dev , DIF_AV_SEP_CTRL , 0x01296e1f ) ;
status = vid_blk_write_word ( dev , DIF_COMP_FLT_CTRL ,
0x009f50c1 ) ;
status = vid_blk_write_word ( dev , DIF_SRC_PHASE_INC ,
0x1befbf06 ) ;
status = vid_blk_write_word ( dev , DIF_SRC_GAIN_CONTROL ,
0x000035e8 ) ;
status = vid_blk_write_word ( dev , DIF_AGC_CTRL_IF , 0xC2262600 ) ;
status = vid_blk_write_word ( dev , DIF_AGC_CTRL_INT ,
0xC2262600 ) ;
status = vid_blk_write_word ( dev , DIF_AGC_CTRL_RF , 0xC2262600 ) ;
2009-03-03 12:14:34 +03:00
/* Save the Spec Inversion value */
dif_misc_ctrl_value & = FLD_DIF_SPEC_INV ;
dif_misc_ctrl_value | = 0x3a003F10 ;
2009-03-11 03:16:26 +03:00
} else {
/* default PAL BG */
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-11 03:16:26 +03:00
DIF_PLL_CTRL , 0 , 31 , 0x6503bc0c ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-11 03:16:26 +03:00
DIF_PLL_CTRL1 , 0 , 31 , 0xbd038c85 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-11 03:16:26 +03:00
DIF_PLL_CTRL2 , 0 , 31 , 0x1db4640a ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-11 03:16:26 +03:00
DIF_PLL_CTRL3 , 0 , 31 , 0x00008800 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-11 03:16:26 +03:00
DIF_AGC_IF_REF , 0 , 31 , 0x444C1380 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-11 03:16:26 +03:00
DIF_AGC_CTRL_IF , 0 , 31 , 0xDA302600 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-11 03:16:26 +03:00
DIF_AGC_CTRL_INT , 0 , 31 , 0xDA261700 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-11 03:16:26 +03:00
DIF_AGC_CTRL_RF , 0 , 31 , 0xDA262600 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-11 03:16:26 +03:00
DIF_AGC_IF_INT_CURRENT , 0 , 31 ,
0x26001700 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-11 03:16:26 +03:00
DIF_AGC_RF_CURRENT , 0 , 31 ,
0x00002660 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-11 03:16:26 +03:00
DIF_VIDEO_AGC_CTRL , 0 , 31 ,
0x72500800 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-11 03:16:26 +03:00
DIF_VID_AUD_OVERRIDE , 0 , 31 ,
0x27000100 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-11 03:16:26 +03:00
DIF_AV_SEP_CTRL , 0 , 31 , 0x3F3530EC ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-11 03:16:26 +03:00
DIF_COMP_FLT_CTRL , 0 , 31 ,
0x00A653A8 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-11 03:16:26 +03:00
DIF_SRC_PHASE_INC , 0 , 31 ,
0x1befbf06 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-11 03:16:26 +03:00
DIF_SRC_GAIN_CONTROL , 0 , 31 ,
0x000035e8 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_reg_mask_write ( dev , VID_BLK_I2C_ADDRESS , 32 ,
2009-03-11 03:16:26 +03:00
DIF_RPT_VARIANCE , 0 , 31 , 0x00000000 ) ;
/* Save the Spec Inversion value */
dif_misc_ctrl_value & = FLD_DIF_SPEC_INV ;
dif_misc_ctrl_value | = 0x3a013F11 ;
2009-03-03 12:14:34 +03:00
}
/* The AGC values should be the same for all standards,
AUD_SRC_SEL [ 19 ] should always be disabled */
dif_misc_ctrl_value & = ~ FLD_DIF_AUD_SRC_SEL ;
2009-03-03 19:31:36 +03:00
/* It is still possible to get Set Standard calls even when we
are in FM mode .
2009-03-03 12:14:34 +03:00
This is done to override the value for FM . */
if ( dev - > active_mode = = V4L2_TUNER_RADIO )
dif_misc_ctrl_value = 0x7a080000 ;
/* Write the calculated value for misc ontrol register */
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , DIF_MISC_CTRL , dif_misc_ctrl_value ) ;
2009-03-03 12:14:34 +03:00
return status ;
2009-03-03 20:37:50 +03:00
}
int cx231xx_tuner_pre_channel_change ( struct cx231xx * dev )
{
int status = 0 ;
u32 dwval ;
/* Set the RF and IF k_agc values to 3 */
2009-03-22 04:00:20 +03:00
status = vid_blk_read_word ( dev , DIF_AGC_IF_REF , & dwval ) ;
2009-03-03 20:37:50 +03:00
dwval & = ~ ( FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF ) ;
dwval | = 0x33000000 ;
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , DIF_AGC_IF_REF , dwval ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
return status ;
2009-03-03 20:37:50 +03:00
}
int cx231xx_tuner_post_channel_change ( struct cx231xx * dev )
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
2009-03-03 20:37:50 +03:00
u32 dwval ;
2009-03-11 03:16:26 +03:00
/* Set the RF and IF k_agc values to 4 for PAL/NTSC and 8 for
* SECAM L / B / D standards */
2009-03-22 04:00:20 +03:00
status = vid_blk_read_word ( dev , DIF_AGC_IF_REF , & dwval ) ;
2009-03-03 12:14:34 +03:00
dwval & = ~ ( FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 19:31:36 +03:00
if ( dev - > norm & ( V4L2_STD_SECAM_L | V4L2_STD_SECAM_B |
V4L2_STD_SECAM_D ) )
2009-03-03 12:14:34 +03:00
dwval | = 0x88000000 ;
2009-03-03 19:31:36 +03:00
else
2009-03-03 12:14:34 +03:00
dwval | = 0x44000000 ;
2009-03-03 20:37:50 +03:00
2009-03-22 04:00:20 +03:00
status = vid_blk_write_word ( dev , DIF_AGC_IF_REF , dwval ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
return status ;
2009-03-03 20:37:50 +03:00
}
2009-03-03 19:31:36 +03:00
/******************************************************************************
2009-03-22 04:00:20 +03:00
* I 2 S - B L O C K C O N T R O L functions *
2009-03-03 19:31:36 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-03-22 04:00:20 +03:00
int cx231xx_i2s_blk_initialize ( struct cx231xx * dev )
2009-03-03 20:37:50 +03:00
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
u32 value ;
2009-03-22 04:00:20 +03:00
status = cx231xx_read_i2c_data ( dev , I2S_BLK_DEVICE_ADDRESS ,
2009-03-03 19:31:36 +03:00
CH_PWR_CTRL1 , 1 , & value , 1 ) ;
2009-03-03 12:14:34 +03:00
/* enables clock to delta-sigma and decimation filter */
value | = 0x80 ;
2009-03-22 04:00:20 +03:00
status = cx231xx_write_i2c_data ( dev , I2S_BLK_DEVICE_ADDRESS ,
2009-03-03 12:14:34 +03:00
CH_PWR_CTRL1 , 1 , value , 1 ) ;
/* power up all channel */
2009-03-22 04:00:20 +03:00
status = cx231xx_write_i2c_data ( dev , I2S_BLK_DEVICE_ADDRESS ,
2009-03-03 12:14:34 +03:00
CH_PWR_CTRL2 , 1 , 0x00 , 1 ) ;
return status ;
2009-03-03 20:37:50 +03:00
}
2009-03-22 04:00:20 +03:00
int cx231xx_i2s_blk_update_power_control ( struct cx231xx * dev ,
2009-03-11 03:16:26 +03:00
enum AV_MODE avmode )
2009-03-03 20:37:50 +03:00
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
u32 value = 0 ;
if ( avmode ! = POLARIS_AVMODE_ENXTERNAL_AV ) {
2009-03-22 04:00:20 +03:00
status = cx231xx_read_i2c_data ( dev , I2S_BLK_DEVICE_ADDRESS ,
2009-03-03 12:14:34 +03:00
CH_PWR_CTRL2 , 1 , & value , 1 ) ;
value | = 0xfe ;
2009-03-22 04:00:20 +03:00
status = cx231xx_write_i2c_data ( dev , I2S_BLK_DEVICE_ADDRESS ,
2009-03-03 12:14:34 +03:00
CH_PWR_CTRL2 , 1 , value , 1 ) ;
} else {
2009-03-22 04:00:20 +03:00
status = cx231xx_write_i2c_data ( dev , I2S_BLK_DEVICE_ADDRESS ,
2009-03-03 12:14:34 +03:00
CH_PWR_CTRL2 , 1 , 0x00 , 1 ) ;
}
return status ;
2009-03-03 20:37:50 +03:00
}
2009-03-22 04:00:20 +03:00
/* set i2s_blk for audio input types */
int cx231xx_i2s_blk_set_audio_input ( struct cx231xx * dev , u8 audio_input )
2009-03-03 20:37:50 +03:00
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
switch ( audio_input ) {
case CX231XX_AMUX_LINE_IN :
2009-03-22 04:00:20 +03:00
status = cx231xx_write_i2c_data ( dev , I2S_BLK_DEVICE_ADDRESS ,
2009-03-03 12:14:34 +03:00
CH_PWR_CTRL2 , 1 , 0x00 , 1 ) ;
2009-03-22 04:00:20 +03:00
status = cx231xx_write_i2c_data ( dev , I2S_BLK_DEVICE_ADDRESS ,
2009-03-03 12:14:34 +03:00
CH_PWR_CTRL1 , 1 , 0x80 , 1 ) ;
break ;
case CX231XX_AMUX_VIDEO :
default :
break ;
}
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
dev - > ctl_ainput = audio_input ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
return status ;
2009-03-03 20:37:50 +03:00
}
2009-03-03 19:31:36 +03:00
/******************************************************************************
* P O W E R C O N T R O L functions *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-03-11 03:16:26 +03:00
int cx231xx_set_power_mode ( struct cx231xx * dev , enum AV_MODE mode )
2009-03-03 20:37:50 +03:00
{
2009-03-03 12:14:34 +03:00
u8 value [ 4 ] = { 0 , 0 , 0 , 0 } ;
u32 tmp = 0 ;
int status = 0 ;
if ( dev - > power_mode ! = mode )
dev - > power_mode = mode ;
else {
cx231xx_info ( " setPowerMode::mode = %d, No Change req. \n " ,
mode ) ;
return 0 ;
}
cx231xx_info ( " setPowerMode::mode = %d \n " , mode ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_read_ctrl_reg ( dev , VRT_GET_REGISTER , PWR_CTL_EN , value ,
4 ) ;
2009-03-03 12:14:34 +03:00
if ( status < 0 )
return status ;
tmp = * ( ( u32 * ) value ) ;
switch ( mode ) {
case POLARIS_AVMODE_ENXTERNAL_AV :
tmp & = ( ~ PWR_MODE_MASK ) ;
tmp | = PWR_AV_EN ;
value [ 0 ] = ( u8 ) tmp ;
value [ 1 ] = ( u8 ) ( tmp > > 8 ) ;
value [ 2 ] = ( u8 ) ( tmp > > 16 ) ;
value [ 3 ] = ( u8 ) ( tmp > > 24 ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_write_ctrl_reg ( dev , VRT_SET_REGISTER ,
PWR_CTL_EN , value , 4 ) ;
2009-03-03 12:14:34 +03:00
msleep ( PWR_SLEEP_INTERVAL ) ;
tmp | = PWR_ISO_EN ;
value [ 0 ] = ( u8 ) tmp ;
value [ 1 ] = ( u8 ) ( tmp > > 8 ) ;
value [ 2 ] = ( u8 ) ( tmp > > 16 ) ;
value [ 3 ] = ( u8 ) ( tmp > > 24 ) ;
status =
cx231xx_write_ctrl_reg ( dev , VRT_SET_REGISTER , PWR_CTL_EN ,
value , 4 ) ;
msleep ( PWR_SLEEP_INTERVAL ) ;
tmp | = POLARIS_AVMODE_ENXTERNAL_AV ;
value [ 0 ] = ( u8 ) tmp ;
value [ 1 ] = ( u8 ) ( tmp > > 8 ) ;
value [ 2 ] = ( u8 ) ( tmp > > 16 ) ;
value [ 3 ] = ( u8 ) ( tmp > > 24 ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_write_ctrl_reg ( dev , VRT_SET_REGISTER ,
PWR_CTL_EN , value , 4 ) ;
2009-03-03 12:14:34 +03:00
2009-03-04 23:49:01 +03:00
/* reset state of xceive tuner */
dev - > xc_fw_load_done = 0 ;
2009-03-03 12:14:34 +03:00
break ;
case POLARIS_AVMODE_ANALOGT_TV :
tmp & = ( ~ PWR_DEMOD_EN ) ;
tmp | = ( I2C_DEMOD_EN ) ;
value [ 0 ] = ( u8 ) tmp ;
value [ 1 ] = ( u8 ) ( tmp > > 8 ) ;
value [ 2 ] = ( u8 ) ( tmp > > 16 ) ;
value [ 3 ] = ( u8 ) ( tmp > > 24 ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_write_ctrl_reg ( dev , VRT_SET_REGISTER ,
PWR_CTL_EN , value , 4 ) ;
2009-03-03 12:14:34 +03:00
msleep ( PWR_SLEEP_INTERVAL ) ;
if ( ! ( tmp & PWR_TUNER_EN ) ) {
tmp | = ( PWR_TUNER_EN ) ;
value [ 0 ] = ( u8 ) tmp ;
value [ 1 ] = ( u8 ) ( tmp > > 8 ) ;
value [ 2 ] = ( u8 ) ( tmp > > 16 ) ;
value [ 3 ] = ( u8 ) ( tmp > > 24 ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_write_ctrl_reg ( dev , VRT_SET_REGISTER ,
PWR_CTL_EN , value , 4 ) ;
2009-03-03 12:14:34 +03:00
msleep ( PWR_SLEEP_INTERVAL ) ;
}
if ( ! ( tmp & PWR_AV_EN ) ) {
tmp | = PWR_AV_EN ;
value [ 0 ] = ( u8 ) tmp ;
value [ 1 ] = ( u8 ) ( tmp > > 8 ) ;
value [ 2 ] = ( u8 ) ( tmp > > 16 ) ;
value [ 3 ] = ( u8 ) ( tmp > > 24 ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_write_ctrl_reg ( dev , VRT_SET_REGISTER ,
PWR_CTL_EN , value , 4 ) ;
2009-03-03 12:14:34 +03:00
msleep ( PWR_SLEEP_INTERVAL ) ;
}
if ( ! ( tmp & PWR_ISO_EN ) ) {
tmp | = PWR_ISO_EN ;
value [ 0 ] = ( u8 ) tmp ;
value [ 1 ] = ( u8 ) ( tmp > > 8 ) ;
value [ 2 ] = ( u8 ) ( tmp > > 16 ) ;
value [ 3 ] = ( u8 ) ( tmp > > 24 ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_write_ctrl_reg ( dev , VRT_SET_REGISTER ,
PWR_CTL_EN , value , 4 ) ;
2009-03-03 12:14:34 +03:00
msleep ( PWR_SLEEP_INTERVAL ) ;
}
if ( ! ( tmp & POLARIS_AVMODE_ANALOGT_TV ) ) {
tmp | = POLARIS_AVMODE_ANALOGT_TV ;
value [ 0 ] = ( u8 ) tmp ;
value [ 1 ] = ( u8 ) ( tmp > > 8 ) ;
value [ 2 ] = ( u8 ) ( tmp > > 16 ) ;
value [ 3 ] = ( u8 ) ( tmp > > 24 ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_write_ctrl_reg ( dev , VRT_SET_REGISTER ,
PWR_CTL_EN , value , 4 ) ;
2009-03-03 12:14:34 +03:00
msleep ( PWR_SLEEP_INTERVAL ) ;
}
if ( ( dev - > model = = CX231XX_BOARD_CNXT_RDE_250 ) | |
( dev - > model = = CX231XX_BOARD_CNXT_RDU_250 ) ) {
/* tuner path to channel 1 from port 3 */
cx231xx_enable_i2c_for_tuner ( dev , I2C_3 ) ;
if ( dev - > cx231xx_reset_analog_tuner )
dev - > cx231xx_reset_analog_tuner ( dev ) ;
}
break ;
case POLARIS_AVMODE_DIGITAL :
if ( ! ( tmp & PWR_TUNER_EN ) ) {
tmp | = ( PWR_TUNER_EN ) ;
value [ 0 ] = ( u8 ) tmp ;
value [ 1 ] = ( u8 ) ( tmp > > 8 ) ;
value [ 2 ] = ( u8 ) ( tmp > > 16 ) ;
value [ 3 ] = ( u8 ) ( tmp > > 24 ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_write_ctrl_reg ( dev , VRT_SET_REGISTER ,
PWR_CTL_EN , value , 4 ) ;
2009-03-03 12:14:34 +03:00
msleep ( PWR_SLEEP_INTERVAL ) ;
}
if ( ! ( tmp & PWR_AV_EN ) ) {
tmp | = PWR_AV_EN ;
value [ 0 ] = ( u8 ) tmp ;
value [ 1 ] = ( u8 ) ( tmp > > 8 ) ;
value [ 2 ] = ( u8 ) ( tmp > > 16 ) ;
value [ 3 ] = ( u8 ) ( tmp > > 24 ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_write_ctrl_reg ( dev , VRT_SET_REGISTER ,
PWR_CTL_EN , value , 4 ) ;
2009-03-03 12:14:34 +03:00
msleep ( PWR_SLEEP_INTERVAL ) ;
}
if ( ! ( tmp & PWR_ISO_EN ) ) {
tmp | = PWR_ISO_EN ;
value [ 0 ] = ( u8 ) tmp ;
value [ 1 ] = ( u8 ) ( tmp > > 8 ) ;
value [ 2 ] = ( u8 ) ( tmp > > 16 ) ;
value [ 3 ] = ( u8 ) ( tmp > > 24 ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_write_ctrl_reg ( dev , VRT_SET_REGISTER ,
PWR_CTL_EN , value , 4 ) ;
2009-03-03 12:14:34 +03:00
msleep ( PWR_SLEEP_INTERVAL ) ;
}
tmp | = POLARIS_AVMODE_DIGITAL | I2C_DEMOD_EN ;
value [ 0 ] = ( u8 ) tmp ;
value [ 1 ] = ( u8 ) ( tmp > > 8 ) ;
value [ 2 ] = ( u8 ) ( tmp > > 16 ) ;
value [ 3 ] = ( u8 ) ( tmp > > 24 ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_write_ctrl_reg ( dev , VRT_SET_REGISTER ,
PWR_CTL_EN , value , 4 ) ;
2009-03-03 12:14:34 +03:00
msleep ( PWR_SLEEP_INTERVAL ) ;
if ( ! ( tmp & PWR_DEMOD_EN ) ) {
tmp | = PWR_DEMOD_EN ;
value [ 0 ] = ( u8 ) tmp ;
value [ 1 ] = ( u8 ) ( tmp > > 8 ) ;
value [ 2 ] = ( u8 ) ( tmp > > 16 ) ;
value [ 3 ] = ( u8 ) ( tmp > > 24 ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_write_ctrl_reg ( dev , VRT_SET_REGISTER ,
PWR_CTL_EN , value , 4 ) ;
2009-03-03 12:14:34 +03:00
msleep ( PWR_SLEEP_INTERVAL ) ;
}
if ( ( dev - > model = = CX231XX_BOARD_CNXT_RDE_250 ) | |
( dev - > model = = CX231XX_BOARD_CNXT_RDU_250 ) ) {
/* tuner path to channel 1 from port 3 */
cx231xx_enable_i2c_for_tuner ( dev , I2C_3 ) ;
if ( dev - > cx231xx_reset_analog_tuner )
dev - > cx231xx_reset_analog_tuner ( dev ) ;
}
break ;
default :
break ;
}
msleep ( PWR_SLEEP_INTERVAL ) ;
2009-03-03 19:31:36 +03:00
/* For power saving, only enable Pwr_resetout_n
when digital TV is selected . */
2009-03-03 12:14:34 +03:00
if ( mode = = POLARIS_AVMODE_DIGITAL ) {
tmp | = PWR_RESETOUT_EN ;
value [ 0 ] = ( u8 ) tmp ;
value [ 1 ] = ( u8 ) ( tmp > > 8 ) ;
value [ 2 ] = ( u8 ) ( tmp > > 16 ) ;
value [ 3 ] = ( u8 ) ( tmp > > 24 ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_write_ctrl_reg ( dev , VRT_SET_REGISTER ,
PWR_CTL_EN , value , 4 ) ;
2009-03-03 12:14:34 +03:00
msleep ( PWR_SLEEP_INTERVAL ) ;
}
2009-03-22 04:00:20 +03:00
/* update power control for afe */
status = cx231xx_afe_update_power_control ( dev , mode ) ;
2009-03-03 12:14:34 +03:00
2009-03-22 04:00:20 +03:00
/* update power control for i2s_blk */
status = cx231xx_i2s_blk_update_power_control ( dev , mode ) ;
2009-03-03 12:14:34 +03:00
2009-03-03 19:31:36 +03:00
status = cx231xx_read_ctrl_reg ( dev , VRT_GET_REGISTER , PWR_CTL_EN , value ,
4 ) ;
2009-03-04 23:49:01 +03:00
cx231xx_info ( " The data of PWR_CTL_EN register 0x74 "
" =0x%0x,0x%0x,0x%0x,0x%0x \n " ,
2009-03-03 19:31:36 +03:00
value [ 0 ] , value [ 1 ] , value [ 2 ] , value [ 3 ] ) ;
2009-03-03 12:14:34 +03:00
return status ;
2009-03-03 20:37:50 +03:00
}
int cx231xx_power_suspend ( struct cx231xx * dev )
{
2009-03-03 12:14:34 +03:00
u8 value [ 4 ] = { 0 , 0 , 0 , 0 } ;
u32 tmp = 0 ;
int status = 0 ;
2009-03-03 20:37:50 +03:00
2009-03-03 19:31:36 +03:00
status = cx231xx_read_ctrl_reg ( dev , VRT_GET_REGISTER , PWR_CTL_EN ,
value , 4 ) ;
2009-03-03 12:14:34 +03:00
if ( status > 0 )
return status ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
tmp = * ( ( u32 * ) value ) ;
tmp & = ( ~ PWR_MODE_MASK ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
value [ 0 ] = ( u8 ) tmp ;
value [ 1 ] = ( u8 ) ( tmp > > 8 ) ;
value [ 2 ] = ( u8 ) ( tmp > > 16 ) ;
value [ 3 ] = ( u8 ) ( tmp > > 24 ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_write_ctrl_reg ( dev , VRT_SET_REGISTER , PWR_CTL_EN ,
value , 4 ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
return status ;
2009-03-03 20:37:50 +03:00
}
2009-03-03 19:31:36 +03:00
/******************************************************************************
* S T R E A M C O N T R O L functions *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-03-03 20:37:50 +03:00
int cx231xx_start_stream ( struct cx231xx * dev , u32 ep_mask )
{
2009-03-03 12:14:34 +03:00
u8 value [ 4 ] = { 0x0 , 0x0 , 0x0 , 0x0 } ;
u32 tmp = 0 ;
int status = 0 ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
cx231xx_info ( " cx231xx_start_stream():: ep_mask = %x \n " , ep_mask ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_read_ctrl_reg ( dev , VRT_GET_REGISTER , EP_MODE_SET ,
value , 4 ) ;
2009-03-03 12:14:34 +03:00
if ( status < 0 )
return status ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
tmp = * ( ( u32 * ) value ) ;
tmp | = ep_mask ;
value [ 0 ] = ( u8 ) tmp ;
value [ 1 ] = ( u8 ) ( tmp > > 8 ) ;
value [ 2 ] = ( u8 ) ( tmp > > 16 ) ;
value [ 3 ] = ( u8 ) ( tmp > > 24 ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 19:31:36 +03:00
status = cx231xx_write_ctrl_reg ( dev , VRT_SET_REGISTER , EP_MODE_SET ,
value , 4 ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
return status ;
2009-03-03 20:37:50 +03:00
}
int cx231xx_stop_stream ( struct cx231xx * dev , u32 ep_mask )
{
2009-03-03 12:14:34 +03:00
u8 value [ 4 ] = { 0x0 , 0x0 , 0x0 , 0x0 } ;
u32 tmp = 0 ;
int status = 0 ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
cx231xx_info ( " cx231xx_stop_stream():: ep_mask = %x \n " , ep_mask ) ;
status =
cx231xx_read_ctrl_reg ( dev , VRT_GET_REGISTER , EP_MODE_SET , value , 4 ) ;
if ( status < 0 )
return status ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
tmp = * ( ( u32 * ) value ) ;
tmp & = ( ~ ep_mask ) ;
value [ 0 ] = ( u8 ) tmp ;
value [ 1 ] = ( u8 ) ( tmp > > 8 ) ;
value [ 2 ] = ( u8 ) ( tmp > > 16 ) ;
value [ 3 ] = ( u8 ) ( tmp > > 24 ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 19:31:36 +03:00
status = cx231xx_write_ctrl_reg ( dev , VRT_SET_REGISTER , EP_MODE_SET ,
value , 4 ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
return status ;
2009-03-03 20:37:50 +03:00
}
int cx231xx_initialize_stream_xfer ( struct cx231xx * dev , u32 media_type )
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
if ( dev - > udev - > speed = = USB_SPEED_HIGH ) {
switch ( media_type ) {
2009-03-11 03:16:26 +03:00
case 81 : /* audio */
2009-03-03 12:14:34 +03:00
cx231xx_info ( " %s: Audio enter HANC \n " , __func__ ) ;
status =
cx231xx_mode_register ( dev , TS_MODE_REG , 0x9300 ) ;
break ;
case 2 : /* vbi */
cx231xx_info ( " %s: set vanc registers \n " , __func__ ) ;
status = cx231xx_mode_register ( dev , TS_MODE_REG , 0x300 ) ;
break ;
case 3 : /* sliced cc */
cx231xx_info ( " %s: set hanc registers \n " , __func__ ) ;
status =
cx231xx_mode_register ( dev , TS_MODE_REG , 0x1300 ) ;
break ;
case 0 : /* video */
cx231xx_info ( " %s: set video registers \n " , __func__ ) ;
status = cx231xx_mode_register ( dev , TS_MODE_REG , 0x100 ) ;
break ;
case 4 : /* ts1 */
cx231xx_info ( " %s: set ts1 registers \n " , __func__ ) ;
status = cx231xx_mode_register ( dev , TS_MODE_REG , 0x101 ) ;
status = cx231xx_mode_register ( dev , TS1_CFG_REG , 0x400 ) ;
break ;
case 6 : /* ts1 parallel mode */
cx231xx_info ( " %s: set ts1 parrallel mode registers \n " ,
__func__ ) ;
status = cx231xx_mode_register ( dev , TS_MODE_REG , 0x100 ) ;
status = cx231xx_mode_register ( dev , TS1_CFG_REG , 0x400 ) ;
break ;
}
} else {
status = cx231xx_mode_register ( dev , TS_MODE_REG , 0x101 ) ;
}
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
return status ;
}
2009-03-03 20:37:50 +03:00
int cx231xx_capture_start ( struct cx231xx * dev , int start , u8 media_type )
{
int rc ;
2009-03-03 12:14:34 +03:00
u32 ep_mask = - 1 ;
2009-03-04 23:49:01 +03:00
struct pcb_config * pcb_config ;
2009-03-03 12:14:34 +03:00
/* get EP for media type */
2009-03-04 23:49:01 +03:00
pcb_config = ( struct pcb_config * ) & dev - > current_pcb_config ;
2009-03-03 12:14:34 +03:00
if ( pcb_config - > config_num = = 1 ) {
switch ( media_type ) {
case 0 : /* Video */
ep_mask = ENABLE_EP4 ; /* ep4 [00:1000] */
break ;
case 1 : /* Audio */
ep_mask = ENABLE_EP3 ; /* ep3 [00:0100] */
break ;
case 2 : /* Vbi */
ep_mask = ENABLE_EP5 ; /* ep5 [01:0000] */
break ;
case 3 : /* Sliced_cc */
ep_mask = ENABLE_EP6 ; /* ep6 [10:0000] */
break ;
case 4 : /* ts1 */
case 6 : /* ts1 parallel mode */
ep_mask = ENABLE_EP1 ; /* ep1 [00:0001] */
break ;
case 5 : /* ts2 */
ep_mask = ENABLE_EP2 ; /* ep2 [00:0010] */
break ;
}
} else if ( pcb_config - > config_num > 1 ) {
switch ( media_type ) {
case 0 : /* Video */
ep_mask = ENABLE_EP4 ; /* ep4 [00:1000] */
break ;
case 1 : /* Audio */
ep_mask = ENABLE_EP3 ; /* ep3 [00:0100] */
break ;
case 2 : /* Vbi */
ep_mask = ENABLE_EP5 ; /* ep5 [01:0000] */
break ;
case 3 : /* Sliced_cc */
ep_mask = ENABLE_EP6 ; /* ep6 [10:0000] */
break ;
case 4 : /* ts1 */
case 6 : /* ts1 parallel mode */
ep_mask = ENABLE_EP1 ; /* ep1 [00:0001] */
break ;
case 5 : /* ts2 */
ep_mask = ENABLE_EP2 ; /* ep2 [00:0010] */
break ;
}
}
if ( start ) {
rc = cx231xx_initialize_stream_xfer ( dev , media_type ) ;
2009-03-03 19:31:36 +03:00
if ( rc < 0 )
2009-03-03 12:14:34 +03:00
return rc ;
/* enable video capture */
if ( ep_mask > 0 )
rc = cx231xx_start_stream ( dev , ep_mask ) ;
} else {
/* disable video capture */
if ( ep_mask > 0 )
rc = cx231xx_stop_stream ( dev , ep_mask ) ;
}
2009-03-04 23:49:01 +03:00
if ( dev - > mode = = CX231XX_ANALOG_MODE )
; /* do any in Analog mode */
else
; /* do any in digital mode */
2009-03-03 20:37:50 +03:00
return rc ;
}
2009-03-03 12:14:34 +03:00
EXPORT_SYMBOL_GPL ( cx231xx_capture_start ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 19:31:36 +03:00
/*****************************************************************************
* G P I O B I T control functions *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-03-03 12:14:34 +03:00
int cx231xx_set_gpio_bit ( struct cx231xx * dev , u32 gpio_bit , u8 * gpio_val )
2009-03-03 20:37:50 +03:00
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
status = cx231xx_send_gpio_cmd ( dev , gpio_bit , gpio_val , 4 , 0 , 0 ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
return status ;
2009-03-03 20:37:50 +03:00
}
2009-03-03 12:14:34 +03:00
int cx231xx_get_gpio_bit ( struct cx231xx * dev , u32 gpio_bit , u8 * gpio_val )
2009-03-03 20:37:50 +03:00
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
status = cx231xx_send_gpio_cmd ( dev , gpio_bit , gpio_val , 4 , 0 , 1 ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
return status ;
2009-03-03 20:37:50 +03:00
}
/*
* cx231xx_set_gpio_direction
* Sets the direction of the GPIO pin to input or output
*
* Parameters :
* pin_number : The GPIO Pin number to program the direction for
* from 0 to 31
* pin_value : The Direction of the GPIO Pin under reference .
* 0 = Input direction
* 1 = Output direction
*/
int cx231xx_set_gpio_direction ( struct cx231xx * dev ,
2009-03-03 12:14:34 +03:00
int pin_number , int pin_value )
2009-03-03 20:37:50 +03:00
{
int status = 0 ;
2009-03-03 12:14:34 +03:00
u32 value = 0 ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
/* Check for valid pin_number - if 32 , bail out */
2009-03-03 19:31:36 +03:00
if ( pin_number > = 32 )
2009-03-03 12:14:34 +03:00
return - EINVAL ;
2009-03-03 20:37:50 +03:00
2009-03-03 19:31:36 +03:00
/* input */
if ( pin_value = = 0 )
2009-03-03 12:14:34 +03:00
value = dev - > gpio_dir & ( ~ ( 1 < < pin_number ) ) ; /* clear */
2009-03-03 19:31:36 +03:00
else
2009-03-03 12:14:34 +03:00
value = dev - > gpio_dir | ( 1 < < pin_number ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , value , ( u8 * ) & dev - > gpio_val ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
/* cache the value for future */
2009-03-03 20:37:50 +03:00
dev - > gpio_dir = value ;
2009-03-03 12:14:34 +03:00
return status ;
2009-03-03 20:37:50 +03:00
}
/*
2009-03-11 03:16:26 +03:00
* cx231xx_set_gpio_value
2009-03-03 20:37:50 +03:00
* Sets the value of the GPIO pin to Logic high or low . The Pin under
* reference should ALREADY BE SET IN OUTPUT MODE ! ! ! ! ! ! ! ! !
*
* Parameters :
* pin_number : The GPIO Pin number to program the direction for
* pin_value : The value of the GPIO Pin under reference .
* 0 = set it to 0
* 1 = set it to 1
*/
2009-03-03 12:14:34 +03:00
int cx231xx_set_gpio_value ( struct cx231xx * dev , int pin_number , int pin_value )
2009-03-03 20:37:50 +03:00
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
u32 value = 0 ;
/* Check for valid pin_number - if 0xFF , bail out */
if ( pin_number > = 32 )
return - EINVAL ;
/* first do a sanity check - if the Pin is not output, make it output */
if ( ( dev - > gpio_dir & ( 1 < < pin_number ) ) = = 0x00 ) {
/* It was in input mode */
value = dev - > gpio_dir | ( 1 < < pin_number ) ;
dev - > gpio_dir = value ;
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir ,
( u8 * ) & dev - > gpio_val ) ;
2009-03-03 20:37:50 +03:00
value = 0 ;
2009-03-03 12:14:34 +03:00
}
2009-03-03 20:37:50 +03:00
2009-03-03 19:31:36 +03:00
if ( pin_value = = 0 )
2009-03-03 12:14:34 +03:00
value = dev - > gpio_val & ( ~ ( 1 < < pin_number ) ) ;
2009-03-03 19:31:36 +03:00
else
2009-03-03 12:14:34 +03:00
value = dev - > gpio_val | ( 1 < < pin_number ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
/* store the value */
dev - > gpio_val = value ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
/* toggle bit0 of GP_IO */
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir , ( u8 * ) & dev - > gpio_val ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
return status ;
2009-03-03 20:37:50 +03:00
}
2009-03-03 19:31:36 +03:00
/*****************************************************************************
* G P I O I2C related functions *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-03-03 20:37:50 +03:00
int cx231xx_gpio_i2c_start ( struct cx231xx * dev )
{
int status = 0 ;
/* set SCL to output 1 ; set SDA to output 1 */
2009-03-03 12:14:34 +03:00
dev - > gpio_dir | = 1 < < dev - > board . tuner_scl_gpio ;
dev - > gpio_dir | = 1 < < dev - > board . tuner_sda_gpio ;
dev - > gpio_val | = 1 < < dev - > board . tuner_scl_gpio ;
dev - > gpio_val | = 1 < < dev - > board . tuner_sda_gpio ;
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir , ( u8 * ) & dev - > gpio_val ) ;
if ( status < 0 )
2009-03-03 20:37:50 +03:00
return - EINVAL ;
/* set SCL to output 1; set SDA to output 0 */
2009-03-03 12:14:34 +03:00
dev - > gpio_val | = 1 < < dev - > board . tuner_scl_gpio ;
dev - > gpio_val & = ~ ( 1 < < dev - > board . tuner_sda_gpio ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir , ( u8 * ) & dev - > gpio_val ) ;
if ( status < 0 )
2009-03-03 20:37:50 +03:00
return - EINVAL ;
2009-03-03 12:14:34 +03:00
/* set SCL to output 0; set SDA to output 0 */
dev - > gpio_val & = ~ ( 1 < < dev - > board . tuner_scl_gpio ) ;
dev - > gpio_val & = ~ ( 1 < < dev - > board . tuner_sda_gpio ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir , ( u8 * ) & dev - > gpio_val ) ;
if ( status < 0 )
2009-03-03 20:37:50 +03:00
return - EINVAL ;
return status ;
}
int cx231xx_gpio_i2c_end ( struct cx231xx * dev )
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
/* set SCL to output 0; set SDA to output 0 */
dev - > gpio_dir | = 1 < < dev - > board . tuner_scl_gpio ;
dev - > gpio_dir | = 1 < < dev - > board . tuner_sda_gpio ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
dev - > gpio_val & = ~ ( 1 < < dev - > board . tuner_scl_gpio ) ;
dev - > gpio_val & = ~ ( 1 < < dev - > board . tuner_sda_gpio ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir , ( u8 * ) & dev - > gpio_val ) ;
if ( status < 0 )
2009-03-03 20:37:50 +03:00
return - EINVAL ;
2009-03-03 12:14:34 +03:00
/* set SCL to output 1; set SDA to output 0 */
dev - > gpio_val | = 1 < < dev - > board . tuner_scl_gpio ;
dev - > gpio_val & = ~ ( 1 < < dev - > board . tuner_sda_gpio ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir , ( u8 * ) & dev - > gpio_val ) ;
if ( status < 0 )
2009-03-03 20:37:50 +03:00
return - EINVAL ;
/* set SCL to input ,release SCL cable control
set SDA to input , release SDA cable control */
2009-03-03 12:14:34 +03:00
dev - > gpio_dir & = ~ ( 1 < < dev - > board . tuner_scl_gpio ) ;
dev - > gpio_dir & = ~ ( 1 < < dev - > board . tuner_sda_gpio ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
status =
2009-03-03 19:31:36 +03:00
cx231xx_set_gpio_bit ( dev , dev - > gpio_dir , ( u8 * ) & dev - > gpio_val ) ;
if ( status < 0 )
2009-03-03 20:37:50 +03:00
return - EINVAL ;
2009-03-03 19:31:36 +03:00
2009-03-03 20:37:50 +03:00
return status ;
}
int cx231xx_gpio_i2c_write_byte ( struct cx231xx * dev , u8 data )
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
u8 i ;
2009-03-03 20:37:50 +03:00
/* set SCL to output ; set SDA to output */
2009-03-03 12:14:34 +03:00
dev - > gpio_dir | = 1 < < dev - > board . tuner_scl_gpio ;
dev - > gpio_dir | = 1 < < dev - > board . tuner_sda_gpio ;
for ( i = 0 ; i < 8 ; i + + ) {
if ( ( ( data < < i ) & 0x80 ) = = 0 ) {
/* set SCL to output 0; set SDA to output 0 */
dev - > gpio_val & = ~ ( 1 < < dev - > board . tuner_scl_gpio ) ;
dev - > gpio_val & = ~ ( 1 < < dev - > board . tuner_sda_gpio ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir ,
( u8 * ) & dev - > gpio_val ) ;
2009-03-03 12:14:34 +03:00
/* set SCL to output 1; set SDA to output 0 */
dev - > gpio_val | = 1 < < dev - > board . tuner_scl_gpio ;
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir ,
( u8 * ) & dev - > gpio_val ) ;
2009-03-03 12:14:34 +03:00
/* set SCL to output 0; set SDA to output 0 */
dev - > gpio_val & = ~ ( 1 < < dev - > board . tuner_scl_gpio ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir ,
( u8 * ) & dev - > gpio_val ) ;
2009-03-03 20:37:50 +03:00
} else {
2009-03-03 12:14:34 +03:00
/* set SCL to output 0; set SDA to output 1 */
dev - > gpio_val & = ~ ( 1 < < dev - > board . tuner_scl_gpio ) ;
dev - > gpio_val | = 1 < < dev - > board . tuner_sda_gpio ;
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir ,
( u8 * ) & dev - > gpio_val ) ;
2009-03-03 12:14:34 +03:00
/* set SCL to output 1; set SDA to output 1 */
dev - > gpio_val | = 1 < < dev - > board . tuner_scl_gpio ;
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir ,
( u8 * ) & dev - > gpio_val ) ;
2009-03-03 12:14:34 +03:00
/* set SCL to output 0; set SDA to output 1 */
dev - > gpio_val & = ~ ( 1 < < dev - > board . tuner_scl_gpio ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir ,
( u8 * ) & dev - > gpio_val ) ;
2009-03-03 12:14:34 +03:00
}
2009-03-03 20:37:50 +03:00
}
return status ;
}
2009-03-03 12:14:34 +03:00
int cx231xx_gpio_i2c_read_byte ( struct cx231xx * dev , u8 * buf )
2009-03-03 20:37:50 +03:00
{
u8 value = 0 ;
2009-03-03 12:14:34 +03:00
int status = 0 ;
u32 gpio_logic_value = 0 ;
u8 i ;
2009-03-03 20:37:50 +03:00
/* read byte */
2009-03-03 12:14:34 +03:00
for ( i = 0 ; i < 8 ; i + + ) { /* send write I2c addr */
2009-03-03 20:37:50 +03:00
/* set SCL to output 0; set SDA to input */
2009-03-03 12:14:34 +03:00
dev - > gpio_val & = ~ ( 1 < < dev - > board . tuner_scl_gpio ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir ,
( u8 * ) & dev - > gpio_val ) ;
2009-03-03 20:37:50 +03:00
/* set SCL to output 1; set SDA to input */
2009-03-03 12:14:34 +03:00
dev - > gpio_val | = 1 < < dev - > board . tuner_scl_gpio ;
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir ,
( u8 * ) & dev - > gpio_val ) ;
2009-03-03 20:37:50 +03:00
/* get SDA data bit */
gpio_logic_value = dev - > gpio_val ;
2009-03-03 19:31:36 +03:00
status = cx231xx_get_gpio_bit ( dev , dev - > gpio_dir ,
( u8 * ) & dev - > gpio_val ) ;
if ( ( dev - > gpio_val & ( 1 < < dev - > board . tuner_sda_gpio ) ) ! = 0 )
2009-03-03 12:14:34 +03:00
value | = ( 1 < < ( 8 - i - 1 ) ) ;
2009-03-03 20:37:50 +03:00
dev - > gpio_val = gpio_logic_value ;
}
/* set SCL to output 0,finish the read latest SCL signal.
2009-03-03 19:31:36 +03:00
! ! ! set SDA to input , never to modify SDA direction at
the same times */
2009-03-03 12:14:34 +03:00
dev - > gpio_val & = ~ ( 1 < < dev - > board . tuner_scl_gpio ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir , ( u8 * ) & dev - > gpio_val ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
/* store the value */
* buf = value & 0xff ;
2009-03-03 20:37:50 +03:00
return status ;
}
int cx231xx_gpio_i2c_read_ack ( struct cx231xx * dev )
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
2009-03-03 20:37:50 +03:00
u32 gpio_logic_value = 0 ;
2009-03-03 12:14:34 +03:00
int nCnt = 10 ;
int nInit = nCnt ;
2009-03-03 20:37:50 +03:00
2009-03-03 19:31:36 +03:00
/* clock stretch; set SCL to input; set SDA to input;
get SCL value till SCL = 1 */
2009-03-03 12:14:34 +03:00
dev - > gpio_dir & = ~ ( 1 < < dev - > board . tuner_sda_gpio ) ;
dev - > gpio_dir & = ~ ( 1 < < dev - > board . tuner_scl_gpio ) ;
2009-03-03 20:37:50 +03:00
gpio_logic_value = dev - > gpio_val ;
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir , ( u8 * ) & dev - > gpio_val ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
do {
2009-03-03 20:37:50 +03:00
msleep ( 2 ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_get_gpio_bit ( dev , dev - > gpio_dir ,
( u8 * ) & dev - > gpio_val ) ;
2009-03-03 12:14:34 +03:00
nCnt - - ;
2009-03-04 23:49:01 +03:00
} while ( ( ( dev - > gpio_val &
( 1 < < dev - > board . tuner_scl_gpio ) ) = = 0 ) & &
( nCnt > 0 ) ) ;
2009-03-03 12:14:34 +03:00
2009-03-03 19:31:36 +03:00
if ( nCnt = = 0 )
2009-03-04 23:49:01 +03:00
cx231xx_info ( " No ACK after %d msec -GPIO I2C failed! " ,
2009-03-03 19:31:36 +03:00
nInit * 10 ) ;
2009-03-03 20:37:50 +03:00
/* readAck
2009-03-03 19:31:36 +03:00
throuth clock stretch , slave has given a SCL signal ,
so the SDA data can be directly read . */
status = cx231xx_get_gpio_bit ( dev , dev - > gpio_dir , ( u8 * ) & dev - > gpio_val ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
if ( ( dev - > gpio_val & 1 < < dev - > board . tuner_sda_gpio ) = = 0 ) {
2009-03-03 20:37:50 +03:00
dev - > gpio_val = gpio_logic_value ;
2009-03-03 12:14:34 +03:00
dev - > gpio_val & = ~ ( 1 < < dev - > board . tuner_sda_gpio ) ;
2009-03-03 20:37:50 +03:00
status = 0 ;
} else {
dev - > gpio_val = gpio_logic_value ;
2009-03-03 12:14:34 +03:00
dev - > gpio_val | = ( 1 < < dev - > board . tuner_sda_gpio ) ;
2009-03-03 20:37:50 +03:00
}
2009-03-03 19:31:36 +03:00
/* read SDA end, set the SCL to output 0, after this operation,
SDA direction can be changed . */
2009-03-03 20:37:50 +03:00
dev - > gpio_val = gpio_logic_value ;
2009-03-03 12:14:34 +03:00
dev - > gpio_dir | = ( 1 < < dev - > board . tuner_scl_gpio ) ;
dev - > gpio_val & = ~ ( 1 < < dev - > board . tuner_scl_gpio ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir , ( u8 * ) & dev - > gpio_val ) ;
2009-03-03 20:37:50 +03:00
return status ;
}
int cx231xx_gpio_i2c_write_ack ( struct cx231xx * dev )
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
2009-03-03 20:37:50 +03:00
/* set SDA to ouput */
2009-03-03 12:14:34 +03:00
dev - > gpio_dir | = 1 < < dev - > board . tuner_sda_gpio ;
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir , ( u8 * ) & dev - > gpio_val ) ;
2009-03-03 20:37:50 +03:00
/* set SCL = 0 (output); set SDA = 0 (output) */
2009-03-03 12:14:34 +03:00
dev - > gpio_val & = ~ ( 1 < < dev - > board . tuner_sda_gpio ) ;
dev - > gpio_val & = ~ ( 1 < < dev - > board . tuner_scl_gpio ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir , ( u8 * ) & dev - > gpio_val ) ;
2009-03-03 20:37:50 +03:00
/* set SCL = 1 (output); set SDA = 0 (output) */
2009-03-03 12:14:34 +03:00
dev - > gpio_val | = 1 < < dev - > board . tuner_scl_gpio ;
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir , ( u8 * ) & dev - > gpio_val ) ;
2009-03-03 20:37:50 +03:00
/* set SCL = 0 (output); set SDA = 0 (output) */
2009-03-03 12:14:34 +03:00
dev - > gpio_val & = ~ ( 1 < < dev - > board . tuner_scl_gpio ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir , ( u8 * ) & dev - > gpio_val ) ;
2009-03-03 20:37:50 +03:00
/* set SDA to input,and then the slave will read data from SDA. */
2009-03-03 12:14:34 +03:00
dev - > gpio_dir & = ~ ( 1 < < dev - > board . tuner_sda_gpio ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir , ( u8 * ) & dev - > gpio_val ) ;
2009-03-03 20:37:50 +03:00
return status ;
}
int cx231xx_gpio_i2c_write_nak ( struct cx231xx * dev )
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
2009-03-03 20:37:50 +03:00
/* set scl to output ; set sda to input */
2009-03-03 12:14:34 +03:00
dev - > gpio_dir | = 1 < < dev - > board . tuner_scl_gpio ;
dev - > gpio_dir & = ~ ( 1 < < dev - > board . tuner_sda_gpio ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir , ( u8 * ) & dev - > gpio_val ) ;
2009-03-03 20:37:50 +03:00
/* set scl to output 0; set sda to input */
2009-03-03 12:14:34 +03:00
dev - > gpio_val & = ~ ( 1 < < dev - > board . tuner_scl_gpio ) ;
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir , ( u8 * ) & dev - > gpio_val ) ;
2009-03-03 20:37:50 +03:00
/* set scl to output 1; set sda to input */
2009-03-03 12:14:34 +03:00
dev - > gpio_val | = 1 < < dev - > board . tuner_scl_gpio ;
2009-03-03 19:31:36 +03:00
status = cx231xx_set_gpio_bit ( dev , dev - > gpio_dir , ( u8 * ) & dev - > gpio_val ) ;
2009-03-03 20:37:50 +03:00
return status ;
}
2009-03-03 19:31:36 +03:00
/*****************************************************************************
* G P I O I2C related functions *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-03-03 20:37:50 +03:00
/* cx231xx_gpio_i2c_read
* Function to read data from gpio based I2C interface
*/
2009-03-03 12:14:34 +03:00
int cx231xx_gpio_i2c_read ( struct cx231xx * dev , u8 dev_addr , u8 * buf , u8 len )
2009-03-03 20:37:50 +03:00
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
int i = 0 ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
/* get the lock */
2009-03-03 20:37:50 +03:00
mutex_lock ( & dev - > gpio_i2c_lock ) ;
/* start */
status = cx231xx_gpio_i2c_start ( dev ) ;
/* write dev_addr */
2009-03-03 12:14:34 +03:00
status = cx231xx_gpio_i2c_write_byte ( dev , ( dev_addr < < 1 ) + 1 ) ;
2009-03-03 20:37:50 +03:00
/* readAck */
status = cx231xx_gpio_i2c_read_ack ( dev ) ;
2009-03-03 12:14:34 +03:00
/* read data */
for ( i = 0 ; i < len ; i + + ) {
/* read data */
buf [ i ] = 0 ;
status = cx231xx_gpio_i2c_read_byte ( dev , & buf [ i ] ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
if ( ( i + 1 ) ! = len ) {
/* only do write ack if we more length */
status = cx231xx_gpio_i2c_write_ack ( dev ) ;
}
}
2009-03-03 20:37:50 +03:00
/* write NAK - inform reads are complete */
status = cx231xx_gpio_i2c_write_nak ( dev ) ;
/* write end */
status = cx231xx_gpio_i2c_end ( dev ) ;
/* release the lock */
mutex_unlock ( & dev - > gpio_i2c_lock ) ;
return status ;
}
/* cx231xx_gpio_i2c_write
* Function to write data to gpio based I2C interface
*/
2009-03-03 12:14:34 +03:00
int cx231xx_gpio_i2c_write ( struct cx231xx * dev , u8 dev_addr , u8 * buf , u8 len )
2009-03-03 20:37:50 +03:00
{
2009-03-03 12:14:34 +03:00
int status = 0 ;
int i = 0 ;
2009-03-03 20:37:50 +03:00
/* get the lock */
mutex_lock ( & dev - > gpio_i2c_lock ) ;
/* start */
status = cx231xx_gpio_i2c_start ( dev ) ;
/* write dev_addr */
status = cx231xx_gpio_i2c_write_byte ( dev , dev_addr < < 1 ) ;
/* read Ack */
2009-03-03 12:14:34 +03:00
status = cx231xx_gpio_i2c_read_ack ( dev ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
for ( i = 0 ; i < len ; i + + ) {
2009-03-03 20:37:50 +03:00
/* Write data */
2009-03-03 12:14:34 +03:00
status = cx231xx_gpio_i2c_write_byte ( dev , buf [ i ] ) ;
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
/* read Ack */
status = cx231xx_gpio_i2c_read_ack ( dev ) ;
}
2009-03-03 20:37:50 +03:00
2009-03-03 12:14:34 +03:00
/* write End */
2009-03-03 20:37:50 +03:00
status = cx231xx_gpio_i2c_end ( dev ) ;
/* release the lock */
mutex_unlock ( & dev - > gpio_i2c_lock ) ;
return 0 ;
}