diff options
Diffstat (limited to 'drivers/media/dvb-frontends')
42 files changed, 2980 insertions, 635 deletions
diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig index fe0ddcca192c..5a134547e325 100644 --- a/drivers/media/dvb-frontends/Kconfig +++ b/drivers/media/dvb-frontends/Kconfig @@ -471,6 +471,11 @@ config DVB_SI2168 help Say Y when you want to support this frontend. +config DVB_AS102_FE + tristate + depends on DVB_CORE + default DVB_AS102 + comment "DVB-C (cable) frontends" depends on DVB_CORE @@ -643,6 +648,14 @@ config DVB_MB86A20S A driver for Fujitsu mb86a20s ISDB-T/ISDB-Tsb demodulator. Say Y when you want to support this frontend. +config DVB_TC90522 + tristate "Toshiba TC90522" + depends on DVB_CORE && I2C + default m if !MEDIA_SUBDRV_AUTOSELECT + help + A Toshiba TC90522 2xISDB-T + 2xISDB-S demodulator. + Say Y when you want to support this frontend. + comment "Digital terrestrial only tuners/PLL" depends on DVB_CORE @@ -720,6 +733,13 @@ config DVB_A8293 depends on DVB_CORE && I2C default m if !MEDIA_SUBDRV_AUTOSELECT +config DVB_SP2 + tristate "CIMaX SP2" + depends on DVB_CORE && I2C + default m if !MEDIA_SUBDRV_AUTOSELECT + help + CIMaX SP2/SP2HF Common Interface module. + config DVB_LGS8GL5 tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)" depends on DVB_CORE && I2C diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile index edf103d45920..ba59df63d050 100644 --- a/drivers/media/dvb-frontends/Makefile +++ b/drivers/media/dvb-frontends/Makefile @@ -107,10 +107,12 @@ obj-$(CONFIG_DVB_DRXK) += drxk.o obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o obj-$(CONFIG_DVB_SI2165) += si2165.o obj-$(CONFIG_DVB_A8293) += a8293.o +obj-$(CONFIG_DVB_SP2) += sp2.o obj-$(CONFIG_DVB_TDA10071) += tda10071.o obj-$(CONFIG_DVB_RTL2830) += rtl2830.o obj-$(CONFIG_DVB_RTL2832) += rtl2832.o obj-$(CONFIG_DVB_RTL2832_SDR) += rtl2832_sdr.o obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o obj-$(CONFIG_DVB_AF9033) += af9033.o - +obj-$(CONFIG_DVB_AS102_FE) += as102_fe.o +obj-$(CONFIG_DVB_TC90522) += tc90522.o diff --git a/drivers/media/dvb-frontends/af9013.c b/drivers/media/dvb-frontends/af9013.c index ecf6388d2200..8001690d7576 100644 --- a/drivers/media/dvb-frontends/af9013.c +++ b/drivers/media/dvb-frontends/af9013.c @@ -683,7 +683,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe) switch (c->transmission_mode) { case TRANSMISSION_MODE_AUTO: - auto_mode = 1; + auto_mode = true; break; case TRANSMISSION_MODE_2K: break; @@ -693,12 +693,12 @@ static int af9013_set_frontend(struct dvb_frontend *fe) default: dev_dbg(&state->i2c->dev, "%s: invalid transmission_mode\n", __func__); - auto_mode = 1; + auto_mode = true; } switch (c->guard_interval) { case GUARD_INTERVAL_AUTO: - auto_mode = 1; + auto_mode = true; break; case GUARD_INTERVAL_1_32: break; @@ -714,12 +714,12 @@ static int af9013_set_frontend(struct dvb_frontend *fe) default: dev_dbg(&state->i2c->dev, "%s: invalid guard_interval\n", __func__); - auto_mode = 1; + auto_mode = true; } switch (c->hierarchy) { case HIERARCHY_AUTO: - auto_mode = 1; + auto_mode = true; break; case HIERARCHY_NONE: break; @@ -734,12 +734,12 @@ static int af9013_set_frontend(struct dvb_frontend *fe) break; default: dev_dbg(&state->i2c->dev, "%s: invalid hierarchy\n", __func__); - auto_mode = 1; + auto_mode = true; } switch (c->modulation) { case QAM_AUTO: - auto_mode = 1; + auto_mode = true; break; case QPSK: break; @@ -751,7 +751,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe) break; default: dev_dbg(&state->i2c->dev, "%s: invalid modulation\n", __func__); - auto_mode = 1; + auto_mode = true; } /* Use HP. How and which case we can switch to LP? */ @@ -759,7 +759,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe) switch (c->code_rate_HP) { case FEC_AUTO: - auto_mode = 1; + auto_mode = true; break; case FEC_1_2: break; @@ -778,12 +778,12 @@ static int af9013_set_frontend(struct dvb_frontend *fe) default: dev_dbg(&state->i2c->dev, "%s: invalid code_rate_HP\n", __func__); - auto_mode = 1; + auto_mode = true; } switch (c->code_rate_LP) { case FEC_AUTO: - auto_mode = 1; + auto_mode = true; break; case FEC_1_2: break; @@ -804,7 +804,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe) default: dev_dbg(&state->i2c->dev, "%s: invalid code_rate_LP\n", __func__); - auto_mode = 1; + auto_mode = true; } switch (c->bandwidth_hz) { diff --git a/drivers/media/dvb-frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c index 5c90ea683a7e..63a89c1c59ff 100644 --- a/drivers/media/dvb-frontends/af9033.c +++ b/drivers/media/dvb-frontends/af9033.c @@ -24,29 +24,35 @@ /* Max transfer size done by I2C transfer functions */ #define MAX_XFER_SIZE 64 -struct af9033_state { - struct i2c_adapter *i2c; +struct af9033_dev { + struct i2c_client *client; struct dvb_frontend fe; struct af9033_config cfg; + bool is_af9035; + bool is_it9135; u32 bandwidth_hz; bool ts_mode_parallel; bool ts_mode_serial; - u32 ber; - u32 ucb; - unsigned long last_stat_check; + fe_status_t fe_status; + u64 post_bit_error_prev; /* for old read_ber we return (curr - prev) */ + u64 post_bit_error; + u64 post_bit_count; + u64 error_block_count; + u64 total_block_count; + struct delayed_work stat_work; }; /* write multiple registers */ -static int af9033_wr_regs(struct af9033_state *state, u32 reg, const u8 *val, +static int af9033_wr_regs(struct af9033_dev *dev, u32 reg, const u8 *val, int len) { int ret; u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg[1] = { { - .addr = state->cfg.i2c_addr, + .addr = dev->client->addr, .flags = 0, .len = 3 + len, .buf = buf, @@ -54,9 +60,9 @@ static int af9033_wr_regs(struct af9033_state *state, u32 reg, const u8 *val, }; if (3 + len > sizeof(buf)) { - dev_warn(&state->i2c->dev, - "%s: i2c wr reg=%04x: len=%d is too big!\n", - KBUILD_MODNAME, reg, len); + dev_warn(&dev->client->dev, + "i2c wr reg=%04x: len=%d is too big!\n", + reg, len); return -EINVAL; } @@ -65,12 +71,12 @@ static int af9033_wr_regs(struct af9033_state *state, u32 reg, const u8 *val, buf[2] = (reg >> 0) & 0xff; memcpy(&buf[3], val, len); - ret = i2c_transfer(state->i2c, msg, 1); + ret = i2c_transfer(dev->client->adapter, msg, 1); if (ret == 1) { ret = 0; } else { - dev_warn(&state->i2c->dev, "%s: i2c wr failed=%d reg=%06x " \ - "len=%d\n", KBUILD_MODNAME, ret, reg, len); + dev_warn(&dev->client->dev, "i2c wr failed=%d reg=%06x len=%d\n", + ret, reg, len); ret = -EREMOTEIO; } @@ -78,31 +84,31 @@ static int af9033_wr_regs(struct af9033_state *state, u32 reg, const u8 *val, } /* read multiple registers */ -static int af9033_rd_regs(struct af9033_state *state, u32 reg, u8 *val, int len) +static int af9033_rd_regs(struct af9033_dev *dev, u32 reg, u8 *val, int len) { int ret; u8 buf[3] = { (reg >> 16) & 0xff, (reg >> 8) & 0xff, (reg >> 0) & 0xff }; struct i2c_msg msg[2] = { { - .addr = state->cfg.i2c_addr, + .addr = dev->client->addr, .flags = 0, .len = sizeof(buf), .buf = buf }, { - .addr = state->cfg.i2c_addr, + .addr = dev->client->addr, .flags = I2C_M_RD, .len = len, .buf = val } }; - ret = i2c_transfer(state->i2c, msg, 2); + ret = i2c_transfer(dev->client->adapter, msg, 2); if (ret == 2) { ret = 0; } else { - dev_warn(&state->i2c->dev, "%s: i2c rd failed=%d reg=%06x " \ - "len=%d\n", KBUILD_MODNAME, ret, reg, len); + dev_warn(&dev->client->dev, "i2c rd failed=%d reg=%06x len=%d\n", + ret, reg, len); ret = -EREMOTEIO; } @@ -111,19 +117,19 @@ static int af9033_rd_regs(struct af9033_state *state, u32 reg, u8 *val, int len) /* write single register */ -static int af9033_wr_reg(struct af9033_state *state, u32 reg, u8 val) +static int af9033_wr_reg(struct af9033_dev *dev, u32 reg, u8 val) { - return af9033_wr_regs(state, reg, &val, 1); + return af9033_wr_regs(dev, reg, &val, 1); } /* read single register */ -static int af9033_rd_reg(struct af9033_state *state, u32 reg, u8 *val) +static int af9033_rd_reg(struct af9033_dev *dev, u32 reg, u8 *val) { - return af9033_rd_regs(state, reg, val, 1); + return af9033_rd_regs(dev, reg, val, 1); } /* write single register with mask */ -static int af9033_wr_reg_mask(struct af9033_state *state, u32 reg, u8 val, +static int af9033_wr_reg_mask(struct af9033_dev *dev, u32 reg, u8 val, u8 mask) { int ret; @@ -131,7 +137,7 @@ static int af9033_wr_reg_mask(struct af9033_state *state, u32 reg, u8 val, /* no need for read if whole reg is written */ if (mask != 0xff) { - ret = af9033_rd_regs(state, reg, &tmp, 1); + ret = af9033_rd_regs(dev, reg, &tmp, 1); if (ret) return ret; @@ -140,17 +146,17 @@ static int af9033_wr_reg_mask(struct af9033_state *state, u32 reg, u8 val, val |= tmp; } - return af9033_wr_regs(state, reg, &val, 1); + return af9033_wr_regs(dev, reg, &val, 1); } /* read single register with mask */ -static int af9033_rd_reg_mask(struct af9033_state *state, u32 reg, u8 *val, +static int af9033_rd_reg_mask(struct af9033_dev *dev, u32 reg, u8 *val, u8 mask) { int ret, i; u8 tmp; - ret = af9033_rd_regs(state, reg, &tmp, 1); + ret = af9033_rd_regs(dev, reg, &tmp, 1); if (ret) return ret; @@ -167,18 +173,17 @@ static int af9033_rd_reg_mask(struct af9033_state *state, u32 reg, u8 *val, } /* write reg val table using reg addr auto increment */ -static int af9033_wr_reg_val_tab(struct af9033_state *state, +static int af9033_wr_reg_val_tab(struct af9033_dev *dev, const struct reg_val *tab, int tab_len) { #define MAX_TAB_LEN 212 int ret, i, j; u8 buf[1 + MAX_TAB_LEN]; - dev_dbg(&state->i2c->dev, "%s: tab_len=%d\n", __func__, tab_len); + dev_dbg(&dev->client->dev, "tab_len=%d\n", tab_len); if (tab_len > sizeof(buf)) { - dev_warn(&state->i2c->dev, "%s: tab len %d is too big\n", - KBUILD_MODNAME, tab_len); + dev_warn(&dev->client->dev, "tab len %d is too big\n", tab_len); return -EINVAL; } @@ -186,7 +191,7 @@ static int af9033_wr_reg_val_tab(struct af9033_state *state, buf[j] = tab[i].val; if (i == tab_len - 1 || tab[i].reg != tab[i + 1].reg - 1) { - ret = af9033_wr_regs(state, tab[i].reg - j, buf, j + 1); + ret = af9033_wr_regs(dev, tab[i].reg - j, buf, j + 1); if (ret < 0) goto err; @@ -199,16 +204,16 @@ static int af9033_wr_reg_val_tab(struct af9033_state *state, return 0; err: - dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->client->dev, "failed=%d\n", ret); return ret; } -static u32 af9033_div(struct af9033_state *state, u32 a, u32 b, u32 x) +static u32 af9033_div(struct af9033_dev *dev, u32 a, u32 b, u32 x) { u32 r = 0, c = 0, i; - dev_dbg(&state->i2c->dev, "%s: a=%d b=%d x=%d\n", __func__, a, b, x); + dev_dbg(&dev->client->dev, "a=%d b=%d x=%d\n", a, b, x); if (a > b) { c = a / b; @@ -225,22 +230,15 @@ static u32 af9033_div(struct af9033_state *state, u32 a, u32 b, u32 x) } r = (c << (u32)x) + r; - dev_dbg(&state->i2c->dev, "%s: a=%d b=%d x=%d r=%d r=%x\n", - __func__, a, b, x, r, r); + dev_dbg(&dev->client->dev, "a=%d b=%d x=%d r=%d r=%x\n", a, b, x, r, r); return r; } -static void af9033_release(struct dvb_frontend *fe) -{ - struct af9033_state *state = fe->demodulator_priv; - - kfree(state); -} - static int af9033_init(struct dvb_frontend *fe) { - struct af9033_state *state = fe->demodulator_priv; + struct af9033_dev *dev = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret, i, len; const struct reg_val *init; u8 buf[4]; @@ -248,7 +246,7 @@ static int af9033_init(struct dvb_frontend *fe) struct reg_val_mask tab[] = { { 0x80fb24, 0x00, 0x08 }, { 0x80004c, 0x00, 0xff }, - { 0x00f641, state->cfg.tuner, 0xff }, + { 0x00f641, dev->cfg.tuner, 0xff }, { 0x80f5ca, 0x01, 0x01 }, { 0x80f715, 0x01, 0x01 }, { 0x00f41f, 0x04, 0x04 }, @@ -267,88 +265,82 @@ static int af9033_init(struct dvb_frontend *fe) { 0x00d830, 0x01, 0xff }, { 0x00d831, 0x00, 0xff }, { 0x00d832, 0x00, 0xff }, - { 0x80f985, state->ts_mode_serial, 0x01 }, - { 0x80f986, state->ts_mode_parallel, 0x01 }, + { 0x80f985, dev->ts_mode_serial, 0x01 }, + { 0x80f986, dev->ts_mode_parallel, 0x01 }, { 0x00d827, 0x00, 0xff }, { 0x00d829, 0x00, 0xff }, - { 0x800045, state->cfg.adc_multiplier, 0xff }, + { 0x800045, dev->cfg.adc_multiplier, 0xff }, }; /* program clock control */ - clock_cw = af9033_div(state, state->cfg.clock, 1000000ul, 19ul); + clock_cw = af9033_div(dev, dev->cfg.clock, 1000000ul, 19ul); buf[0] = (clock_cw >> 0) & 0xff; buf[1] = (clock_cw >> 8) & 0xff; buf[2] = (clock_cw >> 16) & 0xff; buf[3] = (clock_cw >> 24) & 0xff; - dev_dbg(&state->i2c->dev, "%s: clock=%d clock_cw=%08x\n", - __func__, state->cfg.clock, clock_cw); + dev_dbg(&dev->client->dev, "clock=%d clock_cw=%08x\n", + dev->cfg.clock, clock_cw); - ret = af9033_wr_regs(state, 0x800025, buf, 4); + ret = af9033_wr_regs(dev, 0x800025, buf, 4); if (ret < 0) goto err; /* program ADC control */ for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) { - if (clock_adc_lut[i].clock == state->cfg.clock) + if (clock_adc_lut[i].clock == dev->cfg.clock) break; } - adc_cw = af9033_div(state, clock_adc_lut[i].adc, 1000000ul, 19ul); + adc_cw = af9033_div(dev, clock_adc_lut[i].adc, 1000000ul, 19ul); buf[0] = (adc_cw >> 0) & 0xff; buf[1] = (adc_cw >> 8) & 0xff; buf[2] = (adc_cw >> 16) & 0xff; - dev_dbg(&state->i2c->dev, "%s: adc=%d adc_cw=%06x\n", - __func__, clock_adc_lut[i].adc, adc_cw); + dev_dbg(&dev->client->dev, "adc=%d adc_cw=%06x\n", + clock_adc_lut[i].adc, adc_cw); - ret = af9033_wr_regs(state, 0x80f1cd, buf, 3); + ret = af9033_wr_regs(dev, 0x80f1cd, buf, 3); if (ret < 0) goto err; /* program register table */ for (i = 0; i < ARRAY_SIZE(tab); i++) { - ret = af9033_wr_reg_mask(state, tab[i].reg, tab[i].val, + ret = af9033_wr_reg_mask(dev, tab[i].reg, tab[i].val, tab[i].mask); if (ret < 0) goto err; } - /* feed clock to RF tuner */ - switch (state->cfg.tuner) { - case AF9033_TUNER_IT9135_38: - case AF9033_TUNER_IT9135_51: - case AF9033_TUNER_IT9135_52: - case AF9033_TUNER_IT9135_60: - case AF9033_TUNER_IT9135_61: - case AF9033_TUNER_IT9135_62: - ret = af9033_wr_reg(state, 0x80fba8, 0x00); + /* clock output */ + if (dev->cfg.dyn0_clk) { + ret = af9033_wr_reg(dev, 0x80fba8, 0x00); if (ret < 0) goto err; } /* settings for TS interface */ - if (state->cfg.ts_mode == AF9033_TS_MODE_USB) { - ret = af9033_wr_reg_mask(state, 0x80f9a5, 0x00, 0x01); + if (dev->cfg.ts_mode == AF9033_TS_MODE_USB) { + ret = af9033_wr_reg_mask(dev, 0x80f9a5, 0x00, 0x01); if (ret < 0) goto err; - ret = af9033_wr_reg_mask(state, 0x80f9b5, 0x01, 0x01); + ret = af9033_wr_reg_mask(dev, 0x80f9b5, 0x01, 0x01); if (ret < 0) goto err; } else { - ret = af9033_wr_reg_mask(state, 0x80f990, 0x00, 0x01); + ret = af9033_wr_reg_mask(dev, 0x80f990, 0x00, 0x01); if (ret < 0) goto err; - ret = af9033_wr_reg_mask(state, 0x80f9b5, 0x00, 0x01); + ret = af9033_wr_reg_mask(dev, 0x80f9b5, 0x00, 0x01); if (ret < 0) goto err; } /* load OFSM settings */ - dev_dbg(&state->i2c->dev, "%s: load ofsm settings\n", __func__); - switch (state->cfg.tuner) { + dev_dbg(&dev->client->dev, "load ofsm settings\n"); + switch (dev->cfg.tuner) { case AF9033_TUNER_IT9135_38: case AF9033_TUNER_IT9135_51: case AF9033_TUNER_IT9135_52: @@ -367,14 +359,13 @@ static int af9033_init(struct dvb_frontend *fe) break; } - ret = af9033_wr_reg_val_tab(state, init, len); + ret = af9033_wr_reg_val_tab(dev, init, len); if (ret < 0) goto err; /* load tuner specific settings */ - dev_dbg(&state->i2c->dev, "%s: load tuner specific settings\n", - __func__); - switch (state->cfg.tuner) { + dev_dbg(&dev->client->dev, "load tuner specific settings\n"); + switch (dev->cfg.tuner) { case AF9033_TUNER_TUA9001: len = ARRAY_SIZE(tuner_init_tua9001); init = tuner_init_tua9001; @@ -424,90 +415,108 @@ static int af9033_init(struct dvb_frontend *fe) init = tuner_init_it9135_62; break; default: - dev_dbg(&state->i2c->dev, "%s: unsupported tuner ID=%d\n", - __func__, state->cfg.tuner); + dev_dbg(&dev->client->dev, "unsupported tuner ID=%d\n", + dev->cfg.tuner); ret = -ENODEV; goto err; } - ret = af9033_wr_reg_val_tab(state, init, len); + ret = af9033_wr_reg_val_tab(dev, init, len); if (ret < 0) goto err; - if (state->cfg.ts_mode == AF9033_TS_MODE_SERIAL) { - ret = af9033_wr_reg_mask(state, 0x00d91c, 0x01, 0x01); + if (dev->cfg.ts_mode == AF9033_TS_MODE_SERIAL) { + ret = af9033_wr_reg_mask(dev, 0x00d91c, 0x01, 0x01); if (ret < 0) goto err; - ret = af9033_wr_reg_mask(state, 0x00d917, 0x00, 0x01); + ret = af9033_wr_reg_mask(dev, 0x00d917, 0x00, 0x01); if (ret < 0) goto err; - ret = af9033_wr_reg_mask(state, 0x00d916, 0x00, 0x01); + ret = af9033_wr_reg_mask(dev, 0x00d916, 0x00, 0x01); if (ret < 0) goto err; } - switch (state->cfg.tuner) { + switch (dev->cfg.tuner) { case AF9033_TUNER_IT9135_60: case AF9033_TUNER_IT9135_61: case AF9033_TUNER_IT9135_62: - ret = af9033_wr_reg(state, 0x800000, 0x01); + ret = af9033_wr_reg(dev, 0x800000, 0x01); if (ret < 0) goto err; } - state->bandwidth_hz = 0; /* force to program all parameters */ + dev->bandwidth_hz = 0; /* force to program all parameters */ + /* 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->block_count.len = 1; + c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->block_error.len = 1; + c->block_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; + 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; err: - dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->client->dev, "failed=%d\n", ret); return ret; } static int af9033_sleep(struct dvb_frontend *fe) { - struct af9033_state *state = fe->demodulator_priv; + struct af9033_dev *dev = fe->demodulator_priv; int ret, i; u8 tmp; - ret = af9033_wr_reg(state, 0x80004c, 1); + /* stop statistics polling */ + cancel_delayed_work_sync(&dev->stat_work); + + ret = af9033_wr_reg(dev, 0x80004c, 1); if (ret < 0) goto err; - ret = af9033_wr_reg(state, 0x800000, 0); + ret = af9033_wr_reg(dev, 0x800000, 0); if (ret < 0) goto err; for (i = 100, tmp = 1; i && tmp; i--) { - ret = af9033_rd_reg(state, 0x80004c, &tmp); + ret = af9033_rd_reg(dev, 0x80004c, &tmp); if (ret < 0) goto err; usleep_range(200, 10000); } - dev_dbg(&state->i2c->dev, "%s: loop=%d\n", __func__, i); + dev_dbg(&dev->client->dev, "loop=%d\n", i); if (i == 0) { ret = -ETIMEDOUT; goto err; } - ret = af9033_wr_reg_mask(state, 0x80fb24, 0x08, 0x08); + ret = af9033_wr_reg_mask(dev, 0x80fb24, 0x08, 0x08); if (ret < 0) goto err; /* prevent current leak (?) */ - if (state->cfg.ts_mode == AF9033_TS_MODE_SERIAL) { + if (dev->cfg.ts_mode == AF9033_TS_MODE_SERIAL) { /* enable parallel TS */ - ret = af9033_wr_reg_mask(state, 0x00d917, 0x00, 0x01); + ret = af9033_wr_reg_mask(dev, 0x00d917, 0x00, 0x01); if (ret < 0) goto err; - ret = af9033_wr_reg_mask(state, 0x00d916, 0x01, 0x01); + ret = af9033_wr_reg_mask(dev, 0x00d916, 0x01, 0x01); if (ret < 0) goto err; } @@ -515,7 +524,7 @@ static int af9033_sleep(struct dvb_frontend *fe) return 0; err: - dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->client->dev, "failed=%d\n", ret); return ret; } @@ -533,14 +542,14 @@ static int af9033_get_tune_settings(struct dvb_frontend *fe, static int af9033_set_frontend(struct dvb_frontend *fe) { - struct af9033_state *state = fe->demodulator_priv; + struct af9033_dev *dev = fe->demodulator_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret, i, spec_inv, sampling_freq; u8 tmp, buf[3], bandwidth_reg_val; u32 if_frequency, freq_cw, adc_freq; - dev_dbg(&state->i2c->dev, "%s: frequency=%d bandwidth_hz=%d\n", - __func__, c->frequency, c->bandwidth_hz); + dev_dbg(&dev->client->dev, "frequency=%d bandwidth_hz=%d\n", + c->frequency, c->bandwidth_hz); /* check bandwidth */ switch (c->bandwidth_hz) { @@ -554,8 +563,7 @@ static int af9033_set_frontend(struct dvb_frontend *fe) bandwidth_reg_val = 0x02; break; default: - dev_dbg(&state->i2c->dev, "%s: invalid bandwidth_hz\n", - __func__); + dev_dbg(&dev->client->dev, "invalid bandwidth_hz\n"); ret = -EINVAL; goto err; } @@ -565,23 +573,23 @@ static int af9033_set_frontend(struct dvb_frontend *fe) fe->ops.tuner_ops.set_params(fe); /* program CFOE coefficients */ - if (c->bandwidth_hz != state->bandwidth_hz) { + if (c->bandwidth_hz != dev->bandwidth_hz) { for (i = 0; i < ARRAY_SIZE(coeff_lut); i++) { - if (coeff_lut[i].clock == state->cfg.clock && + if (coeff_lut[i].clock == dev->cfg.clock && coeff_lut[i].bandwidth_hz == c->bandwidth_hz) { break; } } - ret = af9033_wr_regs(state, 0x800001, + ret = af9033_wr_regs(dev, 0x800001, coeff_lut[i].val, sizeof(coeff_lut[i].val)); } /* program frequency control */ - if (c->bandwidth_hz != state->bandwidth_hz) { - spec_inv = state->cfg.spec_inv ? -1 : 1; + if (c->bandwidth_hz != dev->bandwidth_hz) { + spec_inv = dev->cfg.spec_inv ? -1 : 1; for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) { - if (clock_adc_lut[i].clock == state->cfg.clock) + if (clock_adc_lut[i].clock == dev->cfg.clock) break; } adc_freq = clock_adc_lut[i].adc; @@ -602,12 +610,12 @@ static int af9033_set_frontend(struct dvb_frontend *fe) else sampling_freq *= -1; - freq_cw = af9033_div(state, sampling_freq, adc_freq, 23ul); + freq_cw = af9033_div(dev, sampling_freq, adc_freq, 23ul); if (spec_inv == -1) freq_cw = 0x800000 - freq_cw; - if (state->cfg.adc_multiplier == AF9033_ADC_MULTIPLIER_2X) + if (dev->cfg.adc_multiplier == AF9033_ADC_MULTIPLIER_2X) freq_cw /= 2; buf[0] = (freq_cw >> 0) & 0xff; @@ -618,26 +626,26 @@ static int af9033_set_frontend(struct dvb_frontend *fe) if (if_frequency == 0) buf[2] = 0; - ret = af9033_wr_regs(state, 0x800029, buf, 3); + ret = af9033_wr_regs(dev, 0x800029, buf, 3); if (ret < 0) goto err; - state->bandwidth_hz = c->bandwidth_hz; + dev->bandwidth_hz = c->bandwidth_hz; } - ret = af9033_wr_reg_mask(state, 0x80f904, bandwidth_reg_val, 0x03); + ret = af9033_wr_reg_mask(dev, 0x80f904, bandwidth_reg_val, 0x03); if (ret < 0) goto err; - ret = af9033_wr_reg(state, 0x800040, 0x00); + ret = af9033_wr_reg(dev, 0x800040, 0x00); if (ret < 0) goto err; - ret = af9033_wr_reg(state, 0x800047, 0x00); + ret = af9033_wr_reg(dev, 0x800047, 0x00); if (ret < 0) goto err; - ret = af9033_wr_reg_mask(state, 0x80f999, 0x00, 0x01); + ret = af9033_wr_reg_mask(dev, 0x80f999, 0x00, 0x01); if (ret < 0) goto err; @@ -646,33 +654,33 @@ static int af9033_set_frontend(struct dvb_frontend *fe) else tmp = 0x01; /* UHF */ - ret = af9033_wr_reg(state, 0x80004b, tmp); + ret = af9033_wr_reg(dev, 0x80004b, tmp); if (ret < 0) goto err; - ret = af9033_wr_reg(state, 0x800000, 0x00); + ret = af9033_wr_reg(dev, 0x800000, 0x00); if (ret < 0) goto err; return 0; err: - dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->client->dev, "failed=%d\n", ret); return ret; } static int af9033_get_frontend(struct dvb_frontend *fe) { - struct af9033_state *state = fe->demodulator_priv; + struct af9033_dev *dev = fe->demodulator_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[8]; - dev_dbg(&state->i2c->dev, "%s:\n", __func__); + dev_dbg(&dev->client->dev, "\n"); /* read all needed registers */ - ret = af9033_rd_regs(state, 0x80f900, buf, sizeof(buf)); + ret = af9033_rd_regs(dev, 0x80f900, buf, sizeof(buf)); if (ret < 0) goto err; @@ -784,21 +792,21 @@ static int af9033_get_frontend(struct dvb_frontend *fe) return 0; err: - dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->client->dev, "failed=%d\n", ret); return ret; } static int af9033_read_status(struct dvb_frontend *fe, fe_status_t *status) { - struct af9033_state *state = fe->demodulator_priv; + struct af9033_dev *dev = fe->demodulator_priv; int ret; u8 tmp; *status = 0; /* radio channel status, 0=no result, 1=has signal, 2=no signal */ - ret = af9033_rd_reg(state, 0x800047, &tmp); + ret = af9033_rd_reg(dev, 0x800047, &tmp); if (ret < 0) goto err; @@ -808,7 +816,7 @@ static int af9033_read_status(struct dvb_frontend *fe, fe_status_t *status) if (tmp != 0x02) { /* TPS lock */ - ret = af9033_rd_reg_mask(state, 0x80f5a9, &tmp, 0x01); + ret = af9033_rd_reg_mask(dev, 0x80f5a9, &tmp, 0x01); if (ret < 0) goto err; @@ -817,7 +825,7 @@ static int af9033_read_status(struct dvb_frontend *fe, fe_status_t *status) FE_HAS_VITERBI; /* full lock */ - ret = af9033_rd_reg_mask(state, 0x80f999, &tmp, 0x01); + ret = af9033_rd_reg_mask(dev, 0x80f999, &tmp, 0x01); if (ret < 0) goto err; @@ -827,76 +835,38 @@ static int af9033_read_status(struct dvb_frontend *fe, fe_status_t *status) FE_HAS_LOCK; } + dev->fe_status = *status; + return 0; err: - dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->client->dev, "failed=%d\n", ret); return ret; } static int af9033_read_snr(struct dvb_frontend *fe, u16 *snr) { - struct af9033_state *state = fe->demodulator_priv; - int ret, i, len; - u8 buf[3], tmp; - u32 snr_val; - const struct val_snr *uninitialized_var(snr_lut); - - /* read value */ - ret = af9033_rd_regs(state, 0x80002c, buf, 3); - if (ret < 0) - goto err; + struct af9033_dev *dev = fe->demodulator_priv; + struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; - snr_val = (buf[2] << 16) | (buf[1] << 8) | buf[0]; - - /* read current modulation */ - ret = af9033_rd_reg(state, 0x80f903, &tmp); - if (ret < 0) - goto err; - - switch ((tmp >> 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; - } - - for (i = 0; i < len; i++) { - tmp = snr_lut[i].snr; - - if (snr_val < snr_lut[i].val) - break; - } - - *snr = tmp * 10; /* dB/10 */ + /* use DVBv5 CNR */ + if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL) + *snr = div_s64(c->cnr.stat[0].svalue, 100); /* 1000x => 10x */ + else + *snr = 0; return 0; - -err: - dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); - - return ret; } static int af9033_read_signal_strength(struct dvb_frontend *fe, u16 *strength) { - struct af9033_state *state = fe->demodulator_priv; + struct af9033_dev *dev = fe->demodulator_priv; int ret; u8 strength2; /* read signal strength of 0-100 scale */ - ret = af9033_rd_reg(state, 0x800048, &strength2); + ret = af9033_rd_reg(dev, 0x800048, &strength2); if (ret < 0) goto err; @@ -906,244 +876,225 @@ static int af9033_read_signal_strength(struct dvb_frontend *fe, u16 *strength) return 0; err: - dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); - - return ret; -} - -static int af9033_update_ch_stat(struct af9033_state *state) -{ - int ret = 0; - u32 err_cnt, bit_cnt; - u16 abort_cnt; - u8 buf[7]; - - /* only update data every half second */ - if (time_after(jiffies, state->last_stat_check + msecs_to_jiffies(500))) { - ret = af9033_rd_regs(state, 0x800032, buf, sizeof(buf)); - if (ret < 0) - goto err; - /* in 8 byte packets? */ - abort_cnt = (buf[1] << 8) + buf[0]; - /* in bits */ - err_cnt = (buf[4] << 16) + (buf[3] << 8) + buf[2]; - /* in 8 byte packets? always(?) 0x2710 = 10000 */ - bit_cnt = (buf[6] << 8) + buf[5]; - - if (bit_cnt < abort_cnt) { - abort_cnt = 1000; - state->ber = 0xffffffff; - } else { - /* 8 byte packets, that have not been rejected already */ - bit_cnt -= (u32)abort_cnt; - if (bit_cnt == 0) { - state->ber = 0xffffffff; - } else { - err_cnt -= (u32)abort_cnt * 8 * 8; - bit_cnt *= 8 * 8; - state->ber = err_cnt * (0xffffffff / bit_cnt); - } - } - state->ucb += abort_cnt; - state->last_stat_check = jiffies; - } - - return 0; -err: - dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->client->dev, "failed=%d\n", ret); return ret; } static int af9033_read_ber(struct dvb_frontend *fe, u32 *ber) { - struct af9033_state *state = fe->demodulator_priv; - int ret; - - ret = af9033_update_ch_stat(state); - if (ret < 0) - return ret; + struct af9033_dev *dev = fe->demodulator_priv; - *ber = state->ber; + *ber = (dev->post_bit_error - dev->post_bit_error_prev); + dev->post_bit_error_prev = dev->post_bit_error; return 0; } static int af9033_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) { - struct af9033_state *state = fe->demodulator_priv; - int ret; - - ret = af9033_update_ch_stat(state); - if (ret < 0) - return ret; - - *ucblocks = state->ucb; + struct af9033_dev *dev = fe->demodulator_priv; + *ucblocks = dev->error_block_count; return 0; } static int af9033_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) { - struct af9033_state *state = fe->demodulator_priv; + struct af9033_dev *dev = fe->demodulator_priv; int ret; - dev_dbg(&state->i2c->dev, "%s: enable=%d\n", __func__, enable); + dev_dbg(&dev->client->dev, "enable=%d\n", enable); - ret = af9033_wr_reg_mask(state, 0x00fa04, enable, 0x01); + ret = af9033_wr_reg_mask(dev, 0x00fa04, enable, 0x01); if (ret < 0) goto err; return 0; err: - dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->client->dev, "failed=%d\n", ret); return ret; } static int af9033_pid_filter_ctrl(struct dvb_frontend *fe, int onoff) { - struct af9033_state *state = fe->demodulator_priv; + struct af9033_dev *dev = fe->demodulator_priv; int ret; - dev_dbg(&state->i2c->dev, "%s: onoff=%d\n", __func__, onoff); + dev_dbg(&dev->client->dev, "onoff=%d\n", onoff); - ret = af9033_wr_reg_mask(state, 0x80f993, onoff, 0x01); + ret = af9033_wr_reg_mask(dev, 0x80f993, onoff, 0x01); if (ret < 0) goto err; return 0; err: - dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->client->dev, "failed=%d\n", ret); return ret; } -static int af9033_pid_filter(struct dvb_frontend *fe, int index, u16 pid, int onoff) +static int af9033_pid_filter(struct dvb_frontend *fe, int index, u16 pid, + int onoff) { - struct af9033_state *state = fe->demodulator_priv; + struct af9033_dev *dev = fe->demodulator_priv; int ret; u8 wbuf[2] = {(pid >> 0) & 0xff, (pid >> 8) & 0xff}; - dev_dbg(&state->i2c->dev, "%s: index=%d pid=%04x onoff=%d\n", - __func__, index, pid, onoff); + dev_dbg(&dev->client->dev, "index=%d pid=%04x onoff=%d\n", + index, pid, onoff); if (pid > 0x1fff) return 0; - ret = af9033_wr_regs(state, 0x80f996, wbuf, 2); + ret = af9033_wr_regs(dev, 0x80f996, wbuf, 2); if (ret < 0) goto err; - ret = af9033_wr_reg(state, 0x80f994, onoff); + ret = af9033_wr_reg(dev, 0x80f994, onoff); if (ret < 0) goto err; - ret = af9033_wr_reg(state, 0x80f995, index); + ret = af9033_wr_reg(dev, 0x80f995, index); if (ret < 0) goto err; return 0; err: - dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->client->dev, "failed=%d\n", ret); return ret; } -static struct dvb_frontend_ops af9033_ops; - -struct dvb_frontend *af9033_attach(const struct af9033_config *config, - struct i2c_adapter *i2c, - struct af9033_ops *ops) +static void af9033_stat_work(struct work_struct *work) { - int ret; - struct af9033_state *state; - u8 buf[8]; + 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; - dev_dbg(&i2c->dev, "%s:\n", __func__); + 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; + } - /* allocate memory for the internal state */ - state = kzalloc(sizeof(struct af9033_state), GFP_KERNEL); - if (state == NULL) - goto err; + /* CNR */ + if (dev->fe_status & FE_HAS_VITERBI) { + u32 snr_val; + const struct val_snr *snr_lut; - /* setup the state */ - state->i2c = i2c; - memcpy(&state->cfg, config, sizeof(struct af9033_config)); + /* read value */ + ret = af9033_rd_regs(dev, 0x80002c, buf, 3); + if (ret) + goto err; - if (state->cfg.clock != 12000000) { - dev_err(&state->i2c->dev, "%s: af9033: unsupported clock=%d, " \ - "only 12000000 Hz is supported currently\n", - KBUILD_MODNAME, state->cfg.clock); - goto err; - } + snr_val = (buf[2] << 16) | (buf[1] << 8) | (buf[0] << 0); - /* firmware version */ - ret = af9033_rd_regs(state, 0x0083e9, &buf[0], 4); - if (ret < 0) - goto err; + /* read current modulation */ + ret = af9033_rd_reg(dev, 0x80f903, &u8tmp); + if (ret) + goto err; - ret = af9033_rd_regs(state, 0x804191, &buf[4], 4); - if (ret < 0) - 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; + } - dev_info(&state->i2c->dev, "%s: firmware version: LINK=%d.%d.%d.%d " \ - "OFDM=%d.%d.%d.%d\n", KBUILD_MODNAME, buf[0], buf[1], - buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); + for (i = 0; i < len; i++) { + tmp = snr_lut[i].snr * 1000; + if (snr_val < snr_lut[i].val) + break; + } - /* sleep */ - switch (state->cfg.tuner) { - case AF9033_TUNER_IT9135_38: - case AF9033_TUNER_IT9135_51: - case AF9033_TUNER_IT9135_52: - case AF9033_TUNER_IT9135_60: - case AF9033_TUNER_IT9135_61: - case AF9033_TUNER_IT9135_62: - /* IT9135 did not like to sleep at that early */ - break; - default: - ret = af9033_wr_reg(state, 0x80004c, 1); - if (ret < 0) - goto err; + 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; + } - ret = af9033_wr_reg(state, 0x800000, 0); - if (ret < 0) + /* 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; - } - /* configure internal TS mode */ - switch (state->cfg.ts_mode) { - case AF9033_TS_MODE_PARALLEL: - state->ts_mode_parallel = true; - break; - case AF9033_TS_MODE_SERIAL: - state->ts_mode_serial = true; - break; - case AF9033_TS_MODE_USB: - /* usb mode for AF9035 */ - default: - break; - } + 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); - /* create dvb_frontend */ - memcpy(&state->fe.ops, &af9033_ops, sizeof(struct dvb_frontend_ops)); - state->fe.demodulator_priv = state; + 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; - if (ops) { - ops->pid_filter = af9033_pid_filter; - ops->pid_filter_ctrl = af9033_pid_filter_ctrl; - } + 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; - return &state->fe; + 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: - kfree(state); - return NULL; + dev_dbg(&dev->client->dev, "failed=%d\n", ret); } -EXPORT_SYMBOL(af9033_attach); static struct dvb_frontend_ops af9033_ops = { .delsys = { SYS_DVBT }, @@ -1170,8 +1121,6 @@ static struct dvb_frontend_ops af9033_ops = { FE_CAN_MUTE_TS }, - .release = af9033_release, - .init = af9033_init, .sleep = af9033_sleep, @@ -1188,6 +1137,150 @@ static struct dvb_frontend_ops af9033_ops = { .i2c_gate_ctrl = af9033_i2c_gate_ctrl, }; +static int af9033_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct af9033_config *cfg = client->dev.platform_data; + struct af9033_dev *dev; + int ret; + u8 buf[8]; + u32 reg; + + /* allocate memory for the internal state */ + dev = kzalloc(sizeof(struct af9033_dev), GFP_KERNEL); + if (dev == NULL) { + ret = -ENOMEM; + dev_err(&client->dev, "Could not allocate memory for state\n"); + goto err; + } + + /* 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) { + ret = -ENODEV; + dev_err(&dev->client->dev, + "unsupported clock %d Hz, only 12000000 Hz is supported currently\n", + dev->cfg.clock); + goto err_kfree; + } + + /* firmware version */ + switch (dev->cfg.tuner) { + case AF9033_TUNER_IT9135_38: + case AF9033_TUNER_IT9135_51: + case AF9033_TUNER_IT9135_52: + case AF9033_TUNER_IT9135_60: + case AF9033_TUNER_IT9135_61: + case AF9033_TUNER_IT9135_62: + dev->is_it9135 = true; + reg = 0x004bfc; + break; + default: + dev->is_af9035 = true; + reg = 0x0083e9; + break; + } + + ret = af9033_rd_regs(dev, reg, &buf[0], 4); + if (ret < 0) + goto err_kfree; + + ret = af9033_rd_regs(dev, 0x804191, &buf[4], 4); + if (ret < 0) + goto err_kfree; + + dev_info(&dev->client->dev, + "firmware version: LINK %d.%d.%d.%d - OFDM %d.%d.%d.%d\n", + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], + buf[7]); + + /* sleep */ + switch (dev->cfg.tuner) { + case AF9033_TUNER_IT9135_38: + case AF9033_TUNER_IT9135_51: + case AF9033_TUNER_IT9135_52: + case AF9033_TUNER_IT9135_60: + case AF9033_TUNER_IT9135_61: + case AF9033_TUNER_IT9135_62: + /* IT9135 did not like to sleep at that early */ + break; + default: + ret = af9033_wr_reg(dev, 0x80004c, 1); + if (ret < 0) + goto err_kfree; + + ret = af9033_wr_reg(dev, 0x800000, 0); + if (ret < 0) + goto err_kfree; + } + + /* configure internal TS mode */ + switch (dev->cfg.ts_mode) { + case AF9033_TS_MODE_PARALLEL: + dev->ts_mode_parallel = true; + break; + case AF9033_TS_MODE_SERIAL: + dev->ts_mode_serial = true; + break; + case AF9033_TS_MODE_USB: + /* usb mode for AF9035 */ + default: + break; + } + + /* create dvb_frontend */ + memcpy(&dev->fe.ops, &af9033_ops, sizeof(struct dvb_frontend_ops)); + dev->fe.demodulator_priv = dev; + *cfg->fe = &dev->fe; + if (cfg->ops) { + cfg->ops->pid_filter = af9033_pid_filter; + cfg->ops->pid_filter_ctrl = af9033_pid_filter_ctrl; + } + i2c_set_clientdata(client, dev); + + dev_info(&dev->client->dev, "Afatech AF9033 successfully attached\n"); + return 0; +err_kfree: + kfree(dev); +err: + dev_dbg(&client->dev, "failed=%d\n", ret); + return ret; +} + +static int af9033_remove(struct i2c_client *client) +{ + struct af9033_dev *dev = i2c_get_clientdata(client); + + dev_dbg(&dev->client->dev, "\n"); + + dev->fe.ops.release = NULL; + dev->fe.demodulator_priv = NULL; + kfree(dev); + + return 0; +} + +static const struct i2c_device_id af9033_id_table[] = { + {"af9033", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, af9033_id_table); + +static struct i2c_driver af9033_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "af9033", + }, + .probe = af9033_probe, + .remove = af9033_remove, + .id_table = af9033_id_table, +}; + +module_i2c_driver(af9033_driver); + MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); MODULE_DESCRIPTION("Afatech AF9033 DVB-T demodulator driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/af9033.h b/drivers/media/dvb-frontends/af9033.h index 539f4db678b8..6ad22b69a636 100644 --- a/drivers/media/dvb-frontends/af9033.h +++ b/drivers/media/dvb-frontends/af9033.h @@ -24,13 +24,12 @@ #include <linux/kconfig.h> +/* + * I2C address (TODO: are these in 8-bit format?) + * 0x38, 0x3a, 0x3c, 0x3e + */ struct af9033_config { /* - * I2C address - */ - u8 i2c_addr; - - /* * clock Hz * 12000000, 22000000, 24000000, 34000000, 32000000, 28000000, 26000000, * 30000000, 36000000, 20480000, 16384000 @@ -75,8 +74,23 @@ struct af9033_config { * input spectrum inversion */ bool spec_inv; -}; + /* + * + */ + bool dyn0_clk; + + /* + * PID filter ops + */ + struct af9033_ops *ops; + + /* + * frontend + * returned by that driver + */ + struct dvb_frontend **fe; +}; struct af9033_ops { int (*pid_filter_ctrl)(struct dvb_frontend *fe, int onoff); @@ -84,36 +98,4 @@ struct af9033_ops { int onoff); }; - -#if IS_ENABLED(CONFIG_DVB_AF9033) -extern -struct dvb_frontend *af9033_attach(const struct af9033_config *config, - struct i2c_adapter *i2c, - struct af9033_ops *ops); - -#else -static inline -struct dvb_frontend *af9033_attach(const struct af9033_config *config, - struct i2c_adapter *i2c, - struct af9033_ops *ops) -{ - pr_warn("%s: driver disabled by Kconfig\n", __func__); - return NULL; -} - -static inline int af9033_pid_filter_ctrl(struct dvb_frontend *fe, int onoff) -{ - pr_warn("%s: driver disabled by Kconfig\n", __func__); - return -ENODEV; -} - -static inline int af9033_pid_filter(struct dvb_frontend *fe, int index, u16 pid, - int onoff) -{ - pr_warn("%s: driver disabled by Kconfig\n", __func__); - return -ENODEV; -} - -#endif - #endif /* AF9033_H */ diff --git a/drivers/media/dvb-frontends/af9033_priv.h b/drivers/media/dvb-frontends/af9033_priv.h index ded7b67d7526..c12c92cb5855 100644 --- a/drivers/media/dvb-frontends/af9033_priv.h +++ b/drivers/media/dvb-frontends/af9033_priv.h @@ -24,6 +24,7 @@ #include "dvb_frontend.h" #include "af9033.h" +#include <linux/math64.h> struct reg_val { u32 reg; diff --git a/drivers/media/dvb-frontends/as102_fe.c b/drivers/media/dvb-frontends/as102_fe.c new file mode 100644 index 000000000000..493665899565 --- /dev/null +++ b/drivers/media/dvb-frontends/as102_fe.c @@ -0,0 +1,480 @@ +/* + * Abilis Systems Single DVB-T Receiver + * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com> + * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <dvb_frontend.h> + +#include "as102_fe.h" + +struct as102_state { + struct dvb_frontend frontend; + struct as10x_demod_stats demod_stats; + + const struct as102_fe_ops *ops; + void *priv; + uint8_t elna_cfg; + + /* signal strength */ + uint16_t signal_strength; + /* bit error rate */ + uint32_t ber; +}; + +static uint8_t as102_fe_get_code_rate(fe_code_rate_t arg) +{ + uint8_t c; + + switch (arg) { + case FEC_1_2: + c = CODE_RATE_1_2; + break; + case FEC_2_3: + c = CODE_RATE_2_3; + break; + case FEC_3_4: + c = CODE_RATE_3_4; + break; + case FEC_5_6: + c = CODE_RATE_5_6; + break; + case FEC_7_8: + c = CODE_RATE_7_8; + break; + default: + c = CODE_RATE_UNKNOWN; + break; + } + + return c; +} + +static int as102_fe_set_frontend(struct dvb_frontend *fe) +{ + struct as102_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + struct as10x_tune_args tune_args = { 0 }; + + /* set frequency */ + tune_args.freq = c->frequency / 1000; + + /* fix interleaving_mode */ + tune_args.interleaving_mode = INTLV_NATIVE; + + switch (c->bandwidth_hz) { + case 8000000: + tune_args.bandwidth = BW_8_MHZ; + break; + case 7000000: + tune_args.bandwidth = BW_7_MHZ; + break; + case 6000000: + tune_args.bandwidth = BW_6_MHZ; + break; + default: + tune_args.bandwidth = BW_8_MHZ; + } + + switch (c->guard_interval) { + case GUARD_INTERVAL_1_32: + tune_args.guard_interval = GUARD_INT_1_32; + break; + case GUARD_INTERVAL_1_16: + tune_args.guard_interval = GUARD_INT_1_16; + break; + case GUARD_INTERVAL_1_8: + tune_args.guard_interval = GUARD_INT_1_8; + break; + case GUARD_INTERVAL_1_4: + tune_args.guard_interval = GUARD_INT_1_4; + break; + case GUARD_INTERVAL_AUTO: + default: + tune_args.guard_interval = GUARD_UNKNOWN; + break; + } + + switch (c->modulation) { + case QPSK: + tune_args.modulation = CONST_QPSK; + break; + case QAM_16: + tune_args.modulation = CONST_QAM16; + break; + case QAM_64: + tune_args.modulation = CONST_QAM64; + break; + default: + tune_args.modulation = CONST_UNKNOWN; + break; + } + + switch (c->transmission_mode) { + case TRANSMISSION_MODE_2K: + tune_args.transmission_mode = TRANS_MODE_2K; + break; + case TRANSMISSION_MODE_8K: + tune_args.transmission_mode = TRANS_MODE_8K; + break; + default: + tune_args.transmission_mode = TRANS_MODE_UNKNOWN; + } + + switch (c->hierarchy) { + case HIERARCHY_NONE: + tune_args.hierarchy = HIER_NONE; + break; + case HIERARCHY_1: + tune_args.hierarchy = HIER_ALPHA_1; + break; + case HIERARCHY_2: + tune_args.hierarchy = HIER_ALPHA_2; + break; + case HIERARCHY_4: + tune_args.hierarchy = HIER_ALPHA_4; + break; + case HIERARCHY_AUTO: + tune_args.hierarchy = HIER_UNKNOWN; + break; + } + + pr_debug("as102: tuner parameters: freq: %d bw: 0x%02x gi: 0x%02x\n", + c->frequency, + tune_args.bandwidth, + tune_args.guard_interval); + + /* + * Detect a hierarchy selection + * if HP/LP are both set to FEC_NONE, HP will be selected. + */ + if ((tune_args.hierarchy != HIER_NONE) && + ((c->code_rate_LP == FEC_NONE) || + (c->code_rate_HP == FEC_NONE))) { + + if (c->code_rate_LP == FEC_NONE) { + tune_args.hier_select = HIER_HIGH_PRIORITY; + tune_args.code_rate = + as102_fe_get_code_rate(c->code_rate_HP); + } + + if (c->code_rate_HP == FEC_NONE) { + tune_args.hier_select = HIER_LOW_PRIORITY; + tune_args.code_rate = + as102_fe_get_code_rate(c->code_rate_LP); + } + + pr_debug("as102: \thierarchy: 0x%02x selected: %s code_rate_%s: 0x%02x\n", + tune_args.hierarchy, + tune_args.hier_select == HIER_HIGH_PRIORITY ? + "HP" : "LP", + tune_args.hier_select == HIER_HIGH_PRIORITY ? + "HP" : "LP", + tune_args.code_rate); + } else { + tune_args.code_rate = + as102_fe_get_code_rate(c->code_rate_HP); + } + + /* Set frontend arguments */ + return state->ops->set_tune(state->priv, &tune_args); +} + +static int as102_fe_get_frontend(struct dvb_frontend *fe) +{ + struct as102_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + int ret = 0; + struct as10x_tps tps = { 0 }; + + /* send abilis command: GET_TPS */ + ret = state->ops->get_tps(state->priv, &tps); + if (ret < 0) + return ret; + + /* extract constellation */ + switch (tps.modulation) { + case CONST_QPSK: + c->modulation = QPSK; + break; + case CONST_QAM16: + c->modulation = QAM_16; + break; + case CONST_QAM64: + c->modulation = QAM_64; + break; + } + + /* extract hierarchy */ + switch (tps.hierarchy) { + case HIER_NONE: + c->hierarchy = HIERARCHY_NONE; + break; + case HIER_ALPHA_1: + c->hierarchy = HIERARCHY_1; + break; + case HIER_ALPHA_2: + c->hierarchy = HIERARCHY_2; + break; + case HIER_ALPHA_4: + c->hierarchy = HIERARCHY_4; + break; + } + + /* extract code rate HP */ + switch (tps.code_rate_HP) { + case CODE_RATE_1_2: + c->code_rate_HP = FEC_1_2; + break; + case CODE_RATE_2_3: + c->code_rate_HP = FEC_2_3; + break; + case CODE_RATE_3_4: + c->code_rate_HP = FEC_3_4; + break; + case CODE_RATE_5_6: + c->code_rate_HP = FEC_5_6; + break; + case CODE_RATE_7_8: + c->code_rate_HP = FEC_7_8; + break; + } + + /* extract code rate LP */ + switch (tps.code_rate_LP) { + case CODE_RATE_1_2: + c->code_rate_LP = FEC_1_2; + break; + case CODE_RATE_2_3: + c->code_rate_LP = FEC_2_3; + break; + case CODE_RATE_3_4: + c->code_rate_LP = FEC_3_4; + break; + case CODE_RATE_5_6: + c->code_rate_LP = FEC_5_6; + break; + case CODE_RATE_7_8: + c->code_rate_LP = FEC_7_8; + break; + } + + /* extract guard interval */ + switch (tps.guard_interval) { + case GUARD_INT_1_32: + c->guard_interval = GUARD_INTERVAL_1_32; + break; + case GUARD_INT_1_16: + c->guard_interval = GUARD_INTERVAL_1_16; + break; + case GUARD_INT_1_8: + c->guard_interval = GUARD_INTERVAL_1_8; + break; + case GUARD_INT_1_4: + c->guard_interval = GUARD_INTERVAL_1_4; + break; + } + + /* extract transmission mode */ + switch (tps.transmission_mode) { + case TRANS_MODE_2K: + c->transmission_mode = TRANSMISSION_MODE_2K; + break; + case TRANS_MODE_8K: + c->transmission_mode = TRANSMISSION_MODE_8K; + break; + } + + return 0; +} + +static int as102_fe_get_tune_settings(struct dvb_frontend *fe, + struct dvb_frontend_tune_settings *settings) { + + settings->min_delay_ms = 1000; + + return 0; +} + +static int as102_fe_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + int ret = 0; + struct as102_state *state = fe->demodulator_priv; + struct as10x_tune_status tstate = { 0 }; + + /* send abilis command: GET_TUNE_STATUS */ + ret = state->ops->get_status(state->priv, &tstate); + if (ret < 0) + return ret; + + state->signal_strength = tstate.signal_strength; + state->ber = tstate.BER; + + switch (tstate.tune_state) { + case TUNE_STATUS_SIGNAL_DVB_OK: + *status = FE_HAS_SIGNAL | FE_HAS_CARRIER; + break; + case TUNE_STATUS_STREAM_DETECTED: + *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC | + FE_HAS_VITERBI; + break; + case TUNE_STATUS_STREAM_TUNED: + *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC | + FE_HAS_LOCK | FE_HAS_VITERBI; + break; + default: + *status = TUNE_STATUS_NOT_TUNED; + } + + pr_debug("as102: tuner status: 0x%02x, strength %d, per: %d, ber: %d\n", + tstate.tune_state, tstate.signal_strength, + tstate.PER, tstate.BER); + + if (!(*status & FE_HAS_LOCK)) { + memset(&state->demod_stats, 0, sizeof(state->demod_stats)); + return 0; + } + + ret = state->ops->get_stats(state->priv, &state->demod_stats); + if (ret < 0) + memset(&state->demod_stats, 0, sizeof(state->demod_stats)); + + return ret; +} + +/* + * Note: + * - in AS102 SNR=MER + * - the SNR will be returned in linear terms, i.e. not in dB + * - the accuracy equals ±2dB for a SNR range from 4dB to 30dB + * - the accuracy is >2dB for SNR values outside this range + */ +static int as102_fe_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + struct as102_state *state = fe->demodulator_priv; + + *snr = state->demod_stats.mer; + + return 0; +} + +static int as102_fe_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + struct as102_state *state = fe->demodulator_priv; + + *ber = state->ber; + + return 0; +} + +static int as102_fe_read_signal_strength(struct dvb_frontend *fe, + u16 *strength) +{ + struct as102_state *state = fe->demodulator_priv; + + *strength = (((0xffff * 400) * state->signal_strength + 41000) * 2); + + return 0; +} + +static int as102_fe_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) +{ + struct as102_state *state = fe->demodulator_priv; + + if (state->demod_stats.has_started) + *ucblocks = state->demod_stats.bad_frame_count; + else + *ucblocks = 0; + + return 0; +} + +static int as102_fe_ts_bus_ctrl(struct dvb_frontend *fe, int acquire) +{ + struct as102_state *state = fe->demodulator_priv; + + return state->ops->stream_ctrl(state->priv, acquire, + state->elna_cfg); +} + +static void as102_fe_release(struct dvb_frontend *fe) +{ + struct as102_state *state = fe->demodulator_priv; + + kfree(state); +} + + +static struct dvb_frontend_ops as102_fe_ops = { + .delsys = { SYS_DVBT }, + .info = { + .name = "Abilis AS102 DVB-T", + .frequency_min = 174000000, + .frequency_max = 862000000, + .frequency_stepsize = 166667, + .caps = FE_CAN_INVERSION_AUTO + | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 + | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO + | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QPSK + | FE_CAN_QAM_AUTO + | FE_CAN_TRANSMISSION_MODE_AUTO + | FE_CAN_GUARD_INTERVAL_AUTO + | FE_CAN_HIERARCHY_AUTO + | FE_CAN_RECOVER + | FE_CAN_MUTE_TS + }, + + .set_frontend = as102_fe_set_frontend, + .get_frontend = as102_fe_get_frontend, + .get_tune_settings = as102_fe_get_tune_settings, + + .read_status = as102_fe_read_status, + .read_snr = as102_fe_read_snr, + .read_ber = as102_fe_read_ber, + .read_signal_strength = as102_fe_read_signal_strength, + .read_ucblocks = as102_fe_read_ucblocks, + .ts_bus_ctrl = as102_fe_ts_bus_ctrl, + .release = as102_fe_release, +}; + +struct dvb_frontend *as102_attach(const char *name, + const struct as102_fe_ops *ops, + void *priv, + uint8_t elna_cfg) +{ + struct as102_state *state; + struct dvb_frontend *fe; + + state = kzalloc(sizeof(struct as102_state), GFP_KERNEL); + if (state == NULL) { + pr_err("%s: unable to allocate memory for state\n", __func__); + return NULL; + } + fe = &state->frontend; + fe->demodulator_priv = state; + state->ops = ops; + state->priv = priv; + state->elna_cfg = elna_cfg; + + /* init frontend callback ops */ + memcpy(&fe->ops, &as102_fe_ops, sizeof(struct dvb_frontend_ops)); + strncpy(fe->ops.info.name, name, sizeof(fe->ops.info.name)); + + return fe; + +} +EXPORT_SYMBOL_GPL(as102_attach); + +MODULE_DESCRIPTION("as102-fe"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Pierrick Hascoet <pierrick.hascoet@abilis.com>"); diff --git a/drivers/media/dvb-frontends/as102_fe.h b/drivers/media/dvb-frontends/as102_fe.h new file mode 100644 index 000000000000..a7c91430ca3d --- /dev/null +++ b/drivers/media/dvb-frontends/as102_fe.h @@ -0,0 +1,29 @@ +/* + * Abilis Systems Single DVB-T Receiver + * Copyright (C) 2014 Mauro Carvalho Chehab <m.chehab@samsung.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "as102_fe_types.h" + +struct as102_fe_ops { + int (*set_tune)(void *priv, struct as10x_tune_args *tune_args); + int (*get_tps)(void *priv, struct as10x_tps *tps); + int (*get_status)(void *priv, struct as10x_tune_status *tstate); + int (*get_stats)(void *priv, struct as10x_demod_stats *demod_stats); + int (*stream_ctrl)(void *priv, int acquire, uint32_t elna_cfg); +}; + +struct dvb_frontend *as102_attach(const char *name, + const struct as102_fe_ops *ops, + void *priv, + uint8_t elna_cfg); diff --git a/drivers/media/dvb-frontends/as102_fe_types.h b/drivers/media/dvb-frontends/as102_fe_types.h new file mode 100644 index 000000000000..80a5398b580f --- /dev/null +++ b/drivers/media/dvb-frontends/as102_fe_types.h @@ -0,0 +1,188 @@ +/* + * Abilis Systems Single DVB-T Receiver + * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef _AS10X_TYPES_H_ +#define _AS10X_TYPES_H_ + +/*********************************/ +/* MACRO DEFINITIONS */ +/*********************************/ + +/* bandwidth constant values */ +#define BW_5_MHZ 0x00 +#define BW_6_MHZ 0x01 +#define BW_7_MHZ 0x02 +#define BW_8_MHZ 0x03 + +/* hierarchy priority selection values */ +#define HIER_NO_PRIORITY 0x00 +#define HIER_LOW_PRIORITY 0x01 +#define HIER_HIGH_PRIORITY 0x02 + +/* constellation available values */ +#define CONST_QPSK 0x00 +#define CONST_QAM16 0x01 +#define CONST_QAM64 0x02 +#define CONST_UNKNOWN 0xFF + +/* hierarchy available values */ +#define HIER_NONE 0x00 +#define HIER_ALPHA_1 0x01 +#define HIER_ALPHA_2 0x02 +#define HIER_ALPHA_4 0x03 +#define HIER_UNKNOWN 0xFF + +/* interleaving available values */ +#define INTLV_NATIVE 0x00 +#define INTLV_IN_DEPTH 0x01 +#define INTLV_UNKNOWN 0xFF + +/* code rate available values */ +#define CODE_RATE_1_2 0x00 +#define CODE_RATE_2_3 0x01 +#define CODE_RATE_3_4 0x02 +#define CODE_RATE_5_6 0x03 +#define CODE_RATE_7_8 0x04 +#define CODE_RATE_UNKNOWN 0xFF + +/* guard interval available values */ +#define GUARD_INT_1_32 0x00 +#define GUARD_INT_1_16 0x01 +#define GUARD_INT_1_8 0x02 +#define GUARD_INT_1_4 0x03 +#define GUARD_UNKNOWN 0xFF + +/* transmission mode available values */ +#define TRANS_MODE_2K 0x00 +#define TRANS_MODE_8K 0x01 +#define TRANS_MODE_4K 0x02 +#define TRANS_MODE_UNKNOWN 0xFF + +/* DVBH signalling available values */ +#define TIMESLICING_PRESENT 0x01 +#define MPE_FEC_PRESENT 0x02 + +/* tune state available */ +#define TUNE_STATUS_NOT_TUNED 0x00 +#define TUNE_STATUS_IDLE 0x01 +#define TUNE_STATUS_LOCKING 0x02 +#define TUNE_STATUS_SIGNAL_DVB_OK 0x03 +#define TUNE_STATUS_STREAM_DETECTED 0x04 +#define TUNE_STATUS_STREAM_TUNED 0x05 +#define TUNE_STATUS_ERROR 0xFF + +/* available TS FID filter types */ +#define TS_PID_TYPE_TS 0 +#define TS_PID_TYPE_PSI_SI 1 +#define TS_PID_TYPE_MPE 2 + +/* number of echos available */ +#define MAX_ECHOS 15 + +/* Context types */ +#define CONTEXT_LNA 1010 +#define CONTEXT_ELNA_HYSTERESIS 4003 +#define CONTEXT_ELNA_GAIN 4004 +#define CONTEXT_MER_THRESHOLD 5005 +#define CONTEXT_MER_OFFSET 5006 +#define CONTEXT_IR_STATE 7000 +#define CONTEXT_TSOUT_MSB_FIRST 7004 +#define CONTEXT_TSOUT_FALLING_EDGE 7005 + +/* Configuration modes */ +#define CFG_MODE_ON 0 +#define CFG_MODE_OFF 1 +#define CFG_MODE_AUTO 2 + +struct as10x_tps { + uint8_t modulation; + uint8_t hierarchy; + uint8_t interleaving_mode; + uint8_t code_rate_HP; + uint8_t code_rate_LP; + uint8_t guard_interval; + uint8_t transmission_mode; + uint8_t DVBH_mask_HP; + uint8_t DVBH_mask_LP; + uint16_t cell_ID; +} __packed; + +struct as10x_tune_args { + /* frequency */ + uint32_t freq; + /* bandwidth */ + uint8_t bandwidth; + /* hierarchy selection */ + uint8_t hier_select; + /* constellation */ + uint8_t modulation; + /* hierarchy */ + uint8_t hierarchy; + /* interleaving mode */ + uint8_t interleaving_mode; + /* code rate */ + uint8_t code_rate; + /* guard interval */ + uint8_t guard_interval; + /* transmission mode */ + uint8_t transmission_mode; +} __packed; + +struct as10x_tune_status { + /* tune status */ + uint8_t tune_state; + /* signal strength */ + int16_t signal_strength; + /* packet error rate 10^-4 */ + uint16_t PER; + /* bit error rate 10^-4 */ + uint16_t BER; +} __packed; + +struct as10x_demod_stats { + /* frame counter */ + uint32_t frame_count; + /* Bad frame counter */ + uint32_t bad_frame_count; + /* Number of wrong bytes fixed by Reed-Solomon */ + uint32_t bytes_fixed_by_rs; + /* Averaged MER */ + uint16_t mer; + /* statistics calculation state indicator (started or not) */ + uint8_t has_started; +} __packed; + +struct as10x_ts_filter { + uint16_t pid; /* valid PID value 0x00 : 0x2000 */ + uint8_t type; /* Red TS_PID_TYPE_<N> values */ + uint8_t idx; /* index in filtering table */ +} __packed; + +struct as10x_register_value { + uint8_t mode; + union { + uint8_t value8; /* 8 bit value */ + uint16_t value16; /* 16 bit value */ + uint32_t value32; /* 32 bit value */ + } __packed u; +} __packed; + +struct as10x_register_addr { + /* register addr */ + uint32_t addr; + /* register mode access */ + uint8_t mode; +}; + +#endif diff --git a/drivers/media/dvb-frontends/bcm3510.c b/drivers/media/dvb-frontends/bcm3510.c index 39a29dd29519..638c7aa0fb7e 100644 --- a/drivers/media/dvb-frontends/bcm3510.c +++ b/drivers/media/dvb-frontends/bcm3510.c @@ -639,12 +639,12 @@ static int bcm3510_download_firmware(struct dvb_frontend* fe) err("could not load firmware (%s): %d",BCM3510_DEFAULT_FIRMWARE,ret); return ret; } - deb_info("got firmware: %zd\n",fw->size); + deb_info("got firmware: %zu\n", fw->size); b = fw->data; for (i = 0; i < fw->size;) { - addr = le16_to_cpu( *( (u16 *)&b[i] ) ); - len = le16_to_cpu( *( (u16 *)&b[i+2] ) ); + addr = le16_to_cpu(*((__le16 *)&b[i])); + len = le16_to_cpu(*((__le16 *)&b[i+2])); deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04zx\n",addr,len,fw->size); if ((ret = bcm3510_write_ram(st,addr,&b[i+4],len)) < 0) { err("firmware download failed: %d\n",ret); diff --git a/drivers/media/dvb-frontends/cxd2820r_c.c b/drivers/media/dvb-frontends/cxd2820r_c.c index 0f4657e01cde..149fdca3fb44 100644 --- a/drivers/media/dvb-frontends/cxd2820r_c.c +++ b/drivers/media/dvb-frontends/cxd2820r_c.c @@ -65,7 +65,7 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe) } priv->delivery_system = SYS_DVBC_ANNEX_A; - priv->ber_running = 0; /* tune stops BER counter */ + priv->ber_running = false; /* tune stops BER counter */ /* program IF frequency */ if (fe->ops.tuner_ops.get_if_frequency) { @@ -168,7 +168,7 @@ int cxd2820r_read_ber_c(struct dvb_frontend *fe, u32 *ber) start_ber = 1; } } else { - priv->ber_running = 1; + priv->ber_running = true; start_ber = 1; } diff --git a/drivers/media/dvb-frontends/cxd2820r_core.c b/drivers/media/dvb-frontends/cxd2820r_core.c index 03930d5e9fea..422e84bbb008 100644 --- a/drivers/media/dvb-frontends/cxd2820r_core.c +++ b/drivers/media/dvb-frontends/cxd2820r_core.c @@ -564,10 +564,10 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe) /* check if we have a valid signal */ if (status & FE_HAS_LOCK) { - priv->last_tune_failed = 0; + priv->last_tune_failed = false; return DVBFE_ALGO_SEARCH_SUCCESS; } else { - priv->last_tune_failed = 1; + priv->last_tune_failed = true; return DVBFE_ALGO_SEARCH_AGAIN; } @@ -584,18 +584,14 @@ static int cxd2820r_get_frontend_algo(struct dvb_frontend *fe) static void cxd2820r_release(struct dvb_frontend *fe) { struct cxd2820r_priv *priv = fe->demodulator_priv; - int uninitialized_var(ret); /* silence compiler warning */ dev_dbg(&priv->i2c->dev, "%s\n", __func__); #ifdef CONFIG_GPIOLIB /* remove GPIOs */ - if (priv->gpio_chip.label) { - ret = gpiochip_remove(&priv->gpio_chip); - if (ret) - dev_err(&priv->i2c->dev, "%s: gpiochip_remove() " \ - "failed=%d\n", KBUILD_MODNAME, ret); - } + if (priv->gpio_chip.label) + gpiochip_remove(&priv->gpio_chip); + #endif kfree(priv); return; diff --git a/drivers/media/dvb-frontends/cxd2820r_t.c b/drivers/media/dvb-frontends/cxd2820r_t.c index 9b5a45b907bc..51401d036530 100644 --- a/drivers/media/dvb-frontends/cxd2820r_t.c +++ b/drivers/media/dvb-frontends/cxd2820r_t.c @@ -89,7 +89,7 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe) } priv->delivery_system = SYS_DVBT; - priv->ber_running = 0; /* tune stops BER counter */ + priv->ber_running = false; /* tune stops BER counter */ /* program IF frequency */ if (fe->ops.tuner_ops.get_if_frequency) { @@ -272,7 +272,7 @@ int cxd2820r_read_ber_t(struct dvb_frontend *fe, u32 *ber) start_ber = 1; } } else { - priv->ber_running = 1; + priv->ber_running = true; start_ber = 1; } diff --git a/drivers/media/dvb-frontends/dib7000p.c b/drivers/media/dvb-frontends/dib7000p.c index 661760d60232..589134e95175 100644 --- a/drivers/media/dvb-frontends/dib7000p.c +++ b/drivers/media/dvb-frontends/dib7000p.c @@ -2559,7 +2559,7 @@ static void dib7090_setHostBusMux(struct dib7000p_state *state, int mode) dib7000p_write_word(state, 1288, reg_1288); } -int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff) +static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff) { struct dib7000p_state *state = fe->demodulator_priv; u16 reg_1287; diff --git a/drivers/media/dvb-frontends/drx39xyj/drxj.c b/drivers/media/dvb-frontends/drx39xyj/drxj.c index 7ca7a21df183..5ec221ffdfca 100644 --- a/drivers/media/dvb-frontends/drx39xyj/drxj.c +++ b/drivers/media/dvb-frontends/drx39xyj/drxj.c @@ -2174,7 +2174,7 @@ int drxj_dap_atomic_read_reg32(struct i2c_device_addr *dev_addr, u32 addr, u32 *data, u32 flags) { - u8 buf[sizeof(*data)]; + u8 buf[sizeof(*data)] = { 0 }; int rc = -EIO; u32 word = 0; @@ -4193,7 +4193,7 @@ int drxj_dap_scu_atomic_read_reg16(struct i2c_device_addr *dev_addr, u32 addr, u16 *data, u32 flags) { - u8 buf[2]; + u8 buf[2] = { 0 }; int rc = -EIO; u16 word = 0; @@ -10667,7 +10667,7 @@ ctrl_sig_quality(struct drx_demod_instance *demod, enum drx_standard standard = ext_attr->standard; int rc; u32 ber, cnt, err, pkt; - u16 mer, strength; + u16 mer, strength = 0; rc = get_sig_strength(demod, &strength); if (rc < 0) { @@ -11602,7 +11602,7 @@ static u16 drx_u_code_compute_crc(u8 *block_data, u16 nr_words) u32 carry = 0; while (i < nr_words) { - crc_word |= (u32)be16_to_cpu(*(u32 *)(block_data)); + crc_word |= (u32)be16_to_cpu(*(__be16 *)(block_data)); for (j = 0; j < 16; j++) { crc_word <<= 1; if (carry != 0) @@ -11629,7 +11629,7 @@ static int drx_check_firmware(struct drx_demod_instance *demod, u8 *mc_data, int i; unsigned count = 2 * sizeof(u16); u32 mc_dev_type, mc_version, mc_base_version; - u16 mc_nr_of_blks = be16_to_cpu(*(u32 *)(mc_data + sizeof(u16))); + u16 mc_nr_of_blks = be16_to_cpu(*(__be16 *)(mc_data + sizeof(u16))); /* * Scan microcode blocks first for version info @@ -11647,13 +11647,13 @@ static int drx_check_firmware(struct drx_demod_instance *demod, u8 *mc_data, goto eof; /* Process block header */ - block_hdr.addr = be32_to_cpu(*(u32 *)(mc_data + count)); + block_hdr.addr = be32_to_cpu(*(__be32 *)(mc_data + count)); count += sizeof(u32); - block_hdr.size = be16_to_cpu(*(u32 *)(mc_data + count)); + block_hdr.size = be16_to_cpu(*(__be16 *)(mc_data + count)); count += sizeof(u16); - block_hdr.flags = be16_to_cpu(*(u32 *)(mc_data + count)); + block_hdr.flags = be16_to_cpu(*(__be16 *)(mc_data + count)); count += sizeof(u16); - block_hdr.CRC = be16_to_cpu(*(u32 *)(mc_data + count)); + block_hdr.CRC = be16_to_cpu(*(__be16 *)(mc_data + count)); count += sizeof(u16); pr_debug("%u: addr %u, size %u, flags 0x%04x, CRC 0x%04x\n", @@ -11667,7 +11667,7 @@ static int drx_check_firmware(struct drx_demod_instance *demod, u8 *mc_data, if (block_hdr.addr + sizeof(u16) > size) goto eof; - auxtype = be16_to_cpu(*(u32 *)(auxblk)); + auxtype = be16_to_cpu(*(__be16 *)(auxblk)); /* Aux block. Check type */ if (DRX_ISMCVERTYPE(auxtype)) { @@ -11675,11 +11675,11 @@ static int drx_check_firmware(struct drx_demod_instance *demod, u8 *mc_data, goto eof; auxblk += sizeof(u16); - mc_dev_type = be32_to_cpu(*(u32 *)(auxblk)); + mc_dev_type = be32_to_cpu(*(__be32 *)(auxblk)); auxblk += sizeof(u32); - mc_version = be32_to_cpu(*(u32 *)(auxblk)); + mc_version = be32_to_cpu(*(__be32 *)(auxblk)); auxblk += sizeof(u32); - mc_base_version = be32_to_cpu(*(u32 *)(auxblk)); + mc_base_version = be32_to_cpu(*(__be32 *)(auxblk)); DRX_ATTR_MCRECORD(demod).aux_type = auxtype; DRX_ATTR_MCRECORD(demod).mc_dev_type = mc_dev_type; @@ -11765,9 +11765,9 @@ static int drx_ctrl_u_code(struct drx_demod_instance *demod, mc_data = (void *)mc_data_init; /* Check data */ - mc_magic_word = be16_to_cpu(*(u32 *)(mc_data)); + mc_magic_word = be16_to_cpu(*(__be16 *)(mc_data)); mc_data += sizeof(u16); - mc_nr_of_blks = be16_to_cpu(*(u32 *)(mc_data)); + mc_nr_of_blks = be16_to_cpu(*(__be16 *)(mc_data)); mc_data += sizeof(u16); if ((mc_magic_word != DRX_UCODE_MAGIC_WORD) || (mc_nr_of_blks == 0)) { @@ -11791,13 +11791,13 @@ static int drx_ctrl_u_code(struct drx_demod_instance *demod, u16 mc_block_nr_bytes = 0; /* Process block header */ - block_hdr.addr = be32_to_cpu(*(u32 *)(mc_data)); + block_hdr.addr = be32_to_cpu(*(__be32 *)(mc_data)); mc_data += sizeof(u32); - block_hdr.size = be16_to_cpu(*(u32 *)(mc_data)); + block_hdr.size = be16_to_cpu(*(__be16 *)(mc_data)); mc_data += sizeof(u16); - block_hdr.flags = be16_to_cpu(*(u32 *)(mc_data)); + block_hdr.flags = be16_to_cpu(*(__be16 *)(mc_data)); mc_data += sizeof(u16); - block_hdr.CRC = be16_to_cpu(*(u32 *)(mc_data)); + block_hdr.CRC = be16_to_cpu(*(__be16 *)(mc_data)); mc_data += sizeof(u16); pr_debug("%u: addr %u, size %u, flags 0x%04x, CRC 0x%04x\n", diff --git a/drivers/media/dvb-frontends/drxd_hard.c b/drivers/media/dvb-frontends/drxd_hard.c index ae2276db77bc..687e893d29fe 100644 --- a/drivers/media/dvb-frontends/drxd_hard.c +++ b/drivers/media/dvb-frontends/drxd_hard.c @@ -2628,10 +2628,11 @@ static int DRXD_init(struct drxd_state *state, const u8 *fw, u32 fw_size) break; /* Apply I2c address patch to B1 */ - if (!state->type_A && state->m_HiI2cPatch != NULL) + if (!state->type_A && state->m_HiI2cPatch != NULL) { status = WriteTable(state, state->m_HiI2cPatch); if (status < 0) break; + } if (state->type_A) { /* HI firmware patch for UIO readout, @@ -2830,14 +2831,8 @@ static int drxd_read_status(struct dvb_frontend *fe, fe_status_t * status) static int drxd_init(struct dvb_frontend *fe) { struct drxd_state *state = fe->demodulator_priv; - int err = 0; -/* if (request_firmware(&state->fw, "drxd.fw", state->dev)<0) */ return DRXD_init(state, NULL, 0); - - err = DRXD_init(state, state->fw->data, state->fw->size); - release_firmware(state->fw); - return err; } static int drxd_config_i2c(struct dvb_frontend *fe, int onoff) diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c index cce94a75b2e1..672195147d01 100644 --- a/drivers/media/dvb-frontends/drxk_hard.c +++ b/drivers/media/dvb-frontends/drxk_hard.c @@ -1028,7 +1028,7 @@ static int hi_command(struct drxk_state *state, u16 cmd, u16 *p_result) ((state->m_hi_cfg_ctrl) & SIO_HI_RA_RAM_PAR_5_CFG_SLEEP__M) == SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ); - if (powerdown_cmd == false) { + if (!powerdown_cmd) { /* Wait until command rdy */ u32 retry_count = 0; u16 wait_cmd; @@ -1129,7 +1129,7 @@ static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable) if (status < 0) goto error; - if (mpeg_enable == false) { + if (!mpeg_enable) { /* Set MPEG TS pads to inputmode */ status = write16(state, SIO_PDR_MSTRT_CFG__A, 0x0000); if (status < 0) @@ -1190,7 +1190,7 @@ static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable) if (status < 0) goto error; - if (state->m_enable_parallel == true) { + if (state->m_enable_parallel) { /* parallel -> enable MD1 to MD7 */ status = write16(state, SIO_PDR_MD1_CFG__A, sio_pdr_mdx_cfg); @@ -1392,7 +1392,7 @@ static int dvbt_enable_ofdm_token_ring(struct drxk_state *state, bool enable) dprintk(1, "\n"); - if (enable == false) { + if (!enable) { desired_ctrl = SIO_OFDM_SH_OFDM_RING_ENABLE_OFF; desired_status = SIO_OFDM_SH_OFDM_RING_STATUS_DOWN; } @@ -2012,7 +2012,7 @@ static int mpegts_dto_setup(struct drxk_state *state, goto error; fec_oc_reg_mode &= (~FEC_OC_MODE_PARITY__M); fec_oc_reg_ipr_mode &= (~FEC_OC_IPR_MODE_MVAL_DIS_PAR__M); - if (state->m_insert_rs_byte == true) { + if (state->m_insert_rs_byte) { /* enable parity symbol forward */ fec_oc_reg_mode |= FEC_OC_MODE_PARITY__M; /* MVAL disable during parity bytes */ @@ -2023,7 +2023,7 @@ static int mpegts_dto_setup(struct drxk_state *state, /* Check serial or parallel output */ fec_oc_reg_ipr_mode &= (~(FEC_OC_IPR_MODE_SERIAL__M)); - if (state->m_enable_parallel == false) { + if (!state->m_enable_parallel) { /* MPEG data output is serial -> set ipr_mode[0] */ fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_SERIAL__M; } @@ -2136,19 +2136,19 @@ static int mpegts_configure_polarity(struct drxk_state *state) /* Control selective inversion of output bits */ fec_oc_reg_ipr_invert &= (~(invert_data_mask)); - if (state->m_invert_data == true) + if (state->m_invert_data) fec_oc_reg_ipr_invert |= invert_data_mask; fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MERR__M)); - if (state->m_invert_err == true) + if (state->m_invert_err) fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MERR__M; fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MSTRT__M)); - if (state->m_invert_str == true) + if (state->m_invert_str) fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MSTRT__M; fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MVAL__M)); - if (state->m_invert_val == true) + if (state->m_invert_val) fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MVAL__M; fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MCLK__M)); - if (state->m_invert_clk == true) + if (state->m_invert_clk) fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MCLK__M; return write16(state, FEC_OC_IPR_INVERT__A, fec_oc_reg_ipr_invert); @@ -2220,12 +2220,13 @@ static int set_agc_rf(struct drxk_state *state, } /* Set TOP, only if IF-AGC is in AUTO mode */ - if (p_if_agc_settings->ctrl_mode == DRXK_AGC_CTRL_AUTO) + if (p_if_agc_settings->ctrl_mode == DRXK_AGC_CTRL_AUTO) { status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, p_agc_cfg->top); if (status < 0) goto error; + } /* Cut-Off current */ status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, @@ -3352,7 +3353,7 @@ static int dvbt_ctrl_set_inc_enable(struct drxk_state *state, bool *enabled) int status; dprintk(1, "\n"); - if (*enabled == true) + if (*enabled) status = write16(state, IQM_CF_BYPASSDET__A, 0); else status = write16(state, IQM_CF_BYPASSDET__A, 1); @@ -3368,7 +3369,7 @@ static int dvbt_ctrl_set_fr_enable(struct drxk_state *state, bool *enabled) int status; dprintk(1, "\n"); - if (*enabled == true) { + if (*enabled) { /* write mask to 1 */ status = write16(state, OFDM_SC_RA_RAM_FR_THRES_8K__A, DEFAULT_FR_THRES_8K); @@ -6794,11 +6795,11 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config, state->enable_merr_cfg = config->enable_merr_cfg; if (config->dynamic_clk) { - state->m_dvbt_static_clk = 0; - state->m_dvbc_static_clk = 0; + state->m_dvbt_static_clk = false; + state->m_dvbc_static_clk = false; } else { - state->m_dvbt_static_clk = 1; - state->m_dvbc_static_clk = 1; + state->m_dvbt_static_clk = true; + state->m_dvbc_static_clk = true; } diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c index dfe0c2f7f1ef..81657e94c5a4 100644 --- a/drivers/media/dvb-frontends/m88ds3103.c +++ b/drivers/media/dvb-frontends/m88ds3103.c @@ -159,6 +159,7 @@ static int m88ds3103_wr_reg_val_tab(struct m88ds3103_priv *priv, { int ret, i, j; u8 buf[83]; + dev_dbg(&priv->i2c->dev, "%s: tab_len=%d\n", __func__, tab_len); if (tab_len > 83) { @@ -247,8 +248,9 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) u8 u8tmp, u8tmp1, u8tmp2; u8 buf[2]; u16 u16tmp, divide_ratio; - u32 tuner_frequency, target_mclk, ts_clk; + u32 tuner_frequency, target_mclk; s32 s32tmp; + 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, @@ -316,9 +318,6 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) target_mclk = 144000; break; case M88DS3103_TS_PARALLEL: - case M88DS3103_TS_PARALLEL_12: - case M88DS3103_TS_PARALLEL_16: - case M88DS3103_TS_PARALLEL_19_2: case M88DS3103_TS_CI: if (c->symbol_rate < 18000000) target_mclk = 96000; @@ -352,33 +351,17 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) switch (priv->cfg->ts_mode) { case M88DS3103_TS_SERIAL: u8tmp1 = 0x00; - ts_clk = 0; - u8tmp = 0x46; + u8tmp = 0x06; break; case M88DS3103_TS_SERIAL_D7: u8tmp1 = 0x20; - ts_clk = 0; - u8tmp = 0x46; + u8tmp = 0x06; break; case M88DS3103_TS_PARALLEL: - ts_clk = 24000; - u8tmp = 0x42; - break; - case M88DS3103_TS_PARALLEL_12: - ts_clk = 12000; - u8tmp = 0x42; - break; - case M88DS3103_TS_PARALLEL_16: - ts_clk = 16000; - u8tmp = 0x42; - break; - case M88DS3103_TS_PARALLEL_19_2: - ts_clk = 19200; - u8tmp = 0x42; + u8tmp = 0x02; break; case M88DS3103_TS_CI: - ts_clk = 6000; - u8tmp = 0x43; + u8tmp = 0x03; break; default: dev_dbg(&priv->i2c->dev, "%s: invalid ts_mode\n", __func__); @@ -386,6 +369,9 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) goto err; } + if (priv->cfg->ts_clk_pol) + u8tmp |= 0x40; + /* TS mode */ ret = m88ds3103_wr_reg(priv, 0xfd, u8tmp); if (ret) @@ -399,8 +385,8 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) goto err; } - if (ts_clk) { - divide_ratio = DIV_ROUND_UP(target_mclk, ts_clk); + if (priv->cfg->ts_clk) { + divide_ratio = DIV_ROUND_UP(target_mclk, priv->cfg->ts_clk); u8tmp1 = divide_ratio / 2; u8tmp2 = DIV_ROUND_UP(divide_ratio, 2); } else { @@ -411,7 +397,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) dev_dbg(&priv->i2c->dev, "%s: target_mclk=%d ts_clk=%d divide_ratio=%d\n", - __func__, target_mclk, ts_clk, divide_ratio); + __func__, target_mclk, priv->cfg->ts_clk, divide_ratio); u8tmp1--; u8tmp2--; @@ -536,6 +522,7 @@ static int m88ds3103_init(struct dvb_frontend *fe) const struct firmware *fw = NULL; u8 *fw_file = M88DS3103_FIRMWARE; u8 u8tmp; + dev_dbg(&priv->i2c->dev, "%s:\n", __func__); /* set cold state by default */ @@ -648,6 +635,7 @@ static int m88ds3103_sleep(struct dvb_frontend *fe) { struct m88ds3103_priv *priv = fe->demodulator_priv; int ret; + dev_dbg(&priv->i2c->dev, "%s:\n", __func__); priv->delivery_system = SYS_UNDEFINED; @@ -682,6 +670,7 @@ static int m88ds3103_get_frontend(struct dvb_frontend *fe) struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[3]; + dev_dbg(&priv->i2c->dev, "%s:\n", __func__); if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) { @@ -857,6 +846,7 @@ static int m88ds3103_read_snr(struct dvb_frontend *fe, u16 *snr) u8 buf[3]; u16 noise, signal; u32 noise_tot, signal_tot; + dev_dbg(&priv->i2c->dev, "%s:\n", __func__); /* reports SNR in resolution of 0.1 dB */ @@ -933,6 +923,7 @@ static int m88ds3103_read_ber(struct dvb_frontend *fe, u32 *ber) int ret; unsigned int utmp; u8 buf[3], u8tmp; + dev_dbg(&priv->i2c->dev, "%s:\n", __func__); switch (c->delivery_system) { @@ -1013,6 +1004,7 @@ static int m88ds3103_set_tone(struct dvb_frontend *fe, struct m88ds3103_priv *priv = fe->demodulator_priv; int ret; u8 u8tmp, tone, reg_a1_mask; + dev_dbg(&priv->i2c->dev, "%s: fe_sec_tone_mode=%d\n", __func__, fe_sec_tone_mode); @@ -1053,12 +1045,64 @@ err: return ret; } +static int m88ds3103_set_voltage(struct dvb_frontend *fe, + fe_sec_voltage_t fe_sec_voltage) +{ + struct m88ds3103_priv *priv = fe->demodulator_priv; + int ret; + u8 u8tmp; + bool voltage_sel, voltage_dis; + + dev_dbg(&priv->i2c->dev, "%s: fe_sec_voltage=%d\n", __func__, + fe_sec_voltage); + + if (!priv->warm) { + ret = -EAGAIN; + goto err; + } + + switch (fe_sec_voltage) { + case SEC_VOLTAGE_18: + voltage_sel = true; + voltage_dis = false; + break; + case SEC_VOLTAGE_13: + voltage_sel = false; + voltage_dis = false; + break; + case SEC_VOLTAGE_OFF: + voltage_sel = false; + voltage_dis = true; + break; + default: + dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_voltage\n", + __func__); + ret = -EINVAL; + goto err; + } + + /* output pin polarity */ + voltage_sel ^= priv->cfg->lnb_hv_pol; + voltage_dis ^= priv->cfg->lnb_en_pol; + + u8tmp = voltage_dis << 1 | voltage_sel << 0; + ret = m88ds3103_wr_reg_mask(priv, 0xa2, u8tmp, 0x03); + if (ret) + goto err; + + return 0; +err: + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + return ret; +} + static int m88ds3103_diseqc_send_master_cmd(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *diseqc_cmd) { struct m88ds3103_priv *priv = fe->demodulator_priv; int ret, i; u8 u8tmp; + dev_dbg(&priv->i2c->dev, "%s: msg=%*ph\n", __func__, diseqc_cmd->msg_len, diseqc_cmd->msg); @@ -1130,6 +1174,7 @@ static int m88ds3103_diseqc_send_burst(struct dvb_frontend *fe, struct m88ds3103_priv *priv = fe->demodulator_priv; int ret, i; u8 u8tmp, burst; + dev_dbg(&priv->i2c->dev, "%s: fe_sec_mini_cmd=%d\n", __func__, fe_sec_mini_cmd); @@ -1202,6 +1247,7 @@ static int m88ds3103_get_tune_settings(struct dvb_frontend *fe, static void m88ds3103_release(struct dvb_frontend *fe) { struct m88ds3103_priv *priv = fe->demodulator_priv; + i2c_del_mux_adapter(priv->i2c_adapter); kfree(priv); } @@ -1370,6 +1416,7 @@ static struct dvb_frontend_ops m88ds3103_ops = { .diseqc_send_burst = m88ds3103_diseqc_send_burst, .set_tone = m88ds3103_set_tone, + .set_voltage = m88ds3103_set_voltage, }; MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); diff --git a/drivers/media/dvb-frontends/m88ds3103.h b/drivers/media/dvb-frontends/m88ds3103.h index bbb7e3aa5675..9b3b4962da7c 100644 --- a/drivers/media/dvb-frontends/m88ds3103.h +++ b/drivers/media/dvb-frontends/m88ds3103.h @@ -47,14 +47,23 @@ struct m88ds3103_config { */ #define M88DS3103_TS_SERIAL 0 /* TS output pin D0, normal */ #define M88DS3103_TS_SERIAL_D7 1 /* TS output pin D7 */ -#define M88DS3103_TS_PARALLEL 2 /* 24 MHz, normal */ -#define M88DS3103_TS_PARALLEL_12 3 /* 12 MHz */ -#define M88DS3103_TS_PARALLEL_16 4 /* 16 MHz */ -#define M88DS3103_TS_PARALLEL_19_2 5 /* 19.2 MHz */ -#define M88DS3103_TS_CI 6 /* 6 MHz */ +#define M88DS3103_TS_PARALLEL 2 /* TS Parallel mode */ +#define M88DS3103_TS_CI 3 /* TS CI Mode */ u8 ts_mode; /* + * TS clk in KHz + * Default: 0. + */ + u32 ts_clk; + + /* + * TS clk polarity. + * Default: 0. 1-active at falling edge; 0-active at rising edge. + */ + u8 ts_clk_pol:1; + + /* * spectrum inversion * Default: 0 */ @@ -86,6 +95,22 @@ struct m88ds3103_config { * Default: none, must set */ u8 agc; + + /* + * LNB H/V pin polarity + * Default: 0. + * 1: pin high set to VOLTAGE_13, pin low to set VOLTAGE_18. + * 0: pin high set to VOLTAGE_18, pin low to set VOLTAGE_13. + */ + u8 lnb_hv_pol:1; + + /* + * LNB enable pin polarity + * Default: 0. + * 1: pin high to enable, pin low to disable. + * 0: pin high to disable, pin low to enable. + */ + u8 lnb_en_pol:1; }; /* diff --git a/drivers/media/dvb-frontends/mb86a16.c b/drivers/media/dvb-frontends/mb86a16.c index 9ae40abfd71a..3ddea4471d2b 100644 --- a/drivers/media/dvb-frontends/mb86a16.c +++ b/drivers/media/dvb-frontends/mb86a16.c @@ -28,7 +28,7 @@ #include "mb86a16.h" #include "mb86a16_priv.h" -unsigned int verbose = 5; +static unsigned int verbose = 5; module_param(verbose, int, 0644); #define ABS(x) ((x) < 0 ? (-x) : (x)) @@ -115,9 +115,11 @@ static int mb86a16_read(struct mb86a16_state *state, u8 reg, u8 *val) }; ret = i2c_transfer(state->i2c_adap, msg, 2); if (ret != 2) { - dprintk(verbose, MB86A16_ERROR, 1, "read error(reg=0x%02x, ret=0x%i)", + dprintk(verbose, MB86A16_ERROR, 1, "read error(reg=0x%02x, ret=%i)", reg, ret); + if (ret < 0) + return ret; return -EREMOTEIO; } *val = b1[0]; diff --git a/drivers/media/dvb-frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c index b931179c70a4..e6f165a5b90d 100644 --- a/drivers/media/dvb-frontends/mb86a20s.c +++ b/drivers/media/dvb-frontends/mb86a20s.c @@ -33,7 +33,7 @@ enum mb86a20s_bandwidth { MB86A20S_3SEG = 3, }; -u8 mb86a20s_subchannel[] = { +static u8 mb86a20s_subchannel[] = { 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0x00, 0x10, 0x20, }; @@ -1228,7 +1228,7 @@ struct linear_segments { * All tables below return a dB/1000 measurement */ -static struct linear_segments cnr_to_db_table[] = { +static const struct linear_segments cnr_to_db_table[] = { { 19648, 0}, { 18187, 1000}, { 16534, 2000}, @@ -1262,7 +1262,7 @@ static struct linear_segments cnr_to_db_table[] = { { 788, 30000}, }; -static struct linear_segments cnr_64qam_table[] = { +static const struct linear_segments cnr_64qam_table[] = { { 3922688, 0}, { 3920384, 1000}, { 3902720, 2000}, @@ -1296,7 +1296,7 @@ static struct linear_segments cnr_64qam_table[] = { { 388864, 30000}, }; -static struct linear_segments cnr_16qam_table[] = { +static const struct linear_segments cnr_16qam_table[] = { { 5314816, 0}, { 5219072, 1000}, { 5118720, 2000}, @@ -1330,7 +1330,7 @@ static struct linear_segments cnr_16qam_table[] = { { 95744, 30000}, }; -struct linear_segments cnr_qpsk_table[] = { +static const struct linear_segments cnr_qpsk_table[] = { { 2834176, 0}, { 2683648, 1000}, { 2536960, 2000}, @@ -1364,7 +1364,7 @@ struct linear_segments cnr_qpsk_table[] = { { 11520, 30000}, }; -static u32 interpolate_value(u32 value, struct linear_segments *segments, +static u32 interpolate_value(u32 value, const struct linear_segments *segments, unsigned len) { u64 tmp64; @@ -1448,7 +1448,7 @@ static int mb86a20s_get_blk_error_layer_CNR(struct dvb_frontend *fe) struct dtv_frontend_properties *c = &fe->dtv_property_cache; u32 mer, cnr; int rc, val, layer; - struct linear_segments *segs; + const struct linear_segments *segs; unsigned segs_len; dev_dbg(&state->i2c->dev, "%s called.\n", __func__); diff --git a/drivers/media/dvb-frontends/mt312.c b/drivers/media/dvb-frontends/mt312.c index a74ac0ddb833..2163490c1e6b 100644 --- a/drivers/media/dvb-frontends/mt312.c +++ b/drivers/media/dvb-frontends/mt312.c @@ -103,7 +103,7 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg, if (1 + count > sizeof(buf)) { printk(KERN_WARNING - "mt312: write: len=%zd is too big!\n", count); + "mt312: write: len=%zu is too big!\n", count); return -EINVAL; } diff --git a/drivers/media/dvb-frontends/or51211.c b/drivers/media/dvb-frontends/or51211.c index 10cfc0579168..873ea1da844b 100644 --- a/drivers/media/dvb-frontends/or51211.c +++ b/drivers/media/dvb-frontends/or51211.c @@ -111,7 +111,7 @@ static int or51211_load_firmware (struct dvb_frontend* fe, u8 tudata[585]; int i; - dprintk("Firmware is %zd bytes\n",fw->size); + dprintk("Firmware is %zu bytes\n", fw->size); /* Get eprom data */ tudata[0] = 17; diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index fdbed35c87fa..eb737cf29a36 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -936,7 +936,7 @@ static void rtl2832_i2c_gate_work(struct work_struct *work) if (ret != 1) goto err; - priv->i2c_gate_state = 0; + priv->i2c_gate_state = false; return; err: diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c index 023e0f49c786..7bf98cf6bbe1 100644 --- a/drivers/media/dvb-frontends/rtl2832_sdr.c +++ b/drivers/media/dvb-frontends/rtl2832_sdr.c @@ -329,7 +329,7 @@ static int rtl2832_sdr_rd_reg_mask(struct rtl2832_sdr_state *s, u16 reg, static struct rtl2832_sdr_frame_buf *rtl2832_sdr_get_next_fill_buf( struct rtl2832_sdr_state *s) { - unsigned long flags = 0; + unsigned long flags; struct rtl2832_sdr_frame_buf *buf = NULL; spin_lock_irqsave(&s->queued_bufs_lock, flags); @@ -365,17 +365,19 @@ static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_state *s, dst_len = 0; } - /* calculate samping rate and output it in 10 seconds intervals */ + /* calculate sample rate and output it in 10 seconds intervals */ if (unlikely(time_is_before_jiffies(s->jiffies_next))) { -#define MSECS 10000UL + #define MSECS 10000UL + unsigned int msecs = jiffies_to_msecs(jiffies - + s->jiffies_next + msecs_to_jiffies(MSECS)); unsigned int samples = s->sample - s->sample_measured; s->jiffies_next = jiffies + msecs_to_jiffies(MSECS); s->sample_measured = s->sample; dev_dbg(&s->udev->dev, - "slen=%d samples=%u msecs=%lu sampling rate=%lu\n", - src_len, samples, MSECS, - samples * 1000UL / MSECS); + "slen=%u samples=%u msecs=%u sample rate=%lu\n", + src_len, samples, msecs, + samples * 1000UL / msecs); } /* total number of I+Q pairs */ @@ -394,8 +396,8 @@ static void rtl2832_sdr_urb_complete(struct urb *urb) struct rtl2832_sdr_frame_buf *fbuf; dev_dbg_ratelimited(&s->udev->dev, - "%s: status=%d length=%d/%d errors=%d\n", - __func__, urb->status, urb->actual_length, + "status=%d length=%d/%d errors=%d\n", + urb->status, urb->actual_length, urb->transfer_buffer_length, urb->error_count); switch (urb->status) { @@ -443,7 +445,7 @@ static int rtl2832_sdr_kill_urbs(struct rtl2832_sdr_state *s) int i; for (i = s->urbs_submitted - 1; i >= 0; i--) { - dev_dbg(&s->udev->dev, "%s: kill urb=%d\n", __func__, i); + dev_dbg(&s->udev->dev, "kill urb=%d\n", i); /* stop the URB */ usb_kill_urb(s->urb_list[i]); } @@ -457,7 +459,7 @@ static int rtl2832_sdr_submit_urbs(struct rtl2832_sdr_state *s) int i, ret; for (i = 0; i < s->urbs_initialized; i++) { - dev_dbg(&s->udev->dev, "%s: submit urb=%d\n", __func__, i); + dev_dbg(&s->udev->dev, "submit urb=%d\n", i); ret = usb_submit_urb(s->urb_list[i], GFP_ATOMIC); if (ret) { dev_err(&s->udev->dev, @@ -477,8 +479,7 @@ static int rtl2832_sdr_free_stream_bufs(struct rtl2832_sdr_state *s) if (s->flags & USB_STATE_URB_BUF) { while (s->buf_num) { s->buf_num--; - dev_dbg(&s->udev->dev, "%s: free buf=%d\n", - __func__, s->buf_num); + dev_dbg(&s->udev->dev, "free buf=%d\n", s->buf_num); usb_free_coherent(s->udev, s->buf_size, s->buf_list[s->buf_num], s->dma_addr[s->buf_num]); @@ -494,24 +495,22 @@ static int rtl2832_sdr_alloc_stream_bufs(struct rtl2832_sdr_state *s) s->buf_num = 0; s->buf_size = BULK_BUFFER_SIZE; - dev_dbg(&s->udev->dev, - "%s: all in all I will use %u bytes for streaming\n", - __func__, MAX_BULK_BUFS * BULK_BUFFER_SIZE); + dev_dbg(&s->udev->dev, "all in all I will use %u bytes for streaming\n", + MAX_BULK_BUFS * BULK_BUFFER_SIZE); for (s->buf_num = 0; s->buf_num < MAX_BULK_BUFS; s->buf_num++) { s->buf_list[s->buf_num] = usb_alloc_coherent(s->udev, BULK_BUFFER_SIZE, GFP_ATOMIC, &s->dma_addr[s->buf_num]); if (!s->buf_list[s->buf_num]) { - dev_dbg(&s->udev->dev, "%s: alloc buf=%d failed\n", - __func__, s->buf_num); + dev_dbg(&s->udev->dev, "alloc buf=%d failed\n", + s->buf_num); rtl2832_sdr_free_stream_bufs(s); return -ENOMEM; } - dev_dbg(&s->udev->dev, "%s: alloc buf=%d %p (dma %llu)\n", - __func__, s->buf_num, - s->buf_list[s->buf_num], + dev_dbg(&s->udev->dev, "alloc buf=%d %p (dma %llu)\n", + s->buf_num, s->buf_list[s->buf_num], (long long)s->dma_addr[s->buf_num]); s->flags |= USB_STATE_URB_BUF; } @@ -527,8 +526,7 @@ static int rtl2832_sdr_free_urbs(struct rtl2832_sdr_state *s) for (i = s->urbs_initialized - 1; i >= 0; i--) { if (s->urb_list[i]) { - dev_dbg(&s->udev->dev, "%s: free urb=%d\n", - __func__, i); + dev_dbg(&s->udev->dev, "free urb=%d\n", i); /* free the URBs */ usb_free_urb(s->urb_list[i]); } @@ -544,10 +542,10 @@ static int rtl2832_sdr_alloc_urbs(struct rtl2832_sdr_state *s) /* allocate the URBs */ for (i = 0; i < MAX_BULK_BUFS; i++) { - dev_dbg(&s->udev->dev, "%s: alloc urb=%d\n", __func__, i); + dev_dbg(&s->udev->dev, "alloc urb=%d\n", i); s->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC); if (!s->urb_list[i]) { - dev_dbg(&s->udev->dev, "%s: failed\n", __func__); + dev_dbg(&s->udev->dev, "failed\n"); for (j = 0; j < i; j++) usb_free_urb(s->urb_list[j]); return -ENOMEM; @@ -570,9 +568,9 @@ static int rtl2832_sdr_alloc_urbs(struct rtl2832_sdr_state *s) /* Must be called with vb_queue_lock hold */ static void rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_state *s) { - unsigned long flags = 0; + unsigned long flags; - dev_dbg(&s->udev->dev, "%s:\n", __func__); + dev_dbg(&s->udev->dev, "\n"); spin_lock_irqsave(&s->queued_bufs_lock, flags); while (!list_empty(&s->queued_bufs)) { @@ -591,7 +589,7 @@ static void rtl2832_sdr_release_sec(struct dvb_frontend *fe) { struct rtl2832_sdr_state *s = fe->sec_priv; - dev_dbg(&s->udev->dev, "%s:\n", __func__); + dev_dbg(&s->udev->dev, "\n"); mutex_lock(&s->vb_queue_lock); mutex_lock(&s->v4l2_lock); @@ -613,7 +611,7 @@ static int rtl2832_sdr_querycap(struct file *file, void *fh, { struct rtl2832_sdr_state *s = video_drvdata(file); - dev_dbg(&s->udev->dev, "%s:\n", __func__); + dev_dbg(&s->udev->dev, "\n"); strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); strlcpy(cap->card, s->vdev.name, sizeof(cap->card)); @@ -631,15 +629,15 @@ static int rtl2832_sdr_queue_setup(struct vb2_queue *vq, { struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq); - dev_dbg(&s->udev->dev, "%s: *nbuffers=%d\n", __func__, *nbuffers); + dev_dbg(&s->udev->dev, "nbuffers=%d\n", *nbuffers); /* Need at least 8 buffers */ if (vq->num_buffers + *nbuffers < 8) *nbuffers = 8 - vq->num_buffers; *nplanes = 1; sizes[0] = PAGE_ALIGN(s->buffersize); - dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n", - __func__, *nbuffers, sizes[0]); + dev_dbg(&s->udev->dev, "nbuffers=%d sizes[0]=%d\n", + *nbuffers, sizes[0]); return 0; } @@ -659,7 +657,7 @@ static void rtl2832_sdr_buf_queue(struct vb2_buffer *vb) struct rtl2832_sdr_state *s = vb2_get_drv_priv(vb->vb2_queue); struct rtl2832_sdr_frame_buf *buf = container_of(vb, struct rtl2832_sdr_frame_buf, vb); - unsigned long flags = 0; + unsigned long flags; /* Check the device has not disconnected between prep and queuing */ if (!s->udev) { @@ -681,7 +679,7 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s) u64 u64tmp; u32 u32tmp; - dev_dbg(&s->udev->dev, "%s: f_adc=%u\n", __func__, s->f_adc); + dev_dbg(&s->udev->dev, "f_adc=%u\n", s->f_adc); if (!test_bit(POWER_ON, &s->flags)) return 0; @@ -715,8 +713,7 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s) u64tmp = -u64tmp; u32tmp = u64tmp & 0x3fffff; - dev_dbg(&s->udev->dev, "%s: f_if=%u if_ctl=%08x\n", - __func__, f_if, u32tmp); + dev_dbg(&s->udev->dev, "f_if=%u if_ctl=%08x\n", f_if, u32tmp); buf[0] = (u32tmp >> 16) & 0xff; buf[1] = (u32tmp >> 8) & 0xff; @@ -903,7 +900,7 @@ static void rtl2832_sdr_unset_adc(struct rtl2832_sdr_state *s) { int ret; - dev_dbg(&s->udev->dev, "%s:\n", __func__); + dev_dbg(&s->udev->dev, "\n"); /* PID filter */ ret = rtl2832_sdr_wr_regs(s, 0x061, "\xe0", 1); @@ -964,8 +961,8 @@ static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_state *s) c->frequency = s->f_tuner; c->delivery_system = SYS_DVBT; - dev_dbg(&s->udev->dev, "%s: frequency=%u bandwidth=%d\n", - __func__, c->frequency, c->bandwidth_hz); + dev_dbg(&s->udev->dev, "frequency=%u bandwidth=%d\n", + c->frequency, c->bandwidth_hz); if (!test_bit(POWER_ON, &s->flags)) return 0; @@ -980,7 +977,7 @@ static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s) { struct dvb_frontend *fe = s->fe; - dev_dbg(&s->udev->dev, "%s:\n", __func__); + dev_dbg(&s->udev->dev, "\n"); if (fe->ops.tuner_ops.init) fe->ops.tuner_ops.init(fe); @@ -992,7 +989,7 @@ static void rtl2832_sdr_unset_tuner(struct rtl2832_sdr_state *s) { struct dvb_frontend *fe = s->fe; - dev_dbg(&s->udev->dev, "%s:\n", __func__); + dev_dbg(&s->udev->dev, "\n"); if (fe->ops.tuner_ops.sleep) fe->ops.tuner_ops.sleep(fe); @@ -1005,7 +1002,7 @@ static int rtl2832_sdr_start_streaming(struct vb2_queue *vq, unsigned int count) struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq); int ret; - dev_dbg(&s->udev->dev, "%s:\n", __func__); + dev_dbg(&s->udev->dev, "\n"); if (!s->udev) return -ENODEV; @@ -1054,7 +1051,7 @@ static void rtl2832_sdr_stop_streaming(struct vb2_queue *vq) { struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq); - dev_dbg(&s->udev->dev, "%s:\n", __func__); + dev_dbg(&s->udev->dev, "\n"); mutex_lock(&s->v4l2_lock); @@ -1088,8 +1085,7 @@ static int rtl2832_sdr_g_tuner(struct file *file, void *priv, { struct rtl2832_sdr_state *s = video_drvdata(file); - dev_dbg(&s->udev->dev, "%s: index=%d type=%d\n", - __func__, v->index, v->type); + dev_dbg(&s->udev->dev, "index=%d type=%d\n", v->index, v->type); if (v->index == 0) { strlcpy(v->name, "ADC: Realtek RTL2832", sizeof(v->name)); @@ -1115,7 +1111,7 @@ static int rtl2832_sdr_s_tuner(struct file *file, void *priv, { struct rtl2832_sdr_state *s = video_drvdata(file); - dev_dbg(&s->udev->dev, "%s:\n", __func__); + dev_dbg(&s->udev->dev, "\n"); if (v->index > 1) return -EINVAL; @@ -1127,8 +1123,8 @@ static int rtl2832_sdr_enum_freq_bands(struct file *file, void *priv, { struct rtl2832_sdr_state *s = video_drvdata(file); - dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d index=%d\n", - __func__, band->tuner, band->type, band->index); + dev_dbg(&s->udev->dev, "tuner=%d type=%d index=%d\n", + band->tuner, band->type, band->index); if (band->tuner == 0) { if (band->index >= ARRAY_SIZE(bands_adc)) @@ -1153,8 +1149,8 @@ static int rtl2832_sdr_g_frequency(struct file *file, void *priv, struct rtl2832_sdr_state *s = video_drvdata(file); int ret = 0; - dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d\n", - __func__, f->tuner, f->type); + dev_dbg(&s->udev->dev, "tuner=%d type=%d\n", + f->tuner, f->type); if (f->tuner == 0) { f->frequency = s->f_adc; @@ -1175,8 +1171,8 @@ static int rtl2832_sdr_s_frequency(struct file *file, void *priv, struct rtl2832_sdr_state *s = video_drvdata(file); int ret, band; - dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d frequency=%u\n", - __func__, f->tuner, f->type, f->frequency); + dev_dbg(&s->udev->dev, "tuner=%d type=%d frequency=%u\n", + f->tuner, f->type, f->frequency); /* ADC band midpoints */ #define BAND_ADC_0 ((bands_adc[0].rangehigh + bands_adc[1].rangelow) / 2) @@ -1194,15 +1190,13 @@ static int rtl2832_sdr_s_frequency(struct file *file, void *priv, bands_adc[band].rangelow, bands_adc[band].rangehigh); - dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n", - __func__, s->f_adc); + dev_dbg(&s->udev->dev, "ADC frequency=%u Hz\n", s->f_adc); ret = rtl2832_sdr_set_adc(s); } else if (f->tuner == 1) { s->f_tuner = clamp_t(unsigned int, f->frequency, bands_fm[0].rangelow, bands_fm[0].rangehigh); - dev_dbg(&s->udev->dev, "%s: RF frequency=%u Hz\n", - __func__, f->frequency); + dev_dbg(&s->udev->dev, "RF frequency=%u Hz\n", f->frequency); ret = rtl2832_sdr_set_tuner_freq(s); } else { @@ -1217,7 +1211,7 @@ static int rtl2832_sdr_enum_fmt_sdr_cap(struct file *file, void *priv, { struct rtl2832_sdr_state *s = video_drvdata(file); - dev_dbg(&s->udev->dev, "%s:\n", __func__); + dev_dbg(&s->udev->dev, "\n"); if (f->index >= s->num_formats) return -EINVAL; @@ -1233,7 +1227,7 @@ static int rtl2832_sdr_g_fmt_sdr_cap(struct file *file, void *priv, { struct rtl2832_sdr_state *s = video_drvdata(file); - dev_dbg(&s->udev->dev, "%s:\n", __func__); + dev_dbg(&s->udev->dev, "\n"); f->fmt.sdr.pixelformat = s->pixelformat; f->fmt.sdr.buffersize = s->buffersize; @@ -1250,7 +1244,7 @@ static int rtl2832_sdr_s_fmt_sdr_cap(struct file *file, void *priv, struct vb2_queue *q = &s->vb_queue; int i; - dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__, + dev_dbg(&s->udev->dev, "pixelformat fourcc %4.4s\n", (char *)&f->fmt.sdr.pixelformat); if (vb2_is_busy(q)) @@ -1280,7 +1274,7 @@ static int rtl2832_sdr_try_fmt_sdr_cap(struct file *file, void *priv, struct rtl2832_sdr_state *s = video_drvdata(file); int i; - dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__, + dev_dbg(&s->udev->dev, "pixelformat fourcc %4.4s\n", (char *)&f->fmt.sdr.pixelformat); memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved)); @@ -1354,8 +1348,8 @@ static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl) int ret; dev_dbg(&s->udev->dev, - "%s: id=%d name=%s val=%d min=%lld max=%lld step=%lld\n", - __func__, ctrl->id, ctrl->name, ctrl->val, + "id=%d name=%s val=%d min=%lld max=%lld step=%lld\n", + ctrl->id, ctrl->name, ctrl->val, ctrl->minimum, ctrl->maximum, ctrl->step); switch (ctrl->id) { @@ -1432,7 +1426,7 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe, s->pixelformat = formats[0].pixelformat; s->buffersize = formats[0].buffersize; s->num_formats = NUM_FORMATS; - if (rtl2832_sdr_emulated_fmt == false) + if (!rtl2832_sdr_emulated_fmt) s->num_formats -= 1; mutex_init(&s->v4l2_lock); diff --git a/drivers/media/dvb-frontends/si2165.c b/drivers/media/dvb-frontends/si2165.c index 3a2d6c5aded6..98ddb49ad52b 100644 --- a/drivers/media/dvb-frontends/si2165.c +++ b/drivers/media/dvb-frontends/si2165.c @@ -1,5 +1,5 @@ /* - Driver for Silicon Labs SI2165 DVB-C/-T Demodulator + Driver for Silicon Labs Si2161 DVB-T and Si2165 DVB-C/-T Demodulator Copyright (C) 2013-2014 Matthias Schwarzott <zzam@gentoo.org> @@ -44,9 +44,7 @@ struct si2165_state { struct si2165_config config; - /* chip revision */ - u8 revcode; - /* chip type */ + u8 chip_revcode; u8 chip_type; /* calculated by xtal and div settings */ @@ -312,7 +310,7 @@ static u32 si2165_get_fe_clk(struct si2165_state *state) return state->adc_clk; } -static bool si2165_wait_init_done(struct si2165_state *state) +static int si2165_wait_init_done(struct si2165_state *state) { int ret = -EINVAL; u8 val = 0; @@ -407,7 +405,7 @@ static int si2165_upload_firmware(struct si2165_state *state) int ret; const struct firmware *fw = NULL; - u8 *fw_file = SI2165_FIRMWARE; + u8 *fw_file; const u8 *data; u32 len; u32 offset; @@ -415,10 +413,20 @@ static int si2165_upload_firmware(struct si2165_state *state) u8 block_count; u16 crc_expected; + switch (state->chip_revcode) { + case 0x03: /* revision D */ + fw_file = SI2165_FIRMWARE_REV_D; + break; + default: + dev_info(&state->i2c->dev, "%s: no firmware file for revision=%d\n", + KBUILD_MODNAME, state->chip_revcode); + return 0; + } + /* request the firmware, this will block and timeout */ ret = request_firmware(&fw, fw_file, state->i2c->dev.parent); if (ret) { - dev_warn(&state->i2c->dev, "%s: firmare file '%s' not found\n", + dev_warn(&state->i2c->dev, "%s: firmware file '%s' not found\n", KBUILD_MODNAME, fw_file); goto error; } @@ -908,7 +916,7 @@ static void si2165_release(struct dvb_frontend *fe) static struct dvb_frontend_ops si2165_ops = { .info = { - .name = "Silicon Labs Si2165", + .name = "Silicon Labs ", .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | @@ -948,6 +956,8 @@ struct dvb_frontend *si2165_attach(const struct si2165_config *config, int n; int io_ret; u8 val; + char rev_char; + const char *chip_name; if (config == NULL || i2c == NULL) goto error; @@ -984,7 +994,7 @@ struct dvb_frontend *si2165_attach(const struct si2165_config *config, if (val != state->config.chip_mode) goto error; - io_ret = si2165_readreg8(state, 0x0023 , &state->revcode); + io_ret = si2165_readreg8(state, 0x0023, &state->chip_revcode); if (io_ret < 0) goto error; @@ -997,22 +1007,35 @@ struct dvb_frontend *si2165_attach(const struct si2165_config *config, if (io_ret < 0) goto error; - dev_info(&state->i2c->dev, "%s: hardware revision 0x%02x, chip type 0x%02x\n", - KBUILD_MODNAME, state->revcode, state->chip_type); + if (state->chip_revcode < 26) + rev_char = 'A' + state->chip_revcode; + else + rev_char = '?'; - /* It is a guess that register 0x0118 (chip type?) can be used to - * differ between si2161, si2163 and si2165 - * Only si2165 has been tested. - */ - if (state->revcode == 0x03 && state->chip_type == 0x07) { + switch (state->chip_type) { + case 0x06: + chip_name = "Si2161"; + state->has_dvbt = true; + break; + case 0x07: + chip_name = "Si2165"; state->has_dvbt = true; state->has_dvbc = true; - } else { - dev_err(&state->i2c->dev, "%s: Unsupported chip.\n", - KBUILD_MODNAME); + break; + default: + dev_err(&state->i2c->dev, "%s: Unsupported Silicon Labs chip (type %d, rev %d)\n", + KBUILD_MODNAME, state->chip_type, state->chip_revcode); goto error; } + dev_info(&state->i2c->dev, + "%s: Detected Silicon Labs %s-%c (type %d, rev %d)\n", + KBUILD_MODNAME, chip_name, rev_char, state->chip_type, + state->chip_revcode); + + strlcat(state->frontend.ops.info.name, chip_name, + sizeof(state->frontend.ops.info.name)); + n = 0; if (state->has_dvbt) { state->frontend.ops.delsys[n++] = SYS_DVBT; @@ -1037,4 +1060,4 @@ MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); MODULE_DESCRIPTION("Silicon Labs Si2165 DVB-C/-T Demodulator driver"); MODULE_AUTHOR("Matthias Schwarzott <zzam@gentoo.org>"); MODULE_LICENSE("GPL"); -MODULE_FIRMWARE(SI2165_FIRMWARE); +MODULE_FIRMWARE(SI2165_FIRMWARE_REV_D); diff --git a/drivers/media/dvb-frontends/si2165_priv.h b/drivers/media/dvb-frontends/si2165_priv.h index d4cc93fe1096..2b70cf12cd79 100644 --- a/drivers/media/dvb-frontends/si2165_priv.h +++ b/drivers/media/dvb-frontends/si2165_priv.h @@ -18,6 +18,6 @@ #ifndef _DVB_SI2165_PRIV #define _DVB_SI2165_PRIV -#define SI2165_FIRMWARE "dvb-demod-si2165.fw" +#define SI2165_FIRMWARE_REV_D "dvb-demod-si2165.fw" #endif /* _DVB_SI2165_PRIV */ diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index 8f81d979de30..1cd93be281ed 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -55,8 +55,7 @@ static int si2168_cmd_execute(struct si2168 *s, struct si2168_cmd *cmd) break; } - dev_dbg(&s->client->dev, "%s: cmd execution took %d ms\n", - __func__, + dev_dbg(&s->client->dev, "cmd execution took %d ms\n", jiffies_to_msecs(jiffies) - (jiffies_to_msecs(timeout) - TIMEOUT)); @@ -75,7 +74,7 @@ err_mutex_unlock: return 0; err: - dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&s->client->dev, "failed=%d\n", ret); return ret; } @@ -150,12 +149,12 @@ static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status) c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; } - dev_dbg(&s->client->dev, "%s: status=%02x args=%*ph\n", - __func__, *status, cmd.rlen, cmd.args); + dev_dbg(&s->client->dev, "status=%02x args=%*ph\n", + *status, cmd.rlen, cmd.args); return 0; err: - dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&s->client->dev, "failed=%d\n", ret); return ret; } @@ -168,10 +167,10 @@ static int si2168_set_frontend(struct dvb_frontend *fe) u8 bandwidth, delivery_system; dev_dbg(&s->client->dev, - "%s: delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%u\n", - __func__, c->delivery_system, c->modulation, + "delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%u, stream_id=%d\n", + c->delivery_system, c->modulation, c->frequency, c->bandwidth_hz, c->symbol_rate, - c->inversion); + c->inversion, c->stream_id); if (!s->active) { ret = -EAGAIN; @@ -235,6 +234,18 @@ static int si2168_set_frontend(struct dvb_frontend *fe) if (ret) goto err; + if (c->delivery_system == SYS_DVBT2) { + /* select PLP */ + cmd.args[0] = 0x52; + cmd.args[1] = c->stream_id & 0xff; + cmd.args[2] = c->stream_id == NO_STREAM_ID_FILTER ? 0 : 1; + cmd.wlen = 3; + cmd.rlen = 1; + ret = si2168_cmd_execute(s, &cmd); + if (ret) + goto err; + } + memcpy(cmd.args, "\x51\x03", 2); cmd.wlen = 2; cmd.rlen = 12; @@ -297,13 +308,6 @@ static int si2168_set_frontend(struct dvb_frontend *fe) if (ret) goto err; - memcpy(cmd.args, "\x14\x00\x01\x10\x16\x00", 6); - cmd.wlen = 6; - cmd.rlen = 4; - ret = si2168_cmd_execute(s, &cmd); - if (ret) - goto err; - memcpy(cmd.args, "\x14\x00\x09\x10\xe3\x18", 6); cmd.wlen = 6; cmd.rlen = 4; @@ -343,7 +347,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe) return 0; err: - dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&s->client->dev, "failed=%d\n", ret); return ret; } @@ -357,8 +361,9 @@ static int si2168_init(struct dvb_frontend *fe) struct si2168_cmd cmd; unsigned int chip_id; - dev_dbg(&s->client->dev, "%s:\n", __func__); + dev_dbg(&s->client->dev, "\n"); + /* initialize */ memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13); cmd.wlen = 13; cmd.rlen = 0; @@ -366,6 +371,26 @@ static int si2168_init(struct dvb_frontend *fe) if (ret) goto err; + if (s->fw_loaded) { + /* resume */ + memcpy(cmd.args, "\xc0\x06\x08\x0f\x00\x20\x21\x01", 8); + cmd.wlen = 8; + cmd.rlen = 1; + ret = si2168_cmd_execute(s, &cmd); + if (ret) + goto err; + + memcpy(cmd.args, "\x85", 1); + cmd.wlen = 1; + cmd.rlen = 1; + ret = si2168_cmd_execute(s, &cmd); + if (ret) + goto err; + + goto warm; + } + + /* power up */ memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8); cmd.wlen = 8; cmd.rlen = 1; @@ -400,16 +425,16 @@ static int si2168_init(struct dvb_frontend *fe) break; default: dev_err(&s->client->dev, - "%s: unkown chip version Si21%d-%c%c%c\n", - KBUILD_MODNAME, cmd.args[2], cmd.args[1], + "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; } /* cold state - try to download firmware */ - dev_info(&s->client->dev, "%s: found a '%s' in cold state\n", - KBUILD_MODNAME, si2168_ops.info.name); + dev_info(&s->client->dev, "found a '%s' in cold state\n", + si2168_ops.info.name); /* request the firmware, this will block and timeout */ ret = request_firmware(&fw, fw_file, &s->client->dev); @@ -422,18 +447,18 @@ static int si2168_init(struct dvb_frontend *fe) if (ret == 0) { dev_notice(&s->client->dev, - "%s: please install firmware file '%s'\n", - KBUILD_MODNAME, SI2168_B40_FIRMWARE); + "please install firmware file '%s'\n", + SI2168_B40_FIRMWARE); } else { dev_err(&s->client->dev, - "%s: firmware file '%s' not found\n", - KBUILD_MODNAME, fw_file); + "firmware file '%s' not found\n", + fw_file); goto err; } } - dev_info(&s->client->dev, "%s: downloading firmware from file '%s'\n", - KBUILD_MODNAME, fw_file); + dev_info(&s->client->dev, "downloading firmware from file '%s'\n", + fw_file); for (remaining = fw->size; remaining > 0; remaining -= i2c_wr_max) { len = remaining; @@ -446,8 +471,8 @@ static int si2168_init(struct dvb_frontend *fe) ret = si2168_cmd_execute(s, &cmd); if (ret) { dev_err(&s->client->dev, - "%s: firmware download failed=%d\n", - KBUILD_MODNAME, ret); + "firmware download failed=%d\n", + ret); goto err; } } @@ -462,8 +487,20 @@ static int si2168_init(struct dvb_frontend *fe) if (ret) goto err; - dev_info(&s->client->dev, "%s: found a '%s' in warm state\n", - KBUILD_MODNAME, si2168_ops.info.name); + /* set ts mode */ + memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6); + cmd.args[4] |= s->ts_mode; + cmd.wlen = 6; + cmd.rlen = 4; + ret = si2168_cmd_execute(s, &cmd); + if (ret) + goto err; + + s->fw_loaded = true; + +warm: + dev_info(&s->client->dev, "found a '%s' in warm state\n", + si2168_ops.info.name); s->active = true; @@ -472,7 +509,7 @@ err: if (fw) release_firmware(fw); - dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&s->client->dev, "failed=%d\n", ret); return ret; } @@ -482,7 +519,7 @@ static int si2168_sleep(struct dvb_frontend *fe) int ret; struct si2168_cmd cmd; - dev_dbg(&s->client->dev, "%s:\n", __func__); + dev_dbg(&s->client->dev, "\n"); s->active = false; @@ -495,7 +532,7 @@ static int si2168_sleep(struct dvb_frontend *fe) return 0; err: - dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&s->client->dev, "failed=%d\n", ret); return ret; } @@ -528,8 +565,7 @@ static int si2168_select(struct i2c_adapter *adap, void *mux_priv, u32 chan) /* open tuner I2C gate */ ret = __i2c_transfer(s->client->adapter, &gate_open_msg, 1); if (ret != 1) { - dev_warn(&s->client->dev, "%s: i2c write failed=%d\n", - KBUILD_MODNAME, ret); + dev_warn(&s->client->dev, "i2c write failed=%d\n", ret); if (ret >= 0) ret = -EREMOTEIO; } else { @@ -553,8 +589,7 @@ static int si2168_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan) /* close tuner I2C gate */ ret = __i2c_transfer(s->client->adapter, &gate_close_msg, 1); if (ret != 1) { - dev_warn(&s->client->dev, "%s: i2c write failed=%d\n", - KBUILD_MODNAME, ret); + dev_warn(&s->client->dev, "i2c write failed=%d\n", ret); if (ret >= 0) ret = -EREMOTEIO; } else { @@ -587,7 +622,8 @@ static const struct dvb_frontend_ops si2168_ops = { FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | FE_CAN_MUTE_TS | - FE_CAN_2G_MODULATION + FE_CAN_2G_MODULATION | + FE_CAN_MULTISTREAM }, .get_tune_settings = si2168_get_tune_settings, @@ -607,12 +643,12 @@ static int si2168_probe(struct i2c_client *client, struct si2168 *s; int ret; - dev_dbg(&client->dev, "%s:\n", __func__); + dev_dbg(&client->dev, "\n"); s = kzalloc(sizeof(struct si2168), GFP_KERNEL); if (!s) { ret = -ENOMEM; - dev_err(&client->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME); + dev_err(&client->dev, "kzalloc() failed\n"); goto err; } @@ -633,16 +669,17 @@ static int si2168_probe(struct i2c_client *client, *config->i2c_adapter = s->adapter; *config->fe = &s->fe; + s->ts_mode = config->ts_mode; + s->fw_loaded = false; i2c_set_clientdata(client, s); dev_info(&s->client->dev, - "%s: Silicon Labs Si2168 successfully attached\n", - KBUILD_MODNAME); + "Silicon Labs Si2168 successfully attached\n"); return 0; err: kfree(s); - dev_dbg(&client->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } @@ -650,7 +687,7 @@ static int si2168_remove(struct i2c_client *client) { struct si2168 *s = i2c_get_clientdata(client); - dev_dbg(&client->dev, "%s:\n", __func__); + dev_dbg(&client->dev, "\n"); i2c_del_mux_adapter(s->adapter); diff --git a/drivers/media/dvb-frontends/si2168.h b/drivers/media/dvb-frontends/si2168.h index 3c5b5ab01796..e086d6719451 100644 --- a/drivers/media/dvb-frontends/si2168.h +++ b/drivers/media/dvb-frontends/si2168.h @@ -34,6 +34,12 @@ struct si2168_config { * returned by driver */ struct i2c_adapter **i2c_adapter; + + /* TS mode */ + u8 ts_mode; }; +#define SI2168_TS_PARALLEL 0x06 +#define SI2168_TS_SERIAL 0x03 + #endif diff --git a/drivers/media/dvb-frontends/si2168_priv.h b/drivers/media/dvb-frontends/si2168_priv.h index ebbf502ec313..e13983ed4be1 100644 --- a/drivers/media/dvb-frontends/si2168_priv.h +++ b/drivers/media/dvb-frontends/si2168_priv.h @@ -36,6 +36,8 @@ struct si2168 { fe_delivery_system_t delivery_system; fe_status_t fe_status; bool active; + bool fw_loaded; + u8 ts_mode; }; /* firmare command struct */ diff --git a/drivers/media/dvb-frontends/si21xx.c b/drivers/media/dvb-frontends/si21xx.c index 73b47cc6a13b..16850e2bf02f 100644 --- a/drivers/media/dvb-frontends/si21xx.c +++ b/drivers/media/dvb-frontends/si21xx.c @@ -236,6 +236,9 @@ static int si21_writeregs(struct si21xx_state *state, u8 reg1, .len = len + 1 }; + if (len > sizeof(buf) - 1) + return -EINVAL; + msg.buf[0] = reg1; memcpy(msg.buf + 1, data, len); diff --git a/drivers/media/dvb-frontends/sp2.c b/drivers/media/dvb-frontends/sp2.c new file mode 100644 index 000000000000..9b684d5c8f91 --- /dev/null +++ b/drivers/media/dvb-frontends/sp2.c @@ -0,0 +1,441 @@ +/* + * CIMaX SP2/SP2HF (Atmel T90FJR) CI driver + * + * Copyright (C) 2014 Olli Salonen <olli.salonen@iki.fi> + * + * Heavily based on CIMax2(R) SP2 driver in conjunction with NetUp Dual + * DVB-S2 CI card (cimax2) with following copyrights: + * + * Copyright (C) 2009 NetUP Inc. + * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru> + * Copyright (C) 2009 Abylay Ospan <aospan@netup.ru> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "sp2_priv.h" + +static int sp2_read_i2c(struct sp2 *s, u8 reg, u8 *buf, int len) +{ + int ret; + struct i2c_client *client = s->client; + struct i2c_adapter *adap = client->adapter; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = 0, + .buf = ®, + .len = 1 + }, { + .addr = client->addr, + .flags = I2C_M_RD, + .buf = buf, + .len = len + } + }; + + ret = i2c_transfer(adap, msg, 2); + + if (ret != 2) { + dev_err(&client->dev, "i2c read error, reg = 0x%02x, status = %d\n", + reg, ret); + if (ret < 0) + return ret; + else + return -EIO; + } + + dev_dbg(&s->client->dev, "addr=0x%04x, reg = 0x%02x, data = %02x\n", + client->addr, reg, buf[0]); + + return 0; +} + +static int sp2_write_i2c(struct sp2 *s, u8 reg, u8 *buf, int len) +{ + int ret; + u8 buffer[35]; + struct i2c_client *client = s->client; + struct i2c_adapter *adap = client->adapter; + struct i2c_msg msg = { + .addr = client->addr, + .flags = 0, + .buf = &buffer[0], + .len = len + 1 + }; + + if ((len + 1) > sizeof(buffer)) { + dev_err(&client->dev, "i2c wr reg=%02x: len=%d is too big!\n", + reg, len); + return -EINVAL; + } + + buffer[0] = reg; + memcpy(&buffer[1], buf, len); + + ret = i2c_transfer(adap, &msg, 1); + + if (ret != 1) { + dev_err(&client->dev, "i2c write error, reg = 0x%02x, status = %d\n", + reg, ret); + if (ret < 0) + return ret; + else + return -EIO; + } + + return 0; +} + +static int sp2_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot, u8 acs, + u8 read, int addr, u8 data) +{ + struct sp2 *s = en50221->data; + u8 store; + int mem, ret; + int (*ci_op_cam)(void*, u8, int, u8, int*) = s->ci_control; + + dev_dbg(&s->client->dev, "slot=%d, acs=0x%02x, addr=0x%04x, data = 0x%02x", + slot, acs, addr, data); + + if (slot != 0) + return -EINVAL; + + /* + * change module access type between IO space and attribute memory + * when needed + */ + if (s->module_access_type != acs) { + ret = sp2_read_i2c(s, 0x00, &store, 1); + + if (ret) + return ret; + + store &= ~(SP2_MOD_CTL_ACS1 | SP2_MOD_CTL_ACS0); + store |= acs; + + ret = sp2_write_i2c(s, 0x00, &store, 1); + if (ret) + return ret; + } + + s->module_access_type = acs; + + /* implementation of ci_op_cam is device specific */ + if (ci_op_cam) { + ret = ci_op_cam(s->priv, read, addr, data, &mem); + } else { + dev_err(&s->client->dev, "callback not defined"); + return -EINVAL; + } + + if (ret) + return ret; + + if (read) { + dev_dbg(&s->client->dev, "cam read, addr=0x%04x, data = 0x%04x", + addr, mem); + return mem; + } else { + return 0; + } +} + +int sp2_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221, + int slot, int addr) +{ + return sp2_ci_op_cam(en50221, slot, SP2_CI_ATTR_ACS, + SP2_CI_RD, addr, 0); +} + +int sp2_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221, + int slot, int addr, u8 data) +{ + return sp2_ci_op_cam(en50221, slot, SP2_CI_ATTR_ACS, + SP2_CI_WR, addr, data); +} + +int sp2_ci_read_cam_control(struct dvb_ca_en50221 *en50221, + int slot, u8 addr) +{ + return sp2_ci_op_cam(en50221, slot, SP2_CI_IO_ACS, + SP2_CI_RD, addr, 0); +} + +int sp2_ci_write_cam_control(struct dvb_ca_en50221 *en50221, + int slot, u8 addr, u8 data) +{ + return sp2_ci_op_cam(en50221, slot, SP2_CI_IO_ACS, + SP2_CI_WR, addr, data); +} + +int sp2_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot) +{ + struct sp2 *s = en50221->data; + u8 buf; + int ret; + + dev_dbg(&s->client->dev, "slot: %d\n", slot); + + if (slot != 0) + return -EINVAL; + + /* RST on */ + buf = SP2_MOD_CTL_RST; + ret = sp2_write_i2c(s, 0x00, &buf, 1); + + if (ret) + return ret; + + usleep_range(500, 600); + + /* RST off */ + buf = 0x00; + ret = sp2_write_i2c(s, 0x00, &buf, 1); + + if (ret) + return ret; + + msleep(1000); + + return 0; +} + +int sp2_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot) +{ + struct sp2 *s = en50221->data; + + dev_dbg(&s->client->dev, "slot:%d\n", slot); + + /* not implemented */ + return 0; +} + +int sp2_ci_slot_ts_enable(struct dvb_ca_en50221 *en50221, int slot) +{ + struct sp2 *s = en50221->data; + u8 buf; + + dev_dbg(&s->client->dev, "slot:%d\n", slot); + + if (slot != 0) + return -EINVAL; + + sp2_read_i2c(s, 0x00, &buf, 1); + + /* disable bypass and enable TS */ + buf |= (SP2_MOD_CTL_TSOEN | SP2_MOD_CTL_TSIEN); + return sp2_write_i2c(s, 0, &buf, 1); +} + +int sp2_ci_poll_slot_status(struct dvb_ca_en50221 *en50221, + int slot, int open) +{ + struct sp2 *s = en50221->data; + u8 buf[2]; + int ret; + + dev_dbg(&s->client->dev, "slot:%d open:%d\n", slot, open); + + /* + * CAM module INSERT/REMOVE processing. Slow operation because of i2c + * transfers. Throttle read to one per sec. + */ + if (time_after(jiffies, s->next_status_checked_time)) { + ret = sp2_read_i2c(s, 0x00, buf, 1); + s->next_status_checked_time = jiffies + msecs_to_jiffies(1000); + + if (ret) + return 0; + + if (buf[0] & SP2_MOD_CTL_DET) + s->status = DVB_CA_EN50221_POLL_CAM_PRESENT | + DVB_CA_EN50221_POLL_CAM_READY; + else + s->status = 0; + } + + return s->status; +} + +int sp2_init(struct sp2 *s) +{ + int ret = 0; + u8 buf; + u8 cimax_init[34] = { + 0x00, /* module A control*/ + 0x00, /* auto select mask high A */ + 0x00, /* auto select mask low A */ + 0x00, /* auto select pattern high A */ + 0x00, /* auto select pattern low A */ + 0x44, /* memory access time A, 600 ns */ + 0x00, /* invert input A */ + 0x00, /* RFU */ + 0x00, /* RFU */ + 0x00, /* module B control*/ + 0x00, /* auto select mask high B */ + 0x00, /* auto select mask low B */ + 0x00, /* auto select pattern high B */ + 0x00, /* auto select pattern low B */ + 0x44, /* memory access time B, 600 ns */ + 0x00, /* invert input B */ + 0x00, /* RFU */ + 0x00, /* RFU */ + 0x00, /* auto select mask high Ext */ + 0x00, /* auto select mask low Ext */ + 0x00, /* auto select pattern high Ext */ + 0x00, /* auto select pattern low Ext */ + 0x00, /* RFU */ + 0x02, /* destination - module A */ + 0x01, /* power control reg, VCC power on */ + 0x00, /* RFU */ + 0x00, /* int status read only */ + 0x00, /* Interrupt Mask Register */ + 0x05, /* EXTINT=active-high, INT=push-pull */ + 0x00, /* USCG1 */ + 0x04, /* ack active low */ + 0x00, /* LOCK = 0 */ + 0x22, /* unknown */ + 0x00, /* synchronization? */ + }; + + dev_dbg(&s->client->dev, "\n"); + + s->ca.owner = THIS_MODULE; + s->ca.read_attribute_mem = sp2_ci_read_attribute_mem; + s->ca.write_attribute_mem = sp2_ci_write_attribute_mem; + s->ca.read_cam_control = sp2_ci_read_cam_control; + s->ca.write_cam_control = sp2_ci_write_cam_control; + s->ca.slot_reset = sp2_ci_slot_reset; + s->ca.slot_shutdown = sp2_ci_slot_shutdown; + s->ca.slot_ts_enable = sp2_ci_slot_ts_enable; + s->ca.poll_slot_status = sp2_ci_poll_slot_status; + s->ca.data = s; + s->module_access_type = 0; + + /* initialize all regs */ + ret = sp2_write_i2c(s, 0x00, &cimax_init[0], 34); + if (ret) + goto err; + + /* lock registers */ + buf = 1; + ret = sp2_write_i2c(s, 0x1f, &buf, 1); + if (ret) + goto err; + + /* power on slots */ + ret = sp2_write_i2c(s, 0x18, &buf, 1); + if (ret) + goto err; + + ret = dvb_ca_en50221_init(s->dvb_adap, &s->ca, 0, 1); + if (ret) + goto err; + + return 0; + +err: + dev_dbg(&s->client->dev, "init failed=%d\n", ret); + return ret; +} + +int sp2_exit(struct i2c_client *client) +{ + struct sp2 *s; + + dev_dbg(&client->dev, "\n"); + + if (client == NULL) + return 0; + + s = i2c_get_clientdata(client); + if (s == NULL) + return 0; + + if (s->ca.data == NULL) + return 0; + + dvb_ca_en50221_release(&s->ca); + + return 0; +} + +static int sp2_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct sp2_config *cfg = client->dev.platform_data; + struct sp2 *s; + int ret; + + dev_dbg(&client->dev, "\n"); + + s = kzalloc(sizeof(struct sp2), GFP_KERNEL); + if (!s) { + ret = -ENOMEM; + dev_err(&client->dev, "kzalloc() failed\n"); + goto err; + } + + s->client = client; + s->dvb_adap = cfg->dvb_adap; + s->priv = cfg->priv; + s->ci_control = cfg->ci_control; + + i2c_set_clientdata(client, s); + + ret = sp2_init(s); + if (ret) + goto err; + + dev_info(&s->client->dev, "CIMaX SP2 successfully attached\n"); + return 0; +err: + dev_dbg(&client->dev, "init failed=%d\n", ret); + kfree(s); + + return ret; +} + +static int sp2_remove(struct i2c_client *client) +{ + struct si2157 *s = i2c_get_clientdata(client); + + dev_dbg(&client->dev, "\n"); + + sp2_exit(client); + if (s != NULL) + kfree(s); + + return 0; +} + +static const struct i2c_device_id sp2_id[] = { + {"sp2", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, sp2_id); + +static struct i2c_driver sp2_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "sp2", + }, + .probe = sp2_probe, + .remove = sp2_remove, + .id_table = sp2_id, +}; + +module_i2c_driver(sp2_driver); + +MODULE_DESCRIPTION("CIMaX SP2/HF CI driver"); +MODULE_AUTHOR("Olli Salonen <olli.salonen@iki.fi>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/sp2.h b/drivers/media/dvb-frontends/sp2.h new file mode 100644 index 000000000000..6cceea022d49 --- /dev/null +++ b/drivers/media/dvb-frontends/sp2.h @@ -0,0 +1,53 @@ +/* + * CIMaX SP2/HF CI driver + * + * Copyright (C) 2014 Olli Salonen <olli.salonen@iki.fi> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef SP2_H +#define SP2_H + +#include <linux/kconfig.h> +#include "dvb_ca_en50221.h" + +/* + * I2C address + * 0x40 (port 0) + * 0x41 (port 1) + */ +struct sp2_config { + /* dvb_adapter to attach the ci to */ + struct dvb_adapter *dvb_adap; + + /* function ci_control handles the device specific ci ops */ + void *ci_control; + + /* priv is passed back to function ci_control */ + void *priv; +}; + +extern int sp2_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221, + int slot, int addr); +extern int sp2_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221, + int slot, int addr, u8 data); +extern int sp2_ci_read_cam_control(struct dvb_ca_en50221 *en50221, + int slot, u8 addr); +extern int sp2_ci_write_cam_control(struct dvb_ca_en50221 *en50221, + int slot, u8 addr, u8 data); +extern int sp2_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot); +extern int sp2_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot); +extern int sp2_ci_slot_ts_enable(struct dvb_ca_en50221 *en50221, int slot); +extern int sp2_ci_poll_slot_status(struct dvb_ca_en50221 *en50221, + int slot, int open); + +#endif diff --git a/drivers/media/dvb-frontends/sp2_priv.h b/drivers/media/dvb-frontends/sp2_priv.h new file mode 100644 index 000000000000..37fef7bcd63f --- /dev/null +++ b/drivers/media/dvb-frontends/sp2_priv.h @@ -0,0 +1,50 @@ +/* + * CIMaX SP2/HF CI driver + * + * Copyright (C) 2014 Olli Salonen <olli.salonen@iki.fi> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef SP2_PRIV_H +#define SP2_PRIV_H + +#include "sp2.h" +#include "dvb_frontend.h" + +/* state struct */ +struct sp2 { + int status; + struct i2c_client *client; + struct dvb_adapter *dvb_adap; + struct dvb_ca_en50221 ca; + int module_access_type; + unsigned long next_status_checked_time; + void *priv; + void *ci_control; +}; + +#define SP2_CI_ATTR_ACS 0x00 +#define SP2_CI_IO_ACS 0x04 +#define SP2_CI_WR 0 +#define SP2_CI_RD 1 + +/* Module control register (0x00 module A, 0x09 module B) bits */ +#define SP2_MOD_CTL_DET 0x01 +#define SP2_MOD_CTL_AUTO 0x02 +#define SP2_MOD_CTL_ACS0 0x04 +#define SP2_MOD_CTL_ACS1 0x08 +#define SP2_MOD_CTL_HAD 0x10 +#define SP2_MOD_CTL_TSIEN 0x20 +#define SP2_MOD_CTL_TSOEN 0x40 +#define SP2_MOD_CTL_RST 0x80 + +#endif diff --git a/drivers/media/dvb-frontends/sp8870.c b/drivers/media/dvb-frontends/sp8870.c index 2aa8ef76eba2..57dc2abaa87b 100644 --- a/drivers/media/dvb-frontends/sp8870.c +++ b/drivers/media/dvb-frontends/sp8870.c @@ -394,8 +394,7 @@ static int sp8870_read_ber (struct dvb_frontend* fe, u32 * ber) if (ret < 0) return -EIO; - tmp = ret << 6; - + tmp = ret << 6; if (tmp >= 0x3FFF0) tmp = ~0; diff --git a/drivers/media/dvb-frontends/stv0367.c b/drivers/media/dvb-frontends/stv0367.c index 59b6e661acc0..b31ff265ff24 100644 --- a/drivers/media/dvb-frontends/stv0367.c +++ b/drivers/media/dvb-frontends/stv0367.c @@ -59,7 +59,6 @@ struct stv0367cab_state { int locked; /* channel found */ u32 freq_khz; /* found frequency (in kHz) */ u32 symbol_rate; /* found symbol rate (in Bds) */ - enum stv0367cab_mod modulation; /* modulation */ fe_spectral_inversion_t spect_inv; /* Spectrum Inversion */ }; @@ -554,7 +553,7 @@ static struct st_register def0367ter[STV0367TER_NBREGS] = { #define RF_LOOKUP_TABLE_SIZE 31 #define RF_LOOKUP_TABLE2_SIZE 16 /* RF Level (for RF AGC->AGC1) Lookup Table, depends on the board and tuner.*/ -s32 stv0367cab_RF_LookUp1[RF_LOOKUP_TABLE_SIZE][RF_LOOKUP_TABLE_SIZE] = { +static const s32 stv0367cab_RF_LookUp1[RF_LOOKUP_TABLE_SIZE][RF_LOOKUP_TABLE_SIZE] = { {/*AGC1*/ 48, 50, 51, 53, 54, 56, 57, 58, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, @@ -566,7 +565,7 @@ s32 stv0367cab_RF_LookUp1[RF_LOOKUP_TABLE_SIZE][RF_LOOKUP_TABLE_SIZE] = { } }; /* RF Level (for IF AGC->AGC2) Lookup Table, depends on the board and tuner.*/ -s32 stv0367cab_RF_LookUp2[RF_LOOKUP_TABLE2_SIZE][RF_LOOKUP_TABLE2_SIZE] = { +static const s32 stv0367cab_RF_LookUp2[RF_LOOKUP_TABLE2_SIZE][RF_LOOKUP_TABLE2_SIZE] = { {/*AGC2*/ 28, 29, 31, 32, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1935,8 +1934,6 @@ static int stv0367ter_get_frontend(struct dvb_frontend *fe) struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct stv0367_state *state = fe->demodulator_priv; struct stv0367ter_state *ter_state = state->ter_state; - - int error = 0; enum stv0367_ter_mode mode; int constell = 0,/* snr = 0,*/ Data = 0; @@ -2020,7 +2017,7 @@ static int stv0367ter_get_frontend(struct dvb_frontend *fe) p->guard_interval = stv0367_readbits(state, F367TER_SYR_GUARD); - return error; + return 0; } static int stv0367ter_read_snr(struct dvb_frontend *fe, u16 *snr) @@ -2999,7 +2996,6 @@ enum stv0367_cab_signal_type stv0367cab_algo(struct stv0367_state *state, if (QAMFEC_Lock) { signalType = FE_CAB_DATAOK; - cab_state->modulation = p->modulation; cab_state->spect_inv = stv0367_readbits(state, F367CAB_QUAD_INV); #if 0 @@ -3165,7 +3161,7 @@ static int stv0367cab_get_frontend(struct dvb_frontend *fe) case FE_CAB_MOD_QAM128: p->modulation = QAM_128; break; - case QAM_256: + case FE_CAB_MOD_QAM256: p->modulation = QAM_256; break; default: diff --git a/drivers/media/dvb-frontends/stv0900_core.c b/drivers/media/dvb-frontends/stv0900_core.c index e5a87b57d855..2c88abfab531 100644 --- a/drivers/media/dvb-frontends/stv0900_core.c +++ b/drivers/media/dvb-frontends/stv0900_core.c @@ -1270,7 +1270,6 @@ enum fe_stv0900_error stv0900_st_dvbs2_single(struct stv0900_internal *intp, enum fe_stv0900_demod_mode LDPC_Mode, enum fe_stv0900_demod_num demod) { - enum fe_stv0900_error error = STV0900_NO_ERROR; s32 reg_ind; dprintk("%s\n", __func__); @@ -1337,7 +1336,7 @@ enum fe_stv0900_error stv0900_st_dvbs2_single(struct stv0900_internal *intp, break; } - return error; + return STV0900_NO_ERROR; } static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, @@ -1555,8 +1554,6 @@ static int stv0900_status(struct stv0900_internal *intp, static int stv0900_set_mis(struct stv0900_internal *intp, enum fe_stv0900_demod_num demod, int mis) { - enum fe_stv0900_error error = STV0900_NO_ERROR; - dprintk("%s\n", __func__); if (mis < 0 || mis > 255) { @@ -1569,7 +1566,7 @@ static int stv0900_set_mis(struct stv0900_internal *intp, stv0900_write_reg(intp, ISIBITENA, 0xff); } - return error; + return STV0900_NO_ERROR; } diff --git a/drivers/media/dvb-frontends/stv0900_sw.c b/drivers/media/dvb-frontends/stv0900_sw.c index 4ce1d260b3eb..a0a7b1664c53 100644 --- a/drivers/media/dvb-frontends/stv0900_sw.c +++ b/drivers/media/dvb-frontends/stv0900_sw.c @@ -1733,9 +1733,10 @@ static void stv0900_set_search_standard(struct stv0900_internal *intp, break; case STV0900_SEARCH_DSS: dprintk("Search Standard = DSS\n"); - case STV0900_SEARCH_DVBS2: break; + case STV0900_SEARCH_DVBS2: dprintk("Search Standard = DVBS2\n"); + break; case STV0900_AUTO_SEARCH: default: dprintk("Search Standard = AUTO\n"); diff --git a/drivers/media/dvb-frontends/tc90522.c b/drivers/media/dvb-frontends/tc90522.c new file mode 100644 index 000000000000..d9905fb52f84 --- /dev/null +++ b/drivers/media/dvb-frontends/tc90522.c @@ -0,0 +1,840 @@ +/* + * Toshiba TC90522 Demodulator + * + * Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* + * NOTICE: + * This driver is incomplete and lacks init/config of the chips, + * as the necessary info is not disclosed. + * It assumes that users of this driver (such as a PCI bridge of + * DTV receiver cards) properly init and configure the chip + * via I2C *before* calling this driver's init() function. + * + * Currently, PT3 driver is the only one that uses this driver, + * and contains init/config code in its firmware. + * Thus some part of the code might be dependent on PT3 specific config. + */ + +#include <linux/kernel.h> +#include <linux/math64.h> +#include <linux/dvb/frontend.h> +#include "dvb_math.h" +#include "tc90522.h" + +#define TC90522_I2C_THRU_REG 0xfe + +#define TC90522_MODULE_IDX(addr) (((u8)(addr) & 0x02U) >> 1) + +struct tc90522_state { + struct tc90522_config cfg; + struct dvb_frontend fe; + struct i2c_client *i2c_client; + struct i2c_adapter tuner_i2c; + + bool lna; +}; + +struct reg_val { + u8 reg; + u8 val; +}; + +static int +reg_write(struct tc90522_state *state, const struct reg_val *regs, int num) +{ + int i, ret; + struct i2c_msg msg; + + ret = 0; + msg.addr = state->i2c_client->addr; + msg.flags = 0; + msg.len = 2; + for (i = 0; i < num; i++) { + msg.buf = (u8 *)®s[i]; + ret = i2c_transfer(state->i2c_client->adapter, &msg, 1); + if (ret == 0) + ret = -EIO; + if (ret < 0) + return ret; + } + return 0; +} + +static int reg_read(struct tc90522_state *state, u8 reg, u8 *val, u8 len) +{ + struct i2c_msg msgs[2] = { + { + .addr = state->i2c_client->addr, + .flags = 0, + .buf = ®, + .len = 1, + }, + { + .addr = state->i2c_client->addr, + .flags = I2C_M_RD, + .buf = val, + .len = len, + }, + }; + int ret; + + ret = i2c_transfer(state->i2c_client->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret == ARRAY_SIZE(msgs)) + ret = 0; + else if (ret >= 0) + ret = -EIO; + return ret; +} + +static struct tc90522_state *cfg_to_state(struct tc90522_config *c) +{ + return container_of(c, struct tc90522_state, cfg); +} + + +static int tc90522s_set_tsid(struct dvb_frontend *fe) +{ + struct reg_val set_tsid[] = { + { 0x8f, 00 }, + { 0x90, 00 } + }; + + set_tsid[0].val = (fe->dtv_property_cache.stream_id & 0xff00) >> 8; + set_tsid[1].val = fe->dtv_property_cache.stream_id & 0xff; + return reg_write(fe->demodulator_priv, set_tsid, ARRAY_SIZE(set_tsid)); +} + +static int tc90522t_set_layers(struct dvb_frontend *fe) +{ + struct reg_val rv; + u8 laysel; + + laysel = ~fe->dtv_property_cache.isdbt_layer_enabled & 0x07; + laysel = (laysel & 0x01) << 2 | (laysel & 0x02) | (laysel & 0x04) >> 2; + rv.reg = 0x71; + rv.val = laysel; + return reg_write(fe->demodulator_priv, &rv, 1); +} + +/* frontend ops */ + +static int tc90522s_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct tc90522_state *state; + int ret; + u8 reg; + + state = fe->demodulator_priv; + ret = reg_read(state, 0xc3, ®, 1); + if (ret < 0) + return ret; + + *status = 0; + if (reg & 0x80) /* input level under min ? */ + return 0; + *status |= FE_HAS_SIGNAL; + + if (reg & 0x60) /* carrier? */ + return 0; + *status |= FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC; + + if (reg & 0x10) + return 0; + if (reg_read(state, 0xc5, ®, 1) < 0 || !(reg & 0x03)) + return 0; + *status |= FE_HAS_LOCK; + return 0; +} + +static int tc90522t_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct tc90522_state *state; + int ret; + u8 reg; + + state = fe->demodulator_priv; + ret = reg_read(state, 0x96, ®, 1); + if (ret < 0) + return ret; + + *status = 0; + if (reg & 0xe0) { + *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI + | FE_HAS_SYNC | FE_HAS_LOCK; + return 0; + } + + ret = reg_read(state, 0x80, ®, 1); + if (ret < 0) + return ret; + + if (reg & 0xf0) + return 0; + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER; + + if (reg & 0x0c) + return 0; + *status |= FE_HAS_SYNC | FE_HAS_VITERBI; + + if (reg & 0x02) + return 0; + *status |= FE_HAS_LOCK; + return 0; +} + +static const fe_code_rate_t fec_conv_sat[] = { + FEC_NONE, /* unused */ + FEC_1_2, /* for BPSK */ + FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8, /* for QPSK */ + FEC_2_3, /* for 8PSK. (trellis code) */ +}; + +static int tc90522s_get_frontend(struct dvb_frontend *fe) +{ + struct tc90522_state *state; + struct dtv_frontend_properties *c; + struct dtv_fe_stats *stats; + int ret, i; + int layers; + u8 val[10]; + u32 cndat; + + state = fe->demodulator_priv; + c = &fe->dtv_property_cache; + c->delivery_system = SYS_ISDBS; + + layers = 0; + ret = reg_read(state, 0xe8, val, 3); + if (ret == 0) { + int slots; + u8 v; + + /* high/single layer */ + v = (val[0] & 0x70) >> 4; + c->modulation = (v == 7) ? PSK_8 : QPSK; + c->fec_inner = fec_conv_sat[v]; + c->layer[0].fec = c->fec_inner; + c->layer[0].modulation = c->modulation; + c->layer[0].segment_count = val[1] & 0x3f; /* slots */ + + /* low layer */ + v = (val[0] & 0x07); + c->layer[1].fec = fec_conv_sat[v]; + if (v == 0) /* no low layer */ + c->layer[1].segment_count = 0; + else + c->layer[1].segment_count = val[2] & 0x3f; /* slots */ + /* actually, BPSK if v==1, but not defined in fe_modulation_t */ + c->layer[1].modulation = QPSK; + layers = (v > 0) ? 2 : 1; + + slots = c->layer[0].segment_count + c->layer[1].segment_count; + c->symbol_rate = 28860000 * slots / 48; + } + + /* statistics */ + + stats = &c->strength; + stats->len = 0; + /* let the connected tuner set RSSI property cache */ + if (fe->ops.tuner_ops.get_rf_strength) { + u16 dummy; + + fe->ops.tuner_ops.get_rf_strength(fe, &dummy); + } + + stats = &c->cnr; + stats->len = 1; + stats->stat[0].scale = FE_SCALE_NOT_AVAILABLE; + cndat = 0; + ret = reg_read(state, 0xbc, val, 2); + if (ret == 0) + cndat = val[0] << 8 | val[1]; + if (cndat >= 3000) { + u32 p, p4; + s64 cn; + + cndat -= 3000; /* cndat: 4.12 fixed point float */ + /* + * cnr[mdB] = -1634.6 * P^5 + 14341 * P^4 - 50259 * P^3 + * + 88977 * P^2 - 89565 * P + 58857 + * (P = sqrt(cndat) / 64) + */ + /* p := sqrt(cndat) << 8 = P << 14, 2.14 fixed point float */ + /* cn = cnr << 3 */ + p = int_sqrt(cndat << 16); + p4 = cndat * cndat; + cn = div64_s64(-16346LL * p4 * p, 10) >> 35; + cn += (14341LL * p4) >> 21; + cn -= (50259LL * cndat * p) >> 23; + cn += (88977LL * cndat) >> 9; + cn -= (89565LL * p) >> 11; + cn += 58857 << 3; + stats->stat[0].svalue = cn >> 3; + stats->stat[0].scale = FE_SCALE_DECIBEL; + } + + /* per-layer post viterbi BER (or PER? config dependent?) */ + stats = &c->post_bit_error; + memset(stats, 0, sizeof(*stats)); + stats->len = layers; + ret = reg_read(state, 0xeb, val, 10); + if (ret < 0) + for (i = 0; i < layers; i++) + stats->stat[i].scale = FE_SCALE_NOT_AVAILABLE; + else { + for (i = 0; i < layers; i++) { + stats->stat[i].scale = FE_SCALE_COUNTER; + stats->stat[i].uvalue = val[i * 5] << 16 + | val[i * 5 + 1] << 8 | val[i * 5 + 2]; + } + } + stats = &c->post_bit_count; + memset(stats, 0, sizeof(*stats)); + stats->len = layers; + if (ret < 0) + for (i = 0; i < layers; i++) + stats->stat[i].scale = FE_SCALE_NOT_AVAILABLE; + else { + for (i = 0; i < layers; i++) { + stats->stat[i].scale = FE_SCALE_COUNTER; + stats->stat[i].uvalue = + val[i * 5 + 3] << 8 | val[i * 5 + 4]; + stats->stat[i].uvalue *= 204 * 8; + } + } + + return 0; +} + + +static const fe_transmit_mode_t tm_conv[] = { + TRANSMISSION_MODE_2K, + TRANSMISSION_MODE_4K, + TRANSMISSION_MODE_8K, + 0 +}; + +static const fe_code_rate_t fec_conv_ter[] = { + FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8, 0, 0, 0 +}; + +static const fe_modulation_t mod_conv[] = { + DQPSK, QPSK, QAM_16, QAM_64, 0, 0, 0, 0 +}; + +static int tc90522t_get_frontend(struct dvb_frontend *fe) +{ + struct tc90522_state *state; + struct dtv_frontend_properties *c; + struct dtv_fe_stats *stats; + int ret, i; + int layers; + u8 val[15], mode; + u32 cndat; + + state = fe->demodulator_priv; + c = &fe->dtv_property_cache; + c->delivery_system = SYS_ISDBT; + c->bandwidth_hz = 6000000; + mode = 1; + ret = reg_read(state, 0xb0, val, 1); + if (ret == 0) { + mode = (val[0] & 0xc0) >> 2; + c->transmission_mode = tm_conv[mode]; + c->guard_interval = (val[0] & 0x30) >> 4; + } + + ret = reg_read(state, 0xb2, val, 6); + layers = 0; + if (ret == 0) { + u8 v; + + c->isdbt_partial_reception = val[0] & 0x01; + c->isdbt_sb_mode = (val[0] & 0xc0) == 0x01; + + /* layer A */ + v = (val[2] & 0x78) >> 3; + if (v == 0x0f) + c->layer[0].segment_count = 0; + else { + layers++; + c->layer[0].segment_count = v; + c->layer[0].fec = fec_conv_ter[(val[1] & 0x1c) >> 2]; + c->layer[0].modulation = mod_conv[(val[1] & 0xe0) >> 5]; + v = (val[1] & 0x03) << 1 | (val[2] & 0x80) >> 7; + c->layer[0].interleaving = v; + } + + /* layer B */ + v = (val[3] & 0x03) << 1 | (val[4] & 0xc0) >> 6; + if (v == 0x0f) + c->layer[1].segment_count = 0; + else { + layers++; + c->layer[1].segment_count = v; + c->layer[1].fec = fec_conv_ter[(val[3] & 0xe0) >> 5]; + c->layer[1].modulation = mod_conv[(val[2] & 0x07)]; + c->layer[1].interleaving = (val[3] & 0x1c) >> 2; + } + + /* layer C */ + v = (val[5] & 0x1e) >> 1; + if (v == 0x0f) + c->layer[2].segment_count = 0; + else { + layers++; + c->layer[2].segment_count = v; + c->layer[2].fec = fec_conv_ter[(val[4] & 0x07)]; + c->layer[2].modulation = mod_conv[(val[4] & 0x38) >> 3]; + c->layer[2].interleaving = (val[5] & 0xe0) >> 5; + } + } + + /* statistics */ + + stats = &c->strength; + stats->len = 0; + /* let the connected tuner set RSSI property cache */ + if (fe->ops.tuner_ops.get_rf_strength) { + u16 dummy; + + fe->ops.tuner_ops.get_rf_strength(fe, &dummy); + } + + stats = &c->cnr; + stats->len = 1; + stats->stat[0].scale = FE_SCALE_NOT_AVAILABLE; + cndat = 0; + ret = reg_read(state, 0x8b, val, 3); + if (ret == 0) + cndat = val[0] << 16 | val[1] << 8 | val[2]; + if (cndat != 0) { + u32 p, tmp; + s64 cn; + + /* + * cnr[mdB] = 0.024 P^4 - 1.6 P^3 + 39.8 P^2 + 549.1 P + 3096.5 + * (P = 10log10(5505024/cndat)) + */ + /* cn = cnr << 3 (61.3 fixed point float */ + /* p = 10log10(5505024/cndat) << 24 (8.24 fixed point float)*/ + p = intlog10(5505024) - intlog10(cndat); + p *= 10; + + cn = 24772; + cn += div64_s64(43827LL * p, 10) >> 24; + tmp = p >> 8; + cn += div64_s64(3184LL * tmp * tmp, 10) >> 32; + tmp = p >> 13; + cn -= div64_s64(128LL * tmp * tmp * tmp, 10) >> 33; + tmp = p >> 18; + cn += div64_s64(192LL * tmp * tmp * tmp * tmp, 1000) >> 24; + + stats->stat[0].svalue = cn >> 3; + stats->stat[0].scale = FE_SCALE_DECIBEL; + } + + /* per-layer post viterbi BER (or PER? config dependent?) */ + stats = &c->post_bit_error; + memset(stats, 0, sizeof(*stats)); + stats->len = layers; + ret = reg_read(state, 0x9d, val, 15); + if (ret < 0) + for (i = 0; i < layers; i++) + stats->stat[i].scale = FE_SCALE_NOT_AVAILABLE; + else { + for (i = 0; i < layers; i++) { + stats->stat[i].scale = FE_SCALE_COUNTER; + stats->stat[i].uvalue = val[i * 3] << 16 + | val[i * 3 + 1] << 8 | val[i * 3 + 2]; + } + } + stats = &c->post_bit_count; + memset(stats, 0, sizeof(*stats)); + stats->len = layers; + if (ret < 0) + for (i = 0; i < layers; i++) + stats->stat[i].scale = FE_SCALE_NOT_AVAILABLE; + else { + for (i = 0; i < layers; i++) { + stats->stat[i].scale = FE_SCALE_COUNTER; + stats->stat[i].uvalue = + val[9 + i * 2] << 8 | val[9 + i * 2 + 1]; + stats->stat[i].uvalue *= 204 * 8; + } + } + + return 0; +} + +static const struct reg_val reset_sat = { 0x03, 0x01 }; +static const struct reg_val reset_ter = { 0x01, 0x40 }; + +static int tc90522_set_frontend(struct dvb_frontend *fe) +{ + struct tc90522_state *state; + int ret; + + state = fe->demodulator_priv; + + if (fe->ops.tuner_ops.set_params) + ret = fe->ops.tuner_ops.set_params(fe); + else + ret = -ENODEV; + if (ret < 0) + goto failed; + + if (fe->ops.delsys[0] == SYS_ISDBS) { + ret = tc90522s_set_tsid(fe); + if (ret < 0) + goto failed; + ret = reg_write(state, &reset_sat, 1); + } else { + ret = tc90522t_set_layers(fe); + if (ret < 0) + goto failed; + ret = reg_write(state, &reset_ter, 1); + } + if (ret < 0) + goto failed; + + return 0; + +failed: + dev_warn(&state->tuner_i2c.dev, "(%s) failed. [adap%d-fe%d]\n", + __func__, fe->dvb->num, fe->id); + return ret; +} + +static int tc90522_get_tune_settings(struct dvb_frontend *fe, + struct dvb_frontend_tune_settings *settings) +{ + if (fe->ops.delsys[0] == SYS_ISDBS) { + settings->min_delay_ms = 250; + settings->step_size = 1000; + settings->max_drift = settings->step_size * 2; + } else { + settings->min_delay_ms = 400; + settings->step_size = 142857; + settings->max_drift = settings->step_size; + } + return 0; +} + +static int tc90522_set_if_agc(struct dvb_frontend *fe, bool on) +{ + struct reg_val agc_sat[] = { + { 0x0a, 0x00 }, + { 0x10, 0x30 }, + { 0x11, 0x00 }, + { 0x03, 0x01 }, + }; + struct reg_val agc_ter[] = { + { 0x25, 0x00 }, + { 0x23, 0x4c }, + { 0x01, 0x40 }, + }; + struct tc90522_state *state; + struct reg_val *rv; + int num; + + state = fe->demodulator_priv; + if (fe->ops.delsys[0] == SYS_ISDBS) { + agc_sat[0].val = on ? 0xff : 0x00; + agc_sat[1].val |= 0x80; + agc_sat[1].val |= on ? 0x01 : 0x00; + agc_sat[2].val |= on ? 0x40 : 0x00; + rv = agc_sat; + num = ARRAY_SIZE(agc_sat); + } else { + agc_ter[0].val = on ? 0x40 : 0x00; + agc_ter[1].val |= on ? 0x00 : 0x01; + rv = agc_ter; + num = ARRAY_SIZE(agc_ter); + } + return reg_write(state, rv, num); +} + +static const struct reg_val sleep_sat = { 0x17, 0x01 }; +static const struct reg_val sleep_ter = { 0x03, 0x90 }; + +static int tc90522_sleep(struct dvb_frontend *fe) +{ + struct tc90522_state *state; + int ret; + + state = fe->demodulator_priv; + if (fe->ops.delsys[0] == SYS_ISDBS) + ret = reg_write(state, &sleep_sat, 1); + else { + ret = reg_write(state, &sleep_ter, 1); + if (ret == 0 && fe->ops.set_lna && + fe->dtv_property_cache.lna == LNA_AUTO) { + fe->dtv_property_cache.lna = 0; + ret = fe->ops.set_lna(fe); + fe->dtv_property_cache.lna = LNA_AUTO; + } + } + if (ret < 0) + dev_warn(&state->tuner_i2c.dev, + "(%s) failed. [adap%d-fe%d]\n", + __func__, fe->dvb->num, fe->id); + return ret; +} + +static const struct reg_val wakeup_sat = { 0x17, 0x00 }; +static const struct reg_val wakeup_ter = { 0x03, 0x80 }; + +static int tc90522_init(struct dvb_frontend *fe) +{ + struct tc90522_state *state; + int ret; + + /* + * Because the init sequence is not public, + * the parent device/driver should have init'ed the device before. + * just wake up the device here. + */ + + state = fe->demodulator_priv; + if (fe->ops.delsys[0] == SYS_ISDBS) + ret = reg_write(state, &wakeup_sat, 1); + else { + ret = reg_write(state, &wakeup_ter, 1); + if (ret == 0 && fe->ops.set_lna && + fe->dtv_property_cache.lna == LNA_AUTO) { + fe->dtv_property_cache.lna = 1; + ret = fe->ops.set_lna(fe); + fe->dtv_property_cache.lna = LNA_AUTO; + } + } + if (ret < 0) { + dev_warn(&state->tuner_i2c.dev, + "(%s) failed. [adap%d-fe%d]\n", + __func__, fe->dvb->num, fe->id); + return ret; + } + + /* prefer 'all-layers' to 'none' as a default */ + if (fe->dtv_property_cache.isdbt_layer_enabled == 0) + fe->dtv_property_cache.isdbt_layer_enabled = 7; + return tc90522_set_if_agc(fe, true); +} + + +/* + * tuner I2C adapter functions + */ + +static int +tc90522_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + struct tc90522_state *state; + struct i2c_msg *new_msgs; + int i, j; + int ret, rd_num; + u8 wbuf[256]; + u8 *p, *bufend; + + if (num <= 0) + return -EINVAL; + + rd_num = 0; + for (i = 0; i < num; i++) + if (msgs[i].flags & I2C_M_RD) + rd_num++; + new_msgs = kmalloc(sizeof(*new_msgs) * (num + rd_num), GFP_KERNEL); + if (!new_msgs) + return -ENOMEM; + + state = i2c_get_adapdata(adap); + p = wbuf; + bufend = wbuf + sizeof(wbuf); + for (i = 0, j = 0; i < num; i++, j++) { + new_msgs[j].addr = state->i2c_client->addr; + new_msgs[j].flags = msgs[i].flags; + + if (msgs[i].flags & I2C_M_RD) { + new_msgs[j].flags &= ~I2C_M_RD; + if (p + 2 > bufend) + break; + p[0] = TC90522_I2C_THRU_REG; + p[1] = msgs[i].addr << 1 | 0x01; + new_msgs[j].buf = p; + new_msgs[j].len = 2; + p += 2; + j++; + new_msgs[j].addr = state->i2c_client->addr; + new_msgs[j].flags = msgs[i].flags; + new_msgs[j].buf = msgs[i].buf; + new_msgs[j].len = msgs[i].len; + continue; + } + + if (p + msgs[i].len + 2 > bufend) + break; + p[0] = TC90522_I2C_THRU_REG; + p[1] = msgs[i].addr << 1; + memcpy(p + 2, msgs[i].buf, msgs[i].len); + new_msgs[j].buf = p; + new_msgs[j].len = msgs[i].len + 2; + p += new_msgs[j].len; + } + + if (i < num) + ret = -ENOMEM; + else + ret = i2c_transfer(state->i2c_client->adapter, new_msgs, j); + if (ret >= 0 && ret < j) + ret = -EIO; + kfree(new_msgs); + return (ret == j) ? num : ret; +} + +static u32 tc90522_functionality(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C; +} + +static const struct i2c_algorithm tc90522_tuner_i2c_algo = { + .master_xfer = &tc90522_master_xfer, + .functionality = &tc90522_functionality, +}; + + +/* + * I2C driver functions + */ + +static const struct dvb_frontend_ops tc90522_ops_sat = { + .delsys = { SYS_ISDBS }, + .info = { + .name = "Toshiba TC90522 ISDB-S module", + .frequency_min = 950000, + .frequency_max = 2150000, + .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO | + FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO, + }, + + .init = tc90522_init, + .sleep = tc90522_sleep, + .set_frontend = tc90522_set_frontend, + .get_tune_settings = tc90522_get_tune_settings, + + .get_frontend = tc90522s_get_frontend, + .read_status = tc90522s_read_status, +}; + +static const struct dvb_frontend_ops tc90522_ops_ter = { + .delsys = { SYS_ISDBT }, + .info = { + .name = "Toshiba TC90522 ISDB-T module", + .frequency_min = 470000000, + .frequency_max = 770000000, + .frequency_stepsize = 142857, + .caps = FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | + FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | + FE_CAN_HIERARCHY_AUTO, + }, + + .init = tc90522_init, + .sleep = tc90522_sleep, + .set_frontend = tc90522_set_frontend, + .get_tune_settings = tc90522_get_tune_settings, + + .get_frontend = tc90522t_get_frontend, + .read_status = tc90522t_read_status, +}; + + +static int tc90522_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct tc90522_state *state; + struct tc90522_config *cfg; + const struct dvb_frontend_ops *ops; + struct i2c_adapter *adap; + int ret; + + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + state->i2c_client = client; + + cfg = client->dev.platform_data; + memcpy(&state->cfg, cfg, sizeof(state->cfg)); + cfg->fe = state->cfg.fe = &state->fe; + ops = id->driver_data == 0 ? &tc90522_ops_sat : &tc90522_ops_ter; + memcpy(&state->fe.ops, ops, sizeof(*ops)); + state->fe.demodulator_priv = state; + + adap = &state->tuner_i2c; + adap->owner = THIS_MODULE; + adap->algo = &tc90522_tuner_i2c_algo; + adap->dev.parent = &client->dev; + strlcpy(adap->name, "tc90522_sub", sizeof(adap->name)); + i2c_set_adapdata(adap, state); + ret = i2c_add_adapter(adap); + if (ret < 0) + goto err; + cfg->tuner_i2c = state->cfg.tuner_i2c = adap; + + i2c_set_clientdata(client, &state->cfg); + dev_info(&client->dev, "Toshiba TC90522 attached.\n"); + return 0; + +err: + kfree(state); + return ret; +} + +static int tc90522_remove(struct i2c_client *client) +{ + struct tc90522_state *state; + + state = cfg_to_state(i2c_get_clientdata(client)); + i2c_del_adapter(&state->tuner_i2c); + kfree(state); + return 0; +} + + +static const struct i2c_device_id tc90522_id[] = { + { TC90522_I2C_DEV_SAT, 0 }, + { TC90522_I2C_DEV_TER, 1 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, tc90522_id); + +static struct i2c_driver tc90522_driver = { + .driver = { + .name = "tc90522", + }, + .probe = tc90522_probe, + .remove = tc90522_remove, + .id_table = tc90522_id, +}; + +module_i2c_driver(tc90522_driver); + +MODULE_DESCRIPTION("Toshiba TC90522 frontend"); +MODULE_AUTHOR("Akihiro TSUKADA"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/tc90522.h b/drivers/media/dvb-frontends/tc90522.h new file mode 100644 index 000000000000..b1cbddfa6ee6 --- /dev/null +++ b/drivers/media/dvb-frontends/tc90522.h @@ -0,0 +1,42 @@ +/* + * Toshiba TC90522 Demodulator + * + * Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* + * The demod has 4 input (2xISDB-T and 2xISDB-S), + * and provides independent sub modules for each input. + * As the sub modules work in parallel and have the separate i2c addr's, + * this driver treats each sub module as one demod device. + */ + +#ifndef TC90522_H +#define TC90522_H + +#include <linux/i2c.h> +#include "dvb_frontend.h" + +/* I2C device types */ +#define TC90522_I2C_DEV_SAT "tc90522sat" +#define TC90522_I2C_DEV_TER "tc90522ter" + +struct tc90522_config { + /* [OUT] frontend returned by driver */ + struct dvb_frontend *fe; + + /* [OUT] tuner I2C adapter returned by driver */ + struct i2c_adapter *tuner_i2c; +}; + +#endif /* TC90522_H */ diff --git a/drivers/media/dvb-frontends/tda10071.c b/drivers/media/dvb-frontends/tda10071.c index 9619be5d4827..4a19b85995f1 100644 --- a/drivers/media/dvb-frontends/tda10071.c +++ b/drivers/media/dvb-frontends/tda10071.c @@ -1037,7 +1037,7 @@ static int tda10071_init(struct dvb_frontend *fe) ret = -EFAULT; goto error; } else { - priv->warm = 1; + priv->warm = true; } cmd.args[0] = CMD_GET_FW_VERSION; diff --git a/drivers/media/dvb-frontends/zl10039.c b/drivers/media/dvb-frontends/zl10039.c index 91b6b2e9b792..ee09ec26c553 100644 --- a/drivers/media/dvb-frontends/zl10039.c +++ b/drivers/media/dvb-frontends/zl10039.c @@ -111,7 +111,7 @@ static int zl10039_write(struct zl10039_state *state, if (1 + count > sizeof(buf)) { printk(KERN_WARNING - "%s: i2c wr reg=%04x: len=%zd is too big!\n", + "%s: i2c wr reg=%04x: len=%zu is too big!\n", KBUILD_MODNAME, reg, count); return -EINVAL; } |