2007-12-18 07:55:51 +03:00
/*
* Driver for Xceive XC5000 " QAM/8VSB single chip tuner "
*
* Copyright ( c ) 2007 Xceive Corporation
2008-09-04 00:12:12 +04:00
* Copyright ( c ) 2007 Steven Toth < stoth @ linuxtv . org >
2009-05-15 04:31:11 +04:00
* Copyright ( c ) 2009 Devin Heitmueller < dheitmueller @ kernellabs . com >
2007-12-18 07:55:51 +03:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
*
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include <linux/module.h>
# include <linux/moduleparam.h>
2008-01-16 03:57:14 +03:00
# include <linux/videodev2.h>
2007-12-18 07:55:51 +03:00
# include <linux/delay.h>
2014-05-21 20:57:30 +04:00
# include <linux/workqueue.h>
2007-12-18 07:55:51 +03:00
# include <linux/dvb/frontend.h>
# include <linux/i2c.h>
# include "dvb_frontend.h"
# include "xc5000.h"
2008-09-06 18:44:53 +04:00
# include "tuner-i2c.h"
2007-12-18 07:55:51 +03:00
static int debug ;
module_param ( debug , int , 0644 ) ;
MODULE_PARM_DESC ( debug , " Turn on/off debugging (default:off). " ) ;
2009-04-28 20:53:38 +04:00
static int no_poweroff ;
module_param ( no_poweroff , int , 0644 ) ;
MODULE_PARM_DESC ( no_poweroff , " 0 (default) powers device off when not used. \n "
" \t \t 1 keep device energized and with tuner ready all the times. \n "
" \t \t Faster, but consumes more power and keeps the device hotter " ) ;
2008-09-06 18:44:53 +04:00
static DEFINE_MUTEX ( xc5000_list_mutex ) ;
static LIST_HEAD ( hybrid_tuner_instance_list ) ;
2008-10-17 03:29:38 +04:00
# define dprintk(level, fmt, arg...) if (debug >= level) \
2007-12-18 07:55:51 +03:00
printk ( KERN_INFO " %s: " fmt , " xc5000 " , # # arg )
2008-09-06 17:52:30 +04:00
struct xc5000_priv {
2008-09-06 18:44:53 +04:00
struct tuner_i2c_props i2c_props ;
struct list_head hybrid_tuner_instance_list ;
2008-09-06 17:52:30 +04:00
2008-09-06 20:54:45 +04:00
u32 if_khz ;
2012-04-16 22:21:51 +04:00
u16 xtal_khz ;
2014-07-21 21:21:18 +04:00
u32 freq_hz , freq_offset ;
2008-09-06 17:52:30 +04:00
u32 bandwidth ;
u8 video_standard ;
2014-08-10 04:47:21 +04:00
unsigned int mode ;
2008-09-06 17:52:30 +04:00
u8 rf_mode ;
2009-09-24 20:27:24 +04:00
u8 radio_input ;
2014-10-26 00:17:22 +04:00
u16 output_amp ;
2012-02-07 02:40:32 +04:00
2012-02-08 21:57:39 +04:00
int chip_id ;
2012-08-07 05:47:08 +04:00
u16 pll_register_no ;
2012-08-07 05:47:09 +04:00
u8 init_status_supported ;
u8 fw_checksum_supported ;
2014-05-21 20:57:30 +04:00
struct dvb_frontend * fe ;
struct delayed_work timer_sleep ;
2014-09-23 04:30:46 +04:00
const struct firmware * firmware ;
2008-09-06 17:52:30 +04:00
} ;
2007-12-18 07:55:51 +03:00
/* Misc Defines */
2011-02-01 11:25:19 +03:00
# define MAX_TV_STANDARD 24
2007-12-18 07:55:51 +03:00
# define XC_MAX_I2C_WRITE_LENGTH 64
2014-05-21 20:57:30 +04:00
/* Time to suspend after the .sleep callback is called */
# define XC5000_SLEEP_TIME 5000 /* ms */
2007-12-18 07:55:51 +03:00
/* Signal Types */
# define XC_RF_MODE_AIR 0
# define XC_RF_MODE_CABLE 1
2008-01-05 22:50:14 +03:00
/* Product id */
# define XC_PRODUCT_ID_FW_NOT_LOADED 0x2000
2014-05-21 20:41:01 +04:00
# define XC_PRODUCT_ID_FW_LOADED 0x1388
2008-01-05 22:50:14 +03:00
2007-12-18 07:55:51 +03:00
/* Registers */
# define XREG_INIT 0x00
# define XREG_VIDEO_MODE 0x01
# define XREG_AUDIO_MODE 0x02
# define XREG_RF_FREQ 0x03
# define XREG_D_CODE 0x04
# define XREG_IF_OUT 0x05
# define XREG_SEEK_MODE 0x07
2009-04-03 05:02:39 +04:00
# define XREG_POWER_DOWN 0x0A /* Obsolete */
2011-02-01 11:25:19 +03:00
/* Set the output amplitude - SIF for analog, DTVP/DTVN for digital */
# define XREG_OUTPUT_AMP 0x0B
2007-12-18 07:55:51 +03:00
# define XREG_SIGNALSOURCE 0x0D /* 0=Air, 1=Cable */
# define XREG_SMOOTHEDCVBS 0x0E
# define XREG_XTALFREQ 0x0F
2009-04-03 05:40:29 +04:00
# define XREG_FINERFREQ 0x10
2007-12-18 07:55:51 +03:00
# define XREG_DDIMODE 0x11
# define XREG_ADC_ENV 0x00
# define XREG_QUALITY 0x01
# define XREG_FRAME_LINES 0x02
# define XREG_HSYNC_FREQ 0x03
# define XREG_LOCK 0x04
# define XREG_FREQ_ERROR 0x05
# define XREG_SNR 0x06
# define XREG_VERSION 0x07
# define XREG_PRODUCT_ID 0x08
# define XREG_BUSY 0x09
2009-04-03 05:24:38 +04:00
# define XREG_BUILD 0x0D
2012-08-07 05:46:56 +04:00
# define XREG_TOTALGAIN 0x0F
2012-08-07 05:47:09 +04:00
# define XREG_FW_CHECKSUM 0x12
# define XREG_INIT_STATUS 0x13
2007-12-18 07:55:51 +03:00
/*
Basic firmware description . This will remain with
the driver for documentation purposes .
This represents an I2C firmware file encoded as a
string of unsigned char . Format is as follows :
char [ 0 ] = len0_MSB - > len = len_MSB * 256 + len_LSB
char [ 1 ] = len0_LSB - > length of first write transaction
char [ 2 ] = data0 - > first byte to be sent
char [ 3 ] = data1
char [ 4 ] = data2
char [ ] = . . .
char [ M ] = dataN - > last byte to be sent
char [ M + 1 ] = len1_MSB - > len = len_MSB * 256 + len_LSB
char [ M + 2 ] = len1_LSB - > length of second write transaction
char [ M + 3 ] = data0
char [ M + 4 ] = data1
. . .
etc .
The [ len ] value should be interpreted as follows :
len = len_MSB _ len_LSB
len = 1111 _1111_1111_1111 : End of I2C_SEQUENCE
len = 0000 _0000_0000_0000 : Reset command : Do hardware reset
len = 0 NNN_NNNN_NNNN_NNNN : Normal transaction : number of bytes = { 1 : 32767 )
len = 1 WWW_WWWW_WWWW_WWWW : Wait command : wait for { 1 : 32767 } ms
For the RESET and WAIT commands , the two following bytes will contain
immediately the length of the following transaction .
*/
2008-10-17 03:29:38 +04:00
struct XC_TV_STANDARD {
2014-05-21 20:23:27 +04:00
char * name ;
u16 audio_mode ;
u16 video_mode ;
2008-10-17 03:29:38 +04:00
} ;
2007-12-18 07:55:51 +03:00
/* Tuner standards */
2008-01-05 22:50:14 +03:00
# define MN_NTSC_PAL_BTSC 0
# define MN_NTSC_PAL_A2 1
# define MN_NTSC_PAL_EIAJ 2
2014-05-21 20:23:27 +04:00
# define MN_NTSC_PAL_MONO 3
2008-01-05 22:50:14 +03:00
# define BG_PAL_A2 4
# define BG_PAL_NICAM 5
# define BG_PAL_MONO 6
# define I_PAL_NICAM 7
# define I_PAL_NICAM_MONO 8
# define DK_PAL_A2 9
# define DK_PAL_NICAM 10
# define DK_PAL_MONO 11
# define DK_SECAM_A2DK1 12
2014-05-21 20:41:01 +04:00
# define DK_SECAM_A2LDK3 13
# define DK_SECAM_A2MONO 14
2008-01-05 22:50:14 +03:00
# define L_SECAM_NICAM 15
# define LC_SECAM_NICAM 16
# define DTV6 17
# define DTV8 18
# define DTV7_8 19
# define DTV7 20
2014-05-21 20:41:01 +04:00
# define FM_RADIO_INPUT2 21
# define FM_RADIO_INPUT1 22
2014-05-21 20:23:27 +04:00
# define FM_RADIO_INPUT1_MONO 23
2007-12-18 07:55:51 +03:00
2014-05-21 20:23:27 +04:00
static struct XC_TV_STANDARD xc5000_standard [ MAX_TV_STANDARD ] = {
2007-12-18 07:55:51 +03:00
{ " M/N-NTSC/PAL-BTSC " , 0x0400 , 0x8020 } ,
{ " M/N-NTSC/PAL-A2 " , 0x0600 , 0x8020 } ,
{ " M/N-NTSC/PAL-EIAJ " , 0x0440 , 0x8020 } ,
{ " M/N-NTSC/PAL-Mono " , 0x0478 , 0x8020 } ,
{ " B/G-PAL-A2 " , 0x0A00 , 0x8049 } ,
{ " B/G-PAL-NICAM " , 0x0C04 , 0x8049 } ,
{ " B/G-PAL-MONO " , 0x0878 , 0x8059 } ,
{ " I-PAL-NICAM " , 0x1080 , 0x8009 } ,
{ " I-PAL-NICAM-MONO " , 0x0E78 , 0x8009 } ,
{ " D/K-PAL-A2 " , 0x1600 , 0x8009 } ,
{ " D/K-PAL-NICAM " , 0x0E80 , 0x8009 } ,
{ " D/K-PAL-MONO " , 0x1478 , 0x8009 } ,
{ " D/K-SECAM-A2 DK1 " , 0x1200 , 0x8009 } ,
2008-10-17 03:29:38 +04:00
{ " D/K-SECAM-A2 L/DK3 " , 0x0E00 , 0x8009 } ,
2007-12-18 07:55:51 +03:00
{ " D/K-SECAM-A2 MONO " , 0x1478 , 0x8009 } ,
{ " L-SECAM-NICAM " , 0x8E82 , 0x0009 } ,
{ " L'-SECAM-NICAM " , 0x8E82 , 0x4009 } ,
{ " DTV6 " , 0x00C0 , 0x8002 } ,
{ " DTV8 " , 0x00C0 , 0x800B } ,
{ " DTV7/8 " , 0x00C0 , 0x801B } ,
{ " DTV7 " , 0x00C0 , 0x8007 } ,
{ " FM Radio-INPUT2 " , 0x9802 , 0x9002 } ,
2011-02-01 11:25:19 +03:00
{ " FM Radio-INPUT1 " , 0x0208 , 0x9002 } ,
{ " FM Radio-INPUT1_MONO " , 0x0278 , 0x9002 }
2007-12-18 07:55:51 +03:00
} ;
2012-02-07 09:39:36 +04:00
struct xc5000_fw_cfg {
char * name ;
u16 size ;
2012-08-07 05:47:08 +04:00
u16 pll_reg ;
2012-08-07 05:47:09 +04:00
u8 init_status_supported ;
u8 fw_checksum_supported ;
2012-02-07 09:39:36 +04:00
} ;
2012-07-25 16:15:19 +04:00
# define XC5000A_FIRMWARE "dvb-fe-xc5000-1.6.114.fw"
2012-02-08 22:03:07 +04:00
static const struct xc5000_fw_cfg xc5000a_1_6_114 = {
2012-07-25 16:15:19 +04:00
. name = XC5000A_FIRMWARE ,
2012-02-07 02:40:32 +04:00
. size = 12401 ,
2012-08-07 05:47:08 +04:00
. pll_reg = 0x806c ,
2012-02-07 02:40:32 +04:00
} ;
2012-08-07 05:47:14 +04:00
# define XC5000C_FIRMWARE "dvb-fe-xc5000c-4.1.30.7.fw"
2012-04-16 21:59:32 +04:00
static const struct xc5000_fw_cfg xc5000c_41_024_5 = {
2012-07-25 16:15:19 +04:00
. name = XC5000C_FIRMWARE ,
2012-04-16 21:59:32 +04:00
. size = 16497 ,
2012-08-07 05:47:08 +04:00
. pll_reg = 0x13 ,
2012-08-07 05:47:09 +04:00
. init_status_supported = 1 ,
. fw_checksum_supported = 1 ,
2012-02-07 08:16:27 +04:00
} ;
2012-02-08 22:03:07 +04:00
static inline const struct xc5000_fw_cfg * xc5000_assign_firmware ( int chip_id )
2012-02-07 09:39:36 +04:00
{
2012-02-08 21:57:39 +04:00
switch ( chip_id ) {
2012-02-07 09:39:36 +04:00
default :
2012-02-08 21:57:39 +04:00
case XC5000A :
2012-02-07 09:39:36 +04:00
return & xc5000a_1_6_114 ;
2012-02-08 21:57:39 +04:00
case XC5000C :
2012-04-16 21:59:32 +04:00
return & xc5000c_41_024_5 ;
2012-02-07 09:39:36 +04:00
}
}
2012-08-07 05:47:08 +04:00
static int xc_load_fw_and_init_tuner ( struct dvb_frontend * fe , int force ) ;
2008-11-16 05:29:11 +03:00
static int xc5000_is_firmware_loaded ( struct dvb_frontend * fe ) ;
2008-11-17 02:17:14 +03:00
static int xc5000_readreg ( struct xc5000_priv * priv , u16 reg , u16 * val ) ;
2014-05-21 20:23:27 +04:00
static int xc5000_tuner_reset ( struct dvb_frontend * fe ) ;
2007-12-18 07:55:51 +03:00
2007-12-20 07:14:43 +03:00
static int xc_send_i2c_data ( struct xc5000_priv * priv , u8 * buf , int len )
2007-12-18 07:55:51 +03:00
{
2008-11-17 02:20:06 +03:00
struct i2c_msg msg = { . addr = priv - > i2c_props . addr ,
. flags = 0 , . buf = buf , . len = len } ;
if ( i2c_transfer ( priv - > i2c_props . adap , & msg , 1 ) ! = 1 ) {
printk ( KERN_ERR " xc5000: I2C write failed (len=%i) \n " , len ) ;
2014-05-21 20:08:18 +04:00
return - EREMOTEIO ;
2008-11-17 02:20:06 +03:00
}
2014-05-21 20:08:18 +04:00
return 0 ;
2007-12-18 07:55:51 +03:00
}
2010-07-06 01:38:46 +04:00
#if 0
2008-11-17 02:17:14 +03:00
/* This routine is never used because the only time we read data from the
i2c bus is when we read registers , and we want that to be an atomic i2c
transaction in case we are on a multi - master bus */
2007-12-20 07:14:43 +03:00
static int xc_read_i2c_data ( struct xc5000_priv * priv , u8 * buf , int len )
2007-12-18 07:55:51 +03:00
{
2008-11-17 02:17:14 +03:00
struct i2c_msg msg = { . addr = priv - > i2c_props . addr ,
. flags = I2C_M_RD , . buf = buf , . len = len } ;
if ( i2c_transfer ( priv - > i2c_props . adap , & msg , 1 ) ! = 1 ) {
printk ( KERN_ERR " xc5000 I2C read failed (len=%i) \n " , len ) ;
return - EREMOTEIO ;
}
return 0 ;
2007-12-18 07:55:51 +03:00
}
2010-07-06 01:38:46 +04:00
# endif
2007-12-18 07:55:51 +03:00
2010-05-18 11:30:11 +04:00
static int xc5000_readreg ( struct xc5000_priv * priv , u16 reg , u16 * val )
{
u8 buf [ 2 ] = { reg > > 8 , reg & 0xff } ;
u8 bval [ 2 ] = { 0 , 0 } ;
struct i2c_msg msg [ 2 ] = {
{ . addr = priv - > i2c_props . addr ,
. flags = 0 , . buf = & buf [ 0 ] , . len = 2 } ,
{ . addr = priv - > i2c_props . addr ,
. flags = I2C_M_RD , . buf = & bval [ 0 ] , . len = 2 } ,
} ;
if ( i2c_transfer ( priv - > i2c_props . adap , msg , 2 ) ! = 2 ) {
printk ( KERN_WARNING " xc5000: I2C read failed \n " ) ;
return - EREMOTEIO ;
}
* val = ( bval [ 0 ] < < 8 ) | bval [ 1 ] ;
2014-05-21 20:08:18 +04:00
return 0 ;
2010-05-18 11:30:11 +04:00
}
2014-05-21 20:23:27 +04:00
static int xc5000_tuner_reset ( struct dvb_frontend * fe )
2007-12-18 07:55:51 +03:00
{
struct xc5000_priv * priv = fe - > tuner_priv ;
int ret ;
2008-04-09 06:20:00 +04:00
dprintk ( 1 , " %s() \n " , __func__ ) ;
2007-12-18 07:55:51 +03:00
2008-09-12 20:31:45 +04:00
if ( fe - > callback ) {
ret = fe - > callback ( ( ( fe - > dvb ) & & ( fe - > dvb - > priv ) ) ?
2008-09-06 21:56:58 +04:00
fe - > dvb - > priv :
priv - > i2c_props . adap - > algo_data ,
2008-09-12 20:31:45 +04:00
DVB_FRONTEND_COMPONENT_TUNER ,
2008-09-06 21:56:58 +04:00
XC5000_TUNER_RESET , 0 ) ;
2008-11-16 05:29:11 +03:00
if ( ret ) {
2007-12-18 07:55:51 +03:00
printk ( KERN_ERR " xc5000: reset failed \n " ) ;
2014-05-21 20:08:18 +04:00
return ret ;
2008-11-16 05:29:11 +03:00
}
} else {
2008-01-05 22:50:14 +03:00
printk ( KERN_ERR " xc5000: no tuner reset callback function, fatal \n " ) ;
2014-05-21 20:08:18 +04:00
return - EINVAL ;
2008-11-16 05:29:11 +03:00
}
2014-05-21 20:08:18 +04:00
return 0 ;
2007-12-18 07:55:51 +03:00
}
2014-05-21 20:23:27 +04:00
static int xc_write_reg ( struct xc5000_priv * priv , u16 reg_addr , u16 i2c_data )
2007-12-18 07:55:51 +03:00
{
2007-12-20 07:14:43 +03:00
u8 buf [ 4 ] ;
2014-05-21 20:23:27 +04:00
int watch_dog_timer = 100 ;
2007-12-18 07:55:51 +03:00
int result ;
2014-05-21 20:23:27 +04:00
buf [ 0 ] = ( reg_addr > > 8 ) & 0xFF ;
buf [ 1 ] = reg_addr & 0xFF ;
buf [ 2 ] = ( i2c_data > > 8 ) & 0xFF ;
buf [ 3 ] = i2c_data & 0xFF ;
2007-12-18 07:55:51 +03:00
result = xc_send_i2c_data ( priv , buf , 4 ) ;
2014-05-21 20:08:18 +04:00
if ( result = = 0 ) {
2007-12-18 07:55:51 +03:00
/* wait for busy flag to clear */
2014-05-21 20:23:27 +04:00
while ( ( watch_dog_timer > 0 ) & & ( result = = 0 ) ) {
2010-07-06 01:38:46 +04:00
result = xc5000_readreg ( priv , XREG_BUSY , ( u16 * ) buf ) ;
2014-05-21 20:08:18 +04:00
if ( result = = 0 ) {
2010-05-18 11:30:11 +04:00
if ( ( buf [ 0 ] = = 0 ) & & ( buf [ 1 ] = = 0 ) ) {
/* busy flag cleared */
2007-12-18 07:55:51 +03:00
break ;
2010-05-18 11:30:11 +04:00
} else {
2014-05-21 20:15:17 +04:00
msleep ( 5 ) ; /* wait 5 ms */
2014-05-21 20:23:27 +04:00
watch_dog_timer - - ;
2007-12-18 07:55:51 +03:00
}
}
}
}
2014-05-21 20:23:27 +04:00
if ( watch_dog_timer < = 0 )
2014-05-21 20:08:18 +04:00
result = - EREMOTEIO ;
2007-12-18 07:55:51 +03:00
return result ;
}
2008-05-24 03:13:34 +04:00
static int xc_load_i2c_sequence ( struct dvb_frontend * fe , const u8 * i2c_sequence )
2007-12-18 07:55:51 +03:00
{
struct xc5000_priv * priv = fe - > tuner_priv ;
int i , nbytes_to_send , result ;
unsigned int len , pos , index ;
2007-12-20 07:14:43 +03:00
u8 buf [ XC_MAX_I2C_WRITE_LENGTH ] ;
2007-12-18 07:55:51 +03:00
2008-10-17 03:29:38 +04:00
index = 0 ;
while ( ( i2c_sequence [ index ] ! = 0xFF ) | |
( i2c_sequence [ index + 1 ] ! = 0xFF ) ) {
len = i2c_sequence [ index ] * 256 + i2c_sequence [ index + 1 ] ;
2007-12-20 07:14:43 +03:00
if ( len = = 0x0000 ) {
2007-12-18 07:55:51 +03:00
/* RESET command */
2014-05-21 20:23:27 +04:00
result = xc5000_tuner_reset ( fe ) ;
2007-12-18 07:55:51 +03:00
index + = 2 ;
2014-05-21 20:08:18 +04:00
if ( result ! = 0 )
2007-12-18 07:55:51 +03:00
return result ;
} else if ( len & 0x8000 ) {
/* WAIT command */
2014-05-21 20:15:17 +04:00
msleep ( len & 0x7FFF ) ;
2007-12-18 07:55:51 +03:00
index + = 2 ;
} else {
/* Send i2c data whilst ensuring individual transactions
* do not exceed XC_MAX_I2C_WRITE_LENGTH bytes .
*/
index + = 2 ;
buf [ 0 ] = i2c_sequence [ index ] ;
buf [ 1 ] = i2c_sequence [ index + 1 ] ;
pos = 2 ;
while ( pos < len ) {
2008-10-17 03:29:38 +04:00
if ( ( len - pos ) > XC_MAX_I2C_WRITE_LENGTH - 2 )
nbytes_to_send =
XC_MAX_I2C_WRITE_LENGTH ;
else
2007-12-18 07:55:51 +03:00
nbytes_to_send = ( len - pos + 2 ) ;
2008-10-17 03:29:38 +04:00
for ( i = 2 ; i < nbytes_to_send ; i + + ) {
buf [ i ] = i2c_sequence [ index + pos +
i - 2 ] ;
2007-12-18 07:55:51 +03:00
}
2008-10-17 03:29:38 +04:00
result = xc_send_i2c_data ( priv , buf ,
nbytes_to_send ) ;
2007-12-18 07:55:51 +03:00
2014-05-21 20:08:18 +04:00
if ( result ! = 0 )
2007-12-18 07:55:51 +03:00
return result ;
pos + = nbytes_to_send - 2 ;
}
index + = len ;
}
}
2014-05-21 20:08:18 +04:00
return 0 ;
2007-12-18 07:55:51 +03:00
}
2007-12-20 07:14:43 +03:00
static int xc_initialize ( struct xc5000_priv * priv )
2007-12-18 07:55:51 +03:00
{
2008-04-09 06:20:00 +04:00
dprintk ( 1 , " %s() \n " , __func__ ) ;
2007-12-18 07:55:51 +03:00
return xc_write_reg ( priv , XREG_INIT , 0 ) ;
}
2014-05-21 20:23:27 +04:00
static int xc_set_tv_standard ( struct xc5000_priv * priv ,
u16 video_mode , u16 audio_mode , u8 radio_mode )
2007-12-18 07:55:51 +03:00
{
int ret ;
2014-05-21 20:23:27 +04:00
dprintk ( 1 , " %s(0x%04x,0x%04x) \n " , __func__ , video_mode , audio_mode ) ;
if ( radio_mode ) {
2013-03-13 07:23:36 +04:00
dprintk ( 1 , " %s() Standard = %s \n " ,
__func__ ,
2014-05-21 20:23:27 +04:00
xc5000_standard [ radio_mode ] . name ) ;
2013-03-13 07:23:36 +04:00
} else {
dprintk ( 1 , " %s() Standard = %s \n " ,
__func__ ,
2014-05-21 20:23:27 +04:00
xc5000_standard [ priv - > video_standard ] . name ) ;
2013-03-13 07:23:36 +04:00
}
2007-12-18 07:55:51 +03:00
2014-05-21 20:23:27 +04:00
ret = xc_write_reg ( priv , XREG_VIDEO_MODE , video_mode ) ;
2014-05-21 20:08:18 +04:00
if ( ret = = 0 )
2014-05-21 20:23:27 +04:00
ret = xc_write_reg ( priv , XREG_AUDIO_MODE , audio_mode ) ;
2007-12-18 07:55:51 +03:00
return ret ;
}
2014-05-21 20:23:27 +04:00
static int xc_set_signal_source ( struct xc5000_priv * priv , u16 rf_mode )
2007-12-18 07:55:51 +03:00
{
2008-04-09 06:20:00 +04:00
dprintk ( 1 , " %s(%d) Source = %s \n " , __func__ , rf_mode ,
2007-12-18 07:55:51 +03:00
rf_mode = = XC_RF_MODE_AIR ? " ANTENNA " : " CABLE " ) ;
2008-10-17 03:29:38 +04:00
if ( ( rf_mode ! = XC_RF_MODE_AIR ) & & ( rf_mode ! = XC_RF_MODE_CABLE ) ) {
2007-12-18 07:55:51 +03:00
rf_mode = XC_RF_MODE_CABLE ;
printk ( KERN_ERR
" %s(), Invalid mode, defaulting to CABLE " ,
2008-04-09 06:20:00 +04:00
__func__ ) ;
2007-12-18 07:55:51 +03:00
}
return xc_write_reg ( priv , XREG_SIGNALSOURCE , rf_mode ) ;
}
2007-12-20 07:14:43 +03:00
static const struct dvb_tuner_ops xc5000_tuner_ops ;
2007-12-18 07:55:51 +03:00
2014-05-21 20:23:27 +04:00
static int xc_set_rf_frequency ( struct xc5000_priv * priv , u32 freq_hz )
2007-12-20 07:14:43 +03:00
{
u16 freq_code ;
2007-12-18 07:55:51 +03:00
2008-04-09 06:20:00 +04:00
dprintk ( 1 , " %s(%u) \n " , __func__ , freq_hz ) ;
2007-12-18 07:55:51 +03:00
2007-12-20 07:14:43 +03:00
if ( ( freq_hz > xc5000_tuner_ops . info . frequency_max ) | |
( freq_hz < xc5000_tuner_ops . info . frequency_min ) )
2014-05-21 20:08:18 +04:00
return - EINVAL ;
2007-12-18 07:55:51 +03:00
2007-12-20 07:14:43 +03:00
freq_code = ( u16 ) ( freq_hz / 15625 ) ;
2009-04-03 05:40:29 +04:00
/* Starting in firmware version 1.1.44, Xceive recommends using the
FINERFREQ for all normal tuning ( the doc indicates reg 0x03 should
only be used for fast scanning for channel lock ) */
return xc_write_reg ( priv , XREG_FINERFREQ , freq_code ) ;
2007-12-18 07:55:51 +03:00
}
2007-12-20 07:14:43 +03:00
static int xc_set_IF_frequency ( struct xc5000_priv * priv , u32 freq_khz )
{
u32 freq_code = ( freq_khz * 1024 ) / 1000 ;
dprintk ( 1 , " %s(freq_khz = %d) freq_code = 0x%x \n " ,
2008-04-09 06:20:00 +04:00
__func__ , freq_khz , freq_code ) ;
2007-12-18 07:55:51 +03:00
2007-12-20 07:14:43 +03:00
return xc_write_reg ( priv , XREG_IF_OUT , freq_code ) ;
2007-12-18 07:55:51 +03:00
}
2014-05-21 20:23:27 +04:00
static int xc_get_adc_envelope ( struct xc5000_priv * priv , u16 * adc_envelope )
2007-12-18 07:55:51 +03:00
{
2008-11-17 02:17:14 +03:00
return xc5000_readreg ( priv , XREG_ADC_ENV , adc_envelope ) ;
2007-12-18 07:55:51 +03:00
}
2007-12-20 07:14:43 +03:00
static int xc_get_frequency_error ( struct xc5000_priv * priv , u32 * freq_error_hz )
2007-12-18 07:55:51 +03:00
{
int result ;
2014-05-21 20:23:27 +04:00
u16 reg_data ;
2007-12-18 07:55:51 +03:00
u32 tmp ;
2014-05-21 20:23:27 +04:00
result = xc5000_readreg ( priv , XREG_FREQ_ERROR , & reg_data ) ;
2014-05-21 20:08:18 +04:00
if ( result ! = 0 )
2007-12-18 07:55:51 +03:00
return result ;
2014-05-21 20:23:27 +04:00
tmp = ( u32 ) reg_data ;
2007-12-20 07:14:43 +03:00
( * freq_error_hz ) = ( tmp * 15625 ) / 1000 ;
2007-12-18 07:55:51 +03:00
return result ;
}
2007-12-20 07:14:43 +03:00
static int xc_get_lock_status ( struct xc5000_priv * priv , u16 * lock_status )
2007-12-18 07:55:51 +03:00
{
2008-11-17 02:17:14 +03:00
return xc5000_readreg ( priv , XREG_LOCK , lock_status ) ;
2007-12-18 07:55:51 +03:00
}
2007-12-20 07:14:43 +03:00
static int xc_get_version ( struct xc5000_priv * priv ,
u8 * hw_majorversion , u8 * hw_minorversion ,
u8 * fw_majorversion , u8 * fw_minorversion )
2007-12-18 07:55:51 +03:00
{
2007-12-20 07:14:43 +03:00
u16 data ;
2007-12-18 07:55:51 +03:00
int result ;
2008-11-17 02:17:14 +03:00
result = xc5000_readreg ( priv , XREG_VERSION , & data ) ;
2014-05-21 20:08:18 +04:00
if ( result ! = 0 )
2007-12-18 07:55:51 +03:00
return result ;
2007-12-20 07:14:43 +03:00
( * hw_majorversion ) = ( data > > 12 ) & 0x0F ;
( * hw_minorversion ) = ( data > > 8 ) & 0x0F ;
( * fw_majorversion ) = ( data > > 4 ) & 0x0F ;
( * fw_minorversion ) = data & 0x0F ;
2007-12-18 07:55:51 +03:00
return 0 ;
}
2009-04-03 05:24:38 +04:00
static int xc_get_buildversion ( struct xc5000_priv * priv , u16 * buildrev )
{
return xc5000_readreg ( priv , XREG_BUILD , buildrev ) ;
}
2007-12-20 07:14:43 +03:00
static int xc_get_hsync_freq ( struct xc5000_priv * priv , u32 * hsync_freq_hz )
2007-12-18 07:55:51 +03:00
{
2014-05-21 20:23:27 +04:00
u16 reg_data ;
2007-12-18 07:55:51 +03:00
int result ;
2014-05-21 20:23:27 +04:00
result = xc5000_readreg ( priv , XREG_HSYNC_FREQ , & reg_data ) ;
2014-05-21 20:08:18 +04:00
if ( result ! = 0 )
2007-12-18 07:55:51 +03:00
return result ;
2014-05-21 20:23:27 +04:00
( * hsync_freq_hz ) = ( ( reg_data & 0x0fff ) * 763 ) / 100 ;
2007-12-18 07:55:51 +03:00
return result ;
}
2007-12-20 07:14:43 +03:00
static int xc_get_frame_lines ( struct xc5000_priv * priv , u16 * frame_lines )
2007-12-18 07:55:51 +03:00
{
2008-11-17 02:17:14 +03:00
return xc5000_readreg ( priv , XREG_FRAME_LINES , frame_lines ) ;
2007-12-18 07:55:51 +03:00
}
2007-12-20 07:14:43 +03:00
static int xc_get_quality ( struct xc5000_priv * priv , u16 * quality )
2007-12-18 07:55:51 +03:00
{
2008-11-17 02:17:14 +03:00
return xc5000_readreg ( priv , XREG_QUALITY , quality ) ;
2007-12-18 07:55:51 +03:00
}
2012-08-07 05:46:56 +04:00
static int xc_get_analogsnr ( struct xc5000_priv * priv , u16 * snr )
{
return xc5000_readreg ( priv , XREG_SNR , snr ) ;
}
static int xc_get_totalgain ( struct xc5000_priv * priv , u16 * totalgain )
{
return xc5000_readreg ( priv , XREG_TOTALGAIN , totalgain ) ;
}
2014-05-21 20:23:27 +04:00
static u16 wait_for_lock ( struct xc5000_priv * priv )
2007-12-18 07:55:51 +03:00
{
2014-05-21 20:23:27 +04:00
u16 lock_state = 0 ;
int watch_dog_count = 40 ;
2007-12-20 07:14:43 +03:00
2014-05-21 20:23:27 +04:00
while ( ( lock_state = = 0 ) & & ( watch_dog_count > 0 ) ) {
xc_get_lock_status ( priv , & lock_state ) ;
if ( lock_state ! = 1 ) {
2014-05-21 20:15:17 +04:00
msleep ( 5 ) ;
2014-05-21 20:23:27 +04:00
watch_dog_count - - ;
2007-12-18 07:55:51 +03:00
}
}
2014-05-21 20:23:27 +04:00
return lock_state ;
2007-12-18 07:55:51 +03:00
}
2008-11-17 02:48:31 +03:00
# define XC_TUNE_ANALOG 0
# define XC_TUNE_DIGITAL 1
static int xc_tune_channel ( struct xc5000_priv * priv , u32 freq_hz , int mode )
2007-12-18 07:55:51 +03:00
{
int found = 0 ;
2008-04-09 06:20:00 +04:00
dprintk ( 1 , " %s(%u) \n " , __func__ , freq_hz ) ;
2007-12-18 07:55:51 +03:00
2014-05-21 20:23:27 +04:00
if ( xc_set_rf_frequency ( priv , freq_hz ) ! = 0 )
2007-12-18 07:55:51 +03:00
return 0 ;
2008-11-17 02:48:31 +03:00
if ( mode = = XC_TUNE_ANALOG ) {
2014-05-21 20:23:27 +04:00
if ( wait_for_lock ( priv ) = = 1 )
2008-11-17 02:48:31 +03:00
found = 1 ;
}
2007-12-18 07:55:51 +03:00
return found ;
}
2012-04-16 21:59:32 +04:00
static int xc_set_xtal ( struct dvb_frontend * fe )
{
struct xc5000_priv * priv = fe - > tuner_priv ;
2014-05-21 20:08:18 +04:00
int ret = 0 ;
2012-04-16 21:59:32 +04:00
switch ( priv - > chip_id ) {
default :
case XC5000A :
/* 32.000 MHz xtal is default */
break ;
case XC5000C :
switch ( priv - > xtal_khz ) {
default :
case 32000 :
/* 32.000 MHz xtal is default */
break ;
case 31875 :
/* 31.875 MHz xtal configuration */
ret = xc_write_reg ( priv , 0x000f , 0x8081 ) ;
break ;
}
break ;
}
return ret ;
}
2007-12-18 07:55:51 +03:00
2014-07-30 18:09:15 +04:00
static int xc5000_fwupload ( struct dvb_frontend * fe ,
const struct xc5000_fw_cfg * desired_fw ,
const struct firmware * fw )
2007-12-18 07:55:51 +03:00
{
struct xc5000_priv * priv = fe - > tuner_priv ;
int ret ;
2007-12-20 07:14:43 +03:00
/* request the firmware, this will block and timeout */
2014-07-30 18:09:15 +04:00
dprintk ( 1 , " waiting for firmware upload (%s)... \n " ,
2012-02-08 21:57:39 +04:00
desired_fw - > name ) ;
2007-12-20 07:14:43 +03:00
2014-07-30 18:09:15 +04:00
priv - > pll_register_no = desired_fw - > pll_reg ;
priv - > init_status_supported = desired_fw - > init_status_supported ;
priv - > fw_checksum_supported = desired_fw - > fw_checksum_supported ;
2007-12-18 07:55:51 +03:00
2014-07-30 18:09:15 +04:00
dprintk ( 1 , " firmware uploading... \n " ) ;
ret = xc_load_i2c_sequence ( fe , fw - > data ) ;
if ( ! ret ) {
ret = xc_set_xtal ( fe ) ;
dprintk ( 1 , " Firmware upload complete... \n " ) ;
} else
printk ( KERN_ERR " xc5000: firmware upload failed... \n " ) ;
2007-12-18 07:55:51 +03:00
return ret ;
}
2007-12-20 07:14:43 +03:00
static void xc_debug_dump ( struct xc5000_priv * priv )
2007-12-18 07:55:51 +03:00
{
2007-12-20 07:14:43 +03:00
u16 adc_envelope ;
u32 freq_error_hz = 0 ;
u16 lock_status ;
u32 hsync_freq_hz = 0 ;
u16 frame_lines ;
u16 quality ;
2012-08-07 05:46:56 +04:00
u16 snr ;
u16 totalgain ;
2007-12-20 07:14:43 +03:00
u8 hw_majorversion = 0 , hw_minorversion = 0 ;
u8 fw_majorversion = 0 , fw_minorversion = 0 ;
2009-04-03 05:24:38 +04:00
u16 fw_buildversion = 0 ;
2012-08-07 05:47:08 +04:00
u16 regval ;
2007-12-18 07:55:51 +03:00
/* Wait for stats to stabilize.
* Frame Lines needs two frame times after initial lock
* before it is valid .
*/
2014-05-21 20:15:17 +04:00
msleep ( 100 ) ;
2007-12-18 07:55:51 +03:00
2014-05-21 20:23:27 +04:00
xc_get_adc_envelope ( priv , & adc_envelope ) ;
2007-12-20 07:14:43 +03:00
dprintk ( 1 , " *** ADC envelope (0-1023) = %d \n " , adc_envelope ) ;
2007-12-18 07:55:51 +03:00
2007-12-20 07:14:43 +03:00
xc_get_frequency_error ( priv , & freq_error_hz ) ;
dprintk ( 1 , " *** Frequency error = %d Hz \n " , freq_error_hz ) ;
2007-12-18 07:55:51 +03:00
2007-12-20 07:14:43 +03:00
xc_get_lock_status ( priv , & lock_status ) ;
dprintk ( 1 , " *** Lock status (0-Wait, 1-Locked, 2-No-signal) = %d \n " ,
2007-12-18 07:55:51 +03:00
lock_status ) ;
xc_get_version ( priv , & hw_majorversion , & hw_minorversion ,
2007-12-20 07:14:43 +03:00
& fw_majorversion , & fw_minorversion ) ;
2009-04-03 05:24:38 +04:00
xc_get_buildversion ( priv , & fw_buildversion ) ;
2012-08-07 05:47:11 +04:00
dprintk ( 1 , " *** HW: V%d.%d, FW: V %d.%d.%d \n " ,
2007-12-18 07:55:51 +03:00
hw_majorversion , hw_minorversion ,
2009-04-03 05:24:38 +04:00
fw_majorversion , fw_minorversion , fw_buildversion ) ;
2007-12-18 07:55:51 +03:00
2007-12-20 07:14:43 +03:00
xc_get_hsync_freq ( priv , & hsync_freq_hz ) ;
dprintk ( 1 , " *** Horizontal sync frequency = %d Hz \n " , hsync_freq_hz ) ;
2007-12-18 07:55:51 +03:00
2007-12-20 07:14:43 +03:00
xc_get_frame_lines ( priv , & frame_lines ) ;
dprintk ( 1 , " *** Frame lines = %d \n " , frame_lines ) ;
2007-12-18 07:55:51 +03:00
2007-12-20 07:14:43 +03:00
xc_get_quality ( priv , & quality ) ;
2012-08-07 05:46:55 +04:00
dprintk ( 1 , " *** Quality (0:<8dB, 7:>56dB) = %d \n " , quality & 0x07 ) ;
2012-08-07 05:46:56 +04:00
xc_get_analogsnr ( priv , & snr ) ;
dprintk ( 1 , " *** Unweighted analog SNR = %d dB \n " , snr & 0x3f ) ;
xc_get_totalgain ( priv , & totalgain ) ;
dprintk ( 1 , " *** Total gain = %d.%d dB \n " , totalgain / 256 ,
( totalgain % 256 ) * 100 / 256 ) ;
2012-08-07 05:47:08 +04:00
if ( priv - > pll_register_no ) {
xc5000_readreg ( priv , priv - > pll_register_no , & regval ) ;
dprintk ( 1 , " *** PLL lock status = 0x%04x \n " , regval ) ;
}
2007-12-18 07:55:51 +03:00
}
2014-08-10 04:47:21 +04:00
static int xc5000_tune_digital ( struct dvb_frontend * fe )
{
struct xc5000_priv * priv = fe - > tuner_priv ;
int ret ;
u32 bw = fe - > dtv_property_cache . bandwidth_hz ;
ret = xc_set_signal_source ( priv , priv - > rf_mode ) ;
if ( ret ! = 0 ) {
printk ( KERN_ERR
" xc5000: xc_set_signal_source(%d) failed \n " ,
priv - > rf_mode ) ;
return - EREMOTEIO ;
}
ret = xc_set_tv_standard ( priv ,
xc5000_standard [ priv - > video_standard ] . video_mode ,
xc5000_standard [ priv - > video_standard ] . audio_mode , 0 ) ;
if ( ret ! = 0 ) {
printk ( KERN_ERR " xc5000: xc_set_tv_standard failed \n " ) ;
return - EREMOTEIO ;
}
ret = xc_set_IF_frequency ( priv , priv - > if_khz ) ;
if ( ret ! = 0 ) {
printk ( KERN_ERR " xc5000: xc_Set_IF_frequency(%d) failed \n " ,
priv - > if_khz ) ;
return - EIO ;
}
2014-10-26 00:17:22 +04:00
dprintk ( 1 , " %s() setting OUTPUT_AMP to 0x%x \n " ,
__func__ , priv - > output_amp ) ;
xc_write_reg ( priv , XREG_OUTPUT_AMP , priv - > output_amp ) ;
2014-08-10 04:47:21 +04:00
xc_tune_channel ( priv , priv - > freq_hz , XC_TUNE_DIGITAL ) ;
if ( debug )
xc_debug_dump ( priv ) ;
priv - > bandwidth = bw ;
return 0 ;
}
2014-08-10 04:47:24 +04:00
static int xc5000_set_digital_params ( struct dvb_frontend * fe )
2007-12-18 07:55:51 +03:00
{
2014-08-10 04:47:21 +04:00
int b ;
2007-12-18 07:55:51 +03:00
struct xc5000_priv * priv = fe - > tuner_priv ;
2011-12-18 03:36:57 +04:00
u32 bw = fe - > dtv_property_cache . bandwidth_hz ;
u32 freq = fe - > dtv_property_cache . frequency ;
u32 delsys = fe - > dtv_property_cache . delivery_system ;
2007-12-18 07:55:51 +03:00
2014-05-21 20:08:18 +04:00
if ( xc_load_fw_and_init_tuner ( fe , 0 ) ! = 0 ) {
2012-08-07 05:47:01 +04:00
dprintk ( 1 , " Unable to load firmware and init tuner \n " ) ;
return - EINVAL ;
2009-10-14 06:44:14 +04:00
}
2008-11-17 02:41:07 +03:00
2011-12-18 03:36:57 +04:00
dprintk ( 1 , " %s() frequency=%d (Hz) \n " , __func__ , freq ) ;
2007-12-18 07:55:51 +03:00
2011-12-18 03:36:57 +04:00
switch ( delsys ) {
case SYS_ATSC :
dprintk ( 1 , " %s() VSB modulation \n " , __func__ ) ;
priv - > rf_mode = XC_RF_MODE_AIR ;
2014-07-21 21:21:18 +04:00
priv - > freq_offset = 1750000 ;
2011-12-18 03:36:57 +04:00
priv - > video_standard = DTV6 ;
break ;
case SYS_DVBC_ANNEX_B :
dprintk ( 1 , " %s() QAM modulation \n " , __func__ ) ;
priv - > rf_mode = XC_RF_MODE_CABLE ;
2014-07-21 21:21:18 +04:00
priv - > freq_offset = 1750000 ;
2011-12-18 03:36:57 +04:00
priv - > video_standard = DTV6 ;
break ;
2012-07-05 21:07:59 +04:00
case SYS_ISDBT :
/* All ISDB-T are currently for 6 MHz bw */
if ( ! bw )
bw = 6000000 ;
/* fall to OFDM handling */
case SYS_DMBTH :
2011-12-18 03:36:57 +04:00
case SYS_DVBT :
case SYS_DVBT2 :
2009-05-05 05:59:58 +04:00
dprintk ( 1 , " %s() OFDM \n " , __func__ ) ;
2011-12-18 03:36:57 +04:00
switch ( bw ) {
case 6000000 :
2009-05-05 05:59:58 +04:00
priv - > video_standard = DTV6 ;
2014-07-21 21:21:18 +04:00
priv - > freq_offset = 1750000 ;
2009-05-05 05:59:58 +04:00
break ;
2011-12-18 03:36:57 +04:00
case 7000000 :
2011-12-09 14:01:01 +04:00
priv - > video_standard = DTV7 ;
2014-07-21 21:21:18 +04:00
priv - > freq_offset = 2250000 ;
2011-12-09 14:01:01 +04:00
break ;
2011-12-18 03:36:57 +04:00
case 8000000 :
2009-05-05 05:59:58 +04:00
priv - > video_standard = DTV8 ;
2014-07-21 21:21:18 +04:00
priv - > freq_offset = 2750000 ;
2009-05-05 05:59:58 +04:00
break ;
default :
printk ( KERN_ERR " xc5000 bandwidth not set! \n " ) ;
return - EINVAL ;
}
2007-12-18 07:55:51 +03:00
priv - > rf_mode = XC_RF_MODE_AIR ;
2013-01-13 22:31:33 +04:00
break ;
2011-12-18 03:36:57 +04:00
case SYS_DVBC_ANNEX_A :
case SYS_DVBC_ANNEX_C :
dprintk ( 1 , " %s() QAM modulation \n " , __func__ ) ;
priv - > rf_mode = XC_RF_MODE_CABLE ;
if ( bw < = 6000000 ) {
priv - > video_standard = DTV6 ;
2014-07-21 21:21:18 +04:00
priv - > freq_offset = 1750000 ;
2011-12-18 03:36:57 +04:00
b = 6 ;
} else if ( bw < = 7000000 ) {
priv - > video_standard = DTV7 ;
2014-07-21 21:21:18 +04:00
priv - > freq_offset = 2250000 ;
2011-12-18 03:36:57 +04:00
b = 7 ;
} else {
priv - > video_standard = DTV7_8 ;
2014-07-21 21:21:18 +04:00
priv - > freq_offset = 2750000 ;
2011-12-18 03:36:57 +04:00
b = 8 ;
2011-01-25 23:03:00 +03:00
}
2011-12-18 03:36:57 +04:00
dprintk ( 1 , " %s() Bandwidth %dMHz (%d) \n " , __func__ ,
b , bw ) ;
break ;
default :
printk ( KERN_ERR " xc5000: delivery system is not supported! \n " ) ;
2007-12-18 07:55:51 +03:00
return - EINVAL ;
}
2014-07-21 21:21:18 +04:00
priv - > freq_hz = freq - priv - > freq_offset ;
2014-08-10 04:47:21 +04:00
priv - > mode = V4L2_TUNER_DIGITAL_TV ;
2014-07-21 21:21:18 +04:00
2011-12-18 03:36:57 +04:00
dprintk ( 1 , " %s() frequency=%d (compensated to %d) \n " ,
__func__ , freq , priv - > freq_hz ) ;
2007-12-18 07:55:51 +03:00
2014-08-10 04:47:21 +04:00
return xc5000_tune_digital ( fe ) ;
2007-12-18 07:55:51 +03:00
}
2008-06-22 04:06:02 +04:00
static int xc5000_is_firmware_loaded ( struct dvb_frontend * fe )
{
struct xc5000_priv * priv = fe - > tuner_priv ;
int ret ;
u16 id ;
ret = xc5000_readreg ( priv , XREG_PRODUCT_ID , & id ) ;
2014-05-21 20:08:18 +04:00
if ( ret = = 0 ) {
2008-06-22 04:06:02 +04:00
if ( id = = XC_PRODUCT_ID_FW_NOT_LOADED )
2014-05-21 20:08:18 +04:00
ret = - ENOENT ;
2008-06-22 04:06:02 +04:00
else
2014-05-21 20:08:18 +04:00
ret = 0 ;
2008-06-22 04:06:02 +04:00
}
dprintk ( 1 , " %s() returns %s id = 0x%x \n " , __func__ ,
2014-05-21 20:08:18 +04:00
ret = = 0 ? " True " : " False " , id ) ;
2008-06-22 04:06:02 +04:00
return ret ;
}
2014-08-10 04:47:22 +04:00
static void xc5000_config_tv ( struct dvb_frontend * fe ,
struct analog_parameters * params )
2008-01-05 22:50:14 +03:00
{
struct xc5000_priv * priv = fe - > tuner_priv ;
dprintk ( 1 , " %s() frequency=%d (in units of 62.5khz) \n " ,
2008-04-09 06:20:00 +04:00
__func__ , params - > frequency ) ;
2008-01-05 22:50:14 +03:00
2009-03-03 20:35:41 +03:00
/* Fix me: it could be air. */
priv - > rf_mode = params - > mode ;
if ( params - > mode > XC_RF_MODE_CABLE )
priv - > rf_mode = XC_RF_MODE_CABLE ;
2008-01-05 22:50:14 +03:00
/* params->frequency is in units of 62.5khz */
priv - > freq_hz = params - > frequency * 62500 ;
/* FIX ME: Some video standards may have several possible audio
standards . We simply default to one of them here .
*/
2008-10-17 03:29:38 +04:00
if ( params - > std & V4L2_STD_MN ) {
2008-01-05 22:50:14 +03:00
/* default to BTSC audio standard */
priv - > video_standard = MN_NTSC_PAL_BTSC ;
2014-08-10 04:47:22 +04:00
return ;
2008-01-05 22:50:14 +03:00
}
2008-10-17 03:29:38 +04:00
if ( params - > std & V4L2_STD_PAL_BG ) {
2008-01-05 22:50:14 +03:00
/* default to NICAM audio standard */
priv - > video_standard = BG_PAL_NICAM ;
2014-08-10 04:47:22 +04:00
return ;
2008-01-05 22:50:14 +03:00
}
2008-10-17 03:29:38 +04:00
if ( params - > std & V4L2_STD_PAL_I ) {
2008-01-05 22:50:14 +03:00
/* default to NICAM audio standard */
priv - > video_standard = I_PAL_NICAM ;
2014-08-10 04:47:22 +04:00
return ;
2008-01-05 22:50:14 +03:00
}
2008-10-17 03:29:38 +04:00
if ( params - > std & V4L2_STD_PAL_DK ) {
2008-01-05 22:50:14 +03:00
/* default to NICAM audio standard */
priv - > video_standard = DK_PAL_NICAM ;
2014-08-10 04:47:22 +04:00
return ;
2008-01-05 22:50:14 +03:00
}
2008-10-17 03:29:38 +04:00
if ( params - > std & V4L2_STD_SECAM_DK ) {
2008-01-05 22:50:14 +03:00
/* default to A2 DK1 audio standard */
priv - > video_standard = DK_SECAM_A2DK1 ;
2014-08-10 04:47:22 +04:00
return ;
2008-01-05 22:50:14 +03:00
}
2008-10-17 03:29:38 +04:00
if ( params - > std & V4L2_STD_SECAM_L ) {
2008-01-05 22:50:14 +03:00
priv - > video_standard = L_SECAM_NICAM ;
2014-08-10 04:47:22 +04:00
return ;
2008-01-05 22:50:14 +03:00
}
2008-10-17 03:29:38 +04:00
if ( params - > std & V4L2_STD_SECAM_LC ) {
2008-01-05 22:50:14 +03:00
priv - > video_standard = LC_SECAM_NICAM ;
2014-08-10 04:47:22 +04:00
return ;
2008-01-05 22:50:14 +03:00
}
2014-08-10 04:47:22 +04:00
}
static int xc5000_set_tv_freq ( struct dvb_frontend * fe )
{
struct xc5000_priv * priv = fe - > tuner_priv ;
u16 pll_lock_status ;
int ret ;
2008-01-05 22:50:14 +03:00
tune_channel :
2014-05-21 20:23:27 +04:00
ret = xc_set_signal_source ( priv , priv - > rf_mode ) ;
2014-05-21 20:08:18 +04:00
if ( ret ! = 0 ) {
2008-10-17 03:29:38 +04:00
printk ( KERN_ERR
2014-05-21 20:23:27 +04:00
" xc5000: xc_set_signal_source(%d) failed \n " ,
2008-01-05 22:50:14 +03:00
priv - > rf_mode ) ;
return - EREMOTEIO ;
}
2014-05-21 20:23:27 +04:00
ret = xc_set_tv_standard ( priv ,
xc5000_standard [ priv - > video_standard ] . video_mode ,
xc5000_standard [ priv - > video_standard ] . audio_mode , 0 ) ;
2014-05-21 20:08:18 +04:00
if ( ret ! = 0 ) {
2014-05-21 20:23:27 +04:00
printk ( KERN_ERR " xc5000: xc_set_tv_standard failed \n " ) ;
2008-01-05 22:50:14 +03:00
return - EREMOTEIO ;
}
2011-02-01 11:25:19 +03:00
xc_write_reg ( priv , XREG_OUTPUT_AMP , 0x09 ) ;
2008-11-17 02:48:31 +03:00
xc_tune_channel ( priv , priv - > freq_hz , XC_TUNE_ANALOG ) ;
2008-01-05 22:50:14 +03:00
if ( debug )
xc_debug_dump ( priv ) ;
2012-08-07 05:47:08 +04:00
if ( priv - > pll_register_no ! = 0 ) {
msleep ( 20 ) ;
xc5000_readreg ( priv , priv - > pll_register_no , & pll_lock_status ) ;
if ( pll_lock_status > 63 ) {
/* PLL is unlocked, force reload of the firmware */
dprintk ( 1 , " xc5000: PLL not locked (0x%x). Reloading... \n " ,
pll_lock_status ) ;
2014-05-21 20:08:18 +04:00
if ( xc_load_fw_and_init_tuner ( fe , 1 ) ! = 0 ) {
2012-08-07 05:47:08 +04:00
printk ( KERN_ERR " xc5000: Unable to reload fw \n " ) ;
return - EREMOTEIO ;
}
goto tune_channel ;
}
}
2008-01-05 22:50:14 +03:00
return 0 ;
}
2014-08-10 04:47:22 +04:00
static int xc5000_config_radio ( struct dvb_frontend * fe ,
struct analog_parameters * params )
2009-09-24 20:13:28 +04:00
{
struct xc5000_priv * priv = fe - > tuner_priv ;
dprintk ( 1 , " %s() frequency=%d (in units of khz) \n " ,
__func__ , params - > frequency ) ;
2009-09-24 20:27:24 +04:00
if ( priv - > radio_input = = XC5000_RADIO_NOT_CONFIGURED ) {
dprintk ( 1 , " %s() radio input not configured \n " , __func__ ) ;
return - EINVAL ;
}
2014-08-10 04:47:22 +04:00
priv - > freq_hz = params - > frequency * 125 / 2 ;
priv - > rf_mode = XC_RF_MODE_AIR ;
return 0 ;
}
static int xc5000_set_radio_freq ( struct dvb_frontend * fe )
{
struct xc5000_priv * priv = fe - > tuner_priv ;
int ret ;
u8 radio_input ;
2009-09-24 20:27:24 +04:00
if ( priv - > radio_input = = XC5000_RADIO_FM1 )
2014-05-21 20:23:27 +04:00
radio_input = FM_RADIO_INPUT1 ;
2009-09-24 20:27:24 +04:00
else if ( priv - > radio_input = = XC5000_RADIO_FM2 )
2014-05-21 20:23:27 +04:00
radio_input = FM_RADIO_INPUT2 ;
2011-02-01 11:25:19 +03:00
else if ( priv - > radio_input = = XC5000_RADIO_FM1_MONO )
2014-05-21 20:23:27 +04:00
radio_input = FM_RADIO_INPUT1_MONO ;
2009-09-24 20:27:24 +04:00
else {
dprintk ( 1 , " %s() unknown radio input %d \n " , __func__ ,
priv - > radio_input ) ;
return - EINVAL ;
}
2014-05-21 20:23:27 +04:00
ret = xc_set_tv_standard ( priv , xc5000_standard [ radio_input ] . video_mode ,
xc5000_standard [ radio_input ] . audio_mode , radio_input ) ;
2009-09-24 20:13:28 +04:00
2014-05-21 20:08:18 +04:00
if ( ret ! = 0 ) {
2014-05-21 20:23:27 +04:00
printk ( KERN_ERR " xc5000: xc_set_tv_standard failed \n " ) ;
2009-09-24 20:13:28 +04:00
return - EREMOTEIO ;
}
2014-05-21 20:23:27 +04:00
ret = xc_set_signal_source ( priv , priv - > rf_mode ) ;
2014-05-21 20:08:18 +04:00
if ( ret ! = 0 ) {
2009-09-24 20:13:28 +04:00
printk ( KERN_ERR
2014-05-21 20:23:27 +04:00
" xc5000: xc_set_signal_source(%d) failed \n " ,
2009-09-24 20:13:28 +04:00
priv - > rf_mode ) ;
return - EREMOTEIO ;
}
2011-02-01 11:25:19 +03:00
if ( ( priv - > radio_input = = XC5000_RADIO_FM1 ) | |
( priv - > radio_input = = XC5000_RADIO_FM2 ) )
xc_write_reg ( priv , XREG_OUTPUT_AMP , 0x09 ) ;
else if ( priv - > radio_input = = XC5000_RADIO_FM1_MONO )
xc_write_reg ( priv , XREG_OUTPUT_AMP , 0x06 ) ;
2009-09-24 20:13:28 +04:00
xc_tune_channel ( priv , priv - > freq_hz , XC_TUNE_ANALOG ) ;
return 0 ;
}
2014-08-10 04:47:24 +04:00
static int xc5000_set_params ( struct dvb_frontend * fe )
2014-08-10 04:47:22 +04:00
{
struct xc5000_priv * priv = fe - > tuner_priv ;
2014-08-10 06:14:22 +04:00
if ( xc_load_fw_and_init_tuner ( fe , 0 ) ! = 0 ) {
dprintk ( 1 , " Unable to load firmware and init tuner \n " ) ;
return - EINVAL ;
}
2014-08-10 04:47:22 +04:00
switch ( priv - > mode ) {
case V4L2_TUNER_RADIO :
return xc5000_set_radio_freq ( fe ) ;
case V4L2_TUNER_ANALOG_TV :
return xc5000_set_tv_freq ( fe ) ;
case V4L2_TUNER_DIGITAL_TV :
return xc5000_tune_digital ( fe ) ;
}
return 0 ;
}
2009-09-24 20:13:28 +04:00
static int xc5000_set_analog_params ( struct dvb_frontend * fe ,
struct analog_parameters * params )
{
struct xc5000_priv * priv = fe - > tuner_priv ;
2014-08-10 04:47:22 +04:00
int ret ;
2009-09-24 20:13:28 +04:00
if ( priv - > i2c_props . adap = = NULL )
return - EINVAL ;
switch ( params - > mode ) {
case V4L2_TUNER_RADIO :
2014-08-10 04:47:22 +04:00
ret = xc5000_config_radio ( fe , params ) ;
if ( ret )
return ret ;
2009-09-24 20:13:28 +04:00
break ;
case V4L2_TUNER_ANALOG_TV :
2014-08-10 04:47:22 +04:00
xc5000_config_tv ( fe , params ) ;
break ;
default :
2009-09-24 20:13:28 +04:00
break ;
}
2014-08-10 04:47:22 +04:00
priv - > mode = params - > mode ;
2009-09-24 20:13:28 +04:00
2014-08-10 04:47:24 +04:00
return xc5000_set_params ( fe ) ;
2009-09-24 20:13:28 +04:00
}
2007-12-18 07:55:51 +03:00
static int xc5000_get_frequency ( struct dvb_frontend * fe , u32 * freq )
{
struct xc5000_priv * priv = fe - > tuner_priv ;
2008-04-09 06:20:00 +04:00
dprintk ( 1 , " %s() \n " , __func__ ) ;
2014-07-21 21:21:18 +04:00
* freq = priv - > freq_hz + priv - > freq_offset ;
2007-12-18 07:55:51 +03:00
return 0 ;
}
2011-09-23 20:03:42 +04:00
static int xc5000_get_if_frequency ( struct dvb_frontend * fe , u32 * freq )
{
struct xc5000_priv * priv = fe - > tuner_priv ;
dprintk ( 1 , " %s() \n " , __func__ ) ;
* freq = priv - > if_khz * 1000 ;
return 0 ;
}
2007-12-18 07:55:51 +03:00
static int xc5000_get_bandwidth ( struct dvb_frontend * fe , u32 * bw )
{
struct xc5000_priv * priv = fe - > tuner_priv ;
2008-04-09 06:20:00 +04:00
dprintk ( 1 , " %s() \n " , __func__ ) ;
2008-01-05 22:50:14 +03:00
2007-12-18 07:55:51 +03:00
* bw = priv - > bandwidth ;
return 0 ;
}
static int xc5000_get_status ( struct dvb_frontend * fe , u32 * status )
{
struct xc5000_priv * priv = fe - > tuner_priv ;
2007-12-20 07:14:43 +03:00
u16 lock_status = 0 ;
2007-12-18 07:55:51 +03:00
xc_get_lock_status ( priv , & lock_status ) ;
2008-04-09 06:20:00 +04:00
dprintk ( 1 , " %s() lock_status = 0x%08x \n " , __func__ , lock_status ) ;
2007-12-18 07:55:51 +03:00
* status = lock_status ;
return 0 ;
}
2012-08-07 05:47:08 +04:00
static int xc_load_fw_and_init_tuner ( struct dvb_frontend * fe , int force )
2007-12-18 07:55:51 +03:00
{
struct xc5000_priv * priv = fe - > tuner_priv ;
2014-07-30 18:09:15 +04:00
const struct xc5000_fw_cfg * desired_fw = xc5000_assign_firmware ( priv - > chip_id ) ;
const struct firmware * fw ;
2014-07-30 17:36:32 +04:00
int ret , i ;
2012-08-07 05:47:08 +04:00
u16 pll_lock_status ;
2012-08-07 05:47:09 +04:00
u16 fw_ck ;
2012-08-07 05:47:08 +04:00
2014-05-21 20:57:30 +04:00
cancel_delayed_work ( & priv - > timer_sleep ) ;
2014-07-30 17:36:32 +04:00
if ( ! force & & xc5000_is_firmware_loaded ( fe ) = = 0 )
return 0 ;
2007-12-18 07:55:51 +03:00
2014-09-23 04:30:46 +04:00
if ( ! priv - > firmware ) {
ret = request_firmware ( & fw , desired_fw - > name ,
priv - > i2c_props . adap - > dev . parent ) ;
if ( ret ) {
pr_err ( " xc5000: Upload failed. rc %d \n " , ret ) ;
return ret ;
}
dprintk ( 1 , " firmware read %Zu bytes. \n " , fw - > size ) ;
2014-07-30 18:09:15 +04:00
2014-09-23 04:30:46 +04:00
if ( fw - > size ! = desired_fw - > size ) {
pr_err ( " xc5000: Firmware file with incorrect size \n " ) ;
release_firmware ( fw ) ;
return - EINVAL ;
}
priv - > firmware = fw ;
} else
fw = priv - > firmware ;
2014-07-30 18:09:15 +04:00
2014-07-30 17:36:32 +04:00
/* Try up to 5 times to load firmware */
for ( i = 0 ; i < 5 ; i + + ) {
2014-07-30 18:17:46 +04:00
if ( i )
printk ( KERN_CONT " - retrying to upload firmware. \n " ) ;
2014-07-30 18:09:15 +04:00
ret = xc5000_fwupload ( fe , desired_fw , fw ) ;
2014-05-21 20:08:18 +04:00
if ( ret ! = 0 )
2014-07-30 18:09:15 +04:00
goto err ;
2007-12-18 07:55:51 +03:00
2012-08-07 05:47:08 +04:00
msleep ( 20 ) ;
2012-08-07 05:47:09 +04:00
if ( priv - > fw_checksum_supported ) {
2014-07-30 17:36:32 +04:00
if ( xc5000_readreg ( priv , XREG_FW_CHECKSUM , & fw_ck ) ) {
2014-07-30 18:17:46 +04:00
printk ( KERN_ERR
" xc5000: FW checksum reading failed. " ) ;
2014-07-30 17:36:32 +04:00
continue ;
2012-08-07 05:47:09 +04:00
}
2014-07-30 17:36:32 +04:00
if ( ! fw_ck ) {
2014-07-30 18:17:46 +04:00
printk ( KERN_ERR
" xc5000: FW checksum failed = 0x%04x. " ,
fw_ck ) ;
2014-07-30 17:36:32 +04:00
continue ;
2012-08-07 05:47:09 +04:00
}
}
2012-08-07 05:47:01 +04:00
/* Start the tuner self-calibration process */
2014-07-30 17:36:32 +04:00
ret = xc_initialize ( priv ) ;
if ( ret ) {
2014-07-30 18:17:46 +04:00
printk ( KERN_ERR
" xc5000: Can't request Self-callibration. " ) ;
2014-07-30 17:36:32 +04:00
continue ;
}
2012-08-07 05:47:08 +04:00
2012-08-07 05:47:01 +04:00
/* Wait for calibration to complete.
* We could continue but XC5000 will clock stretch subsequent
* I2C transactions until calibration is complete . This way we
* don ' t have to rely on clock stretching working .
*/
2014-05-21 20:15:17 +04:00
msleep ( 100 ) ;
2007-12-18 07:55:51 +03:00
2012-08-07 05:47:09 +04:00
if ( priv - > init_status_supported ) {
2014-07-30 17:36:32 +04:00
if ( xc5000_readreg ( priv , XREG_INIT_STATUS , & fw_ck ) ) {
2014-07-30 18:17:46 +04:00
printk ( KERN_ERR
" xc5000: FW failed reading init status. " ) ;
2014-07-30 17:36:32 +04:00
continue ;
2012-08-07 05:47:09 +04:00
}
2014-07-30 17:36:32 +04:00
if ( ! fw_ck ) {
2014-07-30 18:17:46 +04:00
printk ( KERN_ERR
" xc5000: FW init status failed = 0x%04x. " ,
fw_ck ) ;
2014-07-30 17:36:32 +04:00
continue ;
2012-08-07 05:47:09 +04:00
}
}
2012-08-07 05:47:08 +04:00
if ( priv - > pll_register_no ) {
xc5000_readreg ( priv , priv - > pll_register_no ,
& pll_lock_status ) ;
if ( pll_lock_status > 63 ) {
/* PLL is unlocked, force reload of the firmware */
2014-07-30 18:17:46 +04:00
printk ( KERN_ERR
" xc5000: PLL not running after fwload. " ) ;
2014-07-30 17:36:32 +04:00
continue ;
2012-08-07 05:47:08 +04:00
}
}
2012-08-07 05:47:01 +04:00
/* Default to "CABLE" mode */
2014-07-30 17:36:32 +04:00
ret = xc_write_reg ( priv , XREG_SIGNALSOURCE , XC_RF_MODE_CABLE ) ;
2014-07-30 18:17:46 +04:00
if ( ! ret )
break ;
printk ( KERN_ERR " xc5000: can't set to cable mode. " ) ;
2012-08-07 05:47:01 +04:00
}
2007-12-18 07:55:51 +03:00
2014-07-30 18:09:15 +04:00
err :
2014-07-30 18:17:46 +04:00
if ( ! ret )
printk ( KERN_INFO " xc5000: Firmware %s loaded and running. \n " ,
desired_fw - > name ) ;
else
printk ( KERN_CONT " - too many retries. Giving up \n " ) ;
2007-12-18 07:55:51 +03:00
return ret ;
}
2014-05-21 20:57:30 +04:00
static void xc5000_do_timer_sleep ( struct work_struct * timer_sleep )
2007-12-20 07:14:43 +03:00
{
2014-05-21 20:57:30 +04:00
struct xc5000_priv * priv = container_of ( timer_sleep , struct xc5000_priv ,
timer_sleep . work ) ;
struct dvb_frontend * fe = priv - > fe ;
2008-01-05 22:50:14 +03:00
int ret ;
2008-04-09 06:20:00 +04:00
dprintk ( 1 , " %s() \n " , __func__ ) ;
2007-12-20 07:14:43 +03:00
2009-04-03 05:02:39 +04:00
/* According to Xceive technical support, the "powerdown" register
was removed in newer versions of the firmware . The " supported "
way to sleep the tuner is to pull the reset pin low for 10 ms */
2014-05-21 20:23:27 +04:00
ret = xc5000_tuner_reset ( fe ) ;
2014-05-21 20:57:30 +04:00
if ( ret ! = 0 )
2008-01-05 22:50:14 +03:00
printk ( KERN_ERR
" xc5000: %s() unable to shutdown tuner \n " ,
2008-04-09 06:20:00 +04:00
__func__ ) ;
2014-05-21 20:57:30 +04:00
}
static int xc5000_sleep ( struct dvb_frontend * fe )
{
struct xc5000_priv * priv = fe - > tuner_priv ;
dprintk ( 1 , " %s() \n " , __func__ ) ;
/* Avoid firmware reload on slow devices */
if ( no_poweroff )
2014-05-21 20:08:18 +04:00
return 0 ;
2014-05-21 20:57:30 +04:00
schedule_delayed_work ( & priv - > timer_sleep ,
msecs_to_jiffies ( XC5000_SLEEP_TIME ) ) ;
return 0 ;
2007-12-20 07:14:43 +03:00
}
2014-08-10 04:47:20 +04:00
static int xc5000_suspend ( struct dvb_frontend * fe )
{
struct xc5000_priv * priv = fe - > tuner_priv ;
int ret ;
dprintk ( 1 , " %s() \n " , __func__ ) ;
cancel_delayed_work ( & priv - > timer_sleep ) ;
ret = xc5000_tuner_reset ( fe ) ;
if ( ret ! = 0 )
printk ( KERN_ERR
" xc5000: %s() unable to shutdown tuner \n " ,
__func__ ) ;
return 0 ;
}
2014-08-14 05:09:24 +04:00
static int xc5000_resume ( struct dvb_frontend * fe )
{
struct xc5000_priv * priv = fe - > tuner_priv ;
dprintk ( 1 , " %s() \n " , __func__ ) ;
/* suspended before firmware is loaded.
Avoid firmware load in resume path . */
if ( ! priv - > firmware )
return 0 ;
return xc5000_set_params ( fe ) ;
}
2007-12-18 07:55:51 +03:00
static int xc5000_init ( struct dvb_frontend * fe )
{
struct xc5000_priv * priv = fe - > tuner_priv ;
2008-04-09 06:20:00 +04:00
dprintk ( 1 , " %s() \n " , __func__ ) ;
2007-12-18 07:55:51 +03:00
2014-05-21 20:08:18 +04:00
if ( xc_load_fw_and_init_tuner ( fe , 0 ) ! = 0 ) {
2007-12-20 07:14:43 +03:00
printk ( KERN_ERR " xc5000: Unable to initialise tuner \n " ) ;
return - EREMOTEIO ;
}
if ( debug )
xc_debug_dump ( priv ) ;
2007-12-18 07:55:51 +03:00
return 0 ;
}
static int xc5000_release ( struct dvb_frontend * fe )
{
2008-09-06 18:44:53 +04:00
struct xc5000_priv * priv = fe - > tuner_priv ;
2008-04-09 06:20:00 +04:00
dprintk ( 1 , " %s() \n " , __func__ ) ;
2008-09-06 18:44:53 +04:00
mutex_lock ( & xc5000_list_mutex ) ;
2014-05-21 20:57:30 +04:00
if ( priv ) {
cancel_delayed_work ( & priv - > timer_sleep ) ;
2014-09-23 04:30:46 +04:00
if ( priv - > firmware ) {
release_firmware ( priv - > firmware ) ;
priv - > firmware = NULL ;
}
2014-09-25 15:40:08 +04:00
hybrid_tuner_release_state ( priv ) ;
2014-05-21 20:57:30 +04:00
}
2008-09-06 18:44:53 +04:00
mutex_unlock ( & xc5000_list_mutex ) ;
2007-12-18 07:55:51 +03:00
fe - > tuner_priv = NULL ;
2008-09-06 18:44:53 +04:00
2007-12-18 07:55:51 +03:00
return 0 ;
}
2011-02-01 11:25:19 +03:00
static int xc5000_set_config ( struct dvb_frontend * fe , void * priv_cfg )
{
struct xc5000_priv * priv = fe - > tuner_priv ;
struct xc5000_config * p = priv_cfg ;
dprintk ( 1 , " %s() \n " , __func__ ) ;
if ( p - > if_khz )
priv - > if_khz = p - > if_khz ;
if ( p - > radio_input )
priv - > radio_input = p - > radio_input ;
2014-10-26 00:17:22 +04:00
if ( p - > output_amp )
priv - > output_amp = p - > output_amp ;
2011-02-01 11:25:19 +03:00
return 0 ;
}
2007-12-18 07:55:51 +03:00
static const struct dvb_tuner_ops xc5000_tuner_ops = {
. info = {
. name = " Xceive XC5000 " ,
. frequency_min = 1000000 ,
. frequency_max = 1023000000 ,
. frequency_step = 50000 ,
} ,
2008-01-05 22:50:14 +03:00
. release = xc5000_release ,
. init = xc5000_init ,
. sleep = xc5000_sleep ,
2014-08-10 04:47:20 +04:00
. suspend = xc5000_suspend ,
2014-08-14 05:09:24 +04:00
. resume = xc5000_resume ,
2007-12-18 07:55:51 +03:00
2011-02-01 11:25:19 +03:00
. set_config = xc5000_set_config ,
2014-08-10 04:47:24 +04:00
. set_params = xc5000_set_digital_params ,
2008-01-05 22:50:14 +03:00
. set_analog_params = xc5000_set_analog_params ,
. get_frequency = xc5000_get_frequency ,
2011-09-23 20:03:42 +04:00
. get_if_frequency = xc5000_get_if_frequency ,
2008-01-05 22:50:14 +03:00
. get_bandwidth = xc5000_get_bandwidth ,
. get_status = xc5000_get_status
2007-12-18 07:55:51 +03:00
} ;
2008-05-10 21:34:09 +04:00
struct dvb_frontend * xc5000_attach ( struct dvb_frontend * fe ,
struct i2c_adapter * i2c ,
2010-08-25 16:50:20 +04:00
const struct xc5000_config * cfg )
2007-12-18 07:55:51 +03:00
{
struct xc5000_priv * priv = NULL ;
2008-09-06 18:44:53 +04:00
int instance ;
2007-12-18 07:55:51 +03:00
u16 id = 0 ;
2008-09-06 18:44:53 +04:00
dprintk ( 1 , " %s(%d-%04x) \n " , __func__ ,
i2c ? i2c_adapter_id ( i2c ) : - 1 ,
cfg ? cfg - > i2c_address : - 1 ) ;
2007-12-18 07:55:51 +03:00
2008-09-06 18:44:53 +04:00
mutex_lock ( & xc5000_list_mutex ) ;
2007-12-18 07:55:51 +03:00
2008-09-06 18:44:53 +04:00
instance = hybrid_tuner_request_state ( struct xc5000_priv , priv ,
hybrid_tuner_instance_list ,
i2c , cfg - > i2c_address , " xc5000 " ) ;
switch ( instance ) {
case 0 :
goto fail ;
case 1 :
/* new tuner instance */
2011-12-27 03:02:28 +04:00
priv - > bandwidth = 6000000 ;
2008-09-06 18:44:53 +04:00
fe - > tuner_priv = priv ;
2014-05-21 20:57:30 +04:00
priv - > fe = fe ;
INIT_DELAYED_WORK ( & priv - > timer_sleep , xc5000_do_timer_sleep ) ;
2008-09-06 18:44:53 +04:00
break ;
default :
/* existing tuner instance */
fe - > tuner_priv = priv ;
break ;
}
2007-12-18 07:55:51 +03:00
2009-03-11 08:58:53 +03:00
if ( priv - > if_khz = = 0 ) {
/* If the IF hasn't been set yet, use the value provided by
the caller ( occurs in hybrid devices where the analog
call to xc5000_attach occurs before the digital side ) */
priv - > if_khz = cfg - > if_khz ;
}
2012-04-16 21:59:32 +04:00
if ( priv - > xtal_khz = = 0 )
priv - > xtal_khz = cfg - > xtal_khz ;
2009-09-24 20:27:24 +04:00
if ( priv - > radio_input = = 0 )
priv - > radio_input = cfg - > radio_input ;
2012-02-08 21:57:39 +04:00
/* don't override chip id if it's already been set
2012-02-07 02:40:32 +04:00
unless explicitly specified */
2012-02-08 21:57:39 +04:00
if ( ( priv - > chip_id = = 0 ) | | ( cfg - > chip_id ) )
/* use default chip id if none specified, set to 0 so
it can be overridden if this is a hybrid driver */
priv - > chip_id = ( cfg - > chip_id ) ? cfg - > chip_id : 0 ;
2012-02-07 02:40:32 +04:00
2014-10-26 00:17:22 +04:00
/* don't override output_amp if it's already been set
unless explicitly specified */
if ( ( priv - > output_amp = = 0 ) | | ( cfg - > output_amp ) )
/* use default output_amp value if none specified */
priv - > output_amp = ( cfg - > output_amp ) ? cfg - > output_amp : 0x8a ;
2008-01-05 22:50:14 +03:00
/* Check if firmware has been loaded. It is possible that another
instance of the driver has loaded the firmware .
*/
2014-05-21 20:08:18 +04:00
if ( xc5000_readreg ( priv , XREG_PRODUCT_ID , & id ) ! = 0 )
2008-09-06 18:44:53 +04:00
goto fail ;
2007-12-18 07:55:51 +03:00
2008-10-17 03:29:38 +04:00
switch ( id ) {
2008-01-05 22:50:14 +03:00
case XC_PRODUCT_ID_FW_LOADED :
printk ( KERN_INFO
" xc5000: Successfully identified at address 0x%02x \n " ,
cfg - > i2c_address ) ;
printk ( KERN_INFO
" xc5000: Firmware has been loaded previously \n " ) ;
break ;
case XC_PRODUCT_ID_FW_NOT_LOADED :
printk ( KERN_INFO
" xc5000: Successfully identified at address 0x%02x \n " ,
cfg - > i2c_address ) ;
printk ( KERN_INFO
" xc5000: Firmware has not been loaded previously \n " ) ;
break ;
default :
2007-12-18 07:55:51 +03:00
printk ( KERN_ERR
" xc5000: Device not found at addr 0x%02x (0x%x) \n " ,
cfg - > i2c_address , id ) ;
2008-09-06 18:44:53 +04:00
goto fail ;
2007-12-18 07:55:51 +03:00
}
2008-09-06 18:44:53 +04:00
mutex_unlock ( & xc5000_list_mutex ) ;
2007-12-18 07:55:51 +03:00
memcpy ( & fe - > ops . tuner_ops , & xc5000_tuner_ops ,
sizeof ( struct dvb_tuner_ops ) ) ;
return fe ;
2008-09-06 18:44:53 +04:00
fail :
mutex_unlock ( & xc5000_list_mutex ) ;
xc5000_release ( fe ) ;
return NULL ;
2007-12-18 07:55:51 +03:00
}
EXPORT_SYMBOL ( xc5000_attach ) ;
MODULE_AUTHOR ( " Steven Toth " ) ;
2007-12-20 07:14:43 +03:00
MODULE_DESCRIPTION ( " Xceive xc5000 silicon tuner driver " ) ;
2007-12-18 07:55:51 +03:00
MODULE_LICENSE ( " GPL " ) ;
2012-07-25 16:15:19 +04:00
MODULE_FIRMWARE ( XC5000A_FIRMWARE ) ;
MODULE_FIRMWARE ( XC5000C_FIRMWARE ) ;