diff options
Diffstat (limited to 'drivers/media/dvb-frontends/cxd2841er.c')
-rw-r--r-- | drivers/media/dvb-frontends/cxd2841er.c | 302 |
1 files changed, 205 insertions, 97 deletions
diff --git a/drivers/media/dvb-frontends/cxd2841er.c b/drivers/media/dvb-frontends/cxd2841er.c index ce37dc2e89c7..08f67d60a7d9 100644 --- a/drivers/media/dvb-frontends/cxd2841er.c +++ b/drivers/media/dvb-frontends/cxd2841er.c @@ -38,6 +38,8 @@ #define MAX_WRITE_REGSIZE 16 #define LOG2_E_100X 144 +#define INTLOG10X100(x) ((u32) (((u64) intlog10(x) * 100) >> 24)) + /* DVB-C constellation */ enum sony_dvbc_constellation_t { SONY_DVBC_CONSTELLATION_16QAM, @@ -65,6 +67,7 @@ struct cxd2841er_priv { u8 system; enum cxd2841er_xtal xtal; enum fe_caps caps; + u32 flags; }; static const struct cxd2841er_cnr_data s_cn_data[] = { @@ -201,11 +204,6 @@ static const struct cxd2841er_cnr_data s2_cn_data[] = { { 0x0016, 19700 }, { 0x0015, 19900 }, { 0x0014, 20000 }, }; -#define MAKE_IFFREQ_CONFIG(iffreq) ((u32)(((iffreq)/41.0)*16777216.0 + 0.5)) -#define MAKE_IFFREQ_CONFIG_XTAL(xtal, iffreq) ((xtal == SONY_XTAL_24000) ? \ - (u32)(((iffreq)/48.0)*16777216.0 + 0.5) : \ - (u32)(((iffreq)/41.0)*16777216.0 + 0.5)) - static int cxd2841er_freeze_regs(struct cxd2841er_priv *priv); static int cxd2841er_unfreeze_regs(struct cxd2841er_priv *priv); @@ -214,10 +212,8 @@ static void cxd2841er_i2c_debug(struct cxd2841er_priv *priv, const u8 *data, u32 len) { dev_dbg(&priv->i2c->dev, - "cxd2841er: I2C %s addr %02x reg 0x%02x size %d\n", - (write == 0 ? "read" : "write"), addr, reg, len); - print_hex_dump_bytes("cxd2841er: I2C data: ", - DUMP_PREFIX_OFFSET, data, len); + "cxd2841er: I2C %s addr %02x reg 0x%02x size %d data %*ph\n", + (write == 0 ? "read" : "write"), addr, reg, len, len, data); } static int cxd2841er_write_regs(struct cxd2841er_priv *priv, @@ -284,17 +280,8 @@ static int cxd2841er_read_regs(struct cxd2841er_priv *priv, } }; - ret = i2c_transfer(priv->i2c, &msg[0], 1); - if (ret >= 0 && ret != 1) - ret = -EIO; - if (ret < 0) { - dev_warn(&priv->i2c->dev, - "%s: i2c rw failed=%d addr=%02x reg=%02x\n", - KBUILD_MODNAME, ret, i2c_addr, reg); - return ret; - } - ret = i2c_transfer(priv->i2c, &msg[1], 1); - if (ret >= 0 && ret != 1) + ret = i2c_transfer(priv->i2c, msg, 2); + if (ret >= 0 && ret != 2) ret = -EIO; if (ret < 0) { dev_warn(&priv->i2c->dev, @@ -327,6 +314,49 @@ static int cxd2841er_set_reg_bits(struct cxd2841er_priv *priv, return cxd2841er_write_reg(priv, addr, reg, data); } +static u32 cxd2841er_calc_iffreq_xtal(enum cxd2841er_xtal xtal, u32 ifhz) +{ + u64 tmp; + + tmp = (u64) ifhz * 16777216; + do_div(tmp, ((xtal == SONY_XTAL_24000) ? 48000000 : 41000000)); + + return (u32) tmp; +} + +static u32 cxd2841er_calc_iffreq(u32 ifhz) +{ + return cxd2841er_calc_iffreq_xtal(SONY_XTAL_20500, ifhz); +} + +static int cxd2841er_get_if_hz(struct cxd2841er_priv *priv, u32 def_hz) +{ + u32 hz; + + if (priv->frontend.ops.tuner_ops.get_if_frequency + && (priv->flags & CXD2841ER_AUTO_IFHZ)) + priv->frontend.ops.tuner_ops.get_if_frequency( + &priv->frontend, &hz); + else + hz = def_hz; + + return hz; +} + +static int cxd2841er_tuner_set(struct dvb_frontend *fe) +{ + struct cxd2841er_priv *priv = fe->demodulator_priv; + + if ((priv->flags & CXD2841ER_USE_GATECTRL) && fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if (fe->ops.tuner_ops.set_params) + fe->ops.tuner_ops.set_params(fe); + if ((priv->flags & CXD2841ER_USE_GATECTRL) && fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return 0; +} + static int cxd2841er_dvbs2_set_symbol_rate(struct cxd2841er_priv *priv, u32 symbol_rate) { @@ -884,6 +914,18 @@ static void cxd2841er_set_ts_clock_mode(struct cxd2841er_priv *priv, /* * slave Bank Addr Bit default Name + * <SLV-T> 00h C4h [1:0] 2'b?? OSERCKMODE + */ + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xc4, + ((priv->flags & CXD2841ER_TS_SERIAL) ? 0x01 : 0x00), 0x03); + /* + * slave Bank Addr Bit default Name + * <SLV-T> 00h D1h [1:0] 2'b?? OSERDUTYMODE + */ + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xd1, + ((priv->flags & CXD2841ER_TS_SERIAL) ? 0x01 : 0x00), 0x03); + /* + * slave Bank Addr Bit default Name * <SLV-T> 00h D9h [7:0] 8'h08 OTSCKPERIOD */ cxd2841er_write_reg(priv, I2C_SLVT, 0xd9, 0x08); @@ -897,7 +939,8 @@ static void cxd2841er_set_ts_clock_mode(struct cxd2841er_priv *priv, * slave Bank Addr Bit default Name * <SLV-T> 00h 33h [1:0] 2'b01 OREG_CKSEL_TSIF */ - cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x33, 0x00, 0x03); + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x33, + ((priv->flags & CXD2841ER_TS_SERIAL) ? 0x01 : 0x00), 0x03); /* * Enable TS IF Clock * slave Bank Addr Bit default Name @@ -1421,11 +1464,11 @@ static int cxd2841er_read_ber_i(struct cxd2841er_priv *priv, cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x60); cxd2841er_read_regs(priv, I2C_SLVT, 0x5B, pktnum, sizeof(pktnum)); cxd2841er_read_regs(priv, I2C_SLVT, 0x16, data, sizeof(data)); + cxd2841er_unfreeze_regs(priv); if (!pktnum[0] && !pktnum[1]) { dev_dbg(&priv->i2c->dev, "%s(): no valid BER data\n", __func__); - cxd2841er_unfreeze_regs(priv); return -EINVAL; } @@ -1435,7 +1478,6 @@ static int cxd2841er_read_ber_i(struct cxd2841er_priv *priv, dev_dbg(&priv->i2c->dev, "%s(): bit_error=%u bit_count=%u\n", __func__, *bit_error, *bit_count); - cxd2841er_unfreeze_regs(priv); return 0; } @@ -1645,6 +1687,8 @@ static u32 cxd2841er_dvbs_read_snr(struct cxd2841er_priv *priv, * <SLV-T> A1h 12h [7:0] ICPM_QUICKCNDT[7:0] */ cxd2841er_read_regs(priv, I2C_SLVT, 0x10, data, 3); + cxd2841er_unfreeze_regs(priv); + if (data[0] & 0x01) { value = ((u32)(data[1] & 0x1F) << 8) | (u32)(data[2] & 0xFF); min_index = 0; @@ -1687,11 +1731,9 @@ static u32 cxd2841er_dvbs_read_snr(struct cxd2841er_priv *priv, } else { dev_dbg(&priv->i2c->dev, "%s(): no data available\n", __func__); - cxd2841er_unfreeze_regs(priv); return -EINVAL; } done: - cxd2841er_unfreeze_regs(priv); *snr = res; return 0; } @@ -1720,12 +1762,12 @@ static int cxd2841er_read_snr_c(struct cxd2841er_priv *priv, u32 *snr) cxd2841er_read_regs(priv, I2C_SLVT, 0x19, data, 1); qam = (enum sony_dvbc_constellation_t) (data[0] & 0x07); cxd2841er_read_regs(priv, I2C_SLVT, 0x4C, data, 2); + cxd2841er_unfreeze_regs(priv); reg = ((u32)(data[0]&0x1f) << 8) | (u32)data[1]; if (reg == 0) { dev_dbg(&priv->i2c->dev, "%s(): reg value out of range\n", __func__); - cxd2841er_unfreeze_regs(priv); return 0; } @@ -1746,11 +1788,9 @@ static int cxd2841er_read_snr_c(struct cxd2841er_priv *priv, u32 *snr) *snr = -88 * (int32_t)sony_log(reg) + 86999; break; default: - cxd2841er_unfreeze_regs(priv); return -EINVAL; } - cxd2841er_unfreeze_regs(priv); return 0; } @@ -1769,17 +1809,17 @@ static int cxd2841er_read_snr_t(struct cxd2841er_priv *priv, u32 *snr) cxd2841er_freeze_regs(priv); cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10); cxd2841er_read_regs(priv, I2C_SLVT, 0x28, data, sizeof(data)); + cxd2841er_unfreeze_regs(priv); + reg = ((u32)data[0] << 8) | (u32)data[1]; if (reg == 0) { dev_dbg(&priv->i2c->dev, "%s(): reg value out of range\n", __func__); - cxd2841er_unfreeze_regs(priv); return 0; } if (reg > 4996) reg = 4996; - *snr = 10000 * ((intlog10(reg) - intlog10(5350 - reg)) >> 24) + 28500; - cxd2841er_unfreeze_regs(priv); + *snr = 100 * ((INTLOG10X100(reg) - INTLOG10X100(5350 - reg)) + 285); return 0; } @@ -1798,18 +1838,17 @@ static int cxd2841er_read_snr_t2(struct cxd2841er_priv *priv, u32 *snr) cxd2841er_freeze_regs(priv); cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x20); cxd2841er_read_regs(priv, I2C_SLVT, 0x28, data, sizeof(data)); + cxd2841er_unfreeze_regs(priv); + reg = ((u32)data[0] << 8) | (u32)data[1]; if (reg == 0) { dev_dbg(&priv->i2c->dev, "%s(): reg value out of range\n", __func__); - cxd2841er_unfreeze_regs(priv); return 0; } if (reg > 10876) reg = 10876; - *snr = 10000 * ((intlog10(reg) - - intlog10(12600 - reg)) >> 24) + 32000; - cxd2841er_unfreeze_regs(priv); + *snr = 100 * ((INTLOG10X100(reg) - INTLOG10X100(12600 - reg)) + 320); return 0; } @@ -1829,15 +1868,15 @@ static int cxd2841er_read_snr_i(struct cxd2841er_priv *priv, u32 *snr) cxd2841er_freeze_regs(priv); cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x60); cxd2841er_read_regs(priv, I2C_SLVT, 0x28, data, sizeof(data)); + cxd2841er_unfreeze_regs(priv); + reg = ((u32)data[0] << 8) | (u32)data[1]; if (reg == 0) { dev_dbg(&priv->i2c->dev, "%s(): reg value out of range\n", __func__); - cxd2841er_unfreeze_regs(priv); return 0; } *snr = 10000 * (intlog10(reg) >> 24) - 9031; - cxd2841er_unfreeze_regs(priv); return 0; } @@ -2136,7 +2175,7 @@ static int cxd2841er_dvbt2_set_plp_config(struct cxd2841er_priv *priv, static int cxd2841er_sleep_tc_to_active_t2_band(struct cxd2841er_priv *priv, u32 bandwidth) { - u32 iffreq; + u32 iffreq, ifhz; u8 data[MAX_WRITE_REGSIZE]; const uint8_t nominalRate8bw[3][5] = { @@ -2239,10 +2278,12 @@ static int cxd2841er_sleep_tc_to_active_t2_band(struct cxd2841er_priv *priv, /* Group delay equaliser settings for * ASCOT2D, ASCOT2E and ASCOT3 tuners */ - cxd2841er_write_regs(priv, I2C_SLVT, + if (priv->flags & CXD2841ER_ASCOT) + cxd2841er_write_regs(priv, I2C_SLVT, 0xA6, itbCoef8bw[priv->xtal], 14); /* <IF freq setting> */ - iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 4.80); + ifhz = cxd2841er_get_if_hz(priv, 4800000); + iffreq = cxd2841er_calc_iffreq_xtal(priv->xtal, ifhz); data[0] = (u8) ((iffreq >> 16) & 0xff); data[1] = (u8)((iffreq >> 8) & 0xff); data[2] = (u8)(iffreq & 0xff); @@ -2267,10 +2308,12 @@ static int cxd2841er_sleep_tc_to_active_t2_band(struct cxd2841er_priv *priv, /* Group delay equaliser settings for * ASCOT2D, ASCOT2E and ASCOT3 tuners */ - cxd2841er_write_regs(priv, I2C_SLVT, + if (priv->flags & CXD2841ER_ASCOT) + cxd2841er_write_regs(priv, I2C_SLVT, 0xA6, itbCoef7bw[priv->xtal], 14); /* <IF freq setting> */ - iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 4.20); + ifhz = cxd2841er_get_if_hz(priv, 4200000); + iffreq = cxd2841er_calc_iffreq_xtal(priv->xtal, ifhz); data[0] = (u8) ((iffreq >> 16) & 0xff); data[1] = (u8)((iffreq >> 8) & 0xff); data[2] = (u8)(iffreq & 0xff); @@ -2295,10 +2338,12 @@ static int cxd2841er_sleep_tc_to_active_t2_band(struct cxd2841er_priv *priv, /* Group delay equaliser settings for * ASCOT2D, ASCOT2E and ASCOT3 tuners */ - cxd2841er_write_regs(priv, I2C_SLVT, + if (priv->flags & CXD2841ER_ASCOT) + cxd2841er_write_regs(priv, I2C_SLVT, 0xA6, itbCoef6bw[priv->xtal], 14); /* <IF freq setting> */ - iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 3.60); + ifhz = cxd2841er_get_if_hz(priv, 3600000); + iffreq = cxd2841er_calc_iffreq_xtal(priv->xtal, ifhz); data[0] = (u8) ((iffreq >> 16) & 0xff); data[1] = (u8)((iffreq >> 8) & 0xff); data[2] = (u8)(iffreq & 0xff); @@ -2323,10 +2368,12 @@ static int cxd2841er_sleep_tc_to_active_t2_band(struct cxd2841er_priv *priv, /* Group delay equaliser settings for * ASCOT2D, ASCOT2E and ASCOT3 tuners */ - cxd2841er_write_regs(priv, I2C_SLVT, + if (priv->flags & CXD2841ER_ASCOT) + cxd2841er_write_regs(priv, I2C_SLVT, 0xA6, itbCoef5bw[priv->xtal], 14); /* <IF freq setting> */ - iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 3.60); + ifhz = cxd2841er_get_if_hz(priv, 3600000); + iffreq = cxd2841er_calc_iffreq_xtal(priv->xtal, ifhz); data[0] = (u8) ((iffreq >> 16) & 0xff); data[1] = (u8)((iffreq >> 8) & 0xff); data[2] = (u8)(iffreq & 0xff); @@ -2351,10 +2398,12 @@ static int cxd2841er_sleep_tc_to_active_t2_band(struct cxd2841er_priv *priv, /* Group delay equaliser settings for * ASCOT2D, ASCOT2E and ASCOT3 tuners */ - cxd2841er_write_regs(priv, I2C_SLVT, + if (priv->flags & CXD2841ER_ASCOT) + cxd2841er_write_regs(priv, I2C_SLVT, 0xA6, itbCoef17bw[priv->xtal], 14); /* <IF freq setting> */ - iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 3.50); + ifhz = cxd2841er_get_if_hz(priv, 3500000); + iffreq = cxd2841er_calc_iffreq_xtal(priv->xtal, ifhz); data[0] = (u8) ((iffreq >> 16) & 0xff); data[1] = (u8)((iffreq >> 8) & 0xff); data[2] = (u8)(iffreq & 0xff); @@ -2373,7 +2422,7 @@ static int cxd2841er_sleep_tc_to_active_t_band( struct cxd2841er_priv *priv, u32 bandwidth) { u8 data[MAX_WRITE_REGSIZE]; - u32 iffreq; + u32 iffreq, ifhz; u8 nominalRate8bw[3][5] = { /* TRCG Nominal Rate [37:0] */ {0x11, 0xF0, 0x00, 0x00, 0x00}, /* 20.5MHz XTal */ @@ -2450,10 +2499,12 @@ static int cxd2841er_sleep_tc_to_active_t_band( /* Group delay equaliser settings for * ASCOT2D, ASCOT2E and ASCOT3 tuners */ - cxd2841er_write_regs(priv, I2C_SLVT, + if (priv->flags & CXD2841ER_ASCOT) + cxd2841er_write_regs(priv, I2C_SLVT, 0xA6, itbCoef8bw[priv->xtal], 14); /* <IF freq setting> */ - iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 4.80); + ifhz = cxd2841er_get_if_hz(priv, 4800000); + iffreq = cxd2841er_calc_iffreq_xtal(priv->xtal, ifhz); data[0] = (u8) ((iffreq >> 16) & 0xff); data[1] = (u8)((iffreq >> 8) & 0xff); data[2] = (u8)(iffreq & 0xff); @@ -2485,10 +2536,12 @@ static int cxd2841er_sleep_tc_to_active_t_band( /* Group delay equaliser settings for * ASCOT2D, ASCOT2E and ASCOT3 tuners */ - cxd2841er_write_regs(priv, I2C_SLVT, + if (priv->flags & CXD2841ER_ASCOT) + cxd2841er_write_regs(priv, I2C_SLVT, 0xA6, itbCoef7bw[priv->xtal], 14); /* <IF freq setting> */ - iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 4.20); + ifhz = cxd2841er_get_if_hz(priv, 4200000); + iffreq = cxd2841er_calc_iffreq_xtal(priv->xtal, ifhz); data[0] = (u8) ((iffreq >> 16) & 0xff); data[1] = (u8)((iffreq >> 8) & 0xff); data[2] = (u8)(iffreq & 0xff); @@ -2520,10 +2573,12 @@ static int cxd2841er_sleep_tc_to_active_t_band( /* Group delay equaliser settings for * ASCOT2D, ASCOT2E and ASCOT3 tuners */ - cxd2841er_write_regs(priv, I2C_SLVT, + if (priv->flags & CXD2841ER_ASCOT) + cxd2841er_write_regs(priv, I2C_SLVT, 0xA6, itbCoef6bw[priv->xtal], 14); /* <IF freq setting> */ - iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 3.60); + ifhz = cxd2841er_get_if_hz(priv, 3600000); + iffreq = cxd2841er_calc_iffreq_xtal(priv->xtal, ifhz); data[0] = (u8) ((iffreq >> 16) & 0xff); data[1] = (u8)((iffreq >> 8) & 0xff); data[2] = (u8)(iffreq & 0xff); @@ -2555,10 +2610,12 @@ static int cxd2841er_sleep_tc_to_active_t_band( /* Group delay equaliser settings for * ASCOT2D, ASCOT2E and ASCOT3 tuners */ - cxd2841er_write_regs(priv, I2C_SLVT, + if (priv->flags & CXD2841ER_ASCOT) + cxd2841er_write_regs(priv, I2C_SLVT, 0xA6, itbCoef5bw[priv->xtal], 14); /* <IF freq setting> */ - iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 3.60); + ifhz = cxd2841er_get_if_hz(priv, 3600000); + iffreq = cxd2841er_calc_iffreq_xtal(priv->xtal, ifhz); data[0] = (u8) ((iffreq >> 16) & 0xff); data[1] = (u8)((iffreq >> 8) & 0xff); data[2] = (u8)(iffreq & 0xff); @@ -2591,7 +2648,7 @@ static int cxd2841er_sleep_tc_to_active_t_band( static int cxd2841er_sleep_tc_to_active_i_band( struct cxd2841er_priv *priv, u32 bandwidth) { - u32 iffreq; + u32 iffreq, ifhz; u8 data[3]; /* TRCG Nominal Rate */ @@ -2656,11 +2713,13 @@ static int cxd2841er_sleep_tc_to_active_i_band( cxd2841er_write_regs(priv, I2C_SLVT, 0x9F, nominalRate8bw[priv->xtal], 5); /* Group delay equaliser settings for ASCOT tuners optimized */ - cxd2841er_write_regs(priv, I2C_SLVT, + if (priv->flags & CXD2841ER_ASCOT) + cxd2841er_write_regs(priv, I2C_SLVT, 0xA6, itbCoef8bw[priv->xtal], 14); /* IF freq setting */ - iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 4.75); + ifhz = cxd2841er_get_if_hz(priv, 4750000); + iffreq = cxd2841er_calc_iffreq_xtal(priv->xtal, ifhz); data[0] = (u8) ((iffreq >> 16) & 0xff); data[1] = (u8)((iffreq >> 8) & 0xff); data[2] = (u8)(iffreq & 0xff); @@ -2685,11 +2744,13 @@ static int cxd2841er_sleep_tc_to_active_i_band( cxd2841er_write_regs(priv, I2C_SLVT, 0x9F, nominalRate7bw[priv->xtal], 5); /* Group delay equaliser settings for ASCOT tuners optimized */ - cxd2841er_write_regs(priv, I2C_SLVT, + if (priv->flags & CXD2841ER_ASCOT) + cxd2841er_write_regs(priv, I2C_SLVT, 0xA6, itbCoef7bw[priv->xtal], 14); /* IF freq setting */ - iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 4.15); + ifhz = cxd2841er_get_if_hz(priv, 4150000); + iffreq = cxd2841er_calc_iffreq_xtal(priv->xtal, ifhz); data[0] = (u8) ((iffreq >> 16) & 0xff); data[1] = (u8)((iffreq >> 8) & 0xff); data[2] = (u8)(iffreq & 0xff); @@ -2714,11 +2775,13 @@ static int cxd2841er_sleep_tc_to_active_i_band( cxd2841er_write_regs(priv, I2C_SLVT, 0x9F, nominalRate6bw[priv->xtal], 5); /* Group delay equaliser settings for ASCOT tuners optimized */ - cxd2841er_write_regs(priv, I2C_SLVT, + if (priv->flags & CXD2841ER_ASCOT) + cxd2841er_write_regs(priv, I2C_SLVT, 0xA6, itbCoef6bw[priv->xtal], 14); /* IF freq setting */ - iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 3.55); + ifhz = cxd2841er_get_if_hz(priv, 3550000); + iffreq = cxd2841er_calc_iffreq_xtal(priv->xtal, ifhz); data[0] = (u8) ((iffreq >> 16) & 0xff); data[1] = (u8)((iffreq >> 8) & 0xff); data[2] = (u8)(iffreq & 0xff); @@ -2761,7 +2824,7 @@ static int cxd2841er_sleep_tc_to_active_c_band(struct cxd2841er_priv *priv, 0x27, 0xA7, 0x28, 0xB3, 0x02, 0xF0, 0x01, 0xE8, 0x00, 0xCF, 0x00, 0xE6, 0x23, 0xA4 }; u8 b10_b6[3]; - u32 iffreq; + u32 iffreq, ifhz; if (bandwidth != 6000000 && bandwidth != 7000000 && @@ -2776,16 +2839,20 @@ static int cxd2841er_sleep_tc_to_active_c_band(struct cxd2841er_priv *priv, switch (bandwidth) { case 8000000: case 7000000: - cxd2841er_write_regs( - priv, I2C_SLVT, 0xa6, - bw7_8mhz_b10_a6, sizeof(bw7_8mhz_b10_a6)); - iffreq = MAKE_IFFREQ_CONFIG(4.9); + if (priv->flags & CXD2841ER_ASCOT) + cxd2841er_write_regs( + priv, I2C_SLVT, 0xa6, + bw7_8mhz_b10_a6, sizeof(bw7_8mhz_b10_a6)); + ifhz = cxd2841er_get_if_hz(priv, 4900000); + iffreq = cxd2841er_calc_iffreq(ifhz); break; case 6000000: - cxd2841er_write_regs( - priv, I2C_SLVT, 0xa6, - bw6mhz_b10_a6, sizeof(bw6mhz_b10_a6)); - iffreq = MAKE_IFFREQ_CONFIG(3.7); + if (priv->flags & CXD2841ER_ASCOT) + cxd2841er_write_regs( + priv, I2C_SLVT, 0xa6, + bw6mhz_b10_a6, sizeof(bw6mhz_b10_a6)); + ifhz = cxd2841er_get_if_hz(priv, 3700000); + iffreq = cxd2841er_calc_iffreq(ifhz); break; default: dev_err(&priv->i2c->dev, "%s(): unsupported bandwidth %d\n", @@ -2872,8 +2939,9 @@ static int cxd2841er_sleep_tc_to_active_t(struct cxd2841er_priv *priv, cxd2841er_write_reg(priv, I2C_SLVT, 0x6a, 0x50); /* Set SLV-T Bank : 0x10 */ cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10); - /* ASCOT setting ON */ - cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xa5, 0x01, 0x01); + /* ASCOT setting */ + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xa5, + ((priv->flags & CXD2841ER_ASCOT) ? 0x01 : 0x00), 0x01); /* Set SLV-T Bank : 0x18 */ cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x18); /* Pre-RS BER moniter setting */ @@ -2950,8 +3018,9 @@ static int cxd2841er_sleep_tc_to_active_t2(struct cxd2841er_priv *priv, cxd2841er_write_reg(priv, I2C_SLVT, 0x6a, 0x50); /* Set SLV-T Bank : 0x10 */ cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10); - /* ASCOT setting ON */ - cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xa5, 0x01, 0x01); + /* ASCOT setting */ + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xa5, + ((priv->flags & CXD2841ER_ASCOT) ? 0x01 : 0x00), 0x01); /* Set SLV-T Bank : 0x20 */ cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x20); /* Acquisition optimization setting */ @@ -3088,8 +3157,9 @@ static int cxd2841er_sleep_tc_to_active_i(struct cxd2841er_priv *priv, cxd2841er_write_regs(priv, I2C_SLVT, 0x43, data, 2); /* Enable ADC 4 */ cxd2841er_write_reg(priv, I2C_SLVX, 0x18, 0x00); - /* ASCOT setting ON */ - cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xa5, 0x01, 0x01); + /* ASCOT setting */ + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xa5, + ((priv->flags & CXD2841ER_ASCOT) ? 0x01 : 0x00), 0x01); /* FEC Auto Recovery setting */ cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x30, 0x01, 0x01); cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x31, 0x00, 0x01); @@ -3173,8 +3243,9 @@ static int cxd2841er_sleep_tc_to_active_c(struct cxd2841er_priv *priv, cxd2841er_write_reg(priv, I2C_SLVT, 0x6a, 0x48); /* Set SLV-T Bank : 0x10 */ cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10); - /* ASCOT setting ON */ - cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xa5, 0x01, 0x01); + /* ASCOT setting */ + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xa5, + ((priv->flags & CXD2841ER_ASCOT) ? 0x01 : 0x00), 0x01); /* Set SLV-T Bank : 0x40 */ cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x40); /* Demod setting */ @@ -3236,6 +3307,10 @@ static int cxd2841er_set_frontend_s(struct dvb_frontend *fe) __func__, (p->delivery_system == SYS_DVBS ? "DVB-S" : "DVB-S2"), p->frequency, symbol_rate, priv->xtal); + + if (priv->flags & CXD2841ER_EARLY_TUNE) + cxd2841er_tuner_set(fe); + switch (priv->state) { case STATE_SLEEP_S: ret = cxd2841er_sleep_s_to_active_s( @@ -3254,12 +3329,10 @@ static int cxd2841er_set_frontend_s(struct dvb_frontend *fe) dev_dbg(&priv->i2c->dev, "%s(): tune failed\n", __func__); goto done; } - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if (fe->ops.tuner_ops.set_params) - fe->ops.tuner_ops.set_params(fe); - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); + + if (!(priv->flags & CXD2841ER_EARLY_TUNE)) + cxd2841er_tuner_set(fe); + cxd2841er_tune_done(priv); timeout = ((3000000 + (symbol_rate - 1)) / symbol_rate) + 150; for (i = 0; i < timeout / CXD2841ER_DVBS_POLLING_INVL; i++) { @@ -3298,6 +3371,10 @@ static int cxd2841er_set_frontend_tc(struct dvb_frontend *fe) dev_dbg(&priv->i2c->dev, "%s() delivery_system=%d bandwidth_hz=%d\n", __func__, p->delivery_system, p->bandwidth_hz); + + if (priv->flags & CXD2841ER_EARLY_TUNE) + cxd2841er_tuner_set(fe); + if (p->delivery_system == SYS_DVBT) { priv->system = SYS_DVBT; switch (priv->state) { @@ -3379,13 +3456,15 @@ static int cxd2841er_set_frontend_tc(struct dvb_frontend *fe) } if (ret) goto done; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if (fe->ops.tuner_ops.set_params) - fe->ops.tuner_ops.set_params(fe); - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); + + if (!(priv->flags & CXD2841ER_EARLY_TUNE)) + cxd2841er_tuner_set(fe); + cxd2841er_tune_done(priv); + + if (priv->flags & CXD2841ER_NO_WAIT_LOCK) + goto done; + timeout = 2500; while (timeout > 0) { ret = cxd2841er_read_status_tc(fe, &status); @@ -3705,14 +3784,20 @@ static int cxd2841er_init_tc(struct dvb_frontend *fe) dev_dbg(&priv->i2c->dev, "%s() bandwidth_hz=%d\n", __func__, p->bandwidth_hz); cxd2841er_shutdown_to_sleep_tc(priv); - /* SONY_DEMOD_CONFIG_IFAGCNEG = 1 */ + /* SONY_DEMOD_CONFIG_IFAGCNEG = 1 (0 for NO_AGCNEG */ cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10); - cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xcb, 0x40, 0x40); + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xcb, + ((priv->flags & CXD2841ER_NO_AGCNEG) ? 0x00 : 0x40), 0x40); /* SONY_DEMOD_CONFIG_IFAGC_ADC_FS = 0 */ cxd2841er_write_reg(priv, I2C_SLVT, 0xcd, 0x50); /* SONY_DEMOD_CONFIG_PARALLEL_SEL = 1 */ cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x00); - cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xc4, 0x00, 0x80); + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xc4, + ((priv->flags & CXD2841ER_TS_SERIAL) ? 0x80 : 0x00), 0x80); + + /* clear TSCFG bits 3+4 */ + if (priv->flags & CXD2841ER_TSBITS) + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xc4, 0x00, 0x18); cxd2841er_init_stats(fe); @@ -3740,6 +3825,7 @@ static struct dvb_frontend *cxd2841er_attach(struct cxd2841er_config *cfg, priv->i2c_addr_slvx = (cfg->i2c_addr + 4) >> 1; priv->i2c_addr_slvt = (cfg->i2c_addr) >> 1; priv->xtal = cfg->xtal; + priv->flags = cfg->flags; priv->frontend.demodulator_priv = priv; dev_info(&priv->i2c->dev, "%s(): I2C adapter %p SLVX addr %x SLVT addr %x\n", @@ -3747,16 +3833,39 @@ static struct dvb_frontend *cxd2841er_attach(struct cxd2841er_config *cfg, priv->i2c_addr_slvx, priv->i2c_addr_slvt); chip_id = cxd2841er_chip_id(priv); switch (chip_id) { + case CXD2837ER_CHIP_ID: + snprintf(cxd2841er_t_c_ops.info.name, 128, + "Sony CXD2837ER DVB-T/T2/C demodulator"); + name = "CXD2837ER"; + type = "C/T/T2"; + break; + case CXD2838ER_CHIP_ID: + snprintf(cxd2841er_t_c_ops.info.name, 128, + "Sony CXD2838ER ISDB-T demodulator"); + cxd2841er_t_c_ops.delsys[0] = SYS_ISDBT; + cxd2841er_t_c_ops.delsys[1] = SYS_UNDEFINED; + cxd2841er_t_c_ops.delsys[2] = SYS_UNDEFINED; + name = "CXD2838ER"; + type = "ISDB-T"; + break; case CXD2841ER_CHIP_ID: snprintf(cxd2841er_t_c_ops.info.name, 128, "Sony CXD2841ER DVB-T/T2/C demodulator"); name = "CXD2841ER"; + type = "T/T2/C/ISDB-T"; + break; + case CXD2843ER_CHIP_ID: + snprintf(cxd2841er_t_c_ops.info.name, 128, + "Sony CXD2843ER DVB-T/T2/C/C2 demodulator"); + name = "CXD2843ER"; + type = "C/C2/T/T2"; break; case CXD2854ER_CHIP_ID: snprintf(cxd2841er_t_c_ops.info.name, 128, "Sony CXD2854ER DVB-T/T2/C and ISDB-T demodulator"); cxd2841er_t_c_ops.delsys[3] = SYS_ISDBT; name = "CXD2854ER"; + type = "C/C2/T/T2/ISDB-T"; break; default: dev_err(&priv->i2c->dev, "%s(): invalid chip ID 0x%02x\n", @@ -3776,7 +3885,6 @@ static struct dvb_frontend *cxd2841er_attach(struct cxd2841er_config *cfg, memcpy(&priv->frontend.ops, &cxd2841er_t_c_ops, sizeof(struct dvb_frontend_ops)); - type = "T/T2/C/ISDB-T"; } dev_info(&priv->i2c->dev, |