From 4e0c00940bcd81d5198b1532ec0d0463327e8e32 Mon Sep 17 00:00:00 2001 From: qi duan Date: Tue, 20 Nov 2018 16:23:04 +0800 Subject: [PATCH] dvb: tuner: USB DVB tuner support from Google PD#SWPL-932 Problem: USB DVB Dongle search program Function is not implemented Solution: merge usb dvb tuner from kernel3.14 http://10.8.9.5/kernel/common/commit/?h=amlogic-3.14-dev&id=7af9c5c38efdc96f5d3235f17788232a630b3d32 fixed frontend.h structures Verify: Ampere P Change-Id: I16d68c2507711eda43313619d210d05699abcc25 Signed-off-by: qi duan --- arch/arm/configs/meson64_a32_defconfig | 4 + arch/arm64/configs/meson64_defconfig | 4 + drivers/media/tuners/Kconfig | 7 + drivers/media/tuners/Makefile | 1 + drivers/media/tuners/tda18272.c | 1598 ++++++++++++++++++++++++++++ drivers/media/tuners/tda18272.h | 47 + drivers/media/tuners/tda18272_reg.h | 528 +++++++++ drivers/media/usb/cx231xx/Kconfig | 1 + drivers/media/usb/cx231xx/cx231xx-avcore.c | 39 +- drivers/media/usb/cx231xx/cx231xx-cards.c | 111 ++ drivers/media/usb/cx231xx/cx231xx-core.c | 136 +++ drivers/media/usb/cx231xx/cx231xx-dvb.c | 78 +- drivers/media/usb/cx231xx/cx231xx-video.c | 2 + drivers/media/usb/cx231xx/cx231xx.h | 16 + include/uapi/linux/dvb/frontend.h | 8 +- 15 files changed, 2571 insertions(+), 9 deletions(-) create mode 100644 drivers/media/tuners/tda18272.c create mode 100644 drivers/media/tuners/tda18272.h create mode 100644 drivers/media/tuners/tda18272_reg.h diff --git a/arch/arm/configs/meson64_a32_defconfig b/arch/arm/configs/meson64_a32_defconfig index 5e74d95..db75074 100644 --- a/arch/arm/configs/meson64_a32_defconfig +++ b/arch/arm/configs/meson64_a32_defconfig @@ -460,8 +460,12 @@ CONFIG_REGULATOR_PWM=y CONFIG_MEDIA_SUPPORT=y CONFIG_MEDIA_CAMERA_SUPPORT=y CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y +CONFIG_MEDIA_RC_SUPPORT=y CONFIG_MEDIA_USB_SUPPORT=y CONFIG_USB_VIDEO_CLASS=y +CONFIG_VIDEO_CX231XX=y +# CONFIG_VIDEO_CX231XX_RC is not set +CONFIG_VIDEO_CX231XX_DVB=y CONFIG_FB=y CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_BACKLIGHT_CLASS_DEVICE=y diff --git a/arch/arm64/configs/meson64_defconfig b/arch/arm64/configs/meson64_defconfig index 6ae6c537..8858f73 100644 --- a/arch/arm64/configs/meson64_defconfig +++ b/arch/arm64/configs/meson64_defconfig @@ -455,8 +455,12 @@ CONFIG_REGULATOR_PWM=y CONFIG_MEDIA_SUPPORT=y CONFIG_MEDIA_CAMERA_SUPPORT=y CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y +CONFIG_MEDIA_RC_SUPPORT=y CONFIG_MEDIA_USB_SUPPORT=y CONFIG_USB_VIDEO_CLASS=y +CONFIG_VIDEO_CX231XX=y +# CONFIG_VIDEO_CX231XX_RC is not set +CONFIG_VIDEO_CX231XX_DVB=y CONFIG_FB=y CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_BACKLIGHT_CLASS_DEVICE=y diff --git a/drivers/media/tuners/Kconfig b/drivers/media/tuners/Kconfig index 05998f0..c105392 100644 --- a/drivers/media/tuners/Kconfig +++ b/drivers/media/tuners/Kconfig @@ -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 diff --git a/drivers/media/tuners/Makefile b/drivers/media/tuners/Makefile index 06a9ab6..3dd7a04 100644 --- a/drivers/media/tuners/Makefile +++ b/drivers/media/tuners/Makefile @@ -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_MSI001) += msi001.o diff --git a/drivers/media/tuners/tda18272.c b/drivers/media/tuners/tda18272.c new file mode 100644 index 0000000..0db0021 --- /dev/null +++ b/drivers/media/tuners/tda18272.c @@ -0,0 +1,1598 @@ +/* + TDA18272 Silicon tuner driver + Copyright (C) Manu Abraham + + 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. + */ + +#include +#include +#include +#include +#include + +#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 = ®, .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; +} +#if 0 +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; +} +#endif +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, + .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 index 0000000..48acfe6 --- /dev/null +++ b/drivers/media/tuners/tda18272.h @@ -0,0 +1,47 @@ +/* + TDA18272 Silicon tuner driver + Copyright (C) Manu Abraham + + 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. + */ + +#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 index 0000000..610435a --- /dev/null +++ b/drivers/media/tuners/tda18272_reg.h @@ -0,0 +1,528 @@ +/* + TDA18272 Silicon tuner driver + Copyright (C) Manu Abraham + + 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. + */ + +#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 */ diff --git a/drivers/media/usb/cx231xx/Kconfig b/drivers/media/usb/cx231xx/Kconfig index 0cced3e..f08f85a 100644 --- a/drivers/media/usb/cx231xx/Kconfig +++ b/drivers/media/usb/cx231xx/Kconfig @@ -45,6 +45,7 @@ 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 diff --git a/drivers/media/usb/cx231xx/cx231xx-avcore.c b/drivers/media/usb/cx231xx/cx231xx-avcore.c index 2f52d66..4914521 100644 --- a/drivers/media/usb/cx231xx/cx231xx-avcore.c +++ b/drivers/media/usb/cx231xx/cx231xx-avcore.c @@ -2293,6 +2293,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; value[0] = (u8) tmp; value[1] = (u8) (tmp >> 8); value[2] = (u8) (tmp >> 16); @@ -2396,8 +2398,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); @@ -2418,6 +2431,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; } @@ -2592,8 +2620,11 @@ int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type) dev_dbg(dev->dev, "%s: BDA\n", __func__); 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; diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index 69156aff..73d9689 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -841,6 +841,109 @@ 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); @@ -911,6 +1014,12 @@ struct usb_device_id cx231xx_id_table[] = { .driver_info = CX231XX_BOARD_OTG102}, {USB_DEVICE(USB_VID_TERRATEC, 0x00a6), .driver_info = CX231XX_BOARD_TERRATEC_GRABBY}, + {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}, {}, }; @@ -1577,7 +1686,9 @@ static int cx231xx_usb_probe(struct usb_interface *interface, dev->gpio_dir = 0; dev->gpio_val = 0; dev->xc_fw_load_done = 0; + if (!is_model_avermedia_h837_series(dev->model)) { dev->has_alsa_audio = 1; + } dev->power_mode = -1; atomic_set(&dev->devlist_count, 0); diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c b/drivers/media/usb/cx231xx/cx231xx-core.c index 71b65ab..df3351e 100644 --- a/drivers/media/usb/cx231xx/cx231xx-core.c +++ b/drivers/media/usb/cx231xx/cx231xx-core.c @@ -331,6 +331,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) { @@ -339,6 +409,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; @@ -715,6 +788,18 @@ int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode) case CX231XX_BOARD_CNXT_RDU_250: 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); + cx231xx_set_gpio_value(dev, AVERMEDIA_H837_LED_PIN, 0); + return 0; + } + break; case CX231XX_BOARD_CNXT_RDE_253S: case CX231XX_BOARD_CNXT_RDU_253S: case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: @@ -731,6 +816,13 @@ 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); + cx231xx_set_gpio_value(dev, AVERMEDIA_H837_LED_PIN, 1); + return 0; case CX231XX_BOARD_CNXT_CARRAERA: case CX231XX_BOARD_CNXT_RDE_250: case CX231XX_BOARD_CNXT_SHELBY: @@ -1301,6 +1393,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) { + dev_err(dev->dev, "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]; + dev_info(dev->dev, "Correct device model as %s\n", dev->board.name); + } +} + int cx231xx_dev_init(struct cx231xx *dev) { int errCode = 0; @@ -1359,6 +1492,9 @@ int cx231xx_dev_init(struct cx231xx *dev) cx231xx_do_i2c_scan(dev, I2C_2); cx231xx_do_i2c_scan(dev, I2C_1_MUX_3); + /* model check */ + cx231xx_check_model(dev); + /* init hardware */ /* Note : with out calling set power mode function, afe can not be set up correctly */ diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c index 1417515..d2fca65 100644 --- a/drivers/media/usb/cx231xx/cx231xx-dvb.c +++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c @@ -67,6 +67,13 @@ struct cx231xx_dvb { struct dvb_net net; struct i2c_client *i2c_client_demod; struct i2c_client *i2c_client_tuner; + 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 = { @@ -128,6 +135,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, }, @@ -265,7 +283,14 @@ static int start_streaming(struct cx231xx_dvb *dvb) if (dev->USE_ISO) { dev_dbg(dev->dev, "DVB transfer mode is ISO.\n"); - cx231xx_set_alt_setting(dev, INDEX_TS1, 4); + mutex_lock(&dev->i2c_lock); + if (is_model_avermedia_h837_series(dev->model)) { + cx231xx_set_alt_setting(dev, INDEX_TS1, 4); + ++dvb->power_on; + } else { + cx231xx_set_alt_setting(dev, INDEX_TS1, 4); + } + mutex_unlock(&dev->i2c_lock); rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); if (rc < 0) return rc; @@ -280,6 +305,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, @@ -298,6 +326,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; @@ -346,12 +379,21 @@ 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 (dvb != NULL && -1 != dvb->power_on) + ++dvb->power_on; return cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); - else + } else { + if (dvb != NULL && -1 != dvb->power_on) { + --dvb->power_on; + if (dvb->power_on) + return 0; + } return cx231xx_set_mode(dev, CX231XX_SUSPEND); } +} /* ------------------------------------------------------------------ */ @@ -612,14 +654,21 @@ 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; tuner_i2c = cx231xx_get_i2c_adap(dev, dev->board.tuner_i2c_master); demod_i2c = cx231xx_get_i2c_adap(dev, dev->board.demod_i2c_master); mutex_lock(&dev->lock); + 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: @@ -864,6 +913,7 @@ static int dvb_init(struct cx231xx *dev) dev->dvb->i2c_client_tuner = client; break; } + case CX231XX_BOARD_HAUPPAUGE_955Q: { struct i2c_client *client; @@ -948,6 +998,28 @@ static int dvb_init(struct cx231xx *dev) 0x60, tuner_i2c, &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: dev_err(dev->dev, diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index 6414188..a763d5e 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -870,6 +870,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; diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h index 90c8676..c027cef 100644 --- a/drivers/media/usb/cx231xx/cx231xx.h +++ b/drivers/media/usb/cx231xx/cx231xx.h @@ -78,6 +78,9 @@ #define CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx 20 #define CX231XX_BOARD_HAUPPAUGE_955Q 21 #define CX231XX_BOARD_TERRATEC_GRABBY 22 +#define CX231XX_BOARD_AVERMEDIA_H837A 23 +#define CX231XX_BOARD_AVERMEDIA_H837B 24 +#define CX231XX_BOARD_AVERMEDIA_H837M 25 /* Limits minimum and default number of buffers */ #define CX231XX_MIN_BUF 4 @@ -127,6 +130,7 @@ #define SLEEP_S5H1432 30 #define CX23417_OSC_EN 8 #define CX23417_RESET 9 +#define AVERMEDIA_H837_LED_PIN 27 struct cx23417_fmt { char *name; @@ -1005,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 diff --git a/include/uapi/linux/dvb/frontend.h b/include/uapi/linux/dvb/frontend.h index cf8df3d..e851a30 100644 --- a/include/uapi/linux/dvb/frontend.h +++ b/include/uapi/linux/dvb/frontend.h @@ -541,6 +541,7 @@ struct dtv_property { __u32 reserved1[3]; void *reserved2; } buffer; +#if 0 #ifdef CONFIG_AMLOGIC_DVB_COMPAT struct { __u8 data[32]; @@ -549,6 +550,7 @@ struct dtv_property { __u64 reserved; } reserved; #endif +#endif } u; int result; } __attribute__ ((packed)); @@ -558,7 +560,7 @@ struct dtv_property { struct dtv_properties { __u32 num; -#ifdef CONFIG_AMLOGIC_DVB_COMPAT +#if 0 && defined(CONFIG_AMLOGIC_DVB_COMPAT) union { struct dtv_property *props; __u64 reserved; @@ -661,7 +663,7 @@ struct dvb_frontend_parameters { struct dvb_qam_parameters qam; /* DVB-C */ struct dvb_ofdm_parameters ofdm; /* DVB-T */ struct dvb_vsb_parameters vsb; /* ATSC */ -#ifdef CONFIG_AMLOGIC_DVB_COMPAT +#if 0 && defined(CONFIG_AMLOGIC_DVB_COMPAT) struct dvb_analog_parameters analog; #endif } u; @@ -683,10 +685,12 @@ struct dvb_frontend_parameters_ex { } u; }; +/* static char dvb_check_frontend_parameters_size[ (sizeof(struct dvb_frontend_parameters_ex) == sizeof(struct dvb_frontend_parameters)) ? 1 : -1] __attribute__((__unused__)); +*/ #endif /*CONFIG_AMLOGIC_DVB_COMPAT*/ -- 2.7.4