aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb-frontends
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb-frontends')
-rw-r--r--drivers/media/dvb-frontends/Kconfig20
-rw-r--r--drivers/media/dvb-frontends/Makefile4
-rw-r--r--drivers/media/dvb-frontends/af9013.c24
-rw-r--r--drivers/media/dvb-frontends/af9033.c757
-rw-r--r--drivers/media/dvb-frontends/af9033.h58
-rw-r--r--drivers/media/dvb-frontends/af9033_priv.h1
-rw-r--r--drivers/media/dvb-frontends/as102_fe.c480
-rw-r--r--drivers/media/dvb-frontends/as102_fe.h29
-rw-r--r--drivers/media/dvb-frontends/as102_fe_types.h188
-rw-r--r--drivers/media/dvb-frontends/bcm3510.c6
-rw-r--r--drivers/media/dvb-frontends/cxd2820r_c.c4
-rw-r--r--drivers/media/dvb-frontends/cxd2820r_core.c4
-rw-r--r--drivers/media/dvb-frontends/cxd2820r_t.c4
-rw-r--r--drivers/media/dvb-frontends/dib7000p.c2
-rw-r--r--drivers/media/dvb-frontends/drx39xyj/drxj.c38
-rw-r--r--drivers/media/dvb-frontends/drxd_hard.c9
-rw-r--r--drivers/media/dvb-frontends/drxk_hard.c37
-rw-r--r--drivers/media/dvb-frontends/m88ds3103.c101
-rw-r--r--drivers/media/dvb-frontends/m88ds3103.h35
-rw-r--r--drivers/media/dvb-frontends/mb86a16.c6
-rw-r--r--drivers/media/dvb-frontends/mb86a20s.c14
-rw-r--r--drivers/media/dvb-frontends/mt312.c2
-rw-r--r--drivers/media/dvb-frontends/or51211.c2
-rw-r--r--drivers/media/dvb-frontends/rtl2832.c2
-rw-r--r--drivers/media/dvb-frontends/rtl2832_sdr.c118
-rw-r--r--drivers/media/dvb-frontends/si2165.c63
-rw-r--r--drivers/media/dvb-frontends/si2165_priv.h2
-rw-r--r--drivers/media/dvb-frontends/si2168.c129
-rw-r--r--drivers/media/dvb-frontends/si2168.h6
-rw-r--r--drivers/media/dvb-frontends/si2168_priv.h2
-rw-r--r--drivers/media/dvb-frontends/si21xx.c3
-rw-r--r--drivers/media/dvb-frontends/sp2.c441
-rw-r--r--drivers/media/dvb-frontends/sp2.h53
-rw-r--r--drivers/media/dvb-frontends/sp2_priv.h50
-rw-r--r--drivers/media/dvb-frontends/sp8870.c3
-rw-r--r--drivers/media/dvb-frontends/stv0367.c12
-rw-r--r--drivers/media/dvb-frontends/stv0900_core.c7
-rw-r--r--drivers/media/dvb-frontends/stv0900_sw.c3
-rw-r--r--drivers/media/dvb-frontends/tc90522.c840
-rw-r--r--drivers/media/dvb-frontends/tc90522.h42
-rw-r--r--drivers/media/dvb-frontends/tda10071.c2
-rw-r--r--drivers/media/dvb-frontends/zl10039.c2
42 files changed, 2977 insertions, 628 deletions
diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
index fe0ddcc..5a13454 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 edf103d..ba59df6 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 ecf6388..8001690 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 5c90ea6..63a89c1 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 539f4db..6ad22b6 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 ded7b67..c12c92c 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 0000000..4936658
--- /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 0000000..a7c9143
--- /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 0000000..80a5398
--- /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 39a29dd..638c7aa 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 0f4657e..149fdca 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 03930d5..cd2af3e 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;
}
diff --git a/drivers/media/dvb-frontends/cxd2820r_t.c b/drivers/media/dvb-frontends/cxd2820r_t.c
index 9b5a45b..51401d0 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 661760d..589134e 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 7ca7a21..5ec221f 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 ae2276d..687e893 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 cce94a7..6721951 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 dfe0c2f..81657e9 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 bbb7e3a..9b3b496 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 9ae40ab..3ddea44 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 b931179..e6f165a 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 a74ac0d..2163490 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 10cfc05..873ea1d 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 fdbed35..eb737cf 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 023e0f4..7bf98cf 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 3a2d6c5..98ddb49 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 d4cc93f..2b70cf1 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 8f81d97..1cd93be 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 3c5b5ab..e086d67 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 ebbf502..e13983e 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 73b47cc..16850e2 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 0000000..9b684d5
--- /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 = &reg,
+ .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 0000000..6cceea0
--- /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 0000000..37fef7b
--- /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 2aa8ef7..57dc2aba 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 59b6e66..b31ff26 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 e5a87b5..2c88abf 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 4ce1d26..a0a7b16 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 0000000..d9905fb
--- /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 *)&regs[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 = &reg,
+ .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, &reg, 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, &reg, 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, &reg, 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, &reg, 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 0000000..b1cbddf
--- /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 9619be5..4a19b85 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 91b6b2e..ee09ec2 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;
}

Privacy Policy