1645 lines
44 KiB
C
1645 lines
44 KiB
C
/*
|
|
TDA18272 Silicon tuner driver
|
|
Copyright (C) Manu Abraham <abraham.manu@gmail.com>
|
|
|
|
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 02139, USA.
|
|
*/
|
|
|
|
#include <linux/init.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/string.h>
|
|
|
|
#include "dvb_frontend.h"
|
|
|
|
#include "tda18272.h"
|
|
#include "tda18272_reg.h"
|
|
|
|
#define __TDA18272_SETFIELD(mask, bitf, val) \
|
|
(mask = (mask & (~(((1 << TDA18272_WIDTH_##bitf) - 1) << \
|
|
TDA18272_OFFST_##bitf))) | \
|
|
(val << TDA18272_OFFST_##bitf))
|
|
|
|
#define __TDA18272_GETFIELD(bitf, val) \
|
|
((val >> TDA18272_OFFST_##bitf) & \
|
|
((1 << TDA18272_WIDTH_##bitf) - 1))
|
|
|
|
#define TDA18272_SETFIELD(regs, REG_NAME, FIELD, val) \
|
|
__TDA18272_SETFIELD(regs[TDA18272_##REG_NAME], \
|
|
REG_NAME##_##FIELD, val)
|
|
|
|
#define TDA18272_GETFIELD(regs, REG_NAME, FIELD) \
|
|
__TDA18272_GETFIELD(REG_NAME##_##FIELD, \
|
|
regs[TDA18272_##REG_NAME])
|
|
|
|
enum tda18272_lpf {
|
|
TDA18272_LPF_6MHz = 0,
|
|
TDA18272_LPF_7MHz,
|
|
TDA18272_LPF_8MHz,
|
|
TDA18272_LPF_9MHz,
|
|
TDA18272_LPF_1_5MHz
|
|
};
|
|
|
|
enum tda18272_lpf_offset {
|
|
TDA18272_LPFOFFSET_0PC = 0,
|
|
TDA18272_LPFOFFSET_4PC,
|
|
TDA18272_LPFOFFSET_8PC,
|
|
TDA18272_LPFOFFSET_12PC
|
|
};
|
|
|
|
enum tda18272_agcgain {
|
|
TDA18272_AGCGAIN_2VPP = 0,
|
|
TDA18272_AGCGAIN_1_25VPP,
|
|
TDA18272_AGCGAIN_1VPP,
|
|
TDA18272_AGCGAIN_0_8VPP,
|
|
TDA18272_AGCGAIN_0_85VPP,
|
|
TDA18272_AGCGAIN_0_7VPP,
|
|
TDA18272_AGCGAIN_0_6VPP,
|
|
TDA18272_AGCGAIN_0_5VPP
|
|
};
|
|
|
|
enum tda18272_notch {
|
|
TDA18272_NOTCH_DISABLED = 0,
|
|
TDA18272_NOTCH_ENABLED,
|
|
};
|
|
|
|
enum tda18272_hpf {
|
|
TDA18272_HPF_DISABLED = 0,
|
|
TDA18272_HPF_0_4MHz,
|
|
TDA18272_HPF_0_85MHz,
|
|
TDA18272_HPF_1MHz,
|
|
TDA18272_HPF_1_5Mhz
|
|
};
|
|
|
|
enum tda18272_lnatop {
|
|
TDA18272_LNATOP_95_89 = 0,
|
|
TDA18272_LNATOP_95_93, /* unused */
|
|
TDA18272_LNATOP_95_94, /* unused */
|
|
TDA18272_LNATOP_95_95, /* unused */
|
|
TDA18272_LNATOP_99_89,
|
|
TDA18272_LNATOP_99_93,
|
|
TDA18272_LNATOP_99_94,
|
|
TDA18272_LNATOP_99_95,
|
|
TDA18272_LNATOP_99_95s,
|
|
TDA18272_LNATOP_100_93,
|
|
TDA18272_LNATOP_100_94,
|
|
TDA18272_LNATOP_100_95,
|
|
TDA18272_LNATOP_100_95s,
|
|
TDA18272_LNATOP_101_93d,
|
|
TDA18272_LNATOP_101_94d,
|
|
TDA18272_LNATOP_101_95,
|
|
TDA18272_LNATOP_101_95s,
|
|
};
|
|
|
|
enum tda18272_rfatttop {
|
|
TDA18272_RFATTTOP_89_81 = 0,
|
|
TDA18272_RFATTTOP_91_83,
|
|
TDA18272_RFATTTOP_93_85,
|
|
TDA18272_RFATTTOP_95_87,
|
|
TDA18272_RFATTTOP_88_88,
|
|
TDA18272_RFATTTOP_89_82,
|
|
TDA18272_RFATTTOP_90_83,
|
|
TDA18272_RFATTTOP_91_84,
|
|
TDA18272_RFATTTOP_92_85,
|
|
TDA18272_RFATTTOP_93_86,
|
|
TDA18272_RFATTTOP_94_87,
|
|
TDA18272_RFATTTOP_95_88,
|
|
TDA18272_RFATTTOP_87_81,
|
|
TDA18272_RFATTTOP_88_82,
|
|
TDA18272_RFATTTOP_89_83,
|
|
TDA18272_RFATTTOP_90_84,
|
|
TDA18272_RFATTTOP_91_85,
|
|
TDA18272_RFATTTOP_92_86,
|
|
TDA18272_RFATTTOP_93_87,
|
|
TDA18272_RFATTTOP_94_88,
|
|
TDA18272_RFATTTOP_95_89,
|
|
};
|
|
|
|
|
|
#define TDA18272_AGC3_RF_AGC_TOP_FREQ_LIM 291000000
|
|
|
|
enum tda18272_rfagctop {
|
|
TDA18272_RFAGCTOP_94 = 0,
|
|
TDA18272_RFAGCTOP_96,
|
|
TDA18272_RFAGCTOP_98,
|
|
TDA18272_RFAGCTOP_100,
|
|
TDA18272_RFAGCTOP_102,
|
|
TDA18272_RFAGCTOP_104,
|
|
TDA18272_RFAGCTOP_106,
|
|
TDA18272_RFAGCTOP_107,
|
|
};
|
|
|
|
enum tda18272_irmixtop {
|
|
TDA18272_IRMIXTOP_105_99 = 0,
|
|
TDA18272_IRMIXTOP_105_100,
|
|
TDA18272_IRMIXTOP_105_101,
|
|
TDA18272_IRMIXTOP_107_101,
|
|
TDA18272_IRMIXTOP_107_102,
|
|
TDA18272_IRMIXTOP_107_103,
|
|
TDA18272_IRMIXTOP_108_103,
|
|
TDA18272_IRMIXTOP_109_103,
|
|
TDA18272_IRMIXTOP_109_104,
|
|
TDA18272_IRMIXTOP_109_105,
|
|
TDA18272_IRMIXTOP_110_104,
|
|
TDA18272_IRMIXTOP_110_105,
|
|
TDA18272_IRMIXTOP_110_106,
|
|
TDA18272_IRMIXTOP_112_106,
|
|
TDA18272_IRMIXTOP_112_107,
|
|
TDA18272_IRMIXTOP_112_108,
|
|
};
|
|
|
|
enum tda18272_ifagctop {
|
|
TDA18272_IFAGCTOP_105_99 = 0,
|
|
TDA18272_IFAGCTOP_105_100,
|
|
TDA18272_IFAGCTOP_105_101,
|
|
TDA18272_IFAGCTOP_107_101,
|
|
TDA18272_IFAGCTOP_107_102,
|
|
TDA18272_IFAGCTOP_107_103,
|
|
TDA18272_IFAGCTOP_108_103,
|
|
TDA18272_IFAGCTOP_109_103,
|
|
TDA18272_IFAGCTOP_109_104,
|
|
TDA18272_IFAGCTOP_109_105,
|
|
TDA18272_IFAGCTOP_110_104,
|
|
TDA18272_IFAGCTOP_110_105,
|
|
TDA18272_IFAGCTOP_110_106,
|
|
TDA18272_IFAGCTOP_112_106,
|
|
TDA18272_IFAGCTOP_112_107,
|
|
TDA18272_IFAGCTOP_112_108,
|
|
};
|
|
|
|
enum tda18272_dethpf {
|
|
TDA18272_DETHPF_DISABLED = 0,
|
|
TDA18272_DETHPF_ENABLED
|
|
};
|
|
|
|
enum tda18272_agc3adapt {
|
|
TDA18272_AGC3ADAPT_ENABLED = 0,
|
|
TDA18272_AGC3ADAPT_DISABLED,
|
|
};
|
|
|
|
enum tda18272_agc3adapt_top {
|
|
TDA18272_AGC3ADAPT_TOP_0 = 0,
|
|
TDA18272_AGC3ADAPT_TOP_1,
|
|
TDA18272_AGC3ADAPT_TOP_2,
|
|
TDA18272_AGC3ADAPT_TOP_3
|
|
};
|
|
|
|
enum tda18272_3dbatt {
|
|
TDA18272_3DBATT_DISABLED = 0,
|
|
TDA18272_3DBATT_ENABLED,
|
|
};
|
|
|
|
|
|
enum tda18272_vhffilt6 {
|
|
TDA18272_VHFFILT6_DISABLED = 0,
|
|
TDA18272_VHFFILT6_ENABLED,
|
|
};
|
|
|
|
enum tda18272_lpfgain {
|
|
TDA18272_LPFGAIN_UNKNOWN = 0,
|
|
TDA18272_LPFGAIN_FROZEN,
|
|
TDA18272_LPFGAIN_FREE
|
|
};
|
|
|
|
|
|
enum tda18272_stdmode {
|
|
TDA18272_DVBT_6MHz = 0,
|
|
TDA18272_DVBT_7MHz,
|
|
TDA18272_DVBT_8MHz,
|
|
TDA18272_QAM_6MHz,
|
|
TDA18272_QAM_8MHz,
|
|
TDA18272_ISDBT_6MHz,
|
|
TDA18272_ATSC_6MHz,
|
|
TDA18272_DMBT_8MHz,
|
|
TDA18272_ANLG_MN,
|
|
TDA18272_ANLG_B,
|
|
TDA18272_ANLG_GH,
|
|
TDA18272_ANLG_I,
|
|
TDA18272_ANLG_DK,
|
|
TDA18272_ANLG_L,
|
|
TDA18272_ANLG_LL,
|
|
TDA18272_FM_RADIO,
|
|
TDA18272_Scanning,
|
|
TDA18272_ScanXpress,
|
|
};
|
|
|
|
static struct tda18272_coeff {
|
|
u8 desc[16];
|
|
u32 if_val;
|
|
s32 cf_off;
|
|
enum tda18272_lpf lpf;
|
|
enum tda18272_lpf_offset lpf_off;
|
|
enum tda18272_agcgain if_gain;
|
|
enum tda18272_notch if_notch;
|
|
enum tda18272_hpf if_hpf;
|
|
enum tda18272_notch dc_notch;
|
|
enum tda18272_lnatop lna_top;
|
|
enum tda18272_rfatttop rfatt_top;
|
|
enum tda18272_rfagctop loband_rfagc_top;
|
|
enum tda18272_rfagctop hiband_rfagc_top;
|
|
enum tda18272_irmixtop irmix_top;
|
|
enum tda18272_ifagctop ifagc_top;
|
|
enum tda18272_dethpf det_hpf;
|
|
enum tda18272_agc3adapt agc3_adapt;
|
|
enum tda18272_agc3adapt_top agc3_adapt_top;
|
|
|
|
enum tda18272_3dbatt att3db;
|
|
u8 gsk;
|
|
enum tda18272_vhffilt6 filter;
|
|
enum tda18272_lpfgain lpf_gain;
|
|
int agc1_freeze;
|
|
int ltosto_immune;
|
|
} coeft[] = {
|
|
{
|
|
.desc = "DVB-T 6MHz",
|
|
.if_val = 3250000,
|
|
.cf_off = 0,
|
|
.lpf = TDA18272_LPF_6MHz,
|
|
.lpf_off = TDA18272_LPFOFFSET_0PC,
|
|
.if_gain = TDA18272_AGCGAIN_1VPP,
|
|
.if_notch = TDA18272_NOTCH_ENABLED,
|
|
.if_hpf = TDA18272_HPF_0_4MHz,
|
|
.dc_notch = TDA18272_NOTCH_ENABLED,
|
|
.lna_top = TDA18272_LNATOP_95_89,
|
|
.rfatt_top = TDA18272_RFATTTOP_90_84,
|
|
.loband_rfagc_top = TDA18272_RFAGCTOP_100,
|
|
.hiband_rfagc_top = TDA18272_RFAGCTOP_102,
|
|
.irmix_top = TDA18272_IRMIXTOP_110_105,
|
|
.ifagc_top = TDA18272_IFAGCTOP_110_105,
|
|
.det_hpf = TDA18272_DETHPF_DISABLED,
|
|
.agc3_adapt = TDA18272_AGC3ADAPT_ENABLED,
|
|
.agc3_adapt_top = TDA18272_AGC3ADAPT_TOP_2,
|
|
.att3db = TDA18272_3DBATT_ENABLED,
|
|
.gsk = 0x02,
|
|
.filter = TDA18272_VHFFILT6_ENABLED,
|
|
.lpf_gain = TDA18272_LPFGAIN_FREE,
|
|
.agc1_freeze = 0,
|
|
.ltosto_immune = 0
|
|
}, {
|
|
.desc = "DVB-T 7MHz",
|
|
.if_val = 3500000,
|
|
.cf_off = 0,
|
|
.lpf = TDA18272_LPF_7MHz,
|
|
.lpf_off = TDA18272_LPFOFFSET_8PC,
|
|
.if_gain = TDA18272_AGCGAIN_1VPP,
|
|
.if_notch = TDA18272_NOTCH_ENABLED,
|
|
.if_hpf = TDA18272_HPF_DISABLED,
|
|
.dc_notch = TDA18272_NOTCH_ENABLED,
|
|
.lna_top = TDA18272_LNATOP_95_89,
|
|
.rfatt_top = TDA18272_RFATTTOP_90_84,
|
|
.loband_rfagc_top = TDA18272_RFAGCTOP_100,
|
|
.hiband_rfagc_top = TDA18272_RFAGCTOP_102,
|
|
.irmix_top = TDA18272_IRMIXTOP_110_105,
|
|
.ifagc_top = TDA18272_IFAGCTOP_110_105,
|
|
.det_hpf = TDA18272_DETHPF_DISABLED,
|
|
.agc3_adapt = TDA18272_AGC3ADAPT_ENABLED,
|
|
.agc3_adapt_top = TDA18272_AGC3ADAPT_TOP_2,
|
|
.att3db = TDA18272_3DBATT_ENABLED,
|
|
.gsk = 0x02,
|
|
.filter = TDA18272_VHFFILT6_ENABLED,
|
|
.lpf_gain = TDA18272_LPFGAIN_FREE,
|
|
.agc1_freeze = 0,
|
|
.ltosto_immune = 0
|
|
}, {
|
|
.desc = "DVB-T 8MHz",
|
|
.if_val = 4000000,
|
|
.cf_off = 0,
|
|
.lpf = TDA18272_LPF_8MHz,
|
|
.lpf_off = TDA18272_LPFOFFSET_0PC,
|
|
.if_gain = TDA18272_AGCGAIN_1VPP,
|
|
.if_notch = TDA18272_NOTCH_ENABLED,
|
|
.if_hpf = TDA18272_HPF_DISABLED,
|
|
.dc_notch = TDA18272_NOTCH_ENABLED,
|
|
.lna_top = TDA18272_LNATOP_95_89,
|
|
.rfatt_top = TDA18272_RFATTTOP_90_84,
|
|
.loband_rfagc_top = TDA18272_RFAGCTOP_100,
|
|
.hiband_rfagc_top = TDA18272_RFAGCTOP_102,
|
|
.irmix_top = TDA18272_IRMIXTOP_110_105,
|
|
.ifagc_top = TDA18272_IFAGCTOP_110_105,
|
|
.det_hpf = TDA18272_DETHPF_DISABLED,
|
|
.agc3_adapt = TDA18272_AGC3ADAPT_ENABLED,
|
|
.agc3_adapt_top = TDA18272_AGC3ADAPT_TOP_2,
|
|
.att3db = TDA18272_3DBATT_ENABLED,
|
|
.gsk = 0x02,
|
|
.filter = TDA18272_VHFFILT6_ENABLED,
|
|
.lpf_gain = TDA18272_LPFGAIN_FREE,
|
|
.agc1_freeze = 0,
|
|
.ltosto_immune = 0
|
|
}, {
|
|
.desc = "QAM 6MHz",
|
|
.if_val = 3600000,
|
|
.cf_off = 0,
|
|
.lpf = TDA18272_LPF_6MHz,
|
|
.lpf_off = TDA18272_LPFOFFSET_8PC,
|
|
.if_gain = TDA18272_AGCGAIN_1VPP,
|
|
.if_notch = TDA18272_NOTCH_DISABLED,
|
|
.if_hpf = TDA18272_HPF_DISABLED,
|
|
.dc_notch = TDA18272_NOTCH_ENABLED,
|
|
.lna_top = TDA18272_LNATOP_95_89,
|
|
.rfatt_top = TDA18272_RFATTTOP_90_84,
|
|
.loband_rfagc_top = TDA18272_RFAGCTOP_100,
|
|
.hiband_rfagc_top = TDA18272_RFAGCTOP_100,
|
|
.irmix_top = TDA18272_IRMIXTOP_110_105,
|
|
.ifagc_top = TDA18272_IFAGCTOP_110_105,
|
|
.det_hpf = TDA18272_DETHPF_DISABLED,
|
|
.agc3_adapt = TDA18272_AGC3ADAPT_DISABLED,
|
|
.agc3_adapt_top = TDA18272_AGC3ADAPT_TOP_0,
|
|
.att3db = TDA18272_3DBATT_DISABLED,
|
|
.gsk = 0x02,
|
|
.filter = TDA18272_VHFFILT6_DISABLED,
|
|
.lpf_gain = TDA18272_LPFGAIN_FREE,
|
|
.agc1_freeze = 1,
|
|
.ltosto_immune = 1
|
|
}, {
|
|
.desc = "QAM 8MHz",
|
|
.if_val = 5000000,
|
|
.cf_off = 0,
|
|
.lpf = TDA18272_LPF_9MHz,
|
|
.lpf_off = TDA18272_LPFOFFSET_8PC,
|
|
.if_gain = TDA18272_AGCGAIN_1VPP,
|
|
.if_notch = TDA18272_NOTCH_DISABLED,
|
|
.if_hpf = TDA18272_HPF_0_85MHz,
|
|
.dc_notch = TDA18272_NOTCH_ENABLED,
|
|
.lna_top = TDA18272_LNATOP_95_89,
|
|
.rfatt_top = TDA18272_RFATTTOP_90_84,
|
|
.loband_rfagc_top = TDA18272_RFAGCTOP_100,
|
|
.hiband_rfagc_top = TDA18272_RFAGCTOP_100,
|
|
.irmix_top = TDA18272_IRMIXTOP_110_105,
|
|
.ifagc_top = TDA18272_IFAGCTOP_110_105,
|
|
.det_hpf = TDA18272_DETHPF_DISABLED,
|
|
.agc3_adapt = TDA18272_AGC3ADAPT_DISABLED,
|
|
.agc3_adapt_top = TDA18272_AGC3ADAPT_TOP_0,
|
|
.att3db = TDA18272_3DBATT_DISABLED,
|
|
.gsk = 0x02,
|
|
.filter = TDA18272_VHFFILT6_DISABLED,
|
|
.lpf_gain = TDA18272_LPFGAIN_FREE,
|
|
.agc1_freeze = 1,
|
|
.ltosto_immune = 1
|
|
}, {
|
|
.desc = "ISDB-T 6MHz",
|
|
.if_val = 3250000,
|
|
.cf_off = 0,
|
|
.lpf = TDA18272_LPF_6MHz,
|
|
.lpf_off = TDA18272_LPFOFFSET_0PC,
|
|
.if_gain = TDA18272_AGCGAIN_0_6VPP,
|
|
.if_notch = TDA18272_NOTCH_ENABLED,
|
|
.if_hpf = TDA18272_HPF_0_4MHz,
|
|
.dc_notch = TDA18272_NOTCH_ENABLED,
|
|
.lna_top = TDA18272_LNATOP_95_89,
|
|
.rfatt_top = TDA18272_RFATTTOP_90_84,
|
|
.loband_rfagc_top = TDA18272_RFAGCTOP_100,
|
|
.hiband_rfagc_top = TDA18272_RFAGCTOP_102,
|
|
.irmix_top = TDA18272_IRMIXTOP_110_105,
|
|
.ifagc_top = TDA18272_IFAGCTOP_110_105,
|
|
.det_hpf = TDA18272_DETHPF_DISABLED,
|
|
.agc3_adapt = TDA18272_AGC3ADAPT_ENABLED,
|
|
.agc3_adapt_top = TDA18272_AGC3ADAPT_TOP_2,
|
|
.att3db = TDA18272_3DBATT_ENABLED,
|
|
.gsk = 0x02,
|
|
.filter = TDA18272_VHFFILT6_ENABLED,
|
|
.lpf_gain = TDA18272_LPFGAIN_FREE,
|
|
.agc1_freeze = 0,
|
|
.ltosto_immune = 0
|
|
}, {
|
|
.desc = "ATSC 6MHz",
|
|
.if_val = 3250000,
|
|
.cf_off = 0,
|
|
.lpf = TDA18272_LPF_6MHz,
|
|
.lpf_off = TDA18272_LPFOFFSET_0PC,
|
|
.if_gain = TDA18272_AGCGAIN_0_6VPP,
|
|
.if_notch = TDA18272_NOTCH_ENABLED,
|
|
.if_hpf = TDA18272_HPF_0_4MHz,
|
|
.dc_notch = TDA18272_NOTCH_ENABLED,
|
|
.lna_top = TDA18272_LNATOP_100_94,
|
|
.rfatt_top = TDA18272_RFATTTOP_90_84,
|
|
.loband_rfagc_top = TDA18272_RFAGCTOP_104,
|
|
.hiband_rfagc_top = TDA18272_RFAGCTOP_104,
|
|
.irmix_top = TDA18272_IRMIXTOP_112_107,
|
|
.ifagc_top = TDA18272_IFAGCTOP_112_107,
|
|
.det_hpf = TDA18272_DETHPF_DISABLED,
|
|
.agc3_adapt = TDA18272_AGC3ADAPT_ENABLED,
|
|
.agc3_adapt_top = TDA18272_AGC3ADAPT_TOP_3,
|
|
.att3db = TDA18272_3DBATT_ENABLED,
|
|
.gsk = 0x02,
|
|
.filter = TDA18272_VHFFILT6_ENABLED,
|
|
.lpf_gain = TDA18272_LPFGAIN_FREE,
|
|
.agc1_freeze = 0,
|
|
.ltosto_immune = 0
|
|
}, {
|
|
.desc = "DMB-T 8MHz",
|
|
.if_val = 4000000,
|
|
.cf_off = 0,
|
|
.lpf = TDA18272_LPF_8MHz,
|
|
.lpf_off = TDA18272_LPFOFFSET_0PC,
|
|
.if_gain = TDA18272_AGCGAIN_1VPP,
|
|
.if_notch = TDA18272_NOTCH_ENABLED,
|
|
.if_hpf = TDA18272_HPF_DISABLED,
|
|
.dc_notch = TDA18272_NOTCH_ENABLED,
|
|
.lna_top = TDA18272_LNATOP_95_89,
|
|
.rfatt_top = TDA18272_RFATTTOP_90_84,
|
|
.loband_rfagc_top = TDA18272_RFAGCTOP_100,
|
|
.hiband_rfagc_top = TDA18272_RFAGCTOP_102,
|
|
.irmix_top = TDA18272_IRMIXTOP_110_105,
|
|
.ifagc_top = TDA18272_IFAGCTOP_110_105,
|
|
.det_hpf = TDA18272_DETHPF_DISABLED,
|
|
.agc3_adapt = TDA18272_AGC3ADAPT_ENABLED,
|
|
.agc3_adapt_top = TDA18272_AGC3ADAPT_TOP_2,
|
|
.att3db = TDA18272_3DBATT_ENABLED,
|
|
.gsk = 0x02,
|
|
.filter = TDA18272_VHFFILT6_ENABLED,
|
|
.lpf_gain = TDA18272_LPFGAIN_FREE,
|
|
.agc1_freeze = 0,
|
|
.ltosto_immune = 0
|
|
}, {
|
|
.desc = "ATV M/N",
|
|
.if_val = 5400000,
|
|
.cf_off = 1750000,
|
|
.lpf = TDA18272_LPF_6MHz,
|
|
.lpf_off = TDA18272_LPFOFFSET_0PC,
|
|
.if_gain = TDA18272_AGCGAIN_0_7VPP,
|
|
.if_notch = TDA18272_NOTCH_DISABLED,
|
|
.if_hpf = TDA18272_HPF_DISABLED,
|
|
.dc_notch = TDA18272_NOTCH_DISABLED,
|
|
.lna_top = TDA18272_LNATOP_95_89,
|
|
.rfatt_top = TDA18272_RFATTTOP_90_84,
|
|
.loband_rfagc_top = TDA18272_RFAGCTOP_96,
|
|
.hiband_rfagc_top = TDA18272_RFAGCTOP_96,
|
|
.irmix_top = TDA18272_IRMIXTOP_105_100,
|
|
.ifagc_top = TDA18272_IFAGCTOP_105_100,
|
|
.det_hpf = TDA18272_DETHPF_ENABLED,
|
|
.agc3_adapt = TDA18272_AGC3ADAPT_DISABLED,
|
|
.agc3_adapt_top = TDA18272_AGC3ADAPT_TOP_0,
|
|
.att3db = TDA18272_3DBATT_DISABLED,
|
|
.gsk = 0x01,
|
|
.filter = TDA18272_VHFFILT6_DISABLED,
|
|
.lpf_gain = TDA18272_LPFGAIN_FROZEN,
|
|
.agc1_freeze = 0,
|
|
.ltosto_immune = 0
|
|
}, {
|
|
.desc = "ATV B",
|
|
.if_val = 6400000,
|
|
.cf_off = 2250000,
|
|
.lpf = TDA18272_LPF_7MHz,
|
|
.lpf_off = TDA18272_LPFOFFSET_0PC,
|
|
.if_gain = TDA18272_AGCGAIN_0_7VPP,
|
|
.if_notch = TDA18272_NOTCH_DISABLED,
|
|
.if_hpf = TDA18272_HPF_DISABLED,
|
|
.dc_notch = TDA18272_NOTCH_DISABLED,
|
|
.lna_top = TDA18272_LNATOP_95_89,
|
|
.rfatt_top = TDA18272_RFATTTOP_90_84,
|
|
.loband_rfagc_top = TDA18272_RFAGCTOP_96,
|
|
.hiband_rfagc_top = TDA18272_RFAGCTOP_96,
|
|
.irmix_top = TDA18272_IRMIXTOP_105_100,
|
|
.ifagc_top = TDA18272_IFAGCTOP_105_100,
|
|
.det_hpf = TDA18272_DETHPF_ENABLED,
|
|
.agc3_adapt = TDA18272_AGC3ADAPT_DISABLED,
|
|
.agc3_adapt_top = TDA18272_AGC3ADAPT_TOP_0,
|
|
.att3db = TDA18272_3DBATT_DISABLED,
|
|
.gsk = 0x01,
|
|
.filter = TDA18272_VHFFILT6_DISABLED,
|
|
.lpf_gain = TDA18272_LPFGAIN_FROZEN,
|
|
.agc1_freeze = 0,
|
|
.ltosto_immune = 0
|
|
}, {
|
|
.desc = "ATV G/H",
|
|
.if_val = 6750000,
|
|
.cf_off = 2750000,
|
|
.lpf = TDA18272_LPF_8MHz,
|
|
.lpf_off = TDA18272_LPFOFFSET_0PC,
|
|
.if_gain = TDA18272_AGCGAIN_0_7VPP,
|
|
.if_notch = TDA18272_NOTCH_DISABLED,
|
|
.if_hpf = TDA18272_HPF_DISABLED,
|
|
.dc_notch = TDA18272_NOTCH_DISABLED,
|
|
.lna_top = TDA18272_LNATOP_95_89,
|
|
.rfatt_top = TDA18272_RFATTTOP_90_84,
|
|
.loband_rfagc_top = TDA18272_RFAGCTOP_96,
|
|
.hiband_rfagc_top = TDA18272_RFAGCTOP_96,
|
|
.irmix_top = TDA18272_IRMIXTOP_105_100,
|
|
.ifagc_top = TDA18272_IFAGCTOP_105_100,
|
|
.det_hpf = TDA18272_DETHPF_ENABLED,
|
|
.agc3_adapt = TDA18272_AGC3ADAPT_DISABLED,
|
|
.agc3_adapt_top = TDA18272_AGC3ADAPT_TOP_0,
|
|
.att3db = TDA18272_3DBATT_DISABLED,
|
|
.gsk = 0x01,
|
|
.filter = TDA18272_VHFFILT6_DISABLED,
|
|
.lpf_gain = TDA18272_LPFGAIN_FROZEN,
|
|
.agc1_freeze = 0,
|
|
.ltosto_immune = 0
|
|
}, {
|
|
.desc = "ATV I",
|
|
.if_val = 7250000,
|
|
.cf_off = 2750000,
|
|
.lpf = TDA18272_LPF_8MHz,
|
|
.lpf_off = TDA18272_LPFOFFSET_0PC,
|
|
.if_gain = TDA18272_AGCGAIN_0_7VPP,
|
|
.if_notch = TDA18272_NOTCH_DISABLED,
|
|
.if_hpf = TDA18272_HPF_DISABLED,
|
|
.dc_notch = TDA18272_NOTCH_DISABLED,
|
|
.lna_top = TDA18272_LNATOP_95_89,
|
|
.rfatt_top = TDA18272_RFATTTOP_90_84,
|
|
.loband_rfagc_top = TDA18272_RFAGCTOP_96,
|
|
.hiband_rfagc_top = TDA18272_RFAGCTOP_96,
|
|
.irmix_top = TDA18272_IRMIXTOP_105_100,
|
|
.ifagc_top = TDA18272_IFAGCTOP_105_100,
|
|
.det_hpf = TDA18272_DETHPF_ENABLED,
|
|
.agc3_adapt = TDA18272_AGC3ADAPT_DISABLED,
|
|
.agc3_adapt_top = TDA18272_AGC3ADAPT_TOP_0,
|
|
.att3db = TDA18272_3DBATT_DISABLED,
|
|
.gsk = 0x01,
|
|
.filter = TDA18272_VHFFILT6_DISABLED,
|
|
.lpf_gain = TDA18272_LPFGAIN_FROZEN,
|
|
.agc1_freeze = 0,
|
|
.ltosto_immune = 0
|
|
}, {
|
|
.desc = "ATV DK",
|
|
.if_val = 6850000,
|
|
.cf_off = 2750000,
|
|
.lpf = TDA18272_LPF_8MHz,
|
|
.lpf_off = TDA18272_LPFOFFSET_0PC,
|
|
.if_gain = TDA18272_AGCGAIN_0_7VPP,
|
|
.if_notch = TDA18272_NOTCH_ENABLED,
|
|
.if_hpf = TDA18272_HPF_DISABLED,
|
|
.dc_notch = TDA18272_NOTCH_DISABLED,
|
|
.lna_top = TDA18272_LNATOP_95_89,
|
|
.rfatt_top = TDA18272_RFATTTOP_90_84,
|
|
.loband_rfagc_top = TDA18272_RFAGCTOP_96,
|
|
.hiband_rfagc_top = TDA18272_RFAGCTOP_96,
|
|
.irmix_top = TDA18272_IRMIXTOP_105_100,
|
|
.ifagc_top = TDA18272_IFAGCTOP_105_100,
|
|
.det_hpf = TDA18272_DETHPF_ENABLED,
|
|
.agc3_adapt = TDA18272_AGC3ADAPT_DISABLED,
|
|
.agc3_adapt_top = TDA18272_AGC3ADAPT_TOP_0,
|
|
.att3db = TDA18272_3DBATT_DISABLED,
|
|
.gsk = 0x01,
|
|
.filter = TDA18272_VHFFILT6_DISABLED,
|
|
.lpf_gain = TDA18272_LPFGAIN_FROZEN,
|
|
.agc1_freeze = 0,
|
|
.ltosto_immune = 0
|
|
}, {
|
|
.desc = "ATV L",
|
|
.if_val = 6750000,
|
|
.cf_off = 2750000,
|
|
.lpf = TDA18272_LPF_8MHz,
|
|
.lpf_off = TDA18272_LPFOFFSET_0PC,
|
|
.if_gain = TDA18272_AGCGAIN_0_7VPP,
|
|
.if_notch = TDA18272_NOTCH_ENABLED,
|
|
.if_hpf = TDA18272_HPF_DISABLED,
|
|
.dc_notch = TDA18272_NOTCH_DISABLED,
|
|
.lna_top = TDA18272_LNATOP_95_89,
|
|
.rfatt_top = TDA18272_RFATTTOP_90_84,
|
|
.loband_rfagc_top = TDA18272_RFAGCTOP_96,
|
|
.hiband_rfagc_top = TDA18272_RFAGCTOP_96,
|
|
.irmix_top = TDA18272_IRMIXTOP_105_100,
|
|
.ifagc_top = TDA18272_IFAGCTOP_105_100,
|
|
.det_hpf = TDA18272_DETHPF_ENABLED,
|
|
.agc3_adapt = TDA18272_AGC3ADAPT_DISABLED,
|
|
.agc3_adapt_top = TDA18272_AGC3ADAPT_TOP_0,
|
|
.att3db = TDA18272_3DBATT_DISABLED,
|
|
.gsk = 0x01,
|
|
.filter = TDA18272_VHFFILT6_DISABLED,
|
|
.lpf_gain = TDA18272_LPFGAIN_FROZEN,
|
|
.agc1_freeze = 0,
|
|
.ltosto_immune = 0
|
|
}, {
|
|
.desc = "ATV Lc",
|
|
.if_val = 1250000,
|
|
.cf_off = -2750000,
|
|
.lpf = TDA18272_LPF_8MHz,
|
|
.lpf_off = TDA18272_LPFOFFSET_0PC,
|
|
.if_gain = TDA18272_AGCGAIN_0_7VPP,
|
|
.if_notch = TDA18272_NOTCH_DISABLED,
|
|
.if_hpf = TDA18272_HPF_DISABLED,
|
|
.dc_notch = TDA18272_NOTCH_DISABLED,
|
|
.lna_top = TDA18272_LNATOP_95_89,
|
|
.rfatt_top = TDA18272_RFATTTOP_90_84,
|
|
.loband_rfagc_top = TDA18272_RFAGCTOP_96,
|
|
.hiband_rfagc_top = TDA18272_RFAGCTOP_96,
|
|
.irmix_top = TDA18272_IRMIXTOP_105_100,
|
|
.ifagc_top = TDA18272_IFAGCTOP_105_100,
|
|
.det_hpf = TDA18272_DETHPF_DISABLED,
|
|
.agc3_adapt = TDA18272_AGC3ADAPT_DISABLED,
|
|
.agc3_adapt_top = TDA18272_AGC3ADAPT_TOP_0,
|
|
.att3db = TDA18272_3DBATT_DISABLED,
|
|
.gsk = 0x01,
|
|
.filter = TDA18272_VHFFILT6_DISABLED,
|
|
.lpf_gain = TDA18272_LPFGAIN_FROZEN,
|
|
.agc1_freeze = 0,
|
|
.ltosto_immune = 0
|
|
}, {
|
|
.desc = "FM Radio",
|
|
.if_val = 1250000,
|
|
.cf_off = 0,
|
|
.lpf = TDA18272_LPF_1_5MHz,
|
|
.lpf_off = TDA18272_LPFOFFSET_0PC,
|
|
.if_gain = TDA18272_AGCGAIN_0_7VPP,
|
|
.if_notch = TDA18272_NOTCH_DISABLED,
|
|
.if_hpf = TDA18272_HPF_0_85MHz,
|
|
.dc_notch = TDA18272_NOTCH_ENABLED,
|
|
.lna_top = TDA18272_LNATOP_95_89,
|
|
.rfatt_top = TDA18272_RFATTTOP_90_84,
|
|
.loband_rfagc_top = TDA18272_RFAGCTOP_96,
|
|
.hiband_rfagc_top = TDA18272_RFAGCTOP_96,
|
|
.irmix_top = TDA18272_IRMIXTOP_105_100,
|
|
.ifagc_top = TDA18272_IFAGCTOP_105_100,
|
|
.det_hpf = TDA18272_DETHPF_DISABLED,
|
|
.agc3_adapt = TDA18272_AGC3ADAPT_DISABLED,
|
|
.agc3_adapt_top = TDA18272_AGC3ADAPT_TOP_0,
|
|
.att3db = TDA18272_3DBATT_DISABLED,
|
|
.gsk = 0x02,
|
|
.filter = TDA18272_VHFFILT6_DISABLED,
|
|
.lpf_gain = TDA18272_LPFGAIN_FROZEN,
|
|
.agc1_freeze = 0,
|
|
.ltosto_immune = 0
|
|
}, {
|
|
.desc = "PAL I Blindscan",
|
|
.if_val = 7250000,
|
|
.cf_off = 2750000,
|
|
.lpf = TDA18272_LPF_8MHz,
|
|
.lpf_off = TDA18272_LPFOFFSET_0PC,
|
|
.if_gain = TDA18272_AGCGAIN_0_7VPP,
|
|
.if_notch = TDA18272_NOTCH_DISABLED,
|
|
.if_hpf = TDA18272_HPF_DISABLED,
|
|
.dc_notch = TDA18272_NOTCH_DISABLED,
|
|
.lna_top = TDA18272_LNATOP_95_89,
|
|
.rfatt_top = TDA18272_RFATTTOP_90_84,
|
|
.loband_rfagc_top = TDA18272_RFAGCTOP_96,
|
|
.hiband_rfagc_top = TDA18272_RFAGCTOP_96,
|
|
.irmix_top = TDA18272_IRMIXTOP_105_100,
|
|
.ifagc_top = TDA18272_IFAGCTOP_105_100,
|
|
.det_hpf = TDA18272_DETHPF_ENABLED,
|
|
.agc3_adapt = TDA18272_AGC3ADAPT_DISABLED,
|
|
.agc3_adapt_top = TDA18272_AGC3ADAPT_TOP_0,
|
|
.att3db = TDA18272_3DBATT_DISABLED,
|
|
.gsk = 0x01,
|
|
.filter = TDA18272_VHFFILT6_DISABLED,
|
|
.lpf_gain = TDA18272_LPFGAIN_FROZEN,
|
|
.agc1_freeze = 0,
|
|
.ltosto_immune = 0
|
|
}, {
|
|
.desc = "XpressScan",
|
|
.if_val = 5000000,
|
|
.cf_off = 0,
|
|
.lpf = TDA18272_LPF_9MHz,
|
|
.lpf_off = TDA18272_LPFOFFSET_0PC,
|
|
.if_gain = TDA18272_AGCGAIN_1VPP,
|
|
.if_notch = TDA18272_NOTCH_ENABLED,
|
|
.if_hpf = TDA18272_HPF_DISABLED,
|
|
.dc_notch = TDA18272_NOTCH_ENABLED,
|
|
.lna_top = TDA18272_LNATOP_95_89,
|
|
.rfatt_top = TDA18272_RFATTTOP_90_84,
|
|
.loband_rfagc_top = TDA18272_RFAGCTOP_100,
|
|
.hiband_rfagc_top = TDA18272_RFAGCTOP_102,
|
|
.irmix_top = TDA18272_IRMIXTOP_110_105,
|
|
.ifagc_top = TDA18272_IFAGCTOP_110_105,
|
|
.det_hpf = TDA18272_DETHPF_DISABLED,
|
|
.agc3_adapt = TDA18272_AGC3ADAPT_ENABLED,
|
|
.agc3_adapt_top = TDA18272_AGC3ADAPT_TOP_2,
|
|
.att3db = TDA18272_3DBATT_ENABLED,
|
|
.gsk = 0x0e,
|
|
.filter = TDA18272_VHFFILT6_ENABLED,
|
|
.lpf_gain = TDA18272_LPFGAIN_FREE,
|
|
.agc1_freeze = 0,
|
|
.ltosto_immune = 0
|
|
}, { }
|
|
};
|
|
|
|
#define TDA18272_REGMAPSIZ 68
|
|
|
|
struct tda18272_state {
|
|
const struct tda18272_coeff *coe;
|
|
u8 lna_top;
|
|
u8 psm_agc;
|
|
u8 agc1;
|
|
u8 mode;
|
|
|
|
u8 ms;
|
|
|
|
u32 bandwidth;
|
|
u32 frequency;
|
|
|
|
u8 regs[TDA18272_REGMAPSIZ];
|
|
struct dvb_frontend *fe;
|
|
struct i2c_adapter *i2c;
|
|
const struct tda18272_config *config;
|
|
};
|
|
|
|
static int tda18272_rd_regs(struct tda18272_state *tda18272, u8 reg, u8 *data, int count)
|
|
{
|
|
int ret;
|
|
const struct tda18272_config *config = tda18272->config;
|
|
struct dvb_frontend *fe = tda18272->fe;
|
|
struct i2c_msg msg[] = {
|
|
{ .addr = config->addr, .flags = 0, .buf = ®, .len = 1 },
|
|
{ .addr = config->addr, .flags = I2C_M_RD, .buf = data, .len = count }
|
|
};
|
|
|
|
if (count >= 255) {
|
|
dev_err(&tda18272->i2c->dev,
|
|
"I2C read transfer message length error, count: %d\n",
|
|
count);
|
|
return -EINVAL;
|
|
}
|
|
if (fe->ops.i2c_gate_ctrl)
|
|
fe->ops.i2c_gate_ctrl(fe, 1);
|
|
|
|
ret = i2c_transfer(tda18272->i2c, msg, 2);
|
|
|
|
if (fe->ops.i2c_gate_ctrl)
|
|
fe->ops.i2c_gate_ctrl(fe, 0);
|
|
|
|
if (ret != 2) {
|
|
dev_err(&tda18272->i2c->dev, "I2C read transfer error: %d\n",
|
|
ret);
|
|
return -EREMOTEIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int tda18272_wr_regs(struct tda18272_state *tda18272, u8 start, u8 *data, u8 count)
|
|
{
|
|
int ret;
|
|
const struct tda18272_config *config = tda18272->config;
|
|
struct dvb_frontend *fe = tda18272->fe;
|
|
struct device *dev = &tda18272->i2c->dev;
|
|
u8 buf[0x45];
|
|
struct i2c_msg msg = {
|
|
.addr = config->addr,
|
|
.flags = 0,
|
|
.buf = buf,
|
|
.len = count + 1 };
|
|
|
|
if (start >= 0x43) {
|
|
dev_err(dev, "I2C write start position error: %u\n", start);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if ((count >= 0x44) || (start + count > 0x44)) {
|
|
dev_err(dev,
|
|
"I2C write message length error, start: %u count: %u\n",
|
|
start, count);
|
|
return -EINVAL;
|
|
}
|
|
|
|
buf[0] = start;
|
|
memcpy(&buf[1], data, count);
|
|
if (fe->ops.i2c_gate_ctrl)
|
|
fe->ops.i2c_gate_ctrl(fe, 1);
|
|
|
|
ret = i2c_transfer(tda18272->i2c, &msg, 1);
|
|
|
|
if (fe->ops.i2c_gate_ctrl)
|
|
fe->ops.i2c_gate_ctrl(fe, 0);
|
|
|
|
if (ret != 1) {
|
|
dev_err(dev, "I2C write transfer error: %d\n", ret);
|
|
return -EREMOTEIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int tda18272_wr(struct tda18272_state *tda18272, u8 reg)
|
|
{
|
|
return tda18272_wr_regs(tda18272, reg, &tda18272->regs[reg], 1);
|
|
}
|
|
|
|
static int tda18272_rd(struct tda18272_state *tda18272, u8 reg)
|
|
{
|
|
return tda18272_rd_regs(tda18272, reg, &tda18272->regs[reg], 1);
|
|
}
|
|
|
|
static int tda18272_cal_wait(struct tda18272_state *tda18272)
|
|
{
|
|
u8 *regs = tda18272->regs;
|
|
int ret = 0;
|
|
u8 xtal_cal, count;
|
|
|
|
for (count = 20; count > 0; count--) {
|
|
ret = tda18272_rd(tda18272, TDA18272_IRQ_STATUS);
|
|
if (ret)
|
|
break;
|
|
/* xtal_cal status ready */
|
|
xtal_cal = TDA18272_GETFIELD(regs, IRQ_STATUS, XTALCAL_STATUS);
|
|
if (xtal_cal)
|
|
return 0;
|
|
/* Otherwise, retry */
|
|
msleep(5);
|
|
}
|
|
|
|
dev_err(&tda18272->i2c->dev, "ret=%d\n", ret);
|
|
return -1;
|
|
}
|
|
|
|
enum tda18272_power {
|
|
TDA18272_NORMAL = 0,
|
|
TDA18272_STDBY_1,
|
|
TDA18272_STDBY_2,
|
|
TDA18272_STDBY
|
|
};
|
|
|
|
static int tda18272_pstate(struct tda18272_state *tda18272, enum tda18272_power pstate)
|
|
{
|
|
u8 *regs = tda18272->regs;
|
|
int ret;
|
|
|
|
ret = tda18272_rd_regs(tda18272, TDA18272_POWERSTATE_BYTE_2,
|
|
&tda18272->regs[TDA18272_POWERSTATE_BYTE_2], 15);
|
|
if (ret)
|
|
goto err;
|
|
|
|
if (pstate != TDA18272_NORMAL) {
|
|
TDA18272_SETFIELD(regs, REFERENCE, DIGITAL_CLOCK, 0x00);
|
|
ret = tda18272_wr(tda18272, TDA18272_REFERENCE);
|
|
if (ret)
|
|
goto err;
|
|
}
|
|
|
|
switch (pstate) {
|
|
case TDA18272_NORMAL:
|
|
TDA18272_SETFIELD(regs, POWERSTATE_BYTE_2, SM, 0x00);
|
|
TDA18272_SETFIELD(regs, POWERSTATE_BYTE_2, SM_PLL, 0x00);
|
|
TDA18272_SETFIELD(regs, POWERSTATE_BYTE_2, SM_LNA, 0x00);
|
|
break;
|
|
case TDA18272_STDBY_1:
|
|
TDA18272_SETFIELD(regs, POWERSTATE_BYTE_2, SM, 0x01);
|
|
TDA18272_SETFIELD(regs, POWERSTATE_BYTE_2, SM_PLL, 0x00);
|
|
TDA18272_SETFIELD(regs, POWERSTATE_BYTE_2, SM_LNA, 0x00);
|
|
break;
|
|
case TDA18272_STDBY_2:
|
|
TDA18272_SETFIELD(regs, POWERSTATE_BYTE_2, SM, 0x01);
|
|
TDA18272_SETFIELD(regs, POWERSTATE_BYTE_2, SM_PLL, 0x01);
|
|
TDA18272_SETFIELD(regs, POWERSTATE_BYTE_2, SM_LNA, 0x00);
|
|
break;
|
|
case TDA18272_STDBY:
|
|
TDA18272_SETFIELD(regs, POWERSTATE_BYTE_2, SM, 0x01);
|
|
TDA18272_SETFIELD(regs, POWERSTATE_BYTE_2, SM_PLL, 0x01);
|
|
TDA18272_SETFIELD(regs, POWERSTATE_BYTE_2, SM_LNA, 0x01);
|
|
break;
|
|
}
|
|
ret = tda18272_wr(tda18272, TDA18272_POWERSTATE_BYTE_2);
|
|
if (ret)
|
|
goto err;
|
|
|
|
if (pstate == TDA18272_NORMAL) {
|
|
if (tda18272->ms)
|
|
TDA18272_SETFIELD(regs, REFERENCE, XTOUT, 0x03);
|
|
|
|
TDA18272_SETFIELD(regs, REFERENCE, DIGITAL_CLOCK, 0x01);
|
|
ret = tda18272_wr(tda18272, TDA18272_REFERENCE);
|
|
if (ret)
|
|
goto err;
|
|
}
|
|
err:
|
|
dev_dbg(&tda18272->i2c->dev, "ret=%d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
static int tda18272_wait_irq(struct tda18272_state *tda18272, u32 timeout, u32 step, u8 status)
|
|
{
|
|
int ret;
|
|
u8 irq_status;
|
|
u8 *regs = tda18272->regs;
|
|
u32 count = timeout / step;
|
|
struct device *dev = &tda18272->i2c->dev;
|
|
|
|
if (!count) {
|
|
dev_err(dev, "Empty IRQ wait count\n");
|
|
ret = -EINVAL;
|
|
goto err;
|
|
}
|
|
|
|
do {
|
|
ret = tda18272_rd(tda18272, TDA18272_IRQ_STATUS);
|
|
if (ret)
|
|
break;
|
|
|
|
if (TDA18272_GETFIELD(regs, IRQ_STATUS, IRQ_STATUS))
|
|
break;
|
|
|
|
if (status) {
|
|
irq_status = tda18272->regs[TDA18272_IRQ_STATUS] & 0x1f;
|
|
if (status == irq_status)
|
|
break;
|
|
}
|
|
msleep(step);
|
|
--count;
|
|
if (!count) {
|
|
dev_err(dev, "IRQ status read timeout error\n");
|
|
ret = -1;
|
|
break;
|
|
}
|
|
} while (count);
|
|
|
|
err:
|
|
dev_dbg(dev, "ret=%d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
static int tda18272_reset(struct tda18272_state *tda18272)
|
|
{
|
|
struct device *dev = &tda18272->i2c->dev;
|
|
u8 *regs = tda18272->regs;
|
|
u8 data;
|
|
int ret;
|
|
|
|
ret = tda18272_rd_regs(tda18272, TDA18272_ID_BYTE_1,
|
|
tda18272->regs, TDA18272_REGMAPSIZ);
|
|
if (ret)
|
|
goto err;
|
|
TDA18272_SETFIELD(regs, POWER_BYTE_2, RSSI_CK_SPEED, 0x00);
|
|
ret = tda18272_wr(tda18272, TDA18272_POWER_BYTE_2);
|
|
if (ret)
|
|
goto err;
|
|
TDA18272_SETFIELD(regs, AGC1_BYTE_2, AGC1_DO_STEP, 0x02);
|
|
ret = tda18272_wr(tda18272, TDA18272_AGC1_BYTE_2);
|
|
if (ret)
|
|
goto err;
|
|
TDA18272_SETFIELD(regs, RF_FILTER_BYTE_3, AGC2_DO_STEP, 0x01);
|
|
ret = tda18272_wr(tda18272, TDA18272_RF_FILTER_BYTE_3);
|
|
if (ret)
|
|
goto err;
|
|
TDA18272_SETFIELD(regs, AGCK_BYTE_1, AGCs_UP_STEP_ASYM, 0x03);
|
|
ret = tda18272_wr(tda18272, TDA18272_AGCK_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
TDA18272_SETFIELD(regs, AGC5_BYTE_1, AGCs_DO_STEP_ASYM, 0x02);
|
|
|
|
ret = tda18272_wr(tda18272, TDA18272_AGC5_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
data = 0x9f;
|
|
ret = tda18272_wr_regs(tda18272, TDA18272_IRQ_CLEAR, &data, 1);
|
|
if (ret)
|
|
goto err;
|
|
ret = tda18272_pstate(tda18272, TDA18272_NORMAL);
|
|
if (ret) {
|
|
dev_err(dev, "Power state switch failed, ret=%d\n", ret);
|
|
goto err;
|
|
}
|
|
tda18272->regs[TDA18272_MSM_BYTE_1] = 0x38;
|
|
tda18272->regs[TDA18272_MSM_BYTE_2] = 0x01;
|
|
ret = tda18272_wr_regs(tda18272, TDA18272_MSM_BYTE_1,
|
|
&tda18272->regs[TDA18272_MSM_BYTE_1], 2);
|
|
if (ret)
|
|
goto err;
|
|
|
|
ret = tda18272_wait_irq(tda18272, 1500, 50, 0x1f);
|
|
if (ret)
|
|
goto err;
|
|
err:
|
|
dev_dbg(dev, "ret=%d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
static int tda18272_init(struct dvb_frontend *fe)
|
|
{
|
|
struct tda18272_state *tda18272 = fe->tuner_priv;
|
|
u8 *regs = tda18272->regs;
|
|
int ret;
|
|
|
|
if (tda18272->mode) {
|
|
dev_dbg(&tda18272->i2c->dev, "Initializing Master ..\n");
|
|
ret = tda18272_cal_wait(tda18272);
|
|
if (ret)
|
|
goto err;
|
|
} else {
|
|
dev_dbg(&tda18272->i2c->dev, "Initializing Slave ..\n");
|
|
TDA18272_SETFIELD(regs, FLO_MAX_BYTE, FMAX_LO, 0x00);
|
|
|
|
ret = tda18272_wr(tda18272, TDA18272_FLO_MAX_BYTE);
|
|
if (ret)
|
|
goto err;
|
|
TDA18272_SETFIELD(regs, CP_CURRENT, N_CP_CURRENT, 0x68);
|
|
ret = tda18272_wr(tda18272, TDA18272_CP_CURRENT);
|
|
}
|
|
ret = tda18272_reset(tda18272);
|
|
if (ret)
|
|
goto err;
|
|
|
|
TDA18272_SETFIELD(regs, FLO_MAX_BYTE, FMAX_LO, 0x0a);
|
|
ret = tda18272_wr(tda18272, TDA18272_FLO_MAX_BYTE);
|
|
if (ret)
|
|
goto err;
|
|
|
|
TDA18272_SETFIELD(regs, AGC1_BYTE_1, LT_ENABLE, tda18272->lna_top);
|
|
ret = tda18272_wr(tda18272, TDA18272_AGC1_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
|
|
TDA18272_SETFIELD(regs, PSM_BYTE_1, PSM_AGC1, tda18272->psm_agc);
|
|
ret = tda18272_wr(tda18272, TDA18272_PSM_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
|
|
TDA18272_SETFIELD(regs, AGC1_BYTE_1, AGC1_6_15DB, tda18272->agc1);
|
|
ret = tda18272_wr(tda18272, TDA18272_AGC1_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
err:
|
|
dev_dbg(&tda18272->i2c->dev, "ret=%d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
static int tda18272_clear_irq(struct tda18272_state *tda18272, u8 status)
|
|
{
|
|
u8 *regs = tda18272->regs;
|
|
|
|
regs[TDA18272_IRQ_CLEAR] = status & 0x1f;
|
|
TDA18272_SETFIELD(regs, IRQ_CLEAR, IRQ_CLEAR, 0x80);
|
|
|
|
return tda18272_wr(tda18272, TDA18272_IRQ_CLEAR);
|
|
}
|
|
|
|
static int tda18272_set_rf(struct tda18272_state *tda18272, u32 freq)
|
|
{
|
|
u32 tmp;
|
|
int ret;
|
|
|
|
ret = tda18272_clear_irq(tda18272, 0x0c);
|
|
if (ret)
|
|
goto err;
|
|
|
|
ret = tda18272_pstate(tda18272, TDA18272_NORMAL);
|
|
if (ret)
|
|
goto err;
|
|
|
|
tmp = freq / 1000;
|
|
tda18272->regs[TDA18272_RF_FREQUENCY_BYTE_1] = (u8) ((tmp & 0xff0000) >> 16);
|
|
tda18272->regs[TDA18272_RF_FREQUENCY_BYTE_2] = (u8) ((tmp & 0x00ff00) >> 8);
|
|
tda18272->regs[TDA18272_RF_FREQUENCY_BYTE_3] = (u8) (tmp & 0x0000ff);
|
|
ret = tda18272_wr_regs(tda18272, TDA18272_RF_FREQUENCY_BYTE_1,
|
|
&tda18272->regs[TDA18272_RF_FREQUENCY_BYTE_1], 3);
|
|
if (ret)
|
|
goto err;
|
|
|
|
tda18272->regs[TDA18272_MSM_BYTE_1] = 0x41;
|
|
tda18272->regs[TDA18272_MSM_BYTE_2] = 0x01;
|
|
ret = tda18272_wr_regs(tda18272, TDA18272_MSM_BYTE_1,
|
|
&tda18272->regs[TDA18272_MSM_BYTE_1], 2);
|
|
if (ret)
|
|
goto err;
|
|
|
|
ret = tda18272_wait_irq(tda18272, 50, 5, 0x0c);
|
|
if (ret)
|
|
goto err;
|
|
err:
|
|
dev_dbg(&tda18272->i2c->dev, "ret=%d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
static int tda18272_set_frequency(struct tda18272_state *tda18272, u32 frequency)
|
|
{
|
|
u8 *regs = tda18272->regs;
|
|
int ret;
|
|
|
|
u8 ratio_l, ratio_h;
|
|
u32 delta_l, delta_h;
|
|
u8 loop_off, rffilt_gv = 0;
|
|
|
|
u8 g1, count, agc1, agc1_steps, done = 0;
|
|
s16 steps_up, steps_down;
|
|
|
|
const struct tda18272_coeff *coe = tda18272->coe;
|
|
|
|
dev_dbg(&tda18272->i2c->dev, "set freq=%d\n", frequency);
|
|
|
|
TDA18272_SETFIELD(regs, IF_BYTE_1, LP_FC, coe->lpf); /* LPF */
|
|
ret = tda18272_wr(tda18272, TDA18272_IF_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
|
|
TDA18272_SETFIELD(regs, IF_BYTE_1, LP_FC_OFFSET, 0x80);
|
|
ret = tda18272_wr(tda18272, TDA18272_IF_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
|
|
TDA18272_SETFIELD(regs, IFAGC, IF_LEVEL, coe->if_gain);
|
|
ret = tda18272_wr(tda18272, TDA18272_IFAGC);
|
|
if (ret)
|
|
goto err;
|
|
|
|
TDA18272_SETFIELD(regs, IF_BYTE_1, IF_NOTCH, coe->if_notch);
|
|
ret = tda18272_wr(tda18272, TDA18272_IF_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
|
|
if (coe->if_hpf == TDA18272_HPF_DISABLED) {
|
|
TDA18272_SETFIELD(regs, IRMIXER_BYTE_2, HI_PASS, 0x00);
|
|
ret = tda18272_wr(tda18272, TDA18272_IRMIXER_BYTE_2);
|
|
if (ret)
|
|
goto err;
|
|
} else {
|
|
TDA18272_SETFIELD(regs, IRMIXER_BYTE_2, HI_PASS, 0x01);
|
|
ret = tda18272_wr(tda18272, TDA18272_IRMIXER_BYTE_2);
|
|
if (ret)
|
|
goto err;
|
|
TDA18272_SETFIELD(regs, IF_BYTE_1, IF_HP_FC, (coe->if_hpf - 1));
|
|
ret = tda18272_wr(tda18272, TDA18272_IF_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
}
|
|
|
|
TDA18272_SETFIELD(regs, IRMIXER_BYTE_2, DC_NOTCH, coe->dc_notch);
|
|
ret = tda18272_wr(tda18272, TDA18272_IRMIXER_BYTE_2);
|
|
if (ret)
|
|
goto err;
|
|
|
|
TDA18272_SETFIELD(regs, AGC1_BYTE_1, AGC1_TOP, coe->lna_top);
|
|
ret = tda18272_wr(tda18272, TDA18272_AGC1_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
|
|
TDA18272_SETFIELD(regs, AGC2_BYTE_1, AGC2_TOP, coe->rfatt_top);
|
|
ret = tda18272_wr(tda18272, TDA18272_AGC2_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
|
|
if (frequency < TDA18272_AGC3_RF_AGC_TOP_FREQ_LIM)
|
|
TDA18272_SETFIELD(regs, RFAGC_BYTE_1, AGC3_TOP,
|
|
coe->loband_rfagc_top);
|
|
else
|
|
TDA18272_SETFIELD(regs, RFAGC_BYTE_1, AGC3_TOP,
|
|
coe->hiband_rfagc_top);
|
|
ret = tda18272_wr(tda18272, TDA18272_RFAGC_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
|
|
TDA18272_SETFIELD(regs, IRMIXER_BYTE_1, AGC4_TOP, coe->irmix_top);
|
|
ret = tda18272_wr(tda18272, TDA18272_IRMIXER_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
|
|
TDA18272_SETFIELD(regs, AGC5_BYTE_1, AGC5_TOP, coe->ifagc_top);
|
|
ret = tda18272_wr(tda18272, TDA18272_AGC5_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
|
|
TDA18272_SETFIELD(regs, RFAGC_BYTE_1, PD_RFAGC_ADAPT, coe->agc3_adapt);
|
|
ret = tda18272_wr(tda18272, TDA18272_RFAGC_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
|
|
TDA18272_SETFIELD(regs, RFAGC_BYTE_1, RFAGC_ADAPT_TOP,
|
|
coe->agc3_adapt_top);
|
|
ret = tda18272_wr(tda18272, TDA18272_RFAGC_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
|
|
TDA18272_SETFIELD(regs, RFAGC_BYTE_1, RF_ATTEN_3DB, coe->att3db);
|
|
ret = tda18272_wr(tda18272, TDA18272_RFAGC_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
|
|
TDA18272_SETFIELD(regs, AGC5_BYTE_1, AGC5_HPF, coe->det_hpf);
|
|
ret = tda18272_wr(tda18272, TDA18272_AGC5_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
|
|
TDA18272_SETFIELD(regs, AGCK_BYTE_1, AGCK_MODE, coe->gsk & 0x03);
|
|
ret = tda18272_wr(tda18272, TDA18272_AGCK_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
|
|
TDA18272_SETFIELD(regs, AGCK_BYTE_1, AGCK_STEP, (coe->gsk & 0x0c) >> 2);
|
|
ret = tda18272_wr(tda18272, TDA18272_AGCK_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
|
|
TDA18272_SETFIELD(regs, PSM_BYTE_1, PSM_STOB, coe->filter);
|
|
ret = tda18272_wr(tda18272, TDA18272_PSM_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
|
|
TDA18272_SETFIELD(regs, IF_FREQUENCY, IF_FREQ,
|
|
(coe->if_val - coe->cf_off) / 50000);
|
|
ret = tda18272_wr(tda18272, TDA18272_IF_FREQUENCY);
|
|
if (ret)
|
|
goto err;
|
|
|
|
if (coe->ltosto_immune && tda18272->mode) {
|
|
ret = tda18272_rd(tda18272, TDA18272_RF_AGC_GAIN_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
|
|
rffilt_gv = TDA18272_GETFIELD(regs, RF_AGC_GAIN_BYTE_1, RF_FILTER_GAIN);
|
|
TDA18272_SETFIELD(regs, RF_FILTER_BYTE_1, RF_FILTER_GV, rffilt_gv);
|
|
ret = tda18272_wr(tda18272, TDA18272_RF_FILTER_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
|
|
TDA18272_SETFIELD(regs, RF_FILTER_BYTE_1, FORCE_AGC2_GAIN, 0x01);
|
|
ret = tda18272_wr(tda18272, TDA18272_RF_FILTER_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
|
|
if (rffilt_gv) {
|
|
do {
|
|
TDA18272_SETFIELD(regs, RF_FILTER_BYTE_1,
|
|
RF_FILTER_GV, (rffilt_gv - 1));
|
|
ret = tda18272_wr(tda18272, TDA18272_RF_FILTER_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
|
|
msleep(10);
|
|
rffilt_gv -= 1;
|
|
} while (rffilt_gv > 0);
|
|
}
|
|
TDA18272_SETFIELD(regs, RFAGC_BYTE_1, RF_ATTEN_3DB, 0x01);
|
|
ret = tda18272_wr(tda18272, TDA18272_RFAGC_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
}
|
|
ret = tda18272_set_rf(tda18272, frequency + coe->cf_off);
|
|
if (ret)
|
|
goto err;
|
|
|
|
if (coe->ltosto_immune && tda18272->mode) {
|
|
TDA18272_SETFIELD(regs, RFAGC_BYTE_1, RF_ATTEN_3DB, 0x00);
|
|
ret = tda18272_wr(tda18272, TDA18272_RFAGC_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
|
|
msleep(50);
|
|
TDA18272_SETFIELD(regs, RF_FILTER_BYTE_1, FORCE_AGC2_GAIN, 0x01);
|
|
ret = tda18272_wr(tda18272, TDA18272_RF_FILTER_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
}
|
|
ratio_l = (u8)(frequency / 16000000);
|
|
ratio_h = (u8)(frequency / 16000000) + 1;
|
|
delta_l = (frequency - (ratio_l * 16000000));
|
|
delta_h = ((ratio_h * 16000000) - frequency);
|
|
|
|
if (frequency < 72000000) {
|
|
TDA18272_SETFIELD(regs, REFERENCE, DIGITAL_CLOCK, 0x01);
|
|
} else if (frequency < 104000000) {
|
|
TDA18272_SETFIELD(regs, REFERENCE, DIGITAL_CLOCK, 0x00);
|
|
} else if (frequency <= 120000000) {
|
|
TDA18272_SETFIELD(regs, REFERENCE, DIGITAL_CLOCK, 0x01);
|
|
} else {
|
|
if (delta_l <= delta_h) {
|
|
if (ratio_l & 0x000001)
|
|
TDA18272_SETFIELD(regs, REFERENCE, DIGITAL_CLOCK, 0x00);
|
|
else
|
|
TDA18272_SETFIELD(regs, REFERENCE, DIGITAL_CLOCK, 0x01);
|
|
} else {
|
|
if (ratio_l & 0x000001)
|
|
TDA18272_SETFIELD(regs, REFERENCE, DIGITAL_CLOCK, 0x01);
|
|
else
|
|
TDA18272_SETFIELD(regs, REFERENCE, DIGITAL_CLOCK, 0x00);
|
|
}
|
|
}
|
|
ret = tda18272_wr(tda18272, TDA18272_REFERENCE);
|
|
if (ret)
|
|
goto err;
|
|
|
|
if (coe->agc1_freeze) {
|
|
tda18272_rd(tda18272, TDA18272_AGC1_BYTE_2);
|
|
loop_off = TDA18272_GETFIELD(regs, AGC1_BYTE_2, AGC1_LOOP_OFF);
|
|
if (!loop_off) {
|
|
TDA18272_SETFIELD(regs, AGC1_BYTE_2, AGC1_LOOP_OFF, 0x01);
|
|
ret = tda18272_wr(tda18272, TDA18272_AGC1_BYTE_2);
|
|
if (ret)
|
|
goto err;
|
|
TDA18272_SETFIELD(regs, AGC1_BYTE_2, FORCE_AGC1_GAIN, 0x01);
|
|
ret = tda18272_wr(tda18272, TDA18272_AGC1_BYTE_2);
|
|
if (ret)
|
|
goto err;
|
|
}
|
|
|
|
if (!TDA18272_GETFIELD(regs, AGC1_BYTE_1, AGC1_6_15DB)) {
|
|
agc1 = 0;
|
|
agc1_steps = 10;
|
|
} else {
|
|
agc1 = 6;
|
|
agc1_steps = 4;
|
|
}
|
|
|
|
while (done < agc1_steps) {
|
|
count = 0;
|
|
steps_up = 0;
|
|
steps_down = 0;
|
|
done += 1;
|
|
|
|
while ((count++) < 40) {
|
|
ret = tda18272_rd(tda18272, TDA18272_AGC_DET_OUT);
|
|
if (ret)
|
|
goto err;
|
|
steps_down = (TDA18272_GETFIELD(regs, AGC_DET_OUT, DO_AGC1) ? 14 : -1);
|
|
steps_up = (TDA18272_GETFIELD(regs, AGC_DET_OUT, UP_AGC1) ? 1 : -4);
|
|
msleep(1);
|
|
}
|
|
|
|
if (steps_up >= 15 &&
|
|
(TDA18272_GETFIELD(regs, AGC1_BYTE_2, AGC1_GAIN) != 9)) {
|
|
|
|
g1 = TDA18272_GETFIELD(regs, AGC1_BYTE_2, AGC1_GAIN) + 1;
|
|
TDA18272_SETFIELD(regs, AGC1_BYTE_2, AGC1_GAIN, g1);
|
|
ret = tda18272_wr(tda18272, TDA18272_AGC1_BYTE_2);
|
|
if (ret)
|
|
goto err;
|
|
} else if (steps_down >= 10 &&
|
|
TDA18272_GETFIELD(regs, AGC1_BYTE_2, AGC1_GAIN) != agc1) {
|
|
|
|
g1 = TDA18272_GETFIELD(regs, AGC1_BYTE_2, AGC1_GAIN) - 1;
|
|
TDA18272_SETFIELD(regs, AGC1_BYTE_2, AGC1_GAIN, g1);
|
|
ret = tda18272_wr(tda18272, TDA18272_AGC1_BYTE_2);
|
|
if (ret)
|
|
goto err;
|
|
} else {
|
|
done = agc1_steps;
|
|
}
|
|
}
|
|
} else {
|
|
TDA18272_SETFIELD(regs, AGC1_BYTE_2, FORCE_AGC1_GAIN, 0x00);
|
|
ret = tda18272_wr(tda18272, TDA18272_AGC1_BYTE_2);
|
|
if (ret)
|
|
goto err;
|
|
|
|
TDA18272_SETFIELD(regs, AGC1_BYTE_2, AGC1_LOOP_OFF, 0x00);
|
|
ret = tda18272_wr(tda18272, TDA18272_AGC1_BYTE_2);
|
|
if (ret)
|
|
goto err;
|
|
}
|
|
err:
|
|
dev_dbg(&tda18272->i2c->dev, "ret=%d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
static int tda18272_get_status(struct dvb_frontend *fe, u32 *status)
|
|
{
|
|
struct tda18272_state *tda18272 = fe->tuner_priv;
|
|
u8 *regs = tda18272->regs;
|
|
int ret = 0;
|
|
u8 data;
|
|
|
|
*status = 0;
|
|
data = 0x01;
|
|
|
|
ret = tda18272_wr_regs(tda18272, TDA18272_THERMO_BYTE_2, &data, 1);
|
|
if (ret)
|
|
goto err;
|
|
|
|
ret = tda18272_rd(tda18272, TDA18272_THERMO_BYTE_1);
|
|
if (ret)
|
|
goto err;
|
|
|
|
ret = tda18272_rd_regs(tda18272, TDA18272_POWERSTATE_BYTE_1,
|
|
&tda18272->regs[TDA18272_POWERSTATE_BYTE_1], 3);
|
|
if (ret)
|
|
goto err;
|
|
|
|
if (TDA18272_GETFIELD(regs, POWERSTATE_BYTE_1, LO_LOCK)) {
|
|
dev_err(&tda18272->i2c->dev, "PLL Locked\n");
|
|
*status |= 0x01;
|
|
}
|
|
if ((tda18272->regs[TDA18272_POWERSTATE_BYTE_2] >> 1) == 0)
|
|
dev_dbg(&tda18272->i2c->dev, "Normal MODE\n");
|
|
if ((tda18272->regs[TDA18272_POWERSTATE_BYTE_2] >> 1) == 7)
|
|
dev_dbg(&tda18272->i2c->dev, "Standby MODE, LNA=ON, PLL=OFF\n");
|
|
if ((tda18272->regs[TDA18272_POWERSTATE_BYTE_2] >> 1) == 6)
|
|
dev_dbg(&tda18272->i2c->dev, "Standby MODE, LNA=ON, PLL=OFF\n");
|
|
if ((tda18272->regs[TDA18272_POWERSTATE_BYTE_2] >> 1) == 4)
|
|
dev_dbg(&tda18272->i2c->dev, "Standby MODE, LNA=ON, PLL=ON\n");
|
|
|
|
dev_dbg(&tda18272->i2c->dev, "Junction Temperature:%d Power level:%d\n",
|
|
tda18272->regs[TDA18272_THERMO_BYTE_1],
|
|
tda18272->regs[TDA18272_INPUT_POWERLEVEL]);
|
|
|
|
err:
|
|
dev_dbg(&tda18272->i2c->dev, "ret=%d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
static int tda18272_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
|
|
{
|
|
struct tda18272_state *tda18272 = fe->tuner_priv;
|
|
|
|
if (fe->ops.info.type == FE_OFDM)
|
|
*bandwidth = tda18272->bandwidth;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int tda18272_set_params(struct dvb_frontend *fe)
|
|
{
|
|
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
|
struct tda18272_state *tda18272 = fe->tuner_priv;
|
|
struct tda18272_coeff *coe = NULL;
|
|
u32 status;
|
|
u32 delsys = c->delivery_system;
|
|
u32 bw = c->bandwidth_hz;
|
|
u32 freq = c->frequency;
|
|
int ret;
|
|
|
|
if (!tda18272) {
|
|
dev_err(&tda18272->i2c->dev, "Tuner state not set\n");
|
|
ret = -EINVAL;
|
|
goto err;
|
|
}
|
|
|
|
dev_dbg(&tda18272->i2c->dev, "freq=%d, bw=%d\n", freq, bw);
|
|
switch (delsys) {
|
|
case SYS_ATSC:
|
|
coe = coeft + TDA18272_ATSC_6MHz;
|
|
break;
|
|
case SYS_DVBT:
|
|
case SYS_DVBT2:
|
|
switch (bw) {
|
|
case 6000000:
|
|
coe = coeft + TDA18272_DVBT_6MHz;
|
|
break;
|
|
case 7000000:
|
|
coe = coeft + TDA18272_DVBT_7MHz;
|
|
break;
|
|
case 8000000:
|
|
coe = coeft + TDA18272_DVBT_8MHz;
|
|
break;
|
|
default:
|
|
coe = NULL;
|
|
ret = -EINVAL;
|
|
goto err;
|
|
}
|
|
break;
|
|
case SYS_DVBC_ANNEX_A:
|
|
case SYS_DVBC_ANNEX_C:
|
|
coe = coeft + TDA18272_QAM_8MHz;
|
|
break;
|
|
case SYS_DVBC_ANNEX_B:
|
|
coe = coeft + TDA18272_QAM_6MHz;
|
|
break;
|
|
}
|
|
if (!coe) {
|
|
dev_err(&tda18272->i2c->dev, "Tuner coefficients not set\n");
|
|
ret = -EINVAL;
|
|
goto err;
|
|
}
|
|
tda18272->coe = coe;
|
|
dev_dbg(&tda18272->i2c->dev, "Loading %s coeffecients...\n", coe->desc);
|
|
ret = tda18272_set_frequency(tda18272, freq);
|
|
if (ret)
|
|
goto err;
|
|
msleep(100);
|
|
ret = tda18272_get_status(fe, &status);
|
|
if (ret)
|
|
goto err;
|
|
|
|
if (status == 0x01) {
|
|
tda18272->frequency = freq;
|
|
if (fe->ops.info.type == FE_OFDM)
|
|
tda18272->bandwidth = bw;
|
|
}
|
|
err:
|
|
dev_dbg(&tda18272->i2c->dev, "ret=%d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
static int tda18272_get_ifreq(struct dvb_frontend *fe, u32 *frequency)
|
|
{
|
|
struct tda18272_state *tda18272 = fe->tuner_priv;
|
|
const struct tda18272_coeff *coe = tda18272->coe;
|
|
|
|
*frequency = coe->if_val;
|
|
return 0;
|
|
}
|
|
|
|
static int tda18272_release(struct dvb_frontend *fe)
|
|
{
|
|
struct tda18272_state *tda18272 = fe->tuner_priv;
|
|
int ret;
|
|
|
|
if (!tda18272) {
|
|
dev_err(&tda18272->i2c->dev, "Tuner state not set\n");
|
|
ret = -EINVAL;
|
|
} else {
|
|
kfree(tda18272);
|
|
ret = 0;
|
|
}
|
|
|
|
fe->tuner_priv = NULL;
|
|
return ret;
|
|
}
|
|
|
|
static struct dvb_tuner_ops tda18272_ops = {
|
|
.info = {
|
|
.name = "TDA18272 Silicon Tuner",
|
|
.frequency_min = 42000000,
|
|
.frequency_max = 870000000,
|
|
.frequency_step = 50000,
|
|
},
|
|
.init = tda18272_init,
|
|
.get_status = tda18272_get_status,
|
|
.set_params = tda18272_set_params,
|
|
.get_bandwidth = tda18272_get_bandwidth,
|
|
.get_frequency = tda18272_get_ifreq,
|
|
.release = tda18272_release
|
|
};
|
|
|
|
|
|
#define TDA18272_CHIP_ID 18272
|
|
#define TDA18272_MAJOR_REV 1
|
|
#define TDA18272_MINOR_REV 1
|
|
|
|
struct dvb_frontend *tda18272_attach(struct dvb_frontend *fe,
|
|
struct i2c_adapter *i2c,
|
|
const struct tda18272_config *config)
|
|
{
|
|
struct tda18272_state *tda18272 = NULL;
|
|
struct device *dev;
|
|
u8 *regs = NULL;
|
|
u8 major = 0, minor = 0, mode = 0;
|
|
int id = 0, ret;
|
|
|
|
if (!i2c) {
|
|
pr_err("I2C adapter not found\n");
|
|
return NULL;
|
|
}
|
|
dev = &i2c->dev;
|
|
if (!config) {
|
|
dev_err(dev, "TDA18272 config not set\n");
|
|
return NULL;
|
|
}
|
|
|
|
tda18272 = kzalloc(sizeof (struct tda18272_state), GFP_KERNEL);
|
|
if (!tda18272)
|
|
return NULL;
|
|
|
|
tda18272->i2c = i2c;
|
|
tda18272->config = config;
|
|
tda18272->fe = fe;
|
|
|
|
fe->tuner_priv = tda18272;
|
|
fe->ops.tuner_ops = tda18272_ops;
|
|
|
|
regs = tda18272->regs;
|
|
|
|
ret = tda18272_rd_regs(tda18272, TDA18272_ID_BYTE_1,
|
|
®s[TDA18272_ID_BYTE_1], 3);
|
|
if (ret)
|
|
goto err;
|
|
|
|
id = (TDA18272_GETFIELD(regs, ID_BYTE_1, IDENT) << 8) |
|
|
TDA18272_GETFIELD(regs, ID_BYTE_2, IDENT);
|
|
|
|
major = TDA18272_GETFIELD(regs, ID_BYTE_3, MAJOR_REV);
|
|
minor = TDA18272_GETFIELD(regs, ID_BYTE_3, MINOR_REV);
|
|
mode = TDA18272_GETFIELD(regs, ID_BYTE_1, MASTER_SLAVE);
|
|
|
|
if (id != TDA18272_CHIP_ID) {
|
|
dev_err(dev, "TDA18272 not found!, ID=0x%02x exiting..\n", id);
|
|
goto err;
|
|
}
|
|
|
|
dev_dbg(dev, "Found TDA%d %s Rev:%d.%d\n", id,
|
|
mode ? "Master" : "Slave", major, minor);
|
|
if ((major != TDA18272_MAJOR_REV) || (minor != TDA18272_MINOR_REV))
|
|
dev_err(dev, "Unknown Version:%d.%d, trying anyway ..\n",
|
|
major, minor);
|
|
|
|
tda18272->mode = mode;
|
|
if (config->mode == TDA18272_SLAVE && tda18272->mode == 1)
|
|
dev_err(dev,
|
|
"Config as TDA18272 Slave, but TDA18272 Master found ???\n");
|
|
|
|
if (config->mode == TDA18272_MASTER)
|
|
tda18272->ms = 1;
|
|
else
|
|
tda18272->ms = 0;
|
|
|
|
tda18272->lna_top = 0;
|
|
tda18272->psm_agc = 1;
|
|
tda18272->agc1 = 0;
|
|
|
|
ret = tda18272_init(fe);
|
|
if (ret) {
|
|
dev_err(dev, "Error Initializing!\n");
|
|
goto err;
|
|
}
|
|
|
|
dev_dbg(dev, "Done\n");
|
|
return tda18272->fe;
|
|
err:
|
|
if (tda18272)
|
|
kfree(tda18272);
|
|
return NULL;
|
|
}
|
|
EXPORT_SYMBOL(tda18272_attach);
|
|
|
|
MODULE_AUTHOR("Manu Abraham");
|
|
MODULE_DESCRIPTION("TDA18272 Silicon tuner");
|
|
MODULE_LICENSE("GPL");
|