usbtuner: add AVerMedia H837 support
Terry Heo [Thu, 7 May 2015 02:17:38 +0000 (11:17 +0900)]
Bug: 20649732
Bug 1736911

Change-Id: Ib550504231ba2eaedebb864295db50069ebe769c
Signed-off-by: Terry Heo <terryheo@google.com>
Reviewed-on: http://git-master/r/1029830
(cherry picked from commit b290895387dbe45399a095591fc7b61167a9caa0)
Reviewed-on: http://git-master/r/1311288
GVS: Gerrit_Virtual_Submit
Tested-by: Jean Huang <jeanh@nvidia.com>
Reviewed-by: Vinayak Pane <vpane@nvidia.com>
Reviewed-on: http://git-master/r/1456502
Tested-by: Patrick Horng <phorng@nvidia.com>
Reviewed-by: Manish Tuteja <mtuteja@nvidia.com>

12 files changed:
drivers/media/tuners/Kconfig
drivers/media/tuners/Makefile
drivers/media/tuners/tda18272.c [new file with mode: 0644]
drivers/media/tuners/tda18272.h [new file with mode: 0644]
drivers/media/tuners/tda18272_reg.h [new file with mode: 0644]
drivers/media/usb/cx231xx/Kconfig
drivers/media/usb/cx231xx/cx231xx-avcore.c
drivers/media/usb/cx231xx/cx231xx-cards.c
drivers/media/usb/cx231xx/cx231xx-core.c
drivers/media/usb/cx231xx/cx231xx-dvb.c
drivers/media/usb/cx231xx/cx231xx-video.c
drivers/media/usb/cx231xx/cx231xx.h

index 7d09af3..e5150b6 100644 (file)
@@ -49,6 +49,13 @@ config MEDIA_TUNER_TDA18271
        help
          A silicon tuner module. Say Y when you want to support this tuner.
 
+config MEDIA_TUNER_TDA18272
+       tristate "NXP TDA18272 silicon tuner"
+       depends on MEDIA_SUPPORT && I2C
+       default m if !MEDIA_SUBDRV_AUTOSELECT
+       help
+         A silicon tuner module. Say Y when you want to support this tuner.
+
 config MEDIA_TUNER_TDA9887
        tristate "TDA 9885/6/7 analog IF demodulator"
        depends on MEDIA_SUPPORT && I2C
index 55fdbd3..e35349e 100644 (file)
@@ -15,6 +15,7 @@ obj-$(CONFIG_MEDIA_TUNER_TEA5761) += tea5761.o
 obj-$(CONFIG_MEDIA_TUNER_TDA9887) += tda9887.o
 obj-$(CONFIG_MEDIA_TUNER_TDA827X) += tda827x.o
 obj-$(CONFIG_MEDIA_TUNER_TDA18271) += tda18271.o
+obj-$(CONFIG_MEDIA_TUNER_TDA18272) += tda18272.o
 obj-$(CONFIG_MEDIA_TUNER_XC5000) += xc5000.o
 obj-$(CONFIG_MEDIA_TUNER_XC4000) += xc4000.o
 obj-$(CONFIG_MEDIA_TUNER_MT2060) += mt2060.o
diff --git a/drivers/media/tuners/tda18272.c b/drivers/media/tuners/tda18272.c
new file mode 100644 (file)
index 0000000..644d70c
--- /dev/null
@@ -0,0 +1,1602 @@
+/*
+       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"
+
+static unsigned int verbose;
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "Set Verbosity level");
+
+#define FE_ERROR                               0
+#define FE_NOTICE                              1
+#define FE_INFO                                        2
+#define FE_DEBUG                               3
+#define FE_DEBUGREG                            4
+
+#define dprintk(__y, __z, format, arg...) do {                                         \
+       if (__z) {                                                                      \
+               if      ((verbose > FE_ERROR) && (verbose > __y))                       \
+                       printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);          \
+               else if ((verbose > FE_NOTICE) && (verbose > __y))                      \
+                       printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);       \
+               else if ((verbose > FE_INFO) && (verbose > __y))                        \
+                       printk(KERN_INFO "%s: " format "\n", __func__ , ##arg);         \
+               else if ((verbose > FE_DEBUG) && (verbose > __y))                       \
+                       printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);        \
+       } else {                                                                        \
+               if (verbose > __y)                                                      \
+                       printk(format, ##arg);                                          \
+       }                                                                               \
+} while (0)
+
+#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))
+
+
+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 = &reg, .len = 1 },
+               { .addr = config->addr, .flags = I2C_M_RD, .buf = data, .len = count }
+       };
+
+       BUG_ON(count >= 255);
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       ret = i2c_transfer(tda18272->i2c, msg, 2);
+       if (ret != 2) {
+               dprintk(FE_ERROR, 1, "I/O Error");
+               ret = -EREMOTEIO;
+       } else {
+               ret = 0;
+       }
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return ret;
+}
+
+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;
+       u8 buf[0x45];
+       struct i2c_msg msg = { .addr = config->addr, .flags = 0, .buf = buf, .len = count + 1 };
+
+       BUG_ON(count >= 0x44);
+       BUG_ON(start >= 0x43);
+       BUG_ON(start + count > 0x44);
+
+       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 (ret != 1) {
+               dprintk(FE_ERROR, 1, "I/O Error");
+               ret = -EREMOTEIO;
+       } else {
+               ret = 0;
+       }
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return ret;
+}
+
+static int tda18272_wr(struct tda18272_state *tda18272, u8 reg, u8 data)
+{
+       return tda18272_wr_regs(tda18272, reg, &data, 1);
+}
+
+static int tda18272_rd(struct tda18272_state *tda18272, u8 reg, u8 *data)
+{
+       return tda18272_rd_regs(tda18272, reg, data, 1);
+}
+
+static int tda18272_cal_wait(struct tda18272_state *tda18272)
+{
+       int ret = 0;
+       u8 xtal_cal, count = 20;
+
+       while (count > 0) {
+               ret = tda18272_rd(tda18272, TDA18272_IRQ_STATUS, &tda18272->regs[TDA18272_IRQ_STATUS]);
+               xtal_cal = TDA18272_GETFIELD(IRQ_STATUS_XTALCAL_STATUS, tda18272->regs[TDA18272_IRQ_STATUS]);
+               if (ret)
+                       break;
+
+               if (xtal_cal)
+                       break;
+
+               msleep(5);
+               --count;
+               if (!count) {
+                       ret = -1;
+                       break;
+               }
+       }
+       dprintk(FE_DEBUG, 1, "ret=%d", ret);
+       return ret;
+}
+
+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)
+{
+       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(tda18272->regs[TDA18272_REFERENCE], REFERENCE_DIGITAL_CLOCK, 0);
+               ret = tda18272_wr(tda18272, TDA18272_REFERENCE, tda18272->regs[TDA18272_REFERENCE]);
+               if (ret)
+                       goto err;
+       }
+
+       switch (pstate) {
+       case TDA18272_NORMAL:
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_POWERSTATE_BYTE_2], POWERSTATE_BYTE_2_SM, 0x00);
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_POWERSTATE_BYTE_2], POWERSTATE_BYTE_2_SM_PLL, 0x00);
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_POWERSTATE_BYTE_2], POWERSTATE_BYTE_2_SM_LNA, 0x00);
+               break;
+       case TDA18272_STDBY_1:
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_POWERSTATE_BYTE_2], POWERSTATE_BYTE_2_SM, 0x01);
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_POWERSTATE_BYTE_2], POWERSTATE_BYTE_2_SM_PLL, 0x00);
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_POWERSTATE_BYTE_2], POWERSTATE_BYTE_2_SM_LNA, 0x00);
+               break;
+       case TDA18272_STDBY_2:
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_POWERSTATE_BYTE_2], POWERSTATE_BYTE_2_SM, 0x01);
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_POWERSTATE_BYTE_2], POWERSTATE_BYTE_2_SM_PLL, 0x01);
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_POWERSTATE_BYTE_2], POWERSTATE_BYTE_2_SM_LNA, 0x00);
+               break;
+       case TDA18272_STDBY:
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_POWERSTATE_BYTE_2], POWERSTATE_BYTE_2_SM, 0x01);
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_POWERSTATE_BYTE_2], POWERSTATE_BYTE_2_SM_PLL, 0x01);
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_POWERSTATE_BYTE_2], POWERSTATE_BYTE_2_SM_LNA, 0x01);
+               break;
+       }
+       ret = tda18272_wr(tda18272, TDA18272_POWERSTATE_BYTE_2, tda18272->regs[TDA18272_POWERSTATE_BYTE_2]);
+       if (ret)
+               goto err;
+
+       if (pstate == TDA18272_NORMAL) {
+               if (tda18272->ms)
+                       TDA18272_SETFIELD(tda18272->regs[TDA18272_REFERENCE], REFERENCE_XTOUT, 0x03);
+
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_REFERENCE], REFERENCE_DIGITAL_CLOCK, 0x01);
+               ret = tda18272_wr(tda18272, TDA18272_REFERENCE, tda18272->regs[TDA18272_REFERENCE]);
+               if (ret)
+                       goto err;
+       }
+err:
+       dprintk(FE_DEBUG, 1, "ret=%d", ret);
+       return ret;
+}
+
+static int tda18272_wait_irq(struct tda18272_state *tda18272, u32 timeout, u32 step, u8 status)
+{
+       int ret;
+       u8 irq_status;
+       u32 count = timeout / step;
+
+       BUG_ON(!count);
+       do {
+               ret = tda18272_rd(tda18272, TDA18272_IRQ_STATUS, &tda18272->regs[TDA18272_IRQ_STATUS]);
+               if (ret)
+                       break;
+
+               if (TDA18272_GETFIELD(IRQ_STATUS_IRQ_STATUS, tda18272->regs[TDA18272_IRQ_STATUS]))
+                       break;
+
+               if (status) {
+                       irq_status = tda18272->regs[TDA18272_IRQ_STATUS] & 0x1f;
+                       if (status == irq_status)
+                               break;
+               }
+               msleep(step);
+               --count;
+               if (!count) {
+                       ret = -1;
+                       break;
+               }
+       } while (count);
+       dprintk(FE_DEBUG, 1, "ret=%d", ret);
+       return ret;
+}
+
+static int tda18272_reset(struct tda18272_state *tda18272)
+{
+       int ret;
+
+       ret = tda18272_rd_regs(tda18272, TDA18272_ID_BYTE_1, tda18272->regs, TDA18272_REGMAPSIZ);
+       if (ret)
+               goto err;
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_POWER_BYTE_2], POWER_BYTE_2_RSSI_CK_SPEED, 0x00);
+       ret = tda18272_wr(tda18272, TDA18272_POWER_BYTE_2, tda18272->regs[TDA18272_POWER_BYTE_2]);
+       if (ret)
+               goto err;
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_AGC1_BYTE_2], AGC1_BYTE_2_AGC1_DO_STEP, 0x02);
+       ret = tda18272_wr(tda18272, TDA18272_AGC1_BYTE_2, tda18272->regs[TDA18272_AGC1_BYTE_2]);
+       if (ret)
+               goto err;
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_RF_FILTER_BYTE_3], RF_FILTER_BYTE_3_AGC2_DO_STEP, 0x01);
+       ret = tda18272_wr(tda18272, TDA18272_RF_FILTER_BYTE_3, tda18272->regs[TDA18272_RF_FILTER_BYTE_3]);
+       if (ret)
+               goto err;
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_AGCK_BYTE_1], AGC1_BYTE_1_AGCs_UP_STEP_ASYM, 0x03);
+       ret = tda18272_wr(tda18272, TDA18272_AGCK_BYTE_1, tda18272->regs[TDA18272_AGCK_BYTE_1]);
+       if (ret)
+               goto err;
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_AGC5_BYTE_1], AGC5_BYTE_1_AGCs_DO_STEP_ASYM, 0x02);
+       ret = tda18272_wr(tda18272, TDA18272_AGC5_BYTE_1, tda18272->regs[TDA18272_AGC5_BYTE_1]);
+       if (ret)
+               goto err;
+       ret = tda18272_wr(tda18272, TDA18272_IRQ_CLEAR, 0x9f);
+       if (ret)
+               goto err;
+       ret = tda18272_pstate(tda18272, TDA18272_NORMAL);
+       if (ret) {
+               dprintk(FE_ERROR, 1, "Power state switch failed, ret=%d", 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:
+       dprintk(FE_DEBUG, 1, "ret=%d", ret);
+       return ret;
+}
+
+static int tda18272_init(struct dvb_frontend *fe)
+{
+       struct tda18272_state *tda18272 = fe->tuner_priv;
+       int ret;
+
+       if (tda18272->mode) {
+               dprintk(FE_DEBUG, 1, "Initializing Master ..");
+               ret = tda18272_cal_wait(tda18272);
+               if (ret)
+                       goto err;
+       } else {
+               dprintk(FE_DEBUG, 1, "Initializing Slave ..");
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_FLO_MAX_BYTE], FLO_MAX_BYTE_FMAX_LO, 0x00);
+               ret = tda18272_wr(tda18272, TDA18272_FLO_MAX_BYTE, tda18272->regs[TDA18272_FLO_MAX_BYTE]);
+               if (ret)
+                       goto err;
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_CP_CURRENT], CP_CURRENT_N_CP_CURRENT, 0x68);
+               ret = tda18272_wr(tda18272, TDA18272_CP_CURRENT, tda18272->regs[TDA18272_CP_CURRENT]);
+       }
+       ret = tda18272_reset(tda18272);
+       if (ret)
+               goto err;
+
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_FLO_MAX_BYTE], FLO_MAX_BYTE_FMAX_LO, 0x0a);
+       ret = tda18272_wr(tda18272, TDA18272_FLO_MAX_BYTE, tda18272->regs[TDA18272_FLO_MAX_BYTE]);
+       if (ret)
+               goto err;
+
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_AGC1_BYTE_1], AGC1_BYTE_1_LT_ENABLE, tda18272->lna_top);
+       ret = tda18272_wr(tda18272, TDA18272_AGC1_BYTE_1, tda18272->regs[TDA18272_AGC1_BYTE_1]);
+       if (ret)
+               goto err;
+
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_PSM_BYTE_1], PSM_BYTE_1_PSM_AGC1, tda18272->psm_agc);
+       ret = tda18272_wr(tda18272, TDA18272_PSM_BYTE_1, tda18272->regs[TDA18272_PSM_BYTE_1]);
+       if (ret)
+               goto err;
+
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_AGC1_BYTE_1], AGC1_BYTE_1_AGC1_6_15DB, tda18272->agc1);
+       ret = tda18272_wr(tda18272, TDA18272_AGC1_BYTE_1, tda18272->regs[TDA18272_AGC1_BYTE_1]);
+       if (ret)
+               goto err;
+err:
+       dprintk(FE_DEBUG, 1, "ret=%d", ret);
+       return ret;
+}
+
+static int tda18272_clear_irq(struct tda18272_state *tda18272, u8 status)
+{
+       tda18272->regs[TDA18272_IRQ_CLEAR] = status & 0x1f;
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_IRQ_CLEAR], IRQ_CLEAR_IRQ_CLEAR, 0x80);
+       return tda18272_wr(tda18272, TDA18272_IRQ_CLEAR, tda18272->regs[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:
+       dprintk(FE_DEBUG, 1, "ret=%d", ret);
+       return ret;
+}
+
+static int tda18272_set_frequency(struct tda18272_state *tda18272, u32 frequency)
+{
+       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;
+
+       dprintk(FE_DEBUG, 1, "set freq=%d", frequency);
+
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_IF_BYTE_1], IF_BYTE_1_LP_FC, coe->lpf); /* LPF */
+       ret = tda18272_wr(tda18272, TDA18272_IF_BYTE_1, tda18272->regs[TDA18272_IF_BYTE_1]);
+       if (ret)
+               goto err;
+
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_IF_BYTE_1], IF_BYTE_1_LP_FC_OFFSET, coe->lpf_off);
+       ret = tda18272_wr(tda18272, TDA18272_IF_BYTE_1, tda18272->regs[TDA18272_IF_BYTE_1]);
+       if (ret)
+               goto err;
+
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_IFAGC], IFAGC_IF_LEVEL, coe->if_gain);
+       ret = tda18272_wr(tda18272, TDA18272_IFAGC, tda18272->regs[TDA18272_IFAGC]);
+       if (ret)
+               goto err;
+
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_IF_BYTE_1], IF_BYTE_1_IF_NOTCH, coe->if_notch);
+       ret = tda18272_wr(tda18272, TDA18272_IF_BYTE_1, tda18272->regs[TDA18272_IF_BYTE_1]);
+       if (ret)
+               goto err;
+
+       if (coe->if_hpf == TDA18272_HPF_DISABLED) {
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_IRMIXER_BYTE_2], IRMIXER_BYTE_2_HI_PASS, 0x0);
+               ret = tda18272_wr(tda18272, TDA18272_IRMIXER_BYTE_2, tda18272->regs[TDA18272_IRMIXER_BYTE_2]);
+               if (ret)
+                       goto err;
+       } else {
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_IRMIXER_BYTE_2], IRMIXER_BYTE_2_HI_PASS, 0x1);
+               ret = tda18272_wr(tda18272, TDA18272_IRMIXER_BYTE_2, tda18272->regs[TDA18272_IRMIXER_BYTE_2]);
+               if (ret)
+                       goto err;
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_IF_BYTE_1], IF_BYTE_1_IF_HP_FC, (coe->if_hpf - 1));
+               ret = tda18272_wr(tda18272, TDA18272_IF_BYTE_1, tda18272->regs[TDA18272_IF_BYTE_1]);
+               if (ret)
+                       goto err;
+       }
+
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_IRMIXER_BYTE_2], IRMIXER_BYTE_2_DC_NOTCH, coe->dc_notch);
+       ret = tda18272_wr(tda18272, TDA18272_IRMIXER_BYTE_2, tda18272->regs[TDA18272_IRMIXER_BYTE_2]);
+       if (ret)
+               goto err;
+
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_AGC1_BYTE_1], AGC1_BYTE_1_AGC1_TOP, coe->lna_top);
+       ret = tda18272_wr(tda18272, TDA18272_AGC1_BYTE_1, tda18272->regs[TDA18272_AGC1_BYTE_1]);
+       if (ret)
+               goto err;
+
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_AGC2_BYTE_1], AGC2_BYTE_1_AGC2_TOP, coe->rfatt_top);
+       ret = tda18272_wr(tda18272, TDA18272_AGC2_BYTE_1, tda18272->regs[TDA18272_AGC2_BYTE_1]);
+       if (ret)
+               goto err;
+
+       if (frequency < TDA18272_AGC3_RF_AGC_TOP_FREQ_LIM)
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_RFAGC_BYTE_1], RFAGC_BYTE_1_AGC3_TOP, coe->loband_rfagc_top);
+       else
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_RFAGC_BYTE_1], RFAGC_BYTE_1_AGC3_TOP, coe->hiband_rfagc_top);
+       ret= tda18272_wr(tda18272, TDA18272_RFAGC_BYTE_1, tda18272->regs[TDA18272_RFAGC_BYTE_1]);
+       if (ret)
+               goto err;
+
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_IRMIXER_BYTE_1], IRMIXER_BYTE_1_AGC4_TOP, coe->irmix_top);
+       ret = tda18272_wr(tda18272, TDA18272_IRMIXER_BYTE_1, tda18272->regs[TDA18272_IRMIXER_BYTE_1]);
+       if (ret)
+               goto err;
+
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_AGC5_BYTE_1], AGC5_BYTE_1_AGC5_TOP, coe->ifagc_top);
+       ret = tda18272_wr(tda18272, TDA18272_AGC5_BYTE_1, tda18272->regs[TDA18272_AGC5_BYTE_1]);
+       if (ret)
+               goto err;
+
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_RFAGC_BYTE_1], RFAGC_BYTE_1_PD_RFAGC_ADAPT, coe->agc3_adapt);
+       ret = tda18272_wr(tda18272, TDA18272_RFAGC_BYTE_1, tda18272->regs[TDA18272_RFAGC_BYTE_1]);
+       if (ret)
+               goto err;
+
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_RFAGC_BYTE_1], RFAGC_BYTE_1_RFAGC_ADAPT_TOP, coe->agc3_adapt_top);
+       ret = tda18272_wr(tda18272, TDA18272_RFAGC_BYTE_1, tda18272->regs[TDA18272_RFAGC_BYTE_1]);
+       if (ret)
+               goto err;
+
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_RFAGC_BYTE_1], RFAGC_BYTE_1_RF_ATTEN_3DB, coe->att3db);
+       ret = tda18272_wr(tda18272, TDA18272_RFAGC_BYTE_1, tda18272->regs[TDA18272_RFAGC_BYTE_1]);
+       if (ret)
+               goto err;
+
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_AGC5_BYTE_1], AGC5_BYTE_1_AGC5_HPF, coe->det_hpf);
+       ret = tda18272_wr(tda18272, TDA18272_AGC5_BYTE_1, tda18272->regs[TDA18272_AGC5_BYTE_1]);
+       if (ret)
+               goto err;
+
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_AGCK_BYTE_1], AGCK_BYTE_1_AGCK_MODE, coe->gsk & 0x03);
+       ret = tda18272_wr(tda18272, TDA18272_AGCK_BYTE_1, tda18272->regs[TDA18272_AGCK_BYTE_1]);
+       if (ret)
+               goto err;
+
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_AGCK_BYTE_1], AGCK_BYTE_1_AGCK_STEP, (coe->gsk & 0x0c) >> 2);
+       ret = tda18272_wr(tda18272, TDA18272_AGCK_BYTE_1, tda18272->regs[TDA18272_AGCK_BYTE_1]);
+       if (ret)
+               goto err;
+
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_PSM_BYTE_1], PSM_BYTE_1_PSM_STOB, coe->filter);
+       ret = tda18272_wr(tda18272, TDA18272_PSM_BYTE_1, tda18272->regs[TDA18272_PSM_BYTE_1]);
+       if (ret)
+               goto err;
+
+       TDA18272_SETFIELD(tda18272->regs[TDA18272_IF_FREQUENCY], IF_FREQUENCY_IF_FREQ, (coe->if_val - coe->cf_off) / 50000);
+       ret = tda18272_wr(tda18272, TDA18272_IF_FREQUENCY, tda18272->regs[TDA18272_IF_FREQUENCY]);
+       if (ret)
+               goto err;
+
+       if (coe->ltosto_immune && tda18272->mode) {
+               ret = tda18272_rd(tda18272, TDA18272_RF_AGC_GAIN_BYTE_1, &tda18272->regs[TDA18272_RF_AGC_GAIN_BYTE_1]);
+               if (ret)
+                       goto err;
+               rffilt_gv = TDA18272_GETFIELD(RF_AGC_GAIN_BYTE_1_RF_FILTER_GAIN, tda18272->regs[TDA18272_RF_AGC_GAIN_BYTE_1]);
+
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_RF_FILTER_BYTE_1], RF_FILTER_BYTE_1_RF_FILTER_GV, rffilt_gv);
+               ret = tda18272_wr(tda18272, TDA18272_RF_FILTER_BYTE_1, tda18272->regs[TDA18272_RF_FILTER_BYTE_1]);
+               if (ret)
+                       goto err;
+
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_RF_FILTER_BYTE_1], RF_FILTER_BYTE_1_FORCE_AGC2_GAIN, 0x1);
+               ret = tda18272_wr(tda18272, TDA18272_RF_FILTER_BYTE_1, tda18272->regs[TDA18272_RF_FILTER_BYTE_1]);
+               if (ret)
+                       goto err;
+
+               if (rffilt_gv) {
+                       do {
+                               TDA18272_SETFIELD(tda18272->regs[TDA18272_RF_FILTER_BYTE_1], RF_FILTER_BYTE_1_RF_FILTER_GV, (rffilt_gv - 1));
+                               ret = tda18272_wr(tda18272, TDA18272_RF_FILTER_BYTE_1, tda18272->regs[TDA18272_RF_FILTER_BYTE_1]);
+                               if (ret)
+                                       goto err;
+
+                               msleep(10);
+                               rffilt_gv -= 1;
+                       } while (rffilt_gv > 0);
+               }
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_RFAGC_BYTE_1], RFAGC_BYTE_1_RF_ATTEN_3DB, 0x01);
+               ret = tda18272_wr(tda18272, TDA18272_RFAGC_BYTE_1, tda18272->regs[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(tda18272->regs[TDA18272_RFAGC_BYTE_1], RFAGC_BYTE_1_RF_ATTEN_3DB, 0x00);
+               ret = tda18272_wr(tda18272, TDA18272_RFAGC_BYTE_1, tda18272->regs[TDA18272_RFAGC_BYTE_1]);
+               if (ret)
+                       goto err;
+
+               msleep(50);
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_RF_FILTER_BYTE_1], RF_FILTER_BYTE_1_FORCE_AGC2_GAIN, 0x1);
+               ret = tda18272_wr(tda18272, TDA18272_RF_FILTER_BYTE_1, tda18272->regs[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(tda18272->regs[TDA18272_REFERENCE], REFERENCE_DIGITAL_CLOCK, 0x1);
+       } else if (frequency < 104000000 ) {
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_REFERENCE], REFERENCE_DIGITAL_CLOCK, 0x0);
+       } else if (frequency <= 120000000) {
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_REFERENCE], REFERENCE_DIGITAL_CLOCK, 0x1);
+       } else {
+               if (delta_l <= delta_h) {
+                       if (ratio_l & 0x000001)
+                               TDA18272_SETFIELD(tda18272->regs[TDA18272_REFERENCE], REFERENCE_DIGITAL_CLOCK, 0x0);
+                       else
+                               TDA18272_SETFIELD(tda18272->regs[TDA18272_REFERENCE], REFERENCE_DIGITAL_CLOCK, 0x1);
+               } else {
+                       if (ratio_l & 0x000001)
+                               TDA18272_SETFIELD(tda18272->regs[TDA18272_REFERENCE], REFERENCE_DIGITAL_CLOCK, 0x1);
+                       else
+                               TDA18272_SETFIELD(tda18272->regs[TDA18272_REFERENCE], REFERENCE_DIGITAL_CLOCK, 0x0);
+               }
+       }
+       ret = tda18272_wr(tda18272, TDA18272_REFERENCE, tda18272->regs[TDA18272_REFERENCE]);
+       if (ret)
+               goto err;
+
+       if (coe->agc1_freeze) {
+               tda18272_rd(tda18272, TDA18272_AGC1_BYTE_2, &tda18272->regs[TDA18272_AGC1_BYTE_2]);
+               loop_off = TDA18272_GETFIELD(AGC1_BYTE_2_AGC1_LOOP_OFF, tda18272->regs[TDA18272_AGC1_BYTE_2]);
+               if (!loop_off) {
+                       TDA18272_SETFIELD(tda18272->regs[TDA18272_AGC1_BYTE_2], AGC1_BYTE_2_AGC1_LOOP_OFF, 0x1);
+                       ret = tda18272_wr(tda18272, TDA18272_AGC1_BYTE_2, tda18272->regs[TDA18272_AGC1_BYTE_2]);
+                       if (ret)
+                               goto err;
+                       TDA18272_SETFIELD(tda18272->regs[TDA18272_AGC1_BYTE_2], AGC1_BYTE_2_FORCE_AGC1_GAIN, 0x01);
+                       ret = tda18272_wr(tda18272, TDA18272_AGC1_BYTE_2, tda18272->regs[TDA18272_AGC1_BYTE_2]);
+                       if (ret)
+                               goto err;
+               }
+               if (!TDA18272_GETFIELD(AGC1_BYTE_1_AGC1_6_15DB, tda18272->regs[TDA18272_AGC1_BYTE_1])) {
+                       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, &tda18272->regs[TDA18272_AGC_DET_OUT]);
+                               if (ret)
+                                       goto err;
+                               steps_down += (TDA18272_GETFIELD(AGC_DET_OUT_DO_AGC1, tda18272->regs[TDA18272_AGC_DET_OUT]) ? 14 : -1 );
+                               steps_up += (TDA18272_GETFIELD(AGC_DET_OUT_UP_AGC1, tda18272->regs[TDA18272_AGC_DET_OUT]) ? 1 : -4 );
+                               msleep(1);
+                       } if (steps_up >= 15 && (TDA18272_GETFIELD(AGC1_BYTE_2_AGC1_GAIN, tda18272->regs[TDA18272_AGC1_BYTE_2]) != 9)) {
+                               g1 = TDA18272_GETFIELD(AGC1_BYTE_2_AGC1_GAIN, tda18272->regs[TDA18272_AGC1_BYTE_2]) + 1;
+                               TDA18272_SETFIELD(tda18272->regs[TDA18272_AGC1_BYTE_2], AGC1_BYTE_2_AGC1_GAIN, g1);
+                               ret = tda18272_wr(tda18272, TDA18272_AGC1_BYTE_2, tda18272->regs[TDA18272_AGC1_BYTE_2]);
+                               if (ret)
+                                       goto err;
+                       } else if (steps_down >= 10 && TDA18272_GETFIELD(AGC1_BYTE_2_AGC1_GAIN, tda18272->regs[TDA18272_AGC1_BYTE_2]) != agc1) {
+                               g1 = TDA18272_GETFIELD(AGC1_BYTE_2_AGC1_GAIN, tda18272->regs[TDA18272_AGC1_BYTE_2]) - 1;
+                               TDA18272_SETFIELD(tda18272->regs[TDA18272_AGC1_BYTE_2], AGC1_BYTE_2_AGC1_GAIN, g1);
+                               ret = tda18272_wr(tda18272, TDA18272_AGC1_BYTE_2, tda18272->regs[TDA18272_AGC1_BYTE_2]);
+                               if (ret)
+                                       goto err;
+                       } else {
+                               done = agc1_steps;
+                       }
+               }
+       } else {
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_AGC1_BYTE_2], AGC1_BYTE_2_FORCE_AGC1_GAIN, 0x00);
+               ret = tda18272_wr(tda18272, TDA18272_AGC1_BYTE_2, tda18272->regs[TDA18272_AGC1_BYTE_2]);
+               if (ret)
+                       goto err;
+
+               TDA18272_SETFIELD(tda18272->regs[TDA18272_AGC1_BYTE_2], AGC1_BYTE_2_AGC1_LOOP_OFF, 0x00);
+               ret = tda18272_wr(tda18272, TDA18272_AGC1_BYTE_2, tda18272->regs[TDA18272_AGC1_BYTE_2]);
+               if (ret)
+                       goto err;
+       }
+err:
+       dprintk(FE_DEBUG, 1, "ret=%d", ret);
+       return ret;
+}
+
+static int tda18272_get_status(struct dvb_frontend *fe, u32 *status)
+{
+       struct tda18272_state *tda18272 = fe->tuner_priv;
+       int ret = 0;
+
+       *status = 0;
+
+       ret = tda18272_wr(tda18272, TDA18272_THERMO_BYTE_2, 0x01);
+       if (ret)
+               goto err;
+
+       ret = tda18272_rd(tda18272, TDA18272_THERMO_BYTE_1, &tda18272->regs[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(POWERSTATE_BYTE_1_LO_LOCK, tda18272->regs[TDA18272_POWERSTATE_BYTE_1])) {
+               dprintk(FE_ERROR, 1, "PLL Locked");
+               *status |= 0x01;
+       }
+       if ((tda18272->regs[TDA18272_POWERSTATE_BYTE_2] >> 1) == 0)
+               dprintk(FE_ERROR, 1, "Normal MODE");
+       if ((tda18272->regs[TDA18272_POWERSTATE_BYTE_2] >> 1) == 7)
+               dprintk(FE_ERROR, 1, "Standby MODE, LNA=ON, PLL=OFF");
+       if ((tda18272->regs[TDA18272_POWERSTATE_BYTE_2] >> 1) == 6)
+               dprintk(FE_ERROR, 1, "Standby MODE, LNA=ON, PLL=OFF");
+       if ((tda18272->regs[TDA18272_POWERSTATE_BYTE_2] >> 1) == 4)
+               dprintk(FE_ERROR, 1, "Standby MODE, LNA=ON, PLL=ON");
+
+       dprintk(FE_ERROR, 1, "Junction Temperature:%d Power level:%d",
+               tda18272->regs[TDA18272_THERMO_BYTE_1],
+               tda18272->regs[TDA18272_INPUT_POWERLEVEL]);
+
+err:
+       dprintk(FE_DEBUG, 1, "ret=%d", ret);
+       return ret;
+}
+
+static int tda18272_set_state(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state)
+{
+       return -EINVAL;
+}
+
+static int tda18272_get_state(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state)
+{
+       struct tda18272_state *tda18272         = fe->tuner_priv;
+       const struct tda18272_coeff *coe        = tda18272->coe;
+       int ret;
+
+       switch (param) {
+       case DVBFE_TUNER_FREQUENCY:
+               state->frequency = tda18272->frequency;
+               ret = 0;
+               break;
+       case DVBFE_TUNER_TUNERSTEP:
+               state->tunerstep = fe->ops.tuner_ops.info.frequency_step;
+               ret = 0;
+               break;
+       case DVBFE_TUNER_IFFREQ:
+               state->ifreq = coe->if_val;
+               ret = 0;
+               break;
+       case DVBFE_TUNER_BANDWIDTH:
+               if (fe->ops.info.type == FE_OFDM)
+                       state->bandwidth = tda18272->bandwidth;
+               ret = 0;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       return ret;
+}
+
+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;
+
+       BUG_ON(!tda18272);
+
+       dprintk(FE_DEBUG, 1, "freq=%d, bw=%d", 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;
+       }
+       BUG_ON(!coe);
+       tda18272->coe = coe;
+       dprintk(FE_DEBUG, 1, "Loading %s coeffecients...", 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:
+       dprintk(FE_DEBUG, 1, "ret=%d", 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;
+
+       BUG_ON(!tda18272);
+       fe->tuner_priv = NULL;
+       kfree(tda18272);
+       return 0;
+}
+
+static struct dvb_tuner_ops tda18272_ops = {
+       .info = {
+               .name           = "TDA18272 Silicon Tuner",
+               .frequency_min  =  42000000,
+               .frequency_max  = 870000000,
+               .frequency_step = 50000,
+       },
+       .init                   = tda18272_init,
+//     .sleep                  = tda18272_sleep,
+       .get_status             = tda18272_get_status,
+       .set_params             = tda18272_set_params,
+       .set_state              = tda18272_set_state,
+       .get_state              = tda18272_get_state,
+       .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;
+       u8 major = 0, minor = 0, mode = 0;
+       int id = 0, ret;
+
+       tda18272 = kzalloc(sizeof (struct tda18272_state), GFP_KERNEL);
+       if (!tda18272)
+               goto err;
+
+       BUG_ON(!i2c);
+       BUG_ON(!config);
+
+       tda18272->i2c           = i2c;
+       tda18272->config        = config;
+       tda18272->fe            = fe;
+
+       fe->tuner_priv          = tda18272;
+       fe->ops.tuner_ops       = tda18272_ops;
+
+       ret = tda18272_rd_regs(tda18272, TDA18272_ID_BYTE_1, &tda18272->regs[TDA18272_ID_BYTE_1], 3);
+       if (ret)
+               goto err;
+
+       id    = (TDA18272_GETFIELD(ID_BYTE_1_IDENT, tda18272->regs[TDA18272_ID_BYTE_1]) << 8) |
+                TDA18272_GETFIELD(ID_BYTE_2_IDENT, tda18272->regs[TDA18272_ID_BYTE_2]);
+
+       major = TDA18272_GETFIELD(ID_BYTE_3_MAJOR_REV, tda18272->regs[TDA18272_ID_BYTE_3]);
+       minor = TDA18272_GETFIELD(ID_BYTE_3_MINOR_REV, tda18272->regs[TDA18272_ID_BYTE_3]);
+       mode  = TDA18272_GETFIELD(ID_BYTE_1_MASTER_SLAVE, tda18272->regs[TDA18272_ID_BYTE_1]);
+
+       if (id == TDA18272_CHIP_ID) {
+               dprintk(FE_ERROR, 1, "Found TDA%d %s Rev:%d.%d", id, mode ? "Master" : "Slave", major, minor);
+               if ((major != TDA18272_MAJOR_REV) || (minor != TDA18272_MINOR_REV))
+                       dprintk(FE_ERROR, 1, "Unknown Version:%d.%d, trying anyway ..", major, minor);
+
+               tda18272->mode    = mode;
+               if (config->mode == TDA18272_SLAVE && tda18272->mode == 1)
+                       dprintk(FE_ERROR, 1, "Config as TDA18272 Slave, but TDA18272 Master found ???");
+
+               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) {
+                       dprintk(FE_ERROR, 1, "Error Initializing!");
+                       goto err1;
+               }
+
+               dprintk(FE_DEBUG, 1, "Done");
+               return tda18272->fe;
+       }
+err:
+       dprintk(FE_ERROR, 1, "TDA18272 not found!, ID=0x%02x exiting..", id);
+err1:
+       kfree(tda18272);
+       return NULL;
+}
+EXPORT_SYMBOL(tda18272_attach);
+
+MODULE_AUTHOR("Manu Abraham");
+MODULE_DESCRIPTION("TDA18272 Silicon tuner");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/tuners/tda18272.h b/drivers/media/tuners/tda18272.h
new file mode 100644 (file)
index 0000000..179428d
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+       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.
+ */
+
+#ifndef __TDA18272_H
+#define __TDA18272_H
+
+enum tda18272_mode {
+       TDA18272_SINGLE = 0,
+       TDA18272_MASTER,
+       TDA18272_SLAVE,
+};
+
+struct tda18272_config {
+       u8                      addr;
+       enum tda18272_mode      mode;
+};
+
+#if IS_ENABLED(CONFIG_MEDIA_TUNER_TDA18272)
+
+extern struct dvb_frontend *tda18272_attach(struct dvb_frontend *fe,
+                                           struct i2c_adapter *i2c,
+                                           const struct tda18272_config *config);
+
+#else
+static inline struct dvb_frontend *tda18272_attach(struct dvb_frontend *fe,
+                                                  struct i2c_adapter *i2c,
+                                                  const struct tda18272_config *config)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+
+#endif /* CONFIG_MEDIA_TUNER_TDA18272 */
+
+#endif /* __TDA18272_H */
diff --git a/drivers/media/tuners/tda18272_reg.h b/drivers/media/tuners/tda18272_reg.h
new file mode 100644 (file)
index 0000000..fbcb97b
--- /dev/null
@@ -0,0 +1,532 @@
+/*
+       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.
+ */
+
+#ifndef __TDA18272_REG_H
+#define __TDA18272_REG_H
+
+#define TDA18272_ID_BYTE_1                                     0x00
+#define TDA18272_OFFST_ID_BYTE_1_MASTER_SLAVE                  7
+#define TDA18272_WIDTH_ID_BYTE_1_MASTER_SLAVE                  1
+#define TDA18272_OFFST_ID_BYTE_1_IDENT                         0
+#define TDA18272_WIDTH_ID_BYTE_1_IDENT                         7
+
+#define TDA18272_ID_BYTE_2                                     0x01
+#define TDA18272_OFFST_ID_BYTE_2_IDENT                         0
+#define TDA18272_WIDTH_ID_BYTE_2_IDENT                         8
+
+#define TDA18272_ID_BYTE_3                                     0x02
+#define TDA18272_OFFST_ID_BYTE_3_MAJOR_REV                     4
+#define TDA18272_WIDTH_ID_BYTE_3_MAJOR_REV                     4
+#define TDA18272_OFFST_ID_BYTE_3_MINOR_REV                     0
+#define TDA18272_WIDTH_ID_BYTE_3_MINOR_REV                     4
+
+#define TDA18272_THERMO_BYTE_1                                 0x03
+#define TDA18272_OFFST_THERMO_BYTE_1_TM_D                      0
+#define TDA18272_WIDTH_THERMO_BYTE_1_TM_D                      7
+
+#define TDA18272_THERMO_BYTE_2                                 0x04
+#define TDA18272_OFFST_THERMO_BYTE_2_TM_ON                     O
+#define TDA18272_WIDTH_THERMO_BYTE_2_TM_ON                     1
+
+#define TDA18272_POWERSTATE_BYTE_1                             0x05
+#define TDA18272_OFFST_POWERSTATE_BYTE_1_POR                   1
+#define TDA18272_WIDTH_POWERSTATE_BYTE_1_POR                   1
+#define TDA18272_OFFST_POWERSTATE_BYTE_1_LO_LOCK               0
+#define TDA18272_WIDTH_POWERSTATE_BYTE_1_LO_LOCK               1
+
+#define TDA18272_POWERSTATE_BYTE_2                             0x06
+#define TDA18272_OFFST_POWERSTATE_BYTE_2_SM_LNA                        1
+#define TDA18272_WIDTH_POWERSTATE_BYTE_2_SM_LNA                        1
+#define TDA18272_OFFST_POWERSTATE_BYTE_2_SM_PLL                        2
+#define TDA18272_WIDTH_POWERSTATE_BYTE_2_SM_PLL                        1
+#define TDA18272_OFFST_POWERSTATE_BYTE_2_SM                    3
+#define TDA18272_WIDTH_POWERSTATE_BYTE_2_SM                    1
+
+#define TDA18272_INPUT_POWERLEVEL                              0x07
+#define TDA18272_OFFST_INPUT_POWERLEVEL_POWER_LEVEL            0
+#define TDA18272_WIDTH_INPUT_POWERLEVEL_POWER_LEVEL            7
+
+#define TDA18272_IRQ_STATUS                                    0x08
+#define TDA18272_OFFST_IRQ_STATUS_IRQ_STATUS                   7
+#define TDA18272_WIDTH_IRQ_STATUS_IRQ_STATUS                   1
+#define TDA18272_OFFST_IRQ_STATUS_XTALCAL_STATUS               5
+#define TDA18272_WIDTH_IRQ_STATUS_XTALCAL_STATUS               1
+#define TDA18272_OFFST_IRQ_STATUS_MSM_RSSI_STATUS              4
+#define TDA18272_WIDTH_IRQ_STATUS_MSM_RSSI_STATUS              1
+#define TDA18272_OFFST_IRQ_STATUS_MSM_LOCALC_STATUS            3
+#define TDA18272_WIDTH_IRQ_STATUS_MSM_LOCALC_STATUS            1
+#define TDA18272_OFFST_IRQ_STATUS_MSM_RFCAL_STATUS             2
+#define TDA18272_WIDTH_IRQ_STATUS_MSM_RFCAL_STATUS             1
+#define TDA18272_OFFST_IRQ_STATUS_MSM_IRCAL_STATUS             1
+#define TDA18272_WIDTH_IRQ_STATUS_MSM_IRCAL_STATUS             1
+#define TDA18272_OFFST_IRQ_STATUS_MSM_RCCAL_STATUS             0
+#define TDA18272_WIDTH_IRQ_STATUS_MSM_RCCAL_STATUS             1
+
+#define TDA18272_IRQ_ENABLE                                    0x09
+#define TDA18272_OFFST_IRQ_ENABLE_IRQ_ENABLE                   7
+#define TDA18272_WIDTH_IRQ_ENABLE_IRQ_ENABLE                   1
+#define TDA18272_OFFST_IRQ_ENABLE_UNUSED_I0_D0                 6
+#define TDA18272_WIDTH_IRQ_ENABLE_UNUSED_I0_D0                 1
+#define TDA18272_OFFST_IRQ_ENABLE_XTALCAL_ENABLE               5
+#define TDA18272_WIDTH_IRQ_ENABLE_XTALCAL_ENABLE               1
+#define TDA18272_OFFST_IRQ_ENABLE_MSM_RSSI_ENABLE              4
+#define TDA18272_WIDTH_IRQ_ENABLE_MSM_RSSI_ENABLE              1
+#define TDA18272_OFFST_IRQ_ENABLE_MSM_LOCALC_ENABLE            3
+#define TDA18272_WIDTH_IRQ_ENABLE_MSM_LOCALC_ENABLE            1
+#define TDA18272_OFFST_IRQ_ENABLE_MSM_RFCAL_ENABLE             2
+#define TDA18272_WIDTH_IRQ_ENABLE_MSM_RFCAL_ENABLE             1
+#define TDA18272_OFFST_IRQ_ENABLE_MSM_IRCAL_ENABLE             1
+#define TDA18272_WIDTH_IRQ_ENABLE_MSM_IRCAL_ENABLE             1
+#define TDA18272_OFFST_IRQ_ENABLE_MSM_RCCAL_ENABLE             0
+#define TDA18272_WIDTH_IRQ_ENABLE_MSM_RCCAL_ENABLE             1
+
+#define TDA18272_IRQ_CLEAR                                     0x0a
+#define TDA18272_OFFST_IRQ_CLEAR_IRQ_CLEAR                     7
+#define TDA18272_WIDTH_IRQ_CLEAR_IRQ_CLEAR                     1
+
+#define TDA18272_IRQ_SET                                       0x0b
+#define TDA18272_OFFST_IRQ_SET_IRQ_SET                         7
+#define TDA18272_WIDTH_IRQ_SET_IRQ_SET                         1
+#define TDA18272_OFFST_IRQ_SET_UNUSED_I0_D0                    6
+#define TDA18272_WIDTH_IRQ_SET_UNUSED_I0_D0                    1
+#define TDA18272_OFFST_IRQ_SET_XTALCAL_SET                     5
+#define TDA18272_WIDTH_IRQ_SET_XTALCAL_SET                     1
+#define TDA18272_OFFST_IRQ_SET_MSM_RSSI_SET                    4
+#define TDA18272_WIDTH_IRQ_SET_MSM_RSSI_SET                    1
+#define TDA18272_OFFST_IRQ_SET_MSM_LOCALC_SET                  3
+#define TDA18272_WIDTH_IRQ_SET_MSM_LOCALC_SET                  1
+#define TDA18272_OFFST_IRQ_SET_MSM_RFCAL_SET                   2
+#define TDA18272_WIDTH_IRQ_SET_MSM_RFCAL_SET                   1
+#define TDA18272_OFFST_IRQ_SET_MSM_IRCAL_SET                   1
+#define TDA18272_WIDTH_IRQ_SET_MSM_IRCAL_SET                   1
+#define TDA18272_OFFST_IRQ_SET_MSM_RCCAL_SET                   0
+#define TDA18272_WIDTH_IRQ_SET_MSM_RCCAL_SET                   1
+
+#define TDA18272_AGC1_BYTE_1                                   0x0c
+#define TDA18272_OFFST_AGC1_BYTE_1_LT_ENABLE                   7
+#define TDA18272_WIDTH_AGC1_BYTE_1_LT_ENABLE                   1
+#define TDA18272_OFFST_AGC1_BYTE_1_AGC1_6_15DB                 6
+#define TDA18272_WIDTH_AGC1_BYTE_1_AGC1_6_15DB                 1
+#define TDA18272_OFFST_AGC1_BYTE_1_AGC1_TOP                    0
+#define TDA18272_WIDTH_AGC1_BYTE_1_AGC1_TOP                    4
+
+#define TDA18272_AGC2_BYTE_1                                   0x0d
+#define TDA18272_OFFST_AGC2_BYTE_1_UNUSED_I0_D0                        5
+#define TDA18272_WIDTH_AGC2_BYTE_1_UNUSED_I0_D0                        3
+#define TDA18272_OFFST_AGC2_BYTE_1_AGC2_TOP                    0
+#define TDA18272_WIDTH_AGC2_BYTE_1_AGC2_TOP                    5
+
+#define TDA18272_AGCK_BYTE_1                                   0x0e
+#define TDA18272_OFFST_AGC1_BYTE_1_AGCs_UP_STEP_ASYM           6
+#define TDA18272_WIDTH_AGC1_BYTE_1_AGCs_UP_STEP_ASYM           2
+#define TDA18272_OFFST_AGCK_BYTE_1_AGCs_UP_STEP                        5
+#define TDA18272_WIDTH_AGCK_BYTE_1_AGCs_UP_STEP                        1
+#define TDA18272_OFFST_AGCK_BYTE_1_PULSE_SHAPER_DISABLE                4
+#define TDA18272_WIDTH_AGCK_BYTE_1_PULSE_SHAPER_DISABLE                1
+#define TDA18272_OFFST_AGCK_BYTE_1_AGCK_STEP                   2
+#define TDA18272_WIDTH_AGCK_BYTE_1_AGCK_STEP                   2
+#define TDA18272_OFFST_AGCK_BYTE_1_AGCK_MODE                   0
+#define TDA18272_WIDTH_AGCK_BYTE_1_AGCK_MODE                   2
+
+#define TDA18272_RFAGC_BYTE_1                                  0x0f
+#define TDA18272_OFFST_RFAGC_BYTE_1_PD_RFAGC_ADAPT             7
+#define TDA18272_WIDTH_RFAGC_BYTE_1_PD_RFAGC_ADAPT             1
+#define TDA18272_OFFST_RFAGC_BYTE_1_RFAGC_ADAPT_TOP            5
+#define TDA18272_WIDTH_RFAGC_BYTE_1_RFAGC_ADAPT_TOP            2
+#define TDA18272_OFFST_RFAGC_BYTE_1_RF_ATTEN_3DB               3
+#define TDA18272_WIDTH_RFAGC_BYTE_1_RF_ATTEN_3DB               1
+#define TDA18272_OFFST_RFAGC_BYTE_1_AGC3_TOP                   0
+#define TDA18272_WIDTH_RFAGC_BYTE_1_AGC3_TOP                   3
+
+#define TDA18272_IRMIXER_BYTE_1                                        0x10
+#define TDA18272_OFFST_IRMIXER_BYTE_1_AGC4_TOP                 0
+#define TDA18272_WIDTH_IRMIXER_BYTE_1_AGC4_TOP                 4
+
+#define TDA18272_AGC5_BYTE_1                                   0x11
+#define TDA18272_OFFST_AGC5_BYTE_1_AGC5_TOP                    0
+#define TDA18272_WIDTH_AGC5_BYTE_1_AGC5_TOP                    4
+#define TDA18272_OFFST_AGC5_BYTE_1_AGC5_HPF                    4
+#define TDA18272_WIDTH_AGC5_BYTE_1_AGC5_HPF                    1
+#define TDA18272_OFFST_AGC5_BYTE_1_AGCs_DO_STEP_ASYM           5
+#define TDA18272_WIDTH_AGC5_BYTE_1_AGCs_DO_STEP_ASYM           2
+
+
+#define TDA18272_IFAGC                                         0x12
+#define TDA18272_OFFST_IFAGC_IF_LEVEL                          0
+#define TDA18272_WIDTH_IFAGC_IF_LEVEL                          3
+
+#define TDA18272_IF_BYTE_1                                     0x13
+#define TDA18272_OFFST_IF_BYTE_1_IF_HP_FC                      6
+#define TDA18272_WIDTH_IF_BYTE_1_IF_HP_FC                      2
+#define TDA18272_OFFST_IF_BYTE_1_IF_NOTCH                      5
+#define TDA18272_WIDTH_IF_BYTE_1_IF_NOTCH                      1
+#define TDA18272_OFFST_IF_BYTE_1_LP_FC_OFFSET                  3
+#define TDA18272_WIDTH_IF_BYTE_1_LP_FC_OFFSET                  2
+#define TDA18272_OFFST_IF_BYTE_1_LP_FC                         0
+#define TDA18272_WIDTH_IF_BYTE_1_LP_FC                         3
+
+#define TDA18272_REFERENCE                                     0x14
+#define TDA18272_OFFST_REFERENCE_XTOUT                         0
+#define TDA18272_WIDTH_REFERENCE_XTOUT                         2
+#define TDA18272_OFFST_REFERENCE_DIGITAL_CLOCK                 6
+#define TDA18272_WIDTH_REFERENCE_DIGITAL_CLOCK                 1
+
+#define TDA18272_IF_FREQUENCY                                  0x15
+#define TDA18272_OFFST_IF_FREQUENCY_IF_FREQ                    0
+#define TDA18272_WIDTH_IF_FREQUENCY_IF_FREQ                    8
+
+#define TDA18272_RF_FREQUENCY_BYTE_1                           0x16
+#define TDA18272_OFFST_RF_FREQUENCY_BYTE_1_RF_FREQ             0
+#define TDA18272_WIDTH_RF_FREQUENCY_BYTE_1_RF_FREQ             4
+
+#define TDA18272_RF_FREQUENCY_BYTE_2                           0x17
+#define TDA18272_OFFST_RF_FREQUENCY_BYTE_2_RF_FREQ             0
+#define TDA18272_WIDTH_RF_FREQUENCY_BYTE_2_RF_FREQ             8
+
+#define TDA18272_RF_FREQUENCY_BYTE_3                           0x18
+#define TDA18272_OFFST_RF_FREQUENCY_BYTE_3_RF_FREQ             0
+#define TDA18272_WIDTH_RF_FREQUENCY_BYTE_3_RF_FREQ             8
+
+#define TDA18272_MSM_BYTE_1                                    0x19
+#define TDA18272_OFFST_MSM_BYTE_1_POWER_MEAS                   7
+#define TDA18272_WIDTH_MSM_BYTE_1_POWER_MEAS                   1
+#define TDA18272_OFFST_MSM_BYTE_1_RF_CAL_AV                    6
+#define TDA18272_WIDTH_MSM_BYTE_1_RF_CAL_AV                    1
+#define TDA18272_OFFST_MSM_BYTE_1_RF_CAL                       5
+#define TDA18272_WIDTH_MSM_BYTE_1_RF_CAL                       1
+#define TDA18272_OFFST_MSM_BYTE_1_IR_CAL                       3
+#define TDA18272_WIDTH_MSM_BYTE_1_IR_CAL                       2
+#define TDA18272_OFFST_MSM_BYTE_1_RC_CAL                       1
+#define TDA18272_WIDTH_MSM_BYTE_1_RC_CAL                       1
+#define TDA18272_OFFST_MSM_BYTE_1_CALC_PLL                     0
+#define TDA18272_WIDTH_MSM_BYTE_1_CALC_PLL                     1
+
+#define TDA18272_MSM_BYTE_2                                    0x1a
+#define TDA18272_OFFST_MSM_BYTE_2_MSM_LAUNCH                   0
+#define TDA18272_WIDTH_MSM_BYTE_2_MSM_LAUNCH                   1
+
+#define TDA18272_PSM_BYTE_1                                    0x1b
+#define TDA18272_OFFST_PSM_BYTE_1_PSM_AGC1                     6
+#define TDA18272_WIDTH_PSM_BYTE_1_PSM_AGC1                     2
+#define TDA18272_OFFST_PSM_BYTE_1_PSM_STOB                     5
+#define TDA18272_WIDTH_PSM_BYTE_1_PSM_STOB                     1
+#define TDA18272_OFFST_PSM_BYTE_1_PSMRFPOLY                    4
+#define TDA18272_WIDTH_PSM_BYTE_1_PSMRFPOLY                    1
+#define TDA18272_OFFST_PSM_BYTE_1_PSM_MIXER                    3
+#define TDA18272_WIDTH_PSM_BYTE_1_PSM_MIXER                    1
+#define TDA18272_OFFST_PSM_BYTE_1_PSM_IFPOLY                   2
+#define TDA18272_WIDTH_PSM_BYTE_1_PSM_IFPOLY                   1
+#define TDA18272_OFFST_PSM_BYTE_1_PSM_LODRIVER                 0
+#define TDA18272_WIDTH_PSM_BYTE_1_PSM_LODRIVER                 2
+
+#define TDA18272_DCC_BYTE_1                                    0x1c
+#define TDA18272_OFFST_DCC_BYTE_1_DCC_BYPASS                   7
+#define TDA18272_WIDTH_DCC_BYTE_1_DCC_BYPASS                   1
+#define TDA18272_OFFST_DCC_BYTE_1_DCC_SLOW                     6
+#define TDA18272_WIDTH_DCC_BYTE_1_DCC_SLOW                     1
+#define TDA18272_OFFST_DCC_BYTE_1_DCC_PSM                      5
+#define TDA18272_WIDTH_DCC_BYTE_1_DCC_PSM                      1
+#define TDA18272_OFFST_DCC_BYTE_1_UNUSED_I0_D0                 0
+#define TDA18272_WIDTH_DCC_BYTE_1_UNUSED_I0_D0                 5
+
+#define TDA18272_FLO_MAX_BYTE                                  0x1d
+#define TDA18272_OFFST_FLO_MAX_BYTE_UNUSED_I0_D0               6
+#define TDA18272_WIDTH_FLO_MAX_BYTE_UNUSED_I0_D0               2
+#define TDA18272_OFFST_FLO_MAX_BYTE_FMAX_LO                    0
+#define TDA18272_WIDTH_FLO_MAX_BYTE_FMAX_LO                    6
+
+#define TDA18272_IR_CAL_BYTE_1                                 0x1e
+#define TDA18272_OFFST_IR_CAL_BYTE_1_IR_LOOP                   6
+#define TDA18272_WIDTH_IR_CAL_BYTE_1_IR_LOOP                   2
+#define TDA18272_OFFST_IR_CAL_BYTE_1_IR_TARGET                 3
+#define TDA18272_WIDTH_IR_CAL_BYTE_1_IR_TARGET                 3
+#define TDA18272_OFFST_IR_CAL_BYTE_1_IR_GSTEP                  0
+#define TDA18272_WIDTH_IR_CAL_BYTE_1_IR_GSTEP                  3
+
+#define TDA18272_IR_CAL_BYTE_2                                 0x1f
+#define TDA18272_OFFST_IR_CAL_BYTE_2_IR_CORR_BOOST             7
+#define TDA18272_WIDTH_IR_CAL_BYTE_2_IR_CORR_BOOST             1
+#define TDA18272_OFFST_IR_CAL_BYTE_2_IR_FREQLOW_SEL            6
+#define TDA18272_WIDTH_IR_CAL_BYTE_2_IR_FREQLOW_SEL            1
+#define TDA18272_OFFST_IR_CAL_BYTE_2_IR_MODE_RAM_STORE         5
+#define TDA18272_WIDTH_IR_CAL_BYTE_2_IR_MODE_RAM_STORE         1
+#define TDA18272_OFFST_IR_CAL_BYTE_2_IR_FREQLOW                        0
+#define TDA18272_WIDTH_IR_CAL_BYTE_2_IR_FREQLOW                        5
+
+#define TDA18272_IR_CAL_BYTE_3                                 0x20
+#define TDA18272_OFFST_IR_CAL_BYTE_3_UNUSED_I0_D0              5
+#define TDA18272_WIDTH_IR_CAL_BYTE_3_UNUSED_I0_D0              3
+#define TDA18272_OFFST_IR_CAL_BYTE_3_IR_FREQMID                        0
+#define TDA18272_WIDTH_IR_CAL_BYTE_3_IR_FREQMID                        5
+
+#define TDA18272_IR_CAL_BYTE_4                                 0x21
+#define TDA18272_OFFST_IR_CAL_BYTE_4_UNUSED_I0_D0              6
+#define TDA18272_WIDTH_IR_CAL_BYTE_4_UNUSED_I0_D0              2
+#define TDA18272_OFFST_IR_CAL_BYTE_4_COARSE_IR_FREQHIGH                5
+#define TDA18272_WIDTH_IR_CAL_BYTE_4_COARSE_IR_FREQHIGH                1
+#define TDA18272_OFFST_IR_CAL_BYTE_4_IR_FREQHIGH               0
+#define TDA18272_WIDTH_IR_CAL_BYTE_4_IR_FREQHIGH               5
+
+#define TDA18272_VSYNC_MGT                                     0x22
+#define TDA18272_OFFST_VSYNC_MGT_PD_VSYNC_MGT                  7
+#define TDA18272_WIDTH_VSYNC_MGT_PD_VSYNC_MGT                  1
+#define TDA18272_OFFST_VSYNC_MGT_PD_OVLD                       6
+#define TDA18272_WIDTH_VSYNC_MGT_PD_OVLD                       1
+#define TDA18272_OFFST_VSYNC_MGT_PD_UDLD                       5
+#define TDA18272_WIDTH_VSYNC_MGT_PD_UDLD                       1
+#define TDA18272_OFFST_VSYNC_MGT_AGC_OVLD_TOP                  2
+#define TDA18272_WIDTH_VSYNC_MGT_AGC_OVLD_TOP                  3
+#define TDA18272_OFFST_VSYNC_MGT_AGC_OVLD_TIMER                        0
+#define TDA18272_WIDTH_VSYNC_MGT_AGC_OVLD_TIMER                        2
+
+#define TDA18272_IRMIXER_BYTE_2                                        0x23
+#define TDA18272_OFFST_IRMIXER_BYTE_2_HI_PASS                  1
+#define TDA18272_WIDTH_IRMIXER_BYTE_2_HI_PASS                  1
+#define TDA18272_OFFST_IRMIXER_BYTE_2_DC_NOTCH                 0
+#define TDA18272_WIDTH_IRMIXER_BYTE_2_DC_NOTCH                 1
+
+#define TDA18272_AGC1_BYTE_2                                   0x24
+#define TDA18272_OFFST_AGC1_BYTE_2_AGC1_LOOP_OFF               7
+#define TDA18272_WIDTH_AGC1_BYTE_2_AGC1_LOOP_OFF               1
+#define TDA18272_OFFST_AGC1_BYTE_2_AGC1_DO_STEP                        5
+#define TDA18272_WIDTH_AGC1_BYTE_2_AGC1_DO_STEP                        2
+#define TDA18272_OFFST_AGC1_BYTE_2_FORCE_AGC1_GAIN             4
+#define TDA18272_WIDTH_AGC1_BYTE_2_FORCE_AGC1_GAIN             1
+#define TDA18272_OFFST_AGC1_BYTE_2_AGC1_GAIN                   0
+#define TDA18272_WIDTH_AGC1_BYTE_2_AGC1_GAIN                   4
+
+#define TDA18272_AGC5_BYTE_2                                   0x25
+#define TDA18272_OFFST_AGC5_BYTE_2_AGC5_LOOP_OFF               7
+#define TDA18272_WIDTH_AGC5_BYTE_2_AGC5_LOOP_OFF               1
+#define TDA18272_OFFST_AGC5_BYTE_2_AGC5_DO_STEP                        5
+#define TDA18272_WIDTH_AGC5_BYTE_2_AGC5_DO_STEP                        2
+#define TDA18272_OFFST_AGC5_BYTE_2_UNUSED_I1_D0                        4
+#define TDA18272_WIDTH_AGC5_BYTE_2_UNUSED_I1_D0                        1
+#define TDA18272_OFFST_AGC5_BYTE_2_FORCE_AGC5_GAIN             3
+#define TDA18272_WIDTH_AGC5_BYTE_2_FORCE_AGC5_GAIN             1
+#define TDA18272_OFFST_AGC5_BYTE_2_UNUSED_I0_D0                        2
+#define TDA18272_WIDTH_AGC5_BYTE_2_UNUSED_I0_D0                        1
+#define TDA18272_OFFST_AGC5_BYTE_2_AGC5_GAIN                   0
+#define TDA18272_WIDTH_AGC5_BYTE_2_AGC5_GAIN                   2
+
+#define TDA18272_RF_CAL_BYTE_1                                 0x26
+#define TDA18272_OFFST_RF_CAL_BYTE_1_RFCAL_OFFSET_CPROG0       6
+#define TDA18272_WIDTH_RF_CAL_BYTE_1_RFCAL_OFFSET_CPROG0       2
+#define TDA18272_OFFST_RF_CAL_BYTE_1_RFCAL_FREQ0               4
+#define TDA18272_WIDTH_RF_CAL_BYTE_1_RFCAL_FREQ0               2
+#define TDA18272_OFFST_RF_CAL_BYTE_1_RFCAL_OFFSET_CPROG1       2
+#define TDA18272_WIDTH_RF_CAL_BYTE_1_RFCAL_OFFSET_CPROG1       2
+#define TDA18272_OFFST_RF_CAL_BYTE_1_RFCAL_FREQ1               0
+#define TDA18272_WIDTH_RF_CAL_BYTE_1_RFCAL_FREQ1               2
+
+#define TDA18272_RF_CAL_BYTE_2         0x27
+#define TDA18272_OFFST_RF_CAL_BYTE_2_RFCAL_OFFSET_CPROG2       6
+#define TDA18272_WIDTH_RF_CAL_BYTE_2_RFCAL_OFFSET_CPROG2       2
+#define TDA18272_OFFST_RF_CAL_BYTE_2_RFCAL_FREQ2               4
+#define TDA18272_WIDTH_RF_CAL_BYTE_2_RFCAL_FREQ2               2
+#define TDA18272_OFFST_RF_CAL_BYTE_2_RFCAL_OFFSET_CPROG3       2
+#define TDA18272_WIDTH_RF_CAL_BYTE_2_RFCAL_OFFSET_CPROG3       2
+#define TDA18272_OFFST_RF_CAL_BYTE_2_RFCAL_FREQ3               0
+#define TDA18272_WIDTH_RF_CAL_BYTE_2_RFCAL_FREQ3               2
+
+#define TDA18272_RF_CAL_BYTE_3                                 0x28
+#define TDA18272_OFFST_RF_CAL_BYTE_3_RFCAL_OFFSET_CPROG4       6
+#define TDA18272_WIDTH_RF_CAL_BYTE_3_RFCAL_OFFSET_CPROG4       2
+#define TDA18272_OFFST_RF_CAL_BYTE_3_RFCAL_FREQ4               4
+#define TDA18272_WIDTH_RF_CAL_BYTE_3_RFCAL_FREQ4               2
+#define TDA18272_OFFST_RF_CAL_BYTE_3_RFCAL_OFFSET_CPROG5       2
+#define TDA18272_WIDTH_RF_CAL_BYTE_3_RFCAL_OFFSET_CPROG5       2
+#define TDA18272_OFFST_RF_CAL_BYTE_3_RFCAL_FREQ5               0
+#define TDA18272_WIDTH_RF_CAL_BYTE_3_RFCAL_FREQ5               2
+
+#define TDA18272_RF_CAL_BYTE_4                                 0x29
+#define TDA18272_OFFST_RF_CAL_BYTE_4_RFCAL_OFFSET_CPROG6       6
+#define TDA18272_WIDTH_RF_CAL_BYTE_4_RFCAL_OFFSET_CPROG6       2
+#define TDA18272_OFFST_RF_CAL_BYTE_4_RFCAL_FREQ6               4
+#define TDA18272_WIDTH_RF_CAL_BYTE_4_RFCAL_FREQ6               2
+#define TDA18272_OFFST_RF_CAL_BYTE_4_RFCAL_OFFSET_CPROG7       2
+#define TDA18272_WIDTH_RF_CAL_BYTE_4_RFCAL_OFFSET_CPROG7       2
+#define TDA18272_OFFST_RF_CAL_BYTE_4_RFCAL_FREQ7               0
+#define TDA18272_WIDTH_RF_CAL_BYTE_4_RFCAL_FREQ7               2
+
+#define TDA18272_RF_CAL_BYTE_5                                 0x2a
+#define TDA18272_OFFST_RF_CAL_BYTE_5_RFCAL_OFFSET_CPROG                6
+#define TDA18272_WIDTH_RF_CAL_BYTE_5_RFCAL_OFFSET_CPROG8       2
+#define TDA18272_OFFST_RF_CAL_BYTE_5_RFCAL_FREQ8               4
+#define TDA18272_WIDTH_RF_CAL_BYTE_5_RFCAL_FREQ8               2
+#define TDA18272_OFFST_RF_CAL_BYTE_5_RFCAL_OFFSET_CPROG9       2
+#define TDA18272_WIDTH_RF_CAL_BYTE_5_RFCAL_OFFSET_CPROG9       2
+#define TDA18272_OFFST_RF_CAL_BYTE_5_RFCAL_FREQ9               0
+#define TDA18272_WIDTH_RF_CAL_BYTE_5_RFCAL_FREQ9               2
+
+#define TDA18272_RF_CAL_BYTE_6                                 0x2b
+#define TDA18272_OFFST_RF_CAL_BYTE_6_RFCAL_OFFSET_CPROG10      6
+#define TDA18272_WIDTH_RF_CAL_BYTE_6_RFCAL_OFFSET_CPROG10      2
+#define TDA18272_OFFST_RF_CAL_BYTE_6_RFCAL_FREQ10              4
+#define TDA18272_WIDTH_RF_CAL_BYTE_6_RFCAL_FREQ10              2
+#define TDA18272_OFFST_RF_CAL_BYTE_6_RFCAL_OFFSET_CPROG11      2
+#define TDA18272_WIDTH_RF_CAL_BYTE_6_RFCAL_OFFSET_CPROG11      2
+#define TDA18272_OFFST_RF_CAL_BYTE_6_RFCAL_FREQ11              0
+#define TDA18272_WIDTH_RF_CAL_BYTE_6_RFCAL_FREQ11              2
+
+#define TDA18272_RF_FILTER_BYTE_1                              0x2c
+#define TDA18272_OFFST_RF_FILTER_BYTE_1_RF_FILTER_BYPASS       7
+#define TDA18272_WIDTH_RF_FILTER_BYTE_1_RF_FILTER_BYPASS       1
+#define TDA18272_OFFST_RF_FILTER_BYTE_1_UNUSED_I0_D0           6
+#define TDA18272_WIDTH_RF_FILTER_BYTE_1_UNUSED_I0_D0           1
+#define TDA18272_OFFST_RF_FILTER_BYTE_1_AGC2_LOOP_OFF          5
+#define TDA18272_WIDTH_RF_FILTER_BYTE_1_AGC2_LOOP_OFF          1
+#define TDA18272_OFFST_RF_FILTER_BYTE_1_FORCE_AGC2_GAIN                4
+#define TDA18272_WIDTH_RF_FILTER_BYTE_1_FORCE_AGC2_GAIN                1
+#define TDA18272_OFFST_RF_FILTER_BYTE_1_RF_FILTER_GV           2
+#define TDA18272_WIDTH_RF_FILTER_BYTE_1_RF_FILTER_GV           2
+#define TDA18272_OFFST_RF_FILTER_BYTE_1_RF_FILTER_BAND         0
+#define TDA18272_WIDTH_RF_FILTER_BYTE_1_RF_FILTER_BAND         2
+
+#define TDA18272_RF_FILTER_BYTE_2                              0x2d
+#define TDA18272_OFFST_RF_FILTER_BYTE_2_RF_FILTER_CAP          0
+#define TDA18272_WIDTH_RF_FILTER_BYTE_2_RF_FILTER_CAP          8
+
+#define TDA18272_RF_FILTER_BYTE_3                              0x2e
+#define TDA18272_OFFST_RF_FILTER_BYTE_3_AGC2_DO_STEP           6
+#define TDA18272_WIDTH_RF_FILTER_BYTE_3_AGC2_DO_STEP           2
+#define TDA18272_OFFST_RF_FILTER_BYTE_3_GAIN_TAPER             0
+#define TDA18272_WIDTH_RF_FILTER_BYTE_3_GAIN_TAPER             6
+
+#define TDA18272_RF_BANDPASS_FILTER                            0x2f
+#define TDA18272_OFFST_RF_BANDPASS_FILTER_RF_BPF_BYPASS                7
+#define TDA18272_WIDTH_RF_BANDPASS_FILTER_RF_BPF_BYPASS                1
+#define TDA18272_OFFST_RF_BANDPASS_FILTER_UNUSED_I0_D0         3
+#define TDA18272_WIDTH_RF_BANDPASS_FILTER_UNUSED_I0_D0         4
+#define TDA18272_OFFST_RF_BANDPASS_FILTER_RF_BPF               0
+#define TDA18272_WIDTH_RF_BANDPASS_FILTER_RF_BPF               3
+
+#define TDA18272_CP_CURRENT                                    0x30
+#define TDA18272_OFFST_CP_CURRENT_UNUSED_I0_D0                 7
+#define TDA18272_WIDTH_CP_CURRENT_UNUSED_I0_D0                 1
+#define TDA18272_OFFST_CP_CURRENT_N_CP_CURRENT                 0
+#define TDA18272_WIDTH_CP_CURRENT_N_CP_CURRENT                 7
+
+#define TDA18272_AGC_DET_OUT                                   0x31
+#define TDA18272_OFFST_AGC_DET_OUT_UP_AGC5                     7
+#define TDA18272_WIDTH_AGC_DET_OUT_UP_AGC5                     1
+#define TDA18272_OFFST_AGC_DET_OUT_DO_AGC5                     6
+#define TDA18272_WIDTH_AGC_DET_OUT_DO_AGC5                     1
+#define TDA18272_OFFST_AGC_DET_OUT_UP_AGC4                     5
+#define TDA18272_WIDTH_AGC_DET_OUT_UP_AGC4                     1
+#define TDA18272_OFFST_AGC_DET_OUT_DO_AGC4                     4
+#define TDA18272_WIDTH_AGC_DET_OUT_DO_AGC4                     1
+#define TDA18272_OFFST_AGC_DET_OUT_UP_AGC2                     3
+#define TDA18272_WIDTH_AGC_DET_OUT_UP_AGC2                     1
+#define TDA18272_OFFST_AGC_DET_OUT_DO_AGC2                     2
+#define TDA18272_WIDTH_AGC_DET_OUT_DO_AGC2                     1
+#define TDA18272_OFFST_AGC_DET_OUT_UP_AGC1                     1
+#define TDA18272_WIDTH_AGC_DET_OUT_UP_AGC1                     1
+#define TDA18272_OFFST_AGC_DET_OUT_DO_AGC1                     0
+#define TDA18272_WIDTH_AGC_DET_OUT_DO_AGC1                     1
+
+#define TDA18272_RF_AGC_GAIN_BYTE_1                            0x32
+#define TDA18272_OFFST_RF_AGC_GAIN_BYTE_1_RF_FILTER_GAIN       4
+#define TDA18272_WIDTH_RF_AGC_GAIN_BYTE_1_RF_FILTER_GAIN       2
+#define TDA18272_OFFST_RF_AGC_GAIN_BYTE_1_LNA_GAIN             0
+#define TDA18272_WIDTH_RF_AGC_GAIN_BYTE_1_LNA_GAIN             4
+
+#define TDA18272_RF_AGC_GAIN_BYTE_2                            0x33
+#define TDA18272_OFFST_RF_AGC_GAIN_BYTE_2_TOP_AGC3_READ                0
+#define TDA18272_WIDTH_RF_AGC_GAIN_BYTE_2_TOP_AGC3_READ                3
+
+#define TDA18272_IF_AGC_GAIN                                   0x34
+#define TDA18272_OFFST_IF_AGC_GAIN_LPF_GAIN                    3
+#define TDA18272_WIDTH_IF_AGC_GAIN_LPF_GAIN                    2
+#define TDA18272_OFFST_IF_AGC_GAIN_IR_MIXER                    0
+#define TDA18272_WIDTH_IF_AGC_GAIN_IR_MIXER                    3
+
+#define TDA18272_POWER_BYTE_1                                  0x35
+#define TDA18272_OFFST_POWER_BYTE_1_RSSI                       0
+#define TDA18272_WIDTH_POWER_BYTE_1_RSSI                       8
+
+#define TDA18272_POWER_BYTE_2                                  0x36
+#define TDA18272_OFFST_POWER_BYTE_2_UNUSED_I1_D0               6
+#define TDA18272_WIDTH_POWER_BYTE_2_UNUSED_I1_D0               2
+#define TDA18272_OFFST_POWER_BYTE_2_RSSI_AV                    5
+#define TDA18272_WIDTH_POWER_BYTE_2_RSSI_AV                    1
+#define TDA18272_OFFST_POWER_BYTE_2_UNUSED_I0_D0               4
+#define TDA18272_WIDTH_POWER_BYTE_2_UNUSED_I0_D0               1
+#define TDA18272_OFFST_POWER_BYTE_2_RSSI_CAP_RESET_EN          3
+#define TDA18272_WIDTH_POWER_BYTE_2_RSSI_CAP_RESET_EN          1
+#define TDA18272_OFFST_POWER_BYTE_2_RSSI_CAP_VAL               2
+#define TDA18272_WIDTH_POWER_BYTE_2_RSSI_CAP_VAL               1
+#define TDA18272_OFFST_POWER_BYTE_2_RSSI_CK_SPEED              1
+#define TDA18272_WIDTH_POWER_BYTE_2_RSSI_CK_SPEED              1
+#define TDA18272_OFFST_POWER_BYTE_2_RSSI_DICHO_NOT             0
+#define TDA18272_WIDTH_POWER_BYTE_2_RSSI_DICHO_NOT             1
+
+#define TDA18272_MISC_BYTE_1                                   0x37
+#define TDA18272_OFFST_MISC_BYTE_1_IRQ_POLARITY                        0
+#define TDA18272_WIDTH_MISC_BYTE_1_IRQ_POLARITY                        1
+
+#define TDA18272_RF_CAL_LOG_1                                  0x38
+#define TDA18272_OFFST_RF_CAL_LOG_1                            0
+#define TDA18272_WIDTH_RF_CAL_LOG_1                            8
+
+#define TDA18272_RF_CAL_LOG_2                                  0x39
+#define TDA18272_OFFST_RF_CAL_LOG_2                            0
+#define TDA18272_WIDTH_RF_CAL_LOG_2                            8
+
+#define TDA18272_RF_CAL_LOG_3                                  0x3a
+#define TDA18272_OFFST_RF_CAL_LOG_3                            0
+#define TDA18272_WIDTH_RF_CAL_LOG_3                            8
+
+#define TDA18272_RF_CAL_LOG_4                                  0x3b
+#define TDA18272_OFFST_RF_CAL_LOG_4                            0
+#define TDA18272_WIDTH_RF_CAL_LOG_4                            8
+
+#define TDA18272_RF_CAL_LOG_5                                  0x3c
+#define TDA18272_OFFST_RF_CAL_LOG_5                            0
+#define TDA18272_WIDTH_RF_CAL_LOG_5                            8
+
+#define TDA18272_RF_CAL_LOG_6                                  0x3d
+#define TDA18272_OFFST_RF_CAL_LOG_6                            0
+#define TDA18272_WIDTH_RF_CAL_LOG_6                            8
+
+#define TDA18272_RF_CAL_LOG_7                                  0x3e
+#define TDA18272_OFFST_RF_CAL_LOG_7                            0
+#define TDA18272_WIDTH_RF_CAL_LOG_7                            8
+
+#define TDA18272_RF_CAL_LOG_8                                  0x3f
+#define TDA18272_OFFST_RF_CAL_LOG_8                            0
+#define TDA18272_WIDTH_RF_CAL_LOG_8                            8
+
+#define TDA18272_RF_CAL_LOG_9                                  0x40
+#define TDA18272_OFFST_RF_CAL_LOG_9                            0
+#define TDA18272_WIDTH_RF_CAL_LOG_9                            8
+
+#define TDA18272_RF_CAL_LOG_10                                 0x41
+#define TDA18272_OFFST_RF_CAL_LOG_10                           0
+#define TDA18272_WIDTH_RF_CAL_LOG_10                           8
+
+#define TDA18272_RF_CAL_LOG_11                                 0x42
+#define TDA18272_OFFST_RF_CAL_LOG_11                           0
+#define TDA18272_WIDTH_RF_CAL_LOG_11                           8
+
+#define TDA18272_RF_CAL_LOG_12                                 0x43
+#define TDA18272_OFFST_RF_CAL_LOG_12                           0
+#define TDA18272_WIDTH_RF_CAL_LOG_12                           8
+
+#endif /* __TDA18272_REG_H */
index 32d0292..3d55bdf 100644 (file)
@@ -44,7 +44,9 @@ config VIDEO_CX231XX_DVB
        select VIDEOBUF_DVB
        select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT
        select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_TDA18272 if MEDIA_SUBDRV_AUTOSELECT
        select DVB_MB86A20S if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_LGDT3305 if MEDIA_SUBDRV_AUTOSELECT
        select DVB_LGDT3306A if MEDIA_SUBDRV_AUTOSELECT
        select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
 
index 235ba65..9034d24 100644 (file)
@@ -2264,6 +2264,8 @@ int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode)
        case POLARIS_AVMODE_ANALOGT_TV:
 
                tmp |= PWR_DEMOD_EN;
+               if (CX231XX_BOARD_AVERMEDIA_H837B == dev->model)
+                       tmp &= ~PWR_DEMOD_EN;
                tmp |= (I2C_DEMOD_EN);
                value[0] = (u8) tmp;
                value[1] = (u8) (tmp >> 8);
@@ -2371,8 +2373,19 @@ int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode)
                status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
                                                PWR_CTL_EN, value, 4);
                msleep(PWR_SLEEP_INTERVAL);
-
-               if (!(tmp & PWR_DEMOD_EN)) {
+               if (is_model_avermedia_h837_series(dev->model)) {
+                       if (CX231XX_BOARD_AVERMEDIA_H837B == dev->model)
+                               tmp |= PWR_DEMOD_EN;
+                       else
+                               tmp &= ~PWR_DEMOD_EN;
+                       value[0] = (u8) tmp;
+                       value[1] = (u8) (tmp >> 8);
+                       value[2] = (u8) (tmp >> 16);
+                       value[3] = (u8) (tmp >> 24);
+                       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                                                       PWR_CTL_EN, value, 4);
+                       msleep(5 * PWR_SLEEP_INTERVAL);
+               } else if (!(tmp & PWR_DEMOD_EN)) {
                        tmp |= PWR_DEMOD_EN;
                        value[0] = (u8) tmp;
                        value[1] = (u8) (tmp >> 8);
@@ -2402,6 +2415,21 @@ int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode)
                }
                break;
 
+       case POLARIS_AVMODE_DEFAULT:
+               if (is_model_avermedia_h837_series(dev->model)) {
+                       tmp &= ~PWR_MODE_MASK;
+                       if( CX231XX_BOARD_AVERMEDIA_H837A==dev->model ||
+                           CX231XX_BOARD_AVERMEDIA_H837M==dev->model )
+                               tmp |= PWR_DEMOD_EN;
+                       value[0] = (u8) tmp;
+                       value[1] = (u8) (tmp >> 8);
+                       value[2] = (u8) (tmp >> 16);
+                       value[3] = (u8) (tmp >> 24);
+                       cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN, value, 4);
+                       msleep(PWR_SLEEP_INTERVAL);
+                       return 0;
+               }
+
        default:
                break;
        }
@@ -2567,7 +2595,11 @@ int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type)
                } else {
                        cx231xx_info(" BDA\n");
                        status = cx231xx_mode_register(dev, TS_MODE_REG, 0x101);
-                       status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x010);
+                       if (is_model_avermedia_h837_series(dev->model)) {
+                               status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x408);
+                       } else {
+                               status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x010);
+                       }
                }
                        break;
 
index 6e4af9a..e416e94 100644 (file)
@@ -706,6 +706,108 @@ struct cx231xx_board cx231xx_boards[] = {
                        .gpio = NULL,
                } },
        },
+       [CX231XX_BOARD_AVERMEDIA_H837A] = {
+               .name = "AVerMedia H837-A USB Hybrid ATSC/QAM",
+               .tuner_type = TUNER_ABSENT,
+               .tuner_addr = 0x60,
+               .tuner_sif_gpio = 0x05,
+               .demod_xfer_mode = 0,
+               .ctl_pin_status_mask = 0xFFFFFFC4,
+               .agc_analog_digital_select_gpio = 0x1c,
+               .gpio_pin_status_mask = 0x4001000,
+               .tuner_i2c_master = 2,
+               .demod_i2c_master = 1,
+               .has_dvb = 1,
+               .norm = V4L2_STD_NTSC,
+
+               .input = {{
+                       .type = CX231XX_VMUX_TELEVISION,
+                       .vmux = CX231XX_VIN_3_1,
+                       .amux = CX231XX_AMUX_VIDEO,
+                       .gpio = 0,
+               }, {
+                       .type = CX231XX_VMUX_COMPOSITE1,
+                       .vmux = CX231XX_VIN_2_1,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = 0,
+               }, {
+                       .type = CX231XX_VMUX_SVIDEO,
+                       .vmux = CX231XX_VIN_1_1 |
+                               (CX231XX_VIN_1_2 << 8) |
+                               CX25840_SVIDEO_ON,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = 0,
+               }
+               },
+       },
+       [CX231XX_BOARD_AVERMEDIA_H837B] = {
+               .name = "AVerMedia H837-B USB Hybrid ATSC/QAM",
+               .tuner_type = TUNER_ABSENT,
+               .tuner_addr = 0x60,
+               .tuner_sif_gpio = 0x05,
+               .demod_xfer_mode = 0,
+               .ctl_pin_status_mask = 0xFFFFFFC4,
+               .agc_analog_digital_select_gpio = 0x1c,
+               .gpio_pin_status_mask = 0x4001000,
+               .tuner_i2c_master = 2,
+               .demod_i2c_master = 1,
+               .has_dvb = 1,
+               .norm = V4L2_STD_NTSC,
+
+               .input = {{
+                       .type = CX231XX_VMUX_TELEVISION,
+                       .vmux = CX231XX_VIN_3_1,
+                       .amux = CX231XX_AMUX_VIDEO,
+                       .gpio = 0,
+               }, {
+                       .type = CX231XX_VMUX_COMPOSITE1,
+                       .vmux = CX231XX_VIN_2_1,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = 0,
+               }, {
+                       .type = CX231XX_VMUX_SVIDEO,
+                       .vmux = CX231XX_VIN_1_1 |
+                               (CX231XX_VIN_1_2 << 8) |
+                               CX25840_SVIDEO_ON,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = 0,
+               }
+               },
+       },
+       [CX231XX_BOARD_AVERMEDIA_H837M] = {
+               .name = "AVerMedia H837-M USB Hybrid ATSC/QAM",
+               .tuner_type = TUNER_ABSENT,
+               .tuner_addr = 0x60,
+               .tuner_sif_gpio = 0x05,
+               .demod_xfer_mode = 0,
+               .ctl_pin_status_mask = 0xFFFFFFC4,
+               .agc_analog_digital_select_gpio = 0x1c,
+               .gpio_pin_status_mask = 0x4001000,
+               .tuner_i2c_master = 2,
+               .demod_i2c_master = 1,
+               .has_dvb = 1,
+               .norm = V4L2_STD_NTSC,
+
+               .input = {{
+                       .type = CX231XX_VMUX_TELEVISION,
+                       .vmux = CX231XX_VIN_3_1,
+                       .amux = CX231XX_AMUX_VIDEO,
+                       .gpio = 0,
+               }, {
+                       .type = CX231XX_VMUX_COMPOSITE1,
+                       .vmux = CX231XX_VIN_2_1,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = 0,
+               }, {
+                       .type = CX231XX_VMUX_SVIDEO,
+                       .vmux = CX231XX_VIN_1_1 |
+                               (CX231XX_VIN_1_2 << 8) |
+                               CX25840_SVIDEO_ON,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = 0,
+               }
+               },
+       },
 };
 const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards);
 
@@ -751,6 +853,12 @@ struct usb_device_id cx231xx_id_table[] = {
         .driver_info = CX231XX_BOARD_ELGATO_VIDEO_CAPTURE_V2},
        {USB_DEVICE(0x1f4d, 0x0102),
         .driver_info = CX231XX_BOARD_OTG102},
+       {USB_DEVICE(0x07ca, 0x0837),
+        .driver_info = CX231XX_BOARD_AVERMEDIA_H837A},
+       {USB_DEVICE(0x07ca, 0x0837),
+        .driver_info = CX231XX_BOARD_AVERMEDIA_H837B},
+       {USB_DEVICE(0x07ca, 0x1837),
+        .driver_info = CX231XX_BOARD_AVERMEDIA_H837M},
        {},
 };
 
@@ -1173,7 +1281,9 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
        dev->gpio_dir = 0;
        dev->gpio_val = 0;
        dev->xc_fw_load_done = 0;
-       dev->has_alsa_audio = 1;
+       if (!is_model_avermedia_h837_series(dev->model)) {
+               dev->has_alsa_audio = 1;
+       }
        dev->power_mode = -1;
        atomic_set(&dev->devlist_count, 0);
 
index 70f317e..3264f49 100644 (file)
@@ -340,6 +340,76 @@ int cx231xx_read_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg,
        return ret;
 }
 
+int cx231xx_send_h837_vendor_cmd(struct cx231xx *dev,
+                               struct VENDOR_REQUEST_IN *ven_req)
+{
+       int ret;
+       int pipe = 0;
+       int unsend_size = 0;
+       u8 *pdata;
+
+       if (dev->state & DEV_DISCONNECTED)
+               return -ENODEV;
+
+       if ((ven_req->wLength > URB_MAX_CTRL_SIZE))
+               return -EINVAL;
+
+       if (ven_req->direction)
+               pipe = usb_rcvctrlpipe(dev->udev, 0);
+       else
+               pipe = usb_sndctrlpipe(dev->udev, 0);
+
+       /*
+        * If the cx23102 read more than 4 bytes with i2c bus,
+        * need chop to 4 byte per request
+        */
+       if ((ven_req->wLength > 4) && (ven_req->bRequest <= VRT_GET_I2C2)) {
+               unsend_size = 0;
+               pdata = ven_req->pBuff;
+
+
+               unsend_size = ven_req->wLength;
+
+               /* the first package */
+               ven_req->wValue = ven_req->wValue & 0xFFFB;
+               ven_req->wValue = (ven_req->wValue & 0xFFBD) | 0x2;
+               ret = __usb_control_msg(dev, pipe, ven_req->bRequest,
+                       ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       ven_req->wValue, ven_req->wIndex, pdata,
+                       0x0004, HZ);
+               unsend_size = unsend_size - 4;
+
+               /* the middle package */
+               ven_req->wValue = (ven_req->wValue & 0xFFBD) | 0x42;
+               while (unsend_size - 4 > 0) {
+                       pdata = pdata + 4;
+                       ret = __usb_control_msg(dev, pipe,
+                               ven_req->bRequest,
+                               ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               ven_req->wValue, ven_req->wIndex, pdata,
+                               0x0004, HZ);
+                       unsend_size = unsend_size - 4;
+               }
+
+               /* the last package */
+               ven_req->wValue = (ven_req->wValue & 0xFFBD) | 0x40;
+               pdata = pdata + 4;
+               ret = __usb_control_msg(dev, pipe, ven_req->bRequest,
+                       ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       ven_req->wValue, ven_req->wIndex, pdata,
+                       unsend_size, HZ);
+       } else {
+               if (ven_req->bRequest <= VRT_GET_I2C2)
+                       ven_req->wValue &= ~0x42;
+               ret = __usb_control_msg(dev, pipe, ven_req->bRequest,
+                               ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               ven_req->wValue, ven_req->wIndex,
+                               ven_req->pBuff, ven_req->wLength, HZ);
+       }
+
+       return ret;
+}
+
 int cx231xx_send_vendor_cmd(struct cx231xx *dev,
                                struct VENDOR_REQUEST_IN *ven_req)
 {
@@ -348,6 +418,9 @@ int cx231xx_send_vendor_cmd(struct cx231xx *dev,
        int unsend_size = 0;
        u8 *pdata;
 
+       if (is_model_avermedia_h837_series(dev->model))
+               return cx231xx_send_h837_vendor_cmd(dev, ven_req);
+
        if (dev->state & DEV_DISCONNECTED)
                return -ENODEV;
 
@@ -719,7 +792,18 @@ int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode)
                case CX231XX_BOARD_CNXT_RDE_250:
                case CX231XX_BOARD_CNXT_SHELBY:
                case CX231XX_BOARD_CNXT_RDU_250:
-               errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0);
+                       errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0);
+                       break;
+               case CX231XX_BOARD_AVERMEDIA_H837M:
+               case CX231XX_BOARD_AVERMEDIA_H837B:
+               case CX231XX_BOARD_AVERMEDIA_H837A: {
+                       cx231xx_set_power_mode(dev, POLARIS_AVMODE_DEFAULT);
+                       msleep(20);
+                       cx231xx_set_agc_analog_digital_mux_select(dev, 0);
+                       cx231xx_set_power_mode(dev, POLARIS_AVMODE_DIGITAL);
+                       msleep(50);
+                       return 0;
+                       }
                        break;
                case CX231XX_BOARD_CNXT_RDE_253S:
                case CX231XX_BOARD_CNXT_RDU_253S:
@@ -735,6 +819,12 @@ int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode)
        } else/* Set Analog Power mode */ {
        /* set AGC mode to Analog */
                switch (dev->model) {
+               case CX231XX_BOARD_AVERMEDIA_H837A:
+               case CX231XX_BOARD_AVERMEDIA_H837B:
+               case CX231XX_BOARD_AVERMEDIA_H837M:
+                       cx231xx_set_agc_analog_digital_mux_select(dev, 1);
+                       cx231xx_set_power_mode(dev, POLARIS_AVMODE_DEFAULT);
+                       return 0;
                case CX231XX_BOARD_CNXT_CARRAERA:
                case CX231XX_BOARD_CNXT_RDE_250:
                case CX231XX_BOARD_CNXT_SHELBY:
@@ -1278,6 +1368,47 @@ void cx231xx_start_TS1(struct cx231xx *dev)
 /*****************************************************************
 *             Device Init/UnInit functions                       *
 ******************************************************************/
+static void cx231xx_check_model(struct cx231xx *dev)
+{
+       if (is_model_avermedia_h837_series(dev->model)) {
+               struct i2c_msg msg[2];
+               unsigned char offset = 255, value = 0;
+
+               dev->i2c_bus[0].i2c_period =
+               dev->i2c_bus[1].i2c_period =
+               dev->i2c_bus[2].i2c_period = I2C_SPEED_400K;
+               // first a write message to write EE offset
+               msg[0].addr = 0x50;
+               msg[0].flags = 0;
+               msg[0].len = 1;
+               msg[0].buf = &offset;
+
+               // then a read message to read EE content, maximum read length is 4 bytes
+               msg[1].addr = 0x50;
+               msg[1].flags = I2C_M_RD;
+               msg[1].len = 1;
+               msg[1].buf = &value;
+
+               if (i2c_transfer(&dev->i2c_bus[1].i2c_adap, msg, 2) < 0) {
+                       cx231xx_warn("Failed to check EEPROM");
+                       return;
+               }
+
+               if( 0x01 == value) {
+                       if (CX231XX_BOARD_AVERMEDIA_H837B==dev->model)
+                               return;
+                       dev->model = CX231XX_BOARD_AVERMEDIA_H837B;
+               } else {
+                       if (CX231XX_BOARD_AVERMEDIA_H837A==dev->model ||
+                               CX231XX_BOARD_AVERMEDIA_H837M==dev->model)
+                               return;
+                       dev->model = CX231XX_BOARD_AVERMEDIA_H837A;
+               }
+               dev->board = cx231xx_boards[dev->model];
+               cx231xx_info("Correct device model as %s\n", dev->board.name);
+       }
+}
+
 int cx231xx_dev_init(struct cx231xx *dev)
 {
        int errCode = 0;
@@ -1310,6 +1441,9 @@ int cx231xx_dev_init(struct cx231xx *dev)
        cx231xx_i2c_register(&dev->i2c_bus[1]);
        cx231xx_i2c_register(&dev->i2c_bus[2]);
 
+       /* model check */
+       cx231xx_check_model(dev);
+
        /* init hardware */
        /* Note : with out calling set power mode function,
        afe can not be set up correctly */
index e6643e3..a37080d 100644 (file)
@@ -69,6 +69,13 @@ struct cx231xx_dvb {
        struct dmx_frontend fe_hw;
        struct dmx_frontend fe_mem;
        struct dvb_net net;
+       int    power_on;
+};
+
+#include "tda18272.h"
+static struct tda18272_config h837_tda18272_config = {
+         0x60                  //  dev->board.tuner_addr
+       , TDA18272_SINGLE
 };
 
 static struct s5h1432_config dvico_s5h1432_config = {
@@ -130,6 +137,17 @@ static struct lgdt3305_config hcw_lgdt3305_config = {
        .vsb_if_khz         = 3250,
 };
 
+static struct lgdt3305_config h837_lgdt3305_config = {
+       .i2c_addr           = 0xB2 >> 1,
+       .mpeg_mode          = LGDT3305_MPEG_SERIAL,
+       .tpclk_edge         = LGDT3305_TPCLK_FALLING_EDGE,
+       .tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,
+       .deny_i2c_rptr      = 1,
+       .spectral_inversion = 1,
+       .qam_if_khz         = 3600,
+       .vsb_if_khz         = 3250,
+};
+
 static struct tda18271_std_map hauppauge_tda18271_std_map = {
        .atsc_6   = { .if_freq = 3250, .agc_mode = 3, .std = 4,
                      .if_lvl = 1, .rfagc_top = 0x58, },
@@ -271,9 +289,14 @@ static int start_streaming(struct cx231xx_dvb *dvb)
        if (dev->USE_ISO) {
                cx231xx_info("DVB transfer mode is ISO.\n");
                mutex_lock(&dev->i2c_lock);
-               cx231xx_enable_i2c_port_3(dev, false);
-               cx231xx_set_alt_setting(dev, INDEX_TS1, 4);
-               cx231xx_enable_i2c_port_3(dev, true);
+               if (is_model_avermedia_h837_series(dev->model)) {
+                       cx231xx_set_alt_setting(dev, INDEX_TS1, 4);
+                       ++dvb->power_on;
+               } else {
+                       cx231xx_enable_i2c_port_3(dev, false);
+                       cx231xx_set_alt_setting(dev, INDEX_TS1, 4);
+                       cx231xx_enable_i2c_port_3(dev, true);
+               }
                mutex_unlock(&dev->i2c_lock);
                rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
                if (rc < 0)
@@ -289,6 +312,9 @@ static int start_streaming(struct cx231xx_dvb *dvb)
                rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
                if (rc < 0)
                        return rc;
+               if (is_model_avermedia_h837_series(dev->model)) {
+                       ++dvb->power_on;
+               }
                dev->mode_tv = 1;
                return cx231xx_init_bulk(dev, CX231XX_DVB_MAX_PACKETS,
                                        CX231XX_DVB_NUM_BUFS,
@@ -307,6 +333,11 @@ static int stop_streaming(struct cx231xx_dvb *dvb)
        else
                cx231xx_uninit_bulk(dev);
 
+       if (-1 != dvb->power_on) {
+               --dvb->power_on;
+               if (dvb->power_on)
+                       return 0;
+       }
        cx231xx_set_mode(dev, CX231XX_SUSPEND);
 
        return 0;
@@ -355,11 +386,20 @@ static int stop_feed(struct dvb_demux_feed *feed)
 static int cx231xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
 {
        struct cx231xx *dev = fe->dvb->priv;
+       struct cx231xx_dvb *dvb = dev->dvb;
 
-       if (acquire)
+       if (acquire) {
+               if (-1 != dvb->power_on)
+                       ++dvb->power_on;
                return cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
-       else
+       } else {
+               if (-1 != dvb->power_on) {
+                       --dvb->power_on;
+                       if (dvb->power_on)
+                               return 0;
+               }
                return cx231xx_set_mode(dev, CX231XX_SUSPEND);
+       }
 }
 
 /* ------------------------------------------------------------------ */
@@ -595,12 +635,19 @@ static int dvb_init(struct cx231xx *dev)
                return -ENOMEM;
        }
        dev->dvb = dvb;
+       dvb->power_on = -1;
        dev->cx231xx_set_analog_freq = cx231xx_set_analog_freq;
        dev->cx231xx_reset_analog_tuner = cx231xx_reset_analog_tuner;
 
        mutex_lock(&dev->lock);
-       cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
-       cx231xx_demod_reset(dev);
+       if (is_model_avermedia_h837_series(dev->model)) {
+               cx231xx_set_mode(dev, CX231XX_SUSPEND);
+               cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
+               dvb->power_on = 0;
+       } else {
+               cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
+               cx231xx_demod_reset(dev);
+       }
        /* init frontend */
        switch (dev->model) {
        case CX231XX_BOARD_CNXT_CARRAERA:
@@ -771,6 +818,29 @@ static int dvb_init(struct cx231xx *dev)
                           &pv_tda18271_config);
                break;
 
+       case CX231XX_BOARD_AVERMEDIA_H837A:
+       case CX231XX_BOARD_AVERMEDIA_H837B:
+       case CX231XX_BOARD_AVERMEDIA_H837M:
+               dev->dvb->frontend = dvb_attach(lgdt3305_attach,
+                                               &h837_lgdt3305_config,
+                                               &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
+
+               if (dev->dvb->frontend == NULL) {
+                       printk(DRIVER_NAME
+                              ": Failed to attach LG3305 front end\n");
+                       result = -EINVAL;
+                       goto out_free;
+               }
+
+               /* define general-purpose callback pointer */
+               dvb->frontend->callback = cx231xx_tuner_callback;
+               {
+                       dvb_attach(tda18272_attach, dev->dvb->frontend,
+                               &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
+                               &h837_tda18272_config);
+               }
+               break;
+
        default:
                printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"
                       " isn't supported yet\n", dev->name);
index 007567f..eee7e3f 100644 (file)
@@ -802,6 +802,8 @@ static struct videobuf_queue_ops cx231xx_video_qops = {
 
 void video_mux(struct cx231xx *dev, int index)
 {
+       if (is_model_avermedia_h837_series(dev->model))
+               return;
        dev->video_input = index;
        dev->ctl_ainput = INPUT(index)->amux;
 
index 5a7f4fe..b36b5c1 100644 (file)
@@ -73,6 +73,9 @@
 #define CX231XX_BOARD_ELGATO_VIDEO_CAPTURE_V2 16
 #define CX231XX_BOARD_OTG102 17
 #define CX231XX_BOARD_HAUPPAUGE_955Q 18
+#define CX231XX_BOARD_AVERMEDIA_H837A 19
+#define CX231XX_BOARD_AVERMEDIA_H837B 20
+#define CX231XX_BOARD_AVERMEDIA_H837M 21
 
 /* Limits minimum and default number of buffers */
 #define CX231XX_MIN_BUF                 4
@@ -1006,4 +1009,16 @@ static inline unsigned int norm_maxh(struct cx231xx *dev)
        else
                return (dev->norm & V4L2_STD_625_50) ? 576 : 480;
 }
+
+static inline bool is_model_avermedia_h837_series(int model)
+{
+       switch (model) {
+               case CX231XX_BOARD_AVERMEDIA_H837A:
+               case CX231XX_BOARD_AVERMEDIA_H837B:
+               case CX231XX_BOARD_AVERMEDIA_H837M:
+                       return true;
+       }
+       return false;
+}
+
 #endif