2019-05-31 11:09:32 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2011-01-04 10:28:59 +03:00
/*
* Linux - DVB Driver for DiBcom ' s DiB9000 and demodulator - family .
*
* Copyright ( C ) 2005 - 10 DiBcom ( http : //www.dibcom.fr/)
*/
2016-10-14 16:08:40 +03:00
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2011-01-04 10:28:59 +03:00
# include <linux/kernel.h>
# include <linux/i2c.h>
# include <linux/mutex.h>
2017-12-28 21:03:51 +03:00
# include <media/dvb_math.h>
# include <media/dvb_frontend.h>
2011-01-04 10:28:59 +03:00
# include "dib9000.h"
# include "dibx000_common.h"
static int debug ;
module_param ( debug , int , 0644 ) ;
MODULE_PARM_DESC ( debug , " turn on debugging (default: 0) " ) ;
2016-10-14 16:08:40 +03:00
# define dprintk(fmt, arg...) do { \
if ( debug ) \
printk ( KERN_DEBUG pr_fmt ( " %s: " fmt ) , \
__func__ , # # arg ) ; \
} while ( 0 )
2011-01-04 10:28:59 +03:00
# define MAX_NUMBER_OF_FRONTENDS 6
struct i2c_device {
struct i2c_adapter * i2c_adap ;
u8 i2c_addr ;
2011-05-03 19:27:33 +04:00
u8 * i2c_read_buffer ;
u8 * i2c_write_buffer ;
2011-01-04 10:28:59 +03:00
} ;
2011-08-03 19:08:21 +04:00
struct dib9000_pid_ctrl {
# define DIB9000_PID_FILTER_CTRL 0
# define DIB9000_PID_FILTER 1
u8 cmd ;
u8 id ;
u16 pid ;
u8 onoff ;
} ;
2011-01-04 10:28:59 +03:00
struct dib9000_state {
struct i2c_device i2c ;
struct dibx000_i2c_master i2c_master ;
struct i2c_adapter tuner_adap ;
struct i2c_adapter component_bus ;
u16 revision ;
u8 reg_offs ;
enum frontend_tune_state tune_state ;
u32 status ;
struct dvb_frontend_parametersContext channel_status ;
u8 fe_id ;
# define DIB9000_GPIO_DEFAULT_DIRECTIONS 0xffff
u16 gpio_dir ;
# define DIB9000_GPIO_DEFAULT_VALUES 0x0000
u16 gpio_val ;
# define DIB9000_GPIO_DEFAULT_PWM_POS 0xffff
u16 gpio_pwm_pos ;
union { /* common for all chips */
struct {
u8 mobile_mode : 1 ;
} host ;
struct {
struct dib9000_fe_memory_map {
u16 addr ;
u16 size ;
} fe_mm [ 18 ] ;
u8 memcmd ;
2012-03-19 23:48:34 +04:00
struct mutex mbx_if_lock ; /* to protect read/write operations */
struct mutex mbx_lock ; /* to protect the whole mailbox handling */
2011-01-04 10:28:59 +03:00
2012-03-19 23:48:34 +04:00
struct mutex mem_lock ; /* to protect the memory accesses */
struct mutex mem_mbx_lock ; /* to protect the memory-based mailbox */
2011-01-04 10:28:59 +03:00
# define MBX_MAX_WORDS (256 - 200 - 2)
# define DIB9000_MSG_CACHE_SIZE 2
u16 message_cache [ DIB9000_MSG_CACHE_SIZE ] [ MBX_MAX_WORDS ] ;
u8 fw_is_running ;
} risc ;
} platform ;
union { /* common for all platforms */
struct {
struct dib9000_config cfg ;
} d9 ;
} chip ;
struct dvb_frontend * fe [ MAX_NUMBER_OF_FRONTENDS ] ;
u16 component_bus_speed ;
2011-05-03 19:27:33 +04:00
/* for the I2C transfer */
struct i2c_msg msg [ 2 ] ;
u8 i2c_write_buffer [ 255 ] ;
u8 i2c_read_buffer [ 255 ] ;
2012-03-19 23:48:34 +04:00
struct mutex demod_lock ;
2011-08-03 19:08:21 +04:00
u8 get_frontend_internal ;
struct dib9000_pid_ctrl pid_ctrl [ 10 ] ;
s8 pid_ctrl_index ; /* -1: empty list; -2: do not use the list */
2011-01-04 10:28:59 +03:00
} ;
2011-05-03 19:27:33 +04:00
static const u32 fe_info [ 44 ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
2011-01-04 10:28:59 +03:00
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
2011-05-03 19:27:33 +04:00
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
2011-01-04 10:28:59 +03:00
} ;
enum dib9000_power_mode {
DIB9000_POWER_ALL = 0 ,
DIB9000_POWER_NO ,
DIB9000_POWER_INTERF_ANALOG_AGC ,
DIB9000_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD ,
DIB9000_POWER_COR4_CRY_ESRAM_MOUT_NUD ,
DIB9000_POWER_INTERFACE_ONLY ,
} ;
enum dib9000_out_messages {
OUT_MSG_HBM_ACK ,
OUT_MSG_HOST_BUF_FAIL ,
OUT_MSG_REQ_VERSION ,
OUT_MSG_BRIDGE_I2C_W ,
OUT_MSG_BRIDGE_I2C_R ,
OUT_MSG_BRIDGE_APB_W ,
OUT_MSG_BRIDGE_APB_R ,
OUT_MSG_SCAN_CHANNEL ,
OUT_MSG_MONIT_DEMOD ,
OUT_MSG_CONF_GPIO ,
OUT_MSG_DEBUG_HELP ,
OUT_MSG_SUBBAND_SEL ,
OUT_MSG_ENABLE_TIME_SLICE ,
OUT_MSG_FE_FW_DL ,
OUT_MSG_FE_CHANNEL_SEARCH ,
OUT_MSG_FE_CHANNEL_TUNE ,
OUT_MSG_FE_SLEEP ,
OUT_MSG_FE_SYNC ,
OUT_MSG_CTL_MONIT ,
OUT_MSG_CONF_SVC ,
OUT_MSG_SET_HBM ,
OUT_MSG_INIT_DEMOD ,
OUT_MSG_ENABLE_DIVERSITY ,
OUT_MSG_SET_OUTPUT_MODE ,
OUT_MSG_SET_PRIORITARY_CHANNEL ,
OUT_MSG_ACK_FRG ,
OUT_MSG_INIT_PMU ,
} ;
enum dib9000_in_messages {
IN_MSG_DATA ,
IN_MSG_FRAME_INFO ,
IN_MSG_CTL_MONIT ,
IN_MSG_ACK_FREE_ITEM ,
IN_MSG_DEBUG_BUF ,
IN_MSG_MPE_MONITOR ,
IN_MSG_RAWTS_MONITOR ,
IN_MSG_END_BRIDGE_I2C_RW ,
IN_MSG_END_BRIDGE_APB_RW ,
IN_MSG_VERSION ,
IN_MSG_END_OF_SCAN ,
IN_MSG_MONIT_DEMOD ,
IN_MSG_ERROR ,
IN_MSG_FE_FW_DL_DONE ,
IN_MSG_EVENT ,
IN_MSG_ACK_CHANGE_SVC ,
IN_MSG_HBM_PROF ,
} ;
/* memory_access requests */
# define FE_MM_W_CHANNEL 0
# define FE_MM_W_FE_INFO 1
# define FE_MM_RW_SYNC 2
# define FE_SYNC_CHANNEL 1
# define FE_SYNC_W_GENERIC_MONIT 2
# define FE_SYNC_COMPONENT_ACCESS 3
# define FE_MM_R_CHANNEL_SEARCH_STATE 3
# define FE_MM_R_CHANNEL_UNION_CONTEXT 4
# define FE_MM_R_FE_INFO 5
# define FE_MM_R_FE_MONITOR 6
# define FE_MM_W_CHANNEL_HEAD 7
# define FE_MM_W_CHANNEL_UNION 8
# define FE_MM_W_CHANNEL_CONTEXT 9
# define FE_MM_R_CHANNEL_UNION 10
# define FE_MM_R_CHANNEL_CONTEXT 11
# define FE_MM_R_CHANNEL_TUNE_STATE 12
# define FE_MM_R_GENERIC_MONITORING_SIZE 13
# define FE_MM_W_GENERIC_MONITORING 14
# define FE_MM_R_GENERIC_MONITORING 15
# define FE_MM_W_COMPONENT_ACCESS 16
# define FE_MM_RW_COMPONENT_ACCESS_BUFFER 17
2011-01-04 19:08:14 +03:00
static int dib9000_risc_apb_access_read ( struct dib9000_state * state , u32 address , u16 attribute , const u8 * tx , u32 txlen , u8 * b , u32 len ) ;
2011-01-04 10:28:59 +03:00
static int dib9000_risc_apb_access_write ( struct dib9000_state * state , u32 address , u16 attribute , const u8 * b , u32 len ) ;
static u16 to_fw_output_mode ( u16 mode )
{
switch ( mode ) {
case OUTMODE_HIGH_Z :
return 0 ;
case OUTMODE_MPEG2_PAR_GATED_CLK :
return 4 ;
case OUTMODE_MPEG2_PAR_CONT_CLK :
return 8 ;
case OUTMODE_MPEG2_SERIAL :
return 16 ;
case OUTMODE_DIVERSITY :
return 128 ;
case OUTMODE_MPEG2_FIFO :
return 2 ;
case OUTMODE_ANALOG_ADC :
return 1 ;
default :
return 0 ;
}
}
2016-02-22 19:43:57 +03:00
static int dib9000_read16_attr ( struct dib9000_state * state , u16 reg , u8 * b , u32 len , u16 attribute )
2011-01-04 10:28:59 +03:00
{
u32 chunk_size = 126 ;
u32 l ;
int ret ;
if ( state - > platform . risc . fw_is_running & & ( reg < 1024 ) )
return dib9000_risc_apb_access_read ( state , reg , attribute , NULL , 0 , b , len ) ;
2011-05-03 19:27:33 +04:00
memset ( state - > msg , 0 , 2 * sizeof ( struct i2c_msg ) ) ;
state - > msg [ 0 ] . addr = state - > i2c . i2c_addr > > 1 ;
state - > msg [ 0 ] . flags = 0 ;
state - > msg [ 0 ] . buf = state - > i2c_write_buffer ;
state - > msg [ 0 ] . len = 2 ;
state - > msg [ 1 ] . addr = state - > i2c . i2c_addr > > 1 ;
state - > msg [ 1 ] . flags = I2C_M_RD ;
state - > msg [ 1 ] . buf = b ;
state - > msg [ 1 ] . len = len ;
state - > i2c_write_buffer [ 0 ] = reg > > 8 ;
state - > i2c_write_buffer [ 1 ] = reg & 0xff ;
2011-01-04 10:28:59 +03:00
if ( attribute & DATA_BUS_ACCESS_MODE_8BIT )
2011-05-03 19:27:33 +04:00
state - > i2c_write_buffer [ 0 ] | = ( 1 < < 5 ) ;
2011-01-04 10:28:59 +03:00
if ( attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT )
2011-05-03 19:27:33 +04:00
state - > i2c_write_buffer [ 0 ] | = ( 1 < < 4 ) ;
2011-01-04 10:28:59 +03:00
do {
l = len < chunk_size ? len : chunk_size ;
2011-05-03 19:27:33 +04:00
state - > msg [ 1 ] . len = l ;
state - > msg [ 1 ] . buf = b ;
ret = i2c_transfer ( state - > i2c . i2c_adap , state - > msg , 2 ) ! = 2 ? - EREMOTEIO : 0 ;
2011-01-04 10:28:59 +03:00
if ( ret ! = 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " i2c read error on %d \n " , reg ) ;
2011-01-04 10:28:59 +03:00
return - EREMOTEIO ;
}
b + = l ;
len - = l ;
if ( ! ( attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT ) )
reg + = l / 2 ;
} while ( ( ret = = 0 ) & & len ) ;
return 0 ;
}
static u16 dib9000_i2c_read16 ( struct i2c_device * i2c , u16 reg )
{
struct i2c_msg msg [ 2 ] = {
2011-05-03 19:27:33 +04:00
{ . addr = i2c - > i2c_addr > > 1 , . flags = 0 ,
. buf = i2c - > i2c_write_buffer , . len = 2 } ,
{ . addr = i2c - > i2c_addr > > 1 , . flags = I2C_M_RD ,
. buf = i2c - > i2c_read_buffer , . len = 2 } ,
2011-01-04 10:28:59 +03:00
} ;
2011-05-03 19:27:33 +04:00
i2c - > i2c_write_buffer [ 0 ] = reg > > 8 ;
i2c - > i2c_write_buffer [ 1 ] = reg & 0xff ;
2011-01-04 10:28:59 +03:00
if ( i2c_transfer ( i2c - > i2c_adap , msg , 2 ) ! = 2 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " read register %x error \n " , reg ) ;
2011-01-04 10:28:59 +03:00
return 0 ;
}
2011-05-03 19:27:33 +04:00
return ( i2c - > i2c_read_buffer [ 0 ] < < 8 ) | i2c - > i2c_read_buffer [ 1 ] ;
2011-01-04 10:28:59 +03:00
}
static inline u16 dib9000_read_word ( struct dib9000_state * state , u16 reg )
{
2011-05-03 19:27:33 +04:00
if ( dib9000_read16_attr ( state , reg , state - > i2c_read_buffer , 2 , 0 ) ! = 0 )
2011-01-04 10:28:59 +03:00
return 0 ;
2011-05-03 19:27:33 +04:00
return ( state - > i2c_read_buffer [ 0 ] < < 8 ) | state - > i2c_read_buffer [ 1 ] ;
2011-01-04 10:28:59 +03:00
}
static inline u16 dib9000_read_word_attr ( struct dib9000_state * state , u16 reg , u16 attribute )
{
2011-05-03 19:27:33 +04:00
if ( dib9000_read16_attr ( state , reg , state - > i2c_read_buffer , 2 ,
attribute ) ! = 0 )
2011-01-04 10:28:59 +03:00
return 0 ;
2011-05-03 19:27:33 +04:00
return ( state - > i2c_read_buffer [ 0 ] < < 8 ) | state - > i2c_read_buffer [ 1 ] ;
2011-01-04 10:28:59 +03:00
}
# define dib9000_read16_noinc_attr(state, reg, b, len, attribute) dib9000_read16_attr(state, reg, b, len, (attribute) | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
2016-02-22 19:43:57 +03:00
static int dib9000_write16_attr ( struct dib9000_state * state , u16 reg , const u8 * buf , u32 len , u16 attribute )
2011-01-04 10:28:59 +03:00
{
u32 chunk_size = 126 ;
u32 l ;
int ret ;
if ( state - > platform . risc . fw_is_running & & ( reg < 1024 ) ) {
if ( dib9000_risc_apb_access_write
2011-01-04 19:08:14 +03:00
( state , reg , DATA_BUS_ACCESS_MODE_16BIT | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT | attribute , buf , len ) ! = 0 )
2011-01-04 10:28:59 +03:00
return - EINVAL ;
return 0 ;
}
2011-05-03 19:27:33 +04:00
memset ( & state - > msg [ 0 ] , 0 , sizeof ( struct i2c_msg ) ) ;
state - > msg [ 0 ] . addr = state - > i2c . i2c_addr > > 1 ;
state - > msg [ 0 ] . flags = 0 ;
state - > msg [ 0 ] . buf = state - > i2c_write_buffer ;
state - > msg [ 0 ] . len = len + 2 ;
state - > i2c_write_buffer [ 0 ] = ( reg > > 8 ) & 0xff ;
state - > i2c_write_buffer [ 1 ] = ( reg ) & 0xff ;
2011-01-04 10:28:59 +03:00
if ( attribute & DATA_BUS_ACCESS_MODE_8BIT )
2011-05-03 19:27:33 +04:00
state - > i2c_write_buffer [ 0 ] | = ( 1 < < 5 ) ;
2011-01-04 10:28:59 +03:00
if ( attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT )
2011-05-03 19:27:33 +04:00
state - > i2c_write_buffer [ 0 ] | = ( 1 < < 4 ) ;
2011-01-04 10:28:59 +03:00
do {
l = len < chunk_size ? len : chunk_size ;
2011-05-03 19:27:33 +04:00
state - > msg [ 0 ] . len = l + 2 ;
memcpy ( & state - > i2c_write_buffer [ 2 ] , buf , l ) ;
2011-01-04 10:28:59 +03:00
2011-05-03 19:27:33 +04:00
ret = i2c_transfer ( state - > i2c . i2c_adap , state - > msg , 1 ) ! = 1 ? - EREMOTEIO : 0 ;
2011-01-04 10:28:59 +03:00
buf + = l ;
len - = l ;
if ( ! ( attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT ) )
reg + = l / 2 ;
} while ( ( ret = = 0 ) & & len ) ;
return ret ;
}
static int dib9000_i2c_write16 ( struct i2c_device * i2c , u16 reg , u16 val )
{
struct i2c_msg msg = {
2011-05-03 19:27:33 +04:00
. addr = i2c - > i2c_addr > > 1 , . flags = 0 ,
. buf = i2c - > i2c_write_buffer , . len = 4
2011-01-04 10:28:59 +03:00
} ;
2011-05-03 19:27:33 +04:00
i2c - > i2c_write_buffer [ 0 ] = ( reg > > 8 ) & 0xff ;
i2c - > i2c_write_buffer [ 1 ] = reg & 0xff ;
i2c - > i2c_write_buffer [ 2 ] = ( val > > 8 ) & 0xff ;
i2c - > i2c_write_buffer [ 3 ] = val & 0xff ;
2011-01-04 10:28:59 +03:00
return i2c_transfer ( i2c - > i2c_adap , & msg , 1 ) ! = 1 ? - EREMOTEIO : 0 ;
}
static inline int dib9000_write_word ( struct dib9000_state * state , u16 reg , u16 val )
{
u8 b [ 2 ] = { val > > 8 , val & 0xff } ;
return dib9000_write16_attr ( state , reg , b , 2 , 0 ) ;
}
static inline int dib9000_write_word_attr ( struct dib9000_state * state , u16 reg , u16 val , u16 attribute )
{
u8 b [ 2 ] = { val > > 8 , val & 0xff } ;
return dib9000_write16_attr ( state , reg , b , 2 , attribute ) ;
}
# define dib9000_write(state, reg, buf, len) dib9000_write16_attr(state, reg, buf, len, 0)
# define dib9000_write16_noinc(state, reg, buf, len) dib9000_write16_attr(state, reg, buf, len, DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
# define dib9000_write16_noinc_attr(state, reg, buf, len, attribute) dib9000_write16_attr(state, reg, buf, len, DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT | (attribute))
# define dib9000_mbx_send(state, id, data, len) dib9000_mbx_send_attr(state, id, data, len, 0)
# define dib9000_mbx_get_message(state, id, msg, len) dib9000_mbx_get_message_attr(state, id, msg, len, 0)
# define MAC_IRQ (1 << 1)
# define IRQ_POL_MSK (1 << 4)
# define dib9000_risc_mem_read_chunks(state, b, len) dib9000_read16_attr(state, 1063, b, len, DATA_BUS_ACCESS_MODE_8BIT | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
# define dib9000_risc_mem_write_chunks(state, buf, len) dib9000_write16_attr(state, 1063, buf, len, DATA_BUS_ACCESS_MODE_8BIT | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
static void dib9000_risc_mem_setup_cmd ( struct dib9000_state * state , u32 addr , u32 len , u8 reading )
{
u8 b [ 14 ] = { 0 } ;
2011-01-04 19:08:14 +03:00
/* dprintk("%d memcmd: %d %d %d\n", state->fe_id, addr, addr+len, len); */
/* b[0] = 0 << 7; */
2011-01-04 10:28:59 +03:00
b [ 1 ] = 1 ;
2011-01-04 19:08:14 +03:00
/* b[2] = 0; */
/* b[3] = 0; */
b [ 4 ] = ( u8 ) ( addr > > 8 ) ;
2011-01-04 10:28:59 +03:00
b [ 5 ] = ( u8 ) ( addr & 0xff ) ;
2011-01-04 19:08:14 +03:00
/* b[10] = 0; */
/* b[11] = 0; */
b [ 12 ] = ( u8 ) ( addr > > 8 ) ;
2011-01-04 10:28:59 +03:00
b [ 13 ] = ( u8 ) ( addr & 0xff ) ;
addr + = len ;
2011-01-04 19:08:14 +03:00
/* b[6] = 0; */
/* b[7] = 0; */
b [ 8 ] = ( u8 ) ( addr > > 8 ) ;
2011-01-04 10:28:59 +03:00
b [ 9 ] = ( u8 ) ( addr & 0xff ) ;
dib9000_write ( state , 1056 , b , 14 ) ;
if ( reading )
dib9000_write_word ( state , 1056 , ( 1 < < 15 ) | 1 ) ;
state - > platform . risc . memcmd = - 1 ; /* if it was called directly reset it - to force a future setup-call to set it */
}
static void dib9000_risc_mem_setup ( struct dib9000_state * state , u8 cmd )
{
struct dib9000_fe_memory_map * m = & state - > platform . risc . fe_mm [ cmd & 0x7f ] ;
/* decide whether we need to "refresh" the memory controller */
if ( state - > platform . risc . memcmd = = cmd & & /* same command */
2011-01-04 19:08:14 +03:00
! ( cmd & 0x80 & & m - > size < 67 ) ) /* and we do not want to read something with less than 67 bytes looping - working around a bug in the memory controller */
2011-01-04 10:28:59 +03:00
return ;
dib9000_risc_mem_setup_cmd ( state , m - > addr , m - > size , cmd & 0x80 ) ;
state - > platform . risc . memcmd = cmd ;
}
static int dib9000_risc_mem_read ( struct dib9000_state * state , u8 cmd , u8 * b , u16 len )
{
if ( ! state - > platform . risc . fw_is_running )
return - EIO ;
2012-03-19 23:48:34 +04:00
if ( mutex_lock_interruptible ( & state - > platform . risc . mem_lock ) < 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " could not get the lock \n " ) ;
2012-03-07 00:08:29 +04:00
return - EINTR ;
}
2011-01-04 10:28:59 +03:00
dib9000_risc_mem_setup ( state , cmd | 0x80 ) ;
dib9000_risc_mem_read_chunks ( state , b , len ) ;
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > platform . risc . mem_lock ) ;
2011-01-04 10:28:59 +03:00
return 0 ;
}
static int dib9000_risc_mem_write ( struct dib9000_state * state , u8 cmd , const u8 * b )
{
struct dib9000_fe_memory_map * m = & state - > platform . risc . fe_mm [ cmd ] ;
if ( ! state - > platform . risc . fw_is_running )
return - EIO ;
2012-03-19 23:48:34 +04:00
if ( mutex_lock_interruptible ( & state - > platform . risc . mem_lock ) < 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " could not get the lock \n " ) ;
2012-03-07 00:08:29 +04:00
return - EINTR ;
}
2011-01-04 10:28:59 +03:00
dib9000_risc_mem_setup ( state , cmd ) ;
dib9000_risc_mem_write_chunks ( state , b , m - > size ) ;
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > platform . risc . mem_lock ) ;
2011-01-04 10:28:59 +03:00
return 0 ;
}
static int dib9000_firmware_download ( struct dib9000_state * state , u8 risc_id , u16 key , const u8 * code , u32 len )
{
u16 offs ;
if ( risc_id = = 1 )
offs = 16 ;
else
offs = 0 ;
/* config crtl reg */
dib9000_write_word ( state , 1024 + offs , 0x000f ) ;
dib9000_write_word ( state , 1025 + offs , 0 ) ;
dib9000_write_word ( state , 1031 + offs , key ) ;
2016-10-14 16:08:40 +03:00
dprintk ( " going to download %dB of microcode \n " , len ) ;
2011-01-04 10:28:59 +03:00
if ( dib9000_write16_noinc ( state , 1026 + offs , ( u8 * ) code , ( u16 ) len ) ! = 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " error while downloading microcode for RISC %c \n " , ' A ' + risc_id ) ;
2011-01-04 10:28:59 +03:00
return - EIO ;
}
2016-10-14 16:08:40 +03:00
dprintk ( " Microcode for RISC %c loaded \n " , ' A ' + risc_id ) ;
2011-01-04 10:28:59 +03:00
return 0 ;
}
static int dib9000_mbx_host_init ( struct dib9000_state * state , u8 risc_id )
{
u16 mbox_offs ;
u16 reset_reg ;
u16 tries = 1000 ;
if ( risc_id = = 1 )
mbox_offs = 16 ;
else
mbox_offs = 0 ;
/* Reset mailbox */
dib9000_write_word ( state , 1027 + mbox_offs , 0x8000 ) ;
/* Read reset status */
do {
reset_reg = dib9000_read_word ( state , 1027 + mbox_offs ) ;
msleep ( 100 ) ;
} while ( ( reset_reg & 0x8000 ) & & - - tries ) ;
if ( reset_reg & 0x8000 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " MBX: init ERROR, no response from RISC %c \n " , ' A ' + risc_id ) ;
2011-01-04 10:28:59 +03:00
return - EIO ;
}
2016-10-14 16:08:40 +03:00
dprintk ( " MBX: initialized \n " ) ;
2011-01-04 10:28:59 +03:00
return 0 ;
}
# define MAX_MAILBOX_TRY 100
static int dib9000_mbx_send_attr ( struct dib9000_state * state , u8 id , u16 * data , u8 len , u16 attr )
{
2011-01-19 17:28:27 +03:00
u8 * d , b [ 2 ] ;
2011-01-04 10:28:59 +03:00
u16 tmp ;
u16 size ;
u32 i ;
2011-01-19 17:28:27 +03:00
int ret = 0 ;
2011-01-04 10:28:59 +03:00
if ( ! state - > platform . risc . fw_is_running )
return - EINVAL ;
2012-03-19 23:48:34 +04:00
if ( mutex_lock_interruptible ( & state - > platform . risc . mbx_if_lock ) < 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " could not get the lock \n " ) ;
2012-03-07 00:08:29 +04:00
return - EINTR ;
}
2011-01-04 10:28:59 +03:00
tmp = MAX_MAILBOX_TRY ;
do {
size = dib9000_read_word_attr ( state , 1043 , attr ) & 0xff ;
if ( ( size + len + 1 ) > MBX_MAX_WORDS & & - - tmp ) {
2016-10-14 16:08:40 +03:00
dprintk ( " MBX: RISC mbx full, retrying \n " ) ;
2011-01-04 10:28:59 +03:00
msleep ( 100 ) ;
} else
break ;
} while ( 1 ) ;
2016-10-14 16:08:40 +03:00
/*dprintk( "MBX: size: %d\n", size); */
2011-01-04 10:28:59 +03:00
if ( tmp = = 0 ) {
ret = - EINVAL ;
goto out ;
}
# ifdef DUMP_MSG
2016-10-14 16:08:40 +03:00
dprintk ( " --> %02x %d %*ph \n " , id , len + 1 , len , data ) ;
2011-01-04 10:28:59 +03:00
# endif
/* byte-order conversion - works on big (where it is not necessary) or little endian */
d = ( u8 * ) data ;
for ( i = 0 ; i < len ; i + + ) {
tmp = data [ i ] ;
* d + + = tmp > > 8 ;
* d + + = tmp & 0xff ;
}
/* write msg */
b [ 0 ] = id ;
b [ 1 ] = len + 1 ;
if ( dib9000_write16_noinc_attr ( state , 1045 , b , 2 , attr ) ! = 0 | | dib9000_write16_noinc_attr ( state , 1045 , ( u8 * ) data , len * 2 , attr ) ! = 0 ) {
ret = - EIO ;
goto out ;
}
/* update register nb_mes_in_RX */
ret = ( u8 ) dib9000_write_word_attr ( state , 1043 , 1 < < 14 , attr ) ;
2011-01-04 19:08:14 +03:00
out :
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > platform . risc . mbx_if_lock ) ;
2011-01-04 10:28:59 +03:00
return ret ;
}
static u8 dib9000_mbx_read ( struct dib9000_state * state , u16 * data , u8 risc_id , u16 attr )
{
# ifdef DUMP_MSG
u16 * d = data ;
# endif
u16 tmp , i ;
u8 size ;
u8 mc_base ;
if ( ! state - > platform . risc . fw_is_running )
return 0 ;
2012-03-19 23:48:34 +04:00
if ( mutex_lock_interruptible ( & state - > platform . risc . mbx_if_lock ) < 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " could not get the lock \n " ) ;
2012-03-07 00:08:29 +04:00
return 0 ;
}
2011-01-04 10:28:59 +03:00
if ( risc_id = = 1 )
mc_base = 16 ;
else
mc_base = 0 ;
/* Length and type in the first word */
* data = dib9000_read_word_attr ( state , 1029 + mc_base , attr ) ;
size = * data & 0xff ;
if ( size < = MBX_MAX_WORDS ) {
data + + ;
size - - ; /* Initial word already read */
dib9000_read16_noinc_attr ( state , 1029 + mc_base , ( u8 * ) data , size * 2 , attr ) ;
/* to word conversion */
for ( i = 0 ; i < size ; i + + ) {
tmp = * data ;
* data = ( tmp > > 8 ) | ( tmp < < 8 ) ;
data + + ;
}
# ifdef DUMP_MSG
2016-10-14 16:08:40 +03:00
dprintk ( " <-- \n " ) ;
2011-01-04 10:28:59 +03:00
for ( i = 0 ; i < size + 1 ; i + + )
2016-10-14 16:08:40 +03:00
dprintk ( " %04x \n " , d [ i ] ) ;
2011-01-04 10:28:59 +03:00
dprintk ( " \n " ) ;
# endif
} else {
2016-10-14 16:08:40 +03:00
dprintk ( " MBX: message is too big for message cache (%d), flushing message \n " , size ) ;
2011-01-04 10:28:59 +03:00
size - - ; /* Initial word already read */
while ( size - - )
dib9000_read16_noinc_attr ( state , 1029 + mc_base , ( u8 * ) data , 2 , attr ) ;
}
/* Update register nb_mes_in_TX */
dib9000_write_word_attr ( state , 1028 + mc_base , 1 < < 14 , attr ) ;
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > platform . risc . mbx_if_lock ) ;
2011-01-04 10:28:59 +03:00
return size + 1 ;
}
static int dib9000_risc_debug_buf ( struct dib9000_state * state , u16 * data , u8 size )
{
u32 ts = data [ 1 ] < < 16 | data [ 0 ] ;
char * b = ( char * ) & data [ 2 ] ;
b [ 2 * ( size - 2 ) - 1 ] = ' \0 ' ; /* Bullet proof the buffer */
if ( * b = = ' ~ ' ) {
b + + ;
2016-10-14 16:08:40 +03:00
dprintk ( " %s \n " , b ) ;
2011-01-04 10:28:59 +03:00
} else
2016-10-14 16:08:40 +03:00
dprintk ( " RISC%d: %d.%04d %s \n " ,
state - > fe_id ,
ts / 10000 , ts % 10000 , * b ? b : " <empty> " ) ;
2011-01-04 10:28:59 +03:00
return 1 ;
}
static int dib9000_mbx_fetch_to_cache ( struct dib9000_state * state , u16 attr )
{
int i ;
u8 size ;
u16 * block ;
/* find a free slot */
for ( i = 0 ; i < DIB9000_MSG_CACHE_SIZE ; i + + ) {
block = state - > platform . risc . message_cache [ i ] ;
if ( * block = = 0 ) {
size = dib9000_mbx_read ( state , block , 1 , attr ) ;
2016-10-14 16:08:40 +03:00
/* dprintk( "MBX: fetched %04x message to cache\n", *block); */
2011-01-04 10:28:59 +03:00
switch ( * block > > 8 ) {
case IN_MSG_DEBUG_BUF :
dib9000_risc_debug_buf ( state , block + 1 , size ) ; /* debug-messages are going to be printed right away */
* block = 0 ; /* free the block */
break ;
#if 0
case IN_MSG_DATA : /* FE-TRACE */
dib9000_risc_data_process ( state , block + 1 , size ) ;
* block = 0 ;
break ;
# endif
default :
break ;
}
return 1 ;
}
}
2016-10-14 16:08:40 +03:00
dprintk ( " MBX: no free cache-slot found for new message... \n " ) ;
2011-01-04 10:28:59 +03:00
return - 1 ;
}
static u8 dib9000_mbx_count ( struct dib9000_state * state , u8 risc_id , u16 attr )
{
if ( risc_id = = 0 )
return ( u8 ) ( dib9000_read_word_attr ( state , 1028 , attr ) > > 10 ) & 0x1f ; /* 5 bit field */
else
return ( u8 ) ( dib9000_read_word_attr ( state , 1044 , attr ) > > 8 ) & 0x7f ; /* 7 bit field */
}
static int dib9000_mbx_process ( struct dib9000_state * state , u16 attr )
{
int ret = 0 ;
if ( ! state - > platform . risc . fw_is_running )
return - 1 ;
2012-03-19 23:48:34 +04:00
if ( mutex_lock_interruptible ( & state - > platform . risc . mbx_lock ) < 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " could not get the lock \n " ) ;
2012-03-07 00:08:29 +04:00
return - 1 ;
}
2011-01-04 10:28:59 +03:00
if ( dib9000_mbx_count ( state , 1 , attr ) ) /* 1=RiscB */
ret = dib9000_mbx_fetch_to_cache ( state , attr ) ;
2012-04-20 15:04:48 +04:00
dib9000_read_word_attr ( state , 1229 , attr ) ; /* Clear the IRQ */
2011-01-04 19:08:14 +03:00
/* if (tmp) */
2016-10-14 16:08:40 +03:00
/* dprintk( "cleared IRQ: %x\n", tmp); */
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > platform . risc . mbx_lock ) ;
2011-01-04 10:28:59 +03:00
return ret ;
}
static int dib9000_mbx_get_message_attr ( struct dib9000_state * state , u16 id , u16 * msg , u8 * size , u16 attr )
{
u8 i ;
u16 * block ;
u16 timeout = 30 ;
* msg = 0 ;
do {
/* dib9000_mbx_get_from_cache(); */
for ( i = 0 ; i < DIB9000_MSG_CACHE_SIZE ; i + + ) {
block = state - > platform . risc . message_cache [ i ] ;
if ( ( * block > > 8 ) = = id ) {
* size = ( * block & 0xff ) - 1 ;
memcpy ( msg , block + 1 , ( * size ) * 2 ) ;
* block = 0 ; /* free the block */
i = 0 ; /* signal that we found a message */
break ;
}
}
if ( i = = 0 )
break ;
if ( dib9000_mbx_process ( state , attr ) = = - 1 ) /* try to fetch one message - if any */
return - 1 ;
} while ( - - timeout ) ;
if ( timeout = = 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " waiting for message %d timed out \n " , id ) ;
2011-01-04 10:28:59 +03:00
return - 1 ;
}
return i = = 0 ;
}
static int dib9000_risc_check_version ( struct dib9000_state * state )
{
u8 r [ 4 ] ;
u8 size ;
u16 fw_version = 0 ;
if ( dib9000_mbx_send ( state , OUT_MSG_REQ_VERSION , & fw_version , 1 ) ! = 0 )
return - EIO ;
if ( dib9000_mbx_get_message ( state , IN_MSG_VERSION , ( u16 * ) r , & size ) < 0 )
return - EIO ;
fw_version = ( r [ 0 ] < < 8 ) | r [ 1 ] ;
2016-10-14 16:08:40 +03:00
dprintk ( " RISC: ver: %d.%02d (IC: %d) \n " , fw_version > > 10 , fw_version & 0x3ff , ( r [ 2 ] < < 8 ) | r [ 3 ] ) ;
2011-01-04 10:28:59 +03:00
if ( ( fw_version > > 10 ) ! = 7 )
return - EINVAL ;
switch ( fw_version & 0x3ff ) {
case 11 :
case 12 :
case 14 :
case 15 :
case 16 :
case 17 :
break ;
default :
dprintk ( " RISC: invalid firmware version " ) ;
return - EINVAL ;
}
dprintk ( " RISC: valid firmware version " ) ;
return 0 ;
}
static int dib9000_fw_boot ( struct dib9000_state * state , const u8 * codeA , u32 lenA , const u8 * codeB , u32 lenB )
{
/* Reconfig pool mac ram */
dib9000_write_word ( state , 1225 , 0x02 ) ; /* A: 8k C, 4 k D - B: 32k C 6 k D - IRAM 96k */
dib9000_write_word ( state , 1226 , 0x05 ) ;
/* Toggles IP crypto to Host APB interface. */
dib9000_write_word ( state , 1542 , 1 ) ;
/* Set jump and no jump in the dma box */
dib9000_write_word ( state , 1074 , 0 ) ;
dib9000_write_word ( state , 1075 , 0 ) ;
/* Set MAC as APB Master. */
dib9000_write_word ( state , 1237 , 0 ) ;
/* Reset the RISCs */
if ( codeA ! = NULL )
dib9000_write_word ( state , 1024 , 2 ) ;
else
dib9000_write_word ( state , 1024 , 15 ) ;
if ( codeB ! = NULL )
dib9000_write_word ( state , 1040 , 2 ) ;
if ( codeA ! = NULL )
dib9000_firmware_download ( state , 0 , 0x1234 , codeA , lenA ) ;
if ( codeB ! = NULL )
dib9000_firmware_download ( state , 1 , 0x1234 , codeB , lenB ) ;
/* Run the RISCs */
if ( codeA ! = NULL )
dib9000_write_word ( state , 1024 , 0 ) ;
if ( codeB ! = NULL )
dib9000_write_word ( state , 1040 , 0 ) ;
if ( codeA ! = NULL )
if ( dib9000_mbx_host_init ( state , 0 ) ! = 0 )
return - EIO ;
if ( codeB ! = NULL )
if ( dib9000_mbx_host_init ( state , 1 ) ! = 0 )
return - EIO ;
msleep ( 100 ) ;
state - > platform . risc . fw_is_running = 1 ;
if ( dib9000_risc_check_version ( state ) ! = 0 )
return - EINVAL ;
state - > platform . risc . memcmd = 0xff ;
return 0 ;
}
static u16 dib9000_identify ( struct i2c_device * client )
{
u16 value ;
2011-01-04 19:08:14 +03:00
value = dib9000_i2c_read16 ( client , 896 ) ;
if ( value ! = 0x01b3 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " wrong Vendor ID (0x%x) \n " , value ) ;
2011-01-04 10:28:59 +03:00
return 0 ;
}
value = dib9000_i2c_read16 ( client , 897 ) ;
if ( value ! = 0x4000 & & value ! = 0x4001 & & value ! = 0x4002 & & value ! = 0x4003 & & value ! = 0x4004 & & value ! = 0x4005 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " wrong Device ID (0x%x) \n " , value ) ;
2011-01-04 10:28:59 +03:00
return 0 ;
}
/* protect this driver to be used with 7000PC */
if ( value = = 0x4000 & & dib9000_i2c_read16 ( client , 769 ) = = 0x4000 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " this driver does not work with DiB7000PC \n " ) ;
2011-01-04 10:28:59 +03:00
return 0 ;
}
switch ( value ) {
case 0x4000 :
2016-10-14 16:08:40 +03:00
dprintk ( " found DiB7000MA/PA/MB/PB \n " ) ;
2011-01-04 10:28:59 +03:00
break ;
case 0x4001 :
2016-10-14 16:08:40 +03:00
dprintk ( " found DiB7000HC \n " ) ;
2011-01-04 10:28:59 +03:00
break ;
case 0x4002 :
2016-10-14 16:08:40 +03:00
dprintk ( " found DiB7000MC \n " ) ;
2011-01-04 10:28:59 +03:00
break ;
case 0x4003 :
2016-10-14 16:08:40 +03:00
dprintk ( " found DiB9000A \n " ) ;
2011-01-04 10:28:59 +03:00
break ;
case 0x4004 :
2016-10-14 16:08:40 +03:00
dprintk ( " found DiB9000H \n " ) ;
2011-01-04 10:28:59 +03:00
break ;
case 0x4005 :
2016-10-14 16:08:40 +03:00
dprintk ( " found DiB9000M \n " ) ;
2011-01-04 10:28:59 +03:00
break ;
}
return value ;
}
static void dib9000_set_power_mode ( struct dib9000_state * state , enum dib9000_power_mode mode )
{
/* by default everything is going to be powered off */
u16 reg_903 = 0x3fff , reg_904 = 0xffff , reg_905 = 0xffff , reg_906 ;
u8 offset ;
if ( state - > revision = = 0x4003 | | state - > revision = = 0x4004 | | state - > revision = = 0x4005 )
offset = 1 ;
else
offset = 0 ;
reg_906 = dib9000_read_word ( state , 906 + offset ) | 0x3 ; /* keep settings for RISC */
/* now, depending on the requested mode, we power on */
switch ( mode ) {
/* power up everything in the demod */
case DIB9000_POWER_ALL :
reg_903 = 0x0000 ;
reg_904 = 0x0000 ;
reg_905 = 0x0000 ;
reg_906 = 0x0000 ;
break ;
/* just leave power on the control-interfaces: GPIO and (I2C or SDIO or SRAM) */
case DIB9000_POWER_INTERFACE_ONLY : /* TODO power up either SDIO or I2C or SRAM */
reg_905 & = ~ ( ( 1 < < 7 ) | ( 1 < < 6 ) | ( 1 < < 5 ) | ( 1 < < 2 ) ) ;
break ;
case DIB9000_POWER_INTERF_ANALOG_AGC :
reg_903 & = ~ ( ( 1 < < 15 ) | ( 1 < < 14 ) | ( 1 < < 11 ) | ( 1 < < 10 ) ) ;
reg_905 & = ~ ( ( 1 < < 7 ) | ( 1 < < 6 ) | ( 1 < < 5 ) | ( 1 < < 4 ) | ( 1 < < 2 ) ) ;
reg_906 & = ~ ( ( 1 < < 0 ) ) ;
break ;
case DIB9000_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD :
reg_903 = 0x0000 ;
reg_904 = 0x801f ;
reg_905 = 0x0000 ;
reg_906 & = ~ ( ( 1 < < 0 ) ) ;
break ;
case DIB9000_POWER_COR4_CRY_ESRAM_MOUT_NUD :
reg_903 = 0x0000 ;
reg_904 = 0x8000 ;
reg_905 = 0x010b ;
reg_906 & = ~ ( ( 1 < < 0 ) ) ;
break ;
default :
case DIB9000_POWER_NO :
break ;
}
/* always power down unused parts */
if ( ! state - > platform . host . mobile_mode )
reg_904 | = ( 1 < < 7 ) | ( 1 < < 6 ) | ( 1 < < 4 ) | ( 1 < < 2 ) | ( 1 < < 1 ) ;
/* P_sdio_select_clk = 0 on MC and after */
if ( state - > revision ! = 0x4000 )
reg_906 < < = 1 ;
dib9000_write_word ( state , 903 + offset , reg_903 ) ;
dib9000_write_word ( state , 904 + offset , reg_904 ) ;
dib9000_write_word ( state , 905 + offset , reg_905 ) ;
dib9000_write_word ( state , 906 + offset , reg_906 ) ;
}
static int dib9000_fw_reset ( struct dvb_frontend * fe )
{
struct dib9000_state * state = fe - > demodulator_priv ;
2011-01-04 19:08:14 +03:00
dib9000_write_word ( state , 1817 , 0x0003 ) ;
2011-01-04 10:28:59 +03:00
dib9000_write_word ( state , 1227 , 1 ) ;
dib9000_write_word ( state , 1227 , 0 ) ;
switch ( ( state - > revision = dib9000_identify ( & state - > i2c ) ) ) {
case 0x4003 :
case 0x4004 :
case 0x4005 :
state - > reg_offs = 1 ;
break ;
default :
return - EINVAL ;
}
/* reset the i2c-master to use the host interface */
dibx000_reset_i2c_master ( & state - > i2c_master ) ;
dib9000_set_power_mode ( state , DIB9000_POWER_ALL ) ;
/* unforce divstr regardless whether i2c enumeration was done or not */
dib9000_write_word ( state , 1794 , dib9000_read_word ( state , 1794 ) & ~ ( 1 < < 1 ) ) ;
dib9000_write_word ( state , 1796 , 0 ) ;
dib9000_write_word ( state , 1805 , 0x805 ) ;
/* restart all parts */
dib9000_write_word ( state , 898 , 0xffff ) ;
dib9000_write_word ( state , 899 , 0xffff ) ;
dib9000_write_word ( state , 900 , 0x0001 ) ;
dib9000_write_word ( state , 901 , 0xff19 ) ;
dib9000_write_word ( state , 902 , 0x003c ) ;
dib9000_write_word ( state , 898 , 0 ) ;
dib9000_write_word ( state , 899 , 0 ) ;
dib9000_write_word ( state , 900 , 0 ) ;
dib9000_write_word ( state , 901 , 0 ) ;
dib9000_write_word ( state , 902 , 0 ) ;
dib9000_write_word ( state , 911 , state - > chip . d9 . cfg . if_drives ) ;
dib9000_set_power_mode ( state , DIB9000_POWER_INTERFACE_ONLY ) ;
return 0 ;
}
2011-01-04 19:08:14 +03:00
static int dib9000_risc_apb_access_read ( struct dib9000_state * state , u32 address , u16 attribute , const u8 * tx , u32 txlen , u8 * b , u32 len )
2011-01-04 10:28:59 +03:00
{
u16 mb [ 10 ] ;
u8 i , s ;
if ( address > = 1024 | | ! state - > platform . risc . fw_is_running )
return - EINVAL ;
2019-02-18 22:28:55 +03:00
/* dprintk( "APB access through rd fw %d %x\n", address, attribute); */
2011-01-04 10:28:59 +03:00
mb [ 0 ] = ( u16 ) address ;
mb [ 1 ] = len / 2 ;
dib9000_mbx_send_attr ( state , OUT_MSG_BRIDGE_APB_R , mb , 2 , attribute ) ;
switch ( dib9000_mbx_get_message_attr ( state , IN_MSG_END_BRIDGE_APB_RW , mb , & s , attribute ) ) {
case 1 :
2011-01-04 19:08:14 +03:00
s - - ;
2011-01-04 10:28:59 +03:00
for ( i = 0 ; i < s ; i + + ) {
b [ i * 2 ] = ( mb [ i + 1 ] > > 8 ) & 0xff ;
b [ i * 2 + 1 ] = ( mb [ i + 1 ] ) & 0xff ;
}
return 0 ;
default :
return - EIO ;
}
return - EIO ;
}
static int dib9000_risc_apb_access_write ( struct dib9000_state * state , u32 address , u16 attribute , const u8 * b , u32 len )
{
u16 mb [ 10 ] ;
u8 s , i ;
if ( address > = 1024 | | ! state - > platform . risc . fw_is_running )
return - EINVAL ;
2014-06-19 18:49:40 +04:00
if ( len > 18 )
return - EINVAL ;
2019-02-18 22:28:55 +03:00
/* dprintk( "APB access through wr fw %d %x\n", address, attribute); */
2011-01-04 10:28:59 +03:00
2014-06-19 18:49:40 +04:00
mb [ 0 ] = ( u16 ) address ;
for ( i = 0 ; i + 1 < len ; i + = 2 )
mb [ 1 + i / 2 ] = b [ i ] < < 8 | b [ i + 1 ] ;
if ( len & 1 )
mb [ 1 + len / 2 ] = b [ len - 1 ] < < 8 ;
2011-01-04 10:28:59 +03:00
2014-06-19 18:49:40 +04:00
dib9000_mbx_send_attr ( state , OUT_MSG_BRIDGE_APB_W , mb , ( 3 + len ) / 2 , attribute ) ;
2011-01-04 10:28:59 +03:00
return dib9000_mbx_get_message_attr ( state , IN_MSG_END_BRIDGE_APB_RW , mb , & s , attribute ) = = 1 ? 0 : - EINVAL ;
}
static int dib9000_fw_memmbx_sync ( struct dib9000_state * state , u8 i )
{
u8 index_loop = 10 ;
if ( ! state - > platform . risc . fw_is_running )
return 0 ;
dib9000_risc_mem_write ( state , FE_MM_RW_SYNC , & i ) ;
do {
2011-05-03 19:27:33 +04:00
dib9000_risc_mem_read ( state , FE_MM_RW_SYNC , state - > i2c_read_buffer , 1 ) ;
} while ( state - > i2c_read_buffer [ 0 ] & & index_loop - - ) ;
2011-01-04 10:28:59 +03:00
if ( index_loop > 0 )
return 0 ;
return - EIO ;
}
static int dib9000_fw_init ( struct dib9000_state * state )
{
struct dibGPIOFunction * f ;
u16 b [ 40 ] = { 0 } ;
u8 i ;
u8 size ;
if ( dib9000_fw_boot ( state , NULL , 0 , state - > chip . d9 . cfg . microcode_B_fe_buffer , state - > chip . d9 . cfg . microcode_B_fe_size ) ! = 0 )
return - EIO ;
/* initialize the firmware */
for ( i = 0 ; i < ARRAY_SIZE ( state - > chip . d9 . cfg . gpio_function ) ; i + + ) {
f = & state - > chip . d9 . cfg . gpio_function [ i ] ;
if ( f - > mask ) {
switch ( f - > function ) {
case BOARD_GPIO_FUNCTION_COMPONENT_ON :
b [ 0 ] = ( u16 ) f - > mask ;
b [ 1 ] = ( u16 ) f - > direction ;
b [ 2 ] = ( u16 ) f - > value ;
break ;
case BOARD_GPIO_FUNCTION_COMPONENT_OFF :
b [ 3 ] = ( u16 ) f - > mask ;
b [ 4 ] = ( u16 ) f - > direction ;
b [ 5 ] = ( u16 ) f - > value ;
break ;
}
}
}
if ( dib9000_mbx_send ( state , OUT_MSG_CONF_GPIO , b , 15 ) ! = 0 )
return - EIO ;
/* subband */
b [ 0 ] = state - > chip . d9 . cfg . subband . size ; /* type == 0 -> GPIO - PWM not yet supported */
for ( i = 0 ; i < state - > chip . d9 . cfg . subband . size ; i + + ) {
b [ 1 + i * 4 ] = state - > chip . d9 . cfg . subband . subband [ i ] . f_mhz ;
b [ 2 + i * 4 ] = ( u16 ) state - > chip . d9 . cfg . subband . subband [ i ] . gpio . mask ;
b [ 3 + i * 4 ] = ( u16 ) state - > chip . d9 . cfg . subband . subband [ i ] . gpio . direction ;
b [ 4 + i * 4 ] = ( u16 ) state - > chip . d9 . cfg . subband . subband [ i ] . gpio . value ;
}
b [ 1 + i * 4 ] = 0 ; /* fe_id */
if ( dib9000_mbx_send ( state , OUT_MSG_SUBBAND_SEL , b , 2 + 4 * i ) ! = 0 )
return - EIO ;
/* 0 - id, 1 - no_of_frontends */
b [ 0 ] = ( 0 < < 8 ) | 1 ;
/* 0 = i2c-address demod, 0 = tuner */
2011-01-04 19:08:14 +03:00
b [ 1 ] = ( 0 < < 8 ) | ( 0 ) ;
2011-01-04 10:28:59 +03:00
b [ 2 ] = ( u16 ) ( ( ( state - > chip . d9 . cfg . xtal_clock_khz * 1000 ) > > 16 ) & 0xffff ) ;
b [ 3 ] = ( u16 ) ( ( ( state - > chip . d9 . cfg . xtal_clock_khz * 1000 ) ) & 0xffff ) ;
b [ 4 ] = ( u16 ) ( ( state - > chip . d9 . cfg . vcxo_timer > > 16 ) & 0xffff ) ;
b [ 5 ] = ( u16 ) ( ( state - > chip . d9 . cfg . vcxo_timer ) & 0xffff ) ;
b [ 6 ] = ( u16 ) ( ( state - > chip . d9 . cfg . timing_frequency > > 16 ) & 0xffff ) ;
b [ 7 ] = ( u16 ) ( ( state - > chip . d9 . cfg . timing_frequency ) & 0xffff ) ;
b [ 29 ] = state - > chip . d9 . cfg . if_drives ;
if ( dib9000_mbx_send ( state , OUT_MSG_INIT_DEMOD , b , ARRAY_SIZE ( b ) ) ! = 0 )
return - EIO ;
if ( dib9000_mbx_send ( state , OUT_MSG_FE_FW_DL , NULL , 0 ) ! = 0 )
return - EIO ;
if ( dib9000_mbx_get_message ( state , IN_MSG_FE_FW_DL_DONE , b , & size ) < 0 )
return - EIO ;
if ( size > ARRAY_SIZE ( b ) ) {
2011-01-04 19:08:14 +03:00
dprintk ( " error : firmware returned %dbytes needed but the used buffer has only %dbytes \n Firmware init ABORTED " , size ,
( int ) ARRAY_SIZE ( b ) ) ;
2011-01-04 10:28:59 +03:00
return - EINVAL ;
}
for ( i = 0 ; i < size ; i + = 2 ) {
state - > platform . risc . fe_mm [ i / 2 ] . addr = b [ i + 0 ] ;
state - > platform . risc . fe_mm [ i / 2 ] . size = b [ i + 1 ] ;
}
return 0 ;
}
2011-12-23 02:54:08 +04:00
static void dib9000_fw_set_channel_head ( struct dib9000_state * state )
2011-01-04 10:28:59 +03:00
{
u8 b [ 9 ] ;
u32 freq = state - > fe [ 0 ] - > dtv_property_cache . frequency / 1000 ;
if ( state - > fe_id % 2 )
freq + = 101 ;
b [ 0 ] = ( u8 ) ( ( freq > > 0 ) & 0xff ) ;
b [ 1 ] = ( u8 ) ( ( freq > > 8 ) & 0xff ) ;
b [ 2 ] = ( u8 ) ( ( freq > > 16 ) & 0xff ) ;
b [ 3 ] = ( u8 ) ( ( freq > > 24 ) & 0xff ) ;
b [ 4 ] = ( u8 ) ( ( state - > fe [ 0 ] - > dtv_property_cache . bandwidth_hz / 1000 > > 0 ) & 0xff ) ;
b [ 5 ] = ( u8 ) ( ( state - > fe [ 0 ] - > dtv_property_cache . bandwidth_hz / 1000 > > 8 ) & 0xff ) ;
b [ 6 ] = ( u8 ) ( ( state - > fe [ 0 ] - > dtv_property_cache . bandwidth_hz / 1000 > > 16 ) & 0xff ) ;
b [ 7 ] = ( u8 ) ( ( state - > fe [ 0 ] - > dtv_property_cache . bandwidth_hz / 1000 > > 24 ) & 0xff ) ;
b [ 8 ] = 0x80 ; /* do not wait for CELL ID when doing autosearch */
if ( state - > fe [ 0 ] - > dtv_property_cache . delivery_system = = SYS_DVBT )
b [ 8 ] | = 1 ;
dib9000_risc_mem_write ( state , FE_MM_W_CHANNEL_HEAD , b ) ;
}
2011-12-23 02:54:08 +04:00
static int dib9000_fw_get_channel ( struct dvb_frontend * fe )
2011-01-04 10:28:59 +03:00
{
struct dib9000_state * state = fe - > demodulator_priv ;
struct dibDVBTChannel {
s8 spectrum_inversion ;
s8 nfft ;
s8 guard ;
s8 constellation ;
s8 hrch ;
s8 alpha ;
s8 code_rate_hp ;
s8 code_rate_lp ;
s8 select_hp ;
s8 intlv_native ;
} ;
2011-05-03 19:27:33 +04:00
struct dibDVBTChannel * ch ;
2011-01-04 10:28:59 +03:00
int ret = 0 ;
2012-03-19 23:48:34 +04:00
if ( mutex_lock_interruptible ( & state - > platform . risc . mem_mbx_lock ) < 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " could not get the lock \n " ) ;
2012-03-07 00:08:29 +04:00
return - EINTR ;
}
2011-01-04 10:28:59 +03:00
if ( dib9000_fw_memmbx_sync ( state , FE_SYNC_CHANNEL ) < 0 ) {
ret = - EIO ;
2011-08-06 12:01:51 +04:00
goto error ;
2011-01-04 10:28:59 +03:00
}
2011-05-03 19:27:33 +04:00
dib9000_risc_mem_read ( state , FE_MM_R_CHANNEL_UNION ,
state - > i2c_read_buffer , sizeof ( struct dibDVBTChannel ) ) ;
ch = ( struct dibDVBTChannel * ) state - > i2c_read_buffer ;
2011-01-04 10:28:59 +03:00
2011-05-03 19:27:33 +04:00
switch ( ch - > spectrum_inversion & 0x7 ) {
2011-01-04 10:28:59 +03:00
case 1 :
state - > fe [ 0 ] - > dtv_property_cache . inversion = INVERSION_ON ;
break ;
case 0 :
state - > fe [ 0 ] - > dtv_property_cache . inversion = INVERSION_OFF ;
break ;
default :
case - 1 :
state - > fe [ 0 ] - > dtv_property_cache . inversion = INVERSION_AUTO ;
break ;
}
2011-05-03 19:27:33 +04:00
switch ( ch - > nfft ) {
2011-01-04 10:28:59 +03:00
case 0 :
state - > fe [ 0 ] - > dtv_property_cache . transmission_mode = TRANSMISSION_MODE_2K ;
break ;
case 2 :
state - > fe [ 0 ] - > dtv_property_cache . transmission_mode = TRANSMISSION_MODE_4K ;
break ;
case 1 :
state - > fe [ 0 ] - > dtv_property_cache . transmission_mode = TRANSMISSION_MODE_8K ;
break ;
default :
case - 1 :
state - > fe [ 0 ] - > dtv_property_cache . transmission_mode = TRANSMISSION_MODE_AUTO ;
break ;
}
2011-05-03 19:27:33 +04:00
switch ( ch - > guard ) {
2011-01-04 10:28:59 +03:00
case 0 :
state - > fe [ 0 ] - > dtv_property_cache . guard_interval = GUARD_INTERVAL_1_32 ;
break ;
case 1 :
state - > fe [ 0 ] - > dtv_property_cache . guard_interval = GUARD_INTERVAL_1_16 ;
break ;
case 2 :
state - > fe [ 0 ] - > dtv_property_cache . guard_interval = GUARD_INTERVAL_1_8 ;
break ;
case 3 :
state - > fe [ 0 ] - > dtv_property_cache . guard_interval = GUARD_INTERVAL_1_4 ;
break ;
default :
case - 1 :
state - > fe [ 0 ] - > dtv_property_cache . guard_interval = GUARD_INTERVAL_AUTO ;
break ;
}
2011-05-03 19:27:33 +04:00
switch ( ch - > constellation ) {
2011-01-04 10:28:59 +03:00
case 2 :
state - > fe [ 0 ] - > dtv_property_cache . modulation = QAM_64 ;
break ;
case 1 :
state - > fe [ 0 ] - > dtv_property_cache . modulation = QAM_16 ;
break ;
case 0 :
state - > fe [ 0 ] - > dtv_property_cache . modulation = QPSK ;
break ;
default :
case - 1 :
state - > fe [ 0 ] - > dtv_property_cache . modulation = QAM_AUTO ;
break ;
}
2011-05-03 19:27:33 +04:00
switch ( ch - > hrch ) {
2011-01-04 10:28:59 +03:00
case 0 :
state - > fe [ 0 ] - > dtv_property_cache . hierarchy = HIERARCHY_NONE ;
break ;
case 1 :
state - > fe [ 0 ] - > dtv_property_cache . hierarchy = HIERARCHY_1 ;
break ;
default :
case - 1 :
state - > fe [ 0 ] - > dtv_property_cache . hierarchy = HIERARCHY_AUTO ;
break ;
}
2011-05-03 19:27:33 +04:00
switch ( ch - > code_rate_hp ) {
2011-01-04 10:28:59 +03:00
case 1 :
state - > fe [ 0 ] - > dtv_property_cache . code_rate_HP = FEC_1_2 ;
break ;
case 2 :
state - > fe [ 0 ] - > dtv_property_cache . code_rate_HP = FEC_2_3 ;
break ;
case 3 :
state - > fe [ 0 ] - > dtv_property_cache . code_rate_HP = FEC_3_4 ;
break ;
case 5 :
state - > fe [ 0 ] - > dtv_property_cache . code_rate_HP = FEC_5_6 ;
break ;
case 7 :
state - > fe [ 0 ] - > dtv_property_cache . code_rate_HP = FEC_7_8 ;
break ;
default :
case - 1 :
state - > fe [ 0 ] - > dtv_property_cache . code_rate_HP = FEC_AUTO ;
break ;
}
2011-05-03 19:27:33 +04:00
switch ( ch - > code_rate_lp ) {
2011-01-04 10:28:59 +03:00
case 1 :
state - > fe [ 0 ] - > dtv_property_cache . code_rate_LP = FEC_1_2 ;
break ;
case 2 :
state - > fe [ 0 ] - > dtv_property_cache . code_rate_LP = FEC_2_3 ;
break ;
case 3 :
state - > fe [ 0 ] - > dtv_property_cache . code_rate_LP = FEC_3_4 ;
break ;
case 5 :
state - > fe [ 0 ] - > dtv_property_cache . code_rate_LP = FEC_5_6 ;
break ;
case 7 :
state - > fe [ 0 ] - > dtv_property_cache . code_rate_LP = FEC_7_8 ;
break ;
default :
case - 1 :
state - > fe [ 0 ] - > dtv_property_cache . code_rate_LP = FEC_AUTO ;
break ;
}
2011-01-04 19:08:14 +03:00
error :
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > platform . risc . mem_mbx_lock ) ;
2011-01-04 10:28:59 +03:00
return ret ;
}
2011-12-23 03:42:12 +04:00
static int dib9000_fw_set_channel_union ( struct dvb_frontend * fe )
2011-01-04 10:28:59 +03:00
{
struct dib9000_state * state = fe - > demodulator_priv ;
struct dibDVBTChannel {
s8 spectrum_inversion ;
s8 nfft ;
s8 guard ;
s8 constellation ;
s8 hrch ;
s8 alpha ;
s8 code_rate_hp ;
s8 code_rate_lp ;
s8 select_hp ;
s8 intlv_native ;
} ;
struct dibDVBTChannel ch ;
switch ( state - > fe [ 0 ] - > dtv_property_cache . inversion ) {
case INVERSION_ON :
ch . spectrum_inversion = 1 ;
break ;
case INVERSION_OFF :
ch . spectrum_inversion = 0 ;
break ;
default :
case INVERSION_AUTO :
ch . spectrum_inversion = - 1 ;
break ;
}
switch ( state - > fe [ 0 ] - > dtv_property_cache . transmission_mode ) {
case TRANSMISSION_MODE_2K :
ch . nfft = 0 ;
break ;
case TRANSMISSION_MODE_4K :
ch . nfft = 2 ;
break ;
case TRANSMISSION_MODE_8K :
ch . nfft = 1 ;
break ;
default :
case TRANSMISSION_MODE_AUTO :
ch . nfft = 1 ;
break ;
}
switch ( state - > fe [ 0 ] - > dtv_property_cache . guard_interval ) {
case GUARD_INTERVAL_1_32 :
ch . guard = 0 ;
break ;
case GUARD_INTERVAL_1_16 :
ch . guard = 1 ;
break ;
case GUARD_INTERVAL_1_8 :
ch . guard = 2 ;
break ;
case GUARD_INTERVAL_1_4 :
ch . guard = 3 ;
break ;
default :
case GUARD_INTERVAL_AUTO :
ch . guard = - 1 ;
break ;
}
switch ( state - > fe [ 0 ] - > dtv_property_cache . modulation ) {
case QAM_64 :
ch . constellation = 2 ;
break ;
case QAM_16 :
ch . constellation = 1 ;
break ;
case QPSK :
ch . constellation = 0 ;
break ;
default :
case QAM_AUTO :
ch . constellation = - 1 ;
break ;
}
switch ( state - > fe [ 0 ] - > dtv_property_cache . hierarchy ) {
case HIERARCHY_NONE :
ch . hrch = 0 ;
break ;
case HIERARCHY_1 :
case HIERARCHY_2 :
case HIERARCHY_4 :
ch . hrch = 1 ;
break ;
default :
case HIERARCHY_AUTO :
ch . hrch = - 1 ;
break ;
}
ch . alpha = 1 ;
switch ( state - > fe [ 0 ] - > dtv_property_cache . code_rate_HP ) {
case FEC_1_2 :
ch . code_rate_hp = 1 ;
break ;
case FEC_2_3 :
ch . code_rate_hp = 2 ;
break ;
case FEC_3_4 :
ch . code_rate_hp = 3 ;
break ;
case FEC_5_6 :
ch . code_rate_hp = 5 ;
break ;
case FEC_7_8 :
ch . code_rate_hp = 7 ;
break ;
default :
case FEC_AUTO :
ch . code_rate_hp = - 1 ;
break ;
}
switch ( state - > fe [ 0 ] - > dtv_property_cache . code_rate_LP ) {
case FEC_1_2 :
ch . code_rate_lp = 1 ;
break ;
case FEC_2_3 :
ch . code_rate_lp = 2 ;
break ;
case FEC_3_4 :
ch . code_rate_lp = 3 ;
break ;
case FEC_5_6 :
ch . code_rate_lp = 5 ;
break ;
case FEC_7_8 :
ch . code_rate_lp = 7 ;
break ;
default :
case FEC_AUTO :
ch . code_rate_lp = - 1 ;
break ;
}
ch . select_hp = 1 ;
ch . intlv_native = 1 ;
2011-01-04 19:08:14 +03:00
dib9000_risc_mem_write ( state , FE_MM_W_CHANNEL_UNION , ( u8 * ) & ch ) ;
2011-01-04 10:28:59 +03:00
return 0 ;
}
2011-12-23 03:42:12 +04:00
static int dib9000_fw_tune ( struct dvb_frontend * fe )
2011-01-04 10:28:59 +03:00
{
struct dib9000_state * state = fe - > demodulator_priv ;
int ret = 10 , search = state - > channel_status . status = = CHANNEL_STATUS_PARAMETERS_UNKNOWN ;
s8 i ;
switch ( state - > tune_state ) {
case CT_DEMOD_START :
2011-12-23 02:54:08 +04:00
dib9000_fw_set_channel_head ( state ) ;
2011-01-04 10:28:59 +03:00
/* write the channel context - a channel is initialized to 0, so it is OK */
dib9000_risc_mem_write ( state , FE_MM_W_CHANNEL_CONTEXT , ( u8 * ) fe_info ) ;
dib9000_risc_mem_write ( state , FE_MM_W_FE_INFO , ( u8 * ) fe_info ) ;
if ( search )
dib9000_mbx_send ( state , OUT_MSG_FE_CHANNEL_SEARCH , NULL , 0 ) ;
else {
2011-12-23 03:42:12 +04:00
dib9000_fw_set_channel_union ( fe ) ;
2011-01-04 10:28:59 +03:00
dib9000_mbx_send ( state , OUT_MSG_FE_CHANNEL_TUNE , NULL , 0 ) ;
}
state - > tune_state = CT_DEMOD_STEP_1 ;
break ;
case CT_DEMOD_STEP_1 :
if ( search )
2011-05-03 19:27:33 +04:00
dib9000_risc_mem_read ( state , FE_MM_R_CHANNEL_SEARCH_STATE , state - > i2c_read_buffer , 1 ) ;
2011-01-04 10:28:59 +03:00
else
2011-05-03 19:27:33 +04:00
dib9000_risc_mem_read ( state , FE_MM_R_CHANNEL_TUNE_STATE , state - > i2c_read_buffer , 1 ) ;
i = ( s8 ) state - > i2c_read_buffer [ 0 ] ;
2011-01-04 10:28:59 +03:00
switch ( i ) { /* something happened */
case 0 :
break ;
case - 2 : /* tps locks are "slower" than MPEG locks -> even in autosearch data is OK here */
if ( search )
state - > status = FE_STATUS_DEMOD_SUCCESS ;
else {
state - > tune_state = CT_DEMOD_STOP ;
state - > status = FE_STATUS_LOCKED ;
}
break ;
default :
state - > status = FE_STATUS_TUNE_FAILED ;
state - > tune_state = CT_DEMOD_STOP ;
break ;
}
break ;
default :
ret = FE_CALLBACK_TIME_NEVER ;
break ;
}
return ret ;
}
static int dib9000_fw_set_diversity_in ( struct dvb_frontend * fe , int onoff )
{
struct dib9000_state * state = fe - > demodulator_priv ;
u16 mode = ( u16 ) onoff ;
return dib9000_mbx_send ( state , OUT_MSG_ENABLE_DIVERSITY , & mode , 1 ) ;
}
static int dib9000_fw_set_output_mode ( struct dvb_frontend * fe , int mode )
{
struct dib9000_state * state = fe - > demodulator_priv ;
u16 outreg , smo_mode ;
2016-10-14 16:08:40 +03:00
dprintk ( " setting output mode for demod %p to %d \n " , fe , mode ) ;
2011-01-04 10:28:59 +03:00
switch ( mode ) {
2011-01-04 19:08:14 +03:00
case OUTMODE_MPEG2_PAR_GATED_CLK :
2011-01-04 10:28:59 +03:00
outreg = ( 1 < < 10 ) ; /* 0x0400 */
break ;
2011-01-04 19:08:14 +03:00
case OUTMODE_MPEG2_PAR_CONT_CLK :
2011-01-04 10:28:59 +03:00
outreg = ( 1 < < 10 ) | ( 1 < < 6 ) ; /* 0x0440 */
break ;
2011-01-04 19:08:14 +03:00
case OUTMODE_MPEG2_SERIAL :
2011-01-04 10:28:59 +03:00
outreg = ( 1 < < 10 ) | ( 2 < < 6 ) | ( 0 < < 1 ) ; /* 0x0482 */
break ;
case OUTMODE_DIVERSITY :
outreg = ( 1 < < 10 ) | ( 4 < < 6 ) ; /* 0x0500 */
break ;
2011-01-04 19:08:14 +03:00
case OUTMODE_MPEG2_FIFO :
2011-01-04 10:28:59 +03:00
outreg = ( 1 < < 10 ) | ( 5 < < 6 ) ;
break ;
2011-01-04 19:08:14 +03:00
case OUTMODE_HIGH_Z :
2011-01-04 10:28:59 +03:00
outreg = 0 ;
break ;
default :
2016-10-14 16:08:40 +03:00
dprintk ( " Unhandled output_mode passed to be set for demod %p \n " , & state - > fe [ 0 ] ) ;
2011-01-04 10:28:59 +03:00
return - EINVAL ;
}
2011-01-04 19:08:14 +03:00
dib9000_write_word ( state , 1795 , outreg ) ;
2011-01-04 10:28:59 +03:00
switch ( mode ) {
case OUTMODE_MPEG2_PAR_GATED_CLK :
case OUTMODE_MPEG2_PAR_CONT_CLK :
case OUTMODE_MPEG2_SERIAL :
case OUTMODE_MPEG2_FIFO :
smo_mode = ( dib9000_read_word ( state , 295 ) & 0x0010 ) | ( 1 < < 1 ) ;
if ( state - > chip . d9 . cfg . output_mpeg2_in_188_bytes )
smo_mode | = ( 1 < < 5 ) ;
dib9000_write_word ( state , 295 , smo_mode ) ;
break ;
}
outreg = to_fw_output_mode ( mode ) ;
return dib9000_mbx_send ( state , OUT_MSG_SET_OUTPUT_MODE , & outreg , 1 ) ;
}
static int dib9000_tuner_xfer ( struct i2c_adapter * i2c_adap , struct i2c_msg msg [ ] , int num )
{
struct dib9000_state * state = i2c_get_adapdata ( i2c_adap ) ;
u16 i , len , t , index_msg ;
for ( index_msg = 0 ; index_msg < num ; index_msg + + ) {
if ( msg [ index_msg ] . flags & I2C_M_RD ) { /* read */
len = msg [ index_msg ] . len ;
if ( len > 16 )
len = 16 ;
if ( dib9000_read_word ( state , 790 ) ! = 0 )
2016-10-14 16:08:40 +03:00
dprintk ( " TunerITF: read busy \n " ) ;
2011-01-04 10:28:59 +03:00
dib9000_write_word ( state , 784 , ( u16 ) ( msg [ index_msg ] . addr ) ) ;
dib9000_write_word ( state , 787 , ( len / 2 ) - 1 ) ;
dib9000_write_word ( state , 786 , 1 ) ; /* start read */
i = 1000 ;
while ( dib9000_read_word ( state , 790 ) ! = ( len / 2 ) & & i )
i - - ;
if ( i = = 0 )
2016-10-14 16:08:40 +03:00
dprintk ( " TunerITF: read failed \n " ) ;
2011-01-04 10:28:59 +03:00
for ( i = 0 ; i < len ; i + = 2 ) {
t = dib9000_read_word ( state , 785 ) ;
msg [ index_msg ] . buf [ i ] = ( t > > 8 ) & 0xff ;
msg [ index_msg ] . buf [ i + 1 ] = ( t ) & 0xff ;
}
if ( dib9000_read_word ( state , 790 ) ! = 0 )
2016-10-14 16:08:40 +03:00
dprintk ( " TunerITF: read more data than expected \n " ) ;
2011-01-04 10:28:59 +03:00
} else {
i = 1000 ;
while ( dib9000_read_word ( state , 789 ) & & i )
i - - ;
if ( i = = 0 )
2016-10-14 16:08:40 +03:00
dprintk ( " TunerITF: write busy \n " ) ;
2011-01-04 10:28:59 +03:00
len = msg [ index_msg ] . len ;
if ( len > 16 )
len = 16 ;
for ( i = 0 ; i < len ; i + = 2 )
dib9000_write_word ( state , 785 , ( msg [ index_msg ] . buf [ i ] < < 8 ) | msg [ index_msg ] . buf [ i + 1 ] ) ;
dib9000_write_word ( state , 784 , ( u16 ) msg [ index_msg ] . addr ) ;
dib9000_write_word ( state , 787 , ( len / 2 ) - 1 ) ;
dib9000_write_word ( state , 786 , 0 ) ; /* start write */
i = 1000 ;
while ( dib9000_read_word ( state , 791 ) > 0 & & i )
i - - ;
if ( i = = 0 )
2016-10-14 16:08:40 +03:00
dprintk ( " TunerITF: write failed \n " ) ;
2011-01-04 10:28:59 +03:00
}
}
return num ;
}
int dib9000_fw_set_component_bus_speed ( struct dvb_frontend * fe , u16 speed )
{
struct dib9000_state * state = fe - > demodulator_priv ;
state - > component_bus_speed = speed ;
return 0 ;
}
EXPORT_SYMBOL ( dib9000_fw_set_component_bus_speed ) ;
static int dib9000_fw_component_bus_xfer ( struct i2c_adapter * i2c_adap , struct i2c_msg msg [ ] , int num )
{
struct dib9000_state * state = i2c_get_adapdata ( i2c_adap ) ;
2011-01-04 19:08:14 +03:00
u8 type = 0 ; /* I2C */
2011-01-04 10:28:59 +03:00
u8 port = DIBX000_I2C_INTERFACE_GPIO_3_4 ;
2011-01-04 19:08:14 +03:00
u16 scl = state - > component_bus_speed ; /* SCL frequency */
2011-01-04 10:28:59 +03:00
struct dib9000_fe_memory_map * m = & state - > platform . risc . fe_mm [ FE_MM_RW_COMPONENT_ACCESS_BUFFER ] ;
u8 p [ 13 ] = { 0 } ;
p [ 0 ] = type ;
p [ 1 ] = port ;
p [ 2 ] = msg [ 0 ] . addr < < 1 ;
p [ 3 ] = ( u8 ) scl & 0xff ; /* scl */
p [ 4 ] = ( u8 ) ( scl > > 8 ) ;
p [ 7 ] = 0 ;
p [ 8 ] = 0 ;
p [ 9 ] = ( u8 ) ( msg [ 0 ] . len ) ;
p [ 10 ] = ( u8 ) ( msg [ 0 ] . len > > 8 ) ;
if ( ( num > 1 ) & & ( msg [ 1 ] . flags & I2C_M_RD ) ) {
p [ 11 ] = ( u8 ) ( msg [ 1 ] . len ) ;
p [ 12 ] = ( u8 ) ( msg [ 1 ] . len > > 8 ) ;
} else {
p [ 11 ] = 0 ;
p [ 12 ] = 0 ;
}
2012-03-19 23:48:34 +04:00
if ( mutex_lock_interruptible ( & state - > platform . risc . mem_mbx_lock ) < 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " could not get the lock \n " ) ;
2012-03-07 00:08:29 +04:00
return 0 ;
}
2011-01-04 10:28:59 +03:00
dib9000_risc_mem_write ( state , FE_MM_W_COMPONENT_ACCESS , p ) ;
{ /* write-part */
dib9000_risc_mem_setup_cmd ( state , m - > addr , msg [ 0 ] . len , 0 ) ;
dib9000_risc_mem_write_chunks ( state , msg [ 0 ] . buf , msg [ 0 ] . len ) ;
}
/* do the transaction */
if ( dib9000_fw_memmbx_sync ( state , FE_SYNC_COMPONENT_ACCESS ) < 0 ) {
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > platform . risc . mem_mbx_lock ) ;
2011-01-04 10:28:59 +03:00
return 0 ;
}
/* read back any possible result */
if ( ( num > 1 ) & & ( msg [ 1 ] . flags & I2C_M_RD ) )
dib9000_risc_mem_read ( state , FE_MM_RW_COMPONENT_ACCESS_BUFFER , msg [ 1 ] . buf , msg [ 1 ] . len ) ;
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > platform . risc . mem_mbx_lock ) ;
2011-01-04 10:28:59 +03:00
return num ;
}
static u32 dib9000_i2c_func ( struct i2c_adapter * adapter )
{
return I2C_FUNC_I2C ;
}
2017-07-10 01:24:19 +03:00
static const struct i2c_algorithm dib9000_tuner_algo = {
2011-01-04 10:28:59 +03:00
. master_xfer = dib9000_tuner_xfer ,
. functionality = dib9000_i2c_func ,
} ;
2017-07-10 01:24:19 +03:00
static const struct i2c_algorithm dib9000_component_bus_algo = {
2011-01-04 10:28:59 +03:00
. master_xfer = dib9000_fw_component_bus_xfer ,
. functionality = dib9000_i2c_func ,
} ;
struct i2c_adapter * dib9000_get_tuner_interface ( struct dvb_frontend * fe )
{
struct dib9000_state * st = fe - > demodulator_priv ;
return & st - > tuner_adap ;
}
EXPORT_SYMBOL ( dib9000_get_tuner_interface ) ;
struct i2c_adapter * dib9000_get_component_bus_interface ( struct dvb_frontend * fe )
{
struct dib9000_state * st = fe - > demodulator_priv ;
return & st - > component_bus ;
}
EXPORT_SYMBOL ( dib9000_get_component_bus_interface ) ;
struct i2c_adapter * dib9000_get_i2c_master ( struct dvb_frontend * fe , enum dibx000_i2c_interface intf , int gating )
{
struct dib9000_state * st = fe - > demodulator_priv ;
return dibx000_get_i2c_adapter ( & st - > i2c_master , intf , gating ) ;
}
EXPORT_SYMBOL ( dib9000_get_i2c_master ) ;
int dib9000_set_i2c_adapter ( struct dvb_frontend * fe , struct i2c_adapter * i2c )
{
struct dib9000_state * st = fe - > demodulator_priv ;
st - > i2c . i2c_adap = i2c ;
return 0 ;
}
EXPORT_SYMBOL ( dib9000_set_i2c_adapter ) ;
static int dib9000_cfg_gpio ( struct dib9000_state * st , u8 num , u8 dir , u8 val )
{
st - > gpio_dir = dib9000_read_word ( st , 773 ) ;
st - > gpio_dir & = ~ ( 1 < < num ) ; /* reset the direction bit */
st - > gpio_dir | = ( dir & 0x1 ) < < num ; /* set the new direction */
dib9000_write_word ( st , 773 , st - > gpio_dir ) ;
st - > gpio_val = dib9000_read_word ( st , 774 ) ;
st - > gpio_val & = ~ ( 1 < < num ) ; /* reset the direction bit */
st - > gpio_val | = ( val & 0x01 ) < < num ; /* set the new value */
dib9000_write_word ( st , 774 , st - > gpio_val ) ;
2016-10-14 16:08:40 +03:00
dprintk ( " gpio dir: %04x: gpio val: %04x \n " , st - > gpio_dir , st - > gpio_val ) ;
2011-01-04 10:28:59 +03:00
return 0 ;
}
int dib9000_set_gpio ( struct dvb_frontend * fe , u8 num , u8 dir , u8 val )
{
struct dib9000_state * state = fe - > demodulator_priv ;
return dib9000_cfg_gpio ( state , num , dir , val ) ;
}
EXPORT_SYMBOL ( dib9000_set_gpio ) ;
2011-01-04 19:08:14 +03:00
2011-01-04 10:28:59 +03:00
int dib9000_fw_pid_filter_ctrl ( struct dvb_frontend * fe , u8 onoff )
{
struct dib9000_state * state = fe - > demodulator_priv ;
2011-08-03 19:08:21 +04:00
u16 val ;
int ret ;
if ( ( state - > pid_ctrl_index ! = - 2 ) & & ( state - > pid_ctrl_index < 9 ) ) {
/* postpone the pid filtering cmd */
2016-10-14 16:08:40 +03:00
dprintk ( " pid filter cmd postpone \n " ) ;
2011-08-03 19:08:21 +04:00
state - > pid_ctrl_index + + ;
state - > pid_ctrl [ state - > pid_ctrl_index ] . cmd = DIB9000_PID_FILTER_CTRL ;
state - > pid_ctrl [ state - > pid_ctrl_index ] . onoff = onoff ;
return 0 ;
}
2012-03-19 23:48:34 +04:00
if ( mutex_lock_interruptible ( & state - > demod_lock ) < 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " could not get the lock \n " ) ;
2012-03-07 00:08:29 +04:00
return - EINTR ;
}
2011-08-03 19:08:21 +04:00
val = dib9000_read_word ( state , 294 + 1 ) & 0xffef ;
2011-01-04 10:28:59 +03:00
val | = ( onoff & 0x1 ) < < 4 ;
2016-10-14 16:08:40 +03:00
dprintk ( " PID filter enabled %d \n " , onoff ) ;
2011-08-03 19:08:21 +04:00
ret = dib9000_write_word ( state , 294 + 1 , val ) ;
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > demod_lock ) ;
2011-08-03 19:08:21 +04:00
return ret ;
2011-01-04 10:28:59 +03:00
}
EXPORT_SYMBOL ( dib9000_fw_pid_filter_ctrl ) ;
2011-01-04 19:08:14 +03:00
2011-01-04 10:28:59 +03:00
int dib9000_fw_pid_filter ( struct dvb_frontend * fe , u8 id , u16 pid , u8 onoff )
{
struct dib9000_state * state = fe - > demodulator_priv ;
2011-08-03 19:08:21 +04:00
int ret ;
if ( state - > pid_ctrl_index ! = - 2 ) {
/* postpone the pid filtering cmd */
2016-10-14 16:08:40 +03:00
dprintk ( " pid filter postpone \n " ) ;
2011-08-03 19:08:21 +04:00
if ( state - > pid_ctrl_index < 9 ) {
state - > pid_ctrl_index + + ;
state - > pid_ctrl [ state - > pid_ctrl_index ] . cmd = DIB9000_PID_FILTER ;
state - > pid_ctrl [ state - > pid_ctrl_index ] . id = id ;
state - > pid_ctrl [ state - > pid_ctrl_index ] . pid = pid ;
state - > pid_ctrl [ state - > pid_ctrl_index ] . onoff = onoff ;
} else
2016-10-14 16:08:40 +03:00
dprintk ( " can not add any more pid ctrl cmd \n " ) ;
2011-08-03 19:08:21 +04:00
return 0 ;
}
2012-03-19 23:48:34 +04:00
if ( mutex_lock_interruptible ( & state - > demod_lock ) < 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " could not get the lock \n " ) ;
2012-03-07 00:08:29 +04:00
return - EINTR ;
}
2016-10-14 16:08:40 +03:00
dprintk ( " Index %x, PID %d, OnOff %d \n " , id , pid , onoff ) ;
2011-08-03 19:08:21 +04:00
ret = dib9000_write_word ( state , 300 + 1 + id ,
onoff ? ( 1 < < 13 ) | pid : 0 ) ;
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > demod_lock ) ;
2011-08-03 19:08:21 +04:00
return ret ;
2011-01-04 10:28:59 +03:00
}
EXPORT_SYMBOL ( dib9000_fw_pid_filter ) ;
int dib9000_firmware_post_pll_init ( struct dvb_frontend * fe )
{
struct dib9000_state * state = fe - > demodulator_priv ;
return dib9000_fw_init ( state ) ;
}
EXPORT_SYMBOL ( dib9000_firmware_post_pll_init ) ;
static void dib9000_release ( struct dvb_frontend * demod )
{
struct dib9000_state * st = demod - > demodulator_priv ;
u8 index_frontend ;
2011-01-04 19:08:14 +03:00
for ( index_frontend = 1 ; ( index_frontend < MAX_NUMBER_OF_FRONTENDS ) & & ( st - > fe [ index_frontend ] ! = NULL ) ; index_frontend + + )
2011-01-04 10:28:59 +03:00
dvb_frontend_detach ( st - > fe [ index_frontend ] ) ;
dibx000_exit_i2c_master ( & st - > i2c_master ) ;
i2c_del_adapter ( & st - > tuner_adap ) ;
i2c_del_adapter ( & st - > component_bus ) ;
kfree ( st - > fe [ 0 ] ) ;
kfree ( st ) ;
}
static int dib9000_wakeup ( struct dvb_frontend * fe )
{
return 0 ;
}
static int dib9000_sleep ( struct dvb_frontend * fe )
{
struct dib9000_state * state = fe - > demodulator_priv ;
u8 index_frontend ;
2011-08-03 19:08:21 +04:00
int ret = 0 ;
2011-01-04 10:28:59 +03:00
2012-03-19 23:48:34 +04:00
if ( mutex_lock_interruptible ( & state - > demod_lock ) < 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " could not get the lock \n " ) ;
2012-03-07 00:08:29 +04:00
return - EINTR ;
}
2011-01-04 19:08:14 +03:00
for ( index_frontend = 1 ; ( index_frontend < MAX_NUMBER_OF_FRONTENDS ) & & ( state - > fe [ index_frontend ] ! = NULL ) ; index_frontend + + ) {
2011-01-04 10:28:59 +03:00
ret = state - > fe [ index_frontend ] - > ops . sleep ( state - > fe [ index_frontend ] ) ;
if ( ret < 0 )
2011-08-03 19:08:21 +04:00
goto error ;
2011-01-04 10:28:59 +03:00
}
2011-08-03 19:08:21 +04:00
ret = dib9000_mbx_send ( state , OUT_MSG_FE_SLEEP , NULL , 0 ) ;
error :
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > demod_lock ) ;
2011-08-03 19:08:21 +04:00
return ret ;
2011-01-04 10:28:59 +03:00
}
static int dib9000_fe_get_tune_settings ( struct dvb_frontend * fe , struct dvb_frontend_tune_settings * tune )
{
tune - > min_delay_ms = 1000 ;
return 0 ;
}
2016-02-04 17:58:30 +03:00
static int dib9000_get_frontend ( struct dvb_frontend * fe ,
struct dtv_frontend_properties * c )
2011-01-04 10:28:59 +03:00
{
struct dib9000_state * state = fe - > demodulator_priv ;
u8 index_frontend , sub_index_frontend ;
2015-06-07 20:53:52 +03:00
enum fe_status stat ;
2011-08-03 19:08:21 +04:00
int ret = 0 ;
2012-03-07 00:08:29 +04:00
if ( state - > get_frontend_internal = = 0 ) {
2012-03-19 23:48:34 +04:00
if ( mutex_lock_interruptible ( & state - > demod_lock ) < 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " could not get the lock \n " ) ;
2012-03-07 00:08:29 +04:00
return - EINTR ;
}
}
2011-01-04 10:28:59 +03:00
2011-01-04 19:08:14 +03:00
for ( index_frontend = 1 ; ( index_frontend < MAX_NUMBER_OF_FRONTENDS ) & & ( state - > fe [ index_frontend ] ! = NULL ) ; index_frontend + + ) {
2011-01-04 10:28:59 +03:00
state - > fe [ index_frontend ] - > ops . read_status ( state - > fe [ index_frontend ] , & stat ) ;
if ( stat & FE_HAS_SYNC ) {
2016-10-14 16:08:40 +03:00
dprintk ( " TPS lock on the slave%i \n " , index_frontend ) ;
2011-01-04 10:28:59 +03:00
/* synchronize the cache with the other frontends */
2016-02-04 17:58:30 +03:00
state - > fe [ index_frontend ] - > ops . get_frontend ( state - > fe [ index_frontend ] , c ) ;
2011-01-04 19:08:14 +03:00
for ( sub_index_frontend = 0 ; ( sub_index_frontend < MAX_NUMBER_OF_FRONTENDS ) & & ( state - > fe [ sub_index_frontend ] ! = NULL ) ;
sub_index_frontend + + ) {
2011-01-04 10:28:59 +03:00
if ( sub_index_frontend ! = index_frontend ) {
2011-01-04 19:08:14 +03:00
state - > fe [ sub_index_frontend ] - > dtv_property_cache . modulation =
state - > fe [ index_frontend ] - > dtv_property_cache . modulation ;
state - > fe [ sub_index_frontend ] - > dtv_property_cache . inversion =
state - > fe [ index_frontend ] - > dtv_property_cache . inversion ;
state - > fe [ sub_index_frontend ] - > dtv_property_cache . transmission_mode =
state - > fe [ index_frontend ] - > dtv_property_cache . transmission_mode ;
state - > fe [ sub_index_frontend ] - > dtv_property_cache . guard_interval =
state - > fe [ index_frontend ] - > dtv_property_cache . guard_interval ;
state - > fe [ sub_index_frontend ] - > dtv_property_cache . hierarchy =
state - > fe [ index_frontend ] - > dtv_property_cache . hierarchy ;
state - > fe [ sub_index_frontend ] - > dtv_property_cache . code_rate_HP =
state - > fe [ index_frontend ] - > dtv_property_cache . code_rate_HP ;
state - > fe [ sub_index_frontend ] - > dtv_property_cache . code_rate_LP =
state - > fe [ index_frontend ] - > dtv_property_cache . code_rate_LP ;
state - > fe [ sub_index_frontend ] - > dtv_property_cache . rolloff =
state - > fe [ index_frontend ] - > dtv_property_cache . rolloff ;
2011-01-04 10:28:59 +03:00
}
}
2011-08-03 19:08:21 +04:00
ret = 0 ;
goto return_value ;
2011-01-04 10:28:59 +03:00
}
}
/* get the channel from master chip */
2011-12-23 02:54:08 +04:00
ret = dib9000_fw_get_channel ( fe ) ;
2011-01-04 10:28:59 +03:00
if ( ret ! = 0 )
2011-08-03 19:08:21 +04:00
goto return_value ;
2011-01-04 10:28:59 +03:00
/* synchronize the cache with the other frontends */
2011-01-04 19:08:14 +03:00
for ( index_frontend = 1 ; ( index_frontend < MAX_NUMBER_OF_FRONTENDS ) & & ( state - > fe [ index_frontend ] ! = NULL ) ; index_frontend + + ) {
2016-02-04 17:58:30 +03:00
state - > fe [ index_frontend ] - > dtv_property_cache . inversion = c - > inversion ;
state - > fe [ index_frontend ] - > dtv_property_cache . transmission_mode = c - > transmission_mode ;
state - > fe [ index_frontend ] - > dtv_property_cache . guard_interval = c - > guard_interval ;
state - > fe [ index_frontend ] - > dtv_property_cache . modulation = c - > modulation ;
state - > fe [ index_frontend ] - > dtv_property_cache . hierarchy = c - > hierarchy ;
state - > fe [ index_frontend ] - > dtv_property_cache . code_rate_HP = c - > code_rate_HP ;
state - > fe [ index_frontend ] - > dtv_property_cache . code_rate_LP = c - > code_rate_LP ;
state - > fe [ index_frontend ] - > dtv_property_cache . rolloff = c - > rolloff ;
2011-01-04 10:28:59 +03:00
}
2011-08-03 19:08:21 +04:00
ret = 0 ;
2011-01-04 10:28:59 +03:00
2011-08-03 19:08:21 +04:00
return_value :
if ( state - > get_frontend_internal = = 0 )
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > demod_lock ) ;
2011-08-03 19:08:21 +04:00
return ret ;
2011-01-04 10:28:59 +03:00
}
static int dib9000_set_tune_state ( struct dvb_frontend * fe , enum frontend_tune_state tune_state )
{
struct dib9000_state * state = fe - > demodulator_priv ;
state - > tune_state = tune_state ;
if ( tune_state = = CT_DEMOD_START )
state - > status = FE_STATUS_TUNE_PENDING ;
return 0 ;
}
static u32 dib9000_get_status ( struct dvb_frontend * fe )
{
struct dib9000_state * state = fe - > demodulator_priv ;
return state - > status ;
}
static int dib9000_set_channel_status ( struct dvb_frontend * fe , struct dvb_frontend_parametersContext * channel_status )
{
struct dib9000_state * state = fe - > demodulator_priv ;
memcpy ( & state - > channel_status , channel_status , sizeof ( struct dvb_frontend_parametersContext ) ) ;
return 0 ;
}
2011-12-23 03:12:18 +04:00
static int dib9000_set_frontend ( struct dvb_frontend * fe )
2011-01-04 10:28:59 +03:00
{
struct dib9000_state * state = fe - > demodulator_priv ;
int sleep_time , sleep_time_slave ;
u32 frontend_status ;
u8 nbr_pending , exit_condition , index_frontend , index_frontend_success ;
struct dvb_frontend_parametersContext channel_status ;
/* check that the correct parameters are set */
if ( state - > fe [ 0 ] - > dtv_property_cache . frequency = = 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " dib9000: must specify frequency \n " ) ;
2011-01-04 10:28:59 +03:00
return 0 ;
}
if ( state - > fe [ 0 ] - > dtv_property_cache . bandwidth_hz = = 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " dib9000: must specify bandwidth \n " ) ;
2011-01-04 10:28:59 +03:00
return 0 ;
}
2011-08-03 19:08:21 +04:00
state - > pid_ctrl_index = - 1 ; /* postpone the pid filtering cmd */
2012-03-19 23:48:34 +04:00
if ( mutex_lock_interruptible ( & state - > demod_lock ) < 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " could not get the lock \n " ) ;
2012-03-07 00:08:29 +04:00
return 0 ;
}
2011-08-03 19:08:21 +04:00
2011-01-04 10:28:59 +03:00
fe - > dtv_property_cache . delivery_system = SYS_DVBT ;
/* set the master status */
2011-12-23 03:12:18 +04:00
if ( state - > fe [ 0 ] - > dtv_property_cache . transmission_mode = = TRANSMISSION_MODE_AUTO | |
state - > fe [ 0 ] - > dtv_property_cache . guard_interval = = GUARD_INTERVAL_AUTO | |
state - > fe [ 0 ] - > dtv_property_cache . modulation = = QAM_AUTO | |
state - > fe [ 0 ] - > dtv_property_cache . code_rate_HP = = FEC_AUTO ) {
2011-01-04 10:28:59 +03:00
/* no channel specified, autosearch the channel */
state - > channel_status . status = CHANNEL_STATUS_PARAMETERS_UNKNOWN ;
} else
state - > channel_status . status = CHANNEL_STATUS_PARAMETERS_SET ;
/* set mode and status for the different frontends */
2011-01-04 19:08:14 +03:00
for ( index_frontend = 0 ; ( index_frontend < MAX_NUMBER_OF_FRONTENDS ) & & ( state - > fe [ index_frontend ] ! = NULL ) ; index_frontend + + ) {
2011-01-04 10:28:59 +03:00
dib9000_fw_set_diversity_in ( state - > fe [ index_frontend ] , 1 ) ;
/* synchronization of the cache */
memcpy ( & state - > fe [ index_frontend ] - > dtv_property_cache , & fe - > dtv_property_cache , sizeof ( struct dtv_frontend_properties ) ) ;
state - > fe [ index_frontend ] - > dtv_property_cache . delivery_system = SYS_DVBT ;
dib9000_fw_set_output_mode ( state - > fe [ index_frontend ] , OUTMODE_HIGH_Z ) ;
dib9000_set_channel_status ( state - > fe [ index_frontend ] , & state - > channel_status ) ;
dib9000_set_tune_state ( state - > fe [ index_frontend ] , CT_DEMOD_START ) ;
}
/* actual tune */
2011-01-04 19:08:14 +03:00
exit_condition = 0 ; /* 0: tune pending; 1: tune failed; 2:tune success */
2011-01-04 10:28:59 +03:00
index_frontend_success = 0 ;
do {
2011-12-23 03:42:12 +04:00
sleep_time = dib9000_fw_tune ( state - > fe [ 0 ] ) ;
2011-01-04 19:08:14 +03:00
for ( index_frontend = 1 ; ( index_frontend < MAX_NUMBER_OF_FRONTENDS ) & & ( state - > fe [ index_frontend ] ! = NULL ) ; index_frontend + + ) {
2011-12-23 03:42:12 +04:00
sleep_time_slave = dib9000_fw_tune ( state - > fe [ index_frontend ] ) ;
2011-01-04 10:28:59 +03:00
if ( sleep_time = = FE_CALLBACK_TIME_NEVER )
sleep_time = sleep_time_slave ;
else if ( ( sleep_time_slave ! = FE_CALLBACK_TIME_NEVER ) & & ( sleep_time_slave > sleep_time ) )
sleep_time = sleep_time_slave ;
}
if ( sleep_time ! = FE_CALLBACK_TIME_NEVER )
msleep ( sleep_time / 10 ) ;
else
break ;
nbr_pending = 0 ;
exit_condition = 0 ;
index_frontend_success = 0 ;
2011-01-04 19:08:14 +03:00
for ( index_frontend = 0 ; ( index_frontend < MAX_NUMBER_OF_FRONTENDS ) & & ( state - > fe [ index_frontend ] ! = NULL ) ; index_frontend + + ) {
2011-01-04 10:28:59 +03:00
frontend_status = - dib9000_get_status ( state - > fe [ index_frontend ] ) ;
if ( frontend_status > - FE_STATUS_TUNE_PENDING ) {
2011-01-04 19:08:14 +03:00
exit_condition = 2 ; /* tune success */
2011-01-04 10:28:59 +03:00
index_frontend_success = index_frontend ;
break ;
}
if ( frontend_status = = - FE_STATUS_TUNE_PENDING )
2011-01-04 19:08:14 +03:00
nbr_pending + + ; /* some frontends are still tuning */
2011-01-04 10:28:59 +03:00
}
if ( ( exit_condition ! = 2 ) & & ( nbr_pending = = 0 ) )
2011-01-04 19:08:14 +03:00
exit_condition = 1 ; /* if all tune are done and no success, exit: tune failed */
2011-01-04 10:28:59 +03:00
} while ( exit_condition = = 0 ) ;
/* check the tune result */
2011-01-04 19:08:14 +03:00
if ( exit_condition = = 1 ) { /* tune failed */
2016-10-14 16:08:40 +03:00
dprintk ( " tune failed \n " ) ;
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > demod_lock ) ;
2011-08-03 19:08:21 +04:00
/* tune failed; put all the pid filtering cmd to junk */
state - > pid_ctrl_index = - 1 ;
2011-01-04 10:28:59 +03:00
return 0 ;
}
2016-10-14 16:08:40 +03:00
dprintk ( " tune success on frontend%i \n " , index_frontend_success ) ;
2011-01-04 10:28:59 +03:00
/* synchronize all the channel cache */
2011-08-03 19:08:21 +04:00
state - > get_frontend_internal = 1 ;
2016-02-04 17:58:30 +03:00
dib9000_get_frontend ( state - > fe [ 0 ] , & state - > fe [ 0 ] - > dtv_property_cache ) ;
2011-08-03 19:08:21 +04:00
state - > get_frontend_internal = 0 ;
2011-01-04 10:28:59 +03:00
/* retune the other frontends with the found channel */
channel_status . status = CHANNEL_STATUS_PARAMETERS_SET ;
2011-01-04 19:08:14 +03:00
for ( index_frontend = 0 ; ( index_frontend < MAX_NUMBER_OF_FRONTENDS ) & & ( state - > fe [ index_frontend ] ! = NULL ) ; index_frontend + + ) {
2011-01-04 10:28:59 +03:00
/* only retune the frontends which was not tuned success */
if ( index_frontend ! = index_frontend_success ) {
dib9000_set_channel_status ( state - > fe [ index_frontend ] , & channel_status ) ;
dib9000_set_tune_state ( state - > fe [ index_frontend ] , CT_DEMOD_START ) ;
}
}
do {
sleep_time = FE_CALLBACK_TIME_NEVER ;
2011-01-04 19:08:14 +03:00
for ( index_frontend = 0 ; ( index_frontend < MAX_NUMBER_OF_FRONTENDS ) & & ( state - > fe [ index_frontend ] ! = NULL ) ; index_frontend + + ) {
2011-01-04 10:28:59 +03:00
if ( index_frontend ! = index_frontend_success ) {
2011-12-23 03:42:12 +04:00
sleep_time_slave = dib9000_fw_tune ( state - > fe [ index_frontend ] ) ;
2011-01-04 10:28:59 +03:00
if ( sleep_time = = FE_CALLBACK_TIME_NEVER )
sleep_time = sleep_time_slave ;
else if ( ( sleep_time_slave ! = FE_CALLBACK_TIME_NEVER ) & & ( sleep_time_slave > sleep_time ) )
sleep_time = sleep_time_slave ;
}
}
if ( sleep_time ! = FE_CALLBACK_TIME_NEVER )
msleep ( sleep_time / 10 ) ;
else
break ;
nbr_pending = 0 ;
2011-01-04 19:08:14 +03:00
for ( index_frontend = 0 ; ( index_frontend < MAX_NUMBER_OF_FRONTENDS ) & & ( state - > fe [ index_frontend ] ! = NULL ) ; index_frontend + + ) {
2011-01-04 10:28:59 +03:00
if ( index_frontend ! = index_frontend_success ) {
frontend_status = - dib9000_get_status ( state - > fe [ index_frontend ] ) ;
if ( ( index_frontend ! = index_frontend_success ) & & ( frontend_status = = - FE_STATUS_TUNE_PENDING ) )
2011-01-04 19:08:14 +03:00
nbr_pending + + ; /* some frontends are still tuning */
2011-01-04 10:28:59 +03:00
}
}
} while ( nbr_pending ! = 0 ) ;
/* set the output mode */
dib9000_fw_set_output_mode ( state - > fe [ 0 ] , state - > chip . d9 . cfg . output_mode ) ;
2011-01-04 19:08:14 +03:00
for ( index_frontend = 1 ; ( index_frontend < MAX_NUMBER_OF_FRONTENDS ) & & ( state - > fe [ index_frontend ] ! = NULL ) ; index_frontend + + )
2011-01-04 10:28:59 +03:00
dib9000_fw_set_output_mode ( state - > fe [ index_frontend ] , OUTMODE_DIVERSITY ) ;
/* turn off the diversity for the last frontend */
2011-01-04 19:08:14 +03:00
dib9000_fw_set_diversity_in ( state - > fe [ index_frontend - 1 ] , 0 ) ;
2011-01-04 10:28:59 +03:00
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > demod_lock ) ;
2011-08-03 19:08:21 +04:00
if ( state - > pid_ctrl_index > = 0 ) {
u8 index_pid_filter_cmd ;
u8 pid_ctrl_index = state - > pid_ctrl_index ;
state - > pid_ctrl_index = - 2 ;
for ( index_pid_filter_cmd = 0 ;
index_pid_filter_cmd < = pid_ctrl_index ;
index_pid_filter_cmd + + ) {
if ( state - > pid_ctrl [ index_pid_filter_cmd ] . cmd = = DIB9000_PID_FILTER_CTRL )
dib9000_fw_pid_filter_ctrl ( state - > fe [ 0 ] ,
state - > pid_ctrl [ index_pid_filter_cmd ] . onoff ) ;
else if ( state - > pid_ctrl [ index_pid_filter_cmd ] . cmd = = DIB9000_PID_FILTER )
dib9000_fw_pid_filter ( state - > fe [ 0 ] ,
state - > pid_ctrl [ index_pid_filter_cmd ] . id ,
state - > pid_ctrl [ index_pid_filter_cmd ] . pid ,
state - > pid_ctrl [ index_pid_filter_cmd ] . onoff ) ;
}
}
/* do not postpone any more the pid filtering */
state - > pid_ctrl_index = - 2 ;
2011-01-04 10:28:59 +03:00
return 0 ;
}
static u16 dib9000_read_lock ( struct dvb_frontend * fe )
{
struct dib9000_state * state = fe - > demodulator_priv ;
return dib9000_read_word ( state , 535 ) ;
}
2015-06-07 20:53:52 +03:00
static int dib9000_read_status ( struct dvb_frontend * fe , enum fe_status * stat )
2011-01-04 10:28:59 +03:00
{
struct dib9000_state * state = fe - > demodulator_priv ;
u8 index_frontend ;
u16 lock = 0 , lock_slave = 0 ;
2012-03-19 23:48:34 +04:00
if ( mutex_lock_interruptible ( & state - > demod_lock ) < 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " could not get the lock \n " ) ;
2012-03-07 00:08:29 +04:00
return - EINTR ;
}
2011-01-04 19:08:14 +03:00
for ( index_frontend = 1 ; ( index_frontend < MAX_NUMBER_OF_FRONTENDS ) & & ( state - > fe [ index_frontend ] ! = NULL ) ; index_frontend + + )
2011-01-04 10:28:59 +03:00
lock_slave | = dib9000_read_lock ( state - > fe [ index_frontend ] ) ;
lock = dib9000_read_word ( state , 535 ) ;
* stat = 0 ;
if ( ( lock & 0x8000 ) | | ( lock_slave & 0x8000 ) )
* stat | = FE_HAS_SIGNAL ;
if ( ( lock & 0x3000 ) | | ( lock_slave & 0x3000 ) )
* stat | = FE_HAS_CARRIER ;
if ( ( lock & 0x0100 ) | | ( lock_slave & 0x0100 ) )
* stat | = FE_HAS_VITERBI ;
if ( ( ( lock & 0x0038 ) = = 0x38 ) | | ( ( lock_slave & 0x0038 ) = = 0x38 ) )
* stat | = FE_HAS_SYNC ;
if ( ( lock & 0x0008 ) | | ( lock_slave & 0x0008 ) )
* stat | = FE_HAS_LOCK ;
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > demod_lock ) ;
2011-08-03 19:08:21 +04:00
2011-01-04 10:28:59 +03:00
return 0 ;
}
static int dib9000_read_ber ( struct dvb_frontend * fe , u32 * ber )
{
struct dib9000_state * state = fe - > demodulator_priv ;
2011-05-03 19:27:33 +04:00
u16 * c ;
2011-08-03 19:08:21 +04:00
int ret = 0 ;
2011-01-04 10:28:59 +03:00
2012-03-19 23:48:34 +04:00
if ( mutex_lock_interruptible ( & state - > demod_lock ) < 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " could not get the lock \n " ) ;
2012-03-07 00:08:29 +04:00
return - EINTR ;
}
2012-03-19 23:48:34 +04:00
if ( mutex_lock_interruptible ( & state - > platform . risc . mem_mbx_lock ) < 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " could not get the lock \n " ) ;
2012-03-07 00:08:29 +04:00
ret = - EINTR ;
goto error ;
}
2011-08-03 19:08:21 +04:00
if ( dib9000_fw_memmbx_sync ( state , FE_SYNC_CHANNEL ) < 0 ) {
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > platform . risc . mem_mbx_lock ) ;
2011-08-03 19:08:21 +04:00
ret = - EIO ;
goto error ;
}
2011-05-03 19:27:33 +04:00
dib9000_risc_mem_read ( state , FE_MM_R_FE_MONITOR ,
state - > i2c_read_buffer , 16 * 2 ) ;
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > platform . risc . mem_mbx_lock ) ;
2011-01-04 10:28:59 +03:00
2011-05-03 19:27:33 +04:00
c = ( u16 * ) state - > i2c_read_buffer ;
2011-01-04 10:28:59 +03:00
* ber = c [ 10 ] < < 16 | c [ 11 ] ;
2011-08-03 19:08:21 +04:00
error :
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > demod_lock ) ;
2011-08-03 19:08:21 +04:00
return ret ;
2011-01-04 10:28:59 +03:00
}
static int dib9000_read_signal_strength ( struct dvb_frontend * fe , u16 * strength )
{
struct dib9000_state * state = fe - > demodulator_priv ;
u8 index_frontend ;
2011-05-03 19:27:33 +04:00
u16 * c = ( u16 * ) state - > i2c_read_buffer ;
2011-01-04 10:28:59 +03:00
u16 val ;
2011-08-03 19:08:21 +04:00
int ret = 0 ;
2011-01-04 10:28:59 +03:00
2012-03-19 23:48:34 +04:00
if ( mutex_lock_interruptible ( & state - > demod_lock ) < 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " could not get the lock \n " ) ;
2012-03-07 00:08:29 +04:00
return - EINTR ;
}
2011-01-04 10:28:59 +03:00
* strength = 0 ;
2011-01-04 19:08:14 +03:00
for ( index_frontend = 1 ; ( index_frontend < MAX_NUMBER_OF_FRONTENDS ) & & ( state - > fe [ index_frontend ] ! = NULL ) ; index_frontend + + ) {
2011-01-04 10:28:59 +03:00
state - > fe [ index_frontend ] - > ops . read_signal_strength ( state - > fe [ index_frontend ] , & val ) ;
if ( val > 65535 - * strength )
* strength = 65535 ;
else
* strength + = val ;
}
2012-03-19 23:48:34 +04:00
if ( mutex_lock_interruptible ( & state - > platform . risc . mem_mbx_lock ) < 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " could not get the lock \n " ) ;
2012-03-07 00:08:29 +04:00
ret = - EINTR ;
goto error ;
}
2011-08-03 19:08:21 +04:00
if ( dib9000_fw_memmbx_sync ( state , FE_SYNC_CHANNEL ) < 0 ) {
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > platform . risc . mem_mbx_lock ) ;
2011-08-03 19:08:21 +04:00
ret = - EIO ;
goto error ;
}
2011-05-03 19:27:33 +04:00
dib9000_risc_mem_read ( state , FE_MM_R_FE_MONITOR , ( u8 * ) c , 16 * 2 ) ;
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > platform . risc . mem_mbx_lock ) ;
2011-01-04 10:28:59 +03:00
val = 65535 - c [ 4 ] ;
if ( val > 65535 - * strength )
* strength = 65535 ;
else
* strength + = val ;
2011-08-03 19:08:21 +04:00
error :
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > demod_lock ) ;
2011-08-03 19:08:21 +04:00
return ret ;
2011-01-04 10:28:59 +03:00
}
static u32 dib9000_get_snr ( struct dvb_frontend * fe )
{
struct dib9000_state * state = fe - > demodulator_priv ;
2011-05-03 19:27:33 +04:00
u16 * c = ( u16 * ) state - > i2c_read_buffer ;
2011-01-04 10:28:59 +03:00
u32 n , s , exp ;
u16 val ;
2012-03-19 23:48:34 +04:00
if ( mutex_lock_interruptible ( & state - > platform . risc . mem_mbx_lock ) < 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " could not get the lock \n " ) ;
2012-03-07 00:08:29 +04:00
return 0 ;
}
2012-03-07 00:08:16 +04:00
if ( dib9000_fw_memmbx_sync ( state , FE_SYNC_CHANNEL ) < 0 ) {
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > platform . risc . mem_mbx_lock ) ;
2012-03-07 00:08:29 +04:00
return 0 ;
2012-03-07 00:08:16 +04:00
}
2011-05-03 19:27:33 +04:00
dib9000_risc_mem_read ( state , FE_MM_R_FE_MONITOR , ( u8 * ) c , 16 * 2 ) ;
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > platform . risc . mem_mbx_lock ) ;
2011-01-04 10:28:59 +03:00
val = c [ 7 ] ;
n = ( val > > 4 ) & 0xff ;
exp = ( ( val & 0xf ) < < 2 ) ;
val = c [ 8 ] ;
exp + = ( ( val > > 14 ) & 0x3 ) ;
if ( ( exp & 0x20 ) ! = 0 )
exp - = 0x40 ;
n < < = exp + 16 ;
s = ( val > > 6 ) & 0xFF ;
exp = ( val & 0x3F ) ;
if ( ( exp & 0x20 ) ! = 0 )
exp - = 0x40 ;
s < < = exp + 16 ;
if ( n > 0 ) {
u32 t = ( s / n ) < < 16 ;
return t + ( ( s < < 16 ) - n * t ) / n ;
}
return 0xffffffff ;
}
static int dib9000_read_snr ( struct dvb_frontend * fe , u16 * snr )
{
struct dib9000_state * state = fe - > demodulator_priv ;
u8 index_frontend ;
u32 snr_master ;
2012-03-19 23:48:34 +04:00
if ( mutex_lock_interruptible ( & state - > demod_lock ) < 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " could not get the lock \n " ) ;
2012-03-07 00:08:29 +04:00
return - EINTR ;
}
2011-01-04 10:28:59 +03:00
snr_master = dib9000_get_snr ( fe ) ;
2011-01-04 19:08:14 +03:00
for ( index_frontend = 1 ; ( index_frontend < MAX_NUMBER_OF_FRONTENDS ) & & ( state - > fe [ index_frontend ] ! = NULL ) ; index_frontend + + )
2011-01-04 10:28:59 +03:00
snr_master + = dib9000_get_snr ( state - > fe [ index_frontend ] ) ;
if ( ( snr_master > > 16 ) ! = 0 ) {
snr_master = 10 * intlog10 ( snr_master > > 16 ) ;
* snr = snr_master / ( ( 1 < < 24 ) / 10 ) ;
} else
* snr = 0 ;
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > demod_lock ) ;
2011-08-03 19:08:21 +04:00
2011-01-04 10:28:59 +03:00
return 0 ;
}
static int dib9000_read_unc_blocks ( struct dvb_frontend * fe , u32 * unc )
{
struct dib9000_state * state = fe - > demodulator_priv ;
2011-05-03 19:27:33 +04:00
u16 * c = ( u16 * ) state - > i2c_read_buffer ;
2011-08-03 19:08:21 +04:00
int ret = 0 ;
2011-01-04 10:28:59 +03:00
2012-03-19 23:48:34 +04:00
if ( mutex_lock_interruptible ( & state - > demod_lock ) < 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " could not get the lock \n " ) ;
2012-03-07 00:08:29 +04:00
return - EINTR ;
}
2012-03-19 23:48:34 +04:00
if ( mutex_lock_interruptible ( & state - > platform . risc . mem_mbx_lock ) < 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " could not get the lock \n " ) ;
2012-03-07 00:08:29 +04:00
ret = - EINTR ;
goto error ;
}
2011-08-03 19:08:21 +04:00
if ( dib9000_fw_memmbx_sync ( state , FE_SYNC_CHANNEL ) < 0 ) {
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > platform . risc . mem_mbx_lock ) ;
2011-08-03 19:08:21 +04:00
ret = - EIO ;
goto error ;
}
2011-05-03 19:27:33 +04:00
dib9000_risc_mem_read ( state , FE_MM_R_FE_MONITOR , ( u8 * ) c , 16 * 2 ) ;
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > platform . risc . mem_mbx_lock ) ;
2011-01-04 10:28:59 +03:00
* unc = c [ 12 ] ;
2011-08-03 19:08:21 +04:00
error :
2012-03-19 23:48:34 +04:00
mutex_unlock ( & state - > demod_lock ) ;
2011-08-03 19:08:21 +04:00
return ret ;
2011-01-04 10:28:59 +03:00
}
int dib9000_i2c_enumeration ( struct i2c_adapter * i2c , int no_of_demods , u8 default_addr , u8 first_addr )
{
2011-05-03 19:27:33 +04:00
int k = 0 , ret = 0 ;
2011-01-04 10:28:59 +03:00
u8 new_addr = 0 ;
struct i2c_device client = { . i2c_adap = i2c } ;
treewide: kzalloc() -> kcalloc()
The kzalloc() function has a 2-factor argument form, kcalloc(). This
patch replaces cases of:
kzalloc(a * b, gfp)
with:
kcalloc(a * b, gfp)
as well as handling cases of:
kzalloc(a * b * c, gfp)
with:
kzalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kzalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kzalloc(4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kzalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kzalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kzalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kzalloc
+ kcalloc
(
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
kzalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
kzalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
kzalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
kzalloc(sizeof(THING) * C2, ...)
|
kzalloc(sizeof(TYPE) * C2, ...)
|
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(C1 * C2, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * E2
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-13 00:03:40 +03:00
client . i2c_write_buffer = kzalloc ( 4 , GFP_KERNEL ) ;
2011-05-03 19:27:33 +04:00
if ( ! client . i2c_write_buffer ) {
2016-10-14 16:08:40 +03:00
dprintk ( " %s: not enough memory \n " , __func__ ) ;
2011-05-03 19:27:33 +04:00
return - ENOMEM ;
}
treewide: kzalloc() -> kcalloc()
The kzalloc() function has a 2-factor argument form, kcalloc(). This
patch replaces cases of:
kzalloc(a * b, gfp)
with:
kcalloc(a * b, gfp)
as well as handling cases of:
kzalloc(a * b * c, gfp)
with:
kzalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kzalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kzalloc(4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kzalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kzalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kzalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kzalloc
+ kcalloc
(
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
kzalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
kzalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
kzalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
kzalloc(sizeof(THING) * C2, ...)
|
kzalloc(sizeof(TYPE) * C2, ...)
|
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(C1 * C2, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * E2
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-13 00:03:40 +03:00
client . i2c_read_buffer = kzalloc ( 4 , GFP_KERNEL ) ;
2011-05-03 19:27:33 +04:00
if ( ! client . i2c_read_buffer ) {
2016-10-14 16:08:40 +03:00
dprintk ( " %s: not enough memory \n " , __func__ ) ;
2011-05-03 19:27:33 +04:00
ret = - ENOMEM ;
goto error_memory ;
}
2011-01-04 10:28:59 +03:00
client . i2c_addr = default_addr + 16 ;
2011-01-04 19:08:14 +03:00
dib9000_i2c_write16 ( & client , 1796 , 0x0 ) ;
2011-01-04 10:28:59 +03:00
for ( k = no_of_demods - 1 ; k > = 0 ; k - - ) {
/* designated i2c address */
new_addr = first_addr + ( k < < 1 ) ;
client . i2c_addr = default_addr ;
dib9000_i2c_write16 ( & client , 1817 , 3 ) ;
dib9000_i2c_write16 ( & client , 1796 , 0 ) ;
dib9000_i2c_write16 ( & client , 1227 , 1 ) ;
dib9000_i2c_write16 ( & client , 1227 , 0 ) ;
client . i2c_addr = new_addr ;
dib9000_i2c_write16 ( & client , 1817 , 3 ) ;
dib9000_i2c_write16 ( & client , 1796 , 0 ) ;
dib9000_i2c_write16 ( & client , 1227 , 1 ) ;
dib9000_i2c_write16 ( & client , 1227 , 0 ) ;
if ( dib9000_identify ( & client ) = = 0 ) {
client . i2c_addr = default_addr ;
if ( dib9000_identify ( & client ) = = 0 ) {
2016-10-14 16:08:40 +03:00
dprintk ( " DiB9000 #%d: not identified \n " , k ) ;
2011-05-03 19:27:33 +04:00
ret = - EIO ;
goto error ;
2011-01-04 10:28:59 +03:00
}
}
dib9000_i2c_write16 ( & client , 1795 , ( 1 < < 10 ) | ( 4 < < 6 ) ) ;
dib9000_i2c_write16 ( & client , 1794 , ( new_addr < < 2 ) | 2 ) ;
2016-10-14 16:08:40 +03:00
dprintk ( " IC %d initialized (to i2c_address 0x%x) \n " , k , new_addr ) ;
2011-01-04 10:28:59 +03:00
}
for ( k = 0 ; k < no_of_demods ; k + + ) {
new_addr = first_addr | ( k < < 1 ) ;
client . i2c_addr = new_addr ;
dib9000_i2c_write16 ( & client , 1794 , ( new_addr < < 2 ) ) ;
dib9000_i2c_write16 ( & client , 1795 , 0 ) ;
}
2011-05-03 19:27:33 +04:00
error :
kfree ( client . i2c_read_buffer ) ;
error_memory :
kfree ( client . i2c_write_buffer ) ;
return ret ;
2011-01-04 10:28:59 +03:00
}
EXPORT_SYMBOL ( dib9000_i2c_enumeration ) ;
int dib9000_set_slave_frontend ( struct dvb_frontend * fe , struct dvb_frontend * fe_slave )
{
struct dib9000_state * state = fe - > demodulator_priv ;
u8 index_frontend = 1 ;
while ( ( index_frontend < MAX_NUMBER_OF_FRONTENDS ) & & ( state - > fe [ index_frontend ] ! = NULL ) )
index_frontend + + ;
if ( index_frontend < MAX_NUMBER_OF_FRONTENDS ) {
2016-10-14 16:08:40 +03:00
dprintk ( " set slave fe %p to index %i \n " , fe_slave , index_frontend ) ;
2011-01-04 10:28:59 +03:00
state - > fe [ index_frontend ] = fe_slave ;
return 0 ;
}
2016-10-14 16:08:40 +03:00
dprintk ( " too many slave frontend \n " ) ;
2011-01-04 10:28:59 +03:00
return - ENOMEM ;
}
EXPORT_SYMBOL ( dib9000_set_slave_frontend ) ;
2011-01-04 19:08:14 +03:00
struct dvb_frontend * dib9000_get_slave_frontend ( struct dvb_frontend * fe , int slave_index )
2011-01-04 10:28:59 +03:00
{
struct dib9000_state * state = fe - > demodulator_priv ;
if ( slave_index > = MAX_NUMBER_OF_FRONTENDS )
return NULL ;
return state - > fe [ slave_index ] ;
}
EXPORT_SYMBOL ( dib9000_get_slave_frontend ) ;
2016-08-10 00:32:21 +03:00
static const struct dvb_frontend_ops dib9000_ops ;
2011-01-04 10:28:59 +03:00
struct dvb_frontend * dib9000_attach ( struct i2c_adapter * i2c_adap , u8 i2c_addr , const struct dib9000_config * cfg )
{
struct dvb_frontend * fe ;
struct dib9000_state * st ;
st = kzalloc ( sizeof ( struct dib9000_state ) , GFP_KERNEL ) ;
if ( st = = NULL )
return NULL ;
fe = kzalloc ( sizeof ( struct dvb_frontend ) , GFP_KERNEL ) ;
2011-04-07 23:34:30 +04:00
if ( fe = = NULL ) {
kfree ( st ) ;
2011-01-04 10:28:59 +03:00
return NULL ;
2011-04-07 23:34:30 +04:00
}
2011-01-04 10:28:59 +03:00
memcpy ( & st - > chip . d9 . cfg , cfg , sizeof ( struct dib9000_config ) ) ;
st - > i2c . i2c_adap = i2c_adap ;
st - > i2c . i2c_addr = i2c_addr ;
2011-05-03 19:27:33 +04:00
st - > i2c . i2c_write_buffer = st - > i2c_write_buffer ;
st - > i2c . i2c_read_buffer = st - > i2c_read_buffer ;
2011-01-04 10:28:59 +03:00
st - > gpio_dir = DIB9000_GPIO_DEFAULT_DIRECTIONS ;
st - > gpio_val = DIB9000_GPIO_DEFAULT_VALUES ;
st - > gpio_pwm_pos = DIB9000_GPIO_DEFAULT_PWM_POS ;
2012-03-19 23:48:34 +04:00
mutex_init ( & st - > platform . risc . mbx_if_lock ) ;
mutex_init ( & st - > platform . risc . mbx_lock ) ;
mutex_init ( & st - > platform . risc . mem_lock ) ;
mutex_init ( & st - > platform . risc . mem_mbx_lock ) ;
mutex_init ( & st - > demod_lock ) ;
2011-08-03 19:08:21 +04:00
st - > get_frontend_internal = 0 ;
st - > pid_ctrl_index = - 2 ;
2011-01-04 10:28:59 +03:00
st - > fe [ 0 ] = fe ;
fe - > demodulator_priv = st ;
memcpy ( & st - > fe [ 0 ] - > ops , & dib9000_ops , sizeof ( struct dvb_frontend_ops ) ) ;
/* Ensure the output mode remains at the previous default if it's
* not specifically set by the caller .
*/
if ( ( st - > chip . d9 . cfg . output_mode ! = OUTMODE_MPEG2_SERIAL ) & & ( st - > chip . d9 . cfg . output_mode ! = OUTMODE_MPEG2_PAR_GATED_CLK ) )
st - > chip . d9 . cfg . output_mode = OUTMODE_MPEG2_FIFO ;
if ( dib9000_identify ( & st - > i2c ) = = 0 )
goto error ;
dibx000_init_i2c_master ( & st - > i2c_master , DIB7000MC , st - > i2c . i2c_adap , st - > i2c . i2c_addr ) ;
st - > tuner_adap . dev . parent = i2c_adap - > dev . parent ;
2018-09-10 15:19:16 +03:00
strscpy ( st - > tuner_adap . name , " DIB9000_FW TUNER ACCESS " ,
sizeof ( st - > tuner_adap . name ) ) ;
2011-01-04 10:28:59 +03:00
st - > tuner_adap . algo = & dib9000_tuner_algo ;
st - > tuner_adap . algo_data = NULL ;
i2c_set_adapdata ( & st - > tuner_adap , st ) ;
if ( i2c_add_adapter ( & st - > tuner_adap ) < 0 )
goto error ;
st - > component_bus . dev . parent = i2c_adap - > dev . parent ;
2018-09-10 15:19:16 +03:00
strscpy ( st - > component_bus . name , " DIB9000_FW COMPONENT BUS ACCESS " ,
sizeof ( st - > component_bus . name ) ) ;
2011-01-04 10:28:59 +03:00
st - > component_bus . algo = & dib9000_component_bus_algo ;
st - > component_bus . algo_data = NULL ;
st - > component_bus_speed = 340 ;
i2c_set_adapdata ( & st - > component_bus , st ) ;
if ( i2c_add_adapter ( & st - > component_bus ) < 0 )
goto component_bus_add_error ;
dib9000_fw_reset ( fe ) ;
return fe ;
2011-01-04 19:08:14 +03:00
component_bus_add_error :
2011-01-04 10:28:59 +03:00
i2c_del_adapter ( & st - > tuner_adap ) ;
2011-01-04 19:08:14 +03:00
error :
2011-01-04 10:28:59 +03:00
kfree ( st ) ;
return NULL ;
}
EXPORT_SYMBOL ( dib9000_attach ) ;
2016-08-10 00:32:21 +03:00
static const struct dvb_frontend_ops dib9000_ops = {
2011-12-23 03:12:18 +04:00
. delsys = { SYS_DVBT } ,
2011-01-04 10:28:59 +03:00
. info = {
. name = " DiBcom 9000 " ,
2018-07-06 01:59:36 +03:00
. frequency_min_hz = 44250 * kHz ,
. frequency_max_hz = 867250 * kHz ,
. frequency_stepsize_hz = 62500 ,
2011-01-04 10:28:59 +03:00
. caps = FE_CAN_INVERSION_AUTO |
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO ,
} ,
. release = dib9000_release ,
. init = dib9000_wakeup ,
. sleep = dib9000_sleep ,
2011-12-23 03:12:18 +04:00
. set_frontend = dib9000_set_frontend ,
2011-01-04 10:28:59 +03:00
. get_tune_settings = dib9000_fe_get_tune_settings ,
2011-12-23 03:12:18 +04:00
. get_frontend = dib9000_get_frontend ,
2011-01-04 10:28:59 +03:00
. read_status = dib9000_read_status ,
. read_ber = dib9000_read_ber ,
. read_signal_strength = dib9000_read_signal_strength ,
. read_snr = dib9000_read_snr ,
. read_ucblocks = dib9000_read_unc_blocks ,
} ;
2016-01-24 17:56:58 +03:00
MODULE_AUTHOR ( " Patrick Boettcher <patrick.boettcher@posteo.de> " ) ;
MODULE_AUTHOR ( " Olivier Grenie <olivier.grenie@parrot.com> " ) ;
2011-01-04 10:28:59 +03:00
MODULE_DESCRIPTION ( " Driver for the DiBcom 9000 COFDM demodulator " ) ;
MODULE_LICENSE ( " GPL " ) ;