* [PATCH 0/5] support rtl2832 demodulator
@ 2012-05-12 18:08 Thomas Mair
2012-05-12 18:08 ` [PATCH 1/5] rtl2832 ver 0.3: suport for RTL2832 demodulator revised version Thomas Mair
` (5 more replies)
0 siblings, 6 replies; 16+ messages in thread
From: Thomas Mair @ 2012-05-12 18:08 UTC (permalink / raw)
To: linux-media; +Cc: Thomas Mair
This series of patches contains the rtl2832 demodulator driver.
In order to work the fc0012 and fc0013 driver from Hans-Frieder Vogt
have to be applied first.
The current version includes all the comments on the previous patches.
I currently only own a Cinergy Terratec T Stick Black (rev 1) device,
that is why i could only test it with that device. Feel free to
comment on the patch and report issues you are having with it.
Thanks again for all the comments, especially to Antti.
Regards
Thomas
Thomas Mair (5):
rtl2832 ver 0.3: suport for RTL2832 demodulator revised version
rtl28xxu: support for the rtl2832 demod driver
rtl28xxu: renamed rtl2831_rd/rtl2831_wr to rtl28xx_rd/rtl28xx_wr
rtl28xxu: support G-Tek Electronics Group Lifeview LV5TDLX DVB-T
rtl28xxu: support Terratec Noxon DAB/DAB+ stick
drivers/media/dvb/dvb-usb/Kconfig | 3 +
drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 3 +
drivers/media/dvb/dvb-usb/rtl28xxu.c | 513 +++++++++++++--
drivers/media/dvb/frontends/Kconfig | 7 +
drivers/media/dvb/frontends/Makefile | 1 +
drivers/media/dvb/frontends/rtl2832.c | 1009 ++++++++++++++++++++++++++++
drivers/media/dvb/frontends/rtl2832.h | 81 +++
drivers/media/dvb/frontends/rtl2832_priv.h | 260 +++++++
8 files changed, 1829 insertions(+), 48 deletions(-)
create mode 100644 drivers/media/dvb/frontends/rtl2832.c
create mode 100644 drivers/media/dvb/frontends/rtl2832.h
create mode 100644 drivers/media/dvb/frontends/rtl2832_priv.h
--
1.7.7.6
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH 1/5] rtl2832 ver 0.3: suport for RTL2832 demodulator revised version 2012-05-12 18:08 [PATCH 0/5] support rtl2832 demodulator Thomas Mair @ 2012-05-12 18:08 ` Thomas Mair 2012-05-12 22:07 ` poma ` (2 more replies) 2012-05-12 18:08 ` [PATCH 2/5] rtl28xxu: support for the rtl2832 demod driver Thomas Mair ` (4 subsequent siblings) 5 siblings, 3 replies; 16+ messages in thread From: Thomas Mair @ 2012-05-12 18:08 UTC (permalink / raw) To: linux-media; +Cc: Thomas Mair Changes compared to version 0.2: - removed reading of signal strength for tuners FC0012,FC0013 (is now supported by fc0012,fc0013 driver) - moved definition of register names to rtl2832_priv.h - cleaned up demod private structure - replaced rtl2832_log2 function with intlog2 from dvb_math Signed-off-by: Thomas Mair <thomas.mair86@googlemail.com> --- drivers/media/dvb/frontends/Kconfig | 7 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/rtl2832.c | 1009 ++++++++++++++++++++++++++++ drivers/media/dvb/frontends/rtl2832.h | 81 +++ drivers/media/dvb/frontends/rtl2832_priv.h | 260 +++++++ 5 files changed, 1358 insertions(+), 0 deletions(-) create mode 100644 drivers/media/dvb/frontends/rtl2832.c create mode 100644 drivers/media/dvb/frontends/rtl2832.h create mode 100644 drivers/media/dvb/frontends/rtl2832_priv.h diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index f479834..f7d67d7 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -432,6 +432,13 @@ config DVB_RTL2830 help Say Y when you want to support this frontend. +config DVB_RTL2832 + tristate "Realtek RTL2832 DVB-T" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + Say Y when you want to support this frontend. + comment "DVB-C (cable) frontends" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index b0381dc..9731192 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -98,6 +98,7 @@ obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o obj-$(CONFIG_DVB_A8293) += a8293.o obj-$(CONFIG_DVB_TDA10071) += tda10071.o obj-$(CONFIG_DVB_RTL2830) += rtl2830.o +obj-$(CONFIG_DVB_RTL2832) = rtl2832.o obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o obj-$(CONFIG_DVB_AF9033) += af9033.o diff --git a/drivers/media/dvb/frontends/rtl2832.c b/drivers/media/dvb/frontends/rtl2832.c new file mode 100644 index 0000000..1936c50 --- /dev/null +++ b/drivers/media/dvb/frontends/rtl2832.c @@ -0,0 +1,1009 @@ +/* + * Realtek RTL2832 DVB-T demodulator driver + * + * Copyright (C) 2012 Thomas Mair <thomas.mair86@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "rtl2832_priv.h" +#include "dvb_math.h" + + +int rtl2832_debug; +module_param_named(debug, rtl2832_debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + + +static int reg_mask[32] = { + 0x00000001, + 0x00000003, + 0x00000007, + 0x0000000f, + 0x0000001f, + 0x0000003f, + 0x0000007f, + 0x000000ff, + 0x000001ff, + 0x000003ff, + 0x000007ff, + 0x00000fff, + 0x00001fff, + 0x00003fff, + 0x00007fff, + 0x0000ffff, + 0x0001ffff, + 0x0003ffff, + 0x0007ffff, + 0x000fffff, + 0x001fffff, + 0x003fffff, + 0x007fffff, + 0x00ffffff, + 0x01ffffff, + 0x03ffffff, + 0x07ffffff, + 0x0fffffff, + 0x1fffffff, + 0x3fffffff, + 0x7fffffff, + 0xffffffff +}; + +static const rtl2832_reg_entry registers[] = { + [DVBT_SOFT_RST] = {0x1, 0x1, 2, 2}, + [DVBT_IIC_REPEAT] = {0x1, 0x1, 3, 3}, + [DVBT_TR_WAIT_MIN_8K] = {0x1, 0x88, 11, 2}, + [DVBT_RSD_BER_FAIL_VAL] = {0x1, 0x8f, 15, 0}, + [DVBT_EN_BK_TRK] = {0x1, 0xa6, 7, 7}, + [DVBT_AD_EN_REG] = {0x0, 0x8, 7, 7}, + [DVBT_AD_EN_REG1] = {0x0, 0x8, 6, 6}, + [DVBT_EN_BBIN] = {0x1, 0xb1, 0, 0}, + [DVBT_MGD_THD0] = {0x1, 0x95, 7, 0}, + [DVBT_MGD_THD1] = {0x1, 0x96, 7, 0}, + [DVBT_MGD_THD2] = {0x1, 0x97, 7, 0}, + [DVBT_MGD_THD3] = {0x1, 0x98, 7, 0}, + [DVBT_MGD_THD4] = {0x1, 0x99, 7, 0}, + [DVBT_MGD_THD5] = {0x1, 0x9a, 7, 0}, + [DVBT_MGD_THD6] = {0x1, 0x9b, 7, 0}, + [DVBT_MGD_THD7] = {0x1, 0x9c, 7, 0}, + [DVBT_EN_CACQ_NOTCH] = {0x1, 0x61, 4, 4}, + [DVBT_AD_AV_REF] = {0x0, 0x9, 6, 0}, + [DVBT_REG_PI] = {0x0, 0xa, 2, 0}, + [DVBT_PIP_ON] = {0x0, 0x21, 3, 3}, + [DVBT_SCALE1_B92] = {0x2, 0x92, 7, 0}, + [DVBT_SCALE1_B93] = {0x2, 0x93, 7, 0}, + [DVBT_SCALE1_BA7] = {0x2, 0xa7, 7, 0}, + [DVBT_SCALE1_BA9] = {0x2, 0xa9, 7, 0}, + [DVBT_SCALE1_BAA] = {0x2, 0xaa, 7, 0}, + [DVBT_SCALE1_BAB] = {0x2, 0xab, 7, 0}, + [DVBT_SCALE1_BAC] = {0x2, 0xac, 7, 0}, + [DVBT_SCALE1_BB0] = {0x2, 0xb0, 7, 0}, + [DVBT_SCALE1_BB1] = {0x2, 0xb1, 7, 0}, + [DVBT_KB_P1] = {0x1, 0x64, 3, 1}, + [DVBT_KB_P2] = {0x1, 0x64, 6, 4}, + [DVBT_KB_P3] = {0x1, 0x65, 2, 0}, + [DVBT_OPT_ADC_IQ] = {0x0, 0x6, 5, 4}, + [DVBT_AD_AVI] = {0x0, 0x9, 1, 0}, + [DVBT_AD_AVQ] = {0x0, 0x9, 3, 2}, + [DVBT_K1_CR_STEP12] = {0x2, 0xad, 9, 4}, + [DVBT_TRK_KS_P2] = {0x1, 0x6f, 2, 0}, + [DVBT_TRK_KS_I2] = {0x1, 0x70, 5, 3}, + [DVBT_TR_THD_SET2] = {0x1, 0x72, 3, 0}, + [DVBT_TRK_KC_P2] = {0x1, 0x73, 5, 3}, + [DVBT_TRK_KC_I2] = {0x1, 0x75, 2, 0}, + [DVBT_CR_THD_SET2] = {0x1, 0x76, 7, 6}, + [DVBT_PSET_IFFREQ] = {0x1, 0x19, 21, 0}, + [DVBT_SPEC_INV] = {0x1, 0x15, 0, 0}, + [DVBT_RSAMP_RATIO] = {0x1, 0x9f, 27, 2}, + [DVBT_CFREQ_OFF_RATIO] = {0x1, 0x9d, 23, 4}, + [DVBT_FSM_STAGE] = {0x3, 0x51, 6, 3}, + [DVBT_RX_CONSTEL] = {0x3, 0x3c, 3, 2}, + [DVBT_RX_HIER] = {0x3, 0x3c, 6, 4}, + [DVBT_RX_C_RATE_LP] = {0x3, 0x3d, 2, 0}, + [DVBT_RX_C_RATE_HP] = {0x3, 0x3d, 5, 3}, + [DVBT_GI_IDX] = {0x3, 0x51, 1, 0}, + [DVBT_FFT_MODE_IDX] = {0x3, 0x51, 2, 2}, + [DVBT_RSD_BER_EST] = {0x3, 0x4e, 15, 0}, + [DVBT_CE_EST_EVM] = {0x4, 0xc, 15, 0}, + [DVBT_RF_AGC_VAL] = {0x3, 0x5b, 13, 0}, + [DVBT_IF_AGC_VAL] = {0x3, 0x59, 13, 0}, + [DVBT_DAGC_VAL] = {0x3, 0x5, 7, 0}, + [DVBT_SFREQ_OFF] = {0x3, 0x18, 13, 0}, + [DVBT_CFREQ_OFF] = {0x3, 0x5f, 17, 0}, + [DVBT_POLAR_RF_AGC] = {0x0, 0xe, 1, 1}, + [DVBT_POLAR_IF_AGC] = {0x0, 0xe, 0, 0}, + [DVBT_AAGC_HOLD] = {0x1, 0x4, 5, 5}, + [DVBT_EN_RF_AGC] = {0x1, 0x4, 6, 6}, + [DVBT_EN_IF_AGC] = {0x1, 0x4, 7, 7}, + [DVBT_IF_AGC_MIN] = {0x1, 0x8, 7, 0}, + [DVBT_IF_AGC_MAX] = {0x1, 0x9, 7, 0}, + [DVBT_RF_AGC_MIN] = {0x1, 0xa, 7, 0}, + [DVBT_RF_AGC_MAX] = {0x1, 0xb, 7, 0}, + [DVBT_IF_AGC_MAN] = {0x1, 0xc, 6, 6}, + [DVBT_IF_AGC_MAN_VAL] = {0x1, 0xc, 13, 0}, + [DVBT_RF_AGC_MAN] = {0x1, 0xe, 6, 6}, + [DVBT_RF_AGC_MAN_VAL] = {0x1, 0xe, 13, 0}, + [DVBT_DAGC_TRG_VAL] = {0x1, 0x12, 7, 0}, + [DVBT_AGC_TARG_VAL_0] = {0x1, 0x2, 0, 0}, + [DVBT_AGC_TARG_VAL_8_1] = {0x1, 0x3, 7, 0}, + [DVBT_AAGC_LOOP_GAIN] = {0x1, 0xc7, 5, 1}, + [DVBT_LOOP_GAIN2_3_0] = {0x1, 0x4, 4, 1}, + [DVBT_LOOP_GAIN2_4] = {0x1, 0x5, 7, 7}, + [DVBT_LOOP_GAIN3] = {0x1, 0xc8, 4, 0}, + [DVBT_VTOP1] = {0x1, 0x6, 5, 0}, + [DVBT_VTOP2] = {0x1, 0xc9, 5, 0}, + [DVBT_VTOP3] = {0x1, 0xca, 5, 0}, + [DVBT_KRF1] = {0x1, 0xcb, 7, 0}, + [DVBT_KRF2] = {0x1, 0x7, 7, 0}, + [DVBT_KRF3] = {0x1, 0xcd, 7, 0}, + [DVBT_KRF4] = {0x1, 0xce, 7, 0}, + [DVBT_EN_GI_PGA] = {0x1, 0xe5, 0, 0}, + [DVBT_THD_LOCK_UP] = {0x1, 0xd9, 8, 0}, + [DVBT_THD_LOCK_DW] = {0x1, 0xdb, 8, 0}, + [DVBT_THD_UP1] = {0x1, 0xdd, 7, 0}, + [DVBT_THD_DW1] = {0x1, 0xde, 7, 0}, + [DVBT_INTER_CNT_LEN] = {0x1, 0xd8, 3, 0}, + [DVBT_GI_PGA_STATE] = {0x1, 0xe6, 3, 3}, + [DVBT_EN_AGC_PGA] = {0x1, 0xd7, 0, 0}, + [DVBT_CKOUTPAR] = {0x1, 0x7b, 5, 5}, + [DVBT_CKOUT_PWR] = {0x1, 0x7b, 6, 6}, + [DVBT_SYNC_DUR] = {0x1, 0x7b, 7, 7}, + [DVBT_ERR_DUR] = {0x1, 0x7c, 0, 0}, + [DVBT_SYNC_LVL] = {0x1, 0x7c, 1, 1}, + [DVBT_ERR_LVL] = {0x1, 0x7c, 2, 2}, + [DVBT_VAL_LVL] = {0x1, 0x7c, 3, 3}, + [DVBT_SERIAL] = {0x1, 0x7c, 4, 4}, + [DVBT_SER_LSB] = {0x1, 0x7c, 5, 5}, + [DVBT_CDIV_PH0] = {0x1, 0x7d, 3, 0}, + [DVBT_CDIV_PH1] = {0x1, 0x7d, 7, 4}, + [DVBT_MPEG_IO_OPT_2_2] = {0x0, 0x6, 7, 7}, + [DVBT_MPEG_IO_OPT_1_0] = {0x0, 0x7, 7, 6}, + [DVBT_CKOUTPAR_PIP] = {0x0, 0xb7, 4, 4}, + [DVBT_CKOUT_PWR_PIP] = {0x0, 0xb7, 3, 3}, + [DVBT_SYNC_LVL_PIP] = {0x0, 0xb7, 2, 2}, + [DVBT_ERR_LVL_PIP] = {0x0, 0xb7, 1, 1}, + [DVBT_VAL_LVL_PIP] = {0x0, 0xb7, 0, 0}, + [DVBT_CKOUTPAR_PID] = {0x0, 0xb9, 4, 4}, + [DVBT_CKOUT_PWR_PID] = {0x0, 0xb9, 3, 3}, + [DVBT_SYNC_LVL_PID] = {0x0, 0xb9, 2, 2}, + [DVBT_ERR_LVL_PID] = {0x0, 0xb9, 1, 1}, + [DVBT_VAL_LVL_PID] = {0x0, 0xb9, 0, 0}, + [DVBT_SM_PASS] = {0x1, 0x93, 11, 0}, + [DVBT_AD7_SETTING] = {0x0, 0x11, 15, 0}, + [DVBT_RSSI_R] = {0x3, 0x1, 6, 0}, + [DVBT_ACI_DET_IND] = {0x3, 0x12, 0, 0}, + [DVBT_REG_MON] = {0x0, 0xd, 1, 0}, + [DVBT_REG_MONSEL] = {0x0, 0xd, 2, 2}, + [DVBT_REG_GPE] = {0x0, 0xd, 7, 7}, + [DVBT_REG_GPO] = {0x0, 0x10, 0, 0}, + [DVBT_REG_4MSEL] = {0x0, 0x13, 0, 0}, +}; + +/* write multiple hardware registers */ +static int rtl2832_wr(struct rtl2832_priv *priv, u8 reg, u8 *val, int len) +{ + int ret; + u8 buf[1+len]; + struct i2c_msg msg[1] = { + { + .addr = priv->cfg.i2c_addr, + .flags = 0, + .len = 1+len, + .buf = buf, + } + }; + + buf[0] = reg; + memcpy(&buf[1], val, len); + + ret = i2c_transfer(priv->i2c, msg, 1); + if (ret == 1) { + ret = 0; + } else { + warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len); + ret = -EREMOTEIO; + } + return ret; +} + +/* read multiple hardware registers */ +static int rtl2832_rd(struct rtl2832_priv *priv, u8 reg, u8 *val, int len) +{ + int ret; + struct i2c_msg msg[2] = { + { + .addr = priv->cfg.i2c_addr, + .flags = 0, + .len = 1, + .buf = ®, + }, { + .addr = priv->cfg.i2c_addr, + .flags = I2C_M_RD, + .len = len, + .buf = val, + } + }; + + ret = i2c_transfer(priv->i2c, msg, 2); + if (ret == 2) { + ret = 0; + } else { + warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len); + ret = -EREMOTEIO; +} +return ret; +} + +/* write multiple registers */ +static int rtl2832_wr_regs(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val, + int len) +{ + int ret; + + + /* switch bank if needed */ + if (page != priv->page) { + ret = rtl2832_wr(priv, 0x00, &page, 1); + if (ret) + return ret; + + priv->page = page; +} + +return rtl2832_wr(priv, reg, val, len); +} + +/* read multiple registers */ +static int rtl2832_rd_regs(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val, + int len) +{ + int ret; + + /* switch bank if needed */ + if (page != priv->page) { + ret = rtl2832_wr(priv, 0x00, &page, 1); + if (ret) + return ret; + + priv->page = page; + } + + return rtl2832_rd(priv, reg, val, len); +} + +#if 0 /* currently not used */ +/* write single register */ +static int rtl2832_wr_reg(struct rtl2832_priv *priv, u8 reg, u8 page, u8 val) +{ + return rtl2832_wr_regs(priv, reg, page, &val, 1); +} +#endif + +/* read single register */ +static int rtl2832_rd_reg(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val) +{ + return rtl2832_rd_regs(priv, reg, page, val, 1); +} + +int rtl2832_rd_demod_reg(struct rtl2832_priv *priv, int reg, u32 *val) +{ + int ret; + + u8 reg_start_addr; + u8 msb, lsb; + u8 page; + u8 reading[4]; + u32 reading_tmp; + int i; + + u8 len; + u32 mask; + + reg_start_addr = registers[reg].start_address; + msb = registers[reg].msb; + lsb = registers[reg].lsb; + page = registers[reg].page; + + len = (msb >> 3) + 1; + mask = reg_mask[msb-lsb]; + + + ret = rtl2832_rd_regs(priv, reg_start_addr, page, &reading[0], len); + if (ret) + goto err; + + reading_tmp = 0; + for (i = 0; i < len; i++) + reading_tmp |= reading[i] << ((len-1-i)*8); + + *val = (reading_tmp >> lsb) & mask; + + return ret; + +err: + return ret; + +} + +int rtl2832_wr_demod_reg(struct rtl2832_priv *priv, int reg, u32 val) +{ + int ret, i; + u8 len; + u8 reg_start_addr; + u8 msb, lsb; + u8 page; + u32 mask; + + + u8 reading[4]; + u8 writing[4]; + u32 reading_tmp; + u32 writing_tmp; + + + reg_start_addr = registers[reg].start_address; + msb = registers[reg].msb; + lsb = registers[reg].lsb; + page = registers[reg].page; + + len = (msb >> 3) + 1; + mask = reg_mask[msb-lsb]; + + + ret = rtl2832_rd_regs(priv, reg_start_addr, page, &reading[0], len); + if (ret) + goto err; + + reading_tmp = 0; + for (i = 0; i < len; i++) + reading_tmp |= reading[i] << ((len-1-i)*8); + + writing_tmp = reading_tmp & ~(mask << lsb); + writing_tmp |= ((val & mask) << lsb); + + + for (i = 0; i < len; i++) + writing[i] = (writing_tmp >> ((len-1-i)*8)) & 0xff; + + ret = rtl2832_wr_regs(priv, reg_start_addr, page, &writing[0], len); + if (ret) + goto err; + + return ret; + +err: + return ret; + +} + + +static int rtl2832_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) +{ + int ret; + struct rtl2832_priv *priv = fe->demodulator_priv; + + dbg("%s: enable=%d", __func__, enable); + + /* gate already open or close */ + if (priv->i2c_gate_state == enable) + return 0; + + ret = rtl2832_wr_demod_reg(priv, DVBT_IIC_REPEAT, (enable ? 0x1 : 0x0)); + + if (ret) + goto err; + + priv->i2c_gate_state = enable; + + return ret; +err: + dbg("%s: failed=%d", __func__, ret); + return ret; +} + + + +static int rtl2832_init(struct dvb_frontend *fe) +{ + struct rtl2832_priv *priv = fe->demodulator_priv; + int i, ret; + + u8 en_bbin; + u64 pset_iffreq; + + /* initialization values for the demodulator registers */ + static rtl2832_reg_value rtl2832_initial_regs_1[] = { + {DVBT_AD_EN_REG, 0x1}, + {DVBT_AD_EN_REG1, 0x1}, + {DVBT_RSD_BER_FAIL_VAL, 0x2800}, + {DVBT_MGD_THD0, 0x10}, + {DVBT_MGD_THD1, 0x20}, + {DVBT_MGD_THD2, 0x20}, + {DVBT_MGD_THD3, 0x40}, + {DVBT_MGD_THD4, 0x22}, + {DVBT_MGD_THD5, 0x32}, + {DVBT_MGD_THD6, 0x37}, + {DVBT_MGD_THD7, 0x39}, + {DVBT_EN_BK_TRK, 0x0}, + {DVBT_EN_CACQ_NOTCH, 0x0}, + {DVBT_AD_AV_REF, 0x2a}, + {DVBT_REG_PI, 0x6}, + {DVBT_PIP_ON, 0x0}, + {DVBT_CDIV_PH0, 0x8}, + {DVBT_CDIV_PH1, 0x8}, + {DVBT_SCALE1_B92, 0x4}, + {DVBT_SCALE1_B93, 0xb0}, + {DVBT_SCALE1_BA7, 0x78}, + {DVBT_SCALE1_BA9, 0x28}, + {DVBT_SCALE1_BAA, 0x59}, + {DVBT_SCALE1_BAB, 0x83}, + {DVBT_SCALE1_BAC, 0xd4}, + {DVBT_SCALE1_BB0, 0x65}, + {DVBT_SCALE1_BB1, 0x43}, + {DVBT_KB_P1, 0x1}, + {DVBT_KB_P2, 0x4}, + {DVBT_KB_P3, 0x7}, + {DVBT_K1_CR_STEP12, 0xa}, + {DVBT_REG_GPE, 0x1}, + {DVBT_SERIAL, 0x0}, + {DVBT_CDIV_PH0, 0x9}, + {DVBT_CDIV_PH1, 0x9}, + {DVBT_MPEG_IO_OPT_2_2, 0x0}, + {DVBT_MPEG_IO_OPT_1_0, 0x0}, + {DVBT_TRK_KS_P2, 0x4}, + {DVBT_TRK_KS_I2, 0x7}, + {DVBT_TR_THD_SET2, 0x6}, + {DVBT_TRK_KC_I2, 0x5}, + {DVBT_CR_THD_SET2, 0x1}, + + + }; + + static rtl2832_reg_value rtl2832_initial_regs_2[] = { + {DVBT_SPEC_INV, 0x0}, + {DVBT_DAGC_TRG_VAL, 0x5a}, + {DVBT_AGC_TARG_VAL_0, 0x0}, + {DVBT_AGC_TARG_VAL_8_1, 0x5a}, + {DVBT_AAGC_LOOP_GAIN, 0x16}, + {DVBT_LOOP_GAIN2_3_0, 0x6}, + {DVBT_LOOP_GAIN2_4, 0x1}, + {DVBT_LOOP_GAIN3, 0x16}, + {DVBT_VTOP1, 0x35}, + {DVBT_VTOP2, 0x21}, + {DVBT_VTOP3, 0x21}, + {DVBT_KRF1, 0x0}, + {DVBT_KRF2, 0x40}, + {DVBT_KRF3, 0x10}, + {DVBT_KRF4, 0x10}, + {DVBT_IF_AGC_MIN, 0x80}, + {DVBT_IF_AGC_MAX, 0x7f}, + {DVBT_RF_AGC_MIN, 0x80}, + {DVBT_RF_AGC_MAX, 0x7f}, + {DVBT_POLAR_RF_AGC, 0x0}, + {DVBT_POLAR_IF_AGC, 0x0}, + {DVBT_AD7_SETTING, 0xe9bf}, + {DVBT_EN_GI_PGA, 0x0}, + {DVBT_THD_LOCK_UP, 0x0}, + {DVBT_THD_LOCK_DW, 0x0}, + {DVBT_THD_UP1, 0x11}, + {DVBT_THD_DW1, 0xef}, + {DVBT_INTER_CNT_LEN, 0xc}, + {DVBT_GI_PGA_STATE, 0x0}, + {DVBT_EN_AGC_PGA, 0x1}, + {DVBT_IF_AGC_MAN, 0x0}, + }; + + + dbg("%s", __func__); + + en_bbin = (priv->cfg.if_dvbt == 0 ? 0x1 : 0x0); + + /* + * PSET_IFFREQ = - floor((IfFreqHz % CrystalFreqHz) * pow(2, 22) + * / CrystalFreqHz) + */ + pset_iffreq = priv->cfg.if_dvbt % priv->cfg.xtal; + pset_iffreq *= 0x400000; + pset_iffreq = div_u64(pset_iffreq, priv->cfg.xtal); + pset_iffreq = pset_iffreq & 0x3fffff; + + + + for (i = 0; i < 42; i++) { + ret = rtl2832_wr_demod_reg(priv, rtl2832_initial_regs_1[i].reg, + rtl2832_initial_regs_1[i].value); + if (ret) + goto err; + } + + /* if frequency settings */ + ret = rtl2832_wr_demod_reg(priv, DVBT_EN_BBIN, en_bbin); + if (ret) + goto err; + + ret = rtl2832_wr_demod_reg(priv, DVBT_PSET_IFFREQ, pset_iffreq); + if (ret) + goto err; + + for (i = 0; i < 31; i++) { + ret = rtl2832_wr_demod_reg(priv, rtl2832_initial_regs_2[i].reg, + rtl2832_initial_regs_2[i].value); + if (ret) + goto err; + } + + priv->sleeping = false; + + return ret; + +err: + return ret; +} + +static int rtl2832_sleep(struct dvb_frontend *fe) +{ + struct rtl2832_priv *priv = fe->demodulator_priv; + + dbg("%s", __func__); + priv->sleeping = true; + return 0; +} + +int rtl2832_get_tune_settings(struct dvb_frontend *fe, + struct dvb_frontend_tune_settings *s) +{ + dbg("%s", __func__); + s->min_delay_ms = 1000; + s->step_size = fe->ops.info.frequency_stepsize * 2; + s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; + return 0; +} + +static int rtl2832_set_frontend(struct dvb_frontend *fe) +{ + struct rtl2832_priv *priv = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + int ret, i, j; + u64 bw_mode, num, num2; + u32 resamp_ratio, cfreq_off_ratio; + + + static u8 bw_params[3][32] = { + /* 6 MHz bandwidth */ + { + 0xf5, 0xff, 0x15, 0x38, 0x5d, 0x6d, 0x52, 0x07, 0xfa, 0x2f, + 0x53, 0xf5, 0x3f, 0xca, 0x0b, 0x91, 0xea, 0x30, 0x63, 0xb2, + 0x13, 0xda, 0x0b, 0xc4, 0x18, 0x7e, 0x16, 0x66, 0x08, 0x67, + 0x19, 0xe0, + }, + + /* 7 MHz bandwidth */ + { + 0xe7, 0xcc, 0xb5, 0xba, 0xe8, 0x2f, 0x67, 0x61, 0x00, 0xaf, + 0x86, 0xf2, 0xbf, 0x59, 0x04, 0x11, 0xb6, 0x33, 0xa4, 0x30, + 0x15, 0x10, 0x0a, 0x42, 0x18, 0xf8, 0x17, 0xd9, 0x07, 0x22, + 0x19, 0x10, + }, + + /* 8 MHz bandwidth */ + { + 0x09, 0xf6, 0xd2, 0xa7, 0x9a, 0xc9, 0x27, 0x77, 0x06, 0xbf, + 0xec, 0xf4, 0x4f, 0x0b, 0xfc, 0x01, 0x63, 0x35, 0x54, 0xa7, + 0x16, 0x66, 0x08, 0xb4, 0x19, 0x6e, 0x19, 0x65, 0x05, 0xc8, + 0x19, 0xe0, + }, + }; + + + dbg("%s: frequency=%d bandwidth_hz=%d inversion=%d", __func__, + c->frequency, c->bandwidth_hz, c->inversion); + + + /* program tuner */ + if (fe->ops.tuner_ops.set_params) + fe->ops.tuner_ops.set_params(fe); + + + switch (c->bandwidth_hz) { + case 6000000: + i = 0; + bw_mode = 48000000; + break; + case 7000000: + i = 1; + bw_mode = 56000000; + break; + case 8000000: + i = 2; + bw_mode = 64000000; + break; + default: + dbg("invalid bandwidth"); + return -EINVAL; + } + + for (j = 0; j < 32; j++) { + ret = rtl2832_wr_regs(priv, 0x1c+j, 1, &bw_params[i][j], 1); + if (ret) + goto err; + } + + /* calculate and set resample ratio + * RSAMP_RATIO = floor(CrystalFreqHz * 7 * pow(2, 22) + * / ConstWithBandwidthMode) + */ + num = priv->cfg.xtal * 7; + num *= 0x400000; + num = div_u64(num, bw_mode); + resamp_ratio = num & 0x3ffffff; + ret = rtl2832_wr_demod_reg(priv, DVBT_RSAMP_RATIO, resamp_ratio); + if (ret) + goto err; + + /* calculate and set cfreq off ratio + * CFREQ_OFF_RATIO = - floor(ConstWithBandwidthMode * pow(2, 20) + * / (CrystalFreqHz * 7)) + */ + num = bw_mode << 20; + num2 = priv->cfg.xtal * 7; + num = div_u64(num, num2); + num = -num; + cfreq_off_ratio = num & 0xfffff; + ret = rtl2832_wr_demod_reg(priv, DVBT_CFREQ_OFF_RATIO, cfreq_off_ratio); + if (ret) + goto err; + + + /* soft reset */ + ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x1); + if (ret) + goto err; + + ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x0); + if (ret) + goto err; + + return ret; +err: + info("%s: failed=%d", __func__, ret); + return ret; +} + +static int rtl2832_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct rtl2832_priv *priv = fe->demodulator_priv; + int ret; + u32 tmp; + *status = 0; + + + dbg("%s", __func__); + if (priv->sleeping) + return 0; + + ret = rtl2832_rd_demod_reg(priv, DVBT_FSM_STAGE, &tmp); + if (ret) + goto err; + + if (tmp == 11) { + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | + FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; + } + /* TODO find out if this is also true for rtl2832? */ + /*else if (tmp == 10) { + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | + FE_HAS_VITERBI; + }*/ + + return ret; +err: + info("%s: failed=%d", __func__, ret); + return ret; +} + + +#define RTL2832_CE_EST_EVM_MAX_VALUE 65535 +#define RTL2832_SNR_FRAC_BIT_NUM 10 +#define RTL2832_SNR_DB_DEN 3402 + +static int rtl2832_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + struct rtl2832_priv *priv = fe->demodulator_priv; + int ret; + u64 num; + u32 ce_est_evm, fsm_stage, constellation, hierarchy; + + /* Calculated by: 10 * log2(Norm * pow(2, 11)) * pow(2, 10) */ + static const long SnrDbNum[3][4] = { + {122880, 122880, 122880, 122880, }, + {146657, 146657, 156897, 171013, }, + {167857, 167857, 173127, 181810, }, + }; + + static const int snrMaxDb[3] = { 23, 26, 29, }; + + dbg("%s", __func__); + + /* get FSM Stage */ + ret = rtl2832_rd_demod_reg(priv, DVBT_FSM_STAGE, &fsm_stage); + if (ret) + goto err; + + if (fsm_stage < 10) { + ce_est_evm = RTL2832_CE_EST_EVM_MAX_VALUE; + } else { + ret = rtl2832_rd_demod_reg(priv, DVBT_CE_EST_EVM, &ce_est_evm); + if (ret) + goto err; + } + + /* get constellation */ + ret = rtl2832_rd_demod_reg(priv, DVBT_RX_CONSTEL, &constellation); + if (ret) + goto err; + if (constellation > 2) + goto err; + + /* get hierarchy */ + ret = rtl2832_rd_demod_reg(priv, DVBT_RX_HIER, &hierarchy); + if (ret) + goto err; + if (hierarchy > 3) + goto err; + + + /* + SNR dB formula + Original formula: SNR_dB = 10 * log10(Norm * pow(2, 11) / CeEstEvm) + Adjusted formula: SNR_dB = (SNR_DB_NUM_CONST - 10 * log2(CeEstEvm) * + pow(2, 10)) / SNR_DB_DEN + SNR_DB_NUM_CONST = 10 * log2(Norm * pow(2, 11)) * + pow(2, 10) + SNR_DB_DEN = log2(10) * pow(2, 10) = 3402 = 0xd4a + Norm: + None Alpha=1 Alpha=2 Alpha=4 + 4-QAM 2 2 2 2 + 16-QAM 10 10 20 52 + 64-QAM 42 42 60 108 + */ + + /* intlog2 returns log2(x) << 24 */ + num = intlog2(ce_est_evm)>>14; + num = SnrDbNum[constellation][hierarchy] - 10 * num; + + num = div_u64(num, RTL2832_SNR_DB_DEN); + num *= 0xffff; + num = div_u64(num, snrMaxDb[constellation]); + + if (num > 0xffff) + *snr = 0xffff; + else if (num < 0) + *snr = 0; + else + *snr = 0xffff & num; + + return ret; + +err: + info("%s: failed=%d", __func__, ret); + return ret; +} + +static int rtl2832_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + struct rtl2832_priv *priv = fe->demodulator_priv; + int ret; + u32 tmp; + + dbg("%s", __func__); + + /* get BER */ + ret = rtl2832_rd_demod_reg(priv, DVBT_RSD_BER_EST, &tmp); + if (ret) + goto err; + + *ber = tmp; + return ret; + +err: + info("%s: failed=%d", __func__, ret); + *ber = 19616; + return ret; +} + +static int rtl2832_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) +{ + struct rtl2832_priv *priv = fe->demodulator_priv; + int ret; + u32 tmp; + u16 num; + + dbg("%s", __func__); + + + /* get FSM Stage */ + ret = rtl2832_rd_demod_reg(priv, DVBT_FSM_STAGE, &tmp); + if (ret) + goto err; + + /* if signal is not locked quality is zero */ + if (tmp < 10) { + *ucblocks = 0; + return 0; + } + + /* get BER */ + ret = rtl2832_rd_demod_reg(priv, DVBT_RSD_BER_EST, &tmp); + if (ret) + goto err; + + /* + Determine signal quality according to RSD_BER_EST. + Note: Map RSD_BER_EST value 8192 ~ 128 to 10 ~ 100 + Original formula: SignalQuality = 205 - 15 * log2(RSD_BER_EST) + Adjusted formula: SignalQuality = ((205 << 5) - 15 * + (log2(RSD_BER_EST) << 5)) >> 5 + If RSD_BER_EST > 8192, signal quality is 10. + If RSD_BER_EST < 128, signal quality is 100. + */ + + if (tmp > 8192) + *ucblocks = 10; + else if (tmp < 128) + *ucblocks = 100; + else { + num = intlog2(tmp) >> 19; + *ucblocks = ((205 << 5) - 15 * num) >> 5; + } + + return 0; + +err: + info("%s: failed=%d", __func__, ret); + *ucblocks = 0; + return ret; +} + + +static int rtl2832_read_signal_strength(struct dvb_frontend *fe, u16 *strength) +{ + struct rtl2832_priv *priv = fe->demodulator_priv; + int ret, if_agc; + u32 fsm_stage, if_agc_raw; + + dbg("%s", __func__); + + ret = rtl2832_rd_demod_reg(priv, DVBT_FSM_STAGE, &fsm_stage); + if (ret) + goto err; + + if (fsm_stage < 10) + *strength = 0; + else { + /* if_agc is read as a 10bit binary */ + ret = rtl2832_rd_demod_reg(priv, DVBT_IF_AGC_VAL, &if_agc_raw); + if (ret) + goto err; + + if (if_agc_raw < (1 << 9)) + if_agc = if_agc_raw; + else + if_agc = -(~(if_agc_raw-1) & 0x1ff); + + *strength = 55 - if_agc / 182; + *strength |= *strength << 8; + } + return 0; +err: + info("%s: failed=%d", __func__, ret); + return ret; +} + +static struct dvb_frontend_ops rtl2832_ops; + +static void rtl2832_release(struct dvb_frontend *fe) +{ + struct rtl2832_priv *priv = fe->demodulator_priv; + + dbg("%s", __func__); + kfree(priv); +} + +struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg, + struct i2c_adapter *i2c) +{ + struct rtl2832_priv *priv = NULL; + int ret = 0; + u8 tmp; + + dbg("%s", __func__); + + /* allocate memory for the internal state */ + priv = kzalloc(sizeof(struct rtl2832_priv), GFP_KERNEL); + if (priv == NULL) + goto err; + + /* setup the priv */ + priv->i2c = i2c; + priv->tuner = cfg->tuner; + memcpy(&priv->cfg, cfg, sizeof(struct rtl2832_config)); + + /* check if the demod is there */ + ret = rtl2832_rd_reg(priv, 0x00, 0x0, &tmp); + if (ret) + goto err; + + /* create dvb_frontend */ + memcpy(&priv->fe.ops, &rtl2832_ops, sizeof(struct dvb_frontend_ops)); + priv->fe.demodulator_priv = priv; + + /* TODO implement sleep mode depending on RC */ + priv->sleeping = true; + + return &priv->fe; +err: + dbg("%s: failed=%d", __func__, ret); + kfree(priv); + return NULL; +} +EXPORT_SYMBOL(rtl2832_attach); + +static struct dvb_frontend_ops rtl2832_ops = { + .delsys = { SYS_DVBT }, + .info = { + .name = "Realtek RTL2832 (DVB-T)", + .type = FE_OFDM, + .frequency_min = 50000000, + .frequency_max = 862000000, + .frequency_stepsize = 166667, + .caps = FE_CAN_FEC_1_2 | + FE_CAN_FEC_2_3 | + FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | + FE_CAN_FEC_7_8 | + FE_CAN_FEC_AUTO | + FE_CAN_QPSK | + FE_CAN_QAM_16 | + FE_CAN_QAM_64 | + FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_HIERARCHY_AUTO | + FE_CAN_RECOVER | + FE_CAN_MUTE_TS + }, + + .release = rtl2832_release, + + .init = rtl2832_init, + .sleep = rtl2832_sleep, + + .get_tune_settings = rtl2832_get_tune_settings, + + .set_frontend = rtl2832_set_frontend, + + .read_status = rtl2832_read_status, + .read_snr = rtl2832_read_snr, + .read_ber = rtl2832_read_ber, + .read_ucblocks = rtl2832_read_ucblocks, + .read_signal_strength = rtl2832_read_signal_strength, + .i2c_gate_ctrl = rtl2832_i2c_gate_ctrl, +}; + +MODULE_AUTHOR("Thomas Mair <mair.thomas86@gmail.com>"); +MODULE_DESCRIPTION("Realtek RTL2832 DVB-T demodulator driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("0.3"); diff --git a/drivers/media/dvb/frontends/rtl2832.h b/drivers/media/dvb/frontends/rtl2832.h new file mode 100644 index 0000000..6918010 --- /dev/null +++ b/drivers/media/dvb/frontends/rtl2832.h @@ -0,0 +1,81 @@ +/* + * Realtek RTL2832 DVB-T demodulator driver + * + * Copyright (C) 2012 Thomas Mair <thomas.mair86@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef RTL2832_H +#define RTL2832_H + +#include <linux/dvb/frontend.h> + +struct rtl2832_config { + /* + * Demodulator I2C address. + */ + u8 i2c_addr; + + /* + * Xtal frequency. + * Hz + * 4000000, 16000000, 25000000, 28800000 + */ + u32 xtal; + + /* + * IFs for all used modes. + * Hz + * 4570000, 4571429, 36000000, 36125000, 36166667, 44000000 + */ + u32 if_dvbt; + + /* + */ + u8 tuner; +}; + + +#if defined(CONFIG_DVB_RTL2832) || \ + (defined(CONFIG_DVB_RTL2832_MODULE) && defined(MODULE)) +extern struct dvb_frontend *rtl2832_attach( + const struct rtl2832_config *cfg, + struct i2c_adapter *i2c +); + +extern struct i2c_adapter *rtl2832_get_tuner_i2c_adapter( + struct dvb_frontend *fe +); +#else +static inline struct dvb_frontend *rtl2832_attach( + const struct rtl2832_config *config, + struct i2c_adapter *i2c +) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} + +static inline struct i2c_adapter *rtl2832_get_tuner_i2c_adapter( + struct dvb_frontend *fe +) +{ + return NULL; +} +#endif + + +#endif /* RTL2832_H */ diff --git a/drivers/media/dvb/frontends/rtl2832_priv.h b/drivers/media/dvb/frontends/rtl2832_priv.h new file mode 100644 index 0000000..0f5df2f --- /dev/null +++ b/drivers/media/dvb/frontends/rtl2832_priv.h @@ -0,0 +1,260 @@ +/* + * Realtek RTL2832 DVB-T demodulator driver + * + * Copyright (C) 2012 Thomas Mair <thomas.mair86@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef RTL2832_PRIV_H +#define RTL2832_PRIV_H + +#include "dvb_frontend.h" +#include "rtl2832.h" + +#define LOG_PREFIX "rtl2832" + +#undef dbg +#define dbg(f, arg...) \ + if (rtl2832_debug) \ + printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) +#undef err +#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) +#undef info +#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) +#undef warn +#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) + +struct rtl2832_priv { + struct i2c_adapter *i2c; + struct dvb_frontend fe; + struct rtl2832_config cfg; + + bool i2c_gate_state; + bool sleeping; + + u8 tuner; + u8 page; /* active register page */ +}; + +typedef struct { + u8 page; + u8 start_address; + u8 msb; + u8 lsb; +} +rtl2832_reg_entry; + +typedef struct { + int reg; + u32 value; +} +rtl2832_reg_value; + + +/* Demod register bit names */ +enum DVBT_REG_BIT_NAME { + DVBT_SOFT_RST, + DVBT_IIC_REPEAT, + DVBT_TR_WAIT_MIN_8K, + DVBT_RSD_BER_FAIL_VAL, + DVBT_EN_BK_TRK, + DVBT_REG_PI, + DVBT_REG_PFREQ_1_0, + DVBT_PD_DA8, + DVBT_LOCK_TH, + DVBT_BER_PASS_SCAL, + DVBT_CE_FFSM_BYPASS, + DVBT_ALPHAIIR_N, + DVBT_ALPHAIIR_DIF, + DVBT_EN_TRK_SPAN, + DVBT_LOCK_TH_LEN, + DVBT_CCI_THRE, + DVBT_CCI_MON_SCAL, + DVBT_CCI_M0, + DVBT_CCI_M1, + DVBT_CCI_M2, + DVBT_CCI_M3, + DVBT_SPEC_INIT_0, + DVBT_SPEC_INIT_1, + DVBT_SPEC_INIT_2, + DVBT_AD_EN_REG, + DVBT_AD_EN_REG1, + DVBT_EN_BBIN, + DVBT_MGD_THD0, + DVBT_MGD_THD1, + DVBT_MGD_THD2, + DVBT_MGD_THD3, + DVBT_MGD_THD4, + DVBT_MGD_THD5, + DVBT_MGD_THD6, + DVBT_MGD_THD7, + DVBT_EN_CACQ_NOTCH, + DVBT_AD_AV_REF, + DVBT_PIP_ON, + DVBT_SCALE1_B92, + DVBT_SCALE1_B93, + DVBT_SCALE1_BA7, + DVBT_SCALE1_BA9, + DVBT_SCALE1_BAA, + DVBT_SCALE1_BAB, + DVBT_SCALE1_BAC, + DVBT_SCALE1_BB0, + DVBT_SCALE1_BB1, + DVBT_KB_P1, + DVBT_KB_P2, + DVBT_KB_P3, + DVBT_OPT_ADC_IQ, + DVBT_AD_AVI, + DVBT_AD_AVQ, + DVBT_K1_CR_STEP12, + DVBT_TRK_KS_P2, + DVBT_TRK_KS_I2, + DVBT_TR_THD_SET2, + DVBT_TRK_KC_P2, + DVBT_TRK_KC_I2, + DVBT_CR_THD_SET2, + DVBT_PSET_IFFREQ, + DVBT_SPEC_INV, + DVBT_BW_INDEX, + DVBT_RSAMP_RATIO, + DVBT_CFREQ_OFF_RATIO, + DVBT_FSM_STAGE, + DVBT_RX_CONSTEL, + DVBT_RX_HIER, + DVBT_RX_C_RATE_LP, + DVBT_RX_C_RATE_HP, + DVBT_GI_IDX, + DVBT_FFT_MODE_IDX, + DVBT_RSD_BER_EST, + DVBT_CE_EST_EVM, + DVBT_RF_AGC_VAL, + DVBT_IF_AGC_VAL, + DVBT_DAGC_VAL, + DVBT_SFREQ_OFF, + DVBT_CFREQ_OFF, + DVBT_POLAR_RF_AGC, + DVBT_POLAR_IF_AGC, + DVBT_AAGC_HOLD, + DVBT_EN_RF_AGC, + DVBT_EN_IF_AGC, + DVBT_IF_AGC_MIN, + DVBT_IF_AGC_MAX, + DVBT_RF_AGC_MIN, + DVBT_RF_AGC_MAX, + DVBT_IF_AGC_MAN, + DVBT_IF_AGC_MAN_VAL, + DVBT_RF_AGC_MAN, + DVBT_RF_AGC_MAN_VAL, + DVBT_DAGC_TRG_VAL, + DVBT_AGC_TARG_VAL, + DVBT_LOOP_GAIN_3_0, + DVBT_LOOP_GAIN_4, + DVBT_VTOP, + DVBT_KRF, + DVBT_AGC_TARG_VAL_0, + DVBT_AGC_TARG_VAL_8_1, + DVBT_AAGC_LOOP_GAIN, + DVBT_LOOP_GAIN2_3_0, + DVBT_LOOP_GAIN2_4, + DVBT_LOOP_GAIN3, + DVBT_VTOP1, + DVBT_VTOP2, + DVBT_VTOP3, + DVBT_KRF1, + DVBT_KRF2, + DVBT_KRF3, + DVBT_KRF4, + DVBT_EN_GI_PGA, + DVBT_THD_LOCK_UP, + DVBT_THD_LOCK_DW, + DVBT_THD_UP1, + DVBT_THD_DW1, + DVBT_INTER_CNT_LEN, + DVBT_GI_PGA_STATE, + DVBT_EN_AGC_PGA, + DVBT_CKOUTPAR, + DVBT_CKOUT_PWR, + DVBT_SYNC_DUR, + DVBT_ERR_DUR, + DVBT_SYNC_LVL, + DVBT_ERR_LVL, + DVBT_VAL_LVL, + DVBT_SERIAL, + DVBT_SER_LSB, + DVBT_CDIV_PH0, + DVBT_CDIV_PH1, + DVBT_MPEG_IO_OPT_2_2, + DVBT_MPEG_IO_OPT_1_0, + DVBT_CKOUTPAR_PIP, + DVBT_CKOUT_PWR_PIP, + DVBT_SYNC_LVL_PIP, + DVBT_ERR_LVL_PIP, + DVBT_VAL_LVL_PIP, + DVBT_CKOUTPAR_PID, + DVBT_CKOUT_PWR_PID, + DVBT_SYNC_LVL_PID, + DVBT_ERR_LVL_PID, + DVBT_VAL_LVL_PID, + DVBT_SM_PASS, + DVBT_UPDATE_REG_2, + DVBT_BTHD_P3, + DVBT_BTHD_D3, + DVBT_FUNC4_REG0, + DVBT_FUNC4_REG1, + DVBT_FUNC4_REG2, + DVBT_FUNC4_REG3, + DVBT_FUNC4_REG4, + DVBT_FUNC4_REG5, + DVBT_FUNC4_REG6, + DVBT_FUNC4_REG7, + DVBT_FUNC4_REG8, + DVBT_FUNC4_REG9, + DVBT_FUNC4_REG10, + DVBT_FUNC5_REG0, + DVBT_FUNC5_REG1, + DVBT_FUNC5_REG2, + DVBT_FUNC5_REG3, + DVBT_FUNC5_REG4, + DVBT_FUNC5_REG5, + DVBT_FUNC5_REG6, + DVBT_FUNC5_REG7, + DVBT_FUNC5_REG8, + DVBT_FUNC5_REG9, + DVBT_FUNC5_REG10, + DVBT_FUNC5_REG11, + DVBT_FUNC5_REG12, + DVBT_FUNC5_REG13, + DVBT_FUNC5_REG14, + DVBT_FUNC5_REG15, + DVBT_FUNC5_REG16, + DVBT_FUNC5_REG17, + DVBT_FUNC5_REG18, + DVBT_AD7_SETTING, + DVBT_RSSI_R, + DVBT_ACI_DET_IND, + DVBT_REG_MON, + DVBT_REG_MONSEL, + DVBT_REG_GPE, + DVBT_REG_GPO, + DVBT_REG_4MSEL, + DVBT_TEST_REG_1, + DVBT_TEST_REG_2, + DVBT_TEST_REG_3, + DVBT_TEST_REG_4, + DVBT_REG_BIT_NAME_ITEM_TERMINATOR, +}; + +#endif /* RTL2832_PRIV_H */ -- 1.7.7.6 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH 1/5] rtl2832 ver 0.3: suport for RTL2832 demodulator revised version 2012-05-12 18:08 ` [PATCH 1/5] rtl2832 ver 0.3: suport for RTL2832 demodulator revised version Thomas Mair @ 2012-05-12 22:07 ` poma 2012-05-13 18:53 ` Antti Palosaari 2012-05-14 1:37 ` Antti Palosaari 2 siblings, 0 replies; 16+ messages in thread From: poma @ 2012-05-12 22:07 UTC (permalink / raw) To: Thomas Mair, linux-media [-- Attachment #1: Type: text/plain, Size: 38302 bytes --] On 05/12/2012 08:08 PM, Thomas Mair wrote: > Changes compared to version 0.2: > - removed reading of signal strength for tuners FC0012,FC0013 (is now supported by fc0012,fc0013 driver) > - moved definition of register names to rtl2832_priv.h > - cleaned up demod private structure > - replaced rtl2832_log2 function with intlog2 from dvb_math > > Signed-off-by: Thomas Mair <thomas.mair86@googlemail.com> > --- > drivers/media/dvb/frontends/Kconfig | 7 + > drivers/media/dvb/frontends/Makefile | 1 + > drivers/media/dvb/frontends/rtl2832.c | 1009 ++++++++++++++++++++++++++++ > drivers/media/dvb/frontends/rtl2832.h | 81 +++ > drivers/media/dvb/frontends/rtl2832_priv.h | 260 +++++++ > 5 files changed, 1358 insertions(+), 0 deletions(-) > create mode 100644 drivers/media/dvb/frontends/rtl2832.c > create mode 100644 drivers/media/dvb/frontends/rtl2832.h > create mode 100644 drivers/media/dvb/frontends/rtl2832_priv.h > > diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig > index f479834..f7d67d7 100644 > --- a/drivers/media/dvb/frontends/Kconfig > +++ b/drivers/media/dvb/frontends/Kconfig > @@ -432,6 +432,13 @@ config DVB_RTL2830 > help > Say Y when you want to support this frontend. > > +config DVB_RTL2832 > + tristate "Realtek RTL2832 DVB-T" > + depends on DVB_CORE && I2C > + default m if DVB_FE_CUSTOMISE > + help > + Say Y when you want to support this frontend. > + > comment "DVB-C (cable) frontends" > depends on DVB_CORE > > diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile > index b0381dc..9731192 100644 > --- a/drivers/media/dvb/frontends/Makefile > +++ b/drivers/media/dvb/frontends/Makefile > @@ -98,6 +98,7 @@ obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o > obj-$(CONFIG_DVB_A8293) += a8293.o > obj-$(CONFIG_DVB_TDA10071) += tda10071.o > obj-$(CONFIG_DVB_RTL2830) += rtl2830.o > +obj-$(CONFIG_DVB_RTL2832) = rtl2832.o > obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o > obj-$(CONFIG_DVB_AF9033) += af9033.o > > diff --git a/drivers/media/dvb/frontends/rtl2832.c b/drivers/media/dvb/frontends/rtl2832.c > new file mode 100644 > index 0000000..1936c50 > --- /dev/null > +++ b/drivers/media/dvb/frontends/rtl2832.c > @@ -0,0 +1,1009 @@ > +/* > + * Realtek RTL2832 DVB-T demodulator driver > + * > + * Copyright (C) 2012 Thomas Mair <thomas.mair86@gmail.com> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License along > + * with this program; if not, write to the Free Software Foundation, Inc., > + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. > + */ > + > +#include "rtl2832_priv.h" > +#include "dvb_math.h" > + > + > +int rtl2832_debug; > +module_param_named(debug, rtl2832_debug, int, 0644); > +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); > + > + > +static int reg_mask[32] = { > + 0x00000001, > + 0x00000003, > + 0x00000007, > + 0x0000000f, > + 0x0000001f, > + 0x0000003f, > + 0x0000007f, > + 0x000000ff, > + 0x000001ff, > + 0x000003ff, > + 0x000007ff, > + 0x00000fff, > + 0x00001fff, > + 0x00003fff, > + 0x00007fff, > + 0x0000ffff, > + 0x0001ffff, > + 0x0003ffff, > + 0x0007ffff, > + 0x000fffff, > + 0x001fffff, > + 0x003fffff, > + 0x007fffff, > + 0x00ffffff, > + 0x01ffffff, > + 0x03ffffff, > + 0x07ffffff, > + 0x0fffffff, > + 0x1fffffff, > + 0x3fffffff, > + 0x7fffffff, > + 0xffffffff > +}; > + > +static const rtl2832_reg_entry registers[] = { > + [DVBT_SOFT_RST] = {0x1, 0x1, 2, 2}, > + [DVBT_IIC_REPEAT] = {0x1, 0x1, 3, 3}, > + [DVBT_TR_WAIT_MIN_8K] = {0x1, 0x88, 11, 2}, > + [DVBT_RSD_BER_FAIL_VAL] = {0x1, 0x8f, 15, 0}, > + [DVBT_EN_BK_TRK] = {0x1, 0xa6, 7, 7}, > + [DVBT_AD_EN_REG] = {0x0, 0x8, 7, 7}, > + [DVBT_AD_EN_REG1] = {0x0, 0x8, 6, 6}, > + [DVBT_EN_BBIN] = {0x1, 0xb1, 0, 0}, > + [DVBT_MGD_THD0] = {0x1, 0x95, 7, 0}, > + [DVBT_MGD_THD1] = {0x1, 0x96, 7, 0}, > + [DVBT_MGD_THD2] = {0x1, 0x97, 7, 0}, > + [DVBT_MGD_THD3] = {0x1, 0x98, 7, 0}, > + [DVBT_MGD_THD4] = {0x1, 0x99, 7, 0}, > + [DVBT_MGD_THD5] = {0x1, 0x9a, 7, 0}, > + [DVBT_MGD_THD6] = {0x1, 0x9b, 7, 0}, > + [DVBT_MGD_THD7] = {0x1, 0x9c, 7, 0}, > + [DVBT_EN_CACQ_NOTCH] = {0x1, 0x61, 4, 4}, > + [DVBT_AD_AV_REF] = {0x0, 0x9, 6, 0}, > + [DVBT_REG_PI] = {0x0, 0xa, 2, 0}, > + [DVBT_PIP_ON] = {0x0, 0x21, 3, 3}, > + [DVBT_SCALE1_B92] = {0x2, 0x92, 7, 0}, > + [DVBT_SCALE1_B93] = {0x2, 0x93, 7, 0}, > + [DVBT_SCALE1_BA7] = {0x2, 0xa7, 7, 0}, > + [DVBT_SCALE1_BA9] = {0x2, 0xa9, 7, 0}, > + [DVBT_SCALE1_BAA] = {0x2, 0xaa, 7, 0}, > + [DVBT_SCALE1_BAB] = {0x2, 0xab, 7, 0}, > + [DVBT_SCALE1_BAC] = {0x2, 0xac, 7, 0}, > + [DVBT_SCALE1_BB0] = {0x2, 0xb0, 7, 0}, > + [DVBT_SCALE1_BB1] = {0x2, 0xb1, 7, 0}, > + [DVBT_KB_P1] = {0x1, 0x64, 3, 1}, > + [DVBT_KB_P2] = {0x1, 0x64, 6, 4}, > + [DVBT_KB_P3] = {0x1, 0x65, 2, 0}, > + [DVBT_OPT_ADC_IQ] = {0x0, 0x6, 5, 4}, > + [DVBT_AD_AVI] = {0x0, 0x9, 1, 0}, > + [DVBT_AD_AVQ] = {0x0, 0x9, 3, 2}, > + [DVBT_K1_CR_STEP12] = {0x2, 0xad, 9, 4}, > + [DVBT_TRK_KS_P2] = {0x1, 0x6f, 2, 0}, > + [DVBT_TRK_KS_I2] = {0x1, 0x70, 5, 3}, > + [DVBT_TR_THD_SET2] = {0x1, 0x72, 3, 0}, > + [DVBT_TRK_KC_P2] = {0x1, 0x73, 5, 3}, > + [DVBT_TRK_KC_I2] = {0x1, 0x75, 2, 0}, > + [DVBT_CR_THD_SET2] = {0x1, 0x76, 7, 6}, > + [DVBT_PSET_IFFREQ] = {0x1, 0x19, 21, 0}, > + [DVBT_SPEC_INV] = {0x1, 0x15, 0, 0}, > + [DVBT_RSAMP_RATIO] = {0x1, 0x9f, 27, 2}, > + [DVBT_CFREQ_OFF_RATIO] = {0x1, 0x9d, 23, 4}, > + [DVBT_FSM_STAGE] = {0x3, 0x51, 6, 3}, > + [DVBT_RX_CONSTEL] = {0x3, 0x3c, 3, 2}, > + [DVBT_RX_HIER] = {0x3, 0x3c, 6, 4}, > + [DVBT_RX_C_RATE_LP] = {0x3, 0x3d, 2, 0}, > + [DVBT_RX_C_RATE_HP] = {0x3, 0x3d, 5, 3}, > + [DVBT_GI_IDX] = {0x3, 0x51, 1, 0}, > + [DVBT_FFT_MODE_IDX] = {0x3, 0x51, 2, 2}, > + [DVBT_RSD_BER_EST] = {0x3, 0x4e, 15, 0}, > + [DVBT_CE_EST_EVM] = {0x4, 0xc, 15, 0}, > + [DVBT_RF_AGC_VAL] = {0x3, 0x5b, 13, 0}, > + [DVBT_IF_AGC_VAL] = {0x3, 0x59, 13, 0}, > + [DVBT_DAGC_VAL] = {0x3, 0x5, 7, 0}, > + [DVBT_SFREQ_OFF] = {0x3, 0x18, 13, 0}, > + [DVBT_CFREQ_OFF] = {0x3, 0x5f, 17, 0}, > + [DVBT_POLAR_RF_AGC] = {0x0, 0xe, 1, 1}, > + [DVBT_POLAR_IF_AGC] = {0x0, 0xe, 0, 0}, > + [DVBT_AAGC_HOLD] = {0x1, 0x4, 5, 5}, > + [DVBT_EN_RF_AGC] = {0x1, 0x4, 6, 6}, > + [DVBT_EN_IF_AGC] = {0x1, 0x4, 7, 7}, > + [DVBT_IF_AGC_MIN] = {0x1, 0x8, 7, 0}, > + [DVBT_IF_AGC_MAX] = {0x1, 0x9, 7, 0}, > + [DVBT_RF_AGC_MIN] = {0x1, 0xa, 7, 0}, > + [DVBT_RF_AGC_MAX] = {0x1, 0xb, 7, 0}, > + [DVBT_IF_AGC_MAN] = {0x1, 0xc, 6, 6}, > + [DVBT_IF_AGC_MAN_VAL] = {0x1, 0xc, 13, 0}, > + [DVBT_RF_AGC_MAN] = {0x1, 0xe, 6, 6}, > + [DVBT_RF_AGC_MAN_VAL] = {0x1, 0xe, 13, 0}, > + [DVBT_DAGC_TRG_VAL] = {0x1, 0x12, 7, 0}, > + [DVBT_AGC_TARG_VAL_0] = {0x1, 0x2, 0, 0}, > + [DVBT_AGC_TARG_VAL_8_1] = {0x1, 0x3, 7, 0}, > + [DVBT_AAGC_LOOP_GAIN] = {0x1, 0xc7, 5, 1}, > + [DVBT_LOOP_GAIN2_3_0] = {0x1, 0x4, 4, 1}, > + [DVBT_LOOP_GAIN2_4] = {0x1, 0x5, 7, 7}, > + [DVBT_LOOP_GAIN3] = {0x1, 0xc8, 4, 0}, > + [DVBT_VTOP1] = {0x1, 0x6, 5, 0}, > + [DVBT_VTOP2] = {0x1, 0xc9, 5, 0}, > + [DVBT_VTOP3] = {0x1, 0xca, 5, 0}, > + [DVBT_KRF1] = {0x1, 0xcb, 7, 0}, > + [DVBT_KRF2] = {0x1, 0x7, 7, 0}, > + [DVBT_KRF3] = {0x1, 0xcd, 7, 0}, > + [DVBT_KRF4] = {0x1, 0xce, 7, 0}, > + [DVBT_EN_GI_PGA] = {0x1, 0xe5, 0, 0}, > + [DVBT_THD_LOCK_UP] = {0x1, 0xd9, 8, 0}, > + [DVBT_THD_LOCK_DW] = {0x1, 0xdb, 8, 0}, > + [DVBT_THD_UP1] = {0x1, 0xdd, 7, 0}, > + [DVBT_THD_DW1] = {0x1, 0xde, 7, 0}, > + [DVBT_INTER_CNT_LEN] = {0x1, 0xd8, 3, 0}, > + [DVBT_GI_PGA_STATE] = {0x1, 0xe6, 3, 3}, > + [DVBT_EN_AGC_PGA] = {0x1, 0xd7, 0, 0}, > + [DVBT_CKOUTPAR] = {0x1, 0x7b, 5, 5}, > + [DVBT_CKOUT_PWR] = {0x1, 0x7b, 6, 6}, > + [DVBT_SYNC_DUR] = {0x1, 0x7b, 7, 7}, > + [DVBT_ERR_DUR] = {0x1, 0x7c, 0, 0}, > + [DVBT_SYNC_LVL] = {0x1, 0x7c, 1, 1}, > + [DVBT_ERR_LVL] = {0x1, 0x7c, 2, 2}, > + [DVBT_VAL_LVL] = {0x1, 0x7c, 3, 3}, > + [DVBT_SERIAL] = {0x1, 0x7c, 4, 4}, > + [DVBT_SER_LSB] = {0x1, 0x7c, 5, 5}, > + [DVBT_CDIV_PH0] = {0x1, 0x7d, 3, 0}, > + [DVBT_CDIV_PH1] = {0x1, 0x7d, 7, 4}, > + [DVBT_MPEG_IO_OPT_2_2] = {0x0, 0x6, 7, 7}, > + [DVBT_MPEG_IO_OPT_1_0] = {0x0, 0x7, 7, 6}, > + [DVBT_CKOUTPAR_PIP] = {0x0, 0xb7, 4, 4}, > + [DVBT_CKOUT_PWR_PIP] = {0x0, 0xb7, 3, 3}, > + [DVBT_SYNC_LVL_PIP] = {0x0, 0xb7, 2, 2}, > + [DVBT_ERR_LVL_PIP] = {0x0, 0xb7, 1, 1}, > + [DVBT_VAL_LVL_PIP] = {0x0, 0xb7, 0, 0}, > + [DVBT_CKOUTPAR_PID] = {0x0, 0xb9, 4, 4}, > + [DVBT_CKOUT_PWR_PID] = {0x0, 0xb9, 3, 3}, > + [DVBT_SYNC_LVL_PID] = {0x0, 0xb9, 2, 2}, > + [DVBT_ERR_LVL_PID] = {0x0, 0xb9, 1, 1}, > + [DVBT_VAL_LVL_PID] = {0x0, 0xb9, 0, 0}, > + [DVBT_SM_PASS] = {0x1, 0x93, 11, 0}, > + [DVBT_AD7_SETTING] = {0x0, 0x11, 15, 0}, > + [DVBT_RSSI_R] = {0x3, 0x1, 6, 0}, > + [DVBT_ACI_DET_IND] = {0x3, 0x12, 0, 0}, > + [DVBT_REG_MON] = {0x0, 0xd, 1, 0}, > + [DVBT_REG_MONSEL] = {0x0, 0xd, 2, 2}, > + [DVBT_REG_GPE] = {0x0, 0xd, 7, 7}, > + [DVBT_REG_GPO] = {0x0, 0x10, 0, 0}, > + [DVBT_REG_4MSEL] = {0x0, 0x13, 0, 0}, > +}; > + > +/* write multiple hardware registers */ > +static int rtl2832_wr(struct rtl2832_priv *priv, u8 reg, u8 *val, int len) > +{ > + int ret; > + u8 buf[1+len]; > + struct i2c_msg msg[1] = { > + { > + .addr = priv->cfg.i2c_addr, > + .flags = 0, > + .len = 1+len, > + .buf = buf, > + } > + }; > + > + buf[0] = reg; > + memcpy(&buf[1], val, len); > + > + ret = i2c_transfer(priv->i2c, msg, 1); > + if (ret == 1) { > + ret = 0; > + } else { > + warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len); > + ret = -EREMOTEIO; > + } > + return ret; > +} > + > +/* read multiple hardware registers */ > +static int rtl2832_rd(struct rtl2832_priv *priv, u8 reg, u8 *val, int len) > +{ > + int ret; > + struct i2c_msg msg[2] = { > + { > + .addr = priv->cfg.i2c_addr, > + .flags = 0, > + .len = 1, > + .buf = ®, > + }, { > + .addr = priv->cfg.i2c_addr, > + .flags = I2C_M_RD, > + .len = len, > + .buf = val, > + } > + }; > + > + ret = i2c_transfer(priv->i2c, msg, 2); > + if (ret == 2) { > + ret = 0; > + } else { > + warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len); > + ret = -EREMOTEIO; > +} > +return ret; > +} > + > +/* write multiple registers */ > +static int rtl2832_wr_regs(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val, > + int len) > +{ > + int ret; > + > + > + /* switch bank if needed */ > + if (page != priv->page) { > + ret = rtl2832_wr(priv, 0x00, &page, 1); > + if (ret) > + return ret; > + > + priv->page = page; > +} > + > +return rtl2832_wr(priv, reg, val, len); > +} > + > +/* read multiple registers */ > +static int rtl2832_rd_regs(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val, > + int len) > +{ > + int ret; > + > + /* switch bank if needed */ > + if (page != priv->page) { > + ret = rtl2832_wr(priv, 0x00, &page, 1); > + if (ret) > + return ret; > + > + priv->page = page; > + } > + > + return rtl2832_rd(priv, reg, val, len); > +} > + > +#if 0 /* currently not used */ > +/* write single register */ > +static int rtl2832_wr_reg(struct rtl2832_priv *priv, u8 reg, u8 page, u8 val) > +{ > + return rtl2832_wr_regs(priv, reg, page, &val, 1); > +} > +#endif > + > +/* read single register */ > +static int rtl2832_rd_reg(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val) > +{ > + return rtl2832_rd_regs(priv, reg, page, val, 1); > +} > + > +int rtl2832_rd_demod_reg(struct rtl2832_priv *priv, int reg, u32 *val) > +{ > + int ret; > + > + u8 reg_start_addr; > + u8 msb, lsb; > + u8 page; > + u8 reading[4]; > + u32 reading_tmp; > + int i; > + > + u8 len; > + u32 mask; > + > + reg_start_addr = registers[reg].start_address; > + msb = registers[reg].msb; > + lsb = registers[reg].lsb; > + page = registers[reg].page; > + > + len = (msb >> 3) + 1; > + mask = reg_mask[msb-lsb]; > + > + > + ret = rtl2832_rd_regs(priv, reg_start_addr, page, &reading[0], len); > + if (ret) > + goto err; > + > + reading_tmp = 0; > + for (i = 0; i < len; i++) > + reading_tmp |= reading[i] << ((len-1-i)*8); > + > + *val = (reading_tmp >> lsb) & mask; > + > + return ret; > + > +err: > + return ret; > + > +} > + > +int rtl2832_wr_demod_reg(struct rtl2832_priv *priv, int reg, u32 val) > +{ > + int ret, i; > + u8 len; > + u8 reg_start_addr; > + u8 msb, lsb; > + u8 page; > + u32 mask; > + > + > + u8 reading[4]; > + u8 writing[4]; > + u32 reading_tmp; > + u32 writing_tmp; > + > + > + reg_start_addr = registers[reg].start_address; > + msb = registers[reg].msb; > + lsb = registers[reg].lsb; > + page = registers[reg].page; > + > + len = (msb >> 3) + 1; > + mask = reg_mask[msb-lsb]; > + > + > + ret = rtl2832_rd_regs(priv, reg_start_addr, page, &reading[0], len); > + if (ret) > + goto err; > + > + reading_tmp = 0; > + for (i = 0; i < len; i++) > + reading_tmp |= reading[i] << ((len-1-i)*8); > + > + writing_tmp = reading_tmp & ~(mask << lsb); > + writing_tmp |= ((val & mask) << lsb); > + > + > + for (i = 0; i < len; i++) > + writing[i] = (writing_tmp >> ((len-1-i)*8)) & 0xff; > + > + ret = rtl2832_wr_regs(priv, reg_start_addr, page, &writing[0], len); > + if (ret) > + goto err; > + > + return ret; > + > +err: > + return ret; > + > +} > + > + > +static int rtl2832_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) > +{ > + int ret; > + struct rtl2832_priv *priv = fe->demodulator_priv; > + > + dbg("%s: enable=%d", __func__, enable); > + > + /* gate already open or close */ > + if (priv->i2c_gate_state == enable) > + return 0; > + > + ret = rtl2832_wr_demod_reg(priv, DVBT_IIC_REPEAT, (enable ? 0x1 : 0x0)); > + > + if (ret) > + goto err; > + > + priv->i2c_gate_state = enable; > + > + return ret; > +err: > + dbg("%s: failed=%d", __func__, ret); > + return ret; > +} > + > + > + > +static int rtl2832_init(struct dvb_frontend *fe) > +{ > + struct rtl2832_priv *priv = fe->demodulator_priv; > + int i, ret; > + > + u8 en_bbin; > + u64 pset_iffreq; > + > + /* initialization values for the demodulator registers */ > + static rtl2832_reg_value rtl2832_initial_regs_1[] = { > + {DVBT_AD_EN_REG, 0x1}, > + {DVBT_AD_EN_REG1, 0x1}, > + {DVBT_RSD_BER_FAIL_VAL, 0x2800}, > + {DVBT_MGD_THD0, 0x10}, > + {DVBT_MGD_THD1, 0x20}, > + {DVBT_MGD_THD2, 0x20}, > + {DVBT_MGD_THD3, 0x40}, > + {DVBT_MGD_THD4, 0x22}, > + {DVBT_MGD_THD5, 0x32}, > + {DVBT_MGD_THD6, 0x37}, > + {DVBT_MGD_THD7, 0x39}, > + {DVBT_EN_BK_TRK, 0x0}, > + {DVBT_EN_CACQ_NOTCH, 0x0}, > + {DVBT_AD_AV_REF, 0x2a}, > + {DVBT_REG_PI, 0x6}, > + {DVBT_PIP_ON, 0x0}, > + {DVBT_CDIV_PH0, 0x8}, > + {DVBT_CDIV_PH1, 0x8}, > + {DVBT_SCALE1_B92, 0x4}, > + {DVBT_SCALE1_B93, 0xb0}, > + {DVBT_SCALE1_BA7, 0x78}, > + {DVBT_SCALE1_BA9, 0x28}, > + {DVBT_SCALE1_BAA, 0x59}, > + {DVBT_SCALE1_BAB, 0x83}, > + {DVBT_SCALE1_BAC, 0xd4}, > + {DVBT_SCALE1_BB0, 0x65}, > + {DVBT_SCALE1_BB1, 0x43}, > + {DVBT_KB_P1, 0x1}, > + {DVBT_KB_P2, 0x4}, > + {DVBT_KB_P3, 0x7}, > + {DVBT_K1_CR_STEP12, 0xa}, > + {DVBT_REG_GPE, 0x1}, > + {DVBT_SERIAL, 0x0}, > + {DVBT_CDIV_PH0, 0x9}, > + {DVBT_CDIV_PH1, 0x9}, > + {DVBT_MPEG_IO_OPT_2_2, 0x0}, > + {DVBT_MPEG_IO_OPT_1_0, 0x0}, > + {DVBT_TRK_KS_P2, 0x4}, > + {DVBT_TRK_KS_I2, 0x7}, > + {DVBT_TR_THD_SET2, 0x6}, > + {DVBT_TRK_KC_I2, 0x5}, > + {DVBT_CR_THD_SET2, 0x1}, > + > + > + }; > + > + static rtl2832_reg_value rtl2832_initial_regs_2[] = { > + {DVBT_SPEC_INV, 0x0}, > + {DVBT_DAGC_TRG_VAL, 0x5a}, > + {DVBT_AGC_TARG_VAL_0, 0x0}, > + {DVBT_AGC_TARG_VAL_8_1, 0x5a}, > + {DVBT_AAGC_LOOP_GAIN, 0x16}, > + {DVBT_LOOP_GAIN2_3_0, 0x6}, > + {DVBT_LOOP_GAIN2_4, 0x1}, > + {DVBT_LOOP_GAIN3, 0x16}, > + {DVBT_VTOP1, 0x35}, > + {DVBT_VTOP2, 0x21}, > + {DVBT_VTOP3, 0x21}, > + {DVBT_KRF1, 0x0}, > + {DVBT_KRF2, 0x40}, > + {DVBT_KRF3, 0x10}, > + {DVBT_KRF4, 0x10}, > + {DVBT_IF_AGC_MIN, 0x80}, > + {DVBT_IF_AGC_MAX, 0x7f}, > + {DVBT_RF_AGC_MIN, 0x80}, > + {DVBT_RF_AGC_MAX, 0x7f}, > + {DVBT_POLAR_RF_AGC, 0x0}, > + {DVBT_POLAR_IF_AGC, 0x0}, > + {DVBT_AD7_SETTING, 0xe9bf}, > + {DVBT_EN_GI_PGA, 0x0}, > + {DVBT_THD_LOCK_UP, 0x0}, > + {DVBT_THD_LOCK_DW, 0x0}, > + {DVBT_THD_UP1, 0x11}, > + {DVBT_THD_DW1, 0xef}, > + {DVBT_INTER_CNT_LEN, 0xc}, > + {DVBT_GI_PGA_STATE, 0x0}, > + {DVBT_EN_AGC_PGA, 0x1}, > + {DVBT_IF_AGC_MAN, 0x0}, > + }; > + > + > + dbg("%s", __func__); > + > + en_bbin = (priv->cfg.if_dvbt == 0 ? 0x1 : 0x0); > + > + /* > + * PSET_IFFREQ = - floor((IfFreqHz % CrystalFreqHz) * pow(2, 22) > + * / CrystalFreqHz) > + */ > + pset_iffreq = priv->cfg.if_dvbt % priv->cfg.xtal; > + pset_iffreq *= 0x400000; > + pset_iffreq = div_u64(pset_iffreq, priv->cfg.xtal); > + pset_iffreq = pset_iffreq & 0x3fffff; > + > + > + > + for (i = 0; i < 42; i++) { > + ret = rtl2832_wr_demod_reg(priv, rtl2832_initial_regs_1[i].reg, > + rtl2832_initial_regs_1[i].value); > + if (ret) > + goto err; > + } > + > + /* if frequency settings */ > + ret = rtl2832_wr_demod_reg(priv, DVBT_EN_BBIN, en_bbin); > + if (ret) > + goto err; > + > + ret = rtl2832_wr_demod_reg(priv, DVBT_PSET_IFFREQ, pset_iffreq); > + if (ret) > + goto err; > + > + for (i = 0; i < 31; i++) { > + ret = rtl2832_wr_demod_reg(priv, rtl2832_initial_regs_2[i].reg, > + rtl2832_initial_regs_2[i].value); > + if (ret) > + goto err; > + } > + > + priv->sleeping = false; > + > + return ret; > + > +err: > + return ret; > +} > + > +static int rtl2832_sleep(struct dvb_frontend *fe) > +{ > + struct rtl2832_priv *priv = fe->demodulator_priv; > + > + dbg("%s", __func__); > + priv->sleeping = true; > + return 0; > +} > + > +int rtl2832_get_tune_settings(struct dvb_frontend *fe, > + struct dvb_frontend_tune_settings *s) > +{ > + dbg("%s", __func__); > + s->min_delay_ms = 1000; > + s->step_size = fe->ops.info.frequency_stepsize * 2; > + s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; > + return 0; > +} > + > +static int rtl2832_set_frontend(struct dvb_frontend *fe) > +{ > + struct rtl2832_priv *priv = fe->demodulator_priv; > + struct dtv_frontend_properties *c = &fe->dtv_property_cache; > + int ret, i, j; > + u64 bw_mode, num, num2; > + u32 resamp_ratio, cfreq_off_ratio; > + > + > + static u8 bw_params[3][32] = { > + /* 6 MHz bandwidth */ > + { > + 0xf5, 0xff, 0x15, 0x38, 0x5d, 0x6d, 0x52, 0x07, 0xfa, 0x2f, > + 0x53, 0xf5, 0x3f, 0xca, 0x0b, 0x91, 0xea, 0x30, 0x63, 0xb2, > + 0x13, 0xda, 0x0b, 0xc4, 0x18, 0x7e, 0x16, 0x66, 0x08, 0x67, > + 0x19, 0xe0, > + }, > + > + /* 7 MHz bandwidth */ > + { > + 0xe7, 0xcc, 0xb5, 0xba, 0xe8, 0x2f, 0x67, 0x61, 0x00, 0xaf, > + 0x86, 0xf2, 0xbf, 0x59, 0x04, 0x11, 0xb6, 0x33, 0xa4, 0x30, > + 0x15, 0x10, 0x0a, 0x42, 0x18, 0xf8, 0x17, 0xd9, 0x07, 0x22, > + 0x19, 0x10, > + }, > + > + /* 8 MHz bandwidth */ > + { > + 0x09, 0xf6, 0xd2, 0xa7, 0x9a, 0xc9, 0x27, 0x77, 0x06, 0xbf, > + 0xec, 0xf4, 0x4f, 0x0b, 0xfc, 0x01, 0x63, 0x35, 0x54, 0xa7, > + 0x16, 0x66, 0x08, 0xb4, 0x19, 0x6e, 0x19, 0x65, 0x05, 0xc8, > + 0x19, 0xe0, > + }, > + }; > + > + > + dbg("%s: frequency=%d bandwidth_hz=%d inversion=%d", __func__, > + c->frequency, c->bandwidth_hz, c->inversion); > + > + > + /* program tuner */ > + if (fe->ops.tuner_ops.set_params) > + fe->ops.tuner_ops.set_params(fe); > + > + > + switch (c->bandwidth_hz) { > + case 6000000: > + i = 0; > + bw_mode = 48000000; > + break; > + case 7000000: > + i = 1; > + bw_mode = 56000000; > + break; > + case 8000000: > + i = 2; > + bw_mode = 64000000; > + break; > + default: > + dbg("invalid bandwidth"); > + return -EINVAL; > + } > + > + for (j = 0; j < 32; j++) { > + ret = rtl2832_wr_regs(priv, 0x1c+j, 1, &bw_params[i][j], 1); > + if (ret) > + goto err; > + } > + > + /* calculate and set resample ratio > + * RSAMP_RATIO = floor(CrystalFreqHz * 7 * pow(2, 22) > + * / ConstWithBandwidthMode) > + */ > + num = priv->cfg.xtal * 7; > + num *= 0x400000; > + num = div_u64(num, bw_mode); > + resamp_ratio = num & 0x3ffffff; > + ret = rtl2832_wr_demod_reg(priv, DVBT_RSAMP_RATIO, resamp_ratio); > + if (ret) > + goto err; > + > + /* calculate and set cfreq off ratio > + * CFREQ_OFF_RATIO = - floor(ConstWithBandwidthMode * pow(2, 20) > + * / (CrystalFreqHz * 7)) > + */ > + num = bw_mode << 20; > + num2 = priv->cfg.xtal * 7; > + num = div_u64(num, num2); > + num = -num; > + cfreq_off_ratio = num & 0xfffff; > + ret = rtl2832_wr_demod_reg(priv, DVBT_CFREQ_OFF_RATIO, cfreq_off_ratio); > + if (ret) > + goto err; > + > + > + /* soft reset */ > + ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x1); > + if (ret) > + goto err; > + > + ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x0); > + if (ret) > + goto err; > + > + return ret; > +err: > + info("%s: failed=%d", __func__, ret); > + return ret; > +} > + > +static int rtl2832_read_status(struct dvb_frontend *fe, fe_status_t *status) > +{ > + struct rtl2832_priv *priv = fe->demodulator_priv; > + int ret; > + u32 tmp; > + *status = 0; > + > + > + dbg("%s", __func__); > + if (priv->sleeping) > + return 0; > + > + ret = rtl2832_rd_demod_reg(priv, DVBT_FSM_STAGE, &tmp); > + if (ret) > + goto err; > + > + if (tmp == 11) { > + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | > + FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; > + } > + /* TODO find out if this is also true for rtl2832? */ > + /*else if (tmp == 10) { > + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | > + FE_HAS_VITERBI; > + }*/ > + > + return ret; > +err: > + info("%s: failed=%d", __func__, ret); > + return ret; > +} > + > + > +#define RTL2832_CE_EST_EVM_MAX_VALUE 65535 > +#define RTL2832_SNR_FRAC_BIT_NUM 10 > +#define RTL2832_SNR_DB_DEN 3402 > + > +static int rtl2832_read_snr(struct dvb_frontend *fe, u16 *snr) > +{ > + struct rtl2832_priv *priv = fe->demodulator_priv; > + int ret; > + u64 num; > + u32 ce_est_evm, fsm_stage, constellation, hierarchy; > + > + /* Calculated by: 10 * log2(Norm * pow(2, 11)) * pow(2, 10) */ > + static const long SnrDbNum[3][4] = { > + {122880, 122880, 122880, 122880, }, > + {146657, 146657, 156897, 171013, }, > + {167857, 167857, 173127, 181810, }, > + }; > + > + static const int snrMaxDb[3] = { 23, 26, 29, }; > + > + dbg("%s", __func__); > + > + /* get FSM Stage */ > + ret = rtl2832_rd_demod_reg(priv, DVBT_FSM_STAGE, &fsm_stage); > + if (ret) > + goto err; > + > + if (fsm_stage < 10) { > + ce_est_evm = RTL2832_CE_EST_EVM_MAX_VALUE; > + } else { > + ret = rtl2832_rd_demod_reg(priv, DVBT_CE_EST_EVM, &ce_est_evm); > + if (ret) > + goto err; > + } > + > + /* get constellation */ > + ret = rtl2832_rd_demod_reg(priv, DVBT_RX_CONSTEL, &constellation); > + if (ret) > + goto err; > + if (constellation > 2) > + goto err; > + > + /* get hierarchy */ > + ret = rtl2832_rd_demod_reg(priv, DVBT_RX_HIER, &hierarchy); > + if (ret) > + goto err; > + if (hierarchy > 3) > + goto err; > + > + > + /* > + SNR dB formula > + Original formula: SNR_dB = 10 * log10(Norm * pow(2, 11) / CeEstEvm) > + Adjusted formula: SNR_dB = (SNR_DB_NUM_CONST - 10 * log2(CeEstEvm) * > + pow(2, 10)) / SNR_DB_DEN > + SNR_DB_NUM_CONST = 10 * log2(Norm * pow(2, 11)) * > + pow(2, 10) > + SNR_DB_DEN = log2(10) * pow(2, 10) = 3402 = 0xd4a > + Norm: > + None Alpha=1 Alpha=2 Alpha=4 > + 4-QAM 2 2 2 2 > + 16-QAM 10 10 20 52 > + 64-QAM 42 42 60 108 > + */ > + > + /* intlog2 returns log2(x) << 24 */ > + num = intlog2(ce_est_evm)>>14; > + num = SnrDbNum[constellation][hierarchy] - 10 * num; > + > + num = div_u64(num, RTL2832_SNR_DB_DEN); > + num *= 0xffff; > + num = div_u64(num, snrMaxDb[constellation]); > + > + if (num > 0xffff) > + *snr = 0xffff; > + else if (num < 0) > + *snr = 0; > + else > + *snr = 0xffff & num; > + > + return ret; > + > +err: > + info("%s: failed=%d", __func__, ret); > + return ret; > +} > + > +static int rtl2832_read_ber(struct dvb_frontend *fe, u32 *ber) > +{ > + struct rtl2832_priv *priv = fe->demodulator_priv; > + int ret; > + u32 tmp; > + > + dbg("%s", __func__); > + > + /* get BER */ > + ret = rtl2832_rd_demod_reg(priv, DVBT_RSD_BER_EST, &tmp); > + if (ret) > + goto err; > + > + *ber = tmp; > + return ret; > + > +err: > + info("%s: failed=%d", __func__, ret); > + *ber = 19616; > + return ret; > +} > + > +static int rtl2832_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) > +{ > + struct rtl2832_priv *priv = fe->demodulator_priv; > + int ret; > + u32 tmp; > + u16 num; > + > + dbg("%s", __func__); > + > + > + /* get FSM Stage */ > + ret = rtl2832_rd_demod_reg(priv, DVBT_FSM_STAGE, &tmp); > + if (ret) > + goto err; > + > + /* if signal is not locked quality is zero */ > + if (tmp < 10) { > + *ucblocks = 0; > + return 0; > + } > + > + /* get BER */ > + ret = rtl2832_rd_demod_reg(priv, DVBT_RSD_BER_EST, &tmp); > + if (ret) > + goto err; > + > + /* > + Determine signal quality according to RSD_BER_EST. > + Note: Map RSD_BER_EST value 8192 ~ 128 to 10 ~ 100 > + Original formula: SignalQuality = 205 - 15 * log2(RSD_BER_EST) > + Adjusted formula: SignalQuality = ((205 << 5) - 15 * > + (log2(RSD_BER_EST) << 5)) >> 5 > + If RSD_BER_EST > 8192, signal quality is 10. > + If RSD_BER_EST < 128, signal quality is 100. > + */ > + > + if (tmp > 8192) > + *ucblocks = 10; > + else if (tmp < 128) > + *ucblocks = 100; > + else { > + num = intlog2(tmp) >> 19; > + *ucblocks = ((205 << 5) - 15 * num) >> 5; > + } > + > + return 0; > + > +err: > + info("%s: failed=%d", __func__, ret); > + *ucblocks = 0; > + return ret; > +} > + > + > +static int rtl2832_read_signal_strength(struct dvb_frontend *fe, u16 *strength) > +{ > + struct rtl2832_priv *priv = fe->demodulator_priv; > + int ret, if_agc; > + u32 fsm_stage, if_agc_raw; > + > + dbg("%s", __func__); > + > + ret = rtl2832_rd_demod_reg(priv, DVBT_FSM_STAGE, &fsm_stage); > + if (ret) > + goto err; > + > + if (fsm_stage < 10) > + *strength = 0; > + else { > + /* if_agc is read as a 10bit binary */ > + ret = rtl2832_rd_demod_reg(priv, DVBT_IF_AGC_VAL, &if_agc_raw); > + if (ret) > + goto err; > + > + if (if_agc_raw < (1 << 9)) > + if_agc = if_agc_raw; > + else > + if_agc = -(~(if_agc_raw-1) & 0x1ff); > + > + *strength = 55 - if_agc / 182; > + *strength |= *strength << 8; > + } > + return 0; > +err: > + info("%s: failed=%d", __func__, ret); > + return ret; > +} > + > +static struct dvb_frontend_ops rtl2832_ops; > + > +static void rtl2832_release(struct dvb_frontend *fe) > +{ > + struct rtl2832_priv *priv = fe->demodulator_priv; > + > + dbg("%s", __func__); > + kfree(priv); > +} > + > +struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg, > + struct i2c_adapter *i2c) > +{ > + struct rtl2832_priv *priv = NULL; > + int ret = 0; > + u8 tmp; > + > + dbg("%s", __func__); > + > + /* allocate memory for the internal state */ > + priv = kzalloc(sizeof(struct rtl2832_priv), GFP_KERNEL); > + if (priv == NULL) > + goto err; > + > + /* setup the priv */ > + priv->i2c = i2c; > + priv->tuner = cfg->tuner; > + memcpy(&priv->cfg, cfg, sizeof(struct rtl2832_config)); > + > + /* check if the demod is there */ > + ret = rtl2832_rd_reg(priv, 0x00, 0x0, &tmp); > + if (ret) > + goto err; > + > + /* create dvb_frontend */ > + memcpy(&priv->fe.ops, &rtl2832_ops, sizeof(struct dvb_frontend_ops)); > + priv->fe.demodulator_priv = priv; > + > + /* TODO implement sleep mode depending on RC */ > + priv->sleeping = true; > + > + return &priv->fe; > +err: > + dbg("%s: failed=%d", __func__, ret); > + kfree(priv); > + return NULL; > +} > +EXPORT_SYMBOL(rtl2832_attach); > + > +static struct dvb_frontend_ops rtl2832_ops = { > + .delsys = { SYS_DVBT }, > + .info = { > + .name = "Realtek RTL2832 (DVB-T)", > + .type = FE_OFDM, > + .frequency_min = 50000000, > + .frequency_max = 862000000, > + .frequency_stepsize = 166667, > + .caps = FE_CAN_FEC_1_2 | > + FE_CAN_FEC_2_3 | > + FE_CAN_FEC_3_4 | > + FE_CAN_FEC_5_6 | > + FE_CAN_FEC_7_8 | > + FE_CAN_FEC_AUTO | > + FE_CAN_QPSK | > + FE_CAN_QAM_16 | > + FE_CAN_QAM_64 | > + FE_CAN_QAM_AUTO | > + FE_CAN_TRANSMISSION_MODE_AUTO | > + FE_CAN_GUARD_INTERVAL_AUTO | > + FE_CAN_HIERARCHY_AUTO | > + FE_CAN_RECOVER | > + FE_CAN_MUTE_TS > + }, > + > + .release = rtl2832_release, > + > + .init = rtl2832_init, > + .sleep = rtl2832_sleep, > + > + .get_tune_settings = rtl2832_get_tune_settings, > + > + .set_frontend = rtl2832_set_frontend, > + > + .read_status = rtl2832_read_status, > + .read_snr = rtl2832_read_snr, > + .read_ber = rtl2832_read_ber, > + .read_ucblocks = rtl2832_read_ucblocks, > + .read_signal_strength = rtl2832_read_signal_strength, > + .i2c_gate_ctrl = rtl2832_i2c_gate_ctrl, > +}; > + > +MODULE_AUTHOR("Thomas Mair <mair.thomas86@gmail.com>"); > +MODULE_DESCRIPTION("Realtek RTL2832 DVB-T demodulator driver"); > +MODULE_LICENSE("GPL"); > +MODULE_VERSION("0.3"); > diff --git a/drivers/media/dvb/frontends/rtl2832.h b/drivers/media/dvb/frontends/rtl2832.h > new file mode 100644 > index 0000000..6918010 > --- /dev/null > +++ b/drivers/media/dvb/frontends/rtl2832.h > @@ -0,0 +1,81 @@ > +/* > + * Realtek RTL2832 DVB-T demodulator driver > + * > + * Copyright (C) 2012 Thomas Mair <thomas.mair86@gmail.com> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License along > + * with this program; if not, write to the Free Software Foundation, Inc., > + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. > + */ > + > +#ifndef RTL2832_H > +#define RTL2832_H > + > +#include <linux/dvb/frontend.h> > + > +struct rtl2832_config { > + /* > + * Demodulator I2C address. > + */ > + u8 i2c_addr; > + > + /* > + * Xtal frequency. > + * Hz > + * 4000000, 16000000, 25000000, 28800000 > + */ > + u32 xtal; > + > + /* > + * IFs for all used modes. > + * Hz > + * 4570000, 4571429, 36000000, 36125000, 36166667, 44000000 > + */ > + u32 if_dvbt; > + > + /* > + */ > + u8 tuner; > +}; > + > + > +#if defined(CONFIG_DVB_RTL2832) || \ > + (defined(CONFIG_DVB_RTL2832_MODULE) && defined(MODULE)) > +extern struct dvb_frontend *rtl2832_attach( > + const struct rtl2832_config *cfg, > + struct i2c_adapter *i2c > +); > + > +extern struct i2c_adapter *rtl2832_get_tuner_i2c_adapter( > + struct dvb_frontend *fe > +); > +#else > +static inline struct dvb_frontend *rtl2832_attach( > + const struct rtl2832_config *config, > + struct i2c_adapter *i2c > +) > +{ > + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); > + return NULL; > +} > + > +static inline struct i2c_adapter *rtl2832_get_tuner_i2c_adapter( > + struct dvb_frontend *fe > +) > +{ > + return NULL; > +} > +#endif > + > + > +#endif /* RTL2832_H */ > diff --git a/drivers/media/dvb/frontends/rtl2832_priv.h b/drivers/media/dvb/frontends/rtl2832_priv.h > new file mode 100644 > index 0000000..0f5df2f > --- /dev/null > +++ b/drivers/media/dvb/frontends/rtl2832_priv.h > @@ -0,0 +1,260 @@ > +/* > + * Realtek RTL2832 DVB-T demodulator driver > + * > + * Copyright (C) 2012 Thomas Mair <thomas.mair86@gmail.com> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License along > + * with this program; if not, write to the Free Software Foundation, Inc., > + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. > + */ > + > +#ifndef RTL2832_PRIV_H > +#define RTL2832_PRIV_H > + > +#include "dvb_frontend.h" > +#include "rtl2832.h" > + > +#define LOG_PREFIX "rtl2832" > + > +#undef dbg > +#define dbg(f, arg...) \ > + if (rtl2832_debug) \ > + printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) > +#undef err > +#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) > +#undef info > +#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) > +#undef warn > +#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) > + > +struct rtl2832_priv { > + struct i2c_adapter *i2c; > + struct dvb_frontend fe; > + struct rtl2832_config cfg; > + > + bool i2c_gate_state; > + bool sleeping; > + > + u8 tuner; > + u8 page; /* active register page */ > +}; > + > +typedef struct { > + u8 page; > + u8 start_address; > + u8 msb; > + u8 lsb; > +} > +rtl2832_reg_entry; > + > +typedef struct { > + int reg; > + u32 value; > +} > +rtl2832_reg_value; > + > + > +/* Demod register bit names */ > +enum DVBT_REG_BIT_NAME { > + DVBT_SOFT_RST, > + DVBT_IIC_REPEAT, > + DVBT_TR_WAIT_MIN_8K, > + DVBT_RSD_BER_FAIL_VAL, > + DVBT_EN_BK_TRK, > + DVBT_REG_PI, > + DVBT_REG_PFREQ_1_0, > + DVBT_PD_DA8, > + DVBT_LOCK_TH, > + DVBT_BER_PASS_SCAL, > + DVBT_CE_FFSM_BYPASS, > + DVBT_ALPHAIIR_N, > + DVBT_ALPHAIIR_DIF, > + DVBT_EN_TRK_SPAN, > + DVBT_LOCK_TH_LEN, > + DVBT_CCI_THRE, > + DVBT_CCI_MON_SCAL, > + DVBT_CCI_M0, > + DVBT_CCI_M1, > + DVBT_CCI_M2, > + DVBT_CCI_M3, > + DVBT_SPEC_INIT_0, > + DVBT_SPEC_INIT_1, > + DVBT_SPEC_INIT_2, > + DVBT_AD_EN_REG, > + DVBT_AD_EN_REG1, > + DVBT_EN_BBIN, > + DVBT_MGD_THD0, > + DVBT_MGD_THD1, > + DVBT_MGD_THD2, > + DVBT_MGD_THD3, > + DVBT_MGD_THD4, > + DVBT_MGD_THD5, > + DVBT_MGD_THD6, > + DVBT_MGD_THD7, > + DVBT_EN_CACQ_NOTCH, > + DVBT_AD_AV_REF, > + DVBT_PIP_ON, > + DVBT_SCALE1_B92, > + DVBT_SCALE1_B93, > + DVBT_SCALE1_BA7, > + DVBT_SCALE1_BA9, > + DVBT_SCALE1_BAA, > + DVBT_SCALE1_BAB, > + DVBT_SCALE1_BAC, > + DVBT_SCALE1_BB0, > + DVBT_SCALE1_BB1, > + DVBT_KB_P1, > + DVBT_KB_P2, > + DVBT_KB_P3, > + DVBT_OPT_ADC_IQ, > + DVBT_AD_AVI, > + DVBT_AD_AVQ, > + DVBT_K1_CR_STEP12, > + DVBT_TRK_KS_P2, > + DVBT_TRK_KS_I2, > + DVBT_TR_THD_SET2, > + DVBT_TRK_KC_P2, > + DVBT_TRK_KC_I2, > + DVBT_CR_THD_SET2, > + DVBT_PSET_IFFREQ, > + DVBT_SPEC_INV, > + DVBT_BW_INDEX, > + DVBT_RSAMP_RATIO, > + DVBT_CFREQ_OFF_RATIO, > + DVBT_FSM_STAGE, > + DVBT_RX_CONSTEL, > + DVBT_RX_HIER, > + DVBT_RX_C_RATE_LP, > + DVBT_RX_C_RATE_HP, > + DVBT_GI_IDX, > + DVBT_FFT_MODE_IDX, > + DVBT_RSD_BER_EST, > + DVBT_CE_EST_EVM, > + DVBT_RF_AGC_VAL, > + DVBT_IF_AGC_VAL, > + DVBT_DAGC_VAL, > + DVBT_SFREQ_OFF, > + DVBT_CFREQ_OFF, > + DVBT_POLAR_RF_AGC, > + DVBT_POLAR_IF_AGC, > + DVBT_AAGC_HOLD, > + DVBT_EN_RF_AGC, > + DVBT_EN_IF_AGC, > + DVBT_IF_AGC_MIN, > + DVBT_IF_AGC_MAX, > + DVBT_RF_AGC_MIN, > + DVBT_RF_AGC_MAX, > + DVBT_IF_AGC_MAN, > + DVBT_IF_AGC_MAN_VAL, > + DVBT_RF_AGC_MAN, > + DVBT_RF_AGC_MAN_VAL, > + DVBT_DAGC_TRG_VAL, > + DVBT_AGC_TARG_VAL, > + DVBT_LOOP_GAIN_3_0, > + DVBT_LOOP_GAIN_4, > + DVBT_VTOP, > + DVBT_KRF, > + DVBT_AGC_TARG_VAL_0, > + DVBT_AGC_TARG_VAL_8_1, > + DVBT_AAGC_LOOP_GAIN, > + DVBT_LOOP_GAIN2_3_0, > + DVBT_LOOP_GAIN2_4, > + DVBT_LOOP_GAIN3, > + DVBT_VTOP1, > + DVBT_VTOP2, > + DVBT_VTOP3, > + DVBT_KRF1, > + DVBT_KRF2, > + DVBT_KRF3, > + DVBT_KRF4, > + DVBT_EN_GI_PGA, > + DVBT_THD_LOCK_UP, > + DVBT_THD_LOCK_DW, > + DVBT_THD_UP1, > + DVBT_THD_DW1, > + DVBT_INTER_CNT_LEN, > + DVBT_GI_PGA_STATE, > + DVBT_EN_AGC_PGA, > + DVBT_CKOUTPAR, > + DVBT_CKOUT_PWR, > + DVBT_SYNC_DUR, > + DVBT_ERR_DUR, > + DVBT_SYNC_LVL, > + DVBT_ERR_LVL, > + DVBT_VAL_LVL, > + DVBT_SERIAL, > + DVBT_SER_LSB, > + DVBT_CDIV_PH0, > + DVBT_CDIV_PH1, > + DVBT_MPEG_IO_OPT_2_2, > + DVBT_MPEG_IO_OPT_1_0, > + DVBT_CKOUTPAR_PIP, > + DVBT_CKOUT_PWR_PIP, > + DVBT_SYNC_LVL_PIP, > + DVBT_ERR_LVL_PIP, > + DVBT_VAL_LVL_PIP, > + DVBT_CKOUTPAR_PID, > + DVBT_CKOUT_PWR_PID, > + DVBT_SYNC_LVL_PID, > + DVBT_ERR_LVL_PID, > + DVBT_VAL_LVL_PID, > + DVBT_SM_PASS, > + DVBT_UPDATE_REG_2, > + DVBT_BTHD_P3, > + DVBT_BTHD_D3, > + DVBT_FUNC4_REG0, > + DVBT_FUNC4_REG1, > + DVBT_FUNC4_REG2, > + DVBT_FUNC4_REG3, > + DVBT_FUNC4_REG4, > + DVBT_FUNC4_REG5, > + DVBT_FUNC4_REG6, > + DVBT_FUNC4_REG7, > + DVBT_FUNC4_REG8, > + DVBT_FUNC4_REG9, > + DVBT_FUNC4_REG10, > + DVBT_FUNC5_REG0, > + DVBT_FUNC5_REG1, > + DVBT_FUNC5_REG2, > + DVBT_FUNC5_REG3, > + DVBT_FUNC5_REG4, > + DVBT_FUNC5_REG5, > + DVBT_FUNC5_REG6, > + DVBT_FUNC5_REG7, > + DVBT_FUNC5_REG8, > + DVBT_FUNC5_REG9, > + DVBT_FUNC5_REG10, > + DVBT_FUNC5_REG11, > + DVBT_FUNC5_REG12, > + DVBT_FUNC5_REG13, > + DVBT_FUNC5_REG14, > + DVBT_FUNC5_REG15, > + DVBT_FUNC5_REG16, > + DVBT_FUNC5_REG17, > + DVBT_FUNC5_REG18, > + DVBT_AD7_SETTING, > + DVBT_RSSI_R, > + DVBT_ACI_DET_IND, > + DVBT_REG_MON, > + DVBT_REG_MONSEL, > + DVBT_REG_GPE, > + DVBT_REG_GPO, > + DVBT_REG_4MSEL, > + DVBT_TEST_REG_1, > + DVBT_TEST_REG_2, > + DVBT_TEST_REG_3, > + DVBT_TEST_REG_4, > + DVBT_REG_BIT_NAME_ITEM_TERMINATOR, > +}; > + > +#endif /* RTL2832_PRIV_H */ plus ;) regards, poma [-- Attachment #2: rtl2832-ver-0.3-Makefile.diff --] [-- Type: text/x-patch, Size: 470 bytes --] --- linux/drivers/media/dvb/frontends/Makefile.orig 2012-05-12 23:57:06.323042617 +0200 +++ linux/drivers/media/dvb/frontends/Makefile 2012-05-12 23:58:08.850299229 +0200 @@ -98,7 +98,7 @@ obj-$(CONFIG_DVB_A8293) += a8293.o obj-$(CONFIG_DVB_TDA10071) += tda10071.o obj-$(CONFIG_DVB_RTL2830) += rtl2830.o -obj-$(CONFIG_DVB_RTL2832) = rtl2832.o +obj-$(CONFIG_DVB_RTL2832) += rtl2832.o obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o obj-$(CONFIG_DVB_AF9033) += af9033.o ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/5] rtl2832 ver 0.3: suport for RTL2832 demodulator revised version 2012-05-12 18:08 ` [PATCH 1/5] rtl2832 ver 0.3: suport for RTL2832 demodulator revised version Thomas Mair 2012-05-12 22:07 ` poma @ 2012-05-13 18:53 ` Antti Palosaari 2012-05-13 20:56 ` Thomas Mair 2012-05-14 1:37 ` Antti Palosaari 2 siblings, 1 reply; 16+ messages in thread From: Antti Palosaari @ 2012-05-13 18:53 UTC (permalink / raw) To: Thomas Mair; +Cc: linux-media On 12.05.2012 21:08, Thomas Mair wrote: > Changes compared to version 0.2: > - removed reading of signal strength for tuners FC0012,FC0013 (is now supported by fc0012,fc0013 driver) > - moved definition of register names to rtl2832_priv.h > - cleaned up demod private structure > - replaced rtl2832_log2 function with intlog2 from dvb_math > > Signed-off-by: Thomas Mair<thomas.mair86@googlemail.com> Testing shows UCB counter is totally broken. It does that all the time, 64 => <some number> => 64 status SCVYL | signal 2b2b | snr b08c | ber 00000024 | unc 00000064 | FE_HAS_LOCK status SCVYL | signal 2b2b | snr a7b8 | ber 0000007d | unc 0000005e | FE_HAS_LOCK status SCVYL | signal 2b2b | snr b08c | ber 0000002c | unc 00000064 | FE_HAS_LOCK Also other small issue. You have added new line to the log writings provided by DVB USB. DVB USB log writing has already new line! That is 2nd time I point out line errors. Did you use some special set-up during the development ? May 13 21:33:06 localhost kernel: [204738.354039] rtl28xxu: rtl2832u_frontend_attach: FC0012 tuner found May 13 21:33:06 localhost kernel: [204738.354040] May 13 21:33:06 localhost kernel: [204738.361304] DVB: registering adapter 0 frontend 0 (Realtek RTL2832 (DVB-T))... I quickly looked patches through and those looked very good. I will try to review those tonight. And here is whole set (tuner+rtl2832u) if someone else would like to test: http://git.linuxtv.org/anttip/media_tree.git/shortlog/refs/heads/rtl2832u regards Antti -- http://palosaari.fi/ ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/5] rtl2832 ver 0.3: suport for RTL2832 demodulator revised version 2012-05-13 18:53 ` Antti Palosaari @ 2012-05-13 20:56 ` Thomas Mair 0 siblings, 0 replies; 16+ messages in thread From: Thomas Mair @ 2012-05-13 20:56 UTC (permalink / raw) To: Antti Palosaari; +Cc: linux-media On 13.05.2012 20:53, Antti Palosaari wrote: > On 12.05.2012 21:08, Thomas Mair wrote: >> Changes compared to version 0.2: >> - removed reading of signal strength for tuners FC0012,FC0013 (is now supported by fc0012,fc0013 driver) >> - moved definition of register names to rtl2832_priv.h >> - cleaned up demod private structure >> - replaced rtl2832_log2 function with intlog2 from dvb_math >> >> Signed-off-by: Thomas Mair<thomas.mair86@googlemail.com> > > Testing shows UCB counter is totally broken. It does that all the time, 64 => <some number> => 64 > > status SCVYL | signal 2b2b | snr b08c | ber 00000024 | unc 00000064 | FE_HAS_LOCK > status SCVYL | signal 2b2b | snr a7b8 | ber 0000007d | unc 0000005e | FE_HAS_LOCK > status SCVYL | signal 2b2b | snr b08c | ber 0000002c | unc 00000064 | FE_HAS_LOCK > Ok. I will have a look into that. When I test it the count is always 64. status SCVYL | signal 4545 | snr ffff | ber 00000000 | unc 00000064 | FE_HAS_LOCK status SCVYL | signal 4545 | snr ffff | ber 00000000 | unc 00000064 | FE_HAS_LOCK status SCVYL | signal 4545 | snr ffff | ber 00000000 | unc 00000064 | FE_HAS_LOCK > Also other small issue. You have added new line to the log writings provided by DVB USB. DVB USB log writing has already new line! That is 2nd time I point out line errors. Did you use some special set-up during the development ? > > May 13 21:33:06 localhost kernel: [204738.354039] rtl28xxu: rtl2832u_frontend_attach: FC0012 tuner found > May 13 21:33:06 localhost kernel: [204738.354040] > May 13 21:33:06 localhost kernel: [204738.361304] DVB: registering adapter 0 frontend 0 (Realtek RTL2832 (DVB-T))... > I missed that one. I really tried to get rid of all of them. I'll fix that soon. > I quickly looked patches through and those looked very good. I will try to review those tonight. > > And here is whole set (tuner+rtl2832u) if someone else would like to test: > http://git.linuxtv.org/anttip/media_tree.git/shortlog/refs/heads/rtl2832u > > regards > Antti Regrads Thomas ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/5] rtl2832 ver 0.3: suport for RTL2832 demodulator revised version 2012-05-12 18:08 ` [PATCH 1/5] rtl2832 ver 0.3: suport for RTL2832 demodulator revised version Thomas Mair 2012-05-12 22:07 ` poma 2012-05-13 18:53 ` Antti Palosaari @ 2012-05-14 1:37 ` Antti Palosaari 2012-05-14 1:46 ` Antti Palosaari ` (3 more replies) 2 siblings, 4 replies; 16+ messages in thread From: Antti Palosaari @ 2012-05-14 1:37 UTC (permalink / raw) To: Thomas Mair; +Cc: linux-media On 12.05.2012 21:08, Thomas Mair wrote: > Changes compared to version 0.2: > - removed reading of signal strength for tuners FC0012,FC0013 (is now supported by fc0012,fc0013 driver) > - moved definition of register names to rtl2832_priv.h > - cleaned up demod private structure > - replaced rtl2832_log2 function with intlog2 from dvb_math > > Signed-off-by: Thomas Mair<thomas.mair86@googlemail.com> > --- > drivers/media/dvb/frontends/Kconfig | 7 + > drivers/media/dvb/frontends/Makefile | 1 + > drivers/media/dvb/frontends/rtl2832.c | 1009 ++++++++++++++++++++++++++++ > drivers/media/dvb/frontends/rtl2832.h | 81 +++ > drivers/media/dvb/frontends/rtl2832_priv.h | 260 +++++++ > 5 files changed, 1358 insertions(+), 0 deletions(-) > create mode 100644 drivers/media/dvb/frontends/rtl2832.c > create mode 100644 drivers/media/dvb/frontends/rtl2832.h > create mode 100644 drivers/media/dvb/frontends/rtl2832_priv.h > > diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig > index f479834..f7d67d7 100644 > --- a/drivers/media/dvb/frontends/Kconfig > +++ b/drivers/media/dvb/frontends/Kconfig > @@ -432,6 +432,13 @@ config DVB_RTL2830 > help > Say Y when you want to support this frontend. > > +config DVB_RTL2832 > + tristate "Realtek RTL2832 DVB-T" > + depends on DVB_CORE&& I2C > + default m if DVB_FE_CUSTOMISE > + help > + Say Y when you want to support this frontend. > + > comment "DVB-C (cable) frontends" > depends on DVB_CORE > > diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile > index b0381dc..9731192 100644 > --- a/drivers/media/dvb/frontends/Makefile > +++ b/drivers/media/dvb/frontends/Makefile > @@ -98,6 +98,7 @@ obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o > obj-$(CONFIG_DVB_A8293) += a8293.o > obj-$(CONFIG_DVB_TDA10071) += tda10071.o > obj-$(CONFIG_DVB_RTL2830) += rtl2830.o > +obj-$(CONFIG_DVB_RTL2832) = rtl2832.o > obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o > obj-$(CONFIG_DVB_AF9033) += af9033.o > > diff --git a/drivers/media/dvb/frontends/rtl2832.c b/drivers/media/dvb/frontends/rtl2832.c > new file mode 100644 > index 0000000..1936c50 > --- /dev/null > +++ b/drivers/media/dvb/frontends/rtl2832.c > @@ -0,0 +1,1009 @@ > +/* > + * Realtek RTL2832 DVB-T demodulator driver > + * > + * Copyright (C) 2012 Thomas Mair<thomas.mair86@gmail.com> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License along > + * with this program; if not, write to the Free Software Foundation, Inc., > + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. > + */ > + > +#include "rtl2832_priv.h" > +#include "dvb_math.h" > + > + > +int rtl2832_debug; > +module_param_named(debug, rtl2832_debug, int, 0644); > +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); > + > + > +static int reg_mask[32] = { > + 0x00000001, > + 0x00000003, > + 0x00000007, > + 0x0000000f, > + 0x0000001f, > + 0x0000003f, > + 0x0000007f, > + 0x000000ff, > + 0x000001ff, > + 0x000003ff, > + 0x000007ff, > + 0x00000fff, > + 0x00001fff, > + 0x00003fff, > + 0x00007fff, > + 0x0000ffff, > + 0x0001ffff, > + 0x0003ffff, > + 0x0007ffff, > + 0x000fffff, > + 0x001fffff, > + 0x003fffff, > + 0x007fffff, > + 0x00ffffff, > + 0x01ffffff, > + 0x03ffffff, > + 0x07ffffff, > + 0x0fffffff, > + 0x1fffffff, > + 0x3fffffff, > + 0x7fffffff, > + 0xffffffff This looks weird but I don't know which is most correct alternative. There could be even some macros for the - check kernel bit operations at the first hand. You can consider shifting bits to right in order to get mask. For example (0xffffffff >> 30) == 0x00000003. > +}; > + > +static const rtl2832_reg_entry registers[] = { > + [DVBT_SOFT_RST] = {0x1, 0x1, 2, 2}, > + [DVBT_IIC_REPEAT] = {0x1, 0x1, 3, 3}, > + [DVBT_TR_WAIT_MIN_8K] = {0x1, 0x88, 11, 2}, > + [DVBT_RSD_BER_FAIL_VAL] = {0x1, 0x8f, 15, 0}, > + [DVBT_EN_BK_TRK] = {0x1, 0xa6, 7, 7}, > + [DVBT_AD_EN_REG] = {0x0, 0x8, 7, 7}, > + [DVBT_AD_EN_REG1] = {0x0, 0x8, 6, 6}, > + [DVBT_EN_BBIN] = {0x1, 0xb1, 0, 0}, > + [DVBT_MGD_THD0] = {0x1, 0x95, 7, 0}, > + [DVBT_MGD_THD1] = {0x1, 0x96, 7, 0}, > + [DVBT_MGD_THD2] = {0x1, 0x97, 7, 0}, > + [DVBT_MGD_THD3] = {0x1, 0x98, 7, 0}, > + [DVBT_MGD_THD4] = {0x1, 0x99, 7, 0}, > + [DVBT_MGD_THD5] = {0x1, 0x9a, 7, 0}, > + [DVBT_MGD_THD6] = {0x1, 0x9b, 7, 0}, > + [DVBT_MGD_THD7] = {0x1, 0x9c, 7, 0}, > + [DVBT_EN_CACQ_NOTCH] = {0x1, 0x61, 4, 4}, > + [DVBT_AD_AV_REF] = {0x0, 0x9, 6, 0}, > + [DVBT_REG_PI] = {0x0, 0xa, 2, 0}, > + [DVBT_PIP_ON] = {0x0, 0x21, 3, 3}, > + [DVBT_SCALE1_B92] = {0x2, 0x92, 7, 0}, > + [DVBT_SCALE1_B93] = {0x2, 0x93, 7, 0}, > + [DVBT_SCALE1_BA7] = {0x2, 0xa7, 7, 0}, > + [DVBT_SCALE1_BA9] = {0x2, 0xa9, 7, 0}, > + [DVBT_SCALE1_BAA] = {0x2, 0xaa, 7, 0}, > + [DVBT_SCALE1_BAB] = {0x2, 0xab, 7, 0}, > + [DVBT_SCALE1_BAC] = {0x2, 0xac, 7, 0}, > + [DVBT_SCALE1_BB0] = {0x2, 0xb0, 7, 0}, > + [DVBT_SCALE1_BB1] = {0x2, 0xb1, 7, 0}, > + [DVBT_KB_P1] = {0x1, 0x64, 3, 1}, > + [DVBT_KB_P2] = {0x1, 0x64, 6, 4}, > + [DVBT_KB_P3] = {0x1, 0x65, 2, 0}, > + [DVBT_OPT_ADC_IQ] = {0x0, 0x6, 5, 4}, > + [DVBT_AD_AVI] = {0x0, 0x9, 1, 0}, > + [DVBT_AD_AVQ] = {0x0, 0x9, 3, 2}, > + [DVBT_K1_CR_STEP12] = {0x2, 0xad, 9, 4}, > + [DVBT_TRK_KS_P2] = {0x1, 0x6f, 2, 0}, > + [DVBT_TRK_KS_I2] = {0x1, 0x70, 5, 3}, > + [DVBT_TR_THD_SET2] = {0x1, 0x72, 3, 0}, > + [DVBT_TRK_KC_P2] = {0x1, 0x73, 5, 3}, > + [DVBT_TRK_KC_I2] = {0x1, 0x75, 2, 0}, > + [DVBT_CR_THD_SET2] = {0x1, 0x76, 7, 6}, > + [DVBT_PSET_IFFREQ] = {0x1, 0x19, 21, 0}, > + [DVBT_SPEC_INV] = {0x1, 0x15, 0, 0}, > + [DVBT_RSAMP_RATIO] = {0x1, 0x9f, 27, 2}, > + [DVBT_CFREQ_OFF_RATIO] = {0x1, 0x9d, 23, 4}, > + [DVBT_FSM_STAGE] = {0x3, 0x51, 6, 3}, > + [DVBT_RX_CONSTEL] = {0x3, 0x3c, 3, 2}, > + [DVBT_RX_HIER] = {0x3, 0x3c, 6, 4}, > + [DVBT_RX_C_RATE_LP] = {0x3, 0x3d, 2, 0}, > + [DVBT_RX_C_RATE_HP] = {0x3, 0x3d, 5, 3}, > + [DVBT_GI_IDX] = {0x3, 0x51, 1, 0}, > + [DVBT_FFT_MODE_IDX] = {0x3, 0x51, 2, 2}, > + [DVBT_RSD_BER_EST] = {0x3, 0x4e, 15, 0}, > + [DVBT_CE_EST_EVM] = {0x4, 0xc, 15, 0}, > + [DVBT_RF_AGC_VAL] = {0x3, 0x5b, 13, 0}, > + [DVBT_IF_AGC_VAL] = {0x3, 0x59, 13, 0}, > + [DVBT_DAGC_VAL] = {0x3, 0x5, 7, 0}, > + [DVBT_SFREQ_OFF] = {0x3, 0x18, 13, 0}, > + [DVBT_CFREQ_OFF] = {0x3, 0x5f, 17, 0}, > + [DVBT_POLAR_RF_AGC] = {0x0, 0xe, 1, 1}, > + [DVBT_POLAR_IF_AGC] = {0x0, 0xe, 0, 0}, > + [DVBT_AAGC_HOLD] = {0x1, 0x4, 5, 5}, > + [DVBT_EN_RF_AGC] = {0x1, 0x4, 6, 6}, > + [DVBT_EN_IF_AGC] = {0x1, 0x4, 7, 7}, > + [DVBT_IF_AGC_MIN] = {0x1, 0x8, 7, 0}, > + [DVBT_IF_AGC_MAX] = {0x1, 0x9, 7, 0}, > + [DVBT_RF_AGC_MIN] = {0x1, 0xa, 7, 0}, > + [DVBT_RF_AGC_MAX] = {0x1, 0xb, 7, 0}, > + [DVBT_IF_AGC_MAN] = {0x1, 0xc, 6, 6}, > + [DVBT_IF_AGC_MAN_VAL] = {0x1, 0xc, 13, 0}, > + [DVBT_RF_AGC_MAN] = {0x1, 0xe, 6, 6}, > + [DVBT_RF_AGC_MAN_VAL] = {0x1, 0xe, 13, 0}, > + [DVBT_DAGC_TRG_VAL] = {0x1, 0x12, 7, 0}, > + [DVBT_AGC_TARG_VAL_0] = {0x1, 0x2, 0, 0}, > + [DVBT_AGC_TARG_VAL_8_1] = {0x1, 0x3, 7, 0}, > + [DVBT_AAGC_LOOP_GAIN] = {0x1, 0xc7, 5, 1}, > + [DVBT_LOOP_GAIN2_3_0] = {0x1, 0x4, 4, 1}, > + [DVBT_LOOP_GAIN2_4] = {0x1, 0x5, 7, 7}, > + [DVBT_LOOP_GAIN3] = {0x1, 0xc8, 4, 0}, > + [DVBT_VTOP1] = {0x1, 0x6, 5, 0}, > + [DVBT_VTOP2] = {0x1, 0xc9, 5, 0}, > + [DVBT_VTOP3] = {0x1, 0xca, 5, 0}, > + [DVBT_KRF1] = {0x1, 0xcb, 7, 0}, > + [DVBT_KRF2] = {0x1, 0x7, 7, 0}, > + [DVBT_KRF3] = {0x1, 0xcd, 7, 0}, > + [DVBT_KRF4] = {0x1, 0xce, 7, 0}, > + [DVBT_EN_GI_PGA] = {0x1, 0xe5, 0, 0}, > + [DVBT_THD_LOCK_UP] = {0x1, 0xd9, 8, 0}, > + [DVBT_THD_LOCK_DW] = {0x1, 0xdb, 8, 0}, > + [DVBT_THD_UP1] = {0x1, 0xdd, 7, 0}, > + [DVBT_THD_DW1] = {0x1, 0xde, 7, 0}, > + [DVBT_INTER_CNT_LEN] = {0x1, 0xd8, 3, 0}, > + [DVBT_GI_PGA_STATE] = {0x1, 0xe6, 3, 3}, > + [DVBT_EN_AGC_PGA] = {0x1, 0xd7, 0, 0}, > + [DVBT_CKOUTPAR] = {0x1, 0x7b, 5, 5}, > + [DVBT_CKOUT_PWR] = {0x1, 0x7b, 6, 6}, > + [DVBT_SYNC_DUR] = {0x1, 0x7b, 7, 7}, > + [DVBT_ERR_DUR] = {0x1, 0x7c, 0, 0}, > + [DVBT_SYNC_LVL] = {0x1, 0x7c, 1, 1}, > + [DVBT_ERR_LVL] = {0x1, 0x7c, 2, 2}, > + [DVBT_VAL_LVL] = {0x1, 0x7c, 3, 3}, > + [DVBT_SERIAL] = {0x1, 0x7c, 4, 4}, > + [DVBT_SER_LSB] = {0x1, 0x7c, 5, 5}, > + [DVBT_CDIV_PH0] = {0x1, 0x7d, 3, 0}, > + [DVBT_CDIV_PH1] = {0x1, 0x7d, 7, 4}, > + [DVBT_MPEG_IO_OPT_2_2] = {0x0, 0x6, 7, 7}, > + [DVBT_MPEG_IO_OPT_1_0] = {0x0, 0x7, 7, 6}, > + [DVBT_CKOUTPAR_PIP] = {0x0, 0xb7, 4, 4}, > + [DVBT_CKOUT_PWR_PIP] = {0x0, 0xb7, 3, 3}, > + [DVBT_SYNC_LVL_PIP] = {0x0, 0xb7, 2, 2}, > + [DVBT_ERR_LVL_PIP] = {0x0, 0xb7, 1, 1}, > + [DVBT_VAL_LVL_PIP] = {0x0, 0xb7, 0, 0}, > + [DVBT_CKOUTPAR_PID] = {0x0, 0xb9, 4, 4}, > + [DVBT_CKOUT_PWR_PID] = {0x0, 0xb9, 3, 3}, > + [DVBT_SYNC_LVL_PID] = {0x0, 0xb9, 2, 2}, > + [DVBT_ERR_LVL_PID] = {0x0, 0xb9, 1, 1}, > + [DVBT_VAL_LVL_PID] = {0x0, 0xb9, 0, 0}, > + [DVBT_SM_PASS] = {0x1, 0x93, 11, 0}, > + [DVBT_AD7_SETTING] = {0x0, 0x11, 15, 0}, > + [DVBT_RSSI_R] = {0x3, 0x1, 6, 0}, > + [DVBT_ACI_DET_IND] = {0x3, 0x12, 0, 0}, > + [DVBT_REG_MON] = {0x0, 0xd, 1, 0}, > + [DVBT_REG_MONSEL] = {0x0, 0xd, 2, 2}, > + [DVBT_REG_GPE] = {0x0, 0xd, 7, 7}, > + [DVBT_REG_GPO] = {0x0, 0x10, 0, 0}, > + [DVBT_REG_4MSEL] = {0x0, 0x13, 0, 0}, I recommend for intending values too. So that all values in a same "row" can be easily compared. > +}; > + > +/* write multiple hardware registers */ > +static int rtl2832_wr(struct rtl2832_priv *priv, u8 reg, u8 *val, int len) > +{ > + int ret; > + u8 buf[1+len]; > + struct i2c_msg msg[1] = { > + { > + .addr = priv->cfg.i2c_addr, > + .flags = 0, > + .len = 1+len, > + .buf = buf, > + } > + }; > + > + buf[0] = reg; > + memcpy(&buf[1], val, len); > + > + ret = i2c_transfer(priv->i2c, msg, 1); > + if (ret == 1) { > + ret = 0; > + } else { > + warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len); > + ret = -EREMOTEIO; > + } > + return ret; > +} > + > +/* read multiple hardware registers */ > +static int rtl2832_rd(struct rtl2832_priv *priv, u8 reg, u8 *val, int len) > +{ > + int ret; > + struct i2c_msg msg[2] = { > + { > + .addr = priv->cfg.i2c_addr, > + .flags = 0, > + .len = 1, > + .buf =®, > + }, { > + .addr = priv->cfg.i2c_addr, > + .flags = I2C_M_RD, > + .len = len, > + .buf = val, > + } > + }; > + > + ret = i2c_transfer(priv->i2c, msg, 2); > + if (ret == 2) { > + ret = 0; > + } else { > + warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len); > + ret = -EREMOTEIO; > +} > +return ret; > +} > + > +/* write multiple registers */ > +static int rtl2832_wr_regs(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val, > + int len) > +{ > + int ret; > + > + > + /* switch bank if needed */ > + if (page != priv->page) { > + ret = rtl2832_wr(priv, 0x00,&page, 1); > + if (ret) > + return ret; > + > + priv->page = page; > +} > + > +return rtl2832_wr(priv, reg, val, len); > +} > + > +/* read multiple registers */ > +static int rtl2832_rd_regs(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val, > + int len) > +{ > + int ret; > + > + /* switch bank if needed */ > + if (page != priv->page) { > + ret = rtl2832_wr(priv, 0x00,&page, 1); > + if (ret) > + return ret; > + > + priv->page = page; > + } > + > + return rtl2832_rd(priv, reg, val, len); > +} > + > +#if 0 /* currently not used */ > +/* write single register */ > +static int rtl2832_wr_reg(struct rtl2832_priv *priv, u8 reg, u8 page, u8 val) > +{ > + return rtl2832_wr_regs(priv, reg, page,&val, 1); > +} > +#endif > + > +/* read single register */ > +static int rtl2832_rd_reg(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val) > +{ > + return rtl2832_rd_regs(priv, reg, page, val, 1); > +} > + > +int rtl2832_rd_demod_reg(struct rtl2832_priv *priv, int reg, u32 *val) > +{ > + int ret; > + > + u8 reg_start_addr; > + u8 msb, lsb; > + u8 page; > + u8 reading[4]; > + u32 reading_tmp; > + int i; > + > + u8 len; > + u32 mask; > + > + reg_start_addr = registers[reg].start_address; > + msb = registers[reg].msb; > + lsb = registers[reg].lsb; > + page = registers[reg].page; > + > + len = (msb>> 3) + 1; > + mask = reg_mask[msb-lsb]; > + > + > + ret = rtl2832_rd_regs(priv, reg_start_addr, page,&reading[0], len); > + if (ret) > + goto err; > + > + reading_tmp = 0; > + for (i = 0; i< len; i++) > + reading_tmp |= reading[i]<< ((len-1-i)*8); > + > + *val = (reading_tmp>> lsb)& mask; > + > + return ret; > + > +err: > + return ret; excessive return > + > +} > + > +int rtl2832_wr_demod_reg(struct rtl2832_priv *priv, int reg, u32 val) > +{ > + int ret, i; > + u8 len; > + u8 reg_start_addr; > + u8 msb, lsb; > + u8 page; > + u32 mask; > + > + > + u8 reading[4]; > + u8 writing[4]; > + u32 reading_tmp; > + u32 writing_tmp; > + > + > + reg_start_addr = registers[reg].start_address; > + msb = registers[reg].msb; > + lsb = registers[reg].lsb; > + page = registers[reg].page; > + > + len = (msb>> 3) + 1; > + mask = reg_mask[msb-lsb]; > + > + > + ret = rtl2832_rd_regs(priv, reg_start_addr, page,&reading[0], len); > + if (ret) > + goto err; > + > + reading_tmp = 0; > + for (i = 0; i< len; i++) > + reading_tmp |= reading[i]<< ((len-1-i)*8); > + > + writing_tmp = reading_tmp& ~(mask<< lsb); > + writing_tmp |= ((val& mask)<< lsb); > + > + > + for (i = 0; i< len; i++) > + writing[i] = (writing_tmp>> ((len-1-i)*8))& 0xff; > + > + ret = rtl2832_wr_regs(priv, reg_start_addr, page,&writing[0], len); > + if (ret) > + goto err; > + > + return ret; > + > +err: > + return ret; excessive return > + > +} > + > + > +static int rtl2832_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) > +{ > + int ret; > + struct rtl2832_priv *priv = fe->demodulator_priv; > + > + dbg("%s: enable=%d", __func__, enable); > + > + /* gate already open or close */ > + if (priv->i2c_gate_state == enable) > + return 0; > + > + ret = rtl2832_wr_demod_reg(priv, DVBT_IIC_REPEAT, (enable ? 0x1 : 0x0)); > + > + if (ret) > + goto err; > + > + priv->i2c_gate_state = enable; > + > + return ret; > +err: > + dbg("%s: failed=%d", __func__, ret); > + return ret; > +} > + > + > + > +static int rtl2832_init(struct dvb_frontend *fe) > +{ > + struct rtl2832_priv *priv = fe->demodulator_priv; > + int i, ret; > + > + u8 en_bbin; > + u64 pset_iffreq; > + > + /* initialization values for the demodulator registers */ > + static rtl2832_reg_value rtl2832_initial_regs_1[] = { > + {DVBT_AD_EN_REG, 0x1}, > + {DVBT_AD_EN_REG1, 0x1}, > + {DVBT_RSD_BER_FAIL_VAL, 0x2800}, > + {DVBT_MGD_THD0, 0x10}, > + {DVBT_MGD_THD1, 0x20}, > + {DVBT_MGD_THD2, 0x20}, > + {DVBT_MGD_THD3, 0x40}, > + {DVBT_MGD_THD4, 0x22}, > + {DVBT_MGD_THD5, 0x32}, > + {DVBT_MGD_THD6, 0x37}, > + {DVBT_MGD_THD7, 0x39}, > + {DVBT_EN_BK_TRK, 0x0}, > + {DVBT_EN_CACQ_NOTCH, 0x0}, > + {DVBT_AD_AV_REF, 0x2a}, > + {DVBT_REG_PI, 0x6}, > + {DVBT_PIP_ON, 0x0}, > + {DVBT_CDIV_PH0, 0x8}, > + {DVBT_CDIV_PH1, 0x8}, > + {DVBT_SCALE1_B92, 0x4}, > + {DVBT_SCALE1_B93, 0xb0}, > + {DVBT_SCALE1_BA7, 0x78}, > + {DVBT_SCALE1_BA9, 0x28}, > + {DVBT_SCALE1_BAA, 0x59}, > + {DVBT_SCALE1_BAB, 0x83}, > + {DVBT_SCALE1_BAC, 0xd4}, > + {DVBT_SCALE1_BB0, 0x65}, > + {DVBT_SCALE1_BB1, 0x43}, > + {DVBT_KB_P1, 0x1}, > + {DVBT_KB_P2, 0x4}, > + {DVBT_KB_P3, 0x7}, > + {DVBT_K1_CR_STEP12, 0xa}, > + {DVBT_REG_GPE, 0x1}, > + {DVBT_SERIAL, 0x0}, > + {DVBT_CDIV_PH0, 0x9}, > + {DVBT_CDIV_PH1, 0x9}, > + {DVBT_MPEG_IO_OPT_2_2, 0x0}, > + {DVBT_MPEG_IO_OPT_1_0, 0x0}, > + {DVBT_TRK_KS_P2, 0x4}, > + {DVBT_TRK_KS_I2, 0x7}, > + {DVBT_TR_THD_SET2, 0x6}, > + {DVBT_TRK_KC_I2, 0x5}, > + {DVBT_CR_THD_SET2, 0x1}, > + > + > + }; > + > + static rtl2832_reg_value rtl2832_initial_regs_2[] = { > + {DVBT_SPEC_INV, 0x0}, > + {DVBT_DAGC_TRG_VAL, 0x5a}, > + {DVBT_AGC_TARG_VAL_0, 0x0}, > + {DVBT_AGC_TARG_VAL_8_1, 0x5a}, > + {DVBT_AAGC_LOOP_GAIN, 0x16}, > + {DVBT_LOOP_GAIN2_3_0, 0x6}, > + {DVBT_LOOP_GAIN2_4, 0x1}, > + {DVBT_LOOP_GAIN3, 0x16}, > + {DVBT_VTOP1, 0x35}, > + {DVBT_VTOP2, 0x21}, > + {DVBT_VTOP3, 0x21}, > + {DVBT_KRF1, 0x0}, > + {DVBT_KRF2, 0x40}, > + {DVBT_KRF3, 0x10}, > + {DVBT_KRF4, 0x10}, > + {DVBT_IF_AGC_MIN, 0x80}, > + {DVBT_IF_AGC_MAX, 0x7f}, > + {DVBT_RF_AGC_MIN, 0x80}, > + {DVBT_RF_AGC_MAX, 0x7f}, > + {DVBT_POLAR_RF_AGC, 0x0}, > + {DVBT_POLAR_IF_AGC, 0x0}, > + {DVBT_AD7_SETTING, 0xe9bf}, > + {DVBT_EN_GI_PGA, 0x0}, > + {DVBT_THD_LOCK_UP, 0x0}, > + {DVBT_THD_LOCK_DW, 0x0}, > + {DVBT_THD_UP1, 0x11}, > + {DVBT_THD_DW1, 0xef}, > + {DVBT_INTER_CNT_LEN, 0xc}, > + {DVBT_GI_PGA_STATE, 0x0}, > + {DVBT_EN_AGC_PGA, 0x1}, > + {DVBT_IF_AGC_MAN, 0x0}, > + }; Maybe you can check indention here too. Kernel indention is 1 tab == 8 spaces wide. Check your editor has correct settings. > + > + > + dbg("%s", __func__); > + > + en_bbin = (priv->cfg.if_dvbt == 0 ? 0x1 : 0x0); > + > + /* > + * PSET_IFFREQ = - floor((IfFreqHz % CrystalFreqHz) * pow(2, 22) > + * / CrystalFreqHz) > + */ > + pset_iffreq = priv->cfg.if_dvbt % priv->cfg.xtal; > + pset_iffreq *= 0x400000; > + pset_iffreq = div_u64(pset_iffreq, priv->cfg.xtal); > + pset_iffreq = pset_iffreq& 0x3fffff; > + > + > + > + for (i = 0; i< 42; i++) { You should use ARRAY_SIZE() likely here or some other macro. > + ret = rtl2832_wr_demod_reg(priv, rtl2832_initial_regs_1[i].reg, > + rtl2832_initial_regs_1[i].value); > + if (ret) > + goto err; > + } > + > + /* if frequency settings */ > + ret = rtl2832_wr_demod_reg(priv, DVBT_EN_BBIN, en_bbin); > + if (ret) > + goto err; > + > + ret = rtl2832_wr_demod_reg(priv, DVBT_PSET_IFFREQ, pset_iffreq); > + if (ret) > + goto err; > + > + for (i = 0; i< 31; i++) { ARRAY_SIZE() > + ret = rtl2832_wr_demod_reg(priv, rtl2832_initial_regs_2[i].reg, > + rtl2832_initial_regs_2[i].value); > + if (ret) > + goto err; What is the reason behind you have split inittab as a two parts? > + } > + > + priv->sleeping = false; > + > + return ret; > + > +err: > + return ret; excessive return > +} > + > +static int rtl2832_sleep(struct dvb_frontend *fe) > +{ > + struct rtl2832_priv *priv = fe->demodulator_priv; > + > + dbg("%s", __func__); > + priv->sleeping = true; > + return 0; > +} > + > +int rtl2832_get_tune_settings(struct dvb_frontend *fe, > + struct dvb_frontend_tune_settings *s) > +{ > + dbg("%s", __func__); > + s->min_delay_ms = 1000; > + s->step_size = fe->ops.info.frequency_stepsize * 2; > + s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; > + return 0; > +} > + > +static int rtl2832_set_frontend(struct dvb_frontend *fe) > +{ > + struct rtl2832_priv *priv = fe->demodulator_priv; > + struct dtv_frontend_properties *c =&fe->dtv_property_cache; > + int ret, i, j; > + u64 bw_mode, num, num2; > + u32 resamp_ratio, cfreq_off_ratio; > + > + > + static u8 bw_params[3][32] = { > + /* 6 MHz bandwidth */ > + { > + 0xf5, 0xff, 0x15, 0x38, 0x5d, 0x6d, 0x52, 0x07, 0xfa, 0x2f, > + 0x53, 0xf5, 0x3f, 0xca, 0x0b, 0x91, 0xea, 0x30, 0x63, 0xb2, > + 0x13, 0xda, 0x0b, 0xc4, 0x18, 0x7e, 0x16, 0x66, 0x08, 0x67, > + 0x19, 0xe0, > + }, > + > + /* 7 MHz bandwidth */ > + { > + 0xe7, 0xcc, 0xb5, 0xba, 0xe8, 0x2f, 0x67, 0x61, 0x00, 0xaf, > + 0x86, 0xf2, 0xbf, 0x59, 0x04, 0x11, 0xb6, 0x33, 0xa4, 0x30, > + 0x15, 0x10, 0x0a, 0x42, 0x18, 0xf8, 0x17, 0xd9, 0x07, 0x22, > + 0x19, 0x10, > + }, > + > + /* 8 MHz bandwidth */ > + { > + 0x09, 0xf6, 0xd2, 0xa7, 0x9a, 0xc9, 0x27, 0x77, 0x06, 0xbf, > + 0xec, 0xf4, 0x4f, 0x0b, 0xfc, 0x01, 0x63, 0x35, 0x54, 0xa7, > + 0x16, 0x66, 0x08, 0xb4, 0x19, 0x6e, 0x19, 0x65, 0x05, 0xc8, > + 0x19, 0xe0, > + }, > + }; > + > + > + dbg("%s: frequency=%d bandwidth_hz=%d inversion=%d", __func__, > + c->frequency, c->bandwidth_hz, c->inversion); > + > + > + /* program tuner */ > + if (fe->ops.tuner_ops.set_params) > + fe->ops.tuner_ops.set_params(fe); > + > + > + switch (c->bandwidth_hz) { > + case 6000000: > + i = 0; > + bw_mode = 48000000; > + break; > + case 7000000: > + i = 1; > + bw_mode = 56000000; > + break; > + case 8000000: > + i = 2; > + bw_mode = 64000000; > + break; > + default: > + dbg("invalid bandwidth"); > + return -EINVAL; > + } > + > + for (j = 0; j< 32; j++) { use sizeof() here > + ret = rtl2832_wr_regs(priv, 0x1c+j, 1,&bw_params[i][j], 1); > + if (ret) > + goto err; > + } > + > + /* calculate and set resample ratio > + * RSAMP_RATIO = floor(CrystalFreqHz * 7 * pow(2, 22) > + * / ConstWithBandwidthMode) > + */ > + num = priv->cfg.xtal * 7; > + num *= 0x400000; > + num = div_u64(num, bw_mode); > + resamp_ratio = num& 0x3ffffff; > + ret = rtl2832_wr_demod_reg(priv, DVBT_RSAMP_RATIO, resamp_ratio); > + if (ret) > + goto err; > + > + /* calculate and set cfreq off ratio > + * CFREQ_OFF_RATIO = - floor(ConstWithBandwidthMode * pow(2, 20) > + * / (CrystalFreqHz * 7)) > + */ > + num = bw_mode<< 20; > + num2 = priv->cfg.xtal * 7; > + num = div_u64(num, num2); > + num = -num; > + cfreq_off_ratio = num& 0xfffff; > + ret = rtl2832_wr_demod_reg(priv, DVBT_CFREQ_OFF_RATIO, cfreq_off_ratio); > + if (ret) > + goto err; > + > + > + /* soft reset */ > + ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x1); > + if (ret) > + goto err; > + > + ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x0); > + if (ret) > + goto err; > + > + return ret; > +err: > + info("%s: failed=%d", __func__, ret); > + return ret; > +} > + > +static int rtl2832_read_status(struct dvb_frontend *fe, fe_status_t *status) > +{ > + struct rtl2832_priv *priv = fe->demodulator_priv; > + int ret; > + u32 tmp; > + *status = 0; > + > + > + dbg("%s", __func__); > + if (priv->sleeping) > + return 0; > + > + ret = rtl2832_rd_demod_reg(priv, DVBT_FSM_STAGE,&tmp); > + if (ret) > + goto err; > + > + if (tmp == 11) { > + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | > + FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; > + } > + /* TODO find out if this is also true for rtl2832? */ > + /*else if (tmp == 10) { > + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | > + FE_HAS_VITERBI; > + }*/ > + > + return ret; > +err: > + info("%s: failed=%d", __func__, ret); > + return ret; > +} > + > + > +#define RTL2832_CE_EST_EVM_MAX_VALUE 65535 > +#define RTL2832_SNR_FRAC_BIT_NUM 10 > +#define RTL2832_SNR_DB_DEN 3402 > + > +static int rtl2832_read_snr(struct dvb_frontend *fe, u16 *snr) > +{ > + struct rtl2832_priv *priv = fe->demodulator_priv; > + int ret; > + u64 num; > + u32 ce_est_evm, fsm_stage, constellation, hierarchy; > + > + /* Calculated by: 10 * log2(Norm * pow(2, 11)) * pow(2, 10) */ > + static const long SnrDbNum[3][4] = { These numbers fits surely smaller space than a long. > + {122880, 122880, 122880, 122880, }, > + {146657, 146657, 156897, 171013, }, > + {167857, 167857, 173127, 181810, }, > + }; > + > + static const int snrMaxDb[3] = { 23, 26, 29, }; and same here. Wasting few bytes of memory. And for both of those lastly mentioned : those are against naming rules. See naming rules from the Kernel documentation (or just rename style snr_max_db). > + > + dbg("%s", __func__); > + > + /* get FSM Stage */ > + ret = rtl2832_rd_demod_reg(priv, DVBT_FSM_STAGE,&fsm_stage); > + if (ret) > + goto err; > + > + if (fsm_stage< 10) { > + ce_est_evm = RTL2832_CE_EST_EVM_MAX_VALUE; > + } else { > + ret = rtl2832_rd_demod_reg(priv, DVBT_CE_EST_EVM,&ce_est_evm); > + if (ret) > + goto err; > + } > + > + /* get constellation */ > + ret = rtl2832_rd_demod_reg(priv, DVBT_RX_CONSTEL,&constellation); > + if (ret) > + goto err; > + if (constellation> 2) > + goto err; > + > + /* get hierarchy */ > + ret = rtl2832_rd_demod_reg(priv, DVBT_RX_HIER,&hierarchy); > + if (ret) > + goto err; > + if (hierarchy> 3) > + goto err; > + > + > + /* > + SNR dB formula > + Original formula: SNR_dB = 10 * log10(Norm * pow(2, 11) / CeEstEvm) > + Adjusted formula: SNR_dB = (SNR_DB_NUM_CONST - 10 * log2(CeEstEvm) * > + pow(2, 10)) / SNR_DB_DEN > + SNR_DB_NUM_CONST = 10 * log2(Norm * pow(2, 11)) * > + pow(2, 10) > + SNR_DB_DEN = log2(10) * pow(2, 10) = 3402 = 0xd4a > + Norm: > + None Alpha=1 Alpha=2 Alpha=4 > + 4-QAM 2 2 2 2 > + 16-QAM 10 10 20 52 > + 64-QAM 42 42 60 108 > + */ > + > + /* intlog2 returns log2(x)<< 24 */ > + num = intlog2(ce_est_evm)>>14; > + num = SnrDbNum[constellation][hierarchy] - 10 * num; > + > + num = div_u64(num, RTL2832_SNR_DB_DEN); > + num *= 0xffff; > + num = div_u64(num, snrMaxDb[constellation]); > + > + if (num> 0xffff) > + *snr = 0xffff; > + else if (num< 0) > + *snr = 0; > + else > + *snr = 0xffff& num; This is implemented stupidly. num has type u64 *unsigned 64 bit*. Checks like that are mostly useless. If you think it twice you can understand it will never go to the else if (). Also dropping upper bits starting from the 0xffff (else branch) is useless as you have compared it cannot be such big value at the first if(). > + > + return ret; > + > +err: > + info("%s: failed=%d", __func__, ret); > + return ret; > +} Afer some testing I saw this does not work. It returns some crazy numers all the time like "b960" => 4745.6 dB uh. Not possible at all. That driver: status 1f | signal 2f2f | snr b960 | ber 00000000 | unc 00000064 | FE_HAS_LOCK AF9033 driver: status 1f | signal 68f5 | snr 0122 | ber 00000000 | unc 00000000 | FE_HAS_LOCK All(?) statistics are quite broken in mean of returned values. > + > +static int rtl2832_read_ber(struct dvb_frontend *fe, u32 *ber) > +{ > + struct rtl2832_priv *priv = fe->demodulator_priv; > + int ret; > + u32 tmp; > + > + dbg("%s", __func__); > + > + /* get BER */ > + ret = rtl2832_rd_demod_reg(priv, DVBT_RSD_BER_EST,&tmp); > + if (ret) > + goto err; > + > + *ber = tmp; > + return ret; > + > +err: > + info("%s: failed=%d", __func__, ret); > + *ber = 19616; 19616?? what are those magic numbers... it is error situation that should never happen (but happens likely when called during sleep). Leaving *ber untouched in that kind of error situation is just good choise. Caller surely will not look returned value when error status is returned. > + return ret; > +} > + > +static int rtl2832_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) > +{ > + struct rtl2832_priv *priv = fe->demodulator_priv; > + int ret; > + u32 tmp; > + u16 num; > + > + dbg("%s", __func__); > + > + > + /* get FSM Stage */ > + ret = rtl2832_rd_demod_reg(priv, DVBT_FSM_STAGE,&tmp); > + if (ret) > + goto err; > + > + /* if signal is not locked quality is zero */ > + if (tmp< 10) { > + *ucblocks = 0; > + return 0; > + } > + > + /* get BER */ > + ret = rtl2832_rd_demod_reg(priv, DVBT_RSD_BER_EST,&tmp); > + if (ret) > + goto err; > + > + /* > + Determine signal quality according to RSD_BER_EST. > + Note: Map RSD_BER_EST value 8192 ~ 128 to 10 ~ 100 > + Original formula: SignalQuality = 205 - 15 * log2(RSD_BER_EST) > + Adjusted formula: SignalQuality = ((205<< 5) - 15 * > + (log2(RSD_BER_EST)<< 5))>> 5 > + If RSD_BER_EST> 8192, signal quality is 10. > + If RSD_BER_EST< 128, signal quality is 100. > + */ > + > + if (tmp> 8192) > + *ucblocks = 10; > + else if (tmp< 128) > + *ucblocks = 100; > + else { > + num = intlog2(tmp)>> 19; > + *ucblocks = ((205<< 5) - 15 * num)>> 5; > + } > + > + return 0; > + > +err: > + info("%s: failed=%d", __func__, ret); > + *ucblocks = 0; Same here. If it returns error status then returned values are not valid in any way. > + return ret; > +} I have strong feeling whole callback is totally wrong. Looks like you are calculating signal quality - not bit error rate as should. Signal quality is likely same as SNR - or SNR is way to measure signal quality. But BER is quite much different. And thats why it reports always for me 0x64 == 100. > + > + > +static int rtl2832_read_signal_strength(struct dvb_frontend *fe, u16 *strength) > +{ > + struct rtl2832_priv *priv = fe->demodulator_priv; > + int ret, if_agc; > + u32 fsm_stage, if_agc_raw; > + > + dbg("%s", __func__); > + > + ret = rtl2832_rd_demod_reg(priv, DVBT_FSM_STAGE,&fsm_stage); > + if (ret) > + goto err; oops, indentation > + > + if (fsm_stage< 10) > + *strength = 0; indentation > + else { > + /* if_agc is read as a 10bit binary */ > + ret = rtl2832_rd_demod_reg(priv, DVBT_IF_AGC_VAL,&if_agc_raw); > + if (ret) > + goto err; > + > + if (if_agc_raw< (1<< 9)) > + if_agc = if_agc_raw; > + else > + if_agc = -(~(if_agc_raw-1)& 0x1ff); > + > + *strength = 55 - if_agc / 182; > + *strength |= *strength<< 8; That calculation shows doubtful. Why not to scale directly to the counter. Now you divide it by 182 and after that multiply 256 (<< 8 means same as multiply by 256). It is stupid calculation. > + } > + return 0; > +err: > + info("%s: failed=%d", __func__, ret); > + return ret; > +} > + > +static struct dvb_frontend_ops rtl2832_ops; > + > +static void rtl2832_release(struct dvb_frontend *fe) > +{ > + struct rtl2832_priv *priv = fe->demodulator_priv; > + > + dbg("%s", __func__); > + kfree(priv); > +} > + > +struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg, > + struct i2c_adapter *i2c) > +{ > + struct rtl2832_priv *priv = NULL; > + int ret = 0; > + u8 tmp; > + > + dbg("%s", __func__); > + > + /* allocate memory for the internal state */ > + priv = kzalloc(sizeof(struct rtl2832_priv), GFP_KERNEL); > + if (priv == NULL) > + goto err; > + > + /* setup the priv */ > + priv->i2c = i2c; > + priv->tuner = cfg->tuner; > + memcpy(&priv->cfg, cfg, sizeof(struct rtl2832_config)); > + > + /* check if the demod is there */ > + ret = rtl2832_rd_reg(priv, 0x00, 0x0,&tmp); > + if (ret) > + goto err; > + > + /* create dvb_frontend */ > + memcpy(&priv->fe.ops,&rtl2832_ops, sizeof(struct dvb_frontend_ops)); > + priv->fe.demodulator_priv = priv; > + > + /* TODO implement sleep mode depending on RC */ > + priv->sleeping = true; Demod sleep does not have nothing to do with remote AFAIK. Wrong comment? > + > + return&priv->fe; > +err: > + dbg("%s: failed=%d", __func__, ret); > + kfree(priv); > + return NULL; > +} > +EXPORT_SYMBOL(rtl2832_attach); > + > +static struct dvb_frontend_ops rtl2832_ops = { > + .delsys = { SYS_DVBT }, > + .info = { > + .name = "Realtek RTL2832 (DVB-T)", > + .type = FE_OFDM, .type is no longer used as there is .delsys so remove it. I wonder why it even exists struct dvb_frontend_ops... > + .frequency_min = 50000000, Smallest DVB-T frequency is ~174MHz. 50MHz is for DVB-C... > + .frequency_max = 862000000, > + .frequency_stepsize = 166667, > + .caps = FE_CAN_FEC_1_2 | > + FE_CAN_FEC_2_3 | > + FE_CAN_FEC_3_4 | > + FE_CAN_FEC_5_6 | > + FE_CAN_FEC_7_8 | > + FE_CAN_FEC_AUTO | > + FE_CAN_QPSK | > + FE_CAN_QAM_16 | > + FE_CAN_QAM_64 | > + FE_CAN_QAM_AUTO | > + FE_CAN_TRANSMISSION_MODE_AUTO | > + FE_CAN_GUARD_INTERVAL_AUTO | > + FE_CAN_HIERARCHY_AUTO | > + FE_CAN_RECOVER | > + FE_CAN_MUTE_TS > + }, > + > + .release = rtl2832_release, > + > + .init = rtl2832_init, > + .sleep = rtl2832_sleep, > + > + .get_tune_settings = rtl2832_get_tune_settings, > + > + .set_frontend = rtl2832_set_frontend, > + > + .read_status = rtl2832_read_status, > + .read_snr = rtl2832_read_snr, > + .read_ber = rtl2832_read_ber, > + .read_ucblocks = rtl2832_read_ucblocks, > + .read_signal_strength = rtl2832_read_signal_strength, > + .i2c_gate_ctrl = rtl2832_i2c_gate_ctrl, > +}; > + > +MODULE_AUTHOR("Thomas Mair<mair.thomas86@gmail.com>"); > +MODULE_DESCRIPTION("Realtek RTL2832 DVB-T demodulator driver"); > +MODULE_LICENSE("GPL"); > +MODULE_VERSION("0.3"); > diff --git a/drivers/media/dvb/frontends/rtl2832.h b/drivers/media/dvb/frontends/rtl2832.h > new file mode 100644 > index 0000000..6918010 > --- /dev/null > +++ b/drivers/media/dvb/frontends/rtl2832.h > @@ -0,0 +1,81 @@ > +/* > + * Realtek RTL2832 DVB-T demodulator driver > + * > + * Copyright (C) 2012 Thomas Mair<thomas.mair86@gmail.com> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License along > + * with this program; if not, write to the Free Software Foundation, Inc., > + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. > + */ > + > +#ifndef RTL2832_H > +#define RTL2832_H > + > +#include<linux/dvb/frontend.h> > + > +struct rtl2832_config { > + /* > + * Demodulator I2C address. > + */ > + u8 i2c_addr; > + > + /* > + * Xtal frequency. > + * Hz > + * 4000000, 16000000, 25000000, 28800000 > + */ > + u32 xtal; > + > + /* > + * IFs for all used modes. > + * Hz > + * 4570000, 4571429, 36000000, 36125000, 36166667, 44000000 > + */ > + u32 if_dvbt; > + > + /* > + */ > + u8 tuner; > +}; > + > + > +#if defined(CONFIG_DVB_RTL2832) || \ > + (defined(CONFIG_DVB_RTL2832_MODULE)&& defined(MODULE)) > +extern struct dvb_frontend *rtl2832_attach( > + const struct rtl2832_config *cfg, > + struct i2c_adapter *i2c > +); > + > +extern struct i2c_adapter *rtl2832_get_tuner_i2c_adapter( > + struct dvb_frontend *fe > +); > +#else > +static inline struct dvb_frontend *rtl2832_attach( > + const struct rtl2832_config *config, > + struct i2c_adapter *i2c > +) > +{ > + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); > + return NULL; > +} > + > +static inline struct i2c_adapter *rtl2832_get_tuner_i2c_adapter( > + struct dvb_frontend *fe > +) > +{ > + return NULL; > +} There is no i2c_adapter to export. It is copy paste error from the RTL2830 which needs I2C-adapter due to automatic I2C-gate close. > +#endif > + > + > +#endif /* RTL2832_H */ > diff --git a/drivers/media/dvb/frontends/rtl2832_priv.h b/drivers/media/dvb/frontends/rtl2832_priv.h > new file mode 100644 > index 0000000..0f5df2f > --- /dev/null > +++ b/drivers/media/dvb/frontends/rtl2832_priv.h > @@ -0,0 +1,260 @@ > +/* > + * Realtek RTL2832 DVB-T demodulator driver > + * > + * Copyright (C) 2012 Thomas Mair<thomas.mair86@gmail.com> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License along > + * with this program; if not, write to the Free Software Foundation, Inc., > + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. > + */ > + > +#ifndef RTL2832_PRIV_H > +#define RTL2832_PRIV_H > + > +#include "dvb_frontend.h" > +#include "rtl2832.h" > + > +#define LOG_PREFIX "rtl2832" > + > +#undef dbg > +#define dbg(f, arg...) \ > + if (rtl2832_debug) \ > + printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) > +#undef err > +#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) > +#undef info > +#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) > +#undef warn > +#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) > + > +struct rtl2832_priv { > + struct i2c_adapter *i2c; > + struct dvb_frontend fe; > + struct rtl2832_config cfg; > + > + bool i2c_gate_state; > + bool sleeping; > + > + u8 tuner; > + u8 page; /* active register page */ > +}; > + > +typedef struct { > + u8 page; > + u8 start_address; > + u8 msb; > + u8 lsb; > +} > +rtl2832_reg_entry; typedefs are not allowed > + > +typedef struct { > + int reg; > + u32 value; > +} > +rtl2832_reg_value; typedefs are not allowed > + > + > +/* Demod register bit names */ > +enum DVBT_REG_BIT_NAME { > + DVBT_SOFT_RST, > + DVBT_IIC_REPEAT, > + DVBT_TR_WAIT_MIN_8K, > + DVBT_RSD_BER_FAIL_VAL, > + DVBT_EN_BK_TRK, > + DVBT_REG_PI, > + DVBT_REG_PFREQ_1_0, > + DVBT_PD_DA8, > + DVBT_LOCK_TH, > + DVBT_BER_PASS_SCAL, > + DVBT_CE_FFSM_BYPASS, > + DVBT_ALPHAIIR_N, > + DVBT_ALPHAIIR_DIF, > + DVBT_EN_TRK_SPAN, > + DVBT_LOCK_TH_LEN, > + DVBT_CCI_THRE, > + DVBT_CCI_MON_SCAL, > + DVBT_CCI_M0, > + DVBT_CCI_M1, > + DVBT_CCI_M2, > + DVBT_CCI_M3, > + DVBT_SPEC_INIT_0, > + DVBT_SPEC_INIT_1, > + DVBT_SPEC_INIT_2, > + DVBT_AD_EN_REG, > + DVBT_AD_EN_REG1, > + DVBT_EN_BBIN, > + DVBT_MGD_THD0, > + DVBT_MGD_THD1, > + DVBT_MGD_THD2, > + DVBT_MGD_THD3, > + DVBT_MGD_THD4, > + DVBT_MGD_THD5, > + DVBT_MGD_THD6, > + DVBT_MGD_THD7, > + DVBT_EN_CACQ_NOTCH, > + DVBT_AD_AV_REF, > + DVBT_PIP_ON, > + DVBT_SCALE1_B92, > + DVBT_SCALE1_B93, > + DVBT_SCALE1_BA7, > + DVBT_SCALE1_BA9, > + DVBT_SCALE1_BAA, > + DVBT_SCALE1_BAB, > + DVBT_SCALE1_BAC, > + DVBT_SCALE1_BB0, > + DVBT_SCALE1_BB1, > + DVBT_KB_P1, > + DVBT_KB_P2, > + DVBT_KB_P3, > + DVBT_OPT_ADC_IQ, > + DVBT_AD_AVI, > + DVBT_AD_AVQ, > + DVBT_K1_CR_STEP12, > + DVBT_TRK_KS_P2, > + DVBT_TRK_KS_I2, > + DVBT_TR_THD_SET2, > + DVBT_TRK_KC_P2, > + DVBT_TRK_KC_I2, > + DVBT_CR_THD_SET2, > + DVBT_PSET_IFFREQ, > + DVBT_SPEC_INV, > + DVBT_BW_INDEX, > + DVBT_RSAMP_RATIO, > + DVBT_CFREQ_OFF_RATIO, > + DVBT_FSM_STAGE, > + DVBT_RX_CONSTEL, > + DVBT_RX_HIER, > + DVBT_RX_C_RATE_LP, > + DVBT_RX_C_RATE_HP, > + DVBT_GI_IDX, > + DVBT_FFT_MODE_IDX, > + DVBT_RSD_BER_EST, > + DVBT_CE_EST_EVM, > + DVBT_RF_AGC_VAL, > + DVBT_IF_AGC_VAL, > + DVBT_DAGC_VAL, > + DVBT_SFREQ_OFF, > + DVBT_CFREQ_OFF, > + DVBT_POLAR_RF_AGC, > + DVBT_POLAR_IF_AGC, > + DVBT_AAGC_HOLD, > + DVBT_EN_RF_AGC, > + DVBT_EN_IF_AGC, > + DVBT_IF_AGC_MIN, > + DVBT_IF_AGC_MAX, > + DVBT_RF_AGC_MIN, > + DVBT_RF_AGC_MAX, > + DVBT_IF_AGC_MAN, > + DVBT_IF_AGC_MAN_VAL, > + DVBT_RF_AGC_MAN, > + DVBT_RF_AGC_MAN_VAL, > + DVBT_DAGC_TRG_VAL, > + DVBT_AGC_TARG_VAL, > + DVBT_LOOP_GAIN_3_0, > + DVBT_LOOP_GAIN_4, > + DVBT_VTOP, > + DVBT_KRF, > + DVBT_AGC_TARG_VAL_0, > + DVBT_AGC_TARG_VAL_8_1, > + DVBT_AAGC_LOOP_GAIN, > + DVBT_LOOP_GAIN2_3_0, > + DVBT_LOOP_GAIN2_4, > + DVBT_LOOP_GAIN3, > + DVBT_VTOP1, > + DVBT_VTOP2, > + DVBT_VTOP3, > + DVBT_KRF1, > + DVBT_KRF2, > + DVBT_KRF3, > + DVBT_KRF4, > + DVBT_EN_GI_PGA, > + DVBT_THD_LOCK_UP, > + DVBT_THD_LOCK_DW, > + DVBT_THD_UP1, > + DVBT_THD_DW1, > + DVBT_INTER_CNT_LEN, > + DVBT_GI_PGA_STATE, > + DVBT_EN_AGC_PGA, > + DVBT_CKOUTPAR, > + DVBT_CKOUT_PWR, > + DVBT_SYNC_DUR, > + DVBT_ERR_DUR, > + DVBT_SYNC_LVL, > + DVBT_ERR_LVL, > + DVBT_VAL_LVL, > + DVBT_SERIAL, > + DVBT_SER_LSB, > + DVBT_CDIV_PH0, > + DVBT_CDIV_PH1, > + DVBT_MPEG_IO_OPT_2_2, > + DVBT_MPEG_IO_OPT_1_0, > + DVBT_CKOUTPAR_PIP, > + DVBT_CKOUT_PWR_PIP, > + DVBT_SYNC_LVL_PIP, > + DVBT_ERR_LVL_PIP, > + DVBT_VAL_LVL_PIP, > + DVBT_CKOUTPAR_PID, > + DVBT_CKOUT_PWR_PID, > + DVBT_SYNC_LVL_PID, > + DVBT_ERR_LVL_PID, > + DVBT_VAL_LVL_PID, > + DVBT_SM_PASS, > + DVBT_UPDATE_REG_2, > + DVBT_BTHD_P3, > + DVBT_BTHD_D3, > + DVBT_FUNC4_REG0, > + DVBT_FUNC4_REG1, > + DVBT_FUNC4_REG2, > + DVBT_FUNC4_REG3, > + DVBT_FUNC4_REG4, > + DVBT_FUNC4_REG5, > + DVBT_FUNC4_REG6, > + DVBT_FUNC4_REG7, > + DVBT_FUNC4_REG8, > + DVBT_FUNC4_REG9, > + DVBT_FUNC4_REG10, > + DVBT_FUNC5_REG0, > + DVBT_FUNC5_REG1, > + DVBT_FUNC5_REG2, > + DVBT_FUNC5_REG3, > + DVBT_FUNC5_REG4, > + DVBT_FUNC5_REG5, > + DVBT_FUNC5_REG6, > + DVBT_FUNC5_REG7, > + DVBT_FUNC5_REG8, > + DVBT_FUNC5_REG9, > + DVBT_FUNC5_REG10, > + DVBT_FUNC5_REG11, > + DVBT_FUNC5_REG12, > + DVBT_FUNC5_REG13, > + DVBT_FUNC5_REG14, > + DVBT_FUNC5_REG15, > + DVBT_FUNC5_REG16, > + DVBT_FUNC5_REG17, > + DVBT_FUNC5_REG18, > + DVBT_AD7_SETTING, > + DVBT_RSSI_R, > + DVBT_ACI_DET_IND, > + DVBT_REG_MON, > + DVBT_REG_MONSEL, > + DVBT_REG_GPE, > + DVBT_REG_GPO, > + DVBT_REG_4MSEL, > + DVBT_TEST_REG_1, > + DVBT_TEST_REG_2, > + DVBT_TEST_REG_3, > + DVBT_TEST_REG_4, > + DVBT_REG_BIT_NAME_ITEM_TERMINATOR, > +}; > + > +#endif /* RTL2832_PRIV_H */ Puuuh, there was more findings what I supposed earlier. Most of those are easy to fix. But it seems like all the statistics are broken, returning wrong values and one BER was even inplemented as a signal quality meter. What you say if I propose you to remove those statistics and sent driver without? Add those then later. Statistics are not mandatory and it is 3.4-RC7 phase ongoing. It means driver should be quite ready during that week if we want it to the Kernel 3.5. I am almost sure Kernel 3.4 is released next weekend... regards Antti -- http://palosaari.fi/ ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/5] rtl2832 ver 0.3: suport for RTL2832 demodulator revised version 2012-05-14 1:37 ` Antti Palosaari @ 2012-05-14 1:46 ` Antti Palosaari 2012-05-15 15:41 ` Antti Palosaari ` (2 subsequent siblings) 3 siblings, 0 replies; 16+ messages in thread From: Antti Palosaari @ 2012-05-14 1:46 UTC (permalink / raw) To: Thomas Mair; +Cc: linux-media I forget to ran checkpatch.pl. Looks like you too. Mostly simple fixes... You should always ran checkpatch.pl when dending patches. On 14.05.2012 04:37, Antti Palosaari wrote: > Puuuh, there was more findings what I supposed earlier. Most of those > are easy to fix. > > But it seems like all the statistics are broken, returning wrong values > and one BER was even inplemented as a signal quality meter. > > What you say if I propose you to remove those statistics and sent driver > without? Add those then later. > > Statistics are not mandatory and it is 3.4-RC7 phase ongoing. It means > driver should be quite ready during that week if we want it to the > Kernel 3.5. I am almost sure Kernel 3.4 is released next weekend... [crope@localhost linux]$ ./scripts/checkpatch.pl --file drivers/media/dvb/frontends/rtl2832.c WARNING: line over 80 characters #587: FILE: media/dvb/frontends/rtl2832.c:587: + 0xf5, 0xff, 0x15, 0x38, 0x5d, 0x6d, 0x52, 0x07, 0xfa, 0x2f, WARNING: line over 80 characters #588: FILE: media/dvb/frontends/rtl2832.c:588: + 0x53, 0xf5, 0x3f, 0xca, 0x0b, 0x91, 0xea, 0x30, 0x63, 0xb2, WARNING: line over 80 characters #589: FILE: media/dvb/frontends/rtl2832.c:589: + 0x13, 0xda, 0x0b, 0xc4, 0x18, 0x7e, 0x16, 0x66, 0x08, 0x67, WARNING: line over 80 characters #595: FILE: media/dvb/frontends/rtl2832.c:595: + 0xe7, 0xcc, 0xb5, 0xba, 0xe8, 0x2f, 0x67, 0x61, 0x00, 0xaf, WARNING: line over 80 characters #596: FILE: media/dvb/frontends/rtl2832.c:596: + 0x86, 0xf2, 0xbf, 0x59, 0x04, 0x11, 0xb6, 0x33, 0xa4, 0x30, WARNING: line over 80 characters #597: FILE: media/dvb/frontends/rtl2832.c:597: + 0x15, 0x10, 0x0a, 0x42, 0x18, 0xf8, 0x17, 0xd9, 0x07, 0x22, WARNING: line over 80 characters #603: FILE: media/dvb/frontends/rtl2832.c:603: + 0x09, 0xf6, 0xd2, 0xa7, 0x9a, 0xc9, 0x27, 0x77, 0x06, 0xbf, WARNING: line over 80 characters #604: FILE: media/dvb/frontends/rtl2832.c:604: + 0xec, 0xf4, 0x4f, 0x0b, 0xfc, 0x01, 0x63, 0x35, 0x54, 0xa7, WARNING: line over 80 characters #605: FILE: media/dvb/frontends/rtl2832.c:605: + 0x16, 0x66, 0x08, 0xb4, 0x19, 0x6e, 0x19, 0x65, 0x05, 0xc8, WARNING: please, no space before tabs #646: FILE: media/dvb/frontends/rtl2832.c:646: +^I* ^I/ ConstWithBandwidthMode)$ WARNING: please, no space before tabs #658: FILE: media/dvb/frontends/rtl2832.c:658: +^I* ^I/ (CrystalFreqHz * 7))$ total: 0 errors, 11 warnings, 1009 lines checked drivers/media/dvb/frontends/rtl2832.c has style problems, please review. If any of these errors are false positives, please report them to the maintainer, see CHECKPATCH in MAINTAINERS. [crope@localhost linux]$ [crope@localhost linux]$ ./scripts/checkpatch.pl --file drivers/media/dvb/frontends/rtl2832_priv.h ERROR: Macros with complex values should be enclosed in parenthesis #30: FILE: media/dvb/frontends/rtl2832_priv.h:30: +#define dbg(f, arg...) \ + if (rtl2832_debug) \ + printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) WARNING: do not add new typedefs #52: FILE: media/dvb/frontends/rtl2832_priv.h:52: +typedef struct { WARNING: do not add new typedefs #60: FILE: media/dvb/frontends/rtl2832_priv.h:60: +typedef struct { total: 1 errors, 2 warnings, 260 lines checked drivers/media/dvb/frontends/rtl2832_priv.h has style problems, please review. If any of these errors are false positives, please report them to the maintainer, see CHECKPATCH in MAINTAINERS. [crope@localhost linux]$ [crope@localhost linux]$ ./scripts/checkpatch.pl --file drivers/media/dvb/frontends/rtl2832.h total: 0 errors, 0 warnings, 81 lines checked drivers/media/dvb/frontends/rtl2832.h has no obvious style problems and is ready for submission. [crope@localhost linux]$ regards Antti -- http://palosaari.fi/ ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/5] rtl2832 ver 0.3: suport for RTL2832 demodulator revised version 2012-05-14 1:37 ` Antti Palosaari 2012-05-14 1:46 ` Antti Palosaari @ 2012-05-15 15:41 ` Antti Palosaari 2012-05-16 5:10 ` poma 2012-05-18 19:16 ` Antti Palosaari 3 siblings, 0 replies; 16+ messages in thread From: Antti Palosaari @ 2012-05-15 15:41 UTC (permalink / raw) To: Thomas Mair; +Cc: linux-media On 14.05.2012 04:37, Antti Palosaari wrote: > On 12.05.2012 21:08, Thomas Mair wrote: >> Changes compared to version 0.2: >> +++ b/drivers/media/dvb/frontends/Makefile >> @@ -98,6 +98,7 @@ obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o >> obj-$(CONFIG_DVB_A8293) += a8293.o >> obj-$(CONFIG_DVB_TDA10071) += tda10071.o >> obj-$(CONFIG_DVB_RTL2830) += rtl2830.o >> +obj-$(CONFIG_DVB_RTL2832) = rtl2832.o >> obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o >> obj-$(CONFIG_DVB_AF9033) += af9033.o I just realized that very bad bug! That prevents compilation of all the other demods than rtl2832. regards Antti -- http://palosaari.fi/ ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/5] rtl2832 ver 0.3: suport for RTL2832 demodulator revised version 2012-05-14 1:37 ` Antti Palosaari 2012-05-14 1:46 ` Antti Palosaari 2012-05-15 15:41 ` Antti Palosaari @ 2012-05-16 5:10 ` poma 2012-05-18 19:16 ` Antti Palosaari 3 siblings, 0 replies; 16+ messages in thread From: poma @ 2012-05-16 5:10 UTC (permalink / raw) To: Antti Palosaari; +Cc: Thomas Mair, linux-media [-- Attachment #1: Type: text/plain, Size: 49489 bytes --] On 05/14/2012 03:37 AM, Antti Palosaari wrote: > On 12.05.2012 21:08, Thomas Mair wrote: >> Changes compared to version 0.2: >> - removed reading of signal strength for tuners FC0012,FC0013 (is now >> supported by fc0012,fc0013 driver) >> - moved definition of register names to rtl2832_priv.h >> - cleaned up demod private structure >> - replaced rtl2832_log2 function with intlog2 from dvb_math >> >> Signed-off-by: Thomas Mair<thomas.mair86@googlemail.com> >> --- >> drivers/media/dvb/frontends/Kconfig | 7 + >> drivers/media/dvb/frontends/Makefile | 1 + >> drivers/media/dvb/frontends/rtl2832.c | 1009 >> ++++++++++++++++++++++++++++ >> drivers/media/dvb/frontends/rtl2832.h | 81 +++ >> drivers/media/dvb/frontends/rtl2832_priv.h | 260 +++++++ >> 5 files changed, 1358 insertions(+), 0 deletions(-) >> create mode 100644 drivers/media/dvb/frontends/rtl2832.c >> create mode 100644 drivers/media/dvb/frontends/rtl2832.h >> create mode 100644 drivers/media/dvb/frontends/rtl2832_priv.h >> >> diff --git a/drivers/media/dvb/frontends/Kconfig >> b/drivers/media/dvb/frontends/Kconfig >> index f479834..f7d67d7 100644 >> --- a/drivers/media/dvb/frontends/Kconfig >> +++ b/drivers/media/dvb/frontends/Kconfig >> @@ -432,6 +432,13 @@ config DVB_RTL2830 >> help >> Say Y when you want to support this frontend. >> >> +config DVB_RTL2832 >> + tristate "Realtek RTL2832 DVB-T" >> + depends on DVB_CORE&& I2C >> + default m if DVB_FE_CUSTOMISE >> + help >> + Say Y when you want to support this frontend. >> + >> comment "DVB-C (cable) frontends" >> depends on DVB_CORE >> >> diff --git a/drivers/media/dvb/frontends/Makefile >> b/drivers/media/dvb/frontends/Makefile >> index b0381dc..9731192 100644 >> --- a/drivers/media/dvb/frontends/Makefile >> +++ b/drivers/media/dvb/frontends/Makefile >> @@ -98,6 +98,7 @@ obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o >> obj-$(CONFIG_DVB_A8293) += a8293.o >> obj-$(CONFIG_DVB_TDA10071) += tda10071.o >> obj-$(CONFIG_DVB_RTL2830) += rtl2830.o >> +obj-$(CONFIG_DVB_RTL2832) = rtl2832.o >> obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o >> obj-$(CONFIG_DVB_AF9033) += af9033.o >> >> diff --git a/drivers/media/dvb/frontends/rtl2832.c >> b/drivers/media/dvb/frontends/rtl2832.c >> new file mode 100644 >> index 0000000..1936c50 >> --- /dev/null >> +++ b/drivers/media/dvb/frontends/rtl2832.c >> @@ -0,0 +1,1009 @@ >> +/* >> + * Realtek RTL2832 DVB-T demodulator driver >> + * >> + * Copyright (C) 2012 Thomas Mair<thomas.mair86@gmail.com> >> + * >> + * This program is free software; you can redistribute it and/or >> modify >> + * it under the terms of the GNU General Public License as >> published by >> + * the Free Software Foundation; either version 2 of the License, or >> + * (at your option) any later version. >> + * >> + * This program is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> + * GNU General Public License for more details. >> + * >> + * You should have received a copy of the GNU General Public >> License along >> + * with this program; if not, write to the Free Software >> Foundation, Inc., >> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >> + */ >> + >> +#include "rtl2832_priv.h" >> +#include "dvb_math.h" >> + >> + >> +int rtl2832_debug; >> +module_param_named(debug, rtl2832_debug, int, 0644); >> +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging >> (default:off)."); >> + >> + >> +static int reg_mask[32] = { >> + 0x00000001, >> + 0x00000003, >> + 0x00000007, >> + 0x0000000f, >> + 0x0000001f, >> + 0x0000003f, >> + 0x0000007f, >> + 0x000000ff, >> + 0x000001ff, >> + 0x000003ff, >> + 0x000007ff, >> + 0x00000fff, >> + 0x00001fff, >> + 0x00003fff, >> + 0x00007fff, >> + 0x0000ffff, >> + 0x0001ffff, >> + 0x0003ffff, >> + 0x0007ffff, >> + 0x000fffff, >> + 0x001fffff, >> + 0x003fffff, >> + 0x007fffff, >> + 0x00ffffff, >> + 0x01ffffff, >> + 0x03ffffff, >> + 0x07ffffff, >> + 0x0fffffff, >> + 0x1fffffff, >> + 0x3fffffff, >> + 0x7fffffff, >> + 0xffffffff > > This looks weird but I don't know which is most correct alternative. > There could be even some macros for the - check kernel bit operations at > the first hand. > > You can consider shifting bits to right in order to get mask. For > example (0xffffffff >> 30) == 0x00000003. > >> +}; >> + >> +static const rtl2832_reg_entry registers[] = { >> + [DVBT_SOFT_RST] = {0x1, 0x1, 2, 2}, >> + [DVBT_IIC_REPEAT] = {0x1, 0x1, 3, 3}, >> + [DVBT_TR_WAIT_MIN_8K] = {0x1, 0x88, 11, 2}, >> + [DVBT_RSD_BER_FAIL_VAL] = {0x1, 0x8f, 15, 0}, >> + [DVBT_EN_BK_TRK] = {0x1, 0xa6, 7, 7}, >> + [DVBT_AD_EN_REG] = {0x0, 0x8, 7, 7}, >> + [DVBT_AD_EN_REG1] = {0x0, 0x8, 6, 6}, >> + [DVBT_EN_BBIN] = {0x1, 0xb1, 0, 0}, >> + [DVBT_MGD_THD0] = {0x1, 0x95, 7, 0}, >> + [DVBT_MGD_THD1] = {0x1, 0x96, 7, 0}, >> + [DVBT_MGD_THD2] = {0x1, 0x97, 7, 0}, >> + [DVBT_MGD_THD3] = {0x1, 0x98, 7, 0}, >> + [DVBT_MGD_THD4] = {0x1, 0x99, 7, 0}, >> + [DVBT_MGD_THD5] = {0x1, 0x9a, 7, 0}, >> + [DVBT_MGD_THD6] = {0x1, 0x9b, 7, 0}, >> + [DVBT_MGD_THD7] = {0x1, 0x9c, 7, 0}, >> + [DVBT_EN_CACQ_NOTCH] = {0x1, 0x61, 4, 4}, >> + [DVBT_AD_AV_REF] = {0x0, 0x9, 6, 0}, >> + [DVBT_REG_PI] = {0x0, 0xa, 2, 0}, >> + [DVBT_PIP_ON] = {0x0, 0x21, 3, 3}, >> + [DVBT_SCALE1_B92] = {0x2, 0x92, 7, 0}, >> + [DVBT_SCALE1_B93] = {0x2, 0x93, 7, 0}, >> + [DVBT_SCALE1_BA7] = {0x2, 0xa7, 7, 0}, >> + [DVBT_SCALE1_BA9] = {0x2, 0xa9, 7, 0}, >> + [DVBT_SCALE1_BAA] = {0x2, 0xaa, 7, 0}, >> + [DVBT_SCALE1_BAB] = {0x2, 0xab, 7, 0}, >> + [DVBT_SCALE1_BAC] = {0x2, 0xac, 7, 0}, >> + [DVBT_SCALE1_BB0] = {0x2, 0xb0, 7, 0}, >> + [DVBT_SCALE1_BB1] = {0x2, 0xb1, 7, 0}, >> + [DVBT_KB_P1] = {0x1, 0x64, 3, 1}, >> + [DVBT_KB_P2] = {0x1, 0x64, 6, 4}, >> + [DVBT_KB_P3] = {0x1, 0x65, 2, 0}, >> + [DVBT_OPT_ADC_IQ] = {0x0, 0x6, 5, 4}, >> + [DVBT_AD_AVI] = {0x0, 0x9, 1, 0}, >> + [DVBT_AD_AVQ] = {0x0, 0x9, 3, 2}, >> + [DVBT_K1_CR_STEP12] = {0x2, 0xad, 9, 4}, >> + [DVBT_TRK_KS_P2] = {0x1, 0x6f, 2, 0}, >> + [DVBT_TRK_KS_I2] = {0x1, 0x70, 5, 3}, >> + [DVBT_TR_THD_SET2] = {0x1, 0x72, 3, 0}, >> + [DVBT_TRK_KC_P2] = {0x1, 0x73, 5, 3}, >> + [DVBT_TRK_KC_I2] = {0x1, 0x75, 2, 0}, >> + [DVBT_CR_THD_SET2] = {0x1, 0x76, 7, 6}, >> + [DVBT_PSET_IFFREQ] = {0x1, 0x19, 21, 0}, >> + [DVBT_SPEC_INV] = {0x1, 0x15, 0, 0}, >> + [DVBT_RSAMP_RATIO] = {0x1, 0x9f, 27, 2}, >> + [DVBT_CFREQ_OFF_RATIO] = {0x1, 0x9d, 23, 4}, >> + [DVBT_FSM_STAGE] = {0x3, 0x51, 6, 3}, >> + [DVBT_RX_CONSTEL] = {0x3, 0x3c, 3, 2}, >> + [DVBT_RX_HIER] = {0x3, 0x3c, 6, 4}, >> + [DVBT_RX_C_RATE_LP] = {0x3, 0x3d, 2, 0}, >> + [DVBT_RX_C_RATE_HP] = {0x3, 0x3d, 5, 3}, >> + [DVBT_GI_IDX] = {0x3, 0x51, 1, 0}, >> + [DVBT_FFT_MODE_IDX] = {0x3, 0x51, 2, 2}, >> + [DVBT_RSD_BER_EST] = {0x3, 0x4e, 15, 0}, >> + [DVBT_CE_EST_EVM] = {0x4, 0xc, 15, 0}, >> + [DVBT_RF_AGC_VAL] = {0x3, 0x5b, 13, 0}, >> + [DVBT_IF_AGC_VAL] = {0x3, 0x59, 13, 0}, >> + [DVBT_DAGC_VAL] = {0x3, 0x5, 7, 0}, >> + [DVBT_SFREQ_OFF] = {0x3, 0x18, 13, 0}, >> + [DVBT_CFREQ_OFF] = {0x3, 0x5f, 17, 0}, >> + [DVBT_POLAR_RF_AGC] = {0x0, 0xe, 1, 1}, >> + [DVBT_POLAR_IF_AGC] = {0x0, 0xe, 0, 0}, >> + [DVBT_AAGC_HOLD] = {0x1, 0x4, 5, 5}, >> + [DVBT_EN_RF_AGC] = {0x1, 0x4, 6, 6}, >> + [DVBT_EN_IF_AGC] = {0x1, 0x4, 7, 7}, >> + [DVBT_IF_AGC_MIN] = {0x1, 0x8, 7, 0}, >> + [DVBT_IF_AGC_MAX] = {0x1, 0x9, 7, 0}, >> + [DVBT_RF_AGC_MIN] = {0x1, 0xa, 7, 0}, >> + [DVBT_RF_AGC_MAX] = {0x1, 0xb, 7, 0}, >> + [DVBT_IF_AGC_MAN] = {0x1, 0xc, 6, 6}, >> + [DVBT_IF_AGC_MAN_VAL] = {0x1, 0xc, 13, 0}, >> + [DVBT_RF_AGC_MAN] = {0x1, 0xe, 6, 6}, >> + [DVBT_RF_AGC_MAN_VAL] = {0x1, 0xe, 13, 0}, >> + [DVBT_DAGC_TRG_VAL] = {0x1, 0x12, 7, 0}, >> + [DVBT_AGC_TARG_VAL_0] = {0x1, 0x2, 0, 0}, >> + [DVBT_AGC_TARG_VAL_8_1] = {0x1, 0x3, 7, 0}, >> + [DVBT_AAGC_LOOP_GAIN] = {0x1, 0xc7, 5, 1}, >> + [DVBT_LOOP_GAIN2_3_0] = {0x1, 0x4, 4, 1}, >> + [DVBT_LOOP_GAIN2_4] = {0x1, 0x5, 7, 7}, >> + [DVBT_LOOP_GAIN3] = {0x1, 0xc8, 4, 0}, >> + [DVBT_VTOP1] = {0x1, 0x6, 5, 0}, >> + [DVBT_VTOP2] = {0x1, 0xc9, 5, 0}, >> + [DVBT_VTOP3] = {0x1, 0xca, 5, 0}, >> + [DVBT_KRF1] = {0x1, 0xcb, 7, 0}, >> + [DVBT_KRF2] = {0x1, 0x7, 7, 0}, >> + [DVBT_KRF3] = {0x1, 0xcd, 7, 0}, >> + [DVBT_KRF4] = {0x1, 0xce, 7, 0}, >> + [DVBT_EN_GI_PGA] = {0x1, 0xe5, 0, 0}, >> + [DVBT_THD_LOCK_UP] = {0x1, 0xd9, 8, 0}, >> + [DVBT_THD_LOCK_DW] = {0x1, 0xdb, 8, 0}, >> + [DVBT_THD_UP1] = {0x1, 0xdd, 7, 0}, >> + [DVBT_THD_DW1] = {0x1, 0xde, 7, 0}, >> + [DVBT_INTER_CNT_LEN] = {0x1, 0xd8, 3, 0}, >> + [DVBT_GI_PGA_STATE] = {0x1, 0xe6, 3, 3}, >> + [DVBT_EN_AGC_PGA] = {0x1, 0xd7, 0, 0}, >> + [DVBT_CKOUTPAR] = {0x1, 0x7b, 5, 5}, >> + [DVBT_CKOUT_PWR] = {0x1, 0x7b, 6, 6}, >> + [DVBT_SYNC_DUR] = {0x1, 0x7b, 7, 7}, >> + [DVBT_ERR_DUR] = {0x1, 0x7c, 0, 0}, >> + [DVBT_SYNC_LVL] = {0x1, 0x7c, 1, 1}, >> + [DVBT_ERR_LVL] = {0x1, 0x7c, 2, 2}, >> + [DVBT_VAL_LVL] = {0x1, 0x7c, 3, 3}, >> + [DVBT_SERIAL] = {0x1, 0x7c, 4, 4}, >> + [DVBT_SER_LSB] = {0x1, 0x7c, 5, 5}, >> + [DVBT_CDIV_PH0] = {0x1, 0x7d, 3, 0}, >> + [DVBT_CDIV_PH1] = {0x1, 0x7d, 7, 4}, >> + [DVBT_MPEG_IO_OPT_2_2] = {0x0, 0x6, 7, 7}, >> + [DVBT_MPEG_IO_OPT_1_0] = {0x0, 0x7, 7, 6}, >> + [DVBT_CKOUTPAR_PIP] = {0x0, 0xb7, 4, 4}, >> + [DVBT_CKOUT_PWR_PIP] = {0x0, 0xb7, 3, 3}, >> + [DVBT_SYNC_LVL_PIP] = {0x0, 0xb7, 2, 2}, >> + [DVBT_ERR_LVL_PIP] = {0x0, 0xb7, 1, 1}, >> + [DVBT_VAL_LVL_PIP] = {0x0, 0xb7, 0, 0}, >> + [DVBT_CKOUTPAR_PID] = {0x0, 0xb9, 4, 4}, >> + [DVBT_CKOUT_PWR_PID] = {0x0, 0xb9, 3, 3}, >> + [DVBT_SYNC_LVL_PID] = {0x0, 0xb9, 2, 2}, >> + [DVBT_ERR_LVL_PID] = {0x0, 0xb9, 1, 1}, >> + [DVBT_VAL_LVL_PID] = {0x0, 0xb9, 0, 0}, >> + [DVBT_SM_PASS] = {0x1, 0x93, 11, 0}, >> + [DVBT_AD7_SETTING] = {0x0, 0x11, 15, 0}, >> + [DVBT_RSSI_R] = {0x3, 0x1, 6, 0}, >> + [DVBT_ACI_DET_IND] = {0x3, 0x12, 0, 0}, >> + [DVBT_REG_MON] = {0x0, 0xd, 1, 0}, >> + [DVBT_REG_MONSEL] = {0x0, 0xd, 2, 2}, >> + [DVBT_REG_GPE] = {0x0, 0xd, 7, 7}, >> + [DVBT_REG_GPO] = {0x0, 0x10, 0, 0}, >> + [DVBT_REG_4MSEL] = {0x0, 0x13, 0, 0}, > > I recommend for intending values too. So that all values in a same "row" > can be easily compared. > >> +}; >> + >> +/* write multiple hardware registers */ >> +static int rtl2832_wr(struct rtl2832_priv *priv, u8 reg, u8 *val, int >> len) >> +{ >> + int ret; >> + u8 buf[1+len]; >> + struct i2c_msg msg[1] = { >> + { >> + .addr = priv->cfg.i2c_addr, >> + .flags = 0, >> + .len = 1+len, >> + .buf = buf, >> + } >> + }; >> + >> + buf[0] = reg; >> + memcpy(&buf[1], val, len); >> + >> + ret = i2c_transfer(priv->i2c, msg, 1); >> + if (ret == 1) { >> + ret = 0; >> + } else { >> + warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len); >> + ret = -EREMOTEIO; >> + } >> + return ret; >> +} >> + >> +/* read multiple hardware registers */ >> +static int rtl2832_rd(struct rtl2832_priv *priv, u8 reg, u8 *val, int >> len) >> +{ >> + int ret; >> + struct i2c_msg msg[2] = { >> + { >> + .addr = priv->cfg.i2c_addr, >> + .flags = 0, >> + .len = 1, >> + .buf =®, >> + }, { >> + .addr = priv->cfg.i2c_addr, >> + .flags = I2C_M_RD, >> + .len = len, >> + .buf = val, >> + } >> + }; >> + >> + ret = i2c_transfer(priv->i2c, msg, 2); >> + if (ret == 2) { >> + ret = 0; >> + } else { >> + warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len); >> + ret = -EREMOTEIO; >> +} >> +return ret; >> +} >> + >> +/* write multiple registers */ >> +static int rtl2832_wr_regs(struct rtl2832_priv *priv, u8 reg, u8 >> page, u8 *val, >> + int len) >> +{ >> + int ret; >> + >> + >> + /* switch bank if needed */ >> + if (page != priv->page) { >> + ret = rtl2832_wr(priv, 0x00,&page, 1); >> + if (ret) >> + return ret; >> + >> + priv->page = page; >> +} >> + >> +return rtl2832_wr(priv, reg, val, len); >> +} >> + >> +/* read multiple registers */ >> +static int rtl2832_rd_regs(struct rtl2832_priv *priv, u8 reg, u8 >> page, u8 *val, >> + int len) >> +{ >> + int ret; >> + >> + /* switch bank if needed */ >> + if (page != priv->page) { >> + ret = rtl2832_wr(priv, 0x00,&page, 1); >> + if (ret) >> + return ret; >> + >> + priv->page = page; >> + } >> + >> + return rtl2832_rd(priv, reg, val, len); >> +} >> + >> +#if 0 /* currently not used */ >> +/* write single register */ >> +static int rtl2832_wr_reg(struct rtl2832_priv *priv, u8 reg, u8 page, >> u8 val) >> +{ >> + return rtl2832_wr_regs(priv, reg, page,&val, 1); >> +} >> +#endif >> + >> +/* read single register */ >> +static int rtl2832_rd_reg(struct rtl2832_priv *priv, u8 reg, u8 page, >> u8 *val) >> +{ >> + return rtl2832_rd_regs(priv, reg, page, val, 1); >> +} >> + >> +int rtl2832_rd_demod_reg(struct rtl2832_priv *priv, int reg, u32 *val) >> +{ >> + int ret; >> + >> + u8 reg_start_addr; >> + u8 msb, lsb; >> + u8 page; >> + u8 reading[4]; >> + u32 reading_tmp; >> + int i; >> + >> + u8 len; >> + u32 mask; >> + >> + reg_start_addr = registers[reg].start_address; >> + msb = registers[reg].msb; >> + lsb = registers[reg].lsb; >> + page = registers[reg].page; >> + >> + len = (msb>> 3) + 1; >> + mask = reg_mask[msb-lsb]; >> + >> + >> + ret = rtl2832_rd_regs(priv, reg_start_addr, page,&reading[0], len); >> + if (ret) >> + goto err; >> + >> + reading_tmp = 0; >> + for (i = 0; i< len; i++) >> + reading_tmp |= reading[i]<< ((len-1-i)*8); >> + >> + *val = (reading_tmp>> lsb)& mask; >> + >> + return ret; >> + >> +err: >> + return ret; > > excessive return > >> + >> +} >> + >> +int rtl2832_wr_demod_reg(struct rtl2832_priv *priv, int reg, u32 val) >> +{ >> + int ret, i; >> + u8 len; >> + u8 reg_start_addr; >> + u8 msb, lsb; >> + u8 page; >> + u32 mask; >> + >> + >> + u8 reading[4]; >> + u8 writing[4]; >> + u32 reading_tmp; >> + u32 writing_tmp; >> + >> + >> + reg_start_addr = registers[reg].start_address; >> + msb = registers[reg].msb; >> + lsb = registers[reg].lsb; >> + page = registers[reg].page; >> + >> + len = (msb>> 3) + 1; >> + mask = reg_mask[msb-lsb]; >> + >> + >> + ret = rtl2832_rd_regs(priv, reg_start_addr, page,&reading[0], len); >> + if (ret) >> + goto err; >> + >> + reading_tmp = 0; >> + for (i = 0; i< len; i++) >> + reading_tmp |= reading[i]<< ((len-1-i)*8); >> + >> + writing_tmp = reading_tmp& ~(mask<< lsb); >> + writing_tmp |= ((val& mask)<< lsb); >> + >> + >> + for (i = 0; i< len; i++) >> + writing[i] = (writing_tmp>> ((len-1-i)*8))& 0xff; >> + >> + ret = rtl2832_wr_regs(priv, reg_start_addr, page,&writing[0], len); >> + if (ret) >> + goto err; >> + >> + return ret; >> + >> +err: >> + return ret; > > excessive return > >> + >> +} >> + >> + >> +static int rtl2832_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) >> +{ >> + int ret; >> + struct rtl2832_priv *priv = fe->demodulator_priv; >> + >> + dbg("%s: enable=%d", __func__, enable); >> + >> + /* gate already open or close */ >> + if (priv->i2c_gate_state == enable) >> + return 0; >> + >> + ret = rtl2832_wr_demod_reg(priv, DVBT_IIC_REPEAT, (enable ? 0x1 : >> 0x0)); >> + >> + if (ret) >> + goto err; >> + >> + priv->i2c_gate_state = enable; >> + >> + return ret; >> +err: >> + dbg("%s: failed=%d", __func__, ret); >> + return ret; >> +} >> + >> + >> + >> +static int rtl2832_init(struct dvb_frontend *fe) >> +{ >> + struct rtl2832_priv *priv = fe->demodulator_priv; >> + int i, ret; >> + >> + u8 en_bbin; >> + u64 pset_iffreq; >> + >> + /* initialization values for the demodulator registers */ >> + static rtl2832_reg_value rtl2832_initial_regs_1[] = { >> + {DVBT_AD_EN_REG, 0x1}, >> + {DVBT_AD_EN_REG1, 0x1}, >> + {DVBT_RSD_BER_FAIL_VAL, 0x2800}, >> + {DVBT_MGD_THD0, 0x10}, >> + {DVBT_MGD_THD1, 0x20}, >> + {DVBT_MGD_THD2, 0x20}, >> + {DVBT_MGD_THD3, 0x40}, >> + {DVBT_MGD_THD4, 0x22}, >> + {DVBT_MGD_THD5, 0x32}, >> + {DVBT_MGD_THD6, 0x37}, >> + {DVBT_MGD_THD7, 0x39}, >> + {DVBT_EN_BK_TRK, 0x0}, >> + {DVBT_EN_CACQ_NOTCH, 0x0}, >> + {DVBT_AD_AV_REF, 0x2a}, >> + {DVBT_REG_PI, 0x6}, >> + {DVBT_PIP_ON, 0x0}, >> + {DVBT_CDIV_PH0, 0x8}, >> + {DVBT_CDIV_PH1, 0x8}, >> + {DVBT_SCALE1_B92, 0x4}, >> + {DVBT_SCALE1_B93, 0xb0}, >> + {DVBT_SCALE1_BA7, 0x78}, >> + {DVBT_SCALE1_BA9, 0x28}, >> + {DVBT_SCALE1_BAA, 0x59}, >> + {DVBT_SCALE1_BAB, 0x83}, >> + {DVBT_SCALE1_BAC, 0xd4}, >> + {DVBT_SCALE1_BB0, 0x65}, >> + {DVBT_SCALE1_BB1, 0x43}, >> + {DVBT_KB_P1, 0x1}, >> + {DVBT_KB_P2, 0x4}, >> + {DVBT_KB_P3, 0x7}, >> + {DVBT_K1_CR_STEP12, 0xa}, >> + {DVBT_REG_GPE, 0x1}, >> + {DVBT_SERIAL, 0x0}, >> + {DVBT_CDIV_PH0, 0x9}, >> + {DVBT_CDIV_PH1, 0x9}, >> + {DVBT_MPEG_IO_OPT_2_2, 0x0}, >> + {DVBT_MPEG_IO_OPT_1_0, 0x0}, >> + {DVBT_TRK_KS_P2, 0x4}, >> + {DVBT_TRK_KS_I2, 0x7}, >> + {DVBT_TR_THD_SET2, 0x6}, >> + {DVBT_TRK_KC_I2, 0x5}, >> + {DVBT_CR_THD_SET2, 0x1}, >> + >> + >> + }; >> + >> + static rtl2832_reg_value rtl2832_initial_regs_2[] = { >> + {DVBT_SPEC_INV, 0x0}, >> + {DVBT_DAGC_TRG_VAL, 0x5a}, >> + {DVBT_AGC_TARG_VAL_0, 0x0}, >> + {DVBT_AGC_TARG_VAL_8_1, 0x5a}, >> + {DVBT_AAGC_LOOP_GAIN, 0x16}, >> + {DVBT_LOOP_GAIN2_3_0, 0x6}, >> + {DVBT_LOOP_GAIN2_4, 0x1}, >> + {DVBT_LOOP_GAIN3, 0x16}, >> + {DVBT_VTOP1, 0x35}, >> + {DVBT_VTOP2, 0x21}, >> + {DVBT_VTOP3, 0x21}, >> + {DVBT_KRF1, 0x0}, >> + {DVBT_KRF2, 0x40}, >> + {DVBT_KRF3, 0x10}, >> + {DVBT_KRF4, 0x10}, >> + {DVBT_IF_AGC_MIN, 0x80}, >> + {DVBT_IF_AGC_MAX, 0x7f}, >> + {DVBT_RF_AGC_MIN, 0x80}, >> + {DVBT_RF_AGC_MAX, 0x7f}, >> + {DVBT_POLAR_RF_AGC, 0x0}, >> + {DVBT_POLAR_IF_AGC, 0x0}, >> + {DVBT_AD7_SETTING, 0xe9bf}, >> + {DVBT_EN_GI_PGA, 0x0}, >> + {DVBT_THD_LOCK_UP, 0x0}, >> + {DVBT_THD_LOCK_DW, 0x0}, >> + {DVBT_THD_UP1, 0x11}, >> + {DVBT_THD_DW1, 0xef}, >> + {DVBT_INTER_CNT_LEN, 0xc}, >> + {DVBT_GI_PGA_STATE, 0x0}, >> + {DVBT_EN_AGC_PGA, 0x1}, >> + {DVBT_IF_AGC_MAN, 0x0}, >> + }; > > Maybe you can check indention here too. Kernel indention is 1 tab == 8 > spaces wide. Check your editor has correct settings. > >> + >> + >> + dbg("%s", __func__); >> + >> + en_bbin = (priv->cfg.if_dvbt == 0 ? 0x1 : 0x0); >> + >> + /* >> + * PSET_IFFREQ = - floor((IfFreqHz % CrystalFreqHz) * pow(2, 22) >> + * / CrystalFreqHz) >> + */ >> + pset_iffreq = priv->cfg.if_dvbt % priv->cfg.xtal; >> + pset_iffreq *= 0x400000; >> + pset_iffreq = div_u64(pset_iffreq, priv->cfg.xtal); >> + pset_iffreq = pset_iffreq& 0x3fffff; >> + >> + >> + >> + for (i = 0; i< 42; i++) { > > You should use ARRAY_SIZE() likely here or some other macro. > >> + ret = rtl2832_wr_demod_reg(priv, rtl2832_initial_regs_1[i].reg, >> + rtl2832_initial_regs_1[i].value); >> + if (ret) >> + goto err; >> + } >> + >> + /* if frequency settings */ >> + ret = rtl2832_wr_demod_reg(priv, DVBT_EN_BBIN, en_bbin); >> + if (ret) >> + goto err; >> + >> + ret = rtl2832_wr_demod_reg(priv, DVBT_PSET_IFFREQ, pset_iffreq); >> + if (ret) >> + goto err; >> + >> + for (i = 0; i< 31; i++) { > > ARRAY_SIZE() > >> + ret = rtl2832_wr_demod_reg(priv, rtl2832_initial_regs_2[i].reg, >> + rtl2832_initial_regs_2[i].value); >> + if (ret) >> + goto err; > > What is the reason behind you have split inittab as a two parts? > >> + } >> + >> + priv->sleeping = false; >> + >> + return ret; >> + >> +err: >> + return ret; > > excessive return > >> +} >> + >> +static int rtl2832_sleep(struct dvb_frontend *fe) >> +{ >> + struct rtl2832_priv *priv = fe->demodulator_priv; >> + >> + dbg("%s", __func__); >> + priv->sleeping = true; >> + return 0; >> +} >> + >> +int rtl2832_get_tune_settings(struct dvb_frontend *fe, >> + struct dvb_frontend_tune_settings *s) >> +{ >> + dbg("%s", __func__); >> + s->min_delay_ms = 1000; >> + s->step_size = fe->ops.info.frequency_stepsize * 2; >> + s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; >> + return 0; >> +} >> + >> +static int rtl2832_set_frontend(struct dvb_frontend *fe) >> +{ >> + struct rtl2832_priv *priv = fe->demodulator_priv; >> + struct dtv_frontend_properties *c =&fe->dtv_property_cache; >> + int ret, i, j; >> + u64 bw_mode, num, num2; >> + u32 resamp_ratio, cfreq_off_ratio; >> + >> + >> + static u8 bw_params[3][32] = { >> + /* 6 MHz bandwidth */ >> + { >> + 0xf5, 0xff, 0x15, 0x38, 0x5d, 0x6d, 0x52, 0x07, 0xfa, 0x2f, >> + 0x53, 0xf5, 0x3f, 0xca, 0x0b, 0x91, 0xea, 0x30, 0x63, 0xb2, >> + 0x13, 0xda, 0x0b, 0xc4, 0x18, 0x7e, 0x16, 0x66, 0x08, 0x67, >> + 0x19, 0xe0, >> + }, >> + >> + /* 7 MHz bandwidth */ >> + { >> + 0xe7, 0xcc, 0xb5, 0xba, 0xe8, 0x2f, 0x67, 0x61, 0x00, 0xaf, >> + 0x86, 0xf2, 0xbf, 0x59, 0x04, 0x11, 0xb6, 0x33, 0xa4, 0x30, >> + 0x15, 0x10, 0x0a, 0x42, 0x18, 0xf8, 0x17, 0xd9, 0x07, 0x22, >> + 0x19, 0x10, >> + }, >> + >> + /* 8 MHz bandwidth */ >> + { >> + 0x09, 0xf6, 0xd2, 0xa7, 0x9a, 0xc9, 0x27, 0x77, 0x06, 0xbf, >> + 0xec, 0xf4, 0x4f, 0x0b, 0xfc, 0x01, 0x63, 0x35, 0x54, 0xa7, >> + 0x16, 0x66, 0x08, 0xb4, 0x19, 0x6e, 0x19, 0x65, 0x05, 0xc8, >> + 0x19, 0xe0, >> + }, >> + }; >> + >> + >> + dbg("%s: frequency=%d bandwidth_hz=%d inversion=%d", __func__, >> + c->frequency, c->bandwidth_hz, c->inversion); >> + >> + >> + /* program tuner */ >> + if (fe->ops.tuner_ops.set_params) >> + fe->ops.tuner_ops.set_params(fe); >> + >> + >> + switch (c->bandwidth_hz) { >> + case 6000000: >> + i = 0; >> + bw_mode = 48000000; >> + break; >> + case 7000000: >> + i = 1; >> + bw_mode = 56000000; >> + break; >> + case 8000000: >> + i = 2; >> + bw_mode = 64000000; >> + break; >> + default: >> + dbg("invalid bandwidth"); >> + return -EINVAL; >> + } >> + >> + for (j = 0; j< 32; j++) { > > use sizeof() here > >> + ret = rtl2832_wr_regs(priv, 0x1c+j, 1,&bw_params[i][j], 1); >> + if (ret) >> + goto err; >> + } >> + >> + /* calculate and set resample ratio >> + * RSAMP_RATIO = floor(CrystalFreqHz * 7 * pow(2, 22) >> + * / ConstWithBandwidthMode) >> + */ >> + num = priv->cfg.xtal * 7; >> + num *= 0x400000; >> + num = div_u64(num, bw_mode); >> + resamp_ratio = num& 0x3ffffff; >> + ret = rtl2832_wr_demod_reg(priv, DVBT_RSAMP_RATIO, resamp_ratio); >> + if (ret) >> + goto err; >> + >> + /* calculate and set cfreq off ratio >> + * CFREQ_OFF_RATIO = - floor(ConstWithBandwidthMode * pow(2, 20) >> + * / (CrystalFreqHz * 7)) >> + */ >> + num = bw_mode<< 20; >> + num2 = priv->cfg.xtal * 7; >> + num = div_u64(num, num2); >> + num = -num; >> + cfreq_off_ratio = num& 0xfffff; >> + ret = rtl2832_wr_demod_reg(priv, DVBT_CFREQ_OFF_RATIO, >> cfreq_off_ratio); >> + if (ret) >> + goto err; >> + >> + >> + /* soft reset */ >> + ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x1); >> + if (ret) >> + goto err; >> + >> + ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x0); >> + if (ret) >> + goto err; >> + >> + return ret; >> +err: >> + info("%s: failed=%d", __func__, ret); >> + return ret; >> +} >> + >> +static int rtl2832_read_status(struct dvb_frontend *fe, fe_status_t >> *status) >> +{ >> + struct rtl2832_priv *priv = fe->demodulator_priv; >> + int ret; >> + u32 tmp; >> + *status = 0; >> + >> + >> + dbg("%s", __func__); >> + if (priv->sleeping) >> + return 0; >> + >> + ret = rtl2832_rd_demod_reg(priv, DVBT_FSM_STAGE,&tmp); >> + if (ret) >> + goto err; >> + >> + if (tmp == 11) { >> + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | >> + FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; >> + } >> + /* TODO find out if this is also true for rtl2832? */ >> + /*else if (tmp == 10) { >> + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | >> + FE_HAS_VITERBI; >> + }*/ >> + >> + return ret; >> +err: >> + info("%s: failed=%d", __func__, ret); >> + return ret; >> +} >> + >> + >> +#define RTL2832_CE_EST_EVM_MAX_VALUE 65535 >> +#define RTL2832_SNR_FRAC_BIT_NUM 10 >> +#define RTL2832_SNR_DB_DEN 3402 >> + >> +static int rtl2832_read_snr(struct dvb_frontend *fe, u16 *snr) >> +{ >> + struct rtl2832_priv *priv = fe->demodulator_priv; >> + int ret; >> + u64 num; >> + u32 ce_est_evm, fsm_stage, constellation, hierarchy; >> + >> + /* Calculated by: 10 * log2(Norm * pow(2, 11)) * pow(2, 10) */ >> + static const long SnrDbNum[3][4] = { > > These numbers fits surely smaller space than a long. > >> + {122880, 122880, 122880, 122880, }, >> + {146657, 146657, 156897, 171013, }, >> + {167857, 167857, 173127, 181810, }, >> + }; >> + >> + static const int snrMaxDb[3] = { 23, 26, 29, }; > > and same here. Wasting few bytes of memory. > > And for both of those lastly mentioned : those are against naming rules. > See naming rules from the Kernel documentation (or just rename style > snr_max_db). > >> + >> + dbg("%s", __func__); >> + >> + /* get FSM Stage */ >> + ret = rtl2832_rd_demod_reg(priv, DVBT_FSM_STAGE,&fsm_stage); >> + if (ret) >> + goto err; >> + >> + if (fsm_stage< 10) { >> + ce_est_evm = RTL2832_CE_EST_EVM_MAX_VALUE; >> + } else { >> + ret = rtl2832_rd_demod_reg(priv, DVBT_CE_EST_EVM,&ce_est_evm); >> + if (ret) >> + goto err; >> + } >> + >> + /* get constellation */ >> + ret = rtl2832_rd_demod_reg(priv, DVBT_RX_CONSTEL,&constellation); >> + if (ret) >> + goto err; >> + if (constellation> 2) >> + goto err; >> + >> + /* get hierarchy */ >> + ret = rtl2832_rd_demod_reg(priv, DVBT_RX_HIER,&hierarchy); >> + if (ret) >> + goto err; >> + if (hierarchy> 3) >> + goto err; >> + >> + >> + /* >> + SNR dB formula >> + Original formula: SNR_dB = 10 * log10(Norm * pow(2, 11) / CeEstEvm) >> + Adjusted formula: SNR_dB = (SNR_DB_NUM_CONST - 10 * >> log2(CeEstEvm) * >> + pow(2, 10)) / SNR_DB_DEN >> + SNR_DB_NUM_CONST = 10 * log2(Norm * pow(2, 11)) * >> + pow(2, 10) >> + SNR_DB_DEN = log2(10) * pow(2, 10) = 3402 = 0xd4a >> + Norm: >> + None Alpha=1 Alpha=2 Alpha=4 >> + 4-QAM 2 2 2 2 >> + 16-QAM 10 10 20 52 >> + 64-QAM 42 42 60 108 >> + */ >> + >> + /* intlog2 returns log2(x)<< 24 */ >> + num = intlog2(ce_est_evm)>>14; >> + num = SnrDbNum[constellation][hierarchy] - 10 * num; >> + >> + num = div_u64(num, RTL2832_SNR_DB_DEN); >> + num *= 0xffff; >> + num = div_u64(num, snrMaxDb[constellation]); >> + >> + if (num> 0xffff) >> + *snr = 0xffff; >> + else if (num< 0) >> + *snr = 0; >> + else >> + *snr = 0xffff& num; > > This is implemented stupidly. num has type u64 *unsigned 64 bit*. Checks > like that are mostly useless. If you think it twice you can understand > it will never go to the else if (). Also dropping upper bits starting > from the 0xffff (else branch) is useless as you have compared it cannot > be such big value at the first if(). > >> + >> + return ret; >> + >> +err: >> + info("%s: failed=%d", __func__, ret); >> + return ret; >> +} > > Afer some testing I saw this does not work. It returns some crazy numers > all the time like "b960" => 4745.6 dB uh. Not possible at all. > > That driver: > status 1f | signal 2f2f | snr b960 | ber 00000000 | unc 00000064 | > FE_HAS_LOCK > AF9033 driver: > status 1f | signal 68f5 | snr 0122 | ber 00000000 | unc 00000000 | > FE_HAS_LOCK > > All(?) statistics are quite broken in mean of returned values. > > >> + >> +static int rtl2832_read_ber(struct dvb_frontend *fe, u32 *ber) >> +{ >> + struct rtl2832_priv *priv = fe->demodulator_priv; >> + int ret; >> + u32 tmp; >> + >> + dbg("%s", __func__); >> + >> + /* get BER */ >> + ret = rtl2832_rd_demod_reg(priv, DVBT_RSD_BER_EST,&tmp); >> + if (ret) >> + goto err; >> + >> + *ber = tmp; >> + return ret; >> + >> +err: >> + info("%s: failed=%d", __func__, ret); >> + *ber = 19616; > > 19616?? what are those magic numbers... it is error situation that > should never happen (but happens likely when called during sleep). > Leaving *ber untouched in that kind of error situation is just good > choise. Caller surely will not look returned value when error status is > returned. > >> + return ret; >> +} >> + >> +static int rtl2832_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) >> +{ >> + struct rtl2832_priv *priv = fe->demodulator_priv; >> + int ret; >> + u32 tmp; >> + u16 num; >> + >> + dbg("%s", __func__); >> + >> + >> + /* get FSM Stage */ >> + ret = rtl2832_rd_demod_reg(priv, DVBT_FSM_STAGE,&tmp); >> + if (ret) >> + goto err; >> + >> + /* if signal is not locked quality is zero */ >> + if (tmp< 10) { >> + *ucblocks = 0; >> + return 0; >> + } >> + >> + /* get BER */ >> + ret = rtl2832_rd_demod_reg(priv, DVBT_RSD_BER_EST,&tmp); >> + if (ret) >> + goto err; >> + >> + /* >> + Determine signal quality according to RSD_BER_EST. >> + Note: Map RSD_BER_EST value 8192 ~ 128 to 10 ~ 100 >> + Original formula: SignalQuality = 205 - 15 * log2(RSD_BER_EST) >> + Adjusted formula: SignalQuality = ((205<< 5) - 15 * >> + (log2(RSD_BER_EST)<< 5))>> 5 >> + If RSD_BER_EST> 8192, signal quality is 10. >> + If RSD_BER_EST< 128, signal quality is 100. >> + */ >> + >> + if (tmp> 8192) >> + *ucblocks = 10; >> + else if (tmp< 128) >> + *ucblocks = 100; >> + else { >> + num = intlog2(tmp)>> 19; >> + *ucblocks = ((205<< 5) - 15 * num)>> 5; >> + } >> + >> + return 0; >> + >> +err: >> + info("%s: failed=%d", __func__, ret); >> + *ucblocks = 0; > > Same here. If it returns error status then returned values are not valid > in any way. > >> + return ret; >> +} > > I have strong feeling whole callback is totally wrong. Looks like you > are calculating signal quality - not bit error rate as should. Signal > quality is likely same as SNR - or SNR is way to measure signal quality. > But BER is quite much different. > > And thats why it reports always for me 0x64 == 100. > >> + >> + >> +static int rtl2832_read_signal_strength(struct dvb_frontend *fe, u16 >> *strength) >> +{ >> + struct rtl2832_priv *priv = fe->demodulator_priv; >> + int ret, if_agc; >> + u32 fsm_stage, if_agc_raw; >> + >> + dbg("%s", __func__); >> + >> + ret = rtl2832_rd_demod_reg(priv, DVBT_FSM_STAGE,&fsm_stage); >> + if (ret) >> + goto err; > > oops, indentation > >> + >> + if (fsm_stage< 10) >> + *strength = 0; > indentation > >> + else { >> + /* if_agc is read as a 10bit binary */ >> + ret = rtl2832_rd_demod_reg(priv, DVBT_IF_AGC_VAL,&if_agc_raw); >> + if (ret) >> + goto err; >> + >> + if (if_agc_raw< (1<< 9)) >> + if_agc = if_agc_raw; >> + else >> + if_agc = -(~(if_agc_raw-1)& 0x1ff); >> + >> + *strength = 55 - if_agc / 182; >> + *strength |= *strength<< 8; > > That calculation shows doubtful. Why not to scale directly to the > counter. Now you divide it by 182 and after that multiply 256 (<< 8 > means same as multiply by 256). It is stupid calculation. > >> + } >> + return 0; >> +err: >> + info("%s: failed=%d", __func__, ret); >> + return ret; >> +} >> + >> +static struct dvb_frontend_ops rtl2832_ops; >> + >> +static void rtl2832_release(struct dvb_frontend *fe) >> +{ >> + struct rtl2832_priv *priv = fe->demodulator_priv; >> + >> + dbg("%s", __func__); >> + kfree(priv); >> +} >> + >> +struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg, >> + struct i2c_adapter *i2c) >> +{ >> + struct rtl2832_priv *priv = NULL; >> + int ret = 0; >> + u8 tmp; >> + >> + dbg("%s", __func__); >> + >> + /* allocate memory for the internal state */ >> + priv = kzalloc(sizeof(struct rtl2832_priv), GFP_KERNEL); >> + if (priv == NULL) >> + goto err; >> + >> + /* setup the priv */ >> + priv->i2c = i2c; >> + priv->tuner = cfg->tuner; >> + memcpy(&priv->cfg, cfg, sizeof(struct rtl2832_config)); >> + >> + /* check if the demod is there */ >> + ret = rtl2832_rd_reg(priv, 0x00, 0x0,&tmp); >> + if (ret) >> + goto err; >> + >> + /* create dvb_frontend */ >> + memcpy(&priv->fe.ops,&rtl2832_ops, sizeof(struct dvb_frontend_ops)); >> + priv->fe.demodulator_priv = priv; >> + >> + /* TODO implement sleep mode depending on RC */ >> + priv->sleeping = true; > > Demod sleep does not have nothing to do with remote AFAIK. Wrong comment? > >> + >> + return&priv->fe; >> +err: >> + dbg("%s: failed=%d", __func__, ret); >> + kfree(priv); >> + return NULL; >> +} >> +EXPORT_SYMBOL(rtl2832_attach); >> + >> +static struct dvb_frontend_ops rtl2832_ops = { >> + .delsys = { SYS_DVBT }, >> + .info = { >> + .name = "Realtek RTL2832 (DVB-T)", >> + .type = FE_OFDM, > > .type is no longer used as there is .delsys so remove it. > I wonder why it even exists struct dvb_frontend_ops... > >> + .frequency_min = 50000000, > > Smallest DVB-T frequency is ~174MHz. 50MHz is for DVB-C... > >> + .frequency_max = 862000000, >> + .frequency_stepsize = 166667, >> + .caps = FE_CAN_FEC_1_2 | >> + FE_CAN_FEC_2_3 | >> + FE_CAN_FEC_3_4 | >> + FE_CAN_FEC_5_6 | >> + FE_CAN_FEC_7_8 | >> + FE_CAN_FEC_AUTO | >> + FE_CAN_QPSK | >> + FE_CAN_QAM_16 | >> + FE_CAN_QAM_64 | >> + FE_CAN_QAM_AUTO | >> + FE_CAN_TRANSMISSION_MODE_AUTO | >> + FE_CAN_GUARD_INTERVAL_AUTO | >> + FE_CAN_HIERARCHY_AUTO | >> + FE_CAN_RECOVER | >> + FE_CAN_MUTE_TS >> + }, >> + >> + .release = rtl2832_release, >> + >> + .init = rtl2832_init, >> + .sleep = rtl2832_sleep, >> + >> + .get_tune_settings = rtl2832_get_tune_settings, >> + >> + .set_frontend = rtl2832_set_frontend, >> + >> + .read_status = rtl2832_read_status, >> + .read_snr = rtl2832_read_snr, >> + .read_ber = rtl2832_read_ber, >> + .read_ucblocks = rtl2832_read_ucblocks, >> + .read_signal_strength = rtl2832_read_signal_strength, >> + .i2c_gate_ctrl = rtl2832_i2c_gate_ctrl, >> +}; >> + >> +MODULE_AUTHOR("Thomas Mair<mair.thomas86@gmail.com>"); >> +MODULE_DESCRIPTION("Realtek RTL2832 DVB-T demodulator driver"); >> +MODULE_LICENSE("GPL"); >> +MODULE_VERSION("0.3"); >> diff --git a/drivers/media/dvb/frontends/rtl2832.h >> b/drivers/media/dvb/frontends/rtl2832.h >> new file mode 100644 >> index 0000000..6918010 >> --- /dev/null >> +++ b/drivers/media/dvb/frontends/rtl2832.h >> @@ -0,0 +1,81 @@ >> +/* >> + * Realtek RTL2832 DVB-T demodulator driver >> + * >> + * Copyright (C) 2012 Thomas Mair<thomas.mair86@gmail.com> >> + * >> + * This program is free software; you can redistribute it and/or >> modify >> + * it under the terms of the GNU General Public License as >> published by >> + * the Free Software Foundation; either version 2 of the License, or >> + * (at your option) any later version. >> + * >> + * This program is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> + * GNU General Public License for more details. >> + * >> + * You should have received a copy of the GNU General Public >> License along >> + * with this program; if not, write to the Free Software >> Foundation, Inc., >> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >> + */ >> + >> +#ifndef RTL2832_H >> +#define RTL2832_H >> + >> +#include<linux/dvb/frontend.h> >> + >> +struct rtl2832_config { >> + /* >> + * Demodulator I2C address. >> + */ >> + u8 i2c_addr; >> + >> + /* >> + * Xtal frequency. >> + * Hz >> + * 4000000, 16000000, 25000000, 28800000 >> + */ >> + u32 xtal; >> + >> + /* >> + * IFs for all used modes. >> + * Hz >> + * 4570000, 4571429, 36000000, 36125000, 36166667, 44000000 >> + */ >> + u32 if_dvbt; >> + >> + /* >> + */ >> + u8 tuner; >> +}; >> + >> + >> +#if defined(CONFIG_DVB_RTL2832) || \ >> + (defined(CONFIG_DVB_RTL2832_MODULE)&& defined(MODULE)) >> +extern struct dvb_frontend *rtl2832_attach( >> + const struct rtl2832_config *cfg, >> + struct i2c_adapter *i2c >> +); >> + >> +extern struct i2c_adapter *rtl2832_get_tuner_i2c_adapter( >> + struct dvb_frontend *fe >> +); >> +#else >> +static inline struct dvb_frontend *rtl2832_attach( >> + const struct rtl2832_config *config, >> + struct i2c_adapter *i2c >> +) >> +{ >> + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); >> + return NULL; >> +} >> + >> +static inline struct i2c_adapter *rtl2832_get_tuner_i2c_adapter( >> + struct dvb_frontend *fe >> +) >> +{ >> + return NULL; >> +} > > There is no i2c_adapter to export. It is copy paste error from the > RTL2830 which needs I2C-adapter due to automatic I2C-gate close. > >> +#endif >> + >> + >> +#endif /* RTL2832_H */ >> diff --git a/drivers/media/dvb/frontends/rtl2832_priv.h >> b/drivers/media/dvb/frontends/rtl2832_priv.h >> new file mode 100644 >> index 0000000..0f5df2f >> --- /dev/null >> +++ b/drivers/media/dvb/frontends/rtl2832_priv.h >> @@ -0,0 +1,260 @@ >> +/* >> + * Realtek RTL2832 DVB-T demodulator driver >> + * >> + * Copyright (C) 2012 Thomas Mair<thomas.mair86@gmail.com> >> + * >> + * This program is free software; you can redistribute it and/or >> modify >> + * it under the terms of the GNU General Public License as >> published by >> + * the Free Software Foundation; either version 2 of the License, or >> + * (at your option) any later version. >> + * >> + * This program is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> + * GNU General Public License for more details. >> + * >> + * You should have received a copy of the GNU General Public >> License along >> + * with this program; if not, write to the Free Software >> Foundation, Inc., >> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >> + */ >> + >> +#ifndef RTL2832_PRIV_H >> +#define RTL2832_PRIV_H >> + >> +#include "dvb_frontend.h" >> +#include "rtl2832.h" >> + >> +#define LOG_PREFIX "rtl2832" >> + >> +#undef dbg >> +#define dbg(f, arg...) \ >> + if (rtl2832_debug) \ >> + printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) >> +#undef err >> +#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## >> arg) >> +#undef info >> +#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) >> +#undef warn >> +#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , >> ## arg) >> + >> +struct rtl2832_priv { >> + struct i2c_adapter *i2c; >> + struct dvb_frontend fe; >> + struct rtl2832_config cfg; >> + >> + bool i2c_gate_state; >> + bool sleeping; >> + >> + u8 tuner; >> + u8 page; /* active register page */ >> +}; >> + >> +typedef struct { >> + u8 page; >> + u8 start_address; >> + u8 msb; >> + u8 lsb; >> +} >> +rtl2832_reg_entry; > > typedefs are not allowed > >> + >> +typedef struct { >> + int reg; >> + u32 value; >> +} >> +rtl2832_reg_value; > > typedefs are not allowed > >> + >> + >> +/* Demod register bit names */ >> +enum DVBT_REG_BIT_NAME { >> + DVBT_SOFT_RST, >> + DVBT_IIC_REPEAT, >> + DVBT_TR_WAIT_MIN_8K, >> + DVBT_RSD_BER_FAIL_VAL, >> + DVBT_EN_BK_TRK, >> + DVBT_REG_PI, >> + DVBT_REG_PFREQ_1_0, >> + DVBT_PD_DA8, >> + DVBT_LOCK_TH, >> + DVBT_BER_PASS_SCAL, >> + DVBT_CE_FFSM_BYPASS, >> + DVBT_ALPHAIIR_N, >> + DVBT_ALPHAIIR_DIF, >> + DVBT_EN_TRK_SPAN, >> + DVBT_LOCK_TH_LEN, >> + DVBT_CCI_THRE, >> + DVBT_CCI_MON_SCAL, >> + DVBT_CCI_M0, >> + DVBT_CCI_M1, >> + DVBT_CCI_M2, >> + DVBT_CCI_M3, >> + DVBT_SPEC_INIT_0, >> + DVBT_SPEC_INIT_1, >> + DVBT_SPEC_INIT_2, >> + DVBT_AD_EN_REG, >> + DVBT_AD_EN_REG1, >> + DVBT_EN_BBIN, >> + DVBT_MGD_THD0, >> + DVBT_MGD_THD1, >> + DVBT_MGD_THD2, >> + DVBT_MGD_THD3, >> + DVBT_MGD_THD4, >> + DVBT_MGD_THD5, >> + DVBT_MGD_THD6, >> + DVBT_MGD_THD7, >> + DVBT_EN_CACQ_NOTCH, >> + DVBT_AD_AV_REF, >> + DVBT_PIP_ON, >> + DVBT_SCALE1_B92, >> + DVBT_SCALE1_B93, >> + DVBT_SCALE1_BA7, >> + DVBT_SCALE1_BA9, >> + DVBT_SCALE1_BAA, >> + DVBT_SCALE1_BAB, >> + DVBT_SCALE1_BAC, >> + DVBT_SCALE1_BB0, >> + DVBT_SCALE1_BB1, >> + DVBT_KB_P1, >> + DVBT_KB_P2, >> + DVBT_KB_P3, >> + DVBT_OPT_ADC_IQ, >> + DVBT_AD_AVI, >> + DVBT_AD_AVQ, >> + DVBT_K1_CR_STEP12, >> + DVBT_TRK_KS_P2, >> + DVBT_TRK_KS_I2, >> + DVBT_TR_THD_SET2, >> + DVBT_TRK_KC_P2, >> + DVBT_TRK_KC_I2, >> + DVBT_CR_THD_SET2, >> + DVBT_PSET_IFFREQ, >> + DVBT_SPEC_INV, >> + DVBT_BW_INDEX, >> + DVBT_RSAMP_RATIO, >> + DVBT_CFREQ_OFF_RATIO, >> + DVBT_FSM_STAGE, >> + DVBT_RX_CONSTEL, >> + DVBT_RX_HIER, >> + DVBT_RX_C_RATE_LP, >> + DVBT_RX_C_RATE_HP, >> + DVBT_GI_IDX, >> + DVBT_FFT_MODE_IDX, >> + DVBT_RSD_BER_EST, >> + DVBT_CE_EST_EVM, >> + DVBT_RF_AGC_VAL, >> + DVBT_IF_AGC_VAL, >> + DVBT_DAGC_VAL, >> + DVBT_SFREQ_OFF, >> + DVBT_CFREQ_OFF, >> + DVBT_POLAR_RF_AGC, >> + DVBT_POLAR_IF_AGC, >> + DVBT_AAGC_HOLD, >> + DVBT_EN_RF_AGC, >> + DVBT_EN_IF_AGC, >> + DVBT_IF_AGC_MIN, >> + DVBT_IF_AGC_MAX, >> + DVBT_RF_AGC_MIN, >> + DVBT_RF_AGC_MAX, >> + DVBT_IF_AGC_MAN, >> + DVBT_IF_AGC_MAN_VAL, >> + DVBT_RF_AGC_MAN, >> + DVBT_RF_AGC_MAN_VAL, >> + DVBT_DAGC_TRG_VAL, >> + DVBT_AGC_TARG_VAL, >> + DVBT_LOOP_GAIN_3_0, >> + DVBT_LOOP_GAIN_4, >> + DVBT_VTOP, >> + DVBT_KRF, >> + DVBT_AGC_TARG_VAL_0, >> + DVBT_AGC_TARG_VAL_8_1, >> + DVBT_AAGC_LOOP_GAIN, >> + DVBT_LOOP_GAIN2_3_0, >> + DVBT_LOOP_GAIN2_4, >> + DVBT_LOOP_GAIN3, >> + DVBT_VTOP1, >> + DVBT_VTOP2, >> + DVBT_VTOP3, >> + DVBT_KRF1, >> + DVBT_KRF2, >> + DVBT_KRF3, >> + DVBT_KRF4, >> + DVBT_EN_GI_PGA, >> + DVBT_THD_LOCK_UP, >> + DVBT_THD_LOCK_DW, >> + DVBT_THD_UP1, >> + DVBT_THD_DW1, >> + DVBT_INTER_CNT_LEN, >> + DVBT_GI_PGA_STATE, >> + DVBT_EN_AGC_PGA, >> + DVBT_CKOUTPAR, >> + DVBT_CKOUT_PWR, >> + DVBT_SYNC_DUR, >> + DVBT_ERR_DUR, >> + DVBT_SYNC_LVL, >> + DVBT_ERR_LVL, >> + DVBT_VAL_LVL, >> + DVBT_SERIAL, >> + DVBT_SER_LSB, >> + DVBT_CDIV_PH0, >> + DVBT_CDIV_PH1, >> + DVBT_MPEG_IO_OPT_2_2, >> + DVBT_MPEG_IO_OPT_1_0, >> + DVBT_CKOUTPAR_PIP, >> + DVBT_CKOUT_PWR_PIP, >> + DVBT_SYNC_LVL_PIP, >> + DVBT_ERR_LVL_PIP, >> + DVBT_VAL_LVL_PIP, >> + DVBT_CKOUTPAR_PID, >> + DVBT_CKOUT_PWR_PID, >> + DVBT_SYNC_LVL_PID, >> + DVBT_ERR_LVL_PID, >> + DVBT_VAL_LVL_PID, >> + DVBT_SM_PASS, >> + DVBT_UPDATE_REG_2, >> + DVBT_BTHD_P3, >> + DVBT_BTHD_D3, >> + DVBT_FUNC4_REG0, >> + DVBT_FUNC4_REG1, >> + DVBT_FUNC4_REG2, >> + DVBT_FUNC4_REG3, >> + DVBT_FUNC4_REG4, >> + DVBT_FUNC4_REG5, >> + DVBT_FUNC4_REG6, >> + DVBT_FUNC4_REG7, >> + DVBT_FUNC4_REG8, >> + DVBT_FUNC4_REG9, >> + DVBT_FUNC4_REG10, >> + DVBT_FUNC5_REG0, >> + DVBT_FUNC5_REG1, >> + DVBT_FUNC5_REG2, >> + DVBT_FUNC5_REG3, >> + DVBT_FUNC5_REG4, >> + DVBT_FUNC5_REG5, >> + DVBT_FUNC5_REG6, >> + DVBT_FUNC5_REG7, >> + DVBT_FUNC5_REG8, >> + DVBT_FUNC5_REG9, >> + DVBT_FUNC5_REG10, >> + DVBT_FUNC5_REG11, >> + DVBT_FUNC5_REG12, >> + DVBT_FUNC5_REG13, >> + DVBT_FUNC5_REG14, >> + DVBT_FUNC5_REG15, >> + DVBT_FUNC5_REG16, >> + DVBT_FUNC5_REG17, >> + DVBT_FUNC5_REG18, >> + DVBT_AD7_SETTING, >> + DVBT_RSSI_R, >> + DVBT_ACI_DET_IND, >> + DVBT_REG_MON, >> + DVBT_REG_MONSEL, >> + DVBT_REG_GPE, >> + DVBT_REG_GPO, >> + DVBT_REG_4MSEL, >> + DVBT_TEST_REG_1, >> + DVBT_TEST_REG_2, >> + DVBT_TEST_REG_3, >> + DVBT_TEST_REG_4, >> + DVBT_REG_BIT_NAME_ITEM_TERMINATOR, >> +}; >> + >> +#endif /* RTL2832_PRIV_H */ > > Puuuh, there was more findings what I supposed earlier. Most of those > are easy to fix. > > But it seems like all the statistics are broken, returning wrong values > and one BER was even inplemented as a signal quality meter. > > What you say if I propose you to remove those statistics and sent driver > without? Add those then later. > > Statistics are not mandatory and it is 3.4-RC7 phase ongoing. It means > driver should be quite ready during that week if we want it to the > Kernel 3.5. I am almost sure Kernel 3.4 is released next weekend... > > regards > Antti As far as I can manage, according to your reply are those FE(rtl2832) patches: -rtl2832.c.diff -rtl2832.h.diff -rtl2832_priv.h.diff Tested on 3.3.5-2.fc16.x86_64 - PASSED. femon -H -a 2 -c 5 FE: Realtek RTL2832 (DVB-T) (DVBT) status SCVYL | signal 23% | snr 0% | ber 0 | unc 100 | FE_HAS_LOCK status SCVYL | signal 23% | snr 0% | ber 0 | unc 100 | FE_HAS_LOCK status SCVYL | signal 23% | snr 0% | ber 0 | unc 100 | FE_HAS_LOCK status SCVYL | signal 23% | snr 0% | ber 0 | unc 100 | FE_HAS_LOCK status SCVYL | signal 23% | snr 0% | ber 0 | unc 100 | FE_HAS_LOCK Cheers, poma [-- Attachment #2: rtl2832.c.diff --] [-- Type: text/x-patch, Size: 20911 bytes --] --- linux/drivers/media/dvb/frontends/rtl2832.c.orig 2012-05-16 06:46:22.205817091 +0200 +++ linux/drivers/media/dvb/frontends/rtl2832.c 2012-05-16 06:43:29.922912031 +0200 @@ -62,134 +62,134 @@ 0xffffffff }; -static const rtl2832_reg_entry registers[] = { - [DVBT_SOFT_RST] = {0x1, 0x1, 2, 2}, - [DVBT_IIC_REPEAT] = {0x1, 0x1, 3, 3}, - [DVBT_TR_WAIT_MIN_8K] = {0x1, 0x88, 11, 2}, - [DVBT_RSD_BER_FAIL_VAL] = {0x1, 0x8f, 15, 0}, - [DVBT_EN_BK_TRK] = {0x1, 0xa6, 7, 7}, - [DVBT_AD_EN_REG] = {0x0, 0x8, 7, 7}, - [DVBT_AD_EN_REG1] = {0x0, 0x8, 6, 6}, - [DVBT_EN_BBIN] = {0x1, 0xb1, 0, 0}, - [DVBT_MGD_THD0] = {0x1, 0x95, 7, 0}, - [DVBT_MGD_THD1] = {0x1, 0x96, 7, 0}, - [DVBT_MGD_THD2] = {0x1, 0x97, 7, 0}, - [DVBT_MGD_THD3] = {0x1, 0x98, 7, 0}, - [DVBT_MGD_THD4] = {0x1, 0x99, 7, 0}, - [DVBT_MGD_THD5] = {0x1, 0x9a, 7, 0}, - [DVBT_MGD_THD6] = {0x1, 0x9b, 7, 0}, - [DVBT_MGD_THD7] = {0x1, 0x9c, 7, 0}, - [DVBT_EN_CACQ_NOTCH] = {0x1, 0x61, 4, 4}, - [DVBT_AD_AV_REF] = {0x0, 0x9, 6, 0}, - [DVBT_REG_PI] = {0x0, 0xa, 2, 0}, - [DVBT_PIP_ON] = {0x0, 0x21, 3, 3}, - [DVBT_SCALE1_B92] = {0x2, 0x92, 7, 0}, - [DVBT_SCALE1_B93] = {0x2, 0x93, 7, 0}, - [DVBT_SCALE1_BA7] = {0x2, 0xa7, 7, 0}, - [DVBT_SCALE1_BA9] = {0x2, 0xa9, 7, 0}, - [DVBT_SCALE1_BAA] = {0x2, 0xaa, 7, 0}, - [DVBT_SCALE1_BAB] = {0x2, 0xab, 7, 0}, - [DVBT_SCALE1_BAC] = {0x2, 0xac, 7, 0}, - [DVBT_SCALE1_BB0] = {0x2, 0xb0, 7, 0}, - [DVBT_SCALE1_BB1] = {0x2, 0xb1, 7, 0}, - [DVBT_KB_P1] = {0x1, 0x64, 3, 1}, - [DVBT_KB_P2] = {0x1, 0x64, 6, 4}, - [DVBT_KB_P3] = {0x1, 0x65, 2, 0}, - [DVBT_OPT_ADC_IQ] = {0x0, 0x6, 5, 4}, - [DVBT_AD_AVI] = {0x0, 0x9, 1, 0}, - [DVBT_AD_AVQ] = {0x0, 0x9, 3, 2}, - [DVBT_K1_CR_STEP12] = {0x2, 0xad, 9, 4}, - [DVBT_TRK_KS_P2] = {0x1, 0x6f, 2, 0}, - [DVBT_TRK_KS_I2] = {0x1, 0x70, 5, 3}, - [DVBT_TR_THD_SET2] = {0x1, 0x72, 3, 0}, - [DVBT_TRK_KC_P2] = {0x1, 0x73, 5, 3}, - [DVBT_TRK_KC_I2] = {0x1, 0x75, 2, 0}, - [DVBT_CR_THD_SET2] = {0x1, 0x76, 7, 6}, - [DVBT_PSET_IFFREQ] = {0x1, 0x19, 21, 0}, - [DVBT_SPEC_INV] = {0x1, 0x15, 0, 0}, - [DVBT_RSAMP_RATIO] = {0x1, 0x9f, 27, 2}, - [DVBT_CFREQ_OFF_RATIO] = {0x1, 0x9d, 23, 4}, - [DVBT_FSM_STAGE] = {0x3, 0x51, 6, 3}, - [DVBT_RX_CONSTEL] = {0x3, 0x3c, 3, 2}, - [DVBT_RX_HIER] = {0x3, 0x3c, 6, 4}, - [DVBT_RX_C_RATE_LP] = {0x3, 0x3d, 2, 0}, - [DVBT_RX_C_RATE_HP] = {0x3, 0x3d, 5, 3}, - [DVBT_GI_IDX] = {0x3, 0x51, 1, 0}, - [DVBT_FFT_MODE_IDX] = {0x3, 0x51, 2, 2}, - [DVBT_RSD_BER_EST] = {0x3, 0x4e, 15, 0}, - [DVBT_CE_EST_EVM] = {0x4, 0xc, 15, 0}, - [DVBT_RF_AGC_VAL] = {0x3, 0x5b, 13, 0}, - [DVBT_IF_AGC_VAL] = {0x3, 0x59, 13, 0}, - [DVBT_DAGC_VAL] = {0x3, 0x5, 7, 0}, - [DVBT_SFREQ_OFF] = {0x3, 0x18, 13, 0}, - [DVBT_CFREQ_OFF] = {0x3, 0x5f, 17, 0}, - [DVBT_POLAR_RF_AGC] = {0x0, 0xe, 1, 1}, - [DVBT_POLAR_IF_AGC] = {0x0, 0xe, 0, 0}, - [DVBT_AAGC_HOLD] = {0x1, 0x4, 5, 5}, - [DVBT_EN_RF_AGC] = {0x1, 0x4, 6, 6}, - [DVBT_EN_IF_AGC] = {0x1, 0x4, 7, 7}, - [DVBT_IF_AGC_MIN] = {0x1, 0x8, 7, 0}, - [DVBT_IF_AGC_MAX] = {0x1, 0x9, 7, 0}, - [DVBT_RF_AGC_MIN] = {0x1, 0xa, 7, 0}, - [DVBT_RF_AGC_MAX] = {0x1, 0xb, 7, 0}, - [DVBT_IF_AGC_MAN] = {0x1, 0xc, 6, 6}, - [DVBT_IF_AGC_MAN_VAL] = {0x1, 0xc, 13, 0}, - [DVBT_RF_AGC_MAN] = {0x1, 0xe, 6, 6}, - [DVBT_RF_AGC_MAN_VAL] = {0x1, 0xe, 13, 0}, - [DVBT_DAGC_TRG_VAL] = {0x1, 0x12, 7, 0}, - [DVBT_AGC_TARG_VAL_0] = {0x1, 0x2, 0, 0}, - [DVBT_AGC_TARG_VAL_8_1] = {0x1, 0x3, 7, 0}, - [DVBT_AAGC_LOOP_GAIN] = {0x1, 0xc7, 5, 1}, - [DVBT_LOOP_GAIN2_3_0] = {0x1, 0x4, 4, 1}, - [DVBT_LOOP_GAIN2_4] = {0x1, 0x5, 7, 7}, - [DVBT_LOOP_GAIN3] = {0x1, 0xc8, 4, 0}, - [DVBT_VTOP1] = {0x1, 0x6, 5, 0}, - [DVBT_VTOP2] = {0x1, 0xc9, 5, 0}, - [DVBT_VTOP3] = {0x1, 0xca, 5, 0}, - [DVBT_KRF1] = {0x1, 0xcb, 7, 0}, - [DVBT_KRF2] = {0x1, 0x7, 7, 0}, - [DVBT_KRF3] = {0x1, 0xcd, 7, 0}, - [DVBT_KRF4] = {0x1, 0xce, 7, 0}, - [DVBT_EN_GI_PGA] = {0x1, 0xe5, 0, 0}, - [DVBT_THD_LOCK_UP] = {0x1, 0xd9, 8, 0}, - [DVBT_THD_LOCK_DW] = {0x1, 0xdb, 8, 0}, - [DVBT_THD_UP1] = {0x1, 0xdd, 7, 0}, - [DVBT_THD_DW1] = {0x1, 0xde, 7, 0}, - [DVBT_INTER_CNT_LEN] = {0x1, 0xd8, 3, 0}, - [DVBT_GI_PGA_STATE] = {0x1, 0xe6, 3, 3}, - [DVBT_EN_AGC_PGA] = {0x1, 0xd7, 0, 0}, - [DVBT_CKOUTPAR] = {0x1, 0x7b, 5, 5}, - [DVBT_CKOUT_PWR] = {0x1, 0x7b, 6, 6}, - [DVBT_SYNC_DUR] = {0x1, 0x7b, 7, 7}, - [DVBT_ERR_DUR] = {0x1, 0x7c, 0, 0}, - [DVBT_SYNC_LVL] = {0x1, 0x7c, 1, 1}, - [DVBT_ERR_LVL] = {0x1, 0x7c, 2, 2}, - [DVBT_VAL_LVL] = {0x1, 0x7c, 3, 3}, - [DVBT_SERIAL] = {0x1, 0x7c, 4, 4}, - [DVBT_SER_LSB] = {0x1, 0x7c, 5, 5}, - [DVBT_CDIV_PH0] = {0x1, 0x7d, 3, 0}, - [DVBT_CDIV_PH1] = {0x1, 0x7d, 7, 4}, - [DVBT_MPEG_IO_OPT_2_2] = {0x0, 0x6, 7, 7}, - [DVBT_MPEG_IO_OPT_1_0] = {0x0, 0x7, 7, 6}, - [DVBT_CKOUTPAR_PIP] = {0x0, 0xb7, 4, 4}, - [DVBT_CKOUT_PWR_PIP] = {0x0, 0xb7, 3, 3}, - [DVBT_SYNC_LVL_PIP] = {0x0, 0xb7, 2, 2}, - [DVBT_ERR_LVL_PIP] = {0x0, 0xb7, 1, 1}, - [DVBT_VAL_LVL_PIP] = {0x0, 0xb7, 0, 0}, - [DVBT_CKOUTPAR_PID] = {0x0, 0xb9, 4, 4}, - [DVBT_CKOUT_PWR_PID] = {0x0, 0xb9, 3, 3}, - [DVBT_SYNC_LVL_PID] = {0x0, 0xb9, 2, 2}, - [DVBT_ERR_LVL_PID] = {0x0, 0xb9, 1, 1}, - [DVBT_VAL_LVL_PID] = {0x0, 0xb9, 0, 0}, - [DVBT_SM_PASS] = {0x1, 0x93, 11, 0}, - [DVBT_AD7_SETTING] = {0x0, 0x11, 15, 0}, - [DVBT_RSSI_R] = {0x3, 0x1, 6, 0}, - [DVBT_ACI_DET_IND] = {0x3, 0x12, 0, 0}, - [DVBT_REG_MON] = {0x0, 0xd, 1, 0}, - [DVBT_REG_MONSEL] = {0x0, 0xd, 2, 2}, - [DVBT_REG_GPE] = {0x0, 0xd, 7, 7}, - [DVBT_REG_GPO] = {0x0, 0x10, 0, 0}, - [DVBT_REG_4MSEL] = {0x0, 0x13, 0, 0}, +struct rtl2832_reg_entry registers[] = { + [DVBT_SOFT_RST] = {0x1, 0x1, 2, 2}, + [DVBT_IIC_REPEAT] = {0x1, 0x1, 3, 3}, + [DVBT_TR_WAIT_MIN_8K] = {0x1, 0x88, 11, 2}, + [DVBT_RSD_BER_FAIL_VAL] = {0x1, 0x8f, 15, 0}, + [DVBT_EN_BK_TRK] = {0x1, 0xa6, 7, 7}, + [DVBT_AD_EN_REG] = {0x0, 0x8, 7, 7}, + [DVBT_AD_EN_REG1] = {0x0, 0x8, 6, 6}, + [DVBT_EN_BBIN] = {0x1, 0xb1, 0, 0}, + [DVBT_MGD_THD0] = {0x1, 0x95, 7, 0}, + [DVBT_MGD_THD1] = {0x1, 0x96, 7, 0}, + [DVBT_MGD_THD2] = {0x1, 0x97, 7, 0}, + [DVBT_MGD_THD3] = {0x1, 0x98, 7, 0}, + [DVBT_MGD_THD4] = {0x1, 0x99, 7, 0}, + [DVBT_MGD_THD5] = {0x1, 0x9a, 7, 0}, + [DVBT_MGD_THD6] = {0x1, 0x9b, 7, 0}, + [DVBT_MGD_THD7] = {0x1, 0x9c, 7, 0}, + [DVBT_EN_CACQ_NOTCH] = {0x1, 0x61, 4, 4}, + [DVBT_AD_AV_REF] = {0x0, 0x9, 6, 0}, + [DVBT_REG_PI] = {0x0, 0xa, 2, 0}, + [DVBT_PIP_ON] = {0x0, 0x21, 3, 3}, + [DVBT_SCALE1_B92] = {0x2, 0x92, 7, 0}, + [DVBT_SCALE1_B93] = {0x2, 0x93, 7, 0}, + [DVBT_SCALE1_BA7] = {0x2, 0xa7, 7, 0}, + [DVBT_SCALE1_BA9] = {0x2, 0xa9, 7, 0}, + [DVBT_SCALE1_BAA] = {0x2, 0xaa, 7, 0}, + [DVBT_SCALE1_BAB] = {0x2, 0xab, 7, 0}, + [DVBT_SCALE1_BAC] = {0x2, 0xac, 7, 0}, + [DVBT_SCALE1_BB0] = {0x2, 0xb0, 7, 0}, + [DVBT_SCALE1_BB1] = {0x2, 0xb1, 7, 0}, + [DVBT_KB_P1] = {0x1, 0x64, 3, 1}, + [DVBT_KB_P2] = {0x1, 0x64, 6, 4}, + [DVBT_KB_P3] = {0x1, 0x65, 2, 0}, + [DVBT_OPT_ADC_IQ] = {0x0, 0x6, 5, 4}, + [DVBT_AD_AVI] = {0x0, 0x9, 1, 0}, + [DVBT_AD_AVQ] = {0x0, 0x9, 3, 2}, + [DVBT_K1_CR_STEP12] = {0x2, 0xad, 9, 4}, + [DVBT_TRK_KS_P2] = {0x1, 0x6f, 2, 0}, + [DVBT_TRK_KS_I2] = {0x1, 0x70, 5, 3}, + [DVBT_TR_THD_SET2] = {0x1, 0x72, 3, 0}, + [DVBT_TRK_KC_P2] = {0x1, 0x73, 5, 3}, + [DVBT_TRK_KC_I2] = {0x1, 0x75, 2, 0}, + [DVBT_CR_THD_SET2] = {0x1, 0x76, 7, 6}, + [DVBT_PSET_IFFREQ] = {0x1, 0x19, 21, 0}, + [DVBT_SPEC_INV] = {0x1, 0x15, 0, 0}, + [DVBT_RSAMP_RATIO] = {0x1, 0x9f, 27, 2}, + [DVBT_CFREQ_OFF_RATIO] = {0x1, 0x9d, 23, 4}, + [DVBT_FSM_STAGE] = {0x3, 0x51, 6, 3}, + [DVBT_RX_CONSTEL] = {0x3, 0x3c, 3, 2}, + [DVBT_RX_HIER] = {0x3, 0x3c, 6, 4}, + [DVBT_RX_C_RATE_LP] = {0x3, 0x3d, 2, 0}, + [DVBT_RX_C_RATE_HP] = {0x3, 0x3d, 5, 3}, + [DVBT_GI_IDX] = {0x3, 0x51, 1, 0}, + [DVBT_FFT_MODE_IDX] = {0x3, 0x51, 2, 2}, + [DVBT_RSD_BER_EST] = {0x3, 0x4e, 15, 0}, + [DVBT_CE_EST_EVM] = {0x4, 0xc, 15, 0}, + [DVBT_RF_AGC_VAL] = {0x3, 0x5b, 13, 0}, + [DVBT_IF_AGC_VAL] = {0x3, 0x59, 13, 0}, + [DVBT_DAGC_VAL] = {0x3, 0x5, 7, 0}, + [DVBT_SFREQ_OFF] = {0x3, 0x18, 13, 0}, + [DVBT_CFREQ_OFF] = {0x3, 0x5f, 17, 0}, + [DVBT_POLAR_RF_AGC] = {0x0, 0xe, 1, 1}, + [DVBT_POLAR_IF_AGC] = {0x0, 0xe, 0, 0}, + [DVBT_AAGC_HOLD] = {0x1, 0x4, 5, 5}, + [DVBT_EN_RF_AGC] = {0x1, 0x4, 6, 6}, + [DVBT_EN_IF_AGC] = {0x1, 0x4, 7, 7}, + [DVBT_IF_AGC_MIN] = {0x1, 0x8, 7, 0}, + [DVBT_IF_AGC_MAX] = {0x1, 0x9, 7, 0}, + [DVBT_RF_AGC_MIN] = {0x1, 0xa, 7, 0}, + [DVBT_RF_AGC_MAX] = {0x1, 0xb, 7, 0}, + [DVBT_IF_AGC_MAN] = {0x1, 0xc, 6, 6}, + [DVBT_IF_AGC_MAN_VAL] = {0x1, 0xc, 13, 0}, + [DVBT_RF_AGC_MAN] = {0x1, 0xe, 6, 6}, + [DVBT_RF_AGC_MAN_VAL] = {0x1, 0xe, 13, 0}, + [DVBT_DAGC_TRG_VAL] = {0x1, 0x12, 7, 0}, + [DVBT_AGC_TARG_VAL_0] = {0x1, 0x2, 0, 0}, + [DVBT_AGC_TARG_VAL_8_1] = {0x1, 0x3, 7, 0}, + [DVBT_AAGC_LOOP_GAIN] = {0x1, 0xc7, 5, 1}, + [DVBT_LOOP_GAIN2_3_0] = {0x1, 0x4, 4, 1}, + [DVBT_LOOP_GAIN2_4] = {0x1, 0x5, 7, 7}, + [DVBT_LOOP_GAIN3] = {0x1, 0xc8, 4, 0}, + [DVBT_VTOP1] = {0x1, 0x6, 5, 0}, + [DVBT_VTOP2] = {0x1, 0xc9, 5, 0}, + [DVBT_VTOP3] = {0x1, 0xca, 5, 0}, + [DVBT_KRF1] = {0x1, 0xcb, 7, 0}, + [DVBT_KRF2] = {0x1, 0x7, 7, 0}, + [DVBT_KRF3] = {0x1, 0xcd, 7, 0}, + [DVBT_KRF4] = {0x1, 0xce, 7, 0}, + [DVBT_EN_GI_PGA] = {0x1, 0xe5, 0, 0}, + [DVBT_THD_LOCK_UP] = {0x1, 0xd9, 8, 0}, + [DVBT_THD_LOCK_DW] = {0x1, 0xdb, 8, 0}, + [DVBT_THD_UP1] = {0x1, 0xdd, 7, 0}, + [DVBT_THD_DW1] = {0x1, 0xde, 7, 0}, + [DVBT_INTER_CNT_LEN] = {0x1, 0xd8, 3, 0}, + [DVBT_GI_PGA_STATE] = {0x1, 0xe6, 3, 3}, + [DVBT_EN_AGC_PGA] = {0x1, 0xd7, 0, 0}, + [DVBT_CKOUTPAR] = {0x1, 0x7b, 5, 5}, + [DVBT_CKOUT_PWR] = {0x1, 0x7b, 6, 6}, + [DVBT_SYNC_DUR] = {0x1, 0x7b, 7, 7}, + [DVBT_ERR_DUR] = {0x1, 0x7c, 0, 0}, + [DVBT_SYNC_LVL] = {0x1, 0x7c, 1, 1}, + [DVBT_ERR_LVL] = {0x1, 0x7c, 2, 2}, + [DVBT_VAL_LVL] = {0x1, 0x7c, 3, 3}, + [DVBT_SERIAL] = {0x1, 0x7c, 4, 4}, + [DVBT_SER_LSB] = {0x1, 0x7c, 5, 5}, + [DVBT_CDIV_PH0] = {0x1, 0x7d, 3, 0}, + [DVBT_CDIV_PH1] = {0x1, 0x7d, 7, 4}, + [DVBT_MPEG_IO_OPT_2_2] = {0x0, 0x6, 7, 7}, + [DVBT_MPEG_IO_OPT_1_0] = {0x0, 0x7, 7, 6}, + [DVBT_CKOUTPAR_PIP] = {0x0, 0xb7, 4, 4}, + [DVBT_CKOUT_PWR_PIP] = {0x0, 0xb7, 3, 3}, + [DVBT_SYNC_LVL_PIP] = {0x0, 0xb7, 2, 2}, + [DVBT_ERR_LVL_PIP] = {0x0, 0xb7, 1, 1}, + [DVBT_VAL_LVL_PIP] = {0x0, 0xb7, 0, 0}, + [DVBT_CKOUTPAR_PID] = {0x0, 0xb9, 4, 4}, + [DVBT_CKOUT_PWR_PID] = {0x0, 0xb9, 3, 3}, + [DVBT_SYNC_LVL_PID] = {0x0, 0xb9, 2, 2}, + [DVBT_ERR_LVL_PID] = {0x0, 0xb9, 1, 1}, + [DVBT_VAL_LVL_PID] = {0x0, 0xb9, 0, 0}, + [DVBT_SM_PASS] = {0x1, 0x93, 11, 0}, + [DVBT_AD7_SETTING] = {0x0, 0x11, 15, 0}, + [DVBT_RSSI_R] = {0x3, 0x1, 6, 0}, + [DVBT_ACI_DET_IND] = {0x3, 0x12, 0, 0}, + [DVBT_REG_MON] = {0x0, 0xd, 1, 0}, + [DVBT_REG_MONSEL] = {0x0, 0xd, 2, 2}, + [DVBT_REG_GPE] = {0x0, 0xd, 7, 7}, + [DVBT_REG_GPO] = {0x0, 0x10, 0, 0}, + [DVBT_REG_4MSEL] = {0x0, 0x13, 0, 0}, }; /* write multiple hardware registers */ @@ -334,6 +334,7 @@ return ret; err: + dbg("%s: failed=%d", __func__, ret); return ret; } @@ -385,6 +386,7 @@ return ret; err: + dbg("%s: failed=%d", __func__, ret); return ret; } @@ -425,85 +427,80 @@ u64 pset_iffreq; /* initialization values for the demodulator registers */ - static rtl2832_reg_value rtl2832_initial_regs_1[] = { - {DVBT_AD_EN_REG, 0x1}, - {DVBT_AD_EN_REG1, 0x1}, + struct rtl2832_reg_value rtl2832_initial_regs[] = { + {DVBT_AD_EN_REG, 0x1}, + {DVBT_AD_EN_REG1, 0x1}, {DVBT_RSD_BER_FAIL_VAL, 0x2800}, - {DVBT_MGD_THD0, 0x10}, - {DVBT_MGD_THD1, 0x20}, - {DVBT_MGD_THD2, 0x20}, - {DVBT_MGD_THD3, 0x40}, - {DVBT_MGD_THD4, 0x22}, - {DVBT_MGD_THD5, 0x32}, - {DVBT_MGD_THD6, 0x37}, - {DVBT_MGD_THD7, 0x39}, - {DVBT_EN_BK_TRK, 0x0}, + {DVBT_MGD_THD0, 0x10}, + {DVBT_MGD_THD1, 0x20}, + {DVBT_MGD_THD2, 0x20}, + {DVBT_MGD_THD3, 0x40}, + {DVBT_MGD_THD4, 0x22}, + {DVBT_MGD_THD5, 0x32}, + {DVBT_MGD_THD6, 0x37}, + {DVBT_MGD_THD7, 0x39}, + {DVBT_EN_BK_TRK, 0x0}, {DVBT_EN_CACQ_NOTCH, 0x0}, - {DVBT_AD_AV_REF, 0x2a}, - {DVBT_REG_PI, 0x6}, - {DVBT_PIP_ON, 0x0}, - {DVBT_CDIV_PH0, 0x8}, - {DVBT_CDIV_PH1, 0x8}, - {DVBT_SCALE1_B92, 0x4}, - {DVBT_SCALE1_B93, 0xb0}, - {DVBT_SCALE1_BA7, 0x78}, - {DVBT_SCALE1_BA9, 0x28}, - {DVBT_SCALE1_BAA, 0x59}, - {DVBT_SCALE1_BAB, 0x83}, - {DVBT_SCALE1_BAC, 0xd4}, - {DVBT_SCALE1_BB0, 0x65}, - {DVBT_SCALE1_BB1, 0x43}, - {DVBT_KB_P1, 0x1}, - {DVBT_KB_P2, 0x4}, - {DVBT_KB_P3, 0x7}, - {DVBT_K1_CR_STEP12, 0xa}, - {DVBT_REG_GPE, 0x1}, - {DVBT_SERIAL, 0x0}, - {DVBT_CDIV_PH0, 0x9}, - {DVBT_CDIV_PH1, 0x9}, + {DVBT_AD_AV_REF, 0x2a}, + {DVBT_REG_PI, 0x6}, + {DVBT_PIP_ON, 0x0}, + {DVBT_CDIV_PH0, 0x8}, + {DVBT_CDIV_PH1, 0x8}, + {DVBT_SCALE1_B92, 0x4}, + {DVBT_SCALE1_B93, 0xb0}, + {DVBT_SCALE1_BA7, 0x78}, + {DVBT_SCALE1_BA9, 0x28}, + {DVBT_SCALE1_BAA, 0x59}, + {DVBT_SCALE1_BAB, 0x83}, + {DVBT_SCALE1_BAC, 0xd4}, + {DVBT_SCALE1_BB0, 0x65}, + {DVBT_SCALE1_BB1, 0x43}, + {DVBT_KB_P1, 0x1}, + {DVBT_KB_P2, 0x4}, + {DVBT_KB_P3, 0x7}, + {DVBT_K1_CR_STEP12, 0xa}, + {DVBT_REG_GPE, 0x1}, + {DVBT_SERIAL, 0x0}, + {DVBT_CDIV_PH0, 0x9}, + {DVBT_CDIV_PH1, 0x9}, {DVBT_MPEG_IO_OPT_2_2, 0x0}, {DVBT_MPEG_IO_OPT_1_0, 0x0}, - {DVBT_TRK_KS_P2, 0x4}, - {DVBT_TRK_KS_I2, 0x7}, - {DVBT_TR_THD_SET2, 0x6}, - {DVBT_TRK_KC_I2, 0x5}, - {DVBT_CR_THD_SET2, 0x1}, - - - }; - - static rtl2832_reg_value rtl2832_initial_regs_2[] = { - {DVBT_SPEC_INV, 0x0}, - {DVBT_DAGC_TRG_VAL, 0x5a}, + {DVBT_TRK_KS_P2, 0x4}, + {DVBT_TRK_KS_I2, 0x7}, + {DVBT_TR_THD_SET2, 0x6}, + {DVBT_TRK_KC_I2, 0x5}, + {DVBT_CR_THD_SET2, 0x1}, + {DVBT_SPEC_INV, 0x0}, + {DVBT_DAGC_TRG_VAL, 0x5a}, {DVBT_AGC_TARG_VAL_0, 0x0}, {DVBT_AGC_TARG_VAL_8_1, 0x5a}, {DVBT_AAGC_LOOP_GAIN, 0x16}, {DVBT_LOOP_GAIN2_3_0, 0x6}, - {DVBT_LOOP_GAIN2_4, 0x1}, - {DVBT_LOOP_GAIN3, 0x16}, - {DVBT_VTOP1, 0x35}, - {DVBT_VTOP2, 0x21}, - {DVBT_VTOP3, 0x21}, - {DVBT_KRF1, 0x0}, - {DVBT_KRF2, 0x40}, - {DVBT_KRF3, 0x10}, - {DVBT_KRF4, 0x10}, - {DVBT_IF_AGC_MIN, 0x80}, - {DVBT_IF_AGC_MAX, 0x7f}, - {DVBT_RF_AGC_MIN, 0x80}, - {DVBT_RF_AGC_MAX, 0x7f}, - {DVBT_POLAR_RF_AGC, 0x0}, - {DVBT_POLAR_IF_AGC, 0x0}, - {DVBT_AD7_SETTING, 0xe9bf}, - {DVBT_EN_GI_PGA, 0x0}, - {DVBT_THD_LOCK_UP, 0x0}, - {DVBT_THD_LOCK_DW, 0x0}, - {DVBT_THD_UP1, 0x11}, - {DVBT_THD_DW1, 0xef}, + {DVBT_LOOP_GAIN2_4, 0x1}, + {DVBT_LOOP_GAIN3, 0x16}, + {DVBT_VTOP1, 0x35}, + {DVBT_VTOP2, 0x21}, + {DVBT_VTOP3, 0x21}, + {DVBT_KRF1, 0x0}, + {DVBT_KRF2, 0x40}, + {DVBT_KRF3, 0x10}, + {DVBT_KRF4, 0x10}, + {DVBT_IF_AGC_MIN, 0x80}, + {DVBT_IF_AGC_MAX, 0x7f}, + {DVBT_RF_AGC_MIN, 0x80}, + {DVBT_RF_AGC_MAX, 0x7f}, + {DVBT_POLAR_RF_AGC, 0x0}, + {DVBT_POLAR_IF_AGC, 0x0}, + {DVBT_AD7_SETTING, 0xe9bf}, + {DVBT_EN_GI_PGA, 0x0}, + {DVBT_THD_LOCK_UP, 0x0}, + {DVBT_THD_LOCK_DW, 0x0}, + {DVBT_THD_UP1, 0x11}, + {DVBT_THD_DW1, 0xef}, {DVBT_INTER_CNT_LEN, 0xc}, - {DVBT_GI_PGA_STATE, 0x0}, - {DVBT_EN_AGC_PGA, 0x1}, - {DVBT_IF_AGC_MAN, 0x0}, + {DVBT_GI_PGA_STATE, 0x0}, + {DVBT_EN_AGC_PGA, 0x1}, + {DVBT_IF_AGC_MAN, 0x0}, }; @@ -522,9 +519,9 @@ - for (i = 0; i < 42; i++) { - ret = rtl2832_wr_demod_reg(priv, rtl2832_initial_regs_1[i].reg, - rtl2832_initial_regs_1[i].value); + for (i = 0; i < ARRAY_SIZE(rtl2832_initial_regs); i++) { + ret = rtl2832_wr_demod_reg(priv, rtl2832_initial_regs[i].reg, + rtl2832_initial_regs[i].value); if (ret) goto err; } @@ -538,18 +535,12 @@ if (ret) goto err; - for (i = 0; i < 31; i++) { - ret = rtl2832_wr_demod_reg(priv, rtl2832_initial_regs_2[i].reg, - rtl2832_initial_regs_2[i].value); - if (ret) - goto err; - } - priv->sleeping = false; return ret; err: + dbg("%s: failed=%d", __func__, ret); return ret; } @@ -584,26 +575,26 @@ static u8 bw_params[3][32] = { /* 6 MHz bandwidth */ { - 0xf5, 0xff, 0x15, 0x38, 0x5d, 0x6d, 0x52, 0x07, 0xfa, 0x2f, - 0x53, 0xf5, 0x3f, 0xca, 0x0b, 0x91, 0xea, 0x30, 0x63, 0xb2, - 0x13, 0xda, 0x0b, 0xc4, 0x18, 0x7e, 0x16, 0x66, 0x08, 0x67, - 0x19, 0xe0, + 0xf5, 0xff, 0x15, 0x38, 0x5d, 0x6d, 0x52, 0x07, 0xfa, 0x2f, + 0x53, 0xf5, 0x3f, 0xca, 0x0b, 0x91, 0xea, 0x30, 0x63, 0xb2, + 0x13, 0xda, 0x0b, 0xc4, 0x18, 0x7e, 0x16, 0x66, 0x08, 0x67, + 0x19, 0xe0, }, /* 7 MHz bandwidth */ { - 0xe7, 0xcc, 0xb5, 0xba, 0xe8, 0x2f, 0x67, 0x61, 0x00, 0xaf, - 0x86, 0xf2, 0xbf, 0x59, 0x04, 0x11, 0xb6, 0x33, 0xa4, 0x30, - 0x15, 0x10, 0x0a, 0x42, 0x18, 0xf8, 0x17, 0xd9, 0x07, 0x22, - 0x19, 0x10, + 0xe7, 0xcc, 0xb5, 0xba, 0xe8, 0x2f, 0x67, 0x61, 0x00, 0xaf, + 0x86, 0xf2, 0xbf, 0x59, 0x04, 0x11, 0xb6, 0x33, 0xa4, 0x30, + 0x15, 0x10, 0x0a, 0x42, 0x18, 0xf8, 0x17, 0xd9, 0x07, 0x22, + 0x19, 0x10, }, /* 8 MHz bandwidth */ { - 0x09, 0xf6, 0xd2, 0xa7, 0x9a, 0xc9, 0x27, 0x77, 0x06, 0xbf, - 0xec, 0xf4, 0x4f, 0x0b, 0xfc, 0x01, 0x63, 0x35, 0x54, 0xa7, - 0x16, 0x66, 0x08, 0xb4, 0x19, 0x6e, 0x19, 0x65, 0x05, 0xc8, - 0x19, 0xe0, + 0x09, 0xf6, 0xd2, 0xa7, 0x9a, 0xc9, 0x27, 0x77, 0x06, 0xbf, + 0xec, 0xf4, 0x4f, 0x0b, 0xfc, 0x01, 0x63, 0x35, 0x54, 0xa7, + 0x16, 0x66, 0x08, 0xb4, 0x19, 0x6e, 0x19, 0x65, 0x05, 0xc8, + 0x19, 0xe0, }, }; @@ -635,7 +626,7 @@ return -EINVAL; } - for (j = 0; j < 32; j++) { + for (j = 0; j < sizeof(bw_params[j]); j++) { ret = rtl2832_wr_regs(priv, 0x1c+j, 1, &bw_params[i][j], 1); if (ret) goto err; @@ -643,7 +634,7 @@ /* calculate and set resample ratio * RSAMP_RATIO = floor(CrystalFreqHz * 7 * pow(2, 22) - * / ConstWithBandwidthMode) + * / ConstWithBandwidthMode) */ num = priv->cfg.xtal * 7; num *= 0x400000; @@ -655,7 +646,7 @@ /* calculate and set cfreq off ratio * CFREQ_OFF_RATIO = - floor(ConstWithBandwidthMode * pow(2, 20) - * / (CrystalFreqHz * 7)) + * / (CrystalFreqHz * 7)) */ num = bw_mode << 20; num2 = priv->cfg.xtal * 7; @@ -727,13 +718,13 @@ u32 ce_est_evm, fsm_stage, constellation, hierarchy; /* Calculated by: 10 * log2(Norm * pow(2, 11)) * pow(2, 10) */ - static const long SnrDbNum[3][4] = { + static const int SnrDbNum[3][4] = { {122880, 122880, 122880, 122880, }, {146657, 146657, 156897, 171013, }, {167857, 167857, 173127, 181810, }, }; - static const int snrMaxDb[3] = { 23, 26, 29, }; + static const short snr_max_db[3] = { 23, 26, 29, }; dbg("%s", __func__); @@ -786,14 +777,7 @@ num = div_u64(num, RTL2832_SNR_DB_DEN); num *= 0xffff; - num = div_u64(num, snrMaxDb[constellation]); - - if (num > 0xffff) - *snr = 0xffff; - else if (num < 0) - *snr = 0; - else - *snr = 0xffff & num; + num = div_u64(num, snr_max_db[constellation]); return ret; @@ -820,7 +804,6 @@ err: info("%s: failed=%d", __func__, ret); - *ber = 19616; return ret; } @@ -888,10 +871,10 @@ ret = rtl2832_rd_demod_reg(priv, DVBT_FSM_STAGE, &fsm_stage); if (ret) - goto err; + goto err; if (fsm_stage < 10) - *strength = 0; + *strength = 0; else { /* if_agc is read as a 10bit binary */ ret = rtl2832_rd_demod_reg(priv, DVBT_IF_AGC_VAL, &if_agc_raw); @@ -903,8 +886,7 @@ else if_agc = -(~(if_agc_raw-1) & 0x1ff); - *strength = 55 - if_agc / 182; - *strength |= *strength << 8; + *strength = 55 - if_agc / 182 * 256; } return 0; err: @@ -950,7 +932,7 @@ memcpy(&priv->fe.ops, &rtl2832_ops, sizeof(struct dvb_frontend_ops)); priv->fe.demodulator_priv = priv; - /* TODO implement sleep mode depending on RC */ + /* TODO implement sleep mode */ priv->sleeping = true; return &priv->fe; @@ -962,14 +944,13 @@ EXPORT_SYMBOL(rtl2832_attach); static struct dvb_frontend_ops rtl2832_ops = { - .delsys = { SYS_DVBT }, - .info = { - .name = "Realtek RTL2832 (DVB-T)", - .type = FE_OFDM, - .frequency_min = 50000000, - .frequency_max = 862000000, - .frequency_stepsize = 166667, - .caps = FE_CAN_FEC_1_2 | + .delsys = { SYS_DVBT }, + .info = { + .name = "Realtek RTL2832 (DVB-T)", + .frequency_min = 174000000, + .frequency_max = 862000000, + .frequency_stepsize = 166667, + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | [-- Attachment #3: rtl2832.h.diff --] [-- Type: text/x-patch, Size: 409 bytes --] --- linux/drivers/media/dvb/frontends/rtl2832.h.orig 2012-05-16 06:46:29.763379985 +0200 +++ linux/drivers/media/dvb/frontends/rtl2832.h 2012-05-16 06:20:17.845569005 +0200 @@ -68,13 +68,6 @@ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } - -static inline struct i2c_adapter *rtl2832_get_tuner_i2c_adapter( - struct dvb_frontend *fe -) -{ - return NULL; -} #endif [-- Attachment #4: rtl2832_priv.h.diff --] [-- Type: text/x-patch, Size: 506 bytes --] --- linux/drivers/media/dvb/frontends/rtl2832_priv.h.orig 2012-05-16 06:46:39.478818765 +0200 +++ linux/drivers/media/dvb/frontends/rtl2832_priv.h 2012-05-16 06:20:23.734243672 +0200 @@ -49,19 +49,17 @@ u8 page; /* active register page */ }; -typedef struct { +struct rtl2832_reg_entry { u8 page; u8 start_address; u8 msb; u8 lsb; -} -rtl2832_reg_entry; +}; -typedef struct { +struct rtl2832_reg_value { int reg; u32 value; -} -rtl2832_reg_value; +}; /* Demod register bit names */ ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/5] rtl2832 ver 0.3: suport for RTL2832 demodulator revised version 2012-05-14 1:37 ` Antti Palosaari ` (2 preceding siblings ...) 2012-05-16 5:10 ` poma @ 2012-05-18 19:16 ` Antti Palosaari 3 siblings, 0 replies; 16+ messages in thread From: Antti Palosaari @ 2012-05-18 19:16 UTC (permalink / raw) To: Thomas Mair; +Cc: linux-media On 14.05.2012 04:37, Antti Palosaari wrote: > >> + else { >> + /* if_agc is read as a 10bit binary */ >> + ret = rtl2832_rd_demod_reg(priv, DVBT_IF_AGC_VAL,&if_agc_raw); >> + if (ret) >> + goto err; >> + >> + if (if_agc_raw< (1<< 9)) >> + if_agc = if_agc_raw; >> + else >> + if_agc = -(~(if_agc_raw-1)& 0x1ff); >> + >> + *strength = 55 - if_agc / 182; >> + *strength |= *strength<< 8; > > That calculation shows doubtful. Why not to scale directly to the > counter. Now you divide it by 182 and after that multiply 256 (<< 8 > means same as multiply by 256). It is stupid calculation. I was playing with RTL2830 statistics and thus it is quite similar I ended up looking that again. It is not so wrong as I commented. The idea of whole calculation is to underflow unsigned 8 bit value to the *strength. But it goes wrong here because you don't cast it as unsigned char (this should be *strength = (u8) (55 - if_agc / 182);. I implemented that rather similarly for the RTL2830. But it is very poor resolution for some reason... :-( regards Antti -- http://palosaari.fi/ ^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 2/5] rtl28xxu: support for the rtl2832 demod driver 2012-05-12 18:08 [PATCH 0/5] support rtl2832 demodulator Thomas Mair 2012-05-12 18:08 ` [PATCH 1/5] rtl2832 ver 0.3: suport for RTL2832 demodulator revised version Thomas Mair @ 2012-05-12 18:08 ` Thomas Mair 2012-05-12 18:08 ` [PATCH 3/5] rtl28xxu: renamed rtl2831_rd/rtl2831_wr to rtl28xx_rd/rtl28xx_wr Thomas Mair ` (3 subsequent siblings) 5 siblings, 0 replies; 16+ messages in thread From: Thomas Mair @ 2012-05-12 18:08 UTC (permalink / raw) To: linux-media; +Cc: Thomas Mair This only adds support for the Terratec Cinergy T Stick Black device. Signed-off-by: Thomas Mair <thomas.mair86@googlemail.com> --- drivers/media/dvb/dvb-usb/Kconfig | 3 + drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + drivers/media/dvb/dvb-usb/rtl28xxu.c | 431 +++++++++++++++++++++++++++++-- 3 files changed, 411 insertions(+), 24 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index be1db75..98dd0d8 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -417,9 +417,12 @@ config DVB_USB_RTL28XXU tristate "Realtek RTL28xxU DVB USB support" depends on DVB_USB && EXPERIMENTAL select DVB_RTL2830 + select DVB_RTL2832 select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_FC0012 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_FC0013 if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the Realtek RTL28xxU DVB USB receiver. diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 2418e41..fd37be0 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -157,6 +157,7 @@ #define USB_PID_TERRATEC_CINERGY_T_STICK 0x0093 #define USB_PID_TERRATEC_CINERGY_T_STICK_RC 0x0097 #define USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC 0x0099 +#define USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1 0x00a9 #define USB_PID_TWINHAN_VP7041_COLD 0x3201 #define USB_PID_TWINHAN_VP7041_WARM 0x3202 #define USB_PID_TWINHAN_VP7020_COLD 0x3203 diff --git a/drivers/media/dvb/dvb-usb/rtl28xxu.c b/drivers/media/dvb/dvb-usb/rtl28xxu.c index 8f4736a..a2b3d73 100644 --- a/drivers/media/dvb/dvb-usb/rtl28xxu.c +++ b/drivers/media/dvb/dvb-usb/rtl28xxu.c @@ -3,6 +3,7 @@ * * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> * Copyright (C) 2011 Antti Palosaari <crope@iki.fi> + * Copyright (C) 2012 Thomas Mair <thomas.mair86@googlemail.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,10 +23,12 @@ #include "rtl28xxu.h" #include "rtl2830.h" +#include "rtl2832.h" #include "qt1010.h" #include "mt2060.h" #include "mxl5005s.h" +#include "fc0012.h" /* debug */ static int dvb_usb_rtl28xxu_debug; @@ -378,34 +381,153 @@ err: return ret; } +static struct rtl2832_config rtl28xxu_rtl2832_fc0012_config = { + .i2c_addr = 0x10, /* 0x20 */ + .xtal = 28800000, + .if_dvbt = 0, + .tuner = TUNER_RTL2832_FC0012 +}; + + +static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d, + int cmd, int arg) +{ + int ret; + u8 val; + + deb_info("%s cmd=%d arg=%d\n", __func__, cmd, arg); + switch (cmd) { + case FC_FE_CALLBACK_VHF_ENABLE: + /* set output values */ + ret = rtl2831_rd_reg(d, SYS_GPIO_OUT_VAL, &val); + if (ret) + goto err; + + if (arg) + val &= 0xbf; /* set GPIO6 low */ + else + val |= 0x40; /* set GPIO6 high */ + + + ret = rtl2831_wr_reg(d, SYS_GPIO_OUT_VAL, val); + if (ret) + goto err; + break; + default: + ret = -EINVAL; + goto err; + } + return 0; + +err: + err("%s: failed=%d\n", __func__, ret); + + return ret; +} + + +static int rtl2832u_fc0013_tuner_callback(struct dvb_usb_device *d, + int cmd, int arg) +{ + /* TODO implement*/ + return 0; +} + +static int rtl2832u_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) +{ + struct rtl28xxu_priv *priv = d->priv; + + switch (priv->tuner) { + case TUNER_RTL2832_FC0012: + return rtl2832u_fc0012_tuner_callback(d, cmd, arg); + + case TUNER_RTL2832_FC0013: + return rtl2832u_fc0013_tuner_callback(d, cmd, arg); + default: + break; + } + + return -ENODEV; +} + +static int rtl2832u_frontend_callback(void *adapter_priv, int component, + int cmd, int arg) +{ + struct i2c_adapter *adap = adapter_priv; + struct dvb_usb_device *d = i2c_get_adapdata(adap); + + switch (component) { + case DVB_FRONTEND_COMPONENT_TUNER: + return rtl2832u_tuner_callback(d, cmd, arg); + default: + break; + } + + return -EINVAL; +} + + + + static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) { int ret; struct rtl28xxu_priv *priv = adap->dev->priv; - u8 buf[1]; + struct rtl2832_config *rtl2832_config; + + u8 buf[2], val; /* open RTL2832U/RTL2832 I2C gate */ struct rtl28xxu_req req_gate_open = {0x0120, 0x0011, 0x0001, "\x18"}; /* close RTL2832U/RTL2832 I2C gate */ struct rtl28xxu_req req_gate_close = {0x0120, 0x0011, 0x0001, "\x10"}; + /* for FC0012 tuner probe */ + struct rtl28xxu_req req_fc0012 = {0x00c6, CMD_I2C_RD, 1, buf}; + /* for FC0013 tuner probe */ + struct rtl28xxu_req req_fc0013 = {0x00c6, CMD_I2C_RD, 1, buf}; + /* for MT2266 tuner probe */ + struct rtl28xxu_req req_mt2266 = {0x00c0, CMD_I2C_RD, 1, buf}; /* for FC2580 tuner probe */ struct rtl28xxu_req req_fc2580 = {0x01ac, CMD_I2C_RD, 1, buf}; + /* for MT2063 tuner probe */ + struct rtl28xxu_req req_mt2063 = {0x00c0, CMD_I2C_RD, 1, buf}; + /* for MAX3543 tuner probe */ + struct rtl28xxu_req req_max3543 = {0x00c0, CMD_I2C_RD, 1, buf}; + /* for TUA9001 tuner probe */ + struct rtl28xxu_req req_tua9001 = {0x7ec0, CMD_I2C_RD, 2, buf}; + /* for MXL5007T tuner probe */ + struct rtl28xxu_req req_mxl5007t = {0xd9c0, CMD_I2C_RD, 1, buf}; + /* for E4000 tuner probe */ + struct rtl28xxu_req req_e4000 = {0x02c8, CMD_I2C_RD, 1, buf}; + /* for TDA18272 tuner probe */ + struct rtl28xxu_req req_tda18272 = {0x00c0, CMD_I2C_RD, 2, buf}; deb_info("%s:\n", __func__); - /* GPIO direction */ - ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a); + + ret = rtl2831_rd_reg(adap->dev, SYS_GPIO_DIR, &val); if (ret) goto err; - /* enable as output GPIO0, GPIO2, GPIO4 */ - ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_EN, 0x15); + val &= 0xbf; + + ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_DIR, val); if (ret) goto err; - ret = rtl2831_wr_reg(adap->dev, SYS_DEMOD_CTL, 0xe8); + + /* enable as output GPIO3 and GPIO6*/ + ret = rtl2831_rd_reg(adap->dev, SYS_GPIO_OUT_EN, &val); if (ret) goto err; + val |= 0x48; + + ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_EN, val); + if (ret) + goto err; + + + /* * Probe used tuner. We need to know used tuner before demod attach * since there is some demod params needed to set according to tuner. @@ -416,15 +538,95 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) if (ret) goto err; + priv->tuner = TUNER_NONE; + + /* check FC0012 ID register; reg=00 val=a1 */ + ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc0012); + if (ret == 0 && buf[0] == 0xa1) { + priv->tuner = TUNER_RTL2832_FC0012; + rtl2832_config = &rtl28xxu_rtl2832_fc0012_config; + info("%s: FC0012 tuner found\n", __func__); + goto found; + } + + /* check FC0013 ID register; reg=00 val=a3 */ + ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc0013); + if (ret == 0 && buf[0] == 0xa3) { + priv->tuner = TUNER_RTL2832_FC0013; + info("%s: FC0013 tuner found\n", __func__); + goto found; + } + + /* check MT2266 ID register; reg=00 val=85 */ + ret = rtl28xxu_ctrl_msg(adap->dev, &req_mt2266); + if (ret == 0 && buf[0] == 0x85) { + priv->tuner = TUNER_RTL2832_MT2266; + /* TODO implement tuner */ + info("%s: MT2266 tuner found\n", __func__); + goto found; + } + /* check FC2580 ID register; reg=01 val=56 */ ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc2580); if (ret == 0 && buf[0] == 0x56) { priv->tuner = TUNER_RTL2832_FC2580; - deb_info("%s: FC2580\n", __func__); + /* TODO implement tuner */ + info("%s: FC2580 tuner found\n", __func__); + goto found; + } + + /* check MT2063 ID register; reg=00 val=9e || 9c */ + ret = rtl28xxu_ctrl_msg(adap->dev, &req_mt2063); + if (ret == 0 && (buf[0] == 0x9e || buf[0] == 0x9c)) { + priv->tuner = TUNER_RTL2832_MT2063; + /* TODO implement tuner */ + info("%s: MT2063 tuner found\n", __func__); + goto found; + } + + /* check MAX3543 ID register; reg=00 val=38 */ + ret = rtl28xxu_ctrl_msg(adap->dev, &req_max3543); + if (ret == 0 && buf[0] == 0x38) { + priv->tuner = TUNER_RTL2832_MAX3543; + /* TODO implement tuner */ + info("%s: MAX3534 tuner found\n", __func__); + goto found; + } + + /* check TUA9001 ID register; reg=7e val=2328 */ + ret = rtl28xxu_ctrl_msg(adap->dev, &req_tua9001); + if (ret == 0 && buf[0] == 0x23 && buf[1] == 0x28) { + priv->tuner = TUNER_RTL2832_TUA9001; + /* TODO implement tuner */ + info("%s: TUA9001 tuner found\n", __func__); + goto found; + } + + /* check MXL5007R ID register; reg=d9 val=14 */ + ret = rtl28xxu_ctrl_msg(adap->dev, &req_mxl5007t); + if (ret == 0 && buf[0] == 0x14) { + priv->tuner = TUNER_RTL2832_MXL5007T; + /* TODO implement tuner */ + info("%s: MXL5007T tuner found\n", __func__); + goto found; + } + + /* check E4000 ID register; reg=02 val=40 */ + ret = rtl28xxu_ctrl_msg(adap->dev, &req_e4000); + if (ret == 0 && buf[0] == 0x40) { + priv->tuner = TUNER_RTL2832_E4000; + /* TODO implement tuner */ + info("%s: E4000 tuner found\n", __func__); + goto found; + } + + /* check TDA18272 ID register; reg=00 val=c760 */ + ret = rtl28xxu_ctrl_msg(adap->dev, &req_tda18272); + if (ret == 0 && (buf[0] == 0xc7 || buf[1] == 0x60)) { + priv->tuner = TUNER_RTL2832_TDA18272; + /* TODO implement tuner */ + info("%s: TDA18272 tuner found\n", __func__); goto found; - } else { - deb_info("%s: FC2580 probe failed=%d - %02x\n", - __func__, ret, buf[0]); } /* close demod I2C gate */ @@ -433,8 +635,9 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) goto err; /* tuner not found */ + deb_info("No compatible tuner found"); ret = -ENODEV; - goto err; + return ret; found: /* close demod I2C gate */ @@ -443,9 +646,18 @@ found: goto err; /* attach demodulator */ - /* TODO: */ + adap->fe_adap[0].fe = dvb_attach(rtl2832_attach, rtl2832_config, + &adap->dev->i2c_adap); + if (adap->fe_adap[0].fe == NULL) { + ret = -ENODEV; + goto err; + } + + /* set fe callbacks */ + adap->fe_adap[0].fe->callback = rtl2832u_frontend_callback; return ret; + err: deb_info("%s: failed=%d\n", __func__, ret); return ret; @@ -528,9 +740,15 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) deb_info("%s:\n", __func__); switch (priv->tuner) { - case TUNER_RTL2832_FC2580: - /* TODO: */ - fe = NULL; + case TUNER_RTL2832_FC0012: + fe = dvb_attach(fc0012_attach, adap->fe_adap[0].fe, + &adap->dev->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ); + + /* since fc0012 includs reading the signal strength delegate + * that to the tuner driver */ + adap->fe_adap[0].fe->ops.read_signal_strength = adap->fe_adap[0]. + fe->ops.tuner_ops.get_rf_strength; + return 0; break; default: fe = NULL; @@ -548,7 +766,7 @@ err: return ret; } -static int rtl28xxu_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff) +static int rtl2831u_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff) { int ret; u8 buf[2], gpio; @@ -583,7 +801,33 @@ err: return ret; } -static int rtl28xxu_power_ctrl(struct dvb_usb_device *d, int onoff) +static int rtl2832u_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff) +{ + int ret; + u8 buf[2]; + + deb_info("%s: onoff=%d\n", __func__, onoff); + + + if (onoff) { + buf[0] = 0x00; + buf[1] = 0x00; + } else { + buf[0] = 0x10; /* stall EPA */ + buf[1] = 0x02; /* reset EPA */ + } + + ret = rtl2831_wr_regs(adap->dev, USB_EPA_CTL, buf, 2); + if (ret) + goto err; + + return ret; +err: + deb_info("%s: failed=%d\n", __func__, ret); + return ret; +} + +static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff) { int ret; u8 gpio, sys0; @@ -631,6 +875,128 @@ err: return ret; } +static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff) +{ + int ret; + u8 val; + + deb_info("%s: onoff=%d\n", __func__, onoff); + + if (onoff) { + /* set output values */ + ret = rtl2831_rd_reg(d, SYS_GPIO_OUT_VAL, &val); + if (ret) + goto err; + + val |= 0x08; + val &= 0xef; + + ret = rtl2831_wr_reg(d, SYS_GPIO_OUT_VAL, val); + if (ret) + goto err; + + /* demod_ctl_1 */ + ret = rtl2831_rd_reg(d, SYS_DEMOD_CTL1, &val); + if (ret) + goto err; + + val &= 0xef; + + ret = rtl2831_wr_reg(d, SYS_DEMOD_CTL1, val); + if (ret) + goto err; + + /* demod control */ + /* PLL enable */ + ret = rtl2831_rd_reg(d, SYS_DEMOD_CTL, &val); + if (ret) + goto err; + + /* bit 7 to 1 */ + val |= 0x80; + + ret = rtl2831_wr_reg(d, SYS_DEMOD_CTL, val); + if (ret) + goto err; + + /* demod HW reset */ + ret = rtl2831_rd_reg(d, SYS_DEMOD_CTL, &val); + if (ret) + goto err; + /* bit 5 to 0 */ + val &= 0xdf; + + ret = rtl2831_wr_reg(d, SYS_DEMOD_CTL, val); + if (ret) + goto err; + + ret = rtl2831_rd_reg(d, SYS_DEMOD_CTL, &val); + if (ret) + goto err; + + val |= 0x20; + + ret = rtl2831_wr_reg(d, SYS_DEMOD_CTL, val); + if (ret) + goto err; + + mdelay(5); + + /*enable ADC_Q and ADC_I */ + ret = rtl2831_rd_reg(d, SYS_DEMOD_CTL, &val); + if (ret) + goto err; + + val |= 0x48; + + ret = rtl2831_wr_reg(d, SYS_DEMOD_CTL, val); + if (ret) + goto err; + + + } else { + /* demod_ctl_1 */ + ret = rtl2831_rd_reg(d, SYS_DEMOD_CTL1, &val); + if (ret) + goto err; + + val |= 0x0c; + + ret = rtl2831_wr_reg(d, SYS_DEMOD_CTL1, val); + if (ret) + goto err; + + /* set output values */ + ret = rtl2831_rd_reg(d, SYS_GPIO_OUT_VAL, &val); + if (ret) + goto err; + + val |= 0x10; + + ret = rtl2831_wr_reg(d, SYS_GPIO_OUT_VAL, val); + if (ret) + goto err; + + /* demod control */ + ret = rtl2831_rd_reg(d, SYS_DEMOD_CTL, &val); + if (ret) + goto err; + + val &= 0x37; + + ret = rtl2831_wr_reg(d, SYS_DEMOD_CTL, val); + if (ret) + goto err; + + } + + return ret; +err: + deb_info("%s: failed=%d\n", __func__, ret); + return ret; +} + + static int rtl2831u_rc_query(struct dvb_usb_device *d) { int ret, i; @@ -768,6 +1134,7 @@ enum rtl28xxu_usb_table_entry { RTL2831U_0BDA_2831, RTL2831U_14AA_0160, RTL2831U_14AA_0161, + RTL2832U_0CCD_00A9, }; static struct usb_device_id rtl28xxu_table[] = { @@ -780,6 +1147,8 @@ static struct usb_device_id rtl28xxu_table[] = { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT_2)}, /* RTL2832U */ + [RTL2832U_0CCD_00A9] = { + USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1)}, {} /* terminating entry */ }; @@ -802,7 +1171,7 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = { { .frontend_attach = rtl2831u_frontend_attach, .tuner_attach = rtl2831u_tuner_attach, - .streaming_ctrl = rtl28xxu_streaming_ctrl, + .streaming_ctrl = rtl2831u_streaming_ctrl, .stream = { .type = USB_BULK, .count = 6, @@ -818,7 +1187,7 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = { } }, - .power_ctrl = rtl28xxu_power_ctrl, + .power_ctrl = rtl2831u_power_ctrl, .rc.core = { .protocol = RC_TYPE_NEC, @@ -864,7 +1233,7 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = { { .frontend_attach = rtl2832u_frontend_attach, .tuner_attach = rtl2832u_tuner_attach, - .streaming_ctrl = rtl28xxu_streaming_ctrl, + .streaming_ctrl = rtl2832u_streaming_ctrl, .stream = { .type = USB_BULK, .count = 6, @@ -880,7 +1249,7 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = { } }, - .power_ctrl = rtl28xxu_power_ctrl, + .power_ctrl = rtl2832u_power_ctrl, .rc.core = { .protocol = RC_TYPE_NEC, @@ -893,10 +1262,13 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = { .i2c_algo = &rtl28xxu_i2c_algo, - .num_device_descs = 0, /* disabled as no support for RTL2832 */ + .num_device_descs = 1, .devices = { { - .name = "Realtek RTL2832U reference design", + .name = "Terratec Cinergy T Stick Black", + .warm_ids = { + &rtl28xxu_table[RTL2832U_0CCD_00A9], + }, }, } }, @@ -907,6 +1279,7 @@ static int rtl28xxu_probe(struct usb_interface *intf, const struct usb_device_id *id) { int ret, i; + u8 val; int properties_count = ARRAY_SIZE(rtl28xxu_properties); struct dvb_usb_device *d; @@ -926,15 +1299,24 @@ static int rtl28xxu_probe(struct usb_interface *intf, if (ret) goto err; + /* init USB endpoints */ - ret = rtl2831_wr_reg(d, USB_SYSCTL_0, 0x09); + ret = rtl2831_rd_reg(d, USB_SYSCTL_0, &val); + if (ret) + goto err; + + /* enable DMA and Full Packet Mode*/ + val |= 0x09; + ret = rtl2831_wr_reg(d, USB_SYSCTL_0, val); if (ret) goto err; + /* set EPA maximum packet size to 0x0200 */ ret = rtl2831_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4); if (ret) goto err; + /* change EPA FIFO length */ ret = rtl2831_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4); if (ret) goto err; @@ -979,4 +1361,5 @@ module_exit(rtl28xxu_module_exit); MODULE_DESCRIPTION("Realtek RTL28xxU DVB USB driver"); MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); +MODULE_AUTHOR("Thomas Mair <thomas.mair86@googlemail.com>"); MODULE_LICENSE("GPL"); -- 1.7.7.6 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 3/5] rtl28xxu: renamed rtl2831_rd/rtl2831_wr to rtl28xx_rd/rtl28xx_wr 2012-05-12 18:08 [PATCH 0/5] support rtl2832 demodulator Thomas Mair 2012-05-12 18:08 ` [PATCH 1/5] rtl2832 ver 0.3: suport for RTL2832 demodulator revised version Thomas Mair 2012-05-12 18:08 ` [PATCH 2/5] rtl28xxu: support for the rtl2832 demod driver Thomas Mair @ 2012-05-12 18:08 ` Thomas Mair 2012-05-12 18:08 ` [PATCH 4/5] rtl28xxu: support G-Tek Electronics Group Lifeview LV5TDLX DVB-T Thomas Mair ` (2 subsequent siblings) 5 siblings, 0 replies; 16+ messages in thread From: Thomas Mair @ 2012-05-12 18:08 UTC (permalink / raw) To: linux-media; +Cc: Thomas Mair Signed-off-by: Thomas Mair <thomas.mair86@googlemail.com> --- drivers/media/dvb/dvb-usb/rtl28xxu.c | 102 +++++++++++++++++----------------- 1 files changed, 51 insertions(+), 51 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/rtl28xxu.c b/drivers/media/dvb/dvb-usb/rtl28xxu.c index a2b3d73..86304c6 100644 --- a/drivers/media/dvb/dvb-usb/rtl28xxu.c +++ b/drivers/media/dvb/dvb-usb/rtl28xxu.c @@ -83,7 +83,7 @@ err: return ret; } -static int rtl2831_wr_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len) +static int rtl28xx_wr_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len) { struct rtl28xxu_req req; @@ -119,12 +119,12 @@ static int rtl2831_rd_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len) return rtl28xxu_ctrl_msg(d, &req); } -static int rtl2831_wr_reg(struct dvb_usb_device *d, u16 reg, u8 val) +static int rtl28xx_wr_reg(struct dvb_usb_device *d, u16 reg, u8 val) { - return rtl2831_wr_regs(d, reg, &val, 1); + return rtl28xx_wr_regs(d, reg, &val, 1); } -static int rtl2831_rd_reg(struct dvb_usb_device *d, u16 reg, u8 *val) +static int rtl28xx_rd_reg(struct dvb_usb_device *d, u16 reg, u8 *val) { return rtl2831_rd_regs(d, reg, val, 1); } @@ -311,12 +311,12 @@ static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap) */ /* GPIO direction */ - ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a); + ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a); if (ret) goto err; /* enable as output GPIO0, GPIO2, GPIO4 */ - ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_EN, 0x15); + ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_OUT_EN, 0x15); if (ret) goto err; @@ -399,7 +399,7 @@ static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d, switch (cmd) { case FC_FE_CALLBACK_VHF_ENABLE: /* set output values */ - ret = rtl2831_rd_reg(d, SYS_GPIO_OUT_VAL, &val); + ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val); if (ret) goto err; @@ -409,7 +409,7 @@ static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d, val |= 0x40; /* set GPIO6 high */ - ret = rtl2831_wr_reg(d, SYS_GPIO_OUT_VAL, val); + ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val); if (ret) goto err; break; @@ -504,25 +504,25 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) deb_info("%s:\n", __func__); - ret = rtl2831_rd_reg(adap->dev, SYS_GPIO_DIR, &val); + ret = rtl28xx_rd_reg(adap->dev, SYS_GPIO_DIR, &val); if (ret) goto err; val &= 0xbf; - ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_DIR, val); + ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_DIR, val); if (ret) goto err; /* enable as output GPIO3 and GPIO6*/ - ret = rtl2831_rd_reg(adap->dev, SYS_GPIO_OUT_EN, &val); + ret = rtl28xx_rd_reg(adap->dev, SYS_GPIO_OUT_EN, &val); if (ret) goto err; val |= 0x48; - ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_EN, val); + ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_OUT_EN, val); if (ret) goto err; @@ -773,7 +773,7 @@ static int rtl2831u_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff) deb_info("%s: onoff=%d\n", __func__, onoff); - ret = rtl2831_rd_reg(adap->dev, SYS_GPIO_OUT_VAL, &gpio); + ret = rtl28xx_rd_reg(adap->dev, SYS_GPIO_OUT_VAL, &gpio); if (ret) goto err; @@ -787,11 +787,11 @@ static int rtl2831u_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff) gpio &= (~0x04); /* LED off */ } - ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_VAL, gpio); + ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_OUT_VAL, gpio); if (ret) goto err; - ret = rtl2831_wr_regs(adap->dev, USB_EPA_CTL, buf, 2); + ret = rtl28xx_wr_regs(adap->dev, USB_EPA_CTL, buf, 2); if (ret) goto err; @@ -817,7 +817,7 @@ static int rtl2832u_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff) buf[1] = 0x02; /* reset EPA */ } - ret = rtl2831_wr_regs(adap->dev, USB_EPA_CTL, buf, 2); + ret = rtl28xx_wr_regs(adap->dev, USB_EPA_CTL, buf, 2); if (ret) goto err; @@ -835,12 +835,12 @@ static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff) deb_info("%s: onoff=%d\n", __func__, onoff); /* demod adc */ - ret = rtl2831_rd_reg(d, SYS_SYS0, &sys0); + ret = rtl28xx_rd_reg(d, SYS_SYS0, &sys0); if (ret) goto err; /* tuner power, read GPIOs */ - ret = rtl2831_rd_reg(d, SYS_GPIO_OUT_VAL, &gpio); + ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &gpio); if (ret) goto err; @@ -860,12 +860,12 @@ static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff) deb_info("%s: WR SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, sys0, gpio); /* demod adc */ - ret = rtl2831_wr_reg(d, SYS_SYS0, sys0); + ret = rtl28xx_wr_reg(d, SYS_SYS0, sys0); if (ret) goto err; /* tuner power, write GPIOs */ - ret = rtl2831_wr_reg(d, SYS_GPIO_OUT_VAL, gpio); + ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, gpio); if (ret) goto err; @@ -884,107 +884,107 @@ static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff) if (onoff) { /* set output values */ - ret = rtl2831_rd_reg(d, SYS_GPIO_OUT_VAL, &val); + ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val); if (ret) goto err; val |= 0x08; val &= 0xef; - ret = rtl2831_wr_reg(d, SYS_GPIO_OUT_VAL, val); + ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val); if (ret) goto err; /* demod_ctl_1 */ - ret = rtl2831_rd_reg(d, SYS_DEMOD_CTL1, &val); + ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL1, &val); if (ret) goto err; val &= 0xef; - ret = rtl2831_wr_reg(d, SYS_DEMOD_CTL1, val); + ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL1, val); if (ret) goto err; /* demod control */ /* PLL enable */ - ret = rtl2831_rd_reg(d, SYS_DEMOD_CTL, &val); + ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val); if (ret) goto err; /* bit 7 to 1 */ val |= 0x80; - ret = rtl2831_wr_reg(d, SYS_DEMOD_CTL, val); + ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val); if (ret) goto err; /* demod HW reset */ - ret = rtl2831_rd_reg(d, SYS_DEMOD_CTL, &val); + ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val); if (ret) goto err; /* bit 5 to 0 */ val &= 0xdf; - ret = rtl2831_wr_reg(d, SYS_DEMOD_CTL, val); + ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val); if (ret) goto err; - ret = rtl2831_rd_reg(d, SYS_DEMOD_CTL, &val); + ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val); if (ret) goto err; val |= 0x20; - ret = rtl2831_wr_reg(d, SYS_DEMOD_CTL, val); + ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val); if (ret) goto err; mdelay(5); /*enable ADC_Q and ADC_I */ - ret = rtl2831_rd_reg(d, SYS_DEMOD_CTL, &val); + ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val); if (ret) goto err; val |= 0x48; - ret = rtl2831_wr_reg(d, SYS_DEMOD_CTL, val); + ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val); if (ret) goto err; } else { /* demod_ctl_1 */ - ret = rtl2831_rd_reg(d, SYS_DEMOD_CTL1, &val); + ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL1, &val); if (ret) goto err; val |= 0x0c; - ret = rtl2831_wr_reg(d, SYS_DEMOD_CTL1, val); + ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL1, val); if (ret) goto err; /* set output values */ - ret = rtl2831_rd_reg(d, SYS_GPIO_OUT_VAL, &val); + ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val); if (ret) goto err; val |= 0x10; - ret = rtl2831_wr_reg(d, SYS_GPIO_OUT_VAL, val); + ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val); if (ret) goto err; /* demod control */ - ret = rtl2831_rd_reg(d, SYS_DEMOD_CTL, &val); + ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val); if (ret) goto err; val &= 0x37; - ret = rtl2831_wr_reg(d, SYS_DEMOD_CTL, val); + ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val); if (ret) goto err; @@ -1023,7 +1023,7 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d) /* init remote controller */ if (!priv->rc_active) { for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { - ret = rtl2831_wr_reg(d, rc_nec_tab[i].reg, + ret = rtl28xx_wr_reg(d, rc_nec_tab[i].reg, rc_nec_tab[i].val); if (ret) goto err; @@ -1053,12 +1053,12 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d) rc_keydown(d->rc_dev, rc_code, 0); - ret = rtl2831_wr_reg(d, SYS_IRRC_SR, 1); + ret = rtl28xx_wr_reg(d, SYS_IRRC_SR, 1); if (ret) goto err; /* repeated intentionally to avoid extra keypress */ - ret = rtl2831_wr_reg(d, SYS_IRRC_SR, 1); + ret = rtl28xx_wr_reg(d, SYS_IRRC_SR, 1); if (ret) goto err; } @@ -1095,7 +1095,7 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d) /* init remote controller */ if (!priv->rc_active) { for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { - ret = rtl2831_wr_reg(d, rc_nec_tab[i].reg, + ret = rtl28xx_wr_reg(d, rc_nec_tab[i].reg, rc_nec_tab[i].val); if (ret) goto err; @@ -1103,14 +1103,14 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d) priv->rc_active = true; } - ret = rtl2831_rd_reg(d, IR_RX_IF, &buf[0]); + ret = rtl28xx_rd_reg(d, IR_RX_IF, &buf[0]); if (ret) goto err; if (buf[0] != 0x83) goto exit; - ret = rtl2831_rd_reg(d, IR_RX_BC, &buf[0]); + ret = rtl28xx_rd_reg(d, IR_RX_BC, &buf[0]); if (ret) goto err; @@ -1119,9 +1119,9 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d) /* TODO: pass raw IR to Kernel IR decoder */ - ret = rtl2831_wr_reg(d, IR_RX_IF, 0x03); - ret = rtl2831_wr_reg(d, IR_RX_BUF_CTRL, 0x80); - ret = rtl2831_wr_reg(d, IR_RX_CTRL, 0x80); + ret = rtl28xx_wr_reg(d, IR_RX_IF, 0x03); + ret = rtl28xx_wr_reg(d, IR_RX_BUF_CTRL, 0x80); + ret = rtl28xx_wr_reg(d, IR_RX_CTRL, 0x80); exit: return ret; @@ -1301,23 +1301,23 @@ static int rtl28xxu_probe(struct usb_interface *intf, /* init USB endpoints */ - ret = rtl2831_rd_reg(d, USB_SYSCTL_0, &val); + ret = rtl28xx_rd_reg(d, USB_SYSCTL_0, &val); if (ret) goto err; /* enable DMA and Full Packet Mode*/ val |= 0x09; - ret = rtl2831_wr_reg(d, USB_SYSCTL_0, val); + ret = rtl28xx_wr_reg(d, USB_SYSCTL_0, val); if (ret) goto err; /* set EPA maximum packet size to 0x0200 */ - ret = rtl2831_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4); + ret = rtl28xx_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4); if (ret) goto err; /* change EPA FIFO length */ - ret = rtl2831_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4); + ret = rtl28xx_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4); if (ret) goto err; -- 1.7.7.6 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 4/5] rtl28xxu: support G-Tek Electronics Group Lifeview LV5TDLX DVB-T 2012-05-12 18:08 [PATCH 0/5] support rtl2832 demodulator Thomas Mair ` (2 preceding siblings ...) 2012-05-12 18:08 ` [PATCH 3/5] rtl28xxu: renamed rtl2831_rd/rtl2831_wr to rtl28xx_rd/rtl28xx_wr Thomas Mair @ 2012-05-12 18:08 ` Thomas Mair 2012-05-12 18:08 ` [PATCH 5/5] rtl28xxu: support Terratec Noxon DAB/DAB+ stick Thomas Mair 2012-05-13 21:18 ` [PATCH] rtl28xxu: removed newlines from info strings Thomas Mair 5 siblings, 0 replies; 16+ messages in thread From: Thomas Mair @ 2012-05-12 18:08 UTC (permalink / raw) To: linux-media; +Cc: Thomas Mair Signed-off-by: Thomas Mair <thomas.mair86@googlemail.com> --- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + drivers/media/dvb/dvb-usb/rtl28xxu.c | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index fd37be0..b0a86e9 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -135,6 +135,7 @@ #define USB_PID_GENIUS_TVGO_DVB_T03 0x4012 #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 +#define USB_PID_GTEK 0xb803 #define USB_PID_INTEL_CE9500 0x9500 #define USB_PID_ITETECH_IT9135 0x9135 #define USB_PID_ITETECH_IT9135_9005 0x9005 diff --git a/drivers/media/dvb/dvb-usb/rtl28xxu.c b/drivers/media/dvb/dvb-usb/rtl28xxu.c index 86304c6..699da68 100644 --- a/drivers/media/dvb/dvb-usb/rtl28xxu.c +++ b/drivers/media/dvb/dvb-usb/rtl28xxu.c @@ -1135,6 +1135,7 @@ enum rtl28xxu_usb_table_entry { RTL2831U_14AA_0160, RTL2831U_14AA_0161, RTL2832U_0CCD_00A9, + RTL2832U_1F4D_B803, }; static struct usb_device_id rtl28xxu_table[] = { @@ -1149,6 +1150,8 @@ static struct usb_device_id rtl28xxu_table[] = { /* RTL2832U */ [RTL2832U_0CCD_00A9] = { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1)}, + [RTL2832U_1F4D_B803] = { + USB_DEVICE(USB_VID_GTEK, USB_PID_GTEK)}, {} /* terminating entry */ }; @@ -1262,7 +1265,7 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = { .i2c_algo = &rtl28xxu_i2c_algo, - .num_device_descs = 1, + .num_device_descs = 2, .devices = { { .name = "Terratec Cinergy T Stick Black", @@ -1270,6 +1273,12 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = { &rtl28xxu_table[RTL2832U_0CCD_00A9], }, }, + { + .name = "G-Tek Electronics Group Lifeview LV5TDLX DVB-T [RTL2832U]", + .warm_ids = { + &rtl28xxu_table[RTL2832U_1F4D_B803], + }, + }, } }, -- 1.7.7.6 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 5/5] rtl28xxu: support Terratec Noxon DAB/DAB+ stick 2012-05-12 18:08 [PATCH 0/5] support rtl2832 demodulator Thomas Mair ` (3 preceding siblings ...) 2012-05-12 18:08 ` [PATCH 4/5] rtl28xxu: support G-Tek Electronics Group Lifeview LV5TDLX DVB-T Thomas Mair @ 2012-05-12 18:08 ` Thomas Mair 2012-05-12 20:47 ` Thomas Mair 2012-05-13 21:18 ` [PATCH] rtl28xxu: removed newlines from info strings Thomas Mair 5 siblings, 1 reply; 16+ messages in thread From: Thomas Mair @ 2012-05-12 18:08 UTC (permalink / raw) To: linux-media; +Cc: Thomas Mair, Hans-Frieder Vogt Signed-off-by: Hans-Frieder Vogt <hfvogt@gmx.net> Signed-off-by: Thomas Mair <thomas.mair86@googlemail.com> --- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + drivers/media/dvb/dvb-usb/rtl28xxu.c | 27 ++++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index b0a86e9..95c9c14 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -244,6 +244,7 @@ #define USB_PID_TERRATEC_H7_2 0x10a3 #define USB_PID_TERRATEC_T3 0x10a0 #define USB_PID_TERRATEC_T5 0x10a1 +#define USB_PID_NOXON_DAB_STICK 0x00b3 #define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e #define USB_PID_PINNACLE_PCTV2000E 0x022c #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228 diff --git a/drivers/media/dvb/dvb-usb/rtl28xxu.c b/drivers/media/dvb/dvb-usb/rtl28xxu.c index 699da68..bacc783 100644 --- a/drivers/media/dvb/dvb-usb/rtl28xxu.c +++ b/drivers/media/dvb/dvb-usb/rtl28xxu.c @@ -29,6 +29,7 @@ #include "mt2060.h" #include "mxl5005s.h" #include "fc0012.h" +#include "fc0013.h" /* debug */ static int dvb_usb_rtl28xxu_debug; @@ -388,6 +389,12 @@ static struct rtl2832_config rtl28xxu_rtl2832_fc0012_config = { .tuner = TUNER_RTL2832_FC0012 }; +static struct rtl2832_config rtl28xxu_rtl2832_fc0013_config = { + .i2c_addr = 0x10, /* 0x20 */ + .xtal = 28800000, + .if_dvbt = 0, + .tuner = TUNER_RTL2832_FC0013 +}; static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) @@ -553,6 +560,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc0013); if (ret == 0 && buf[0] == 0xa3) { priv->tuner = TUNER_RTL2832_FC0013; + rtl2832_config = &rtl28xxu_rtl2832_fc0013_config; info("%s: FC0013 tuner found\n", __func__); goto found; } @@ -750,6 +758,14 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) fe->ops.tuner_ops.get_rf_strength; return 0; break; + case TUNER_RTL2832_FC0013: + fe = dvb_attach(fc0013_attach, adap->fe_adap[0].fe, + &adap->dev->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ); + + /* fc0013 also supports signal strength reading */ + adap->fe_adap[0].fe->ops.read_signal_strength = adap->fe_adap[0] + .fe->ops.tuner_ops.get_rf_strength; + return 0; default: fe = NULL; err("unknown tuner=%d", priv->tuner); @@ -1136,6 +1152,7 @@ enum rtl28xxu_usb_table_entry { RTL2831U_14AA_0161, RTL2832U_0CCD_00A9, RTL2832U_1F4D_B803, + RTL2832U_0CCD_00B3, }; static struct usb_device_id rtl28xxu_table[] = { @@ -1152,6 +1169,8 @@ static struct usb_device_id rtl28xxu_table[] = { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1)}, [RTL2832U_1F4D_B803] = { USB_DEVICE(USB_VID_GTEK, USB_PID_GTEK)}, + [RTL2832U_0CCD_00B3] = { + USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK)}, {} /* terminating entry */ }; @@ -1265,7 +1284,7 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = { .i2c_algo = &rtl28xxu_i2c_algo, - .num_device_descs = 2, + .num_device_descs = 3, .devices = { { .name = "Terratec Cinergy T Stick Black", @@ -1279,6 +1298,12 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = { &rtl28xxu_table[RTL2832U_1F4D_B803], }, }, + { + .name = "NOXON DAB/DAB+ USB dongle", + .warm_ids = { + &rtl28xxu_table[RTL2832U_0CCD_00B3], + }, + }, } }, -- 1.7.7.6 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH 5/5] rtl28xxu: support Terratec Noxon DAB/DAB+ stick 2012-05-12 18:08 ` [PATCH 5/5] rtl28xxu: support Terratec Noxon DAB/DAB+ stick Thomas Mair @ 2012-05-12 20:47 ` Thomas Mair 0 siblings, 0 replies; 16+ messages in thread From: Thomas Mair @ 2012-05-12 20:47 UTC (permalink / raw) To: linux-media The patch contains two small errors that prevent its application. This is the fixed version. Signed-off-by: Hans-Frieder Vogt <hfvogt@gmx.net> Signed-off-by: Thomas Mair <thomas.mair86@googlemail.com> --- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + drivers/media/dvb/dvb-usb/rtl28xxu.c | 27 ++++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index b0a86e9..95c9c14 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -244,6 +244,7 @@ #define USB_PID_TERRATEC_H7_2 0x10a3 #define USB_PID_TERRATEC_T3 0x10a0 #define USB_PID_TERRATEC_T5 0x10a1 +#define USB_PID_NOXON_DAB_STICK 0x00b3 #define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e #define USB_PID_PINNACLE_PCTV2000E 0x022c #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228 diff --git a/drivers/media/dvb/dvb-usb/rtl28xxu.c b/drivers/media/dvb/dvb-usb/rtl28xxu.c index 699da68..bacc783 100644 --- a/drivers/media/dvb/dvb-usb/rtl28xxu.c +++ b/drivers/media/dvb/dvb-usb/rtl28xxu.c @@ -29,6 +29,7 @@ #include "mt2060.h" #include "mxl5005s.h" #include "fc0012.h" +#include "fc0013.h" /* debug */ static int dvb_usb_rtl28xxu_debug; @@ -388,6 +389,12 @@ static struct rtl2832_config rtl28xxu_rtl2832_fc0012_config = { .tuner = TUNER_RTL2832_FC0012 }; +static struct rtl2832_config rtl28xxu_rtl2832_fc0013_config = { + .i2c_addr = 0x10, /* 0x20 */ + .xtal = 28800000, + .if_dvbt = 0, + .tuner = TUNER_RTL2832_FC0013 +}; static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) @@ -553,6 +560,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc0013); if (ret == 0 && buf[0] == 0xa3) { priv->tuner = TUNER_RTL2832_FC0013; + rtl2832_config = &rtl28xxu_rtl2832_fc0013_config; info("%s: FC0013 tuner found\n", __func__); goto found; } @@ -750,6 +758,14 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) fe->ops.tuner_ops.get_rf_strength; return 0; break; + case TUNER_RTL2832_FC0013: + fe = dvb_attach(fc0013_attach, adap->fe_adap[0].fe, + &adap->dev->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ); + + /* fc0013 also supports signal strength reading */ + adap->fe_adap[0].fe->ops.read_signal_strength = adap->fe_adap[0] + .fe->ops.tuner_ops.get_rf_strength; + return 0; default: fe = NULL; err("unknown tuner=%d", priv->tuner); @@ -1136,6 +1152,7 @@ enum rtl28xxu_usb_table_entry { RTL2831U_14AA_0161, RTL2832U_0CCD_00A9, RTL2832U_1F4D_B803, + RTL2832U_0CCD_00B3, }; static struct usb_device_id rtl28xxu_table[] = { @@ -1152,6 +1169,8 @@ static struct usb_device_id rtl28xxu_table[] = { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1)}, [RTL2832U_1F4D_B803] = { USB_DEVICE(USB_VID_GTEK, USB_PID_GTEK)}, + [RTL2832U_0CCD_00B3] = { + USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK)}, {} /* terminating entry */ }; @@ -1265,7 +1284,7 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = { .i2c_algo = &rtl28xxu_i2c_algo, - .num_device_descs = 2, + .num_device_descs = 3, .devices = { { .name = "Terratec Cinergy T Stick Black", @@ -1279,6 +1298,12 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = { &rtl28xxu_table[RTL2832U_1F4D_B803], }, }, + { + .name = "NOXON DAB/DAB+ USB dongle", + .warm_ids = { + &rtl28xxu_table[RTL2832U_0CCD_00B3], + }, + }, } }, -- 1.7.7.6 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH] rtl28xxu: removed newlines from info strings 2012-05-12 18:08 [PATCH 0/5] support rtl2832 demodulator Thomas Mair ` (4 preceding siblings ...) 2012-05-12 18:08 ` [PATCH 5/5] rtl28xxu: support Terratec Noxon DAB/DAB+ stick Thomas Mair @ 2012-05-13 21:18 ` Thomas Mair 5 siblings, 0 replies; 16+ messages in thread From: Thomas Mair @ 2012-05-13 21:18 UTC (permalink / raw) To: Antti Palosaari; +Cc: Thomas Mair, Linux Media Mailing List Signed-off-by: Thomas Mair <thomas.mair86@googlemail.com> --- drivers/media/dvb/dvb-usb/rtl28xxu.c | 20 ++++++++++---------- 1 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/rtl28xxu.c b/drivers/media/dvb/dvb-usb/rtl28xxu.c index ef02f0f..f10cac2 100644 --- a/drivers/media/dvb/dvb-usb/rtl28xxu.c +++ b/drivers/media/dvb/dvb-usb/rtl28xxu.c @@ -552,7 +552,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) if (ret == 0 && buf[0] == 0xa1) { priv->tuner = TUNER_RTL2832_FC0012; rtl2832_config = &rtl28xxu_rtl2832_fc0012_config; - info("%s: FC0012 tuner found\n", __func__); + info("%s: FC0012 tuner found", __func__); goto found; } @@ -561,7 +561,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) if (ret == 0 && buf[0] == 0xa3) { priv->tuner = TUNER_RTL2832_FC0013; rtl2832_config = &rtl28xxu_rtl2832_fc0013_config; - info("%s: FC0013 tuner found\n", __func__); + info("%s: FC0013 tuner found", __func__); goto found; } @@ -570,7 +570,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) if (ret == 0 && buf[0] == 0x85) { priv->tuner = TUNER_RTL2832_MT2266; /* TODO implement tuner */ - info("%s: MT2266 tuner found\n", __func__); + info("%s: MT2266 tuner found", __func__); goto found; } @@ -579,7 +579,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) if (ret == 0 && buf[0] == 0x56) { priv->tuner = TUNER_RTL2832_FC2580; /* TODO implement tuner */ - info("%s: FC2580 tuner found\n", __func__); + info("%s: FC2580 tuner found", __func__); goto found; } @@ -588,7 +588,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) if (ret == 0 && (buf[0] == 0x9e || buf[0] == 0x9c)) { priv->tuner = TUNER_RTL2832_MT2063; /* TODO implement tuner */ - info("%s: MT2063 tuner found\n", __func__); + info("%s: MT2063 tuner found", __func__); goto found; } @@ -597,7 +597,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) if (ret == 0 && buf[0] == 0x38) { priv->tuner = TUNER_RTL2832_MAX3543; /* TODO implement tuner */ - info("%s: MAX3534 tuner found\n", __func__); + info("%s: MAX3534 tuner found", __func__); goto found; } @@ -606,7 +606,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) if (ret == 0 && buf[0] == 0x23 && buf[1] == 0x28) { priv->tuner = TUNER_RTL2832_TUA9001; /* TODO implement tuner */ - info("%s: TUA9001 tuner found\n", __func__); + info("%s: TUA9001 tuner found", __func__); goto found; } @@ -615,7 +615,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) if (ret == 0 && buf[0] == 0x14) { priv->tuner = TUNER_RTL2832_MXL5007T; /* TODO implement tuner */ - info("%s: MXL5007T tuner found\n", __func__); + info("%s: MXL5007T tuner found", __func__); goto found; } @@ -624,7 +624,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) if (ret == 0 && buf[0] == 0x40) { priv->tuner = TUNER_RTL2832_E4000; /* TODO implement tuner */ - info("%s: E4000 tuner found\n", __func__); + info("%s: E4000 tuner found", __func__); goto found; } @@ -633,7 +633,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) if (ret == 0 && (buf[0] == 0xc7 || buf[1] == 0x60)) { priv->tuner = TUNER_RTL2832_TDA18272; /* TODO implement tuner */ - info("%s: TDA18272 tuner found\n", __func__); + info("%s: TDA18272 tuner found", __func__); goto found; } -- 1.7.7.6 ^ permalink raw reply related [flat|nested] 16+ messages in thread
end of thread, other threads:[~2012-05-18 19:16 UTC | newest] Thread overview: 16+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-05-12 18:08 [PATCH 0/5] support rtl2832 demodulator Thomas Mair 2012-05-12 18:08 ` [PATCH 1/5] rtl2832 ver 0.3: suport for RTL2832 demodulator revised version Thomas Mair 2012-05-12 22:07 ` poma 2012-05-13 18:53 ` Antti Palosaari 2012-05-13 20:56 ` Thomas Mair 2012-05-14 1:37 ` Antti Palosaari 2012-05-14 1:46 ` Antti Palosaari 2012-05-15 15:41 ` Antti Palosaari 2012-05-16 5:10 ` poma 2012-05-18 19:16 ` Antti Palosaari 2012-05-12 18:08 ` [PATCH 2/5] rtl28xxu: support for the rtl2832 demod driver Thomas Mair 2012-05-12 18:08 ` [PATCH 3/5] rtl28xxu: renamed rtl2831_rd/rtl2831_wr to rtl28xx_rd/rtl28xx_wr Thomas Mair 2012-05-12 18:08 ` [PATCH 4/5] rtl28xxu: support G-Tek Electronics Group Lifeview LV5TDLX DVB-T Thomas Mair 2012-05-12 18:08 ` [PATCH 5/5] rtl28xxu: support Terratec Noxon DAB/DAB+ stick Thomas Mair 2012-05-12 20:47 ` Thomas Mair 2012-05-13 21:18 ` [PATCH] rtl28xxu: removed newlines from info strings Thomas Mair
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).