diff options
Diffstat (limited to 'kernel/drivers/media/dvb-frontends/tda10071.c')
-rw-r--r-- | kernel/drivers/media/dvb-frontends/tda10071.c | 904 |
1 files changed, 426 insertions, 478 deletions
diff --git a/kernel/drivers/media/dvb-frontends/tda10071.c b/kernel/drivers/media/dvb-frontends/tda10071.c index 4a19b8599..119d47596 100644 --- a/kernel/drivers/media/dvb-frontends/tda10071.c +++ b/kernel/drivers/media/dvb-frontends/tda10071.c @@ -20,102 +20,15 @@ #include "tda10071_priv.h" -/* Max transfer size done by I2C transfer functions */ -#define MAX_XFER_SIZE 64 - static struct dvb_frontend_ops tda10071_ops; -/* write multiple registers */ -static int tda10071_wr_regs(struct tda10071_priv *priv, u8 reg, u8 *val, - int len) -{ - int ret; - u8 buf[MAX_XFER_SIZE]; - struct i2c_msg msg[1] = { - { - .addr = priv->cfg.demod_i2c_addr, - .flags = 0, - .len = 1 + len, - .buf = buf, - } - }; - - if (1 + len > sizeof(buf)) { - dev_warn(&priv->i2c->dev, - "%s: i2c wr reg=%04x: len=%d is too big!\n", - KBUILD_MODNAME, reg, len); - return -EINVAL; - } - - buf[0] = reg; - memcpy(&buf[1], val, len); - - ret = i2c_transfer(priv->i2c, msg, 1); - if (ret == 1) { - ret = 0; - } else { - dev_warn(&priv->i2c->dev, - "%s: i2c wr failed=%d reg=%02x len=%d\n", - KBUILD_MODNAME, ret, reg, len); - ret = -EREMOTEIO; - } - return ret; -} - -/* read multiple registers */ -static int tda10071_rd_regs(struct tda10071_priv *priv, u8 reg, u8 *val, - int len) -{ - int ret; - u8 buf[MAX_XFER_SIZE]; - struct i2c_msg msg[2] = { - { - .addr = priv->cfg.demod_i2c_addr, - .flags = 0, - .len = 1, - .buf = ®, - }, { - .addr = priv->cfg.demod_i2c_addr, - .flags = I2C_M_RD, - .len = len, - .buf = buf, - } - }; - - if (len > sizeof(buf)) { - dev_warn(&priv->i2c->dev, - "%s: i2c wr reg=%04x: len=%d is too big!\n", - KBUILD_MODNAME, reg, len); - return -EINVAL; - } - - ret = i2c_transfer(priv->i2c, msg, 2); - if (ret == 2) { - memcpy(val, buf, len); - ret = 0; - } else { - dev_warn(&priv->i2c->dev, - "%s: i2c rd failed=%d reg=%02x len=%d\n", - KBUILD_MODNAME, ret, reg, len); - ret = -EREMOTEIO; - } - return ret; -} - -/* write single register */ -static int tda10071_wr_reg(struct tda10071_priv *priv, u8 reg, u8 val) -{ - return tda10071_wr_regs(priv, reg, &val, 1); -} - -/* read single register */ -static int tda10071_rd_reg(struct tda10071_priv *priv, u8 reg, u8 *val) -{ - return tda10071_rd_regs(priv, reg, val, 1); -} - +/* + * XXX: regmap_update_bits() does not fit our needs as it does not support + * partially volatile registers. Also it performs register read even mask is as + * wide as register value. + */ /* write single register with mask */ -static int tda10071_wr_reg_mask(struct tda10071_priv *priv, +static int tda10071_wr_reg_mask(struct tda10071_dev *dev, u8 reg, u8 val, u8 mask) { int ret; @@ -123,7 +36,7 @@ static int tda10071_wr_reg_mask(struct tda10071_priv *priv, /* no need for read if whole reg is written */ if (mask != 0xff) { - ret = tda10071_rd_regs(priv, reg, &tmp, 1); + ret = regmap_bulk_read(dev->regmap, reg, &tmp, 1); if (ret) return ret; @@ -132,64 +45,45 @@ static int tda10071_wr_reg_mask(struct tda10071_priv *priv, val |= tmp; } - return tda10071_wr_regs(priv, reg, &val, 1); -} - -/* read single register with mask */ -static int tda10071_rd_reg_mask(struct tda10071_priv *priv, - u8 reg, u8 *val, u8 mask) -{ - int ret, i; - u8 tmp; - - ret = tda10071_rd_regs(priv, reg, &tmp, 1); - if (ret) - return ret; - - tmp &= mask; - - /* find position of the first bit */ - for (i = 0; i < 8; i++) { - if ((mask >> i) & 0x01) - break; - } - *val = tmp >> i; - - return 0; + return regmap_bulk_write(dev->regmap, reg, &val, 1); } /* execute firmware command */ -static int tda10071_cmd_execute(struct tda10071_priv *priv, +static int tda10071_cmd_execute(struct tda10071_dev *dev, struct tda10071_cmd *cmd) { + struct i2c_client *client = dev->client; int ret, i; - u8 tmp; + unsigned int uitmp; - if (!priv->warm) { + if (!dev->warm) { ret = -EFAULT; goto error; } + mutex_lock(&dev->cmd_execute_mutex); + /* write cmd and args for firmware */ - ret = tda10071_wr_regs(priv, 0x00, cmd->args, cmd->len); + ret = regmap_bulk_write(dev->regmap, 0x00, cmd->args, cmd->len); if (ret) - goto error; + goto error_mutex_unlock; /* start cmd execution */ - ret = tda10071_wr_reg(priv, 0x1f, 1); + ret = regmap_write(dev->regmap, 0x1f, 1); if (ret) - goto error; + goto error_mutex_unlock; /* wait cmd execution terminate */ - for (i = 1000, tmp = 1; i && tmp; i--) { - ret = tda10071_rd_reg(priv, 0x1f, &tmp); + for (i = 1000, uitmp = 1; i && uitmp; i--) { + ret = regmap_read(dev->regmap, 0x1f, &uitmp); if (ret) - goto error; + goto error_mutex_unlock; usleep_range(200, 5000); } - dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i); + mutex_unlock(&dev->cmd_execute_mutex); + dev_dbg(&client->dev, "loop=%d\n", i); if (i == 0) { ret = -ETIMEDOUT; @@ -197,26 +91,28 @@ static int tda10071_cmd_execute(struct tda10071_priv *priv, } return ret; +error_mutex_unlock: + mutex_unlock(&dev->cmd_execute_mutex); error: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } static int tda10071_set_tone(struct dvb_frontend *fe, - fe_sec_tone_mode_t fe_sec_tone_mode) + enum fe_sec_tone_mode fe_sec_tone_mode) { - struct tda10071_priv *priv = fe->demodulator_priv; + struct tda10071_dev *dev = fe->demodulator_priv; + struct i2c_client *client = dev->client; struct tda10071_cmd cmd; int ret; u8 tone; - if (!priv->warm) { + if (!dev->warm) { ret = -EFAULT; goto error; } - dev_dbg(&priv->i2c->dev, "%s: tone_mode=%d\n", __func__, - fe_sec_tone_mode); + dev_dbg(&client->dev, "tone_mode=%d\n", fe_sec_tone_mode); switch (fe_sec_tone_mode) { case SEC_TONE_ON: @@ -226,8 +122,7 @@ static int tda10071_set_tone(struct dvb_frontend *fe, tone = 0; break; default: - dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_tone_mode\n", - __func__); + dev_dbg(&client->dev, "invalid fe_sec_tone_mode\n"); ret = -EINVAL; goto error; } @@ -238,30 +133,31 @@ static int tda10071_set_tone(struct dvb_frontend *fe, cmd.args[3] = 0x00; cmd.args[4] = tone; cmd.len = 5; - ret = tda10071_cmd_execute(priv, &cmd); + ret = tda10071_cmd_execute(dev, &cmd); 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; } static int tda10071_set_voltage(struct dvb_frontend *fe, - fe_sec_voltage_t fe_sec_voltage) + enum fe_sec_voltage fe_sec_voltage) { - struct tda10071_priv *priv = fe->demodulator_priv; + struct tda10071_dev *dev = fe->demodulator_priv; + struct i2c_client *client = dev->client; struct tda10071_cmd cmd; int ret; u8 voltage; - if (!priv->warm) { + if (!dev->warm) { ret = -EFAULT; goto error; } - dev_dbg(&priv->i2c->dev, "%s: voltage=%d\n", __func__, fe_sec_voltage); + dev_dbg(&client->dev, "voltage=%d\n", fe_sec_voltage); switch (fe_sec_voltage) { case SEC_VOLTAGE_13: @@ -274,8 +170,7 @@ static int tda10071_set_voltage(struct dvb_frontend *fe, voltage = 0; break; default: - dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_voltage\n", - __func__); + dev_dbg(&client->dev, "invalid fe_sec_voltage\n"); ret = -EINVAL; goto error; } @@ -284,31 +179,31 @@ static int tda10071_set_voltage(struct dvb_frontend *fe, cmd.args[1] = 0; cmd.args[2] = voltage; cmd.len = 3; - ret = tda10071_cmd_execute(priv, &cmd); + ret = tda10071_cmd_execute(dev, &cmd); 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; } static int tda10071_diseqc_send_master_cmd(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *diseqc_cmd) { - struct tda10071_priv *priv = fe->demodulator_priv; + struct tda10071_dev *dev = fe->demodulator_priv; + struct i2c_client *client = dev->client; struct tda10071_cmd cmd; int ret, i; - u8 tmp; + unsigned int uitmp; - if (!priv->warm) { + if (!dev->warm) { ret = -EFAULT; goto error; } - dev_dbg(&priv->i2c->dev, "%s: msg_len=%d\n", __func__, - diseqc_cmd->msg_len); + dev_dbg(&client->dev, "msg_len=%d\n", diseqc_cmd->msg_len); if (diseqc_cmd->msg_len < 3 || diseqc_cmd->msg_len > 6) { ret = -EINVAL; @@ -316,22 +211,22 @@ static int tda10071_diseqc_send_master_cmd(struct dvb_frontend *fe, } /* wait LNB TX */ - for (i = 500, tmp = 0; i && !tmp; i--) { - ret = tda10071_rd_reg_mask(priv, 0x47, &tmp, 0x01); + for (i = 500, uitmp = 0; i && !uitmp; i--) { + ret = regmap_read(dev->regmap, 0x47, &uitmp); if (ret) goto error; - + uitmp = (uitmp >> 0) & 1; usleep_range(10000, 20000); } - dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i); + dev_dbg(&client->dev, "loop=%d\n", i); if (i == 0) { ret = -ETIMEDOUT; goto error; } - ret = tda10071_wr_reg_mask(priv, 0x47, 0x00, 0x01); + ret = regmap_update_bits(dev->regmap, 0x47, 0x01, 0x00); if (ret) goto error; @@ -344,41 +239,42 @@ static int tda10071_diseqc_send_master_cmd(struct dvb_frontend *fe, cmd.args[6] = diseqc_cmd->msg_len; memcpy(&cmd.args[7], diseqc_cmd->msg, diseqc_cmd->msg_len); cmd.len = 7 + diseqc_cmd->msg_len; - ret = tda10071_cmd_execute(priv, &cmd); + ret = tda10071_cmd_execute(dev, &cmd); 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; } static int tda10071_diseqc_recv_slave_reply(struct dvb_frontend *fe, struct dvb_diseqc_slave_reply *reply) { - struct tda10071_priv *priv = fe->demodulator_priv; + struct tda10071_dev *dev = fe->demodulator_priv; + struct i2c_client *client = dev->client; struct tda10071_cmd cmd; int ret, i; - u8 tmp; + unsigned int uitmp; - if (!priv->warm) { + if (!dev->warm) { ret = -EFAULT; goto error; } - dev_dbg(&priv->i2c->dev, "%s:\n", __func__); + dev_dbg(&client->dev, "\n"); /* wait LNB RX */ - for (i = 500, tmp = 0; i && !tmp; i--) { - ret = tda10071_rd_reg_mask(priv, 0x47, &tmp, 0x02); + for (i = 500, uitmp = 0; i && !uitmp; i--) { + ret = regmap_read(dev->regmap, 0x47, &uitmp); if (ret) goto error; - + uitmp = (uitmp >> 1) & 1; usleep_range(10000, 20000); } - dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i); + dev_dbg(&client->dev, "loop=%d\n", i); if (i == 0) { ret = -ETIMEDOUT; @@ -386,11 +282,11 @@ static int tda10071_diseqc_recv_slave_reply(struct dvb_frontend *fe, } /* reply len */ - ret = tda10071_rd_reg(priv, 0x46, &tmp); + ret = regmap_read(dev->regmap, 0x46, &uitmp); if (ret) goto error; - reply->msg_len = tmp & 0x1f; /* [4:0] */ + reply->msg_len = uitmp & 0x1f; /* [4:0] */ if (reply->msg_len > sizeof(reply->msg)) reply->msg_len = sizeof(reply->msg); /* truncate API max */ @@ -398,35 +294,37 @@ static int tda10071_diseqc_recv_slave_reply(struct dvb_frontend *fe, cmd.args[0] = CMD_LNB_UPDATE_REPLY; cmd.args[1] = 0; cmd.len = 2; - ret = tda10071_cmd_execute(priv, &cmd); + ret = tda10071_cmd_execute(dev, &cmd); if (ret) goto error; - ret = tda10071_rd_regs(priv, cmd.len, reply->msg, reply->msg_len); + ret = regmap_bulk_read(dev->regmap, cmd.len, reply->msg, + reply->msg_len); 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; } static int tda10071_diseqc_send_burst(struct dvb_frontend *fe, - fe_sec_mini_cmd_t fe_sec_mini_cmd) + enum fe_sec_mini_cmd fe_sec_mini_cmd) { - struct tda10071_priv *priv = fe->demodulator_priv; + struct tda10071_dev *dev = fe->demodulator_priv; + struct i2c_client *client = dev->client; struct tda10071_cmd cmd; int ret, i; - u8 tmp, burst; + unsigned int uitmp; + u8 burst; - if (!priv->warm) { + if (!dev->warm) { ret = -EFAULT; goto error; } - dev_dbg(&priv->i2c->dev, "%s: fe_sec_mini_cmd=%d\n", __func__, - fe_sec_mini_cmd); + dev_dbg(&client->dev, "fe_sec_mini_cmd=%d\n", fe_sec_mini_cmd); switch (fe_sec_mini_cmd) { case SEC_MINI_A: @@ -436,29 +334,28 @@ static int tda10071_diseqc_send_burst(struct dvb_frontend *fe, burst = 1; break; default: - dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_mini_cmd\n", - __func__); + dev_dbg(&client->dev, "invalid fe_sec_mini_cmd\n"); ret = -EINVAL; goto error; } /* wait LNB TX */ - for (i = 500, tmp = 0; i && !tmp; i--) { - ret = tda10071_rd_reg_mask(priv, 0x47, &tmp, 0x01); + for (i = 500, uitmp = 0; i && !uitmp; i--) { + ret = regmap_read(dev->regmap, 0x47, &uitmp); if (ret) goto error; - + uitmp = (uitmp >> 0) & 1; usleep_range(10000, 20000); } - dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i); + dev_dbg(&client->dev, "loop=%d\n", i); if (i == 0) { ret = -ETIMEDOUT; goto error; } - ret = tda10071_wr_reg_mask(priv, 0x47, 0x00, 0x01); + ret = regmap_update_bits(dev->regmap, 0x47, 0x01, 0x00); if (ret) goto error; @@ -466,219 +363,217 @@ static int tda10071_diseqc_send_burst(struct dvb_frontend *fe, cmd.args[1] = 0; cmd.args[2] = burst; cmd.len = 3; - ret = tda10071_cmd_execute(priv, &cmd); + ret = tda10071_cmd_execute(dev, &cmd); 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; } -static int tda10071_read_status(struct dvb_frontend *fe, fe_status_t *status) +static int tda10071_read_status(struct dvb_frontend *fe, enum fe_status *status) { - struct tda10071_priv *priv = fe->demodulator_priv; + struct tda10071_dev *dev = fe->demodulator_priv; + struct i2c_client *client = dev->client; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + struct tda10071_cmd cmd; int ret; - u8 tmp; + unsigned int uitmp; + u8 buf[8]; *status = 0; - if (!priv->warm) { + if (!dev->warm) { ret = 0; goto error; } - ret = tda10071_rd_reg(priv, 0x39, &tmp); + ret = regmap_read(dev->regmap, 0x39, &uitmp); if (ret) goto error; /* 0x39[0] tuner PLL */ - if (tmp & 0x02) /* demod PLL */ + if (uitmp & 0x02) /* demod PLL */ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER; - if (tmp & 0x04) /* viterbi or LDPC*/ + if (uitmp & 0x04) /* viterbi or LDPC*/ *status |= FE_HAS_VITERBI; - if (tmp & 0x08) /* RS or BCH */ + if (uitmp & 0x08) /* RS or BCH */ *status |= FE_HAS_SYNC | FE_HAS_LOCK; - priv->fe_status = *status; + dev->fe_status = *status; - return ret; -error: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); - return ret; -} + /* signal strength */ + if (dev->fe_status & FE_HAS_SIGNAL) { + cmd.args[0] = CMD_GET_AGCACC; + cmd.args[1] = 0; + cmd.len = 2; + ret = tda10071_cmd_execute(dev, &cmd); + if (ret) + goto error; -static int tda10071_read_snr(struct dvb_frontend *fe, u16 *snr) -{ - struct tda10071_priv *priv = fe->demodulator_priv; - int ret; - u8 buf[2]; + /* input power estimate dBm */ + ret = regmap_read(dev->regmap, 0x50, &uitmp); + if (ret) + goto error; - if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) { - *snr = 0; - ret = 0; - goto error; + c->strength.stat[0].scale = FE_SCALE_DECIBEL; + c->strength.stat[0].svalue = (int) (uitmp - 256) * 1000; + } else { + c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; } - ret = tda10071_rd_regs(priv, 0x3a, buf, 2); - if (ret) - goto error; + /* CNR */ + if (dev->fe_status & FE_HAS_VITERBI) { + /* Es/No */ + ret = regmap_bulk_read(dev->regmap, 0x3a, buf, 2); + if (ret) + goto error; - /* Es/No dBx10 */ - *snr = buf[0] << 8 | buf[1]; + c->cnr.stat[0].scale = FE_SCALE_DECIBEL; + c->cnr.stat[0].svalue = (buf[0] << 8 | buf[1] << 0) * 100; + } else { + 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; -} + /* UCB/PER/BER */ + if (dev->fe_status & FE_HAS_LOCK) { + /* TODO: report total bits/packets */ + u8 delivery_system, reg, len; -static int tda10071_read_signal_strength(struct dvb_frontend *fe, u16 *strength) -{ - struct tda10071_priv *priv = fe->demodulator_priv; - struct tda10071_cmd cmd; - int ret; - u8 tmp; + switch (dev->delivery_system) { + case SYS_DVBS: + reg = 0x4c; + len = 8; + delivery_system = 1; + break; + case SYS_DVBS2: + reg = 0x4d; + len = 4; + delivery_system = 0; + break; + default: + ret = -EINVAL; + goto error; + } - if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) { - *strength = 0; - ret = 0; - goto error; - } + ret = regmap_read(dev->regmap, reg, &uitmp); + if (ret) + goto error; - cmd.args[0] = CMD_GET_AGCACC; - cmd.args[1] = 0; - cmd.len = 2; - ret = tda10071_cmd_execute(priv, &cmd); - if (ret) - goto error; + if (dev->meas_count == uitmp) { + dev_dbg(&client->dev, "meas not ready=%02x\n", uitmp); + ret = 0; + goto error; + } else { + dev->meas_count = uitmp; + } - /* input power estimate dBm */ - ret = tda10071_rd_reg(priv, 0x50, &tmp); - if (ret) - goto error; + cmd.args[0] = CMD_BER_UPDATE_COUNTERS; + cmd.args[1] = 0; + cmd.args[2] = delivery_system; + cmd.len = 3; + ret = tda10071_cmd_execute(dev, &cmd); + if (ret) + goto error; - if (tmp < 181) - tmp = 181; /* -75 dBm */ - else if (tmp > 236) - tmp = 236; /* -20 dBm */ + ret = regmap_bulk_read(dev->regmap, cmd.len, buf, len); + if (ret) + goto error; - /* scale value to 0x0000-0xffff */ - *strength = (tmp-181) * 0xffff / (236-181); + if (dev->delivery_system == SYS_DVBS) { + dev->dvbv3_ber = buf[0] << 24 | buf[1] << 16 | + buf[2] << 8 | buf[3] << 0; + dev->post_bit_error += buf[0] << 24 | buf[1] << 16 | + buf[2] << 8 | buf[3] << 0; + c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; + c->post_bit_error.stat[0].uvalue = dev->post_bit_error; + dev->block_error += buf[4] << 8 | buf[5] << 0; + c->block_error.stat[0].scale = FE_SCALE_COUNTER; + c->block_error.stat[0].uvalue = dev->block_error; + } else { + dev->dvbv3_ber = buf[0] << 8 | buf[1] << 0; + dev->post_bit_error += buf[0] << 8 | buf[1] << 0; + c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; + c->post_bit_error.stat[0].uvalue = dev->post_bit_error; + c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + } + } else { + c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->block_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; } -static int tda10071_read_ber(struct dvb_frontend *fe, u32 *ber) +static int tda10071_read_snr(struct dvb_frontend *fe, u16 *snr) { - struct tda10071_priv *priv = fe->demodulator_priv; - struct tda10071_cmd cmd; - int ret, i, len; - u8 tmp, reg, buf[8]; - - if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) { - *ber = priv->ber = 0; - ret = 0; - goto error; - } + struct dtv_frontend_properties *c = &fe->dtv_property_cache; - switch (priv->delivery_system) { - case SYS_DVBS: - reg = 0x4c; - len = 8; - i = 1; - break; - case SYS_DVBS2: - reg = 0x4d; - len = 4; - i = 0; - break; - default: - *ber = priv->ber = 0; - return 0; - } + if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL) + *snr = div_s64(c->cnr.stat[0].svalue, 100); + else + *snr = 0; + return 0; +} - ret = tda10071_rd_reg(priv, reg, &tmp); - if (ret) - goto error; +static int tda10071_read_signal_strength(struct dvb_frontend *fe, u16 *strength) +{ + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + unsigned int uitmp; - if (priv->meas_count[i] == tmp) { - dev_dbg(&priv->i2c->dev, "%s: meas not ready=%02x\n", __func__, - tmp); - *ber = priv->ber; - return 0; + if (c->strength.stat[0].scale == FE_SCALE_DECIBEL) { + uitmp = div_s64(c->strength.stat[0].svalue, 1000) + 256; + uitmp = clamp(uitmp, 181U, 236U); /* -75dBm - -20dBm */ + /* scale value to 0x0000-0xffff */ + *strength = (uitmp-181) * 0xffff / (236-181); } else { - priv->meas_count[i] = tmp; + *strength = 0; } + return 0; +} - cmd.args[0] = CMD_BER_UPDATE_COUNTERS; - cmd.args[1] = 0; - cmd.args[2] = i; - cmd.len = 3; - ret = tda10071_cmd_execute(priv, &cmd); - if (ret) - goto error; - - ret = tda10071_rd_regs(priv, cmd.len, buf, len); - if (ret) - goto error; - - if (priv->delivery_system == SYS_DVBS) { - *ber = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; - priv->ucb += (buf[4] << 8) | buf[5]; - } else { - *ber = (buf[0] << 8) | buf[1]; - } - priv->ber = *ber; +static int tda10071_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + struct tda10071_dev *dev = fe->demodulator_priv; - return ret; -error: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); - return ret; + *ber = dev->dvbv3_ber; + return 0; } static int tda10071_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) { - struct tda10071_priv *priv = fe->demodulator_priv; - int ret = 0; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; - if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) { + if (c->block_error.stat[0].scale == FE_SCALE_COUNTER) + *ucblocks = c->block_error.stat[0].uvalue; + else *ucblocks = 0; - goto error; - } - - /* UCB is updated when BER is read. Assume BER is read anyway. */ - - *ucblocks = priv->ucb; - - return ret; -error: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); - return ret; + return 0; } static int tda10071_set_frontend(struct dvb_frontend *fe) { - struct tda10071_priv *priv = fe->demodulator_priv; + struct tda10071_dev *dev = fe->demodulator_priv; + struct i2c_client *client = dev->client; struct tda10071_cmd cmd; struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret, i; u8 mode, rolloff, pilot, inversion, div; - fe_modulation_t modulation; + enum fe_modulation modulation; - dev_dbg(&priv->i2c->dev, - "%s: delivery_system=%d modulation=%d frequency=%d symbol_rate=%d inversion=%d pilot=%d rolloff=%d\n", - __func__, c->delivery_system, c->modulation, - c->frequency, c->symbol_rate, c->inversion, c->pilot, - c->rolloff); + dev_dbg(&client->dev, + "delivery_system=%d modulation=%d frequency=%u symbol_rate=%d inversion=%d pilot=%d rolloff=%d\n", + c->delivery_system, c->modulation, c->frequency, c->symbol_rate, + c->inversion, c->pilot, c->rolloff); - priv->delivery_system = SYS_UNDEFINED; + dev->delivery_system = SYS_UNDEFINED; - if (!priv->warm) { + if (!dev->warm) { ret = -EFAULT; goto error; } @@ -696,7 +591,7 @@ static int tda10071_set_frontend(struct dvb_frontend *fe) inversion = 3; break; default: - dev_dbg(&priv->i2c->dev, "%s: invalid inversion\n", __func__); + dev_dbg(&client->dev, "invalid inversion\n"); ret = -EINVAL; goto error; } @@ -722,8 +617,7 @@ static int tda10071_set_frontend(struct dvb_frontend *fe) break; case ROLLOFF_AUTO: default: - dev_dbg(&priv->i2c->dev, "%s: invalid rolloff\n", - __func__); + dev_dbg(&client->dev, "invalid rolloff\n"); ret = -EINVAL; goto error; } @@ -739,15 +633,13 @@ static int tda10071_set_frontend(struct dvb_frontend *fe) pilot = 2; break; default: - dev_dbg(&priv->i2c->dev, "%s: invalid pilot\n", - __func__); + dev_dbg(&client->dev, "invalid pilot\n"); ret = -EINVAL; goto error; } break; default: - dev_dbg(&priv->i2c->dev, "%s: invalid delivery_system\n", - __func__); + dev_dbg(&client->dev, "invalid delivery_system\n"); ret = -EINVAL; goto error; } @@ -757,15 +649,13 @@ static int tda10071_set_frontend(struct dvb_frontend *fe) modulation == TDA10071_MODCOD[i].modulation && c->fec_inner == TDA10071_MODCOD[i].fec) { mode = TDA10071_MODCOD[i].val; - dev_dbg(&priv->i2c->dev, "%s: mode found=%02x\n", - __func__, mode); + dev_dbg(&client->dev, "mode found=%02x\n", mode); break; } } if (mode == 0xff) { - dev_dbg(&priv->i2c->dev, "%s: invalid parameter combination\n", - __func__); + dev_dbg(&client->dev, "invalid parameter combination\n"); ret = -EINVAL; goto error; } @@ -775,11 +665,11 @@ static int tda10071_set_frontend(struct dvb_frontend *fe) else div = 4; - ret = tda10071_wr_reg(priv, 0x81, div); + ret = regmap_write(dev->regmap, 0x81, div); if (ret) goto error; - ret = tda10071_wr_reg(priv, 0xe3, div); + ret = regmap_write(dev->regmap, 0xe3, div); if (ret) goto error; @@ -799,31 +689,32 @@ static int tda10071_set_frontend(struct dvb_frontend *fe) cmd.args[13] = 0x00; cmd.args[14] = 0x00; cmd.len = 15; - ret = tda10071_cmd_execute(priv, &cmd); + ret = tda10071_cmd_execute(dev, &cmd); if (ret) goto error; - priv->delivery_system = c->delivery_system; + dev->delivery_system = c->delivery_system; return ret; error: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } static int tda10071_get_frontend(struct dvb_frontend *fe) { - struct tda10071_priv *priv = fe->demodulator_priv; + struct tda10071_dev *dev = fe->demodulator_priv; + struct i2c_client *client = dev->client; struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret, i; u8 buf[5], tmp; - if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) { - ret = -EFAULT; + if (!dev->warm || !(dev->fe_status & FE_HAS_LOCK)) { + ret = 0; goto error; } - ret = tda10071_rd_regs(priv, 0x30, buf, 5); + ret = regmap_bulk_read(dev->regmap, 0x30, buf, 5); if (ret) goto error; @@ -856,7 +747,7 @@ static int tda10071_get_frontend(struct dvb_frontend *fe) c->frequency = (buf[2] << 16) | (buf[3] << 8) | (buf[4] << 0); - ret = tda10071_rd_regs(priv, 0x52, buf, 3); + ret = regmap_bulk_read(dev->regmap, 0x52, buf, 3); if (ret) goto error; @@ -864,15 +755,18 @@ static int tda10071_get_frontend(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; } static int tda10071_init(struct dvb_frontend *fe) { - struct tda10071_priv *priv = fe->demodulator_priv; + struct tda10071_dev *dev = fe->demodulator_priv; + struct i2c_client *client = dev->client; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct tda10071_cmd cmd; int ret, i, len, remaining, fw_size; + unsigned int uitmp; const struct firmware *fw; u8 *fw_file = TDA10071_FIRMWARE; u8 tmp, buf[4]; @@ -890,7 +784,7 @@ static int tda10071_init(struct dvb_frontend *fe) }; struct tda10071_reg_val_mask tab2[] = { { 0xf1, 0x70, 0xff }, - { 0x88, priv->cfg.pll_multiplier, 0x3f }, + { 0x88, dev->pll_multiplier, 0x3f }, { 0x89, 0x00, 0x10 }, { 0x89, 0x10, 0x10 }, { 0xc0, 0x01, 0x01 }, @@ -934,11 +828,11 @@ static int tda10071_init(struct dvb_frontend *fe) { 0xd5, 0x03, 0x03 }, }; - if (priv->warm) { + if (dev->warm) { /* warm state - wake up device from sleep */ for (i = 0; i < ARRAY_SIZE(tab); i++) { - ret = tda10071_wr_reg_mask(priv, tab[i].reg, + ret = tda10071_wr_reg_mask(dev, tab[i].reg, tab[i].val, tab[i].mask); if (ret) goto error; @@ -948,78 +842,76 @@ static int tda10071_init(struct dvb_frontend *fe) cmd.args[1] = 0; cmd.args[2] = 0; cmd.len = 3; - ret = tda10071_cmd_execute(priv, &cmd); + ret = tda10071_cmd_execute(dev, &cmd); if (ret) goto error; } else { /* cold state - try to download firmware */ /* request the firmware, this will block and timeout */ - ret = request_firmware(&fw, fw_file, priv->i2c->dev.parent); + ret = request_firmware(&fw, fw_file, &client->dev); if (ret) { - dev_err(&priv->i2c->dev, - "%s: did not find the firmware file. (%s) Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)\n", - KBUILD_MODNAME, fw_file, ret); + dev_err(&client->dev, + "did not find the firmware file. (%s) Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)\n", + fw_file, ret); goto error; } /* init */ for (i = 0; i < ARRAY_SIZE(tab2); i++) { - ret = tda10071_wr_reg_mask(priv, tab2[i].reg, + ret = tda10071_wr_reg_mask(dev, tab2[i].reg, tab2[i].val, tab2[i].mask); if (ret) goto error_release_firmware; } /* download firmware */ - ret = tda10071_wr_reg(priv, 0xe0, 0x7f); + ret = regmap_write(dev->regmap, 0xe0, 0x7f); if (ret) goto error_release_firmware; - ret = tda10071_wr_reg(priv, 0xf7, 0x81); + ret = regmap_write(dev->regmap, 0xf7, 0x81); if (ret) goto error_release_firmware; - ret = tda10071_wr_reg(priv, 0xf8, 0x00); + ret = regmap_write(dev->regmap, 0xf8, 0x00); if (ret) goto error_release_firmware; - ret = tda10071_wr_reg(priv, 0xf9, 0x00); + ret = regmap_write(dev->regmap, 0xf9, 0x00); if (ret) goto error_release_firmware; - dev_info(&priv->i2c->dev, - "%s: found a '%s' in cold state, will try to load a firmware\n", - KBUILD_MODNAME, tda10071_ops.info.name); - dev_info(&priv->i2c->dev, - "%s: downloading firmware from file '%s'\n", - KBUILD_MODNAME, fw_file); + dev_info(&client->dev, + "found a '%s' in cold state, will try to load a firmware\n", + tda10071_ops.info.name); + dev_info(&client->dev, "downloading firmware from file '%s'\n", + fw_file); /* do not download last byte */ fw_size = fw->size - 1; for (remaining = fw_size; remaining > 0; - remaining -= (priv->cfg.i2c_wr_max - 1)) { + remaining -= (dev->i2c_wr_max - 1)) { len = remaining; - if (len > (priv->cfg.i2c_wr_max - 1)) - len = (priv->cfg.i2c_wr_max - 1); + if (len > (dev->i2c_wr_max - 1)) + len = (dev->i2c_wr_max - 1); - ret = tda10071_wr_regs(priv, 0xfa, + ret = regmap_bulk_write(dev->regmap, 0xfa, (u8 *) &fw->data[fw_size - remaining], len); if (ret) { - dev_err(&priv->i2c->dev, - "%s: firmware download failed=%d\n", - KBUILD_MODNAME, ret); + dev_err(&client->dev, + "firmware download failed=%d\n", ret); goto error_release_firmware; } } release_firmware(fw); - ret = tda10071_wr_reg(priv, 0xf7, 0x0c); + ret = regmap_write(dev->regmap, 0xf7, 0x0c); if (ret) goto error; - ret = tda10071_wr_reg(priv, 0xe0, 0x00); + ret = regmap_write(dev->regmap, 0xe0, 0x00); if (ret) goto error; @@ -1027,53 +919,52 @@ static int tda10071_init(struct dvb_frontend *fe) msleep(250); /* firmware status */ - ret = tda10071_rd_reg(priv, 0x51, &tmp); + ret = regmap_read(dev->regmap, 0x51, &uitmp); if (ret) goto error; - if (tmp) { - dev_info(&priv->i2c->dev, "%s: firmware did not run\n", - KBUILD_MODNAME); + if (uitmp) { + dev_info(&client->dev, "firmware did not run\n"); ret = -EFAULT; goto error; } else { - priv->warm = true; + dev->warm = true; } cmd.args[0] = CMD_GET_FW_VERSION; cmd.len = 1; - ret = tda10071_cmd_execute(priv, &cmd); + ret = tda10071_cmd_execute(dev, &cmd); if (ret) goto error; - ret = tda10071_rd_regs(priv, cmd.len, buf, 4); + ret = regmap_bulk_read(dev->regmap, cmd.len, buf, 4); if (ret) goto error; - dev_info(&priv->i2c->dev, "%s: firmware version %d.%d.%d.%d\n", - KBUILD_MODNAME, buf[0], buf[1], buf[2], buf[3]); - dev_info(&priv->i2c->dev, "%s: found a '%s' in warm state\n", - KBUILD_MODNAME, tda10071_ops.info.name); + dev_info(&client->dev, "firmware version %d.%d.%d.%d\n", + buf[0], buf[1], buf[2], buf[3]); + dev_info(&client->dev, "found a '%s' in warm state\n", + tda10071_ops.info.name); - ret = tda10071_rd_regs(priv, 0x81, buf, 2); + ret = regmap_bulk_read(dev->regmap, 0x81, buf, 2); if (ret) goto error; cmd.args[0] = CMD_DEMOD_INIT; - cmd.args[1] = ((priv->cfg.xtal / 1000) >> 8) & 0xff; - cmd.args[2] = ((priv->cfg.xtal / 1000) >> 0) & 0xff; + cmd.args[1] = ((dev->clk / 1000) >> 8) & 0xff; + cmd.args[2] = ((dev->clk / 1000) >> 0) & 0xff; cmd.args[3] = buf[0]; cmd.args[4] = buf[1]; - cmd.args[5] = priv->cfg.pll_multiplier; - cmd.args[6] = priv->cfg.spec_inv; + cmd.args[5] = dev->pll_multiplier; + cmd.args[6] = dev->spec_inv; cmd.args[7] = 0x00; cmd.len = 8; - ret = tda10071_cmd_execute(priv, &cmd); + ret = tda10071_cmd_execute(dev, &cmd); if (ret) goto error; - if (priv->cfg.tuner_i2c_addr) - tmp = priv->cfg.tuner_i2c_addr; + if (dev->tuner_i2c_addr) + tmp = dev->tuner_i2c_addr; else tmp = 0x14; @@ -1093,22 +984,22 @@ static int tda10071_init(struct dvb_frontend *fe) cmd.args[13] = 0x00; cmd.args[14] = 0x00; cmd.len = 15; - ret = tda10071_cmd_execute(priv, &cmd); + ret = tda10071_cmd_execute(dev, &cmd); if (ret) goto error; cmd.args[0] = CMD_MPEG_CONFIG; cmd.args[1] = 0; - cmd.args[2] = priv->cfg.ts_mode; + cmd.args[2] = dev->ts_mode; cmd.args[3] = 0x00; cmd.args[4] = 0x04; cmd.args[5] = 0x00; cmd.len = 6; - ret = tda10071_cmd_execute(priv, &cmd); + ret = tda10071_cmd_execute(dev, &cmd); if (ret) goto error; - ret = tda10071_wr_reg_mask(priv, 0xf0, 0x01, 0x01); + ret = regmap_update_bits(dev->regmap, 0xf0, 0x01, 0x01); if (ret) goto error; @@ -1124,7 +1015,7 @@ static int tda10071_init(struct dvb_frontend *fe) cmd.args[9] = 30; cmd.args[10] = 30; cmd.len = 11; - ret = tda10071_cmd_execute(priv, &cmd); + ret = tda10071_cmd_execute(dev, &cmd); if (ret) goto error; @@ -1133,22 +1024,33 @@ static int tda10071_init(struct dvb_frontend *fe) cmd.args[2] = 14; cmd.args[3] = 14; cmd.len = 4; - ret = tda10071_cmd_execute(priv, &cmd); + ret = tda10071_cmd_execute(dev, &cmd); if (ret) goto error; } + /* init stats here in order signal app which stats are supported */ + c->strength.len = 1; + c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->cnr.len = 1; + c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->post_bit_error.len = 1; + c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->block_error.len = 1; + c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + return ret; error_release_firmware: release_firmware(fw); error: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } static int tda10071_sleep(struct dvb_frontend *fe) { - struct tda10071_priv *priv = fe->demodulator_priv; + struct tda10071_dev *dev = fe->demodulator_priv; + struct i2c_client *client = dev->client; struct tda10071_cmd cmd; int ret, i; struct tda10071_reg_val_mask tab[] = { @@ -1164,7 +1066,7 @@ static int tda10071_sleep(struct dvb_frontend *fe) { 0xce, 0x10, 0x10 }, }; - if (!priv->warm) { + if (!dev->warm) { ret = -EFAULT; goto error; } @@ -1173,12 +1075,12 @@ static int tda10071_sleep(struct dvb_frontend *fe) cmd.args[1] = 0; cmd.args[2] = 1; cmd.len = 3; - ret = tda10071_cmd_execute(priv, &cmd); + ret = tda10071_cmd_execute(dev, &cmd); if (ret) goto error; for (i = 0; i < ARRAY_SIZE(tab); i++) { - ret = tda10071_wr_reg_mask(priv, tab[i].reg, tab[i].val, + ret = tda10071_wr_reg_mask(dev, tab[i].reg, tab[i].val, tab[i].mask); if (ret) goto error; @@ -1186,7 +1088,7 @@ static int tda10071_sleep(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; } @@ -1200,71 +1102,6 @@ static int tda10071_get_tune_settings(struct dvb_frontend *fe, return 0; } -static void tda10071_release(struct dvb_frontend *fe) -{ - struct tda10071_priv *priv = fe->demodulator_priv; - kfree(priv); -} - -struct dvb_frontend *tda10071_attach(const struct tda10071_config *config, - struct i2c_adapter *i2c) -{ - int ret; - struct tda10071_priv *priv = NULL; - u8 tmp; - - /* allocate memory for the internal priv */ - priv = kzalloc(sizeof(struct tda10071_priv), GFP_KERNEL); - if (priv == NULL) { - ret = -ENOMEM; - goto error; - } - - /* make sure demod i2c address is specified */ - if (!config->demod_i2c_addr) { - dev_dbg(&i2c->dev, "%s: invalid demod i2c address\n", __func__); - ret = -EINVAL; - goto error; - } - - /* make sure tuner i2c address is specified */ - if (!config->tuner_i2c_addr) { - dev_dbg(&i2c->dev, "%s: invalid tuner i2c address\n", __func__); - ret = -EINVAL; - goto error; - } - - /* setup the priv */ - priv->i2c = i2c; - memcpy(&priv->cfg, config, sizeof(struct tda10071_config)); - - /* chip ID */ - ret = tda10071_rd_reg(priv, 0xff, &tmp); - if (ret || tmp != 0x0f) - goto error; - - /* chip type */ - ret = tda10071_rd_reg(priv, 0xdd, &tmp); - if (ret || tmp != 0x00) - goto error; - - /* chip version */ - ret = tda10071_rd_reg(priv, 0xfe, &tmp); - if (ret || tmp != 0x01) - goto error; - - /* create dvb_frontend */ - memcpy(&priv->fe.ops, &tda10071_ops, sizeof(struct dvb_frontend_ops)); - priv->fe.demodulator_priv = priv; - - return &priv->fe; -error: - dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret); - kfree(priv); - return NULL; -} -EXPORT_SYMBOL(tda10071_attach); - static struct dvb_frontend_ops tda10071_ops = { .delsys = { SYS_DVBS, SYS_DVBS2 }, .info = { @@ -1289,8 +1126,6 @@ static struct dvb_frontend_ops tda10071_ops = { FE_CAN_2G_MODULATION }, - .release = tda10071_release, - .get_tune_settings = tda10071_get_tune_settings, .init = tda10071_init, @@ -1313,6 +1148,119 @@ static struct dvb_frontend_ops tda10071_ops = { .set_voltage = tda10071_set_voltage, }; +static struct dvb_frontend *tda10071_get_dvb_frontend(struct i2c_client *client) +{ + struct tda10071_dev *dev = i2c_get_clientdata(client); + + dev_dbg(&client->dev, "\n"); + + return &dev->fe; +} + +static int tda10071_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct tda10071_dev *dev; + struct tda10071_platform_data *pdata = client->dev.platform_data; + int ret; + unsigned int uitmp; + static const struct regmap_config regmap_config = { + .reg_bits = 8, + .val_bits = 8, + }; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) { + ret = -ENOMEM; + goto err; + } + + dev->client = client; + mutex_init(&dev->cmd_execute_mutex); + dev->clk = pdata->clk; + dev->i2c_wr_max = pdata->i2c_wr_max; + dev->ts_mode = pdata->ts_mode; + dev->spec_inv = pdata->spec_inv; + dev->pll_multiplier = pdata->pll_multiplier; + dev->tuner_i2c_addr = pdata->tuner_i2c_addr; + dev->regmap = devm_regmap_init_i2c(client, ®map_config); + if (IS_ERR(dev->regmap)) { + ret = PTR_ERR(dev->regmap); + goto err_kfree; + } + + /* chip ID */ + ret = regmap_read(dev->regmap, 0xff, &uitmp); + if (ret) + goto err_kfree; + if (uitmp != 0x0f) { + ret = -ENODEV; + goto err_kfree; + } + + /* chip type */ + ret = regmap_read(dev->regmap, 0xdd, &uitmp); + if (ret) + goto err_kfree; + if (uitmp != 0x00) { + ret = -ENODEV; + goto err_kfree; + } + + /* chip version */ + ret = regmap_read(dev->regmap, 0xfe, &uitmp); + if (ret) + goto err_kfree; + if (uitmp != 0x01) { + ret = -ENODEV; + goto err_kfree; + } + + /* create dvb_frontend */ + memcpy(&dev->fe.ops, &tda10071_ops, sizeof(struct dvb_frontend_ops)); + dev->fe.demodulator_priv = dev; + i2c_set_clientdata(client, dev); + + /* setup callbacks */ + pdata->get_dvb_frontend = tda10071_get_dvb_frontend; + + dev_info(&client->dev, "NXP TDA10071 successfully identified\n"); + return 0; +err_kfree: + kfree(dev); +err: + dev_dbg(&client->dev, "failed=%d\n", ret); + return ret; +} + +static int tda10071_remove(struct i2c_client *client) +{ + struct tda10071_dev *dev = i2c_get_clientdata(client); + + dev_dbg(&client->dev, "\n"); + + kfree(dev); + return 0; +} + +static const struct i2c_device_id tda10071_id_table[] = { + {"tda10071_cx24118", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, tda10071_id_table); + +static struct i2c_driver tda10071_driver = { + .driver = { + .name = "tda10071", + .suppress_bind_attrs = true, + }, + .probe = tda10071_probe, + .remove = tda10071_remove, + .id_table = tda10071_id_table, +}; + +module_i2c_driver(tda10071_driver); + MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); MODULE_DESCRIPTION("NXP TDA10071 DVB-S/S2 demodulator driver"); MODULE_LICENSE("GPL"); |