diff options
Diffstat (limited to 'drivers/media/dvb-frontends')
-rw-r--r-- | drivers/media/dvb-frontends/af9033.c | 327 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/ascot2e.c | 2 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/cxd2841er.c | 468 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/m88ds3103.c | 144 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/m88ds3103_priv.h | 3 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/mb86a20s.c | 3 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/rtl2830.c | 203 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/rtl2830_priv.h | 2 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/rtl2832.c | 1 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/rtl2832_sdr.c | 2 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/si2168.c | 127 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/si2168_priv.h | 8 |
12 files changed, 737 insertions, 553 deletions
diff --git a/drivers/media/dvb-frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c index efebe5ce2429..9a8157a5f49d 100644 --- a/drivers/media/dvb-frontends/af9033.c +++ b/drivers/media/dvb-frontends/af9033.c @@ -41,7 +41,6 @@ struct af9033_dev { u64 post_bit_count; u64 error_block_count; u64 total_block_count; - struct delayed_work stat_work; }; /* write multiple registers */ @@ -468,8 +467,6 @@ static int af9033_init(struct dvb_frontend *fe) c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; c->post_bit_error.len = 1; c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; - /* start statistics polling */ - schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000)); return 0; @@ -485,9 +482,6 @@ static int af9033_sleep(struct dvb_frontend *fe) int ret, i; u8 tmp; - /* stop statistics polling */ - cancel_delayed_work_sync(&dev->stat_work); - ret = af9033_wr_reg(dev, 0x80004c, 1); if (ret < 0) goto err; @@ -821,36 +815,39 @@ err: static int af9033_read_status(struct dvb_frontend *fe, enum fe_status *status) { struct af9033_dev *dev = fe->demodulator_priv; - int ret; - u8 tmp; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + int ret, i, tmp = 0; + u8 u8tmp, buf[7]; + + dev_dbg(&dev->client->dev, "\n"); *status = 0; /* radio channel status, 0=no result, 1=has signal, 2=no signal */ - ret = af9033_rd_reg(dev, 0x800047, &tmp); + ret = af9033_rd_reg(dev, 0x800047, &u8tmp); if (ret < 0) goto err; /* has signal */ - if (tmp == 0x01) + if (u8tmp == 0x01) *status |= FE_HAS_SIGNAL; - if (tmp != 0x02) { + if (u8tmp != 0x02) { /* TPS lock */ - ret = af9033_rd_reg_mask(dev, 0x80f5a9, &tmp, 0x01); + ret = af9033_rd_reg_mask(dev, 0x80f5a9, &u8tmp, 0x01); if (ret < 0) goto err; - if (tmp) + if (u8tmp) *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI; /* full lock */ - ret = af9033_rd_reg_mask(dev, 0x80f999, &tmp, 0x01); + ret = af9033_rd_reg_mask(dev, 0x80f999, &u8tmp, 0x01); if (ret < 0) goto err; - if (tmp) + if (u8tmp) *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; @@ -858,6 +855,148 @@ static int af9033_read_status(struct dvb_frontend *fe, enum fe_status *status) dev->fe_status = *status; + /* signal strength */ + if (dev->fe_status & FE_HAS_SIGNAL) { + if (dev->is_af9035) { + ret = af9033_rd_reg(dev, 0x80004a, &u8tmp); + if (ret) + goto err; + tmp = -u8tmp * 1000; + } else { + ret = af9033_rd_reg(dev, 0x8000f7, &u8tmp); + if (ret) + goto err; + tmp = (u8tmp - 100) * 1000; + } + + c->strength.len = 1; + c->strength.stat[0].scale = FE_SCALE_DECIBEL; + c->strength.stat[0].svalue = tmp; + } else { + c->strength.len = 1; + c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + } + + /* CNR */ + if (dev->fe_status & FE_HAS_VITERBI) { + u32 snr_val, snr_lut_size; + const struct val_snr *snr_lut = NULL; + + /* read value */ + ret = af9033_rd_regs(dev, 0x80002c, buf, 3); + if (ret) + goto err; + + snr_val = (buf[2] << 16) | (buf[1] << 8) | (buf[0] << 0); + + /* read superframe number */ + ret = af9033_rd_reg(dev, 0x80f78b, &u8tmp); + if (ret) + goto err; + + if (u8tmp) + snr_val /= u8tmp; + + /* read current transmission mode */ + ret = af9033_rd_reg(dev, 0x80f900, &u8tmp); + if (ret) + goto err; + + switch ((u8tmp >> 0) & 3) { + case 0: + snr_val *= 4; + break; + case 1: + snr_val *= 1; + break; + case 2: + snr_val *= 2; + break; + default: + snr_val *= 0; + break; + } + + /* read current modulation */ + ret = af9033_rd_reg(dev, 0x80f903, &u8tmp); + if (ret) + goto err; + + switch ((u8tmp >> 0) & 3) { + case 0: + snr_lut_size = ARRAY_SIZE(qpsk_snr_lut); + snr_lut = qpsk_snr_lut; + break; + case 1: + snr_lut_size = ARRAY_SIZE(qam16_snr_lut); + snr_lut = qam16_snr_lut; + break; + case 2: + snr_lut_size = ARRAY_SIZE(qam64_snr_lut); + snr_lut = qam64_snr_lut; + break; + default: + snr_lut_size = 0; + tmp = 0; + break; + } + + for (i = 0; i < snr_lut_size; i++) { + tmp = snr_lut[i].snr * 1000; + if (snr_val < snr_lut[i].val) + break; + } + + c->cnr.len = 1; + c->cnr.stat[0].scale = FE_SCALE_DECIBEL; + c->cnr.stat[0].svalue = tmp; + } else { + c->cnr.len = 1; + c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + } + + /* UCB/PER/BER */ + if (dev->fe_status & FE_HAS_LOCK) { + /* outer FEC, 204 byte packets */ + u16 abort_packet_count, rsd_packet_count; + /* inner FEC, bits */ + u32 rsd_bit_err_count; + + /* + * Packet count used for measurement is 10000 + * (rsd_packet_count). Maybe it should be increased? + */ + + ret = af9033_rd_regs(dev, 0x800032, buf, 7); + if (ret) + goto err; + + abort_packet_count = (buf[1] << 8) | (buf[0] << 0); + rsd_bit_err_count = (buf[4] << 16) | (buf[3] << 8) | buf[2]; + rsd_packet_count = (buf[6] << 8) | (buf[5] << 0); + + dev->error_block_count += abort_packet_count; + dev->total_block_count += rsd_packet_count; + dev->post_bit_error += rsd_bit_err_count; + dev->post_bit_count += rsd_packet_count * 204 * 8; + + c->block_count.len = 1; + c->block_count.stat[0].scale = FE_SCALE_COUNTER; + c->block_count.stat[0].uvalue = dev->total_block_count; + + c->block_error.len = 1; + c->block_error.stat[0].scale = FE_SCALE_COUNTER; + c->block_error.stat[0].uvalue = dev->error_block_count; + + c->post_bit_count.len = 1; + c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; + c->post_bit_count.stat[0].uvalue = dev->post_bit_count; + + c->post_bit_error.len = 1; + c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; + c->post_bit_error.stat[0].uvalue = dev->post_bit_error; + } + return 0; err: @@ -1059,159 +1198,6 @@ err: return ret; } -static void af9033_stat_work(struct work_struct *work) -{ - struct af9033_dev *dev = container_of(work, struct af9033_dev, stat_work.work); - struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; - int ret, tmp, i, len; - u8 u8tmp, buf[7]; - - dev_dbg(&dev->client->dev, "\n"); - - /* signal strength */ - if (dev->fe_status & FE_HAS_SIGNAL) { - if (dev->is_af9035) { - ret = af9033_rd_reg(dev, 0x80004a, &u8tmp); - tmp = -u8tmp * 1000; - } else { - ret = af9033_rd_reg(dev, 0x8000f7, &u8tmp); - tmp = (u8tmp - 100) * 1000; - } - if (ret) - goto err; - - c->strength.len = 1; - c->strength.stat[0].scale = FE_SCALE_DECIBEL; - c->strength.stat[0].svalue = tmp; - } else { - c->strength.len = 1; - c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; - } - - /* CNR */ - if (dev->fe_status & FE_HAS_VITERBI) { - u32 snr_val; - const struct val_snr *snr_lut; - - /* read value */ - ret = af9033_rd_regs(dev, 0x80002c, buf, 3); - if (ret) - goto err; - - snr_val = (buf[2] << 16) | (buf[1] << 8) | (buf[0] << 0); - - /* read superframe number */ - ret = af9033_rd_reg(dev, 0x80f78b, &u8tmp); - if (ret) - goto err; - - if (u8tmp) - snr_val /= u8tmp; - - /* read current transmission mode */ - ret = af9033_rd_reg(dev, 0x80f900, &u8tmp); - if (ret) - goto err; - - switch ((u8tmp >> 0) & 3) { - case 0: - snr_val *= 4; - break; - case 1: - snr_val *= 1; - break; - case 2: - snr_val *= 2; - break; - default: - goto err_schedule_delayed_work; - } - - /* read current modulation */ - ret = af9033_rd_reg(dev, 0x80f903, &u8tmp); - if (ret) - goto err; - - switch ((u8tmp >> 0) & 3) { - case 0: - len = ARRAY_SIZE(qpsk_snr_lut); - snr_lut = qpsk_snr_lut; - break; - case 1: - len = ARRAY_SIZE(qam16_snr_lut); - snr_lut = qam16_snr_lut; - break; - case 2: - len = ARRAY_SIZE(qam64_snr_lut); - snr_lut = qam64_snr_lut; - break; - default: - goto err_schedule_delayed_work; - } - - for (i = 0; i < len; i++) { - tmp = snr_lut[i].snr * 1000; - if (snr_val < snr_lut[i].val) - break; - } - - c->cnr.len = 1; - c->cnr.stat[0].scale = FE_SCALE_DECIBEL; - c->cnr.stat[0].svalue = tmp; - } else { - c->cnr.len = 1; - c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; - } - - /* UCB/PER/BER */ - if (dev->fe_status & FE_HAS_LOCK) { - /* outer FEC, 204 byte packets */ - u16 abort_packet_count, rsd_packet_count; - /* inner FEC, bits */ - u32 rsd_bit_err_count; - - /* - * Packet count used for measurement is 10000 - * (rsd_packet_count). Maybe it should be increased? - */ - - ret = af9033_rd_regs(dev, 0x800032, buf, 7); - if (ret) - goto err; - - abort_packet_count = (buf[1] << 8) | (buf[0] << 0); - rsd_bit_err_count = (buf[4] << 16) | (buf[3] << 8) | buf[2]; - rsd_packet_count = (buf[6] << 8) | (buf[5] << 0); - - dev->error_block_count += abort_packet_count; - dev->total_block_count += rsd_packet_count; - dev->post_bit_error += rsd_bit_err_count; - dev->post_bit_count += rsd_packet_count * 204 * 8; - - c->block_count.len = 1; - c->block_count.stat[0].scale = FE_SCALE_COUNTER; - c->block_count.stat[0].uvalue = dev->total_block_count; - - c->block_error.len = 1; - c->block_error.stat[0].scale = FE_SCALE_COUNTER; - c->block_error.stat[0].uvalue = dev->error_block_count; - - c->post_bit_count.len = 1; - c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; - c->post_bit_count.stat[0].uvalue = dev->post_bit_count; - - c->post_bit_error.len = 1; - c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; - c->post_bit_error.stat[0].uvalue = dev->post_bit_error; - } - -err_schedule_delayed_work: - schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000)); - return; -err: - dev_dbg(&dev->client->dev, "failed=%d\n", ret); -} - static struct dvb_frontend_ops af9033_ops = { .delsys = { SYS_DVBT }, .info = { @@ -1272,7 +1258,6 @@ static int af9033_probe(struct i2c_client *client, /* setup the state */ dev->client = client; - INIT_DELAYED_WORK(&dev->stat_work, af9033_stat_work); memcpy(&dev->cfg, cfg, sizeof(struct af9033_config)); if (dev->cfg.clock != 12000000) { @@ -1372,9 +1357,6 @@ static int af9033_remove(struct i2c_client *client) dev_dbg(&dev->client->dev, "\n"); - /* stop statistics polling */ - cancel_delayed_work_sync(&dev->stat_work); - dev->fe.ops.release = NULL; dev->fe.demodulator_priv = NULL; kfree(dev); @@ -1391,6 +1373,7 @@ MODULE_DEVICE_TABLE(i2c, af9033_id_table); static struct i2c_driver af9033_driver = { .driver = { .name = "af9033", + .suppress_bind_attrs = true, }, .probe = af9033_probe, .remove = af9033_remove, diff --git a/drivers/media/dvb-frontends/ascot2e.c b/drivers/media/dvb-frontends/ascot2e.c index f770f6a2c987..8cc8c4597b6a 100644 --- a/drivers/media/dvb-frontends/ascot2e.c +++ b/drivers/media/dvb-frontends/ascot2e.c @@ -132,7 +132,7 @@ static int ascot2e_write_regs(struct ascot2e_priv *priv, } }; - if (len + 1 >= sizeof(buf)) { + if (len + 1 > sizeof(buf)) { dev_warn(&priv->i2c->dev,"wr reg=%04x: len=%d is too big!\n", reg, len + 1); return -E2BIG; diff --git a/drivers/media/dvb-frontends/cxd2841er.c b/drivers/media/dvb-frontends/cxd2841er.c index d369a7567d18..09c39346167f 100644 --- a/drivers/media/dvb-frontends/cxd2841er.c +++ b/drivers/media/dvb-frontends/cxd2841er.c @@ -36,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, @@ -1262,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) { @@ -1330,11 +1358,53 @@ static int cxd2841er_read_packet_errors_i( return 0; } -static u32 cxd2841er_mon_read_ber_s(struct cxd2841er_priv *priv) +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); @@ -1350,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); @@ -1398,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); @@ -1411,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); @@ -1455,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); @@ -1502,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; @@ -1569,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) @@ -1656,6 +1778,21 @@ static int cxd2841er_read_snr_i(struct cxd2841er_priv *priv, u32 *snr) 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) { @@ -1702,111 +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 = 65535 - cxd2841er_read_agc_gain_i( - priv, p->delivery_system); + 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: - cxd2841er_read_snr_i(priv, &tmp); + 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; case SYS_ISDBT: - cxd2841er_read_packet_errors_i(priv, ucblocks); + cxd2841er_read_packet_errors_i(priv, &ucblocks); break; default: - *ucblocks = 0; - break; + 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( @@ -2926,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__); @@ -2936,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; } @@ -3021,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; } @@ -3382,6 +3569,23 @@ 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; @@ -3403,6 +3607,9 @@ static int cxd2841er_init_s(struct dvb_frontend *fe) /* 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; } @@ -3422,6 +3629,9 @@ 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; } diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c index 5557ef8fc704..e0fe5bc9dbce 100644 --- a/drivers/media/dvb-frontends/m88ds3103.c +++ b/drivers/media/dvb-frontends/m88ds3103.c @@ -306,8 +306,8 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) const struct m88ds3103_reg_val *init; u8 u8tmp, u8tmp1 = 0, u8tmp2 = 0; /* silence compiler warning */ u8 buf[3]; - u16 u16tmp, divide_ratio = 0; - u32 tuner_frequency, target_mclk; + u16 u16tmp; + u32 tuner_frequency_khz, target_mclk; s32 s32tmp; dev_dbg(&client->dev, @@ -344,7 +344,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) } if (fe->ops.tuner_ops.get_frequency) { - ret = fe->ops.tuner_ops.get_frequency(fe, &tuner_frequency); + ret = fe->ops.tuner_ops.get_frequency(fe, &tuner_frequency_khz); if (ret) goto err; } else { @@ -353,20 +353,20 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) * actual frequency used. Carrier offset calculation is not * valid. */ - tuner_frequency = c->frequency; + tuner_frequency_khz = c->frequency; } /* select M88RS6000 demod main mclk and ts mclk from tuner die. */ if (dev->chip_id == M88RS6000_CHIP_ID) { if (c->symbol_rate > 45010000) - dev->mclk_khz = 110250; + dev->mclk = 110250000; else - dev->mclk_khz = 96000; + dev->mclk = 96000000; if (c->delivery_system == SYS_DVBS) - target_mclk = 96000; + target_mclk = 96000000; else - target_mclk = 144000; + target_mclk = 144000000; /* Enable demod clock path */ ret = regmap_write(dev->regmap, 0x06, 0x00); @@ -375,7 +375,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) usleep_range(10000, 20000); } else { /* set M88DS3103 mclk and ts mclk. */ - dev->mclk_khz = 96000; + dev->mclk = 96000000; switch (dev->cfg->ts_mode) { case M88DS3103_TS_SERIAL: @@ -385,14 +385,14 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) case M88DS3103_TS_PARALLEL: case M88DS3103_TS_CI: if (c->delivery_system == SYS_DVBS) - target_mclk = 96000; + target_mclk = 96000000; else { if (c->symbol_rate < 18000000) - target_mclk = 96000; + target_mclk = 96000000; else if (c->symbol_rate < 28000000) - target_mclk = 144000; + target_mclk = 144000000; else - target_mclk = 192000; + target_mclk = 192000000; } break; default: @@ -402,15 +402,15 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) } switch (target_mclk) { - case 96000: + case 96000000: u8tmp1 = 0x02; /* 0b10 */ u8tmp2 = 0x01; /* 0b01 */ break; - case 144000: + case 144000000: u8tmp1 = 0x00; /* 0b00 */ u8tmp2 = 0x01; /* 0b01 */ break; - case 192000: + case 192000000: u8tmp1 = 0x03; /* 0b11 */ u8tmp2 = 0x00; /* 0b00 */ break; @@ -464,8 +464,8 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) } if (dev->chip_id == M88RS6000_CHIP_ID) { - if ((c->delivery_system == SYS_DVBS2) - && ((c->symbol_rate / 1000) <= 5000)) { + if (c->delivery_system == SYS_DVBS2 && + c->symbol_rate <= 5000000) { ret = regmap_write(dev->regmap, 0xc0, 0x04); if (ret) goto err; @@ -522,37 +522,25 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) ret = m88ds3103_update_bits(dev, 0x29, 0x20, u8tmp1); if (ret) goto err; - u8tmp1 = 0; - u8tmp2 = 0; + u16tmp = 0; + u8tmp1 = 0x3f; + u8tmp2 = 0x3f; break; default: - if (dev->cfg->ts_clk) { - divide_ratio = DIV_ROUND_UP(target_mclk, dev->cfg->ts_clk); - u8tmp1 = divide_ratio / 2; - u8tmp2 = DIV_ROUND_UP(divide_ratio, 2); - } + u16tmp = DIV_ROUND_UP(target_mclk, dev->cfg->ts_clk); + u8tmp1 = u16tmp / 2 - 1; + u8tmp2 = DIV_ROUND_UP(u16tmp, 2) - 1; } - dev_dbg(&client->dev, - "target_mclk=%d ts_clk=%d divide_ratio=%d\n", - target_mclk, dev->cfg->ts_clk, divide_ratio); + dev_dbg(&client->dev, "target_mclk=%u ts_clk=%u ts_clk_divide_ratio=%u\n", + target_mclk, dev->cfg->ts_clk, u16tmp); - u8tmp1--; - u8tmp2--; /* u8tmp1[5:2] => fe[3:0], u8tmp1[1:0] => ea[7:6] */ - u8tmp1 &= 0x3f; /* u8tmp2[5:0] => ea[5:0] */ - u8tmp2 &= 0x3f; - - ret = regmap_bulk_read(dev->regmap, 0xfe, &u8tmp, 1); + u8tmp = (u8tmp1 >> 2) & 0x0f; + ret = regmap_update_bits(dev->regmap, 0xfe, 0x0f, u8tmp); if (ret) goto err; - - u8tmp = ((u8tmp & 0xf0) << 0) | u8tmp1 >> 2; - ret = regmap_write(dev->regmap, 0xfe, u8tmp); - if (ret) - goto err; - u8tmp = ((u8tmp1 & 0x03) << 6) | u8tmp2 >> 0; ret = regmap_write(dev->regmap, 0xea, u8tmp); if (ret) @@ -581,7 +569,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) if (ret) goto err; - u16tmp = DIV_ROUND_CLOSEST((c->symbol_rate / 1000) << 15, dev->mclk_khz / 2); + u16tmp = DIV_ROUND_CLOSEST_ULL((u64)c->symbol_rate * 0x10000, dev->mclk); buf[0] = (u16tmp >> 0) & 0xff; buf[1] = (u16tmp >> 8) & 0xff; ret = regmap_bulk_write(dev->regmap, 0x61, buf, 2); @@ -601,13 +589,11 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) goto err; dev_dbg(&client->dev, "carrier offset=%d\n", - (tuner_frequency - c->frequency)); - - s32tmp = 0x10000 * (tuner_frequency - c->frequency); - s32tmp = DIV_ROUND_CLOSEST(s32tmp, dev->mclk_khz); - if (s32tmp < 0) - s32tmp += 0x10000; + (tuner_frequency_khz - c->frequency)); + /* Use 32-bit calc as there is no s64 version of DIV_ROUND_CLOSEST() */ + s32tmp = 0x10000 * (tuner_frequency_khz - c->frequency); + s32tmp = DIV_ROUND_CLOSEST(s32tmp, dev->mclk / 1000); buf[0] = (s32tmp >> 0) & 0xff; buf[1] = (s32tmp >> 8) & 0xff; ret = regmap_bulk_write(dev->regmap, 0x5e, buf, 2); @@ -635,10 +621,10 @@ static int m88ds3103_init(struct dvb_frontend *fe) struct m88ds3103_dev *dev = fe->demodulator_priv; struct i2c_client *client = dev->client; struct dtv_frontend_properties *c = &fe->dtv_property_cache; - int ret, len, remaining; + int ret, len, rem; unsigned int utmp; - const struct firmware *fw = NULL; - u8 *fw_file; + const struct firmware *firmware; + const char *name; dev_dbg(&client->dev, "\n"); @@ -664,7 +650,7 @@ static int m88ds3103_init(struct dvb_frontend *fe) dev_dbg(&client->dev, "firmware=%02x\n", utmp); if (utmp) - goto skip_fw_download; + goto warm; /* global reset, global diseqc reset, golbal fec reset */ ret = regmap_write(dev->regmap, 0x07, 0xe0); @@ -679,52 +665,47 @@ static int m88ds3103_init(struct dvb_frontend *fe) m88ds3103_ops.info.name); if (dev->chip_id == M88RS6000_CHIP_ID) - fw_file = M88RS6000_FIRMWARE; + name = M88RS6000_FIRMWARE; else - fw_file = M88DS3103_FIRMWARE; + name = M88DS3103_FIRMWARE; /* request the firmware, this will block and timeout */ - ret = request_firmware(&fw, fw_file, &client->dev); + ret = request_firmware(&firmware, name, &client->dev); if (ret) { - dev_err(&client->dev, "firmware file '%s' not found\n", fw_file); + dev_err(&client->dev, "firmware file '%s' not found\n", name); goto err; } - dev_info(&client->dev, "downloading firmware from file '%s'\n", - fw_file); + dev_info(&client->dev, "downloading firmware from file '%s'\n", name); ret = regmap_write(dev->regmap, 0xb2, 0x01); if (ret) - goto error_fw_release; - - for (remaining = fw->size; remaining > 0; - remaining -= (dev->cfg->i2c_wr_max - 1)) { - len = remaining; - if (len > (dev->cfg->i2c_wr_max - 1)) - len = (dev->cfg->i2c_wr_max - 1); + goto err_release_firmware; + for (rem = firmware->size; rem > 0; rem -= (dev->cfg->i2c_wr_max - 1)) { + len = min(dev->cfg->i2c_wr_max - 1, rem); ret = regmap_bulk_write(dev->regmap, 0xb0, - &fw->data[fw->size - remaining], len); + &firmware->data[firmware->size - rem], + len); if (ret) { - dev_err(&client->dev, "firmware download failed=%d\n", + dev_err(&client->dev, "firmware download failed %d\n", ret); - goto error_fw_release; + goto err_release_firmware; } } ret = regmap_write(dev->regmap, 0xb2, 0x00); if (ret) - goto error_fw_release; + goto err_release_firmware; - release_firmware(fw); - fw = NULL; + release_firmware(firmware); ret = regmap_read(dev->regmap, 0xb9, &utmp); if (ret) goto err; if (!utmp) { + ret = -EINVAL; dev_info(&client->dev, "firmware did not run\n"); - ret = -EFAULT; goto err; } @@ -733,7 +714,7 @@ static int m88ds3103_init(struct dvb_frontend *fe) dev_info(&client->dev, "firmware version: %X.%X\n", (utmp >> 4) & 0xf, (utmp >> 0 & 0xf)); -skip_fw_download: +warm: /* warm state */ dev->warm = true; @@ -746,8 +727,8 @@ skip_fw_download: c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; return 0; -error_fw_release: - release_firmware(fw); +err_release_firmware: + release_firmware(firmware); err: dev_dbg(&client->dev, "failed=%d\n", ret); return ret; @@ -952,8 +933,7 @@ static int m88ds3103_get_frontend(struct dvb_frontend *fe, if (ret) goto err; - c->symbol_rate = 1ull * ((buf[1] << 8) | (buf[0] << 0)) * - dev->mclk_khz * 1000 / 0x10000; + c->symbol_rate = DIV_ROUND_CLOSEST_ULL((u64)(buf[1] << 8 | buf[0] << 0) * dev->mclk, 0x10000); return 0; err: @@ -1119,8 +1099,9 @@ static int m88ds3103_diseqc_send_master_cmd(struct dvb_frontend *fe, #define SEND_MASTER_CMD_TIMEOUT 120 timeout = jiffies + msecs_to_jiffies(SEND_MASTER_CMD_TIMEOUT); - /* DiSEqC message typical period is 54 ms */ - usleep_range(50000, 54000); + /* DiSEqC message period is 13.5 ms per byte */ + utmp = diseqc_cmd->msg_len * 13500; + usleep_range(utmp - 4000, utmp); for (utmp = 1; !time_after(jiffies, timeout) && utmp;) { ret = regmap_read(dev->regmap, 0xa1, &utmp); @@ -1395,7 +1376,7 @@ static int m88ds3103_probe(struct i2c_client *client, dev->config.clock = pdata->clk; dev->config.i2c_wr_max = pdata->i2c_wr_max; dev->config.ts_mode = pdata->ts_mode; - dev->config.ts_clk = pdata->ts_clk; + dev->config.ts_clk = pdata->ts_clk * 1000; dev->config.ts_clk_pol = pdata->ts_clk_pol; dev->config.spec_inv = pdata->spec_inv; dev->config.agc_inv = pdata->agc_inv; @@ -1446,6 +1427,11 @@ static int m88ds3103_probe(struct i2c_client *client, goto err_kfree; } + if (!pdata->ts_clk) { + ret = -EINVAL; + goto err_kfree; + } + /* 0x29 register is defined differently for m88rs6000. */ /* set internal tuner address to 0x21 */ if (dev->chip_id == M88RS6000_CHIP_ID) diff --git a/drivers/media/dvb-frontends/m88ds3103_priv.h b/drivers/media/dvb-frontends/m88ds3103_priv.h index d78e467295d2..07f20c269c67 100644 --- a/drivers/media/dvb-frontends/m88ds3103_priv.h +++ b/drivers/media/dvb-frontends/m88ds3103_priv.h @@ -27,7 +27,6 @@ #define M88DS3103_FIRMWARE "dvb-demod-m88ds3103.fw" #define M88RS6000_FIRMWARE "dvb-demod-m88rs6000.fw" -#define M88DS3103_MCLK_KHZ 96000 #define M88RS6000_CHIP_ID 0x74 #define M88DS3103_CHIP_ID 0x70 @@ -46,7 +45,7 @@ struct m88ds3103_dev { /* auto detect chip id to do different config */ u8 chip_id; /* main mclk is calculated for M88RS6000 dynamically */ - s32 mclk_khz; + s32 mclk; u64 post_bit_error; u64 post_bit_count; }; diff --git a/drivers/media/dvb-frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c index fb88dddaf3a3..41325328a22e 100644 --- a/drivers/media/dvb-frontends/mb86a20s.c +++ b/drivers/media/dvb-frontends/mb86a20s.c @@ -301,10 +301,11 @@ static int mb86a20s_read_status(struct dvb_frontend *fe, enum fe_status *status) *status = 0; - val = mb86a20s_readreg(state, 0x0a) & 0xf; + val = mb86a20s_readreg(state, 0x0a); if (val < 0) return val; + val &= 0xf; if (val >= 2) *status |= FE_HAS_SIGNAL; diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index d25d1e0cd4ca..87226056f226 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -135,8 +135,6 @@ static int rtl2830_init(struct dvb_frontend *fe) c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; c->post_bit_count.len = 1; c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; - /* start statistics polling */ - schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000)); dev->sleeping = false; @@ -152,8 +150,6 @@ static int rtl2830_sleep(struct dvb_frontend *fe) struct rtl2830_dev *dev = i2c_get_clientdata(client); dev->sleeping = true; - /* stop statistics polling */ - cancel_delayed_work_sync(&dev->stat_work); dev->fe_status = 0; return 0; @@ -396,8 +392,10 @@ static int rtl2830_read_status(struct dvb_frontend *fe, enum fe_status *status) { struct i2c_client *client = fe->demodulator_priv; struct rtl2830_dev *dev = i2c_get_clientdata(client); - int ret; - u8 u8tmp; + struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; + int ret, stmp; + unsigned int utmp; + u8 u8tmp, buf[2]; *status = 0; @@ -419,6 +417,89 @@ static int rtl2830_read_status(struct dvb_frontend *fe, enum fe_status *status) dev->fe_status = *status; + /* Signal strength */ + if (dev->fe_status & FE_HAS_SIGNAL) { + /* Read IF AGC */ + ret = rtl2830_bulk_read(client, 0x359, buf, 2); + if (ret) + goto err; + + stmp = buf[0] << 8 | buf[1] << 0; + stmp = sign_extend32(stmp, 13); + utmp = clamp_val(-4 * stmp + 32767, 0x0000, 0xffff); + + dev_dbg(&client->dev, "IF AGC=%d\n", stmp); + + c->strength.stat[0].scale = FE_SCALE_RELATIVE; + c->strength.stat[0].uvalue = utmp; + } else { + c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + } + + /* CNR */ + if (dev->fe_status & FE_HAS_VITERBI) { + unsigned int hierarchy, constellation; + #define CONSTELLATION_NUM 3 + #define HIERARCHY_NUM 4 + static const u32 constant[CONSTELLATION_NUM][HIERARCHY_NUM] = { + {70705899, 70705899, 70705899, 70705899}, + {82433173, 82433173, 87483115, 94445660}, + {92888734, 92888734, 95487525, 99770748}, + }; + + ret = rtl2830_bulk_read(client, 0x33c, &u8tmp, 1); + if (ret) + goto err; + + constellation = (u8tmp >> 2) & 0x03; /* [3:2] */ + if (constellation > CONSTELLATION_NUM - 1) + goto err; + + hierarchy = (u8tmp >> 4) & 0x07; /* [6:4] */ + if (hierarchy > HIERARCHY_NUM - 1) + goto err; + + ret = rtl2830_bulk_read(client, 0x40c, buf, 2); + if (ret) + goto err; + + utmp = buf[0] << 8 | buf[1] << 0; + if (utmp) + stmp = (constant[constellation][hierarchy] - + intlog10(utmp)) / ((1 << 24) / 10000); + else + stmp = 0; + + dev_dbg(&client->dev, "CNR raw=%u\n", utmp); + + c->cnr.stat[0].scale = FE_SCALE_DECIBEL; + c->cnr.stat[0].svalue = stmp; + } else { + c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + } + + /* BER */ + if (dev->fe_status & FE_HAS_LOCK) { + ret = rtl2830_bulk_read(client, 0x34e, buf, 2); + if (ret) + goto err; + + utmp = buf[0] << 8 | buf[1] << 0; + dev->post_bit_error += utmp; + dev->post_bit_count += 1000000; + + dev_dbg(&client->dev, "BER errors=%u total=1000000\n", utmp); + + c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; + c->post_bit_error.stat[0].uvalue = dev->post_bit_error; + c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; + c->post_bit_count.stat[0].uvalue = dev->post_bit_count; + } else { + c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + } + + return ret; err: dev_dbg(&client->dev, "failed=%d\n", ret); @@ -503,109 +584,6 @@ static struct dvb_frontend_ops rtl2830_ops = { .read_signal_strength = rtl2830_read_signal_strength, }; -static void rtl2830_stat_work(struct work_struct *work) -{ - struct rtl2830_dev *dev = container_of(work, struct rtl2830_dev, stat_work.work); - struct i2c_client *client = dev->client; - struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; - int ret, tmp; - u8 u8tmp, buf[2]; - u16 u16tmp; - - dev_dbg(&client->dev, "\n"); - - /* signal strength */ - if (dev->fe_status & FE_HAS_SIGNAL) { - struct {signed int x:14; } s; - - /* read IF AGC */ - ret = rtl2830_bulk_read(client, 0x359, buf, 2); - if (ret) - goto err; - - u16tmp = buf[0] << 8 | buf[1] << 0; - u16tmp &= 0x3fff; /* [13:0] */ - tmp = s.x = u16tmp; /* 14-bit bin to 2 complement */ - u16tmp = clamp_val(-4 * tmp + 32767, 0x0000, 0xffff); - - dev_dbg(&client->dev, "IF AGC=%d\n", tmp); - - c->strength.stat[0].scale = FE_SCALE_RELATIVE; - c->strength.stat[0].uvalue = u16tmp; - } else { - c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; - } - - /* CNR */ - if (dev->fe_status & FE_HAS_VITERBI) { - unsigned hierarchy, constellation; - #define CONSTELLATION_NUM 3 - #define HIERARCHY_NUM 4 - static const u32 constant[CONSTELLATION_NUM][HIERARCHY_NUM] = { - {70705899, 70705899, 70705899, 70705899}, - {82433173, 82433173, 87483115, 94445660}, - {92888734, 92888734, 95487525, 99770748}, - }; - - ret = rtl2830_bulk_read(client, 0x33c, &u8tmp, 1); - if (ret) - goto err; - - constellation = (u8tmp >> 2) & 0x03; /* [3:2] */ - if (constellation > CONSTELLATION_NUM - 1) - goto err_schedule_delayed_work; - - hierarchy = (u8tmp >> 4) & 0x07; /* [6:4] */ - if (hierarchy > HIERARCHY_NUM - 1) - goto err_schedule_delayed_work; - - ret = rtl2830_bulk_read(client, 0x40c, buf, 2); - if (ret) - goto err; - - u16tmp = buf[0] << 8 | buf[1] << 0; - if (u16tmp) - tmp = (constant[constellation][hierarchy] - - intlog10(u16tmp)) / ((1 << 24) / 10000); - else - tmp = 0; - - dev_dbg(&client->dev, "CNR raw=%u\n", u16tmp); - - c->cnr.stat[0].scale = FE_SCALE_DECIBEL; - c->cnr.stat[0].svalue = tmp; - } else { - c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; - } - - /* BER */ - if (dev->fe_status & FE_HAS_LOCK) { - ret = rtl2830_bulk_read(client, 0x34e, buf, 2); - if (ret) - goto err; - - u16tmp = buf[0] << 8 | buf[1] << 0; - dev->post_bit_error += u16tmp; - dev->post_bit_count += 1000000; - - dev_dbg(&client->dev, "BER errors=%u total=1000000\n", u16tmp); - - c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; - c->post_bit_error.stat[0].uvalue = dev->post_bit_error; - c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; - c->post_bit_count.stat[0].uvalue = dev->post_bit_count; - } else { - c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; - c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; - } - -err_schedule_delayed_work: - schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000)); - return; -err: - dev_dbg(&client->dev, "failed=%d\n", ret); -} - static int rtl2830_pid_filter_ctrl(struct dvb_frontend *fe, int onoff) { struct i2c_client *client = fe->demodulator_priv; @@ -851,7 +829,6 @@ static int rtl2830_probe(struct i2c_client *client, dev->client = client; dev->pdata = client->dev.platform_data; dev->sleeping = true; - INIT_DELAYED_WORK(&dev->stat_work, rtl2830_stat_work); dev->regmap = regmap_init(&client->dev, ®map_bus, client, ®map_config); if (IS_ERR(dev->regmap)) { @@ -904,9 +881,6 @@ static int rtl2830_remove(struct i2c_client *client) dev_dbg(&client->dev, "\n"); - /* stop statistics polling */ - cancel_delayed_work_sync(&dev->stat_work); - i2c_mux_del_adapters(dev->muxc); regmap_exit(dev->regmap); kfree(dev); @@ -922,7 +896,8 @@ MODULE_DEVICE_TABLE(i2c, rtl2830_id_table); static struct i2c_driver rtl2830_driver = { .driver = { - .name = "rtl2830", + .name = "rtl2830", + .suppress_bind_attrs = true, }, .probe = rtl2830_probe, .remove = rtl2830_remove, diff --git a/drivers/media/dvb-frontends/rtl2830_priv.h b/drivers/media/dvb-frontends/rtl2830_priv.h index da4909543da2..8ec4721d79ac 100644 --- a/drivers/media/dvb-frontends/rtl2830_priv.h +++ b/drivers/media/dvb-frontends/rtl2830_priv.h @@ -24,6 +24,7 @@ #include <linux/i2c-mux.h> #include <linux/math64.h> #include <linux/regmap.h> +#include <linux/bitops.h> struct rtl2830_dev { struct rtl2830_platform_data *pdata; @@ -33,7 +34,6 @@ struct rtl2830_dev { struct dvb_frontend fe; bool sleeping; unsigned long filters; - struct delayed_work stat_work; enum fe_status fe_status; u64 post_bit_error_prev; /* for old DVBv3 read_ber() calculation */ u64 post_bit_error; diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index c16c69e9d26c..0ced01f1012e 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -1148,6 +1148,7 @@ MODULE_DEVICE_TABLE(i2c, rtl2832_id_table); static struct i2c_driver rtl2832_driver = { .driver = { .name = "rtl2832", + .suppress_bind_attrs = true, }, .probe = rtl2832_probe, .remove = rtl2832_remove, diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c index 47a480a7d46c..6e22af36b637 100644 --- a/drivers/media/dvb-frontends/rtl2832_sdr.c +++ b/drivers/media/dvb-frontends/rtl2832_sdr.c @@ -452,7 +452,7 @@ static int rtl2832_sdr_querycap(struct file *file, void *fh, /* Videobuf2 operations */ static int rtl2832_sdr_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, - unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) + unsigned int *nplanes, unsigned int sizes[], struct device *alloc_devs[]) { struct rtl2832_sdr_dev *dev = vb2_get_drv_priv(vq); struct platform_device *pdev = dev->pdev; diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index 108a069fa1ae..20b4a659e2e4 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -357,9 +357,7 @@ static int si2168_init(struct dvb_frontend *fe) struct si2168_dev *dev = i2c_get_clientdata(client); int ret, len, remaining; const struct firmware *fw; - const char *fw_name; struct si2168_cmd cmd; - unsigned int chip_id; dev_dbg(&client->dev, "\n"); @@ -371,7 +369,7 @@ static int si2168_init(struct dvb_frontend *fe) if (ret) goto err; - if (dev->fw_loaded) { + if (dev->warm) { /* resume */ memcpy(cmd.args, "\xc0\x06\x08\x0f\x00\x20\x21\x01", 8); cmd.wlen = 8; @@ -398,49 +396,14 @@ static int si2168_init(struct dvb_frontend *fe) if (ret) goto err; - /* query chip revision */ - memcpy(cmd.args, "\x02", 1); - cmd.wlen = 1; - cmd.rlen = 13; - ret = si2168_cmd_execute(client, &cmd); - if (ret) - goto err; - - chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | cmd.args[3] << 8 | - cmd.args[4] << 0; - - #define SI2168_A20 ('A' << 24 | 68 << 16 | '2' << 8 | '0' << 0) - #define SI2168_A30 ('A' << 24 | 68 << 16 | '3' << 8 | '0' << 0) - #define SI2168_B40 ('B' << 24 | 68 << 16 | '4' << 8 | '0' << 0) - - switch (chip_id) { - case SI2168_A20: - fw_name = SI2168_A20_FIRMWARE; - break; - case SI2168_A30: - fw_name = SI2168_A30_FIRMWARE; - break; - case SI2168_B40: - fw_name = SI2168_B40_FIRMWARE; - break; - default: - dev_err(&client->dev, "unknown chip version Si21%d-%c%c%c\n", - cmd.args[2], cmd.args[1], - cmd.args[3], cmd.args[4]); - ret = -EINVAL; - goto err; - } - - dev_info(&client->dev, "found a 'Silicon Labs Si21%d-%c%c%c'\n", - cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]); - /* request the firmware, this will block and timeout */ - ret = request_firmware(&fw, fw_name, &client->dev); + ret = request_firmware(&fw, dev->firmware_name, &client->dev); if (ret) { /* fallback mechanism to handle old name for Si2168 B40 fw */ - if (chip_id == SI2168_B40) { - fw_name = SI2168_B40_FIRMWARE_FALLBACK; - ret = request_firmware(&fw, fw_name, &client->dev); + if (dev->chip_id == SI2168_CHIP_ID_B40) { + dev->firmware_name = SI2168_B40_FIRMWARE_FALLBACK; + ret = request_firmware(&fw, dev->firmware_name, + &client->dev); } if (ret == 0) { @@ -450,13 +413,13 @@ static int si2168_init(struct dvb_frontend *fe) } else { dev_err(&client->dev, "firmware file '%s' not found\n", - fw_name); + dev->firmware_name); goto err_release_firmware; } } dev_info(&client->dev, "downloading firmware from file '%s'\n", - fw_name); + dev->firmware_name); if ((fw->size % 17 == 0) && (fw->data[0] > 5)) { /* firmware is in the new format */ @@ -511,8 +474,11 @@ static int si2168_init(struct dvb_frontend *fe) if (ret) goto err; - dev_info(&client->dev, "firmware version: %c.%c.%d\n", - cmd.args[6], cmd.args[7], cmd.args[8]); + dev->version = (cmd.args[9] + '@') << 24 | (cmd.args[6] - '0') << 16 | + (cmd.args[7] - '0') << 8 | (cmd.args[8]) << 0; + dev_info(&client->dev, "firmware version: %c %d.%d.%d\n", + dev->version >> 24 & 0xff, dev->version >> 16 & 0xff, + dev->version >> 8 & 0xff, dev->version >> 0 & 0xff); /* set ts mode */ memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6); @@ -525,7 +491,7 @@ static int si2168_init(struct dvb_frontend *fe) if (ret) goto err; - dev->fw_loaded = true; + dev->warm = true; warm: dev->active = true; @@ -549,6 +515,10 @@ static int si2168_sleep(struct dvb_frontend *fe) dev->active = false; + /* Firmware B 4.0-11 or later loses warm state during sleep */ + if (dev->version > ('B' << 24 | 4 << 16 | 0 << 8 | 11 << 0)) + dev->warm = false; + memcpy(cmd.args, "\x13", 1); cmd.wlen = 1; cmd.rlen = 0; @@ -653,6 +623,7 @@ static int si2168_probe(struct i2c_client *client, struct si2168_config *config = client->dev.platform_data; struct si2168_dev *dev; int ret; + struct si2168_cmd cmd; dev_dbg(&client->dev, "\n"); @@ -663,8 +634,56 @@ static int si2168_probe(struct i2c_client *client, goto err; } + i2c_set_clientdata(client, dev); mutex_init(&dev->i2c_mutex); + /* Initialize */ + memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13); + cmd.wlen = 13; + cmd.rlen = 0; + ret = si2168_cmd_execute(client, &cmd); + if (ret) + goto err_kfree; + + /* Power up */ + memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8); + cmd.wlen = 8; + cmd.rlen = 1; + ret = si2168_cmd_execute(client, &cmd); + if (ret) + goto err_kfree; + + /* Query chip revision */ + memcpy(cmd.args, "\x02", 1); + cmd.wlen = 1; + cmd.rlen = 13; + ret = si2168_cmd_execute(client, &cmd); + if (ret) + goto err_kfree; + + dev->chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | + cmd.args[3] << 8 | cmd.args[4] << 0; + + switch (dev->chip_id) { + case SI2168_CHIP_ID_A20: + dev->firmware_name = SI2168_A20_FIRMWARE; + break; + case SI2168_CHIP_ID_A30: + dev->firmware_name = SI2168_A30_FIRMWARE; + break; + case SI2168_CHIP_ID_B40: + dev->firmware_name = SI2168_B40_FIRMWARE; + break; + default: + dev_dbg(&client->dev, "unknown chip version Si21%d-%c%c%c\n", + cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]); + ret = -ENODEV; + goto err_kfree; + } + + dev->version = (cmd.args[1]) << 24 | (cmd.args[3] - '0') << 16 | + (cmd.args[4] - '0') << 8 | (cmd.args[5]) << 0; + /* create mux i2c adapter for tuner */ dev->muxc = i2c_mux_alloc(client->adapter, &client->dev, 1, 0, I2C_MUX_LOCKED, @@ -686,11 +705,14 @@ static int si2168_probe(struct i2c_client *client, dev->ts_mode = config->ts_mode; dev->ts_clock_inv = config->ts_clock_inv; dev->ts_clock_gapped = config->ts_clock_gapped; - dev->fw_loaded = false; - i2c_set_clientdata(client, dev); + dev_info(&client->dev, "Silicon Labs Si2168-%c%d%d successfully identified\n", + dev->version >> 24 & 0xff, dev->version >> 16 & 0xff, + dev->version >> 8 & 0xff); + dev_info(&client->dev, "firmware version: %c %d.%d.%d\n", + dev->version >> 24 & 0xff, dev->version >> 16 & 0xff, + dev->version >> 8 & 0xff, dev->version >> 0 & 0xff); - dev_info(&client->dev, "Silicon Labs Si2168 successfully attached\n"); return 0; err_kfree: kfree(dev); @@ -723,7 +745,8 @@ MODULE_DEVICE_TABLE(i2c, si2168_id_table); static struct i2c_driver si2168_driver = { .driver = { - .name = "si2168", + .name = "si2168", + .suppress_bind_attrs = true, }, .probe = si2168_probe, .remove = si2168_remove, diff --git a/drivers/media/dvb-frontends/si2168_priv.h b/drivers/media/dvb-frontends/si2168_priv.h index 8a1f36d2014d..7843ccb448a0 100644 --- a/drivers/media/dvb-frontends/si2168_priv.h +++ b/drivers/media/dvb-frontends/si2168_priv.h @@ -34,8 +34,14 @@ struct si2168_dev { struct dvb_frontend fe; enum fe_delivery_system delivery_system; enum fe_status fe_status; + #define SI2168_CHIP_ID_A20 ('A' << 24 | 68 << 16 | '2' << 8 | '0' << 0) + #define SI2168_CHIP_ID_A30 ('A' << 24 | 68 << 16 | '3' << 8 | '0' << 0) + #define SI2168_CHIP_ID_B40 ('B' << 24 | 68 << 16 | '4' << 8 | '0' << 0) + unsigned int chip_id; + unsigned int version; + const char *firmware_name; bool active; - bool fw_loaded; + bool warm; u8 ts_mode; bool ts_clock_inv; bool ts_clock_gapped; |