diff options
Diffstat (limited to 'drivers/media/dvb-frontends/m88ds3103.c')
-rw-r--r-- | drivers/media/dvb-frontends/m88ds3103.c | 144 |
1 files changed, 65 insertions, 79 deletions
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) |