diff options
Diffstat (limited to 'drivers/media/dvb-frontends/cxd2820r_t2.c')
-rw-r--r-- | drivers/media/dvb-frontends/cxd2820r_t2.c | 278 |
1 files changed, 135 insertions, 143 deletions
diff --git a/drivers/media/dvb-frontends/cxd2820r_t2.c b/drivers/media/dvb-frontends/cxd2820r_t2.c index 704475676234..e641fde75379 100644 --- a/drivers/media/dvb-frontends/cxd2820r_t2.c +++ b/drivers/media/dvb-frontends/cxd2820r_t2.c @@ -23,11 +23,12 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct cxd2820r_priv *priv = fe->demodulator_priv; - int ret, i, bw_i; - u32 if_freq, if_ctl; - u64 num; + struct i2c_client *client = priv->client[0]; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + int ret, bw_i; + unsigned int utmp; + u32 if_frequency; u8 buf[3], bw_param; u8 bw_params1[][5] = { { 0x1c, 0xb3, 0x33, 0x33, 0x33 }, /* 5 MHz */ @@ -45,10 +46,10 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe) { 0x0207f, 0x2a, 0xff }, { 0x02082, 0x0a, 0xff }, { 0x02083, 0x0a, 0xff }, - { 0x020cb, priv->cfg.if_agc_polarity << 6, 0x40 }, - { 0x02070, priv->cfg.ts_mode, 0xff }, - { 0x02071, !priv->cfg.ts_clock_inv << 6, 0x40 }, - { 0x020b5, priv->cfg.spec_inv << 4, 0x10 }, + { 0x020cb, priv->if_agc_polarity << 6, 0x40 }, + { 0x02070, priv->ts_mode, 0xff }, + { 0x02071, !priv->ts_clk_inv << 6, 0x40 }, + { 0x020b5, priv->spec_inv << 4, 0x10 }, { 0x02567, 0x07, 0x0f }, { 0x02569, 0x03, 0x03 }, { 0x02595, 0x1a, 0xff }, @@ -69,8 +70,10 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe) { 0x027ef, 0x10, 0x18 }, }; - dev_dbg(&priv->i2c->dev, "%s: frequency=%d bandwidth_hz=%d\n", __func__, - c->frequency, c->bandwidth_hz); + dev_dbg(&client->dev, + "delivery_system=%d modulation=%d frequency=%u bandwidth_hz=%u inversion=%d stream_id=%u\n", + c->delivery_system, c->modulation, c->frequency, + c->bandwidth_hz, c->inversion, c->stream_id); switch (c->bandwidth_hz) { case 5000000: @@ -98,73 +101,67 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe) fe->ops.tuner_ops.set_params(fe); if (priv->delivery_system != SYS_DVBT2) { - for (i = 0; i < ARRAY_SIZE(tab); i++) { - ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, - tab[i].val, tab[i].mask); - if (ret) - goto error; - } + ret = cxd2820r_wr_reg_val_mask_tab(priv, tab, ARRAY_SIZE(tab)); + if (ret) + goto error; } priv->delivery_system = SYS_DVBT2; /* program IF frequency */ if (fe->ops.tuner_ops.get_if_frequency) { - ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq); + ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency); if (ret) goto error; - } else - if_freq = 0; - - dev_dbg(&priv->i2c->dev, "%s: if_freq=%d\n", __func__, if_freq); + dev_dbg(&client->dev, "if_frequency=%u\n", if_frequency); + } else { + ret = -EINVAL; + goto error; + } - num = if_freq / 1000; /* Hz => kHz */ - num *= 0x1000000; - if_ctl = DIV_ROUND_CLOSEST_ULL(num, 41000); - buf[0] = ((if_ctl >> 16) & 0xff); - buf[1] = ((if_ctl >> 8) & 0xff); - buf[2] = ((if_ctl >> 0) & 0xff); + utmp = DIV_ROUND_CLOSEST_ULL((u64)if_frequency * 0x1000000, CXD2820R_CLK); + buf[0] = (utmp >> 16) & 0xff; + buf[1] = (utmp >> 8) & 0xff; + buf[2] = (utmp >> 0) & 0xff; + ret = regmap_bulk_write(priv->regmap[0], 0x20b6, buf, 3); + if (ret) + goto error; /* PLP filtering */ if (c->stream_id > 255) { - dev_dbg(&priv->i2c->dev, "%s: Disable PLP filtering\n", __func__); - ret = cxd2820r_wr_reg(priv, 0x023ad , 0); + dev_dbg(&client->dev, "disable PLP filtering\n"); + ret = regmap_write(priv->regmap[0], 0x23ad, 0x00); if (ret) goto error; } else { - dev_dbg(&priv->i2c->dev, "%s: Enable PLP filtering = %d\n", __func__, - c->stream_id); - ret = cxd2820r_wr_reg(priv, 0x023af , c->stream_id & 0xFF); + dev_dbg(&client->dev, "enable PLP filtering\n"); + ret = regmap_write(priv->regmap[0], 0x23af, c->stream_id & 0xff); if (ret) goto error; - ret = cxd2820r_wr_reg(priv, 0x023ad , 1); + ret = regmap_write(priv->regmap[0], 0x23ad, 0x01); if (ret) goto error; } - ret = cxd2820r_wr_regs(priv, 0x020b6, buf, 3); + ret = regmap_bulk_write(priv->regmap[0], 0x209f, bw_params1[bw_i], 5); if (ret) goto error; - ret = cxd2820r_wr_regs(priv, 0x0209f, bw_params1[bw_i], 5); + ret = regmap_update_bits(priv->regmap[0], 0x20d7, 0xc0, bw_param << 6); if (ret) goto error; - ret = cxd2820r_wr_reg_mask(priv, 0x020d7, bw_param << 6, 0xc0); + ret = regmap_write(priv->regmap[0], 0x00ff, 0x08); if (ret) goto error; - ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08); - if (ret) - goto error; - - ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01); + ret = regmap_write(priv->regmap[0], 0x00fe, 0x01); if (ret) goto error; return ret; error: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } @@ -173,10 +170,14 @@ int cxd2820r_get_frontend_t2(struct dvb_frontend *fe, struct dtv_frontend_properties *c) { struct cxd2820r_priv *priv = fe->demodulator_priv; + struct i2c_client *client = priv->client[0]; int ret; + unsigned int utmp; u8 buf[2]; - ret = cxd2820r_rd_regs(priv, 0x0205c, buf, 2); + dev_dbg(&client->dev, "\n"); + + ret = regmap_bulk_read(priv->regmap[0], 0x205c, buf, 2); if (ret) goto error; @@ -225,7 +226,7 @@ int cxd2820r_get_frontend_t2(struct dvb_frontend *fe, break; } - ret = cxd2820r_rd_regs(priv, 0x0225b, buf, 2); + ret = regmap_bulk_read(priv->regmap[0], 0x225b, buf, 2); if (ret) goto error; @@ -265,11 +266,11 @@ int cxd2820r_get_frontend_t2(struct dvb_frontend *fe, break; } - ret = cxd2820r_rd_reg(priv, 0x020b5, &buf[0]); + ret = regmap_read(priv->regmap[0], 0x20b5, &utmp); if (ret) goto error; - switch ((buf[0] >> 4) & 0x01) { + switch ((utmp >> 4) & 0x01) { case 0: c->inversion = INVERSION_OFF; break; @@ -280,130 +281,124 @@ int cxd2820r_get_frontend_t2(struct dvb_frontend *fe, return ret; error: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } int cxd2820r_read_status_t2(struct dvb_frontend *fe, enum fe_status *status) { struct cxd2820r_priv *priv = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + struct i2c_client *client = priv->client[0]; int ret; - u8 buf[1]; - *status = 0; + unsigned int utmp, utmp1, utmp2; + u8 buf[4]; - ret = cxd2820r_rd_reg(priv, 0x02010 , &buf[0]); + /* Lock detection */ + ret = regmap_bulk_read(priv->regmap[0], 0x2010, &buf[0], 1); if (ret) goto error; - if ((buf[0] & 0x07) == 6) { - if (((buf[0] >> 5) & 0x01) == 1) { - *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | - FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; - } else { - *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | - FE_HAS_VITERBI | FE_HAS_SYNC; - } - } + utmp1 = (buf[0] >> 0) & 0x07; + utmp2 = (buf[0] >> 5) & 0x01; - dev_dbg(&priv->i2c->dev, "%s: lock=%02x\n", __func__, buf[0]); + if (utmp1 == 6 && utmp2 == 1) { + *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | + FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; + } else if (utmp1 == 6 || utmp2 == 1) { + *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | + FE_HAS_VITERBI | FE_HAS_SYNC; + } else { + *status = 0; + } - return ret; -error: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); - return ret; -} + dev_dbg(&client->dev, "status=%02x raw=%*ph sync=%u ts=%u\n", + *status, 1, buf, utmp1, utmp2); -int cxd2820r_read_ber_t2(struct dvb_frontend *fe, u32 *ber) -{ - struct cxd2820r_priv *priv = fe->demodulator_priv; - int ret; - u8 buf[4]; - unsigned int errbits; - *ber = 0; - /* FIXME: correct calculation */ + /* Signal strength */ + if (*status & FE_HAS_SIGNAL) { + unsigned int strength; - ret = cxd2820r_rd_regs(priv, 0x02039, buf, sizeof(buf)); - if (ret) - goto error; + ret = regmap_bulk_read(priv->regmap[0], 0x2026, buf, 2); + if (ret) + goto error; - if ((buf[0] >> 4) & 0x01) { - errbits = (buf[0] & 0x0f) << 24 | buf[1] << 16 | - buf[2] << 8 | buf[3]; + utmp = buf[0] << 8 | buf[1] << 0; + utmp = ~utmp & 0x0fff; + /* Scale value to 0x0000-0xffff */ + strength = utmp << 4 | utmp >> 8; - if (errbits) - *ber = errbits * 64 / 16588800; + c->strength.len = 1; + c->strength.stat[0].scale = FE_SCALE_RELATIVE; + c->strength.stat[0].uvalue = strength; + } else { + c->strength.len = 1; + c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; } - return ret; -error: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); - return ret; -} + /* CNR */ + if (*status & FE_HAS_VITERBI) { + unsigned int cnr; -int cxd2820r_read_signal_strength_t2(struct dvb_frontend *fe, - u16 *strength) -{ - struct cxd2820r_priv *priv = fe->demodulator_priv; - int ret; - u8 buf[2]; - u16 tmp; - - ret = cxd2820r_rd_regs(priv, 0x02026, buf, sizeof(buf)); - if (ret) - goto error; - - tmp = (buf[0] & 0x0f) << 8 | buf[1]; - tmp = ~tmp & 0x0fff; + ret = regmap_bulk_read(priv->regmap[0], 0x2028, buf, 2); + if (ret) + goto error; - /* scale value to 0x0000-0xffff from 0x0000-0x0fff */ - *strength = tmp * 0xffff / 0x0fff; + utmp = buf[0] << 8 | buf[1] << 0; + utmp = utmp & 0x0fff; + #define CXD2820R_LOG10_8_24 15151336 /* log10(8) << 24 */ + if (utmp) + cnr = div_u64((u64)(intlog10(utmp) + - CXD2820R_LOG10_8_24) * 10000, + (1 << 24)); + else + cnr = 0; + + c->cnr.len = 1; + c->cnr.stat[0].scale = FE_SCALE_DECIBEL; + c->cnr.stat[0].svalue = cnr; + } else { + c->cnr.len = 1; + c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + } - return ret; -error: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); - return ret; -} + /* BER */ + if (*status & FE_HAS_SYNC) { + unsigned int post_bit_error; -int cxd2820r_read_snr_t2(struct dvb_frontend *fe, u16 *snr) -{ - struct cxd2820r_priv *priv = fe->demodulator_priv; - int ret; - u8 buf[2]; - u16 tmp; - /* report SNR in dB * 10 */ + ret = regmap_bulk_read(priv->regmap[0], 0x2039, buf, 4); + if (ret) + goto error; - ret = cxd2820r_rd_regs(priv, 0x02028, buf, sizeof(buf)); - if (ret) - goto error; + if ((buf[0] >> 4) & 0x01) { + post_bit_error = buf[0] << 24 | buf[1] << 16 | + buf[2] << 8 | buf[3] << 0; + post_bit_error &= 0x0fffffff; + } else { + post_bit_error = 0; + } - tmp = (buf[0] & 0x0f) << 8 | buf[1]; - #define CXD2820R_LOG10_8_24 15151336 /* log10(8) << 24 */ - if (tmp) - *snr = (intlog10(tmp) - CXD2820R_LOG10_8_24) / ((1 << 24) - / 100); - else - *snr = 0; + priv->post_bit_error += post_bit_error; - dev_dbg(&priv->i2c->dev, "%s: dBx10=%d val=%04x\n", __func__, *snr, - tmp); + c->post_bit_error.len = 1; + c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; + c->post_bit_error.stat[0].uvalue = priv->post_bit_error; + } else { + c->post_bit_error.len = 1; + c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + } return ret; error: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } -int cxd2820r_read_ucblocks_t2(struct dvb_frontend *fe, u32 *ucblocks) -{ - *ucblocks = 0; - /* no way to read ? */ - return 0; -} - int cxd2820r_sleep_t2(struct dvb_frontend *fe) { struct cxd2820r_priv *priv = fe->demodulator_priv; - int ret, i; + struct i2c_client *client = priv->client[0]; + int ret; struct reg_val_mask tab[] = { { 0x000ff, 0x1f, 0xff }, { 0x00085, 0x00, 0xff }, @@ -413,20 +408,17 @@ int cxd2820r_sleep_t2(struct dvb_frontend *fe) { 0x00080, 0x00, 0xff }, }; - dev_dbg(&priv->i2c->dev, "%s\n", __func__); + dev_dbg(&client->dev, "\n"); - for (i = 0; i < ARRAY_SIZE(tab); i++) { - ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val, - tab[i].mask); - if (ret) - goto error; - } + ret = cxd2820r_wr_reg_val_mask_tab(priv, tab, ARRAY_SIZE(tab)); + if (ret) + goto error; priv->delivery_system = SYS_UNDEFINED; return ret; error: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } |