diff options
Diffstat (limited to 'drivers/media/dvb-frontends/cxd2841er.c')
-rw-r--r-- | drivers/media/dvb-frontends/cxd2841er.c | 1927 |
1 files changed, 1493 insertions, 434 deletions
diff --git a/drivers/media/dvb-frontends/cxd2841er.c b/drivers/media/dvb-frontends/cxd2841er.c index 900186ba8e62..09c39346167f 100644 --- a/drivers/media/dvb-frontends/cxd2841er.c +++ b/drivers/media/dvb-frontends/cxd2841er.c @@ -1,7 +1,9 @@ /* * cxd2841er.c * - * Sony CXD2441ER digital demodulator driver + * Sony digital demodulator driver for + * CXD2841ER - DVB-S/S2/T/T2/C/C2 + * CXD2854ER - DVB-S/S2/T/T2/C/C2, ISDB-T/S * * Copyright 2012 Sony Corporation * Copyright (C) 2014 NetUP Inc. @@ -34,6 +36,16 @@ #include "cxd2841er_priv.h" #define MAX_WRITE_REGSIZE 16 +#define LOG2_E_100X 144 + +/* DVB-C constellation */ +enum sony_dvbc_constellation_t { + SONY_DVBC_CONSTELLATION_16QAM, + SONY_DVBC_CONSTELLATION_32QAM, + SONY_DVBC_CONSTELLATION_64QAM, + SONY_DVBC_CONSTELLATION_128QAM, + SONY_DVBC_CONSTELLATION_256QAM +}; enum cxd2841er_state { STATE_SHUTDOWN = 0, @@ -51,6 +63,8 @@ struct cxd2841er_priv { const struct cxd2841er_config *config; enum cxd2841er_state state; u8 system; + enum cxd2841er_xtal xtal; + enum fe_caps caps; }; static const struct cxd2841er_cnr_data s_cn_data[] = { @@ -188,6 +202,9 @@ static const struct cxd2841er_cnr_data s2_cn_data[] = { }; #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 void cxd2841er_i2c_debug(struct cxd2841er_priv *priv, u8 addr, u8 reg, u8 write, @@ -217,7 +234,7 @@ static int cxd2841er_write_regs(struct cxd2841er_priv *priv, }; if (len + 1 >= sizeof(buf)) { - dev_warn(&priv->i2c->dev,"wr reg=%04x: len=%d is too big!\n", + dev_warn(&priv->i2c->dev, "wr reg=%04x: len=%d is too big!\n", reg, len + 1); return -E2BIG; } @@ -282,6 +299,7 @@ static int cxd2841er_read_regs(struct cxd2841er_priv *priv, KBUILD_MODNAME, ret, i2c_addr, reg); return ret; } + cxd2841er_i2c_debug(priv, i2c_addr, reg, 0, val, len); return 0; } @@ -427,6 +445,15 @@ static int cxd2841er_sleep_tc_to_active_t2_band(struct cxd2841er_priv *priv, static int cxd2841er_sleep_tc_to_active_c_band(struct cxd2841er_priv *priv, u32 bandwidth); +static int cxd2841er_sleep_tc_to_active_i(struct cxd2841er_priv *priv, + u32 bandwidth); + +static int cxd2841er_active_i_to_sleep_tc(struct cxd2841er_priv *priv); + +static int cxd2841er_sleep_tc_to_shutdown(struct cxd2841er_priv *priv); + +static int cxd2841er_shutdown_to_sleep_tc(struct cxd2841er_priv *priv); + static int cxd2841er_retune_active(struct cxd2841er_priv *priv, struct dtv_frontend_properties *p) { @@ -454,7 +481,13 @@ static int cxd2841er_retune_active(struct cxd2841er_priv *priv, priv, p->bandwidth_hz); case SYS_DVBC_ANNEX_A: return cxd2841er_sleep_tc_to_active_c_band( - priv, 8000000); + priv, p->bandwidth_hz); + case SYS_ISDBT: + cxd2841er_active_i_to_sleep_tc(priv); + cxd2841er_sleep_tc_to_shutdown(priv); + cxd2841er_shutdown_to_sleep_tc(priv); + return cxd2841er_sleep_tc_to_active_i( + priv, p->bandwidth_hz); } } dev_dbg(&priv->i2c->dev, "%s(): invalid delivery system %d\n", @@ -669,6 +702,45 @@ static int cxd2841er_active_c_to_sleep_tc(struct cxd2841er_priv *priv) return 0; } +static int cxd2841er_active_i_to_sleep_tc(struct cxd2841er_priv *priv) +{ + dev_dbg(&priv->i2c->dev, "%s()\n", __func__); + if (priv->state != STATE_ACTIVE_TC) { + dev_err(&priv->i2c->dev, "%s(): invalid state %d\n", + __func__, priv->state); + return -EINVAL; + } + /* Set SLV-T Bank : 0x00 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x00); + /* disable TS output */ + cxd2841er_write_reg(priv, I2C_SLVT, 0xc3, 0x01); + /* enable Hi-Z setting 1 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x80, 0x3f); + /* enable Hi-Z setting 2 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x81, 0xff); + + /* TODO: Cancel demod parameter */ + + /* Set SLV-X Bank : 0x00 */ + cxd2841er_write_reg(priv, I2C_SLVX, 0x00, 0x00); + /* disable ADC 1 */ + cxd2841er_write_reg(priv, I2C_SLVX, 0x18, 0x01); + /* Set SLV-T Bank : 0x00 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x00); + /* Disable ADC 2 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x43, 0x0a); + /* Disable ADC 3 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x41, 0x0a); + /* Disable ADC clock */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x30, 0x00); + /* Disable RF level monitor */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x2f, 0x00); + /* Disable demod clock */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x2c, 0x00); + priv->state = STATE_SLEEP_TC; + return 0; +} + static int cxd2841er_shutdown_to_sleep_s(struct cxd2841er_priv *priv) { dev_dbg(&priv->i2c->dev, "%s()\n", __func__); @@ -686,8 +758,25 @@ static int cxd2841er_shutdown_to_sleep_s(struct cxd2841er_priv *priv) cxd2841er_write_reg(priv, I2C_SLVX, 0x00, 0x00); /* Set demod SW reset */ cxd2841er_write_reg(priv, I2C_SLVX, 0x10, 0x01); - /* Set X'tal clock to 20.5Mhz */ - cxd2841er_write_reg(priv, I2C_SLVX, 0x14, 0x00); + + switch (priv->xtal) { + case SONY_XTAL_20500: + cxd2841er_write_reg(priv, I2C_SLVX, 0x14, 0x00); + break; + case SONY_XTAL_24000: + /* Select demod frequency */ + cxd2841er_write_reg(priv, I2C_SLVX, 0x12, 0x00); + cxd2841er_write_reg(priv, I2C_SLVX, 0x14, 0x03); + break; + case SONY_XTAL_41000: + cxd2841er_write_reg(priv, I2C_SLVX, 0x14, 0x01); + break; + default: + dev_dbg(&priv->i2c->dev, "%s(): invalid demod xtal %d\n", + __func__, priv->xtal); + return -EINVAL; + } + /* Set demod mode */ cxd2841er_write_reg(priv, I2C_SLVX, 0x17, 0x0a); /* Clear demod SW reset */ @@ -712,6 +801,8 @@ static int cxd2841er_shutdown_to_sleep_s(struct cxd2841er_priv *priv) static int cxd2841er_shutdown_to_sleep_tc(struct cxd2841er_priv *priv) { + u8 data = 0; + dev_dbg(&priv->i2c->dev, "%s()\n", __func__); if (priv->state != STATE_SHUTDOWN) { dev_dbg(&priv->i2c->dev, "%s(): invalid demod state %d\n", @@ -727,9 +818,24 @@ static int cxd2841er_shutdown_to_sleep_tc(struct cxd2841er_priv *priv) cxd2841er_write_reg(priv, I2C_SLVX, 0x00, 0x00); /* Set demod SW reset */ cxd2841er_write_reg(priv, I2C_SLVX, 0x10, 0x01); - /* Set X'tal clock to 20.5Mhz */ + /* Select ADC clock mode */ cxd2841er_write_reg(priv, I2C_SLVX, 0x13, 0x00); - cxd2841er_write_reg(priv, I2C_SLVX, 0x14, 0x00); + + switch (priv->xtal) { + case SONY_XTAL_20500: + data = 0x0; + break; + case SONY_XTAL_24000: + /* Select demod frequency */ + cxd2841er_write_reg(priv, I2C_SLVX, 0x12, 0x00); + data = 0x3; + break; + case SONY_XTAL_41000: + cxd2841er_write_reg(priv, I2C_SLVX, 0x12, 0x00); + data = 0x1; + break; + } + cxd2841er_write_reg(priv, I2C_SLVX, 0x14, data); /* Clear demod SW reset */ cxd2841er_write_reg(priv, I2C_SLVX, 0x10, 0x00); usleep_range(1000, 2000); @@ -809,11 +915,14 @@ static void cxd2841er_set_ts_clock_mode(struct cxd2841er_priv *priv, static u8 cxd2841er_chip_id(struct cxd2841er_priv *priv) { - u8 chip_id; + u8 chip_id = 0; dev_dbg(&priv->i2c->dev, "%s()\n", __func__); - cxd2841er_write_reg(priv, I2C_SLVT, 0, 0); - cxd2841er_read_reg(priv, I2C_SLVT, 0xfd, &chip_id); + if (cxd2841er_write_reg(priv, I2C_SLVT, 0, 0) == 0) + cxd2841er_read_reg(priv, I2C_SLVT, 0xfd, &chip_id); + else if (cxd2841er_write_reg(priv, I2C_SLVX, 0, 0) == 0) + cxd2841er_read_reg(priv, I2C_SLVX, 0xfd, &chip_id); + return chip_id; } @@ -896,6 +1005,25 @@ static int cxd2841er_read_status_c(struct cxd2841er_priv *priv, u8 *tslock) return 0; } +static int cxd2841er_read_status_i(struct cxd2841er_priv *priv, + u8 *sync, u8 *tslock, u8 *unlock) +{ + u8 data = 0; + + dev_dbg(&priv->i2c->dev, "%s()\n", __func__); + if (priv->state != STATE_ACTIVE_TC) + return -EINVAL; + /* Set SLV-T Bank : 0x60 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x60); + cxd2841er_read_reg(priv, I2C_SLVT, 0x10, &data); + dev_dbg(&priv->i2c->dev, + "%s(): lock=0x%x\n", __func__, data); + *sync = ((data & 0x02) ? 1 : 0); + *tslock = ((data & 0x01) ? 1 : 0); + *unlock = ((data & 0x10) ? 1 : 0); + return 0; +} + static int cxd2841er_read_status_tc(struct dvb_frontend *fe, enum fe_status *status) { @@ -921,6 +1049,20 @@ static int cxd2841er_read_status_tc(struct dvb_frontend *fe, FE_HAS_SYNC; if (tslock) *status |= FE_HAS_LOCK; + } else if (priv->system == SYS_ISDBT) { + ret = cxd2841er_read_status_i( + priv, &sync, &tslock, &unlock); + if (ret) + goto done; + if (unlock) + goto done; + if (sync) + *status = FE_HAS_SIGNAL | + FE_HAS_CARRIER | + FE_HAS_VITERBI | + FE_HAS_SYNC; + if (tslock) + *status |= FE_HAS_LOCK; } else if (priv->system == SYS_DVBC_ANNEX_A) { ret = cxd2841er_read_status_c(priv, &tslock); if (ret) @@ -997,6 +1139,76 @@ static int cxd2841er_get_carrier_offset_s_s2(struct cxd2841er_priv *priv, return 0; } +static int cxd2841er_get_carrier_offset_i(struct cxd2841er_priv *priv, + u32 bandwidth, int *offset) +{ + u8 data[4]; + + dev_dbg(&priv->i2c->dev, "%s()\n", __func__); + if (priv->state != STATE_ACTIVE_TC) { + dev_dbg(&priv->i2c->dev, "%s(): invalid state %d\n", + __func__, priv->state); + return -EINVAL; + } + if (priv->system != SYS_ISDBT) { + dev_dbg(&priv->i2c->dev, "%s(): invalid delivery system %d\n", + __func__, priv->system); + return -EINVAL; + } + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x60); + cxd2841er_read_regs(priv, I2C_SLVT, 0x4c, data, sizeof(data)); + *offset = -1 * sign_extend32( + ((u32)(data[0] & 0x1F) << 24) | ((u32)data[1] << 16) | + ((u32)data[2] << 8) | (u32)data[3], 29); + + switch (bandwidth) { + case 6000000: + *offset = -1 * ((*offset) * 8/264); + break; + case 7000000: + *offset = -1 * ((*offset) * 8/231); + break; + case 8000000: + *offset = -1 * ((*offset) * 8/198); + break; + default: + dev_dbg(&priv->i2c->dev, "%s(): invalid bandwidth %d\n", + __func__, bandwidth); + return -EINVAL; + } + + dev_dbg(&priv->i2c->dev, "%s(): bandwidth %d offset %d\n", + __func__, bandwidth, *offset); + + return 0; +} + +static int cxd2841er_get_carrier_offset_t(struct cxd2841er_priv *priv, + u32 bandwidth, int *offset) +{ + u8 data[4]; + + dev_dbg(&priv->i2c->dev, "%s()\n", __func__); + if (priv->state != STATE_ACTIVE_TC) { + dev_dbg(&priv->i2c->dev, "%s(): invalid state %d\n", + __func__, priv->state); + return -EINVAL; + } + if (priv->system != SYS_DVBT) { + dev_dbg(&priv->i2c->dev, "%s(): invalid delivery system %d\n", + __func__, priv->system); + return -EINVAL; + } + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10); + cxd2841er_read_regs(priv, I2C_SLVT, 0x4c, data, sizeof(data)); + *offset = -1 * sign_extend32( + ((u32)(data[0] & 0x1F) << 24) | ((u32)data[1] << 16) | + ((u32)data[2] << 8) | (u32)data[3], 29); + *offset *= (bandwidth / 1000000); + *offset /= 235; + return 0; +} + static int cxd2841er_get_carrier_offset_t2(struct cxd2841er_priv *priv, u32 bandwidth, int *offset) { @@ -1060,6 +1272,24 @@ static int cxd2841er_get_carrier_offset_c(struct cxd2841er_priv *priv, return 0; } +static int cxd2841er_read_packet_errors_c( + struct cxd2841er_priv *priv, u32 *penum) +{ + u8 data[3]; + + *penum = 0; + if (priv->state != STATE_ACTIVE_TC) { + dev_dbg(&priv->i2c->dev, "%s(): invalid state %d\n", + __func__, priv->state); + return -EINVAL; + } + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x40); + cxd2841er_read_regs(priv, I2C_SLVT, 0xea, data, sizeof(data)); + if (data[2] & 0x01) + *penum = ((u32)data[0] << 8) | (u32)data[1]; + return 0; +} + static int cxd2841er_read_packet_errors_t( struct cxd2841er_priv *priv, u32 *penum) { @@ -1096,11 +1326,85 @@ static int cxd2841er_read_packet_errors_t2( return 0; } -static u32 cxd2841er_mon_read_ber_s(struct cxd2841er_priv *priv) +static int cxd2841er_read_packet_errors_i( + struct cxd2841er_priv *priv, u32 *penum) +{ + u8 data[2]; + + *penum = 0; + if (priv->state != STATE_ACTIVE_TC) { + dev_dbg(&priv->i2c->dev, "%s(): invalid state %d\n", + __func__, priv->state); + return -EINVAL; + } + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x60); + cxd2841er_read_regs(priv, I2C_SLVT, 0xA1, data, 1); + + if (!(data[0] & 0x01)) + return 0; + + /* Layer A */ + cxd2841er_read_regs(priv, I2C_SLVT, 0xA2, data, sizeof(data)); + *penum = ((u32)data[0] << 8) | (u32)data[1]; + + /* Layer B */ + cxd2841er_read_regs(priv, I2C_SLVT, 0xA4, data, sizeof(data)); + *penum += ((u32)data[0] << 8) | (u32)data[1]; + + /* Layer C */ + cxd2841er_read_regs(priv, I2C_SLVT, 0xA6, data, sizeof(data)); + *penum += ((u32)data[0] << 8) | (u32)data[1]; + + return 0; +} + +static int cxd2841er_read_ber_c(struct cxd2841er_priv *priv, + u32 *bit_error, u32 *bit_count) +{ + u8 data[3]; + u32 bit_err, period_exp; + + dev_dbg(&priv->i2c->dev, "%s()\n", __func__); + if (priv->state != STATE_ACTIVE_TC) { + dev_dbg(&priv->i2c->dev, "%s(): invalid state %d\n", + __func__, priv->state); + return -EINVAL; + } + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x40); + cxd2841er_read_regs(priv, I2C_SLVT, 0x62, data, sizeof(data)); + if (!(data[0] & 0x80)) { + dev_dbg(&priv->i2c->dev, + "%s(): no valid BER data\n", __func__); + return -EINVAL; + } + bit_err = ((u32)(data[0] & 0x3f) << 16) | + ((u32)data[1] << 8) | + (u32)data[2]; + cxd2841er_read_reg(priv, I2C_SLVT, 0x60, data); + period_exp = data[0] & 0x1f; + + if ((period_exp <= 11) && (bit_err > (1 << period_exp) * 204 * 8)) { + dev_dbg(&priv->i2c->dev, + "%s(): period_exp(%u) or bit_err(%u) not in range. no valid BER data\n", + __func__, period_exp, bit_err); + return -EINVAL; + } + + dev_dbg(&priv->i2c->dev, + "%s(): period_exp(%u) or bit_err(%u) count=%d\n", + __func__, period_exp, bit_err, + ((1 << period_exp) * 204 * 8)); + + *bit_error = bit_err; + *bit_count = ((1 << period_exp) * 204 * 8); + + return 0; +} + +static int cxd2841er_mon_read_ber_s(struct cxd2841er_priv *priv, + u32 *bit_error, u32 *bit_count) { u8 data[11]; - u32 bit_error, bit_count; - u32 temp_q, temp_r; /* Set SLV-T Bank : 0xA0 */ cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0xa0); @@ -1116,40 +1420,30 @@ static u32 cxd2841er_mon_read_ber_s(struct cxd2841er_priv *priv) */ cxd2841er_read_regs(priv, I2C_SLVT, 0x35, data, 11); if (data[0] & 0x01) { - bit_error = ((u32)(data[1] & 0x3F) << 16) | - ((u32)(data[2] & 0xFF) << 8) | - (u32)(data[3] & 0xFF); - bit_count = ((u32)(data[8] & 0x3F) << 16) | - ((u32)(data[9] & 0xFF) << 8) | - (u32)(data[10] & 0xFF); - /* - * BER = bitError / bitCount - * = (bitError * 10^7) / bitCount - * = ((bitError * 625 * 125 * 128) / bitCount - */ - if ((bit_count == 0) || (bit_error > bit_count)) { + *bit_error = ((u32)(data[1] & 0x3F) << 16) | + ((u32)(data[2] & 0xFF) << 8) | + (u32)(data[3] & 0xFF); + *bit_count = ((u32)(data[8] & 0x3F) << 16) | + ((u32)(data[9] & 0xFF) << 8) | + (u32)(data[10] & 0xFF); + if ((*bit_count == 0) || (*bit_error > *bit_count)) { dev_dbg(&priv->i2c->dev, "%s(): invalid bit_error %d, bit_count %d\n", - __func__, bit_error, bit_count); - return 0; + __func__, *bit_error, *bit_count); + return -EINVAL; } - temp_q = div_u64_rem(10000000ULL * bit_error, - bit_count, &temp_r); - if (bit_count != 1 && temp_r >= bit_count / 2) - temp_q++; - return temp_q; + return 0; } dev_dbg(&priv->i2c->dev, "%s(): no data available\n", __func__); - return 0; + return -EINVAL; } -static u32 cxd2841er_mon_read_ber_s2(struct cxd2841er_priv *priv) +static int cxd2841er_mon_read_ber_s2(struct cxd2841er_priv *priv, + u32 *bit_error, u32 *bit_count) { u8 data[5]; - u32 bit_error, period; - u32 temp_q, temp_r; - u32 result = 0; + u32 period; /* Set SLV-T Bank : 0xB2 */ cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0xb2); @@ -1164,10 +1458,10 @@ static u32 cxd2841er_mon_read_ber_s2(struct cxd2841er_priv *priv) cxd2841er_read_regs(priv, I2C_SLVT, 0x30, data, 5); if (data[0] & 0x01) { /* Bit error count */ - bit_error = ((u32)(data[1] & 0x0F) << 24) | - ((u32)(data[2] & 0xFF) << 16) | - ((u32)(data[3] & 0xFF) << 8) | - (u32)(data[4] & 0xFF); + *bit_error = ((u32)(data[1] & 0x0F) << 24) | + ((u32)(data[2] & 0xFF) << 16) | + ((u32)(data[3] & 0xFF) << 8) | + (u32)(data[4] & 0xFF); /* Set SLV-T Bank : 0xA0 */ cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0xa0); @@ -1177,40 +1471,30 @@ static u32 cxd2841er_mon_read_ber_s2(struct cxd2841er_priv *priv) if (period == 0) { dev_dbg(&priv->i2c->dev, "%s(): period is 0\n", __func__); - return 0; + return -EINVAL; } - if (bit_error > (period * 64800)) { + if (*bit_error > (period * 64800)) { dev_dbg(&priv->i2c->dev, "%s(): invalid bit_err 0x%x period 0x%x\n", - __func__, bit_error, period); - return 0; + __func__, *bit_error, period); + return -EINVAL; } - /* - * BER = bitError / (period * 64800) - * = (bitError * 10^7) / (period * 64800) - * = (bitError * 10^5) / (period * 648) - * = (bitError * 12500) / (period * 81) - * = (bitError * 10) * 1250 / (period * 81) - */ - temp_q = div_u64_rem(12500ULL * bit_error, - period * 81, &temp_r); - if (temp_r >= period * 40) - temp_q++; - result = temp_q; + *bit_count = period * 64800; + + return 0; } else { dev_dbg(&priv->i2c->dev, "%s(): no data available\n", __func__); } - return result; + return -EINVAL; } -static int cxd2841er_read_ber_t2(struct cxd2841er_priv *priv, u32 *ber) +static int cxd2841er_read_ber_t2(struct cxd2841er_priv *priv, + u32 *bit_error, u32 *bit_count) { u8 data[4]; - u32 div, q, r; - u32 bit_err, period_exp, n_ldpc; + u32 period_exp, n_ldpc; - *ber = 0; if (priv->state != STATE_ACTIVE_TC) { dev_dbg(&priv->i2c->dev, "%s(): invalid state %d\n", __func__, priv->state); @@ -1221,40 +1505,44 @@ static int cxd2841er_read_ber_t2(struct cxd2841er_priv *priv, u32 *ber) if (!(data[0] & 0x10)) { dev_dbg(&priv->i2c->dev, "%s(): no valid BER data\n", __func__); - return 0; + return -EINVAL; } - bit_err = ((u32)(data[0] & 0x0f) << 24) | - ((u32)data[1] << 16) | - ((u32)data[2] << 8) | - (u32)data[3]; + *bit_error = ((u32)(data[0] & 0x0f) << 24) | + ((u32)data[1] << 16) | + ((u32)data[2] << 8) | + (u32)data[3]; cxd2841er_read_reg(priv, I2C_SLVT, 0x6f, data); period_exp = data[0] & 0x0f; cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x22); cxd2841er_read_reg(priv, I2C_SLVT, 0x5e, data); n_ldpc = ((data[0] & 0x03) == 0 ? 16200 : 64800); - if (bit_err > ((1U << period_exp) * n_ldpc)) { + if (*bit_error > ((1U << period_exp) * n_ldpc)) { dev_dbg(&priv->i2c->dev, "%s(): invalid BER value\n", __func__); return -EINVAL; } + + /* + * FIXME: the right thing would be to return bit_error untouched, + * but, as we don't know the scale returned by the counters, let's + * at least preserver BER = bit_error/bit_count. + */ if (period_exp >= 4) { - div = (1U << (period_exp - 4)) * (n_ldpc / 200); - q = div_u64_rem(3125ULL * bit_err, div, &r); + *bit_count = (1U << (period_exp - 4)) * (n_ldpc / 200); + *bit_error *= 3125ULL; } else { - div = (1U << period_exp) * (n_ldpc / 200); - q = div_u64_rem(50000ULL * bit_err, div, &r); + *bit_count = (1U << period_exp) * (n_ldpc / 200); + *bit_error *= 50000ULL; } - *ber = (r >= div / 2) ? q + 1 : q; return 0; } -static int cxd2841er_read_ber_t(struct cxd2841er_priv *priv, u32 *ber) +static int cxd2841er_read_ber_t(struct cxd2841er_priv *priv, + u32 *bit_error, u32 *bit_count) { u8 data[2]; - u32 div, q, r; - u32 bit_err, period; + u32 period; - *ber = 0; if (priv->state != STATE_ACTIVE_TC) { dev_dbg(&priv->i2c->dev, "%s(): invalid state %d\n", __func__, priv->state); @@ -1268,16 +1556,22 @@ static int cxd2841er_read_ber_t(struct cxd2841er_priv *priv, u32 *ber) return 0; } cxd2841er_read_regs(priv, I2C_SLVT, 0x22, data, sizeof(data)); - bit_err = ((u32)data[0] << 8) | (u32)data[1]; + *bit_error = ((u32)data[0] << 8) | (u32)data[1]; cxd2841er_read_reg(priv, I2C_SLVT, 0x6f, data); period = ((data[0] & 0x07) == 0) ? 256 : (4096 << (data[0] & 0x07)); - div = period / 128; - q = div_u64_rem(78125ULL * bit_err, div, &r); - *ber = (r >= div / 2) ? q + 1 : q; + + /* + * FIXME: the right thing would be to return bit_error untouched, + * but, as we don't know the scale returned by the counters, let's + * at least preserver BER = bit_error/bit_count. + */ + *bit_count = period / 128; + *bit_error *= 78125ULL; return 0; } -static u32 cxd2841er_dvbs_read_snr(struct cxd2841er_priv *priv, u8 delsys) +static u32 cxd2841er_dvbs_read_snr(struct cxd2841er_priv *priv, + u8 delsys, u32 *snr) { u8 data[3]; u32 res = 0, value; @@ -1335,9 +1629,71 @@ static u32 cxd2841er_dvbs_read_snr(struct cxd2841er_priv *priv, u8 delsys) } else { dev_dbg(&priv->i2c->dev, "%s(): no data available\n", __func__); + return -EINVAL; } done: - return res; + *snr = res; + return 0; +} + +static uint32_t sony_log(uint32_t x) +{ + return (((10000>>8)*(intlog2(x)>>16) + LOG2_E_100X/2)/LOG2_E_100X); +} + +static int cxd2841er_read_snr_c(struct cxd2841er_priv *priv, u32 *snr) +{ + u32 reg; + u8 data[2]; + enum sony_dvbc_constellation_t qam = SONY_DVBC_CONSTELLATION_16QAM; + + *snr = 0; + if (priv->state != STATE_ACTIVE_TC) { + dev_dbg(&priv->i2c->dev, + "%s(): invalid state %d\n", + __func__, priv->state); + return -EINVAL; + } + + /* + * Freeze registers: ensure multiple separate register reads + * are from the same snapshot + */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x01, 0x01); + + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x40); + 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); + + 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__); + return 0; + } + + switch (qam) { + case SONY_DVBC_CONSTELLATION_16QAM: + case SONY_DVBC_CONSTELLATION_64QAM: + case SONY_DVBC_CONSTELLATION_256QAM: + /* SNR(dB) = -9.50 * ln(IREG_SNR_ESTIMATE / (24320)) */ + if (reg < 126) + reg = 126; + *snr = -95 * (int32_t)sony_log(reg) + 95941; + break; + case SONY_DVBC_CONSTELLATION_32QAM: + case SONY_DVBC_CONSTELLATION_128QAM: + /* SNR(dB) = -8.75 * ln(IREG_SNR_ESTIMATE / (20800)) */ + if (reg < 69) + reg = 69; + *snr = -88 * (int32_t)sony_log(reg) + 86999; + break; + default: + return -EINVAL; + } + + return 0; } static int cxd2841er_read_snr_t(struct cxd2841er_priv *priv, u32 *snr) @@ -1391,6 +1747,52 @@ static int cxd2841er_read_snr_t2(struct cxd2841er_priv *priv, u32 *snr) return 0; } +static int cxd2841er_read_snr_i(struct cxd2841er_priv *priv, u32 *snr) +{ + u32 reg; + u8 data[2]; + + *snr = 0; + if (priv->state != STATE_ACTIVE_TC) { + dev_dbg(&priv->i2c->dev, + "%s(): invalid state %d\n", __func__, + priv->state); + return -EINVAL; + } + + /* Freeze all registers */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x01, 0x01); + + + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x60); + cxd2841er_read_regs(priv, I2C_SLVT, 0x28, data, sizeof(data)); + reg = ((u32)data[0] << 8) | (u32)data[1]; + if (reg == 0) { + dev_dbg(&priv->i2c->dev, + "%s(): reg value out of range\n", __func__); + return 0; + } + if (reg > 4996) + reg = 4996; + *snr = 100 * intlog10(reg) - 9031; + return 0; +} + +static u16 cxd2841er_read_agc_gain_c(struct cxd2841er_priv *priv, + u8 delsys) +{ + u8 data[2]; + + cxd2841er_write_reg( + priv, I2C_SLVT, 0x00, 0x40); + cxd2841er_read_regs(priv, I2C_SLVT, 0x49, data, 2); + dev_dbg(&priv->i2c->dev, + "%s(): AGC value=%u\n", + __func__, (((u16)data[0] & 0x0F) << 8) | + (u16)(data[1] & 0xFF)); + return ((((u16)data[0] & 0x0F) << 8) | (u16)(data[1] & 0xFF)) << 4; +} + static u16 cxd2841er_read_agc_gain_t_t2(struct cxd2841er_priv *priv, u8 delsys) { @@ -1399,6 +1801,26 @@ static u16 cxd2841er_read_agc_gain_t_t2(struct cxd2841er_priv *priv, cxd2841er_write_reg( priv, I2C_SLVT, 0x00, (delsys == SYS_DVBT ? 0x10 : 0x20)); cxd2841er_read_regs(priv, I2C_SLVT, 0x26, data, 2); + dev_dbg(&priv->i2c->dev, + "%s(): AGC value=%u\n", + __func__, (((u16)data[0] & 0x0F) << 8) | + (u16)(data[1] & 0xFF)); + return ((((u16)data[0] & 0x0F) << 8) | (u16)(data[1] & 0xFF)) << 4; +} + +static u16 cxd2841er_read_agc_gain_i(struct cxd2841er_priv *priv, + u8 delsys) +{ + u8 data[2]; + + cxd2841er_write_reg( + priv, I2C_SLVT, 0x00, 0x60); + cxd2841er_read_regs(priv, I2C_SLVT, 0x26, data, 2); + + dev_dbg(&priv->i2c->dev, + "%s(): AGC value=%u\n", + __func__, (((u16)data[0] & 0x0F) << 8) | + (u16)(data[1] & 0xFF)); return ((((u16)data[0] & 0x0F) << 8) | (u16)(data[1] & 0xFF)) << 4; } @@ -1417,101 +1839,170 @@ static u16 cxd2841er_read_agc_gain_s(struct cxd2841er_priv *priv) return ((((u16)data[0] & 0x1F) << 8) | (u16)(data[1] & 0xFF)) << 3; } -static int cxd2841er_read_ber(struct dvb_frontend *fe, u32 *ber) +static void cxd2841er_read_ber(struct dvb_frontend *fe) { struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct cxd2841er_priv *priv = fe->demodulator_priv; + u32 ret, bit_error = 0, bit_count = 0; dev_dbg(&priv->i2c->dev, "%s()\n", __func__); - *ber = 0; switch (p->delivery_system) { + case SYS_DVBC_ANNEX_A: + case SYS_DVBC_ANNEX_B: + case SYS_DVBC_ANNEX_C: + ret = cxd2841er_read_ber_c(priv, &bit_error, &bit_count); + break; case SYS_DVBS: - *ber = cxd2841er_mon_read_ber_s(priv); + ret = cxd2841er_mon_read_ber_s(priv, &bit_error, &bit_count); break; case SYS_DVBS2: - *ber = cxd2841er_mon_read_ber_s2(priv); + ret = cxd2841er_mon_read_ber_s2(priv, &bit_error, &bit_count); break; case SYS_DVBT: - return cxd2841er_read_ber_t(priv, ber); + ret = cxd2841er_read_ber_t(priv, &bit_error, &bit_count); + break; case SYS_DVBT2: - return cxd2841er_read_ber_t2(priv, ber); - default: - *ber = 0; + ret = cxd2841er_read_ber_t2(priv, &bit_error, &bit_count); break; + default: + p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + return; + } + + if (!ret) { + p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; + p->post_bit_error.stat[0].uvalue += bit_error; + p->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; + p->post_bit_count.stat[0].uvalue += bit_count; + } else { + p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; } - return 0; } -static int cxd2841er_read_signal_strength(struct dvb_frontend *fe, - u16 *strength) +static void cxd2841er_read_signal_strength(struct dvb_frontend *fe) { struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct cxd2841er_priv *priv = fe->demodulator_priv; + s32 strength; dev_dbg(&priv->i2c->dev, "%s()\n", __func__); switch (p->delivery_system) { case SYS_DVBT: case SYS_DVBT2: - *strength = 65535 - cxd2841er_read_agc_gain_t_t2( - priv, p->delivery_system); + strength = cxd2841er_read_agc_gain_t_t2(priv, + p->delivery_system); + p->strength.stat[0].scale = FE_SCALE_DECIBEL; + /* Formula was empirically determinated @ 410 MHz */ + p->strength.stat[0].uvalue = strength * 366 / 100 - 89520; + break; /* Code moved out of the function */ + case SYS_DVBC_ANNEX_A: + case SYS_DVBC_ANNEX_B: + case SYS_DVBC_ANNEX_C: + strength = cxd2841er_read_agc_gain_c(priv, + p->delivery_system); + p->strength.stat[0].scale = FE_SCALE_DECIBEL; + /* + * Formula was empirically determinated via linear regression, + * using frequencies: 175 MHz, 410 MHz and 800 MHz, and a + * stream modulated with QAM64 + */ + p->strength.stat[0].uvalue = strength * 4045 / 1000 - 85224; + break; + case SYS_ISDBT: + strength = cxd2841er_read_agc_gain_i(priv, p->delivery_system); + p->strength.stat[0].scale = FE_SCALE_DECIBEL; + /* + * Formula was empirically determinated via linear regression, + * using frequencies: 175 MHz, 410 MHz and 800 MHz. + */ + p->strength.stat[0].uvalue = strength * 3775 / 1000 - 90185; break; case SYS_DVBS: case SYS_DVBS2: - *strength = 65535 - cxd2841er_read_agc_gain_s(priv); + strength = 65535 - cxd2841er_read_agc_gain_s(priv); + p->strength.stat[0].scale = FE_SCALE_RELATIVE; + p->strength.stat[0].uvalue = strength; break; default: - *strength = 0; + p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; break; } - return 0; } -static int cxd2841er_read_snr(struct dvb_frontend *fe, u16 *snr) +static void cxd2841er_read_snr(struct dvb_frontend *fe) { u32 tmp = 0; + int ret = 0; struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct cxd2841er_priv *priv = fe->demodulator_priv; dev_dbg(&priv->i2c->dev, "%s()\n", __func__); switch (p->delivery_system) { + case SYS_DVBC_ANNEX_A: + case SYS_DVBC_ANNEX_B: + case SYS_DVBC_ANNEX_C: + ret = cxd2841er_read_snr_c(priv, &tmp); + break; case SYS_DVBT: - cxd2841er_read_snr_t(priv, &tmp); + ret = cxd2841er_read_snr_t(priv, &tmp); break; case SYS_DVBT2: - cxd2841er_read_snr_t2(priv, &tmp); + ret = cxd2841er_read_snr_t2(priv, &tmp); + break; + case SYS_ISDBT: + ret = cxd2841er_read_snr_i(priv, &tmp); break; case SYS_DVBS: case SYS_DVBS2: - tmp = cxd2841er_dvbs_read_snr(priv, p->delivery_system); + ret = cxd2841er_dvbs_read_snr(priv, p->delivery_system, &tmp); break; default: dev_dbg(&priv->i2c->dev, "%s(): unknown delivery system %d\n", __func__, p->delivery_system); - break; + p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + return; + } + + if (!ret) { + p->cnr.stat[0].scale = FE_SCALE_DECIBEL; + p->cnr.stat[0].svalue = tmp; + } else { + p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; } - *snr = tmp & 0xffff; - return 0; } -static int cxd2841er_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) +static void cxd2841er_read_ucblocks(struct dvb_frontend *fe) { struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct cxd2841er_priv *priv = fe->demodulator_priv; + u32 ucblocks; dev_dbg(&priv->i2c->dev, "%s()\n", __func__); switch (p->delivery_system) { + case SYS_DVBC_ANNEX_A: + case SYS_DVBC_ANNEX_B: + case SYS_DVBC_ANNEX_C: + cxd2841er_read_packet_errors_c(priv, &ucblocks); + break; case SYS_DVBT: - cxd2841er_read_packet_errors_t(priv, ucblocks); + cxd2841er_read_packet_errors_t(priv, &ucblocks); break; case SYS_DVBT2: - cxd2841er_read_packet_errors_t2(priv, ucblocks); + cxd2841er_read_packet_errors_t2(priv, &ucblocks); break; - default: - *ucblocks = 0; + case SYS_ISDBT: + cxd2841er_read_packet_errors_i(priv, &ucblocks); break; + default: + p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + return; } dev_dbg(&priv->i2c->dev, "%s()\n", __func__); - return 0; + + p->block_error.stat[0].scale = FE_SCALE_COUNTER; + p->block_error.stat[0].uvalue = ucblocks; } static int cxd2841er_dvbt2_set_profile( @@ -1524,15 +2015,18 @@ static int cxd2841er_dvbt2_set_profile( switch (profile) { case DVBT2_PROFILE_BASE: tune_mode = 0x01; - seq_not2d_time = 12; + /* Set early unlock time */ + seq_not2d_time = (priv->xtal == SONY_XTAL_24000)?0x0E:0x0C; break; case DVBT2_PROFILE_LITE: tune_mode = 0x05; - seq_not2d_time = 40; + /* Set early unlock time */ + seq_not2d_time = (priv->xtal == SONY_XTAL_24000)?0x2E:0x28; break; case DVBT2_PROFILE_ANY: tune_mode = 0x00; - seq_not2d_time = 40; + /* Set early unlock time */ + seq_not2d_time = (priv->xtal == SONY_XTAL_24000)?0x2E:0x28; break; default: return -EINVAL; @@ -1574,254 +2068,617 @@ static int cxd2841er_sleep_tc_to_active_t2_band(struct cxd2841er_priv *priv, u32 bandwidth) { u32 iffreq; - u8 b20_9f[5]; - u8 b10_a6[14]; - u8 b10_b6[3]; - u8 b10_d7; + u8 data[MAX_WRITE_REGSIZE]; + + const uint8_t nominalRate8bw[3][5] = { + /* TRCG Nominal Rate [37:0] */ + {0x11, 0xF0, 0x00, 0x00, 0x00}, /* 20.5MHz XTal */ + {0x15, 0x00, 0x00, 0x00, 0x00}, /* 24MHz XTal */ + {0x11, 0xF0, 0x00, 0x00, 0x00} /* 41MHz XTal */ + }; + + const uint8_t nominalRate7bw[3][5] = { + /* TRCG Nominal Rate [37:0] */ + {0x14, 0x80, 0x00, 0x00, 0x00}, /* 20.5MHz XTal */ + {0x18, 0x00, 0x00, 0x00, 0x00}, /* 24MHz XTal */ + {0x14, 0x80, 0x00, 0x00, 0x00} /* 41MHz XTal */ + }; + + const uint8_t nominalRate6bw[3][5] = { + /* TRCG Nominal Rate [37:0] */ + {0x17, 0xEA, 0xAA, 0xAA, 0xAA}, /* 20.5MHz XTal */ + {0x1C, 0x00, 0x00, 0x00, 0x00}, /* 24MHz XTal */ + {0x17, 0xEA, 0xAA, 0xAA, 0xAA} /* 41MHz XTal */ + }; + + const uint8_t nominalRate5bw[3][5] = { + /* TRCG Nominal Rate [37:0] */ + {0x1C, 0xB3, 0x33, 0x33, 0x33}, /* 20.5MHz XTal */ + {0x21, 0x99, 0x99, 0x99, 0x99}, /* 24MHz XTal */ + {0x1C, 0xB3, 0x33, 0x33, 0x33} /* 41MHz XTal */ + }; + + const uint8_t nominalRate17bw[3][5] = { + /* TRCG Nominal Rate [37:0] */ + {0x58, 0xE2, 0xAF, 0xE0, 0xBC}, /* 20.5MHz XTal */ + {0x68, 0x0F, 0xA2, 0x32, 0xD0}, /* 24MHz XTal */ + {0x58, 0xE2, 0xAF, 0xE0, 0xBC} /* 41MHz XTal */ + }; + + const uint8_t itbCoef8bw[3][14] = { + {0x26, 0xAF, 0x06, 0xCD, 0x13, 0xBB, 0x28, 0xBA, + 0x23, 0xA9, 0x1F, 0xA8, 0x2C, 0xC8}, /* 20.5MHz XTal */ + {0x2F, 0xBA, 0x28, 0x9B, 0x28, 0x9D, 0x28, 0xA1, + 0x29, 0xA5, 0x2A, 0xAC, 0x29, 0xB5}, /* 24MHz XTal */ + {0x26, 0xAF, 0x06, 0xCD, 0x13, 0xBB, 0x28, 0xBA, + 0x23, 0xA9, 0x1F, 0xA8, 0x2C, 0xC8} /* 41MHz XTal */ + }; + + const uint8_t itbCoef7bw[3][14] = { + {0x2C, 0xBD, 0x02, 0xCF, 0x04, 0xF8, 0x23, 0xA6, + 0x29, 0xB0, 0x26, 0xA9, 0x21, 0xA5}, /* 20.5MHz XTal */ + {0x30, 0xB1, 0x29, 0x9A, 0x28, 0x9C, 0x28, 0xA0, + 0x29, 0xA2, 0x2B, 0xA6, 0x2B, 0xAD}, /* 24MHz XTal */ + {0x2C, 0xBD, 0x02, 0xCF, 0x04, 0xF8, 0x23, 0xA6, + 0x29, 0xB0, 0x26, 0xA9, 0x21, 0xA5} /* 41MHz XTal */ + }; + + const uint8_t itbCoef6bw[3][14] = { + {0x27, 0xA7, 0x28, 0xB3, 0x02, 0xF0, 0x01, 0xE8, + 0x00, 0xCF, 0x00, 0xE6, 0x23, 0xA4}, /* 20.5MHz XTal */ + {0x31, 0xA8, 0x29, 0x9B, 0x27, 0x9C, 0x28, 0x9E, + 0x29, 0xA4, 0x29, 0xA2, 0x29, 0xA8}, /* 24MHz XTal */ + {0x27, 0xA7, 0x28, 0xB3, 0x02, 0xF0, 0x01, 0xE8, + 0x00, 0xCF, 0x00, 0xE6, 0x23, 0xA4} /* 41MHz XTal */ + }; + + const uint8_t itbCoef5bw[3][14] = { + {0x27, 0xA7, 0x28, 0xB3, 0x02, 0xF0, 0x01, 0xE8, + 0x00, 0xCF, 0x00, 0xE6, 0x23, 0xA4}, /* 20.5MHz XTal */ + {0x31, 0xA8, 0x29, 0x9B, 0x27, 0x9C, 0x28, 0x9E, + 0x29, 0xA4, 0x29, 0xA2, 0x29, 0xA8}, /* 24MHz XTal */ + {0x27, 0xA7, 0x28, 0xB3, 0x02, 0xF0, 0x01, 0xE8, + 0x00, 0xCF, 0x00, 0xE6, 0x23, 0xA4} /* 41MHz XTal */ + }; + + const uint8_t itbCoef17bw[3][14] = { + {0x25, 0xA0, 0x36, 0x8D, 0x2E, 0x94, 0x28, 0x9B, + 0x32, 0x90, 0x2C, 0x9D, 0x29, 0x99}, /* 20.5MHz XTal */ + {0x33, 0x8E, 0x2B, 0x97, 0x2D, 0x95, 0x37, 0x8B, + 0x30, 0x97, 0x2D, 0x9A, 0x21, 0xA4}, /* 24MHz XTal */ + {0x25, 0xA0, 0x36, 0x8D, 0x2E, 0x94, 0x28, 0x9B, + 0x32, 0x90, 0x2C, 0x9D, 0x29, 0x99} /* 41MHz XTal */ + }; + + /* Set SLV-T Bank : 0x20 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x20); - dev_dbg(&priv->i2c->dev, "%s()\n", __func__); switch (bandwidth) { case 8000000: - /* bank 0x20, reg 0x9f */ - b20_9f[0] = 0x11; - b20_9f[1] = 0xf0; - b20_9f[2] = 0x00; - b20_9f[3] = 0x00; - b20_9f[4] = 0x00; - /* bank 0x10, reg 0xa6 */ - b10_a6[0] = 0x26; - b10_a6[1] = 0xaf; - b10_a6[2] = 0x06; - b10_a6[3] = 0xcd; - b10_a6[4] = 0x13; - b10_a6[5] = 0xbb; - b10_a6[6] = 0x28; - b10_a6[7] = 0xba; - b10_a6[8] = 0x23; - b10_a6[9] = 0xa9; - b10_a6[10] = 0x1f; - b10_a6[11] = 0xa8; - b10_a6[12] = 0x2c; - b10_a6[13] = 0xc8; - iffreq = MAKE_IFFREQ_CONFIG(4.80); - b10_d7 = 0x00; + /* <Timing Recovery setting> */ + cxd2841er_write_regs(priv, I2C_SLVT, + 0x9F, nominalRate8bw[priv->xtal], 5); + + /* Set SLV-T Bank : 0x27 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x27); + cxd2841er_set_reg_bits(priv, I2C_SLVT, + 0x7a, 0x00, 0x0f); + + /* Set SLV-T Bank : 0x10 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10); + + /* Group delay equaliser settings for + * ASCOT2D, ASCOT2E and ASCOT3 tuners + */ + cxd2841er_write_regs(priv, I2C_SLVT, + 0xA6, itbCoef8bw[priv->xtal], 14); + /* <IF freq setting> */ + iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 4.80); + data[0] = (u8) ((iffreq >> 16) & 0xff); + data[1] = (u8)((iffreq >> 8) & 0xff); + data[2] = (u8)(iffreq & 0xff); + cxd2841er_write_regs(priv, I2C_SLVT, 0xB6, data, 3); + /* System bandwidth setting */ + cxd2841er_set_reg_bits( + priv, I2C_SLVT, 0xD7, 0x00, 0x07); break; case 7000000: - /* bank 0x20, reg 0x9f */ - b20_9f[0] = 0x14; - b20_9f[1] = 0x80; - b20_9f[2] = 0x00; - b20_9f[3] = 0x00; - b20_9f[4] = 0x00; - /* bank 0x10, reg 0xa6 */ - b10_a6[0] = 0x2C; - b10_a6[1] = 0xBD; - b10_a6[2] = 0x02; - b10_a6[3] = 0xCF; - b10_a6[4] = 0x04; - b10_a6[5] = 0xF8; - b10_a6[6] = 0x23; - b10_a6[7] = 0xA6; - b10_a6[8] = 0x29; - b10_a6[9] = 0xB0; - b10_a6[10] = 0x26; - b10_a6[11] = 0xA9; - b10_a6[12] = 0x21; - b10_a6[13] = 0xA5; - iffreq = MAKE_IFFREQ_CONFIG(4.2); - b10_d7 = 0x02; + /* <Timing Recovery setting> */ + cxd2841er_write_regs(priv, I2C_SLVT, + 0x9F, nominalRate7bw[priv->xtal], 5); + + /* Set SLV-T Bank : 0x27 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x27); + cxd2841er_set_reg_bits(priv, I2C_SLVT, + 0x7a, 0x00, 0x0f); + + /* Set SLV-T Bank : 0x10 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10); + + /* Group delay equaliser settings for + * ASCOT2D, ASCOT2E and ASCOT3 tuners + */ + cxd2841er_write_regs(priv, I2C_SLVT, + 0xA6, itbCoef7bw[priv->xtal], 14); + /* <IF freq setting> */ + iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 4.20); + data[0] = (u8) ((iffreq >> 16) & 0xff); + data[1] = (u8)((iffreq >> 8) & 0xff); + data[2] = (u8)(iffreq & 0xff); + cxd2841er_write_regs(priv, I2C_SLVT, 0xB6, data, 3); + /* System bandwidth setting */ + cxd2841er_set_reg_bits( + priv, I2C_SLVT, 0xD7, 0x02, 0x07); break; case 6000000: - /* bank 0x20, reg 0x9f */ - b20_9f[0] = 0x17; - b20_9f[1] = 0xEA; - b20_9f[2] = 0xAA; - b20_9f[3] = 0xAA; - b20_9f[4] = 0xAA; - /* bank 0x10, reg 0xa6 */ - b10_a6[0] = 0x27; - b10_a6[1] = 0xA7; - b10_a6[2] = 0x28; - b10_a6[3] = 0xB3; - b10_a6[4] = 0x02; - b10_a6[5] = 0xF0; - b10_a6[6] = 0x01; - b10_a6[7] = 0xE8; - b10_a6[8] = 0x00; - b10_a6[9] = 0xCF; - b10_a6[10] = 0x00; - b10_a6[11] = 0xE6; - b10_a6[12] = 0x23; - b10_a6[13] = 0xA4; - iffreq = MAKE_IFFREQ_CONFIG(3.6); - b10_d7 = 0x04; + /* <Timing Recovery setting> */ + cxd2841er_write_regs(priv, I2C_SLVT, + 0x9F, nominalRate6bw[priv->xtal], 5); + + /* Set SLV-T Bank : 0x27 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x27); + cxd2841er_set_reg_bits(priv, I2C_SLVT, + 0x7a, 0x00, 0x0f); + + /* Set SLV-T Bank : 0x10 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10); + + /* Group delay equaliser settings for + * ASCOT2D, ASCOT2E and ASCOT3 tuners + */ + cxd2841er_write_regs(priv, I2C_SLVT, + 0xA6, itbCoef6bw[priv->xtal], 14); + /* <IF freq setting> */ + iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 3.60); + data[0] = (u8) ((iffreq >> 16) & 0xff); + data[1] = (u8)((iffreq >> 8) & 0xff); + data[2] = (u8)(iffreq & 0xff); + cxd2841er_write_regs(priv, I2C_SLVT, 0xB6, data, 3); + /* System bandwidth setting */ + cxd2841er_set_reg_bits( + priv, I2C_SLVT, 0xD7, 0x04, 0x07); break; case 5000000: - /* bank 0x20, reg 0x9f */ - b20_9f[0] = 0x1C; - b20_9f[1] = 0xB3; - b20_9f[2] = 0x33; - b20_9f[3] = 0x33; - b20_9f[4] = 0x33; - /* bank 0x10, reg 0xa6 */ - b10_a6[0] = 0x27; - b10_a6[1] = 0xA7; - b10_a6[2] = 0x28; - b10_a6[3] = 0xB3; - b10_a6[4] = 0x02; - b10_a6[5] = 0xF0; - b10_a6[6] = 0x01; - b10_a6[7] = 0xE8; - b10_a6[8] = 0x00; - b10_a6[9] = 0xCF; - b10_a6[10] = 0x00; - b10_a6[11] = 0xE6; - b10_a6[12] = 0x23; - b10_a6[13] = 0xA4; - iffreq = MAKE_IFFREQ_CONFIG(3.6); - b10_d7 = 0x06; + /* <Timing Recovery setting> */ + cxd2841er_write_regs(priv, I2C_SLVT, + 0x9F, nominalRate5bw[priv->xtal], 5); + + /* Set SLV-T Bank : 0x27 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x27); + cxd2841er_set_reg_bits(priv, I2C_SLVT, + 0x7a, 0x00, 0x0f); + + /* Set SLV-T Bank : 0x10 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10); + + /* Group delay equaliser settings for + * ASCOT2D, ASCOT2E and ASCOT3 tuners + */ + cxd2841er_write_regs(priv, I2C_SLVT, + 0xA6, itbCoef5bw[priv->xtal], 14); + /* <IF freq setting> */ + iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 3.60); + data[0] = (u8) ((iffreq >> 16) & 0xff); + data[1] = (u8)((iffreq >> 8) & 0xff); + data[2] = (u8)(iffreq & 0xff); + cxd2841er_write_regs(priv, I2C_SLVT, 0xB6, data, 3); + /* System bandwidth setting */ + cxd2841er_set_reg_bits( + priv, I2C_SLVT, 0xD7, 0x06, 0x07); break; case 1712000: - /* bank 0x20, reg 0x9f */ - b20_9f[0] = 0x58; - b20_9f[1] = 0xE2; - b20_9f[2] = 0xAF; - b20_9f[3] = 0xE0; - b20_9f[4] = 0xBC; - /* bank 0x10, reg 0xa6 */ - b10_a6[0] = 0x25; - b10_a6[1] = 0xA0; - b10_a6[2] = 0x36; - b10_a6[3] = 0x8D; - b10_a6[4] = 0x2E; - b10_a6[5] = 0x94; - b10_a6[6] = 0x28; - b10_a6[7] = 0x9B; - b10_a6[8] = 0x32; - b10_a6[9] = 0x90; - b10_a6[10] = 0x2C; - b10_a6[11] = 0x9D; - b10_a6[12] = 0x29; - b10_a6[13] = 0x99; - iffreq = MAKE_IFFREQ_CONFIG(3.5); - b10_d7 = 0x03; + /* <Timing Recovery setting> */ + cxd2841er_write_regs(priv, I2C_SLVT, + 0x9F, nominalRate17bw[priv->xtal], 5); + + /* Set SLV-T Bank : 0x27 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x27); + cxd2841er_set_reg_bits(priv, I2C_SLVT, + 0x7a, 0x03, 0x0f); + + /* Set SLV-T Bank : 0x10 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10); + + /* Group delay equaliser settings for + * ASCOT2D, ASCOT2E and ASCOT3 tuners + */ + cxd2841er_write_regs(priv, I2C_SLVT, + 0xA6, itbCoef17bw[priv->xtal], 14); + /* <IF freq setting> */ + iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 3.50); + data[0] = (u8) ((iffreq >> 16) & 0xff); + data[1] = (u8)((iffreq >> 8) & 0xff); + data[2] = (u8)(iffreq & 0xff); + cxd2841er_write_regs(priv, I2C_SLVT, 0xB6, data, 3); + /* System bandwidth setting */ + cxd2841er_set_reg_bits( + priv, I2C_SLVT, 0xD7, 0x03, 0x07); break; default: return -EINVAL; } - /* Set SLV-T Bank : 0x20 */ - cxd2841er_write_reg(priv, I2C_SLVX, 0x00, 0x20); - cxd2841er_write_regs(priv, I2C_SLVT, 0x9f, b20_9f, sizeof(b20_9f)); - /* Set SLV-T Bank : 0x27 */ - cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x27); - cxd2841er_set_reg_bits( - priv, I2C_SLVT, 0x7a, - (bandwidth == 1712000 ? 0x03 : 0x00), 0x0f); - /* Set SLV-T Bank : 0x10 */ - cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10); - /* Group delay equaliser sett. for ASCOT2E */ - cxd2841er_write_regs(priv, I2C_SLVT, 0xa6, b10_a6, sizeof(b10_a6)); - /* <IF freq setting> */ - b10_b6[0] = (u8) ((iffreq >> 16) & 0xff); - b10_b6[1] = (u8)((iffreq >> 8) & 0xff); - b10_b6[2] = (u8)(iffreq & 0xff); - cxd2841er_write_regs(priv, I2C_SLVT, 0xb6, b10_b6, sizeof(b10_b6)); - /* System bandwidth setting */ - cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xd7, b10_d7, 0x07); return 0; } static int cxd2841er_sleep_tc_to_active_t_band( struct cxd2841er_priv *priv, u32 bandwidth) { - u8 b13_9c[2] = { 0x01, 0x14 }; - u8 bw8mhz_b10_9f[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 }; - u8 bw8mhz_b10_a6[] = { 0x26, 0xAF, 0x06, 0xCD, 0x13, 0xBB, - 0x28, 0xBA, 0x23, 0xA9, 0x1F, 0xA8, 0x2C, 0xC8 }; - u8 bw8mhz_b10_d9[] = { 0x01, 0xE0 }; - u8 bw8mhz_b17_38[] = { 0x01, 0x02 }; - u8 bw7mhz_b10_9f[] = { 0x14, 0x80, 0x00, 0x00, 0x00 }; - u8 bw7mhz_b10_a6[] = { 0x2C, 0xBD, 0x02, 0xCF, 0x04, 0xF8, - 0x23, 0xA6, 0x29, 0xB0, 0x26, 0xA9, 0x21, 0xA5 }; - u8 bw7mhz_b10_d9[] = { 0x12, 0xF8 }; - u8 bw7mhz_b17_38[] = { 0x00, 0x03 }; - u8 bw6mhz_b10_9f[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA }; - u8 bw6mhz_b10_a6[] = { 0x27, 0xA7, 0x28, 0xB3, 0x02, 0xF0, - 0x01, 0xE8, 0x00, 0xCF, 0x00, 0xE6, 0x23, 0xA4 }; - u8 bw6mhz_b10_d9[] = { 0x1F, 0xDC }; - u8 bw6mhz_b17_38[] = { 0x00, 0x03 }; - u8 bw5mhz_b10_9f[] = { 0x1C, 0xB3, 0x33, 0x33, 0x33 }; - u8 bw5mhz_b10_a6[] = { 0x27, 0xA7, 0x28, 0xB3, 0x02, 0xF0, - 0x01, 0xE8, 0x00, 0xCF, 0x00, 0xE6, 0x23, 0xA4 }; - u8 bw5mhz_b10_d9[] = { 0x26, 0x3C }; - u8 bw5mhz_b17_38[] = { 0x00, 0x03 }; - u8 b10_b6[3]; - u8 d7val; + u8 data[MAX_WRITE_REGSIZE]; u32 iffreq; - u8 *b10_9f; - u8 *b10_a6; - u8 *b10_d9; - u8 *b17_38; + u8 nominalRate8bw[3][5] = { + /* TRCG Nominal Rate [37:0] */ + {0x11, 0xF0, 0x00, 0x00, 0x00}, /* 20.5MHz XTal */ + {0x15, 0x00, 0x00, 0x00, 0x00}, /* 24MHz XTal */ + {0x11, 0xF0, 0x00, 0x00, 0x00} /* 41MHz XTal */ + }; + u8 nominalRate7bw[3][5] = { + /* TRCG Nominal Rate [37:0] */ + {0x14, 0x80, 0x00, 0x00, 0x00}, /* 20.5MHz XTal */ + {0x18, 0x00, 0x00, 0x00, 0x00}, /* 24MHz XTal */ + {0x14, 0x80, 0x00, 0x00, 0x00} /* 41MHz XTal */ + }; + u8 nominalRate6bw[3][5] = { + /* TRCG Nominal Rate [37:0] */ + {0x17, 0xEA, 0xAA, 0xAA, 0xAA}, /* 20.5MHz XTal */ + {0x1C, 0x00, 0x00, 0x00, 0x00}, /* 24MHz XTal */ + {0x17, 0xEA, 0xAA, 0xAA, 0xAA} /* 41MHz XTal */ + }; + u8 nominalRate5bw[3][5] = { + /* TRCG Nominal Rate [37:0] */ + {0x1C, 0xB3, 0x33, 0x33, 0x33}, /* 20.5MHz XTal */ + {0x21, 0x99, 0x99, 0x99, 0x99}, /* 24MHz XTal */ + {0x1C, 0xB3, 0x33, 0x33, 0x33} /* 41MHz XTal */ + }; - dev_dbg(&priv->i2c->dev, "%s()\n", __func__); + u8 itbCoef8bw[3][14] = { + {0x26, 0xAF, 0x06, 0xCD, 0x13, 0xBB, 0x28, 0xBA, 0x23, 0xA9, + 0x1F, 0xA8, 0x2C, 0xC8}, /* 20.5MHz XTal */ + {0x2F, 0xBA, 0x28, 0x9B, 0x28, 0x9D, 0x28, 0xA1, 0x29, 0xA5, + 0x2A, 0xAC, 0x29, 0xB5}, /* 24MHz XTal */ + {0x26, 0xAF, 0x06, 0xCD, 0x13, 0xBB, 0x28, 0xBA, 0x23, 0xA9, + 0x1F, 0xA8, 0x2C, 0xC8} /* 41MHz XTal */ + }; + u8 itbCoef7bw[3][14] = { + {0x2C, 0xBD, 0x02, 0xCF, 0x04, 0xF8, 0x23, 0xA6, 0x29, 0xB0, + 0x26, 0xA9, 0x21, 0xA5}, /* 20.5MHz XTal */ + {0x30, 0xB1, 0x29, 0x9A, 0x28, 0x9C, 0x28, 0xA0, 0x29, 0xA2, + 0x2B, 0xA6, 0x2B, 0xAD}, /* 24MHz XTal */ + {0x2C, 0xBD, 0x02, 0xCF, 0x04, 0xF8, 0x23, 0xA6, 0x29, 0xB0, + 0x26, 0xA9, 0x21, 0xA5} /* 41MHz XTal */ + }; + u8 itbCoef6bw[3][14] = { + {0x27, 0xA7, 0x28, 0xB3, 0x02, 0xF0, 0x01, 0xE8, 0x00, 0xCF, + 0x00, 0xE6, 0x23, 0xA4}, /* 20.5MHz XTal */ + {0x31, 0xA8, 0x29, 0x9B, 0x27, 0x9C, 0x28, 0x9E, 0x29, 0xA4, + 0x29, 0xA2, 0x29, 0xA8}, /* 24MHz XTal */ + {0x27, 0xA7, 0x28, 0xB3, 0x02, 0xF0, 0x01, 0xE8, 0x00, 0xCF, + 0x00, 0xE6, 0x23, 0xA4} /* 41MHz XTal */ + }; + u8 itbCoef5bw[3][14] = { + {0x27, 0xA7, 0x28, 0xB3, 0x02, 0xF0, 0x01, 0xE8, 0x00, 0xCF, + 0x00, 0xE6, 0x23, 0xA4}, /* 20.5MHz XTal */ + {0x31, 0xA8, 0x29, 0x9B, 0x27, 0x9C, 0x28, 0x9E, 0x29, 0xA4, + 0x29, 0xA2, 0x29, 0xA8}, /* 24MHz XTal */ + {0x27, 0xA7, 0x28, 0xB3, 0x02, 0xF0, 0x01, 0xE8, 0x00, 0xCF, + 0x00, 0xE6, 0x23, 0xA4} /* 41MHz XTal */ + }; + + /* Set SLV-T Bank : 0x13 */ cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x13); /* Echo performance optimization setting */ - cxd2841er_write_regs(priv, I2C_SLVT, 0x9c, b13_9c, sizeof(b13_9c)); + data[0] = 0x01; + data[1] = 0x14; + cxd2841er_write_regs(priv, I2C_SLVT, 0x9C, data, 2); + + /* Set SLV-T Bank : 0x10 */ cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10); switch (bandwidth) { case 8000000: - b10_9f = bw8mhz_b10_9f; - b10_a6 = bw8mhz_b10_a6; - b10_d9 = bw8mhz_b10_d9; - b17_38 = bw8mhz_b17_38; - d7val = 0; - iffreq = MAKE_IFFREQ_CONFIG(4.80); + /* <Timing Recovery setting> */ + cxd2841er_write_regs(priv, I2C_SLVT, + 0x9F, nominalRate8bw[priv->xtal], 5); + /* Group delay equaliser settings for + * ASCOT2D, ASCOT2E and ASCOT3 tuners + */ + cxd2841er_write_regs(priv, I2C_SLVT, + 0xA6, itbCoef8bw[priv->xtal], 14); + /* <IF freq setting> */ + iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 4.80); + data[0] = (u8) ((iffreq >> 16) & 0xff); + data[1] = (u8)((iffreq >> 8) & 0xff); + data[2] = (u8)(iffreq & 0xff); + cxd2841er_write_regs(priv, I2C_SLVT, 0xB6, data, 3); + /* System bandwidth setting */ + cxd2841er_set_reg_bits( + priv, I2C_SLVT, 0xD7, 0x00, 0x07); + + /* Demod core latency setting */ + if (priv->xtal == SONY_XTAL_24000) { + data[0] = 0x15; + data[1] = 0x28; + } else { + data[0] = 0x01; + data[1] = 0xE0; + } + cxd2841er_write_regs(priv, I2C_SLVT, 0xD9, data, 2); + + /* Notch filter setting */ + data[0] = 0x01; + data[1] = 0x02; + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x17); + cxd2841er_write_regs(priv, I2C_SLVT, 0x38, data, 2); break; case 7000000: - b10_9f = bw7mhz_b10_9f; - b10_a6 = bw7mhz_b10_a6; - b10_d9 = bw7mhz_b10_d9; - b17_38 = bw7mhz_b17_38; - d7val = 2; - iffreq = MAKE_IFFREQ_CONFIG(4.20); + /* <Timing Recovery setting> */ + cxd2841er_write_regs(priv, I2C_SLVT, + 0x9F, nominalRate7bw[priv->xtal], 5); + /* Group delay equaliser settings for + * ASCOT2D, ASCOT2E and ASCOT3 tuners + */ + cxd2841er_write_regs(priv, I2C_SLVT, + 0xA6, itbCoef7bw[priv->xtal], 14); + /* <IF freq setting> */ + iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 4.20); + data[0] = (u8) ((iffreq >> 16) & 0xff); + data[1] = (u8)((iffreq >> 8) & 0xff); + data[2] = (u8)(iffreq & 0xff); + cxd2841er_write_regs(priv, I2C_SLVT, 0xB6, data, 3); + /* System bandwidth setting */ + cxd2841er_set_reg_bits( + priv, I2C_SLVT, 0xD7, 0x02, 0x07); + + /* Demod core latency setting */ + if (priv->xtal == SONY_XTAL_24000) { + data[0] = 0x1F; + data[1] = 0xF8; + } else { + data[0] = 0x12; + data[1] = 0xF8; + } + cxd2841er_write_regs(priv, I2C_SLVT, 0xD9, data, 2); + + /* Notch filter setting */ + data[0] = 0x00; + data[1] = 0x03; + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x17); + cxd2841er_write_regs(priv, I2C_SLVT, 0x38, data, 2); break; case 6000000: - b10_9f = bw6mhz_b10_9f; - b10_a6 = bw6mhz_b10_a6; - b10_d9 = bw6mhz_b10_d9; - b17_38 = bw6mhz_b17_38; - d7val = 4; - iffreq = MAKE_IFFREQ_CONFIG(3.60); + /* <Timing Recovery setting> */ + cxd2841er_write_regs(priv, I2C_SLVT, + 0x9F, nominalRate6bw[priv->xtal], 5); + /* Group delay equaliser settings for + * ASCOT2D, ASCOT2E and ASCOT3 tuners + */ + cxd2841er_write_regs(priv, I2C_SLVT, + 0xA6, itbCoef6bw[priv->xtal], 14); + /* <IF freq setting> */ + iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 3.60); + data[0] = (u8) ((iffreq >> 16) & 0xff); + data[1] = (u8)((iffreq >> 8) & 0xff); + data[2] = (u8)(iffreq & 0xff); + cxd2841er_write_regs(priv, I2C_SLVT, 0xB6, data, 3); + /* System bandwidth setting */ + cxd2841er_set_reg_bits( + priv, I2C_SLVT, 0xD7, 0x04, 0x07); + + /* Demod core latency setting */ + if (priv->xtal == SONY_XTAL_24000) { + data[0] = 0x25; + data[1] = 0x4C; + } else { + data[0] = 0x1F; + data[1] = 0xDC; + } + cxd2841er_write_regs(priv, I2C_SLVT, 0xD9, data, 2); + + /* Notch filter setting */ + data[0] = 0x00; + data[1] = 0x03; + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x17); + cxd2841er_write_regs(priv, I2C_SLVT, 0x38, data, 2); break; case 5000000: - b10_9f = bw5mhz_b10_9f; - b10_a6 = bw5mhz_b10_a6; - b10_d9 = bw5mhz_b10_d9; - b17_38 = bw5mhz_b17_38; - d7val = 6; - iffreq = MAKE_IFFREQ_CONFIG(3.60); + /* <Timing Recovery setting> */ + cxd2841er_write_regs(priv, I2C_SLVT, + 0x9F, nominalRate5bw[priv->xtal], 5); + /* Group delay equaliser settings for + * ASCOT2D, ASCOT2E and ASCOT3 tuners + */ + cxd2841er_write_regs(priv, I2C_SLVT, + 0xA6, itbCoef5bw[priv->xtal], 14); + /* <IF freq setting> */ + iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 3.60); + data[0] = (u8) ((iffreq >> 16) & 0xff); + data[1] = (u8)((iffreq >> 8) & 0xff); + data[2] = (u8)(iffreq & 0xff); + cxd2841er_write_regs(priv, I2C_SLVT, 0xB6, data, 3); + /* System bandwidth setting */ + cxd2841er_set_reg_bits( + priv, I2C_SLVT, 0xD7, 0x06, 0x07); + + /* Demod core latency setting */ + if (priv->xtal == SONY_XTAL_24000) { + data[0] = 0x2C; + data[1] = 0xC2; + } else { + data[0] = 0x26; + data[1] = 0x3C; + } + cxd2841er_write_regs(priv, I2C_SLVT, 0xD9, data, 2); + + /* Notch filter setting */ + data[0] = 0x00; + data[1] = 0x03; + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x17); + cxd2841er_write_regs(priv, I2C_SLVT, 0x38, data, 2); + break; + } + + return 0; +} + +static int cxd2841er_sleep_tc_to_active_i_band( + struct cxd2841er_priv *priv, u32 bandwidth) +{ + u32 iffreq; + u8 data[3]; + + /* TRCG Nominal Rate */ + u8 nominalRate8bw[3][5] = { + {0x00, 0x00, 0x00, 0x00, 0x00}, /* 20.5MHz XTal */ + {0x11, 0xB8, 0x00, 0x00, 0x00}, /* 24MHz XTal */ + {0x00, 0x00, 0x00, 0x00, 0x00} /* 41MHz XTal */ + }; + + u8 nominalRate7bw[3][5] = { + {0x00, 0x00, 0x00, 0x00, 0x00}, /* 20.5MHz XTal */ + {0x14, 0x40, 0x00, 0x00, 0x00}, /* 24MHz XTal */ + {0x00, 0x00, 0x00, 0x00, 0x00} /* 41MHz XTal */ + }; + + u8 nominalRate6bw[3][5] = { + {0x14, 0x2E, 0x00, 0x00, 0x00}, /* 20.5MHz XTal */ + {0x17, 0xA0, 0x00, 0x00, 0x00}, /* 24MHz XTal */ + {0x14, 0x2E, 0x00, 0x00, 0x00} /* 41MHz XTal */ + }; + + u8 itbCoef8bw[3][14] = { + {0x00}, /* 20.5MHz XTal */ + {0x2F, 0xBA, 0x28, 0x9B, 0x28, 0x9D, 0x28, 0xA1, 0x29, + 0xA5, 0x2A, 0xAC, 0x29, 0xB5}, /* 24MHz Xtal */ + {0x0}, /* 41MHz XTal */ + }; + + u8 itbCoef7bw[3][14] = { + {0x00}, /* 20.5MHz XTal */ + {0x30, 0xB1, 0x29, 0x9A, 0x28, 0x9C, 0x28, 0xA0, 0x29, + 0xA2, 0x2B, 0xA6, 0x2B, 0xAD}, /* 24MHz Xtal */ + {0x00}, /* 41MHz XTal */ + }; + + u8 itbCoef6bw[3][14] = { + {0x27, 0xA7, 0x28, 0xB3, 0x02, 0xF0, 0x01, 0xE8, 0x00, + 0xCF, 0x00, 0xE6, 0x23, 0xA4}, /* 20.5MHz XTal */ + {0x31, 0xA8, 0x29, 0x9B, 0x27, 0x9C, 0x28, 0x9E, 0x29, + 0xA4, 0x29, 0xA2, 0x29, 0xA8}, /* 24MHz Xtal */ + {0x27, 0xA7, 0x28, 0xB3, 0x02, 0xF0, 0x01, 0xE8, 0x00, + 0xCF, 0x00, 0xE6, 0x23, 0xA4}, /* 41MHz XTal */ + }; + + dev_dbg(&priv->i2c->dev, "%s() bandwidth=%u\n", __func__, bandwidth); + /* Set SLV-T Bank : 0x10 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10); + + /* 20.5/41MHz Xtal support is not available + * on ISDB-T 7MHzBW and 8MHzBW + */ + if (priv->xtal != SONY_XTAL_24000 && bandwidth > 6000000) { + dev_err(&priv->i2c->dev, + "%s(): bandwidth %d supported only for 24MHz xtal\n", + __func__, bandwidth); + return -EINVAL; + } + + switch (bandwidth) { + case 8000000: + /* TRCG Nominal Rate */ + 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, + 0xA6, itbCoef8bw[priv->xtal], 14); + + /* IF freq setting */ + iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 4.75); + data[0] = (u8) ((iffreq >> 16) & 0xff); + data[1] = (u8)((iffreq >> 8) & 0xff); + data[2] = (u8)(iffreq & 0xff); + cxd2841er_write_regs(priv, I2C_SLVT, 0xB6, data, 3); + + /* System bandwidth setting */ + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xd7, 0x0, 0x7); + + /* Demod core latency setting */ + data[0] = 0x13; + data[1] = 0xFC; + cxd2841er_write_regs(priv, I2C_SLVT, 0xD9, data, 2); + + /* Acquisition optimization setting */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x12); + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x71, 0x03, 0x07); + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x15); + cxd2841er_write_reg(priv, I2C_SLVT, 0xBE, 0x03); + break; + case 7000000: + /* TRCG Nominal Rate */ + 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, + 0xA6, itbCoef7bw[priv->xtal], 14); + + /* IF freq setting */ + iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 4.15); + data[0] = (u8) ((iffreq >> 16) & 0xff); + data[1] = (u8)((iffreq >> 8) & 0xff); + data[2] = (u8)(iffreq & 0xff); + cxd2841er_write_regs(priv, I2C_SLVT, 0xB6, data, 3); + + /* System bandwidth setting */ + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xd7, 0x02, 0x7); + + /* Demod core latency setting */ + data[0] = 0x1A; + data[1] = 0xFA; + cxd2841er_write_regs(priv, I2C_SLVT, 0xD9, data, 2); + + /* Acquisition optimization setting */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x12); + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x71, 0x03, 0x07); + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x15); + cxd2841er_write_reg(priv, I2C_SLVT, 0xBE, 0x02); + break; + case 6000000: + /* TRCG Nominal Rate */ + 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, + 0xA6, itbCoef6bw[priv->xtal], 14); + + /* IF freq setting */ + iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 3.55); + data[0] = (u8) ((iffreq >> 16) & 0xff); + data[1] = (u8)((iffreq >> 8) & 0xff); + data[2] = (u8)(iffreq & 0xff); + cxd2841er_write_regs(priv, I2C_SLVT, 0xB6, data, 3); + + /* System bandwidth setting */ + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xd7, 0x04, 0x7); + + /* Demod core latency setting */ + if (priv->xtal == SONY_XTAL_24000) { + data[0] = 0x1F; + data[1] = 0x79; + } else { + data[0] = 0x1A; + data[1] = 0xE2; + } + cxd2841er_write_regs(priv, I2C_SLVT, 0xD9, data, 2); + + /* Acquisition optimization setting */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x12); + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x71, 0x07, 0x07); + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x15); + cxd2841er_write_reg(priv, I2C_SLVT, 0xBE, 0x02); break; default: dev_dbg(&priv->i2c->dev, "%s(): invalid bandwidth %d\n", - __func__, bandwidth); + __func__, bandwidth); return -EINVAL; } - /* <IF freq setting> */ - b10_b6[0] = (u8) ((iffreq >> 16) & 0xff); - b10_b6[1] = (u8)((iffreq >> 8) & 0xff); - b10_b6[2] = (u8)(iffreq & 0xff); - cxd2841er_write_regs( - priv, I2C_SLVT, 0x9f, b10_9f, sizeof(bw8mhz_b10_9f)); - cxd2841er_write_regs( - priv, I2C_SLVT, 0xa6, b10_a6, sizeof(bw8mhz_b10_a6)); - cxd2841er_write_regs(priv, I2C_SLVT, 0xb6, b10_b6, sizeof(b10_b6)); - cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xd7, d7val, 0x7); - cxd2841er_write_regs( - priv, I2C_SLVT, 0xd9, b10_d9, sizeof(bw8mhz_b10_d9)); - cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x17); - cxd2841er_write_regs( - priv, I2C_SLVT, 0x38, b17_38, sizeof(bw8mhz_b17_38)); return 0; } @@ -1837,7 +2694,7 @@ static int cxd2841er_sleep_tc_to_active_c_band(struct cxd2841er_priv *priv, u8 b10_b6[3]; u32 iffreq; - dev_dbg(&priv->i2c->dev, "%s()\n", __func__); + dev_dbg(&priv->i2c->dev, "%s() bw=%d\n", __func__, bandwidth); cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10); switch (bandwidth) { case 8000000: @@ -1854,7 +2711,7 @@ static int cxd2841er_sleep_tc_to_active_c_band(struct cxd2841er_priv *priv, iffreq = MAKE_IFFREQ_CONFIG(3.7); break; default: - dev_dbg(&priv->i2c->dev, "%s(): unsupported bandwidth %d\n", + dev_err(&priv->i2c->dev, "%s(): unsupported bandwidth %d\n", __func__, bandwidth); return -EINVAL; } @@ -1902,6 +2759,7 @@ static int cxd2841er_sleep_tc_to_active_t(struct cxd2841er_priv *priv, u32 bandwidth) { u8 data[2] = { 0x09, 0x54 }; + u8 data24m[3] = {0xDC, 0x6C, 0x00}; dev_dbg(&priv->i2c->dev, "%s()\n", __func__); cxd2841er_set_ts_clock_mode(priv, SYS_DVBT); @@ -1919,7 +2777,11 @@ static int cxd2841er_sleep_tc_to_active_t(struct cxd2841er_priv *priv, cxd2841er_write_reg(priv, I2C_SLVT, 0x30, 0x00); /* Enable ADC 1 */ cxd2841er_write_reg(priv, I2C_SLVT, 0x41, 0x1a); - /* xtal freq 20.5MHz */ + /* Enable ADC 2 & 3 */ + if (priv->xtal == SONY_XTAL_41000) { + data[0] = 0x0A; + data[1] = 0xD4; + } cxd2841er_write_regs(priv, I2C_SLVT, 0x43, data, 2); /* Enable ADC 4 */ cxd2841er_write_reg(priv, I2C_SLVX, 0x18, 0x00); @@ -1947,6 +2809,15 @@ static int cxd2841er_sleep_tc_to_active_t(struct cxd2841er_priv *priv, /* TSIF setting */ cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xce, 0x01, 0x01); cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xcf, 0x01, 0x01); + + if (priv->xtal == SONY_XTAL_24000) { + /* Set SLV-T Bank : 0x10 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10); + cxd2841er_write_reg(priv, I2C_SLVT, 0xBF, 0x60); + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x18); + cxd2841er_write_regs(priv, I2C_SLVT, 0x24, data24m, 3); + } + cxd2841er_sleep_tc_to_active_t_band(priv, bandwidth); /* Set SLV-T Bank : 0x00 */ cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x00); @@ -1961,7 +2832,7 @@ static int cxd2841er_sleep_tc_to_active_t(struct cxd2841er_priv *priv, static int cxd2841er_sleep_tc_to_active_t2(struct cxd2841er_priv *priv, u32 bandwidth) { - u8 data[2] = { 0x09, 0x54 }; + u8 data[MAX_WRITE_REGSIZE]; dev_dbg(&priv->i2c->dev, "%s()\n", __func__); cxd2841er_set_ts_clock_mode(priv, SYS_DVBT2); @@ -1974,12 +2845,21 @@ static int cxd2841er_sleep_tc_to_active_t2(struct cxd2841er_priv *priv, /* Enable demod clock */ cxd2841er_write_reg(priv, I2C_SLVT, 0x2c, 0x01); /* Disable RF level monitor */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x59, 0x00); cxd2841er_write_reg(priv, I2C_SLVT, 0x2f, 0x00); /* Enable ADC clock */ cxd2841er_write_reg(priv, I2C_SLVT, 0x30, 0x00); /* Enable ADC 1 */ cxd2841er_write_reg(priv, I2C_SLVT, 0x41, 0x1a); - /* xtal freq 20.5MHz */ + + if (priv->xtal == SONY_XTAL_41000) { + data[0] = 0x0A; + data[1] = 0xD4; + } else { + data[0] = 0x09; + data[1] = 0x54; + } + cxd2841er_write_regs(priv, I2C_SLVT, 0x43, data, 2); /* Enable ADC 4 */ cxd2841er_write_reg(priv, I2C_SLVX, 0x18, 0x00); @@ -2002,6 +2882,10 @@ static int cxd2841er_sleep_tc_to_active_t2(struct cxd2841er_priv *priv, /* Set SLV-T Bank : 0x2b */ cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x2b); cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x76, 0x20, 0x70); + /* Set SLV-T Bank : 0x23 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x23); + /* L1 Control setting */ + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xE6, 0x00, 0x03); /* Set SLV-T Bank : 0x00 */ cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x00); /* TSIF setting */ @@ -2020,6 +2904,72 @@ static int cxd2841er_sleep_tc_to_active_t2(struct cxd2841er_priv *priv, cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x2b); cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x11, 0x20, 0x3f); + /* 24MHz Xtal setting */ + if (priv->xtal == SONY_XTAL_24000) { + /* Set SLV-T Bank : 0x11 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x11); + data[0] = 0xEB; + data[1] = 0x03; + data[2] = 0x3B; + cxd2841er_write_regs(priv, I2C_SLVT, 0x33, data, 3); + + /* Set SLV-T Bank : 0x20 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x20); + data[0] = 0x5E; + data[1] = 0x5E; + data[2] = 0x47; + cxd2841er_write_regs(priv, I2C_SLVT, 0x95, data, 3); + + cxd2841er_write_reg(priv, I2C_SLVT, 0x99, 0x18); + + data[0] = 0x3F; + data[1] = 0xFF; + cxd2841er_write_regs(priv, I2C_SLVT, 0xD9, data, 2); + + /* Set SLV-T Bank : 0x24 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x24); + data[0] = 0x0B; + data[1] = 0x72; + cxd2841er_write_regs(priv, I2C_SLVT, 0x34, data, 2); + + data[0] = 0x93; + data[1] = 0xF3; + data[2] = 0x00; + cxd2841er_write_regs(priv, I2C_SLVT, 0xD2, data, 3); + + data[0] = 0x05; + data[1] = 0xB8; + data[2] = 0xD8; + cxd2841er_write_regs(priv, I2C_SLVT, 0xDD, data, 3); + + cxd2841er_write_reg(priv, I2C_SLVT, 0xE0, 0x00); + + /* Set SLV-T Bank : 0x25 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x25); + cxd2841er_write_reg(priv, I2C_SLVT, 0xED, 0x60); + + /* Set SLV-T Bank : 0x27 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x27); + cxd2841er_write_reg(priv, I2C_SLVT, 0xFA, 0x34); + + /* Set SLV-T Bank : 0x2B */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x2B); + cxd2841er_write_reg(priv, I2C_SLVT, 0x4B, 0x2F); + cxd2841er_write_reg(priv, I2C_SLVT, 0x9E, 0x0E); + + /* Set SLV-T Bank : 0x2D */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x2D); + data[0] = 0x89; + data[1] = 0x89; + cxd2841er_write_regs(priv, I2C_SLVT, 0x24, data, 2); + + /* Set SLV-T Bank : 0x5E */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x5E); + data[0] = 0x24; + data[1] = 0x95; + cxd2841er_write_regs(priv, I2C_SLVT, 0x8C, data, 2); + } + cxd2841er_sleep_tc_to_active_t2_band(priv, bandwidth); /* Set SLV-T Bank : 0x00 */ @@ -2032,6 +2982,84 @@ static int cxd2841er_sleep_tc_to_active_t2(struct cxd2841er_priv *priv, return 0; } +/* ISDB-Tb part */ +static int cxd2841er_sleep_tc_to_active_i(struct cxd2841er_priv *priv, + u32 bandwidth) +{ + u8 data[2] = { 0x09, 0x54 }; + u8 data24m[2] = {0x60, 0x00}; + u8 data24m2[3] = {0xB7, 0x1B, 0x00}; + + dev_dbg(&priv->i2c->dev, "%s()\n", __func__); + cxd2841er_set_ts_clock_mode(priv, SYS_DVBT); + /* Set SLV-X Bank : 0x00 */ + cxd2841er_write_reg(priv, I2C_SLVX, 0x00, 0x00); + /* Set demod mode */ + cxd2841er_write_reg(priv, I2C_SLVX, 0x17, 0x06); + /* Set SLV-T Bank : 0x00 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x00); + /* Enable demod clock */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x2c, 0x01); + /* Enable RF level monitor */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x2f, 0x01); + cxd2841er_write_reg(priv, I2C_SLVT, 0x59, 0x01); + /* Enable ADC clock */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x30, 0x00); + /* Enable ADC 1 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x41, 0x1a); + /* xtal freq 20.5MHz or 24M */ + 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); + /* FEC Auto Recovery setting */ + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x30, 0x01, 0x01); + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x31, 0x00, 0x01); + /* ISDB-T initial setting */ + /* Set SLV-T Bank : 0x00 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x00); + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xce, 0x00, 0x01); + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xcf, 0x00, 0x01); + /* Set SLV-T Bank : 0x10 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10); + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x69, 0x04, 0x07); + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x6B, 0x03, 0x07); + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x9D, 0x50, 0xFF); + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xD3, 0x06, 0x1F); + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xED, 0x00, 0x01); + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xE2, 0xCE, 0x80); + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xF2, 0x13, 0x10); + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xDE, 0x2E, 0x3F); + /* Set SLV-T Bank : 0x15 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x15); + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xDE, 0x02, 0x03); + /* Set SLV-T Bank : 0x1E */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x1E); + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x73, 0x68, 0xFF); + /* Set SLV-T Bank : 0x63 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x63); + cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x81, 0x00, 0x01); + + /* for xtal 24MHz */ + /* Set SLV-T Bank : 0x10 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10); + cxd2841er_write_regs(priv, I2C_SLVT, 0xBF, data24m, 2); + /* Set SLV-T Bank : 0x60 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x60); + cxd2841er_write_regs(priv, I2C_SLVT, 0xA8, data24m2, 3); + + cxd2841er_sleep_tc_to_active_i_band(priv, bandwidth); + /* Set SLV-T Bank : 0x00 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x00); + /* Disable HiZ Setting 1 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x80, 0x28); + /* Disable HiZ Setting 2 */ + cxd2841er_write_reg(priv, I2C_SLVT, 0x81, 0x00); + priv->state = STATE_ACTIVE_TC; + return 0; +} + static int cxd2841er_sleep_tc_to_active_c(struct cxd2841er_priv *priv, u32 bandwidth) { @@ -2079,7 +3107,7 @@ static int cxd2841er_sleep_tc_to_active_c(struct cxd2841er_priv *priv, cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xce, 0x01, 0x01); cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xcf, 0x01, 0x01); - cxd2841er_sleep_tc_to_active_c_band(priv, 8000000); + cxd2841er_sleep_tc_to_active_c_band(priv, bandwidth); /* Set SLV-T Bank : 0x00 */ cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x00); /* Disable HiZ Setting 1 */ @@ -2094,8 +3122,6 @@ static int cxd2841er_get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties *p) { enum fe_status status = 0; - u16 strength = 0, snr = 0; - u32 errors = 0, ber = 0; struct cxd2841er_priv *priv = fe->demodulator_priv; dev_dbg(&priv->i2c->dev, "%s()\n", __func__); @@ -2104,32 +3130,18 @@ static int cxd2841er_get_frontend(struct dvb_frontend *fe, else if (priv->state == STATE_ACTIVE_TC) cxd2841er_read_status_tc(fe, &status); + cxd2841er_read_signal_strength(fe); + if (status & FE_HAS_LOCK) { - cxd2841er_read_signal_strength(fe, &strength); - p->strength.len = 1; - p->strength.stat[0].scale = FE_SCALE_RELATIVE; - p->strength.stat[0].uvalue = strength; - cxd2841er_read_snr(fe, &snr); - p->cnr.len = 1; - p->cnr.stat[0].scale = FE_SCALE_DECIBEL; - p->cnr.stat[0].svalue = snr; - cxd2841er_read_ucblocks(fe, &errors); - p->block_error.len = 1; - p->block_error.stat[0].scale = FE_SCALE_COUNTER; - p->block_error.stat[0].uvalue = errors; - cxd2841er_read_ber(fe, &ber); - p->post_bit_error.len = 1; - p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; - p->post_bit_error.stat[0].uvalue = ber; + cxd2841er_read_snr(fe); + cxd2841er_read_ucblocks(fe); + + cxd2841er_read_ber(fe); } else { - p->strength.len = 1; - p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; - p->cnr.len = 1; p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; - p->block_error.len = 1; p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; - p->post_bit_error.len = 1; p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; } return 0; } @@ -2142,10 +3154,10 @@ static int cxd2841er_set_frontend_s(struct dvb_frontend *fe) struct dtv_frontend_properties *p = &fe->dtv_property_cache; u32 symbol_rate = p->symbol_rate/1000; - dev_dbg(&priv->i2c->dev, "%s(): %s frequency=%d symbol_rate=%d\n", + dev_dbg(&priv->i2c->dev, "%s(): %s frequency=%d symbol_rate=%d xtal=%d\n", __func__, (p->delivery_system == SYS_DVBS ? "DVB-S" : "DVB-S2"), - p->frequency, symbol_rate); + p->frequency, symbol_rate, priv->xtal); switch (priv->state) { case STATE_SLEEP_S: ret = cxd2841er_sleep_s_to_active_s( @@ -2189,6 +3201,13 @@ static int cxd2841er_set_frontend_s(struct dvb_frontend *fe) __func__, carr_offset); } done: + /* Reset stats */ + p->strength.stat[0].scale = FE_SCALE_RELATIVE; + p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + return ret; } @@ -2199,7 +3218,8 @@ static int cxd2841er_set_frontend_tc(struct dvb_frontend *fe) struct cxd2841er_priv *priv = fe->demodulator_priv; struct dtv_frontend_properties *p = &fe->dtv_property_cache; - dev_dbg(&priv->i2c->dev, "%s()\n", __func__); + dev_dbg(&priv->i2c->dev, "%s() delivery_system=%d bandwidth_hz=%d\n", + __func__, p->delivery_system, p->bandwidth_hz); if (p->delivery_system == SYS_DVBT) { priv->system = SYS_DVBT; switch (priv->state) { @@ -2233,9 +3253,33 @@ static int cxd2841er_set_frontend_tc(struct dvb_frontend *fe) __func__, priv->state); ret = -EINVAL; } + } else if (p->delivery_system == SYS_ISDBT) { + priv->system = SYS_ISDBT; + switch (priv->state) { + case STATE_SLEEP_TC: + ret = cxd2841er_sleep_tc_to_active_i( + priv, p->bandwidth_hz); + break; + case STATE_ACTIVE_TC: + ret = cxd2841er_retune_active(priv, p); + break; + default: + dev_dbg(&priv->i2c->dev, "%s(): invalid state %d\n", + __func__, priv->state); + ret = -EINVAL; + } } else if (p->delivery_system == SYS_DVBC_ANNEX_A || p->delivery_system == SYS_DVBC_ANNEX_C) { priv->system = SYS_DVBC_ANNEX_A; + /* correct bandwidth */ + if (p->bandwidth_hz != 6000000 && + p->bandwidth_hz != 7000000 && + p->bandwidth_hz != 8000000) { + p->bandwidth_hz = 8000000; + dev_dbg(&priv->i2c->dev, "%s(): forcing bandwidth to %d\n", + __func__, p->bandwidth_hz); + } + switch (priv->state) { case STATE_SLEEP_TC: ret = cxd2841er_sleep_tc_to_active_c( @@ -2321,7 +3365,8 @@ static int cxd2841er_tune_tc(struct dvb_frontend *fe, struct cxd2841er_priv *priv = fe->demodulator_priv; struct dtv_frontend_properties *p = &fe->dtv_property_cache; - dev_dbg(&priv->i2c->dev, "%s(): re_tune %d\n", __func__, re_tune); + dev_dbg(&priv->i2c->dev, "%s(): re_tune %d bandwidth=%d\n", __func__, + re_tune, p->bandwidth_hz); if (re_tune) { ret = cxd2841er_set_frontend_tc(fe); if (ret) @@ -2329,7 +3374,16 @@ static int cxd2841er_tune_tc(struct dvb_frontend *fe, cxd2841er_read_status_tc(fe, status); if (*status & FE_HAS_LOCK) { switch (priv->system) { + case SYS_ISDBT: + ret = cxd2841er_get_carrier_offset_i( + priv, p->bandwidth_hz, + &carrier_offset); + break; case SYS_DVBT: + ret = cxd2841er_get_carrier_offset_t( + priv, p->bandwidth_hz, + &carrier_offset); + break; case SYS_DVBT2: ret = cxd2841er_get_carrier_offset_t2( priv, p->bandwidth_hz, @@ -2382,6 +3436,9 @@ static int cxd2841er_sleep_tc(struct dvb_frontend *fe) case SYS_DVBT2: cxd2841er_active_t2_to_sleep_tc(priv); break; + case SYS_ISDBT: + cxd2841er_active_i_to_sleep_tc(priv); + break; case SYS_DVBC_ANNEX_A: cxd2841er_active_c_to_sleep_tc(priv); break; @@ -2512,23 +3569,57 @@ static enum dvbfe_algo cxd2841er_get_algo(struct dvb_frontend *fe) return DVBFE_ALGO_HW; } +static void cxd2841er_init_stats(struct dvb_frontend *fe) +{ + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + + p->strength.len = 1; + p->strength.stat[0].scale = FE_SCALE_RELATIVE; + p->cnr.len = 1; + p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + p->block_error.len = 1; + p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + p->post_bit_error.len = 1; + p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + p->post_bit_count.len = 1; + p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; +} + + static int cxd2841er_init_s(struct dvb_frontend *fe) { struct cxd2841er_priv *priv = fe->demodulator_priv; + /* sanity. force demod to SHUTDOWN state */ + if (priv->state == STATE_SLEEP_S) { + dev_dbg(&priv->i2c->dev, "%s() forcing sleep->shutdown\n", + __func__); + cxd2841er_sleep_s_to_shutdown(priv); + } else if (priv->state == STATE_ACTIVE_S) { + dev_dbg(&priv->i2c->dev, "%s() forcing active->sleep->shutdown\n", + __func__); + cxd2841er_active_s_to_sleep_s(priv); + cxd2841er_sleep_s_to_shutdown(priv); + } + dev_dbg(&priv->i2c->dev, "%s()\n", __func__); cxd2841er_shutdown_to_sleep_s(priv); /* SONY_DEMOD_CONFIG_SAT_IFAGCNEG set to 1 */ cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0xa0); cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xb9, 0x01, 0x01); + + cxd2841er_init_stats(fe); + return 0; } static int cxd2841er_init_tc(struct dvb_frontend *fe) { struct cxd2841er_priv *priv = fe->demodulator_priv; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; - dev_dbg(&priv->i2c->dev, "%s()\n", __func__); + 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 */ cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10); @@ -2538,12 +3629,14 @@ static int cxd2841er_init_tc(struct dvb_frontend *fe) /* 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_init_stats(fe); + return 0; } static struct dvb_frontend_ops cxd2841er_dvbs_s2_ops; -static struct dvb_frontend_ops cxd2841er_dvbt_t2_ops; -static struct dvb_frontend_ops cxd2841er_dvbc_ops; +static struct dvb_frontend_ops cxd2841er_t_c_ops; static struct dvb_frontend *cxd2841er_attach(struct cxd2841er_config *cfg, struct i2c_adapter *i2c, @@ -2551,6 +3644,7 @@ static struct dvb_frontend *cxd2841er_attach(struct cxd2841er_config *cfg, { u8 chip_id = 0; const char *type; + const char *name; struct cxd2841er_priv *priv = NULL; /* allocate memory for the internal state */ @@ -2561,46 +3655,49 @@ static struct dvb_frontend *cxd2841er_attach(struct cxd2841er_config *cfg, priv->config = cfg; priv->i2c_addr_slvx = (cfg->i2c_addr + 4) >> 1; priv->i2c_addr_slvt = (cfg->i2c_addr) >> 1; - /* create dvb_frontend */ - switch (system) { - case SYS_DVBS: - memcpy(&priv->frontend.ops, - &cxd2841er_dvbs_s2_ops, - sizeof(struct dvb_frontend_ops)); - type = "S/S2"; - break; - case SYS_DVBT: - memcpy(&priv->frontend.ops, - &cxd2841er_dvbt_t2_ops, - sizeof(struct dvb_frontend_ops)); - type = "T/T2"; - break; - case SYS_DVBC_ANNEX_A: - memcpy(&priv->frontend.ops, - &cxd2841er_dvbc_ops, - sizeof(struct dvb_frontend_ops)); - type = "C/C2"; - break; - default: - kfree(priv); - return NULL; - } + priv->xtal = cfg->xtal; priv->frontend.demodulator_priv = priv; dev_info(&priv->i2c->dev, - "%s(): attaching CXD2841ER DVB-%s frontend\n", - __func__, type); - dev_info(&priv->i2c->dev, "%s(): I2C adapter %p SLVX addr %x SLVT addr %x\n", __func__, priv->i2c, priv->i2c_addr_slvx, priv->i2c_addr_slvt); chip_id = cxd2841er_chip_id(priv); - if (chip_id != CXD2841ER_CHIP_ID) { + switch (chip_id) { + case CXD2841ER_CHIP_ID: + snprintf(cxd2841er_t_c_ops.info.name, 128, + "Sony CXD2841ER DVB-T/T2/C demodulator"); + name = "CXD2841ER"; + 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"; + break; + default: dev_err(&priv->i2c->dev, "%s(): invalid chip ID 0x%02x\n", - __func__, chip_id); + __func__, chip_id); priv->frontend.demodulator_priv = NULL; kfree(priv); return NULL; } + + /* create dvb_frontend */ + if (system == SYS_DVBS) { + memcpy(&priv->frontend.ops, + &cxd2841er_dvbs_s2_ops, + sizeof(struct dvb_frontend_ops)); + type = "S/S2"; + } else { + memcpy(&priv->frontend.ops, + &cxd2841er_t_c_ops, + sizeof(struct dvb_frontend_ops)); + type = "T/T2/C/ISDB-T"; + } + + dev_info(&priv->i2c->dev, + "%s(): attaching %s DVB-%s frontend\n", + __func__, name, type); dev_info(&priv->i2c->dev, "%s(): chip ID 0x%02x OK.\n", __func__, chip_id); return &priv->frontend; @@ -2613,19 +3710,12 @@ struct dvb_frontend *cxd2841er_attach_s(struct cxd2841er_config *cfg, } EXPORT_SYMBOL(cxd2841er_attach_s); -struct dvb_frontend *cxd2841er_attach_t(struct cxd2841er_config *cfg, +struct dvb_frontend *cxd2841er_attach_t_c(struct cxd2841er_config *cfg, struct i2c_adapter *i2c) { - return cxd2841er_attach(cfg, i2c, SYS_DVBT); + return cxd2841er_attach(cfg, i2c, 0); } -EXPORT_SYMBOL(cxd2841er_attach_t); - -struct dvb_frontend *cxd2841er_attach_c(struct cxd2841er_config *cfg, - struct i2c_adapter *i2c) -{ - return cxd2841er_attach(cfg, i2c, SYS_DVBC_ANNEX_A); -} -EXPORT_SYMBOL(cxd2841er_attach_c); +EXPORT_SYMBOL(cxd2841er_attach_t_c); static struct dvb_frontend_ops cxd2841er_dvbs_s2_ops = { .delsys = { SYS_DVBS, SYS_DVBS2 }, @@ -2655,10 +3745,10 @@ static struct dvb_frontend_ops cxd2841er_dvbs_s2_ops = { .tune = cxd2841er_tune_s }; -static struct dvb_frontend_ops cxd2841er_dvbt_t2_ops = { - .delsys = { SYS_DVBT, SYS_DVBT2 }, +static struct dvb_frontend_ops cxd2841er_t_c_ops = { + .delsys = { SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A }, .info = { - .name = "Sony CXD2841ER DVB-T/T2 demodulator", + .name = "", /* will set in attach function */ .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | @@ -2691,37 +3781,6 @@ static struct dvb_frontend_ops cxd2841er_dvbt_t2_ops = { .get_frontend_algo = cxd2841er_get_algo }; -static struct dvb_frontend_ops cxd2841er_dvbc_ops = { - .delsys = { SYS_DVBC_ANNEX_A }, - .info = { - .name = "Sony CXD2841ER DVB-C demodulator", - .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_QAM_16 | - FE_CAN_QAM_32 | - FE_CAN_QAM_64 | - FE_CAN_QAM_128 | - FE_CAN_QAM_256 | - FE_CAN_QAM_AUTO | - FE_CAN_INVERSION_AUTO, - .frequency_min = 42000000, - .frequency_max = 1002000000 - }, - .init = cxd2841er_init_tc, - .sleep = cxd2841er_sleep_tc, - .release = cxd2841er_release, - .set_frontend = cxd2841er_set_frontend_tc, - .get_frontend = cxd2841er_get_frontend, - .read_status = cxd2841er_read_status_tc, - .tune = cxd2841er_tune_tc, - .i2c_gate_ctrl = cxd2841er_i2c_gate_ctrl, - .get_frontend_algo = cxd2841er_get_algo, -}; - -MODULE_DESCRIPTION("Sony CXD2841ER DVB-C/C2/T/T2/S/S2 demodulator driver"); -MODULE_AUTHOR("Sergey Kozlov <serjk@netup.ru>"); +MODULE_DESCRIPTION("Sony CXD2841ER/CXD2854ER DVB-C/C2/T/T2/S/S2 demodulator driver"); +MODULE_AUTHOR("Sergey Kozlov <serjk@netup.ru>, Abylay Ospan <aospan@netup.ru>"); MODULE_LICENSE("GPL"); |