summaryrefslogtreecommitdiff
path: root/drivers/media/dvb-frontends
diff options
context:
space:
mode:
authorAndré Fabian Silva Delgado <emulatorman@parabola.nu>2015-09-08 01:01:14 -0300
committerAndré Fabian Silva Delgado <emulatorman@parabola.nu>2015-09-08 01:01:14 -0300
commite5fd91f1ef340da553f7a79da9540c3db711c937 (patch)
treeb11842027dc6641da63f4bcc524f8678263304a3 /drivers/media/dvb-frontends
parent2a9b0348e685a63d97486f6749622b61e9e3292f (diff)
Linux-libre 4.2-gnu
Diffstat (limited to 'drivers/media/dvb-frontends')
-rw-r--r--drivers/media/dvb-frontends/Kconfig11
-rw-r--r--drivers/media/dvb-frontends/Makefile1
-rw-r--r--drivers/media/dvb-frontends/a8293.c89
-rw-r--r--drivers/media/dvb-frontends/a8293.h15
-rw-r--r--drivers/media/dvb-frontends/af9013.c4
-rw-r--r--drivers/media/dvb-frontends/af9033.c4
-rw-r--r--drivers/media/dvb-frontends/as102_fe.c4
-rw-r--r--drivers/media/dvb-frontends/atbm8830.c3
-rw-r--r--drivers/media/dvb-frontends/au8522_dig.c4
-rw-r--r--drivers/media/dvb-frontends/au8522_priv.h2
-rw-r--r--drivers/media/dvb-frontends/bcm3510.c6
-rw-r--r--drivers/media/dvb-frontends/cx22700.c9
-rw-r--r--drivers/media/dvb-frontends/cx22702.c2
-rw-r--r--drivers/media/dvb-frontends/cx24110.c19
-rw-r--r--drivers/media/dvb-frontends/cx24116.c38
-rw-r--r--drivers/media/dvb-frontends/cx24117.c40
-rw-r--r--drivers/media/dvb-frontends/cx24120.c1595
-rw-r--r--drivers/media/dvb-frontends/cx24120.h58
-rw-r--r--drivers/media/dvb-frontends/cx24123.c18
-rw-r--r--drivers/media/dvb-frontends/cx24123.h2
-rw-r--r--drivers/media/dvb-frontends/cxd2820r_c.c2
-rw-r--r--drivers/media/dvb-frontends/cxd2820r_core.c5
-rw-r--r--drivers/media/dvb-frontends/cxd2820r_priv.h8
-rw-r--r--drivers/media/dvb-frontends/cxd2820r_t.c2
-rw-r--r--drivers/media/dvb-frontends/cxd2820r_t2.c2
-rw-r--r--drivers/media/dvb-frontends/dib0070.c575
-rw-r--r--drivers/media/dvb-frontends/dib0090.c4
-rw-r--r--drivers/media/dvb-frontends/dib3000mb.c7
-rw-r--r--drivers/media/dvb-frontends/dib3000mc.c20
-rw-r--r--drivers/media/dvb-frontends/dib7000m.c2
-rw-r--r--drivers/media/dvb-frontends/dib7000p.c6
-rw-r--r--drivers/media/dvb-frontends/dib8000.c10
-rw-r--r--drivers/media/dvb-frontends/dib8000.h2
-rw-r--r--drivers/media/dvb-frontends/dib9000.c4
-rw-r--r--drivers/media/dvb-frontends/drx39xyj/drxj.c42
-rw-r--r--drivers/media/dvb-frontends/drxd_hard.c2
-rw-r--r--drivers/media/dvb-frontends/drxk_hard.c11
-rw-r--r--drivers/media/dvb-frontends/drxk_hard.h2
-rw-r--r--drivers/media/dvb-frontends/ds3000.c13
-rw-r--r--drivers/media/dvb-frontends/dvb_dummy_fe.c9
-rw-r--r--drivers/media/dvb-frontends/ec100.c2
-rw-r--r--drivers/media/dvb-frontends/hd29l2.c2
-rw-r--r--drivers/media/dvb-frontends/hd29l2_priv.h2
-rw-r--r--drivers/media/dvb-frontends/isl6405.c3
-rw-r--r--drivers/media/dvb-frontends/isl6421.c6
-rw-r--r--drivers/media/dvb-frontends/l64781.c2
-rw-r--r--drivers/media/dvb-frontends/lg2160.c2
-rw-r--r--drivers/media/dvb-frontends/lgdt3305.c4
-rw-r--r--drivers/media/dvb-frontends/lgdt3306a.c11
-rw-r--r--drivers/media/dvb-frontends/lgdt330x.c8
-rw-r--r--drivers/media/dvb-frontends/lgs8gl5.c2
-rw-r--r--drivers/media/dvb-frontends/lgs8gxx.c3
-rw-r--r--drivers/media/dvb-frontends/lnbp21.c4
-rw-r--r--drivers/media/dvb-frontends/lnbp22.c3
-rw-r--r--drivers/media/dvb-frontends/m88ds3103.c1275
-rw-r--r--drivers/media/dvb-frontends/m88ds3103.h67
-rw-r--r--drivers/media/dvb-frontends/m88ds3103_priv.h20
-rw-r--r--drivers/media/dvb-frontends/m88rs2000.c19
-rw-r--r--drivers/media/dvb-frontends/mb86a16.c7
-rw-r--r--drivers/media/dvb-frontends/mb86a16.h3
-rw-r--r--drivers/media/dvb-frontends/mb86a20s.c6
-rw-r--r--drivers/media/dvb-frontends/mb86a20s.h2
-rw-r--r--drivers/media/dvb-frontends/mt312.c17
-rw-r--r--drivers/media/dvb-frontends/mt352.c2
-rw-r--r--drivers/media/dvb-frontends/nxt200x.c2
-rw-r--r--drivers/media/dvb-frontends/nxt6000.c12
-rw-r--r--drivers/media/dvb-frontends/or51132.c6
-rw-r--r--drivers/media/dvb-frontends/or51211.c2
-rw-r--r--drivers/media/dvb-frontends/rtl2830.c2
-rw-r--r--drivers/media/dvb-frontends/rtl2830_priv.h2
-rw-r--r--drivers/media/dvb-frontends/rtl2832.c10
-rw-r--r--drivers/media/dvb-frontends/rtl2832.h2
-rw-r--r--drivers/media/dvb-frontends/rtl2832_priv.h51
-rw-r--r--drivers/media/dvb-frontends/rtl2832_sdr.c120
-rw-r--r--drivers/media/dvb-frontends/rtl2832_sdr.h1
-rw-r--r--drivers/media/dvb-frontends/s5h1409.c6
-rw-r--r--drivers/media/dvb-frontends/s5h1411.c6
-rw-r--r--drivers/media/dvb-frontends/s5h1420.c41
-rw-r--r--drivers/media/dvb-frontends/s5h1432.c4
-rw-r--r--drivers/media/dvb-frontends/s921.c6
-rw-r--r--drivers/media/dvb-frontends/s921.h2
-rw-r--r--drivers/media/dvb-frontends/si2165.c2
-rw-r--r--drivers/media/dvb-frontends/si2168.c144
-rw-r--r--drivers/media/dvb-frontends/si2168.h3
-rw-r--r--drivers/media/dvb-frontends/si2168_priv.h6
-rw-r--r--drivers/media/dvb-frontends/si21xx.c10
-rw-r--r--drivers/media/dvb-frontends/sp8870.c3
-rw-r--r--drivers/media/dvb-frontends/sp887x.c2
-rw-r--r--drivers/media/dvb-frontends/stb0899_drv.c8
-rw-r--r--drivers/media/dvb-frontends/stv0288.c39
-rw-r--r--drivers/media/dvb-frontends/stv0297.c19
-rw-r--r--drivers/media/dvb-frontends/stv0299.c34
-rw-r--r--drivers/media/dvb-frontends/stv0367.c12
-rw-r--r--drivers/media/dvb-frontends/stv0367_priv.h2
-rw-r--r--drivers/media/dvb-frontends/stv0900_core.c6
-rw-r--r--drivers/media/dvb-frontends/stv0900_sw.c6
-rw-r--r--drivers/media/dvb-frontends/stv090x.c5
-rw-r--r--drivers/media/dvb-frontends/stv6110.c2
-rw-r--r--drivers/media/dvb-frontends/tc90522.c17
-rw-r--r--drivers/media/dvb-frontends/tda10021.c9
-rw-r--r--drivers/media/dvb-frontends/tda10023.c5
-rw-r--r--drivers/media/dvb-frontends/tda10048.c2
-rw-r--r--drivers/media/dvb-frontends/tda1004x.c5
-rw-r--r--drivers/media/dvb-frontends/tda10071.c117
-rw-r--r--drivers/media/dvb-frontends/tda10071.h29
-rw-r--r--drivers/media/dvb-frontends/tda10071_priv.h11
-rw-r--r--drivers/media/dvb-frontends/tda10086.c13
-rw-r--r--drivers/media/dvb-frontends/tda8083.c38
-rw-r--r--drivers/media/dvb-frontends/ts2020.c591
-rw-r--r--drivers/media/dvb-frontends/ts2020.h17
-rw-r--r--drivers/media/dvb-frontends/ves1820.c6
-rw-r--r--drivers/media/dvb-frontends/ves1x93.c15
-rw-r--r--drivers/media/dvb-frontends/zl10353.c12
113 files changed, 3974 insertions, 1615 deletions
diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
index 97c151d5b..5ab90f36a 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -36,8 +36,9 @@ config DVB_STV6110x
A Silicon tuner that supports DVB-S and DVB-S2 modes
config DVB_M88DS3103
- tristate "Montage M88DS3103"
+ tristate "Montage Technology M88DS3103"
depends on DVB_CORE && I2C && I2C_MUX
+ select REGMAP_I2C
default m if !MEDIA_SUBDRV_AUTOSELECT
help
Say Y when you want to support this frontend.
@@ -223,6 +224,13 @@ config DVB_CX24117
help
A Dual DVB-S/S2 tuner module. Say Y when you want to support this frontend.
+config DVB_CX24120
+ tristate "Conexant CX24120 based"
+ depends on DVB_CORE && I2C
+ default m if !MEDIA_SUBDRV_AUTOSELECT
+ help
+ A DVB-S/S2 tuner module. Say Y when you want to support this frontend.
+
config DVB_SI21XX
tristate "Silicon Labs SI21XX based"
depends on DVB_CORE && I2C
@@ -233,6 +241,7 @@ config DVB_SI21XX
config DVB_TS2020
tristate "Montage Tehnology TS2020 based tuners"
depends on DVB_CORE && I2C
+ select REGMAP_I2C
default m if !MEDIA_SUBDRV_AUTOSELECT
help
A DVB-S/S2 silicon tuner. Say Y when you want to support this tuner.
diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile
index 23d399bec..ebab1b83e 100644
--- a/drivers/media/dvb-frontends/Makefile
+++ b/drivers/media/dvb-frontends/Makefile
@@ -83,6 +83,7 @@ obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o
obj-$(CONFIG_DVB_AF9013) += af9013.o
obj-$(CONFIG_DVB_CX24116) += cx24116.o
obj-$(CONFIG_DVB_CX24117) += cx24117.o
+obj-$(CONFIG_DVB_CX24120) += cx24120.o
obj-$(CONFIG_DVB_SI21XX) += si21xx.o
obj-$(CONFIG_DVB_SI2168) += si2168.o
obj-$(CONFIG_DVB_STV0288) += stv0288.o
diff --git a/drivers/media/dvb-frontends/a8293.c b/drivers/media/dvb-frontends/a8293.c
index 780da5813..97ecbe010 100644
--- a/drivers/media/dvb-frontends/a8293.c
+++ b/drivers/media/dvb-frontends/a8293.c
@@ -22,8 +22,9 @@
#include "a8293.h"
struct a8293_priv {
+ u8 i2c_addr;
struct i2c_adapter *i2c;
- const struct a8293_config *cfg;
+ struct i2c_client *client;
u8 reg[2];
};
@@ -32,7 +33,7 @@ static int a8293_i2c(struct a8293_priv *priv, u8 *val, int len, bool rd)
int ret;
struct i2c_msg msg[1] = {
{
- .addr = priv->cfg->i2c_addr,
+ .addr = priv->i2c_addr,
.len = len,
.buf = val,
}
@@ -66,7 +67,7 @@ static int a8293_rd(struct a8293_priv *priv, u8 *val, int len)
}
static int a8293_set_voltage(struct dvb_frontend *fe,
- fe_sec_voltage_t fe_sec_voltage)
+ enum fe_sec_voltage fe_sec_voltage)
{
struct a8293_priv *priv = fe->sec_priv;
int ret;
@@ -128,7 +129,7 @@ struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
/* setup the priv */
priv->i2c = i2c;
- priv->cfg = cfg;
+ priv->i2c_addr = cfg->i2c_addr;
fe->sec_priv = priv;
/* check if the SEC is there */
@@ -164,6 +165,86 @@ err:
}
EXPORT_SYMBOL(a8293_attach);
+static int a8293_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct a8293_priv *dev;
+ struct a8293_platform_data *pdata = client->dev.platform_data;
+ struct dvb_frontend *fe = pdata->dvb_frontend;
+ int ret;
+ u8 buf[2];
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ dev->client = client;
+ dev->i2c = client->adapter;
+ dev->i2c_addr = client->addr;
+
+ /* check if the SEC is there */
+ ret = a8293_rd(dev, buf, 2);
+ if (ret)
+ goto err_kfree;
+
+ /* ENB=0 */
+ dev->reg[0] = 0x10;
+ ret = a8293_wr(dev, &dev->reg[0], 1);
+ if (ret)
+ goto err_kfree;
+
+ /* TMODE=0, TGATE=1 */
+ dev->reg[1] = 0x82;
+ ret = a8293_wr(dev, &dev->reg[1], 1);
+ if (ret)
+ goto err_kfree;
+
+ /* override frontend ops */
+ fe->ops.set_voltage = a8293_set_voltage;
+
+ fe->sec_priv = dev;
+ i2c_set_clientdata(client, dev);
+
+ dev_info(&client->dev, "Allegro A8293 SEC successfully attached\n");
+ return 0;
+err_kfree:
+ kfree(dev);
+err:
+ dev_dbg(&client->dev, "failed=%d\n", ret);
+ return ret;
+}
+
+static int a8293_remove(struct i2c_client *client)
+{
+ struct a8293_dev *dev = i2c_get_clientdata(client);
+
+ dev_dbg(&client->dev, "\n");
+
+ kfree(dev);
+ return 0;
+}
+
+static const struct i2c_device_id a8293_id_table[] = {
+ {"a8293", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, a8293_id_table);
+
+static struct i2c_driver a8293_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "a8293",
+ .suppress_bind_attrs = true,
+ },
+ .probe = a8293_probe,
+ .remove = a8293_remove,
+ .id_table = a8293_id_table,
+};
+
+module_i2c_driver(a8293_driver);
+
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
MODULE_DESCRIPTION("Allegro A8293 SEC driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/a8293.h b/drivers/media/dvb-frontends/a8293.h
index 5f0411939..aff36538f 100644
--- a/drivers/media/dvb-frontends/a8293.h
+++ b/drivers/media/dvb-frontends/a8293.h
@@ -21,8 +21,23 @@
#ifndef A8293_H
#define A8293_H
+#include "dvb_frontend.h"
#include <linux/kconfig.h>
+/*
+ * I2C address
+ * 0x08, 0x09, 0x0a, 0x0b
+ */
+
+/**
+ * struct a8293_platform_data - Platform data for the a8293 driver
+ * @dvb_frontend: DVB frontend.
+ */
+struct a8293_platform_data {
+ struct dvb_frontend *dvb_frontend;
+};
+
+
struct a8293_config {
u8 i2c_addr;
};
diff --git a/drivers/media/dvb-frontends/af9013.c b/drivers/media/dvb-frontends/af9013.c
index 8d75d6d0b..bbc226144 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -39,7 +39,7 @@ struct af9013_state {
u32 ucblocks;
u16 snr;
u32 bandwidth_hz;
- fe_status_t fe_status;
+ enum fe_status fe_status;
unsigned long set_frontend_jiffies;
unsigned long read_status_jiffies;
bool first_tune;
@@ -983,7 +983,7 @@ err:
return ret;
}
-static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int af9013_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct af9013_state *state = fe->demodulator_priv;
int ret;
diff --git a/drivers/media/dvb-frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c
index 82ce47bdf..59018afaa 100644
--- a/drivers/media/dvb-frontends/af9033.c
+++ b/drivers/media/dvb-frontends/af9033.c
@@ -35,7 +35,7 @@ struct af9033_dev {
bool ts_mode_parallel;
bool ts_mode_serial;
- fe_status_t fe_status;
+ enum fe_status fe_status;
u64 post_bit_error_prev; /* for old read_ber we return (curr - prev) */
u64 post_bit_error;
u64 post_bit_count;
@@ -818,7 +818,7 @@ err:
return ret;
}
-static int af9033_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int af9033_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct af9033_dev *dev = fe->demodulator_priv;
int ret;
diff --git a/drivers/media/dvb-frontends/as102_fe.c b/drivers/media/dvb-frontends/as102_fe.c
index 493665899..544c5f65d 100644
--- a/drivers/media/dvb-frontends/as102_fe.c
+++ b/drivers/media/dvb-frontends/as102_fe.c
@@ -32,7 +32,7 @@ struct as102_state {
uint32_t ber;
};
-static uint8_t as102_fe_get_code_rate(fe_code_rate_t arg)
+static uint8_t as102_fe_get_code_rate(enum fe_code_rate arg)
{
uint8_t c;
@@ -306,7 +306,7 @@ static int as102_fe_get_tune_settings(struct dvb_frontend *fe,
return 0;
}
-static int as102_fe_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int as102_fe_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
int ret = 0;
struct as102_state *state = fe->demodulator_priv;
diff --git a/drivers/media/dvb-frontends/atbm8830.c b/drivers/media/dvb-frontends/atbm8830.c
index 4e11dc4b1..8fe552e29 100644
--- a/drivers/media/dvb-frontends/atbm8830.c
+++ b/drivers/media/dvb-frontends/atbm8830.c
@@ -335,7 +335,8 @@ static int atbm8830_get_tune_settings(struct dvb_frontend *fe,
return 0;
}
-static int atbm8830_read_status(struct dvb_frontend *fe, fe_status_t *fe_status)
+static int atbm8830_read_status(struct dvb_frontend *fe,
+ enum fe_status *fe_status)
{
struct atbm_state *priv = fe->demodulator_priv;
u8 locked = 0;
diff --git a/drivers/media/dvb-frontends/au8522_dig.c b/drivers/media/dvb-frontends/au8522_dig.c
index 5d06c99b0..b744a3f8d 100644
--- a/drivers/media/dvb-frontends/au8522_dig.c
+++ b/drivers/media/dvb-frontends/au8522_dig.c
@@ -552,7 +552,7 @@ static struct {
};
static int au8522_enable_modulation(struct dvb_frontend *fe,
- fe_modulation_t m)
+ enum fe_modulation m)
{
struct au8522_state *state = fe->demodulator_priv;
int i;
@@ -644,7 +644,7 @@ static int au8522_set_frontend(struct dvb_frontend *fe)
return 0;
}
-static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int au8522_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct au8522_state *state = fe->demodulator_priv;
u8 reg;
diff --git a/drivers/media/dvb-frontends/au8522_priv.h b/drivers/media/dvb-frontends/au8522_priv.h
index b8aca1c84..951b3847e 100644
--- a/drivers/media/dvb-frontends/au8522_priv.h
+++ b/drivers/media/dvb-frontends/au8522_priv.h
@@ -55,7 +55,7 @@ struct au8522_state {
struct dvb_frontend frontend;
u32 current_frequency;
- fe_modulation_t current_modulation;
+ enum fe_modulation current_modulation;
u32 fe_status;
unsigned int led_state;
diff --git a/drivers/media/dvb-frontends/bcm3510.c b/drivers/media/dvb-frontends/bcm3510.c
index 9121ecb72..d84d08a5b 100644
--- a/drivers/media/dvb-frontends/bcm3510.c
+++ b/drivers/media/dvb-frontends/bcm3510.c
@@ -287,7 +287,7 @@ static int bcm3510_refresh_state(struct bcm3510_state *st)
return 0;
}
-static int bcm3510_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int bcm3510_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct bcm3510_state* st = fe->demodulator_priv;
bcm3510_refresh_state(st);
@@ -683,7 +683,7 @@ static int bcm3510_reset(struct bcm3510_state *st)
if ((ret = bcm3510_writeB(st,0xa0,v)) < 0)
return ret;
- t = jiffies + 3*HZ;
+ t = jiffies + 3*HZ;
while (time_before(jiffies, t)) {
msleep(10);
if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
@@ -706,7 +706,7 @@ static int bcm3510_clear_reset(struct bcm3510_state *st)
if ((ret = bcm3510_writeB(st,0xa0,v)) < 0)
return ret;
- t = jiffies + 3*HZ;
+ t = jiffies + 3*HZ;
while (time_before(jiffies, t)) {
msleep(10);
if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
diff --git a/drivers/media/dvb-frontends/cx22700.c b/drivers/media/dvb-frontends/cx22700.c
index 86563260d..fd033cca6 100644
--- a/drivers/media/dvb-frontends/cx22700.c
+++ b/drivers/media/dvb-frontends/cx22700.c
@@ -191,9 +191,10 @@ static int cx22700_set_tps(struct cx22700_state *state,
static int cx22700_get_tps(struct cx22700_state *state,
struct dtv_frontend_properties *p)
{
- static const fe_modulation_t qam_tab [3] = { QPSK, QAM_16, QAM_64 };
- static const fe_code_rate_t fec_tab [5] = { FEC_1_2, FEC_2_3, FEC_3_4,
- FEC_5_6, FEC_7_8 };
+ static const enum fe_modulation qam_tab[3] = { QPSK, QAM_16, QAM_64 };
+ static const enum fe_code_rate fec_tab[5] = {
+ FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8
+ };
u8 val;
dprintk ("%s\n", __func__);
@@ -253,7 +254,7 @@ static int cx22700_init (struct dvb_frontend* fe)
return 0;
}
-static int cx22700_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int cx22700_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct cx22700_state* state = fe->demodulator_priv;
diff --git a/drivers/media/dvb-frontends/cx22702.c b/drivers/media/dvb-frontends/cx22702.c
index edc8eafc5..d2d06dcd7 100644
--- a/drivers/media/dvb-frontends/cx22702.c
+++ b/drivers/media/dvb-frontends/cx22702.c
@@ -452,7 +452,7 @@ static int cx22702_init(struct dvb_frontend *fe)
return 0;
}
-static int cx22702_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int cx22702_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct cx22702_state *state = fe->demodulator_priv;
u8 reg0A;
diff --git a/drivers/media/dvb-frontends/cx24110.c b/drivers/media/dvb-frontends/cx24110.c
index 7b510f2ae..cb36475e3 100644
--- a/drivers/media/dvb-frontends/cx24110.c
+++ b/drivers/media/dvb-frontends/cx24110.c
@@ -143,7 +143,8 @@ static int cx24110_readreg (struct cx24110_state* state, u8 reg)
return b1[0];
}
-static int cx24110_set_inversion (struct cx24110_state* state, fe_spectral_inversion_t inversion)
+static int cx24110_set_inversion(struct cx24110_state *state,
+ enum fe_spectral_inversion inversion)
{
/* fixme (low): error handling */
@@ -177,7 +178,7 @@ static int cx24110_set_inversion (struct cx24110_state* state, fe_spectral_inver
return 0;
}
-static int cx24110_set_fec(struct cx24110_state* state, fe_code_rate_t fec)
+static int cx24110_set_fec(struct cx24110_state *state, enum fe_code_rate fec)
{
static const int rate[FEC_AUTO] = {-1, 1, 2, 3, 5, 7, -1};
static const int g1[FEC_AUTO] = {-1, 0x01, 0x02, 0x05, 0x15, 0x45, -1};
@@ -220,7 +221,7 @@ static int cx24110_set_fec(struct cx24110_state* state, fe_code_rate_t fec)
return 0;
}
-static fe_code_rate_t cx24110_get_fec (struct cx24110_state* state)
+static enum fe_code_rate cx24110_get_fec(struct cx24110_state *state)
{
int i;
@@ -365,7 +366,8 @@ static int cx24110_initfe(struct dvb_frontend* fe)
return 0;
}
-static int cx24110_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+static int cx24110_set_voltage(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage)
{
struct cx24110_state *state = fe->demodulator_priv;
@@ -379,7 +381,8 @@ static int cx24110_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
}
}
-static int cx24110_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
+static int cx24110_diseqc_send_burst(struct dvb_frontend *fe,
+ enum fe_sec_mini_cmd burst)
{
int rv, bit;
struct cx24110_state *state = fe->demodulator_priv;
@@ -434,7 +437,8 @@ static int cx24110_send_diseqc_msg(struct dvb_frontend* fe,
return 0;
}
-static int cx24110_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int cx24110_read_status(struct dvb_frontend *fe,
+ enum fe_status *status)
{
struct cx24110_state *state = fe->demodulator_priv;
@@ -574,7 +578,8 @@ static int cx24110_get_frontend(struct dvb_frontend *fe)
return 0;
}
-static int cx24110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+static int cx24110_set_tone(struct dvb_frontend *fe,
+ enum fe_sec_tone_mode tone)
{
struct cx24110_state *state = fe->demodulator_priv;
diff --git a/drivers/media/dvb-frontends/cx24116.c b/drivers/media/dvb-frontends/cx24116.c
index 36de5fe1b..5b461bb57 100644
--- a/drivers/media/dvb-frontends/cx24116.c
+++ b/drivers/media/dvb-frontends/cx24116.c
@@ -160,13 +160,13 @@ enum cmds {
struct cx24116_tuning {
u32 frequency;
u32 symbol_rate;
- fe_spectral_inversion_t inversion;
- fe_code_rate_t fec;
+ enum fe_spectral_inversion inversion;
+ enum fe_code_rate fec;
- fe_delivery_system_t delsys;
- fe_modulation_t modulation;
- fe_pilot_t pilot;
- fe_rolloff_t rolloff;
+ enum fe_delivery_system delsys;
+ enum fe_modulation modulation;
+ enum fe_pilot pilot;
+ enum fe_rolloff rolloff;
/* Demod values */
u8 fec_val;
@@ -285,7 +285,7 @@ static int cx24116_readreg(struct cx24116_state *state, u8 reg)
}
static int cx24116_set_inversion(struct cx24116_state *state,
- fe_spectral_inversion_t inversion)
+ enum fe_spectral_inversion inversion)
{
dprintk("%s(%d)\n", __func__, inversion);
@@ -373,9 +373,9 @@ static int cx24116_set_inversion(struct cx24116_state *state,
* a scheme are support. Especially, no auto detect when in S2 mode.
*/
static struct cx24116_modfec {
- fe_delivery_system_t delivery_system;
- fe_modulation_t modulation;
- fe_code_rate_t fec;
+ enum fe_delivery_system delivery_system;
+ enum fe_modulation modulation;
+ enum fe_code_rate fec;
u8 mask; /* In DVBS mode this is used to autodetect */
u8 val; /* Passed to the firmware to indicate mode selection */
} CX24116_MODFEC_MODES[] = {
@@ -415,7 +415,7 @@ static struct cx24116_modfec {
};
static int cx24116_lookup_fecmod(struct cx24116_state *state,
- fe_delivery_system_t d, fe_modulation_t m, fe_code_rate_t f)
+ enum fe_delivery_system d, enum fe_modulation m, enum fe_code_rate f)
{
int i, ret = -EOPNOTSUPP;
@@ -434,7 +434,9 @@ static int cx24116_lookup_fecmod(struct cx24116_state *state,
}
static int cx24116_set_fec(struct cx24116_state *state,
- fe_delivery_system_t delsys, fe_modulation_t mod, fe_code_rate_t fec)
+ enum fe_delivery_system delsys,
+ enum fe_modulation mod,
+ enum fe_code_rate fec)
{
int ret = 0;
@@ -683,7 +685,7 @@ static int cx24116_load_firmware(struct dvb_frontend *fe,
return 0;
}
-static int cx24116_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int cx24116_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct cx24116_state *state = fe->demodulator_priv;
@@ -844,7 +846,7 @@ static int cx24116_wait_for_lnb(struct dvb_frontend *fe)
}
static int cx24116_set_voltage(struct dvb_frontend *fe,
- fe_sec_voltage_t voltage)
+ enum fe_sec_voltage voltage)
{
struct cx24116_cmd cmd;
int ret;
@@ -872,7 +874,7 @@ static int cx24116_set_voltage(struct dvb_frontend *fe,
}
static int cx24116_set_tone(struct dvb_frontend *fe,
- fe_sec_tone_mode_t tone)
+ enum fe_sec_tone_mode tone)
{
struct cx24116_cmd cmd;
int ret;
@@ -1055,7 +1057,7 @@ static int cx24116_send_diseqc_msg(struct dvb_frontend *fe,
/* Send DiSEqC burst */
static int cx24116_diseqc_send_burst(struct dvb_frontend *fe,
- fe_sec_mini_cmd_t burst)
+ enum fe_sec_mini_cmd burst)
{
struct cx24116_state *state = fe->demodulator_priv;
int ret;
@@ -1220,7 +1222,7 @@ static int cx24116_set_frontend(struct dvb_frontend *fe)
struct cx24116_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct cx24116_cmd cmd;
- fe_status_t tunerstat;
+ enum fe_status tunerstat;
int i, status, ret, retune = 1;
dprintk("%s()\n", __func__);
@@ -1441,7 +1443,7 @@ tuned: /* Set/Reset B/W */
}
static int cx24116_tune(struct dvb_frontend *fe, bool re_tune,
- unsigned int mode_flags, unsigned int *delay, fe_status_t *status)
+ unsigned int mode_flags, unsigned int *delay, enum fe_status *status)
{
/*
* It is safe to discard "params" here, as the DVB core will sync
diff --git a/drivers/media/dvb-frontends/cx24117.c b/drivers/media/dvb-frontends/cx24117.c
index 10e60cbf4..28ad11147 100644
--- a/drivers/media/dvb-frontends/cx24117.c
+++ b/drivers/media/dvb-frontends/cx24117.c
@@ -171,13 +171,13 @@ static DEFINE_MUTEX(cx24117_list_mutex);
struct cx24117_tuning {
u32 frequency;
u32 symbol_rate;
- fe_spectral_inversion_t inversion;
- fe_code_rate_t fec;
+ enum fe_spectral_inversion inversion;
+ enum fe_code_rate fec;
- fe_delivery_system_t delsys;
- fe_modulation_t modulation;
- fe_pilot_t pilot;
- fe_rolloff_t rolloff;
+ enum fe_delivery_system delsys;
+ enum fe_modulation modulation;
+ enum fe_pilot pilot;
+ enum fe_rolloff rolloff;
/* Demod values */
u8 fec_val;
@@ -220,9 +220,9 @@ struct cx24117_state {
/* modfec (modulation and FEC) lookup table */
/* Check cx24116.c for a detailed description of each field */
static struct cx24117_modfec {
- fe_delivery_system_t delivery_system;
- fe_modulation_t modulation;
- fe_code_rate_t fec;
+ enum fe_delivery_system delivery_system;
+ enum fe_modulation modulation;
+ enum fe_code_rate fec;
u8 mask; /* In DVBS mode this is used to autodetect */
u8 val; /* Passed to the firmware to indicate mode selection */
} cx24117_modfec_modes[] = {
@@ -362,7 +362,7 @@ static int cx24117_readregN(struct cx24117_state *state,
}
static int cx24117_set_inversion(struct cx24117_state *state,
- fe_spectral_inversion_t inversion)
+ enum fe_spectral_inversion inversion)
{
dev_dbg(&state->priv->i2c->dev, "%s(%d) demod%d\n",
__func__, inversion, state->demod);
@@ -387,7 +387,7 @@ static int cx24117_set_inversion(struct cx24117_state *state,
}
static int cx24117_lookup_fecmod(struct cx24117_state *state,
- fe_delivery_system_t d, fe_modulation_t m, fe_code_rate_t f)
+ enum fe_delivery_system d, enum fe_modulation m, enum fe_code_rate f)
{
int i, ret = -EINVAL;
@@ -408,7 +408,9 @@ static int cx24117_lookup_fecmod(struct cx24117_state *state,
}
static int cx24117_set_fec(struct cx24117_state *state,
- fe_delivery_system_t delsys, fe_modulation_t mod, fe_code_rate_t fec)
+ enum fe_delivery_system delsys,
+ enum fe_modulation mod,
+ enum fe_code_rate fec)
{
int ret;
@@ -737,7 +739,7 @@ error:
return ret;
}
-static int cx24117_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int cx24117_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct cx24117_state *state = fe->demodulator_priv;
int lock;
@@ -843,7 +845,7 @@ static int cx24117_read_snr(struct dvb_frontend *fe, u16 *snr)
static int cx24117_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
{
struct cx24117_state *state = fe->demodulator_priv;
- fe_delivery_system_t delsys = fe->dtv_property_cache.delivery_system;
+ enum fe_delivery_system delsys = fe->dtv_property_cache.delivery_system;
int ret;
u8 buf[2];
u8 reg = (state->demod == 0) ?
@@ -904,7 +906,7 @@ static int cx24117_wait_for_lnb(struct dvb_frontend *fe)
}
static int cx24117_set_voltage(struct dvb_frontend *fe,
- fe_sec_voltage_t voltage)
+ enum fe_sec_voltage voltage)
{
struct cx24117_state *state = fe->demodulator_priv;
struct cx24117_cmd cmd;
@@ -956,7 +958,7 @@ static int cx24117_set_voltage(struct dvb_frontend *fe,
}
static int cx24117_set_tone(struct dvb_frontend *fe,
- fe_sec_tone_mode_t tone)
+ enum fe_sec_tone_mode tone)
{
struct cx24117_state *state = fe->demodulator_priv;
struct cx24117_cmd cmd;
@@ -1112,7 +1114,7 @@ static int cx24117_send_diseqc_msg(struct dvb_frontend *fe,
/* Send DiSEqC burst */
static int cx24117_diseqc_send_burst(struct dvb_frontend *fe,
- fe_sec_mini_cmd_t burst)
+ enum fe_sec_mini_cmd burst)
{
struct cx24117_state *state = fe->demodulator_priv;
@@ -1306,7 +1308,7 @@ static int cx24117_set_frontend(struct dvb_frontend *fe)
struct cx24117_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct cx24117_cmd cmd;
- fe_status_t tunerstat;
+ enum fe_status tunerstat;
int i, status, ret, retune = 1;
u8 reg_clkdiv, reg_ratediv;
@@ -1537,7 +1539,7 @@ static int cx24117_set_frontend(struct dvb_frontend *fe)
}
static int cx24117_tune(struct dvb_frontend *fe, bool re_tune,
- unsigned int mode_flags, unsigned int *delay, fe_status_t *status)
+ unsigned int mode_flags, unsigned int *delay, enum fe_status *status)
{
struct cx24117_state *state = fe->demodulator_priv;
diff --git a/drivers/media/dvb-frontends/cx24120.c b/drivers/media/dvb-frontends/cx24120.c
new file mode 100644
index 000000000..38ad1e713
--- /dev/null
+++ b/drivers/media/dvb-frontends/cx24120.c
@@ -0,0 +1,1595 @@
+/*
+ Conexant cx24120/cx24118 - DVBS/S2 Satellite demod/tuner driver
+
+ Copyright (C) 2008 Patrick Boettcher <pb@linuxtv.org>
+ Copyright (C) 2009 Sergey Tyurin <forum.free-x.de>
+ Updated 2012 by Jannis Achstetter <jannis_achstetter@web.de>
+ Copyright (C) 2015 Jemma Denson <jdenson@gmail.com>
+ April 2015
+ Refactored & simplified driver
+ Updated to work with delivery system supplied by DVBv5
+ Add frequency, fec & pilot to get_frontend
+
+ Cards supported: Technisat Skystar S2
+
+ 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 <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/firmware.h>
+#include "dvb_frontend.h"
+#include "cx24120.h"
+
+#define CX24120_SEARCH_RANGE_KHZ 5000
+#define CX24120_FIRMWARE "/*(DEBLOBBED)*/"
+
+/* cx24120 i2c registers */
+#define CX24120_REG_CMD_START 0x00 /* write cmd_id */
+#define CX24120_REG_CMD_ARGS 0x01 /* write command arguments */
+#define CX24120_REG_CMD_END 0x1f /* write 0x01 for end */
+
+#define CX24120_REG_MAILBOX 0x33
+#define CX24120_REG_FREQ3 0x34 /* frequency */
+#define CX24120_REG_FREQ2 0x35
+#define CX24120_REG_FREQ1 0x36
+
+#define CX24120_REG_FECMODE 0x39 /* FEC status */
+#define CX24120_REG_STATUS 0x3a /* Tuner status */
+#define CX24120_REG_SIGSTR_H 0x3a /* Signal strength high */
+#define CX24120_REG_SIGSTR_L 0x3b /* Signal strength low byte */
+#define CX24120_REG_QUALITY_H 0x40 /* SNR high byte */
+#define CX24120_REG_QUALITY_L 0x41 /* SNR low byte */
+
+#define CX24120_REG_BER_HH 0x47 /* BER high byte of high word */
+#define CX24120_REG_BER_HL 0x48 /* BER low byte of high word */
+#define CX24120_REG_BER_LH 0x49 /* BER high byte of low word */
+#define CX24120_REG_BER_LL 0x4a /* BER low byte of low word */
+
+#define CX24120_REG_UCB_H 0x50 /* UCB high byte */
+#define CX24120_REG_UCB_L 0x51 /* UCB low byte */
+
+#define CX24120_REG_CLKDIV 0xe6
+#define CX24120_REG_RATEDIV 0xf0
+
+#define CX24120_REG_REVISION 0xff /* Chip revision (ro) */
+
+/* Command messages */
+enum command_message_id {
+ CMD_VCO_SET = 0x10, /* cmd.len = 12; */
+ CMD_TUNEREQUEST = 0x11, /* cmd.len = 15; */
+
+ CMD_MPEG_ONOFF = 0x13, /* cmd.len = 4; */
+ CMD_MPEG_INIT = 0x14, /* cmd.len = 7; */
+ CMD_BANDWIDTH = 0x15, /* cmd.len = 12; */
+ CMD_CLOCK_READ = 0x16, /* read clock */
+ CMD_CLOCK_SET = 0x17, /* cmd.len = 10; */
+
+ CMD_DISEQC_MSG1 = 0x20, /* cmd.len = 11; */
+ CMD_DISEQC_MSG2 = 0x21, /* cmd.len = d->msg_len + 6; */
+ CMD_SETVOLTAGE = 0x22, /* cmd.len = 2; */
+ CMD_SETTONE = 0x23, /* cmd.len = 4; */
+ CMD_DISEQC_BURST = 0x24, /* cmd.len not used !!! */
+
+ CMD_READ_SNR = 0x1a, /* Read signal strength */
+ CMD_START_TUNER = 0x1b, /* ??? */
+
+ CMD_FWVERSION = 0x35,
+
+ CMD_BER_CTRL = 0x3c, /* cmd.len = 0x03; */
+};
+
+#define CX24120_MAX_CMD_LEN 30
+
+/* pilot mask */
+#define CX24120_PILOT_OFF 0x00
+#define CX24120_PILOT_ON 0x40
+#define CX24120_PILOT_AUTO 0x80
+
+/* signal status */
+#define CX24120_HAS_SIGNAL 0x01
+#define CX24120_HAS_CARRIER 0x02
+#define CX24120_HAS_VITERBI 0x04
+#define CX24120_HAS_LOCK 0x08
+#define CX24120_HAS_UNK1 0x10
+#define CX24120_HAS_UNK2 0x20
+#define CX24120_STATUS_MASK 0x0f
+#define CX24120_SIGNAL_MASK 0xc0
+
+/* ber window */
+#define CX24120_BER_WINDOW 16
+#define CX24120_BER_WSIZE ((1 << CX24120_BER_WINDOW) * 208 * 8)
+
+#define info(args...) pr_info("cx24120: " args)
+#define err(args...) pr_err("cx24120: ### ERROR: " args)
+
+/* The Demod/Tuner can't easily provide these, we cache them */
+struct cx24120_tuning {
+ u32 frequency;
+ u32 symbol_rate;
+ enum fe_spectral_inversion inversion;
+ enum fe_code_rate fec;
+
+ enum fe_delivery_system delsys;
+ enum fe_modulation modulation;
+ enum fe_pilot pilot;
+
+ /* Demod values */
+ u8 fec_val;
+ u8 fec_mask;
+ u8 clkdiv;
+ u8 ratediv;
+ u8 inversion_val;
+ u8 pilot_val;
+};
+
+/* Private state */
+struct cx24120_state {
+ struct i2c_adapter *i2c;
+ const struct cx24120_config *config;
+ struct dvb_frontend frontend;
+
+ u8 cold_init;
+ u8 mpeg_enabled;
+ u8 need_clock_set;
+
+ /* current and next tuning parameters */
+ struct cx24120_tuning dcur;
+ struct cx24120_tuning dnxt;
+
+ enum fe_status fe_status;
+
+ /* dvbv5 stats calculations */
+ u32 bitrate;
+ u32 berw_usecs;
+ u32 ber_prev;
+ u32 ucb_offset;
+ unsigned long ber_jiffies_stats;
+ unsigned long per_jiffies_stats;
+};
+
+/* Command message to firmware */
+struct cx24120_cmd {
+ u8 id;
+ u8 len;
+ u8 arg[CX24120_MAX_CMD_LEN];
+};
+
+/* Read single register */
+static int cx24120_readreg(struct cx24120_state *state, u8 reg)
+{
+ int ret;
+ u8 buf = 0;
+ struct i2c_msg msg[] = {
+ {
+ .addr = state->config->i2c_addr,
+ .flags = 0,
+ .len = 1,
+ .buf = &reg
+ }, {
+ .addr = state->config->i2c_addr,
+ .flags = I2C_M_RD,
+ .len = 1,
+ .buf = &buf
+ }
+ };
+
+ ret = i2c_transfer(state->i2c, msg, 2);
+ if (ret != 2) {
+ err("Read error: reg=0x%02x, ret=%i)\n", reg, ret);
+ return ret;
+ }
+
+ dev_dbg(&state->i2c->dev, "reg=0x%02x; data=0x%02x\n", reg, buf);
+
+ return buf;
+}
+
+/* Write single register */
+static int cx24120_writereg(struct cx24120_state *state, u8 reg, u8 data)
+{
+ u8 buf[] = { reg, data };
+ struct i2c_msg msg = {
+ .addr = state->config->i2c_addr,
+ .flags = 0,
+ .buf = buf,
+ .len = 2
+ };
+ int ret;
+
+ ret = i2c_transfer(state->i2c, &msg, 1);
+ if (ret != 1) {
+ err("Write error: i2c_write error(err == %i, 0x%02x: 0x%02x)\n",
+ ret, reg, data);
+ return ret;
+ }
+
+ dev_dbg(&state->i2c->dev, "reg=0x%02x; data=0x%02x\n", reg, data);
+
+ return 0;
+}
+
+/* Write multiple registers in chunks of i2c_wr_max-sized buffers */
+static int cx24120_writeregs(struct cx24120_state *state,
+ u8 reg, const u8 *values, u16 len, u8 incr)
+{
+ int ret;
+ u16 max = state->config->i2c_wr_max > 0 ?
+ state->config->i2c_wr_max :
+ len;
+
+ struct i2c_msg msg = {
+ .addr = state->config->i2c_addr,
+ .flags = 0,
+ };
+
+ msg.buf = kmalloc(max + 1, GFP_KERNEL);
+ if (!msg.buf)
+ return -ENOMEM;
+
+ while (len) {
+ msg.buf[0] = reg;
+ msg.len = len > max ? max : len;
+ memcpy(&msg.buf[1], values, msg.len);
+
+ len -= msg.len; /* data length revers counter */
+ values += msg.len; /* incr data pointer */
+
+ if (incr)
+ reg += msg.len;
+ msg.len++; /* don't forget the addr byte */
+
+ ret = i2c_transfer(state->i2c, &msg, 1);
+ if (ret != 1) {
+ err("i2c_write error(err == %i, 0x%02x)\n", ret, reg);
+ goto out;
+ }
+
+ dev_dbg(&state->i2c->dev, "reg=0x%02x; data=%*ph\n",
+ reg, msg.len - 1, msg.buf + 1);
+ }
+
+ ret = 0;
+
+out:
+ kfree(msg.buf);
+ return ret;
+}
+
+static struct dvb_frontend_ops cx24120_ops;
+
+struct dvb_frontend *cx24120_attach(const struct cx24120_config *config,
+ struct i2c_adapter *i2c)
+{
+ struct cx24120_state *state;
+ int demod_rev;
+
+ info("Conexant cx24120/cx24118 - DVBS/S2 Satellite demod/tuner\n");
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (!state) {
+ err("Unable to allocate memory for cx24120_state\n");
+ goto error;
+ }
+
+ /* setup the state */
+ state->config = config;
+ state->i2c = i2c;
+
+ /* check if the demod is present and has proper type */
+ demod_rev = cx24120_readreg(state, CX24120_REG_REVISION);
+ switch (demod_rev) {
+ case 0x07:
+ info("Demod cx24120 rev. 0x07 detected.\n");
+ break;
+ case 0x05:
+ info("Demod cx24120 rev. 0x05 detected.\n");
+ break;
+ default:
+ err("Unsupported demod revision: 0x%x detected.\n", demod_rev);
+ goto error;
+ }
+
+ /* create dvb_frontend */
+ state->cold_init = 0;
+ memcpy(&state->frontend.ops, &cx24120_ops,
+ sizeof(struct dvb_frontend_ops));
+ state->frontend.demodulator_priv = state;
+
+ info("Conexant cx24120/cx24118 attached.\n");
+ return &state->frontend;
+
+error:
+ kfree(state);
+ return NULL;
+}
+EXPORT_SYMBOL(cx24120_attach);
+
+static int cx24120_test_rom(struct cx24120_state *state)
+{
+ int err, ret;
+
+ err = cx24120_readreg(state, 0xfd);
+ if (err & 4) {
+ ret = cx24120_readreg(state, 0xdf) & 0xfe;
+ err = cx24120_writereg(state, 0xdf, ret);
+ }
+ return err;
+}
+
+static int cx24120_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+ if (c->cnr.stat[0].scale != FE_SCALE_DECIBEL)
+ *snr = 0;
+ else
+ *snr = div_s64(c->cnr.stat[0].svalue, 100);
+
+ return 0;
+}
+
+static int cx24120_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+ struct cx24120_state *state = fe->demodulator_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+ if (c->post_bit_error.stat[0].scale != FE_SCALE_COUNTER) {
+ *ber = 0;
+ return 0;
+ }
+
+ *ber = c->post_bit_error.stat[0].uvalue - state->ber_prev;
+ state->ber_prev = c->post_bit_error.stat[0].uvalue;
+
+ return 0;
+}
+
+static int cx24120_msg_mpeg_output_global_config(struct cx24120_state *state,
+ u8 flag);
+
+/* Check if we're running a command that needs to disable mpeg out */
+static void cx24120_check_cmd(struct cx24120_state *state, u8 id)
+{
+ switch (id) {
+ case CMD_TUNEREQUEST:
+ case CMD_CLOCK_READ:
+ case CMD_DISEQC_MSG1:
+ case CMD_DISEQC_MSG2:
+ case CMD_SETVOLTAGE:
+ case CMD_SETTONE:
+ case CMD_DISEQC_BURST:
+ cx24120_msg_mpeg_output_global_config(state, 0);
+ /* Old driver would do a msleep(100) here */
+ default:
+ return;
+ }
+}
+
+/* Send a message to the firmware */
+static int cx24120_message_send(struct cx24120_state *state,
+ struct cx24120_cmd *cmd)
+{
+ int ficus;
+
+ if (state->mpeg_enabled) {
+ /* Disable mpeg out on certain commands */
+ cx24120_check_cmd(state, cmd->id);
+ }
+
+ cx24120_writereg(state, CX24120_REG_CMD_START, cmd->id);
+ cx24120_writeregs(state, CX24120_REG_CMD_ARGS, &cmd->arg[0],
+ cmd->len, 1);
+ cx24120_writereg(state, CX24120_REG_CMD_END, 0x01);
+
+ ficus = 1000;
+ while (cx24120_readreg(state, CX24120_REG_CMD_END)) {
+ msleep(20);
+ ficus -= 20;
+ if (ficus == 0) {
+ err("Error sending message to firmware\n");
+ return -EREMOTEIO;
+ }
+ }
+ dev_dbg(&state->i2c->dev, "sent message 0x%02x\n", cmd->id);
+
+ return 0;
+}
+
+/* Send a message and fill arg[] with the results */
+static int cx24120_message_sendrcv(struct cx24120_state *state,
+ struct cx24120_cmd *cmd, u8 numreg)
+{
+ int ret, i;
+
+ if (numreg > CX24120_MAX_CMD_LEN) {
+ err("Too many registers to read. cmd->reg = %d", numreg);
+ return -EREMOTEIO;
+ }
+
+ ret = cx24120_message_send(state, cmd);
+ if (ret != 0)
+ return ret;
+
+ if (!numreg)
+ return 0;
+
+ /* Read numreg registers starting from register cmd->len */
+ for (i = 0; i < numreg; i++)
+ cmd->arg[i] = cx24120_readreg(state, (cmd->len + i + 1));
+
+ return 0;
+}
+
+static int cx24120_read_signal_strength(struct dvb_frontend *fe,
+ u16 *signal_strength)
+{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+ if (c->strength.stat[0].scale != FE_SCALE_RELATIVE)
+ *signal_strength = 0;
+ else
+ *signal_strength = c->strength.stat[0].uvalue;
+
+ return 0;
+}
+
+static int cx24120_msg_mpeg_output_global_config(struct cx24120_state *state,
+ u8 enable)
+{
+ struct cx24120_cmd cmd;
+ int ret;
+
+ cmd.id = CMD_MPEG_ONOFF;
+ cmd.len = 4;
+ cmd.arg[0] = 0x01;
+ cmd.arg[1] = 0x00;
+ cmd.arg[2] = enable ? 0 : (u8)(-1);
+ cmd.arg[3] = 0x01;
+
+ ret = cx24120_message_send(state, &cmd);
+ if (ret != 0) {
+ dev_dbg(&state->i2c->dev, "failed to %s MPEG output\n",
+ enable ? "enable" : "disable");
+ return ret;
+ }
+
+ state->mpeg_enabled = enable;
+ dev_dbg(&state->i2c->dev, "MPEG output %s\n",
+ enable ? "enabled" : "disabled");
+
+ return 0;
+}
+
+static int cx24120_msg_mpeg_output_config(struct cx24120_state *state, u8 seq)
+{
+ struct cx24120_cmd cmd;
+ struct cx24120_initial_mpeg_config i =
+ state->config->initial_mpeg_config;
+
+ cmd.id = CMD_MPEG_INIT;
+ cmd.len = 7;
+ cmd.arg[0] = seq; /* sequental number - can be 0,1,2 */
+ cmd.arg[1] = ((i.x1 & 0x01) << 1) | ((i.x1 >> 1) & 0x01);
+ cmd.arg[2] = 0x05;
+ cmd.arg[3] = 0x02;
+ cmd.arg[4] = ((i.x2 >> 1) & 0x01);
+ cmd.arg[5] = (i.x2 & 0xf0) | (i.x3 & 0x0f);
+ cmd.arg[6] = 0x10;
+
+ return cx24120_message_send(state, &cmd);
+}
+
+static int cx24120_diseqc_send_burst(struct dvb_frontend *fe,
+ enum fe_sec_mini_cmd burst)
+{
+ struct cx24120_state *state = fe->demodulator_priv;
+ struct cx24120_cmd cmd;
+
+ dev_dbg(&state->i2c->dev, "\n");
+
+ /*
+ * Yes, cmd.len is set to zero. The old driver
+ * didn't specify any len, but also had a
+ * memset 0 before every use of the cmd struct
+ * which would have set it to zero.
+ * This quite probably needs looking into.
+ */
+ cmd.id = CMD_DISEQC_BURST;
+ cmd.len = 0;
+ cmd.arg[0] = 0x00;
+ cmd.arg[1] = (burst == SEC_MINI_B) ? 0x01 : 0x00;
+
+ return cx24120_message_send(state, &cmd);
+}
+
+static int cx24120_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)
+{
+ struct cx24120_state *state = fe->demodulator_priv;
+ struct cx24120_cmd cmd;
+
+ dev_dbg(&state->i2c->dev, "(%d)\n", tone);
+
+ if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) {
+ err("Invalid tone=%d\n", tone);
+ return -EINVAL;
+ }
+
+ cmd.id = CMD_SETTONE;
+ cmd.len = 4;
+ cmd.arg[0] = 0x00;
+ cmd.arg[1] = 0x00;
+ cmd.arg[2] = 0x00;
+ cmd.arg[3] = (tone == SEC_TONE_ON) ? 0x01 : 0x00;
+
+ return cx24120_message_send(state, &cmd);
+}
+
+static int cx24120_set_voltage(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage)
+{
+ struct cx24120_state *state = fe->demodulator_priv;
+ struct cx24120_cmd cmd;
+
+ dev_dbg(&state->i2c->dev, "(%d)\n", voltage);
+
+ cmd.id = CMD_SETVOLTAGE;
+ cmd.len = 2;
+ cmd.arg[0] = 0x00;
+ cmd.arg[1] = (voltage == SEC_VOLTAGE_18) ? 0x01 : 0x00;
+
+ return cx24120_message_send(state, &cmd);
+}
+
+static int cx24120_send_diseqc_msg(struct dvb_frontend *fe,
+ struct dvb_diseqc_master_cmd *d)
+{
+ struct cx24120_state *state = fe->demodulator_priv;
+ struct cx24120_cmd cmd;
+ int back_count;
+
+ dev_dbg(&state->i2c->dev, "\n");
+
+ cmd.id = CMD_DISEQC_MSG1;
+ cmd.len = 11;
+ cmd.arg[0] = 0x00;
+ cmd.arg[1] = 0x00;
+ cmd.arg[2] = 0x03;
+ cmd.arg[3] = 0x16;
+ cmd.arg[4] = 0x28;
+ cmd.arg[5] = 0x01;
+ cmd.arg[6] = 0x01;
+ cmd.arg[7] = 0x14;
+ cmd.arg[8] = 0x19;
+ cmd.arg[9] = 0x14;
+ cmd.arg[10] = 0x1e;
+
+ if (cx24120_message_send(state, &cmd)) {
+ err("send 1st message(0x%x) failed\n", cmd.id);
+ return -EREMOTEIO;
+ }
+
+ cmd.id = CMD_DISEQC_MSG2;
+ cmd.len = d->msg_len + 6;
+ cmd.arg[0] = 0x00;
+ cmd.arg[1] = 0x01;
+ cmd.arg[2] = 0x02;
+ cmd.arg[3] = 0x00;
+ cmd.arg[4] = 0x00;
+ cmd.arg[5] = d->msg_len;
+
+ memcpy(&cmd.arg[6], &d->msg, d->msg_len);
+
+ if (cx24120_message_send(state, &cmd)) {
+ err("send 2nd message(0x%x) failed\n", cmd.id);
+ return -EREMOTEIO;
+ }
+
+ back_count = 500;
+ do {
+ if (!(cx24120_readreg(state, 0x93) & 0x01)) {
+ dev_dbg(&state->i2c->dev, "diseqc sequence sent\n");
+ return 0;
+ }
+ msleep(20);
+ back_count -= 20;
+ } while (back_count);
+
+ err("Too long waiting for diseqc.\n");
+ return -ETIMEDOUT;
+}
+
+static void cx24120_get_stats(struct cx24120_state *state)
+{
+ struct dvb_frontend *fe = &state->frontend;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ struct cx24120_cmd cmd;
+ int ret, cnr, msecs;
+ u16 sig, ucb;
+ u32 ber;
+
+ dev_dbg(&state->i2c->dev, "\n");
+
+ /* signal strength */
+ if (state->fe_status & FE_HAS_SIGNAL) {
+ cmd.id = CMD_READ_SNR;
+ cmd.len = 1;
+ cmd.arg[0] = 0x00;
+
+ ret = cx24120_message_send(state, &cmd);
+ if (ret != 0) {
+ err("error reading signal strength\n");
+ return;
+ }
+
+ /* raw */
+ sig = cx24120_readreg(state, CX24120_REG_SIGSTR_H) >> 6;
+ sig = sig << 8;
+ sig |= cx24120_readreg(state, CX24120_REG_SIGSTR_L);
+ dev_dbg(&state->i2c->dev,
+ "signal strength from firmware = 0x%x\n", sig);
+
+ /* cooked */
+ sig = -100 * sig + 94324;
+
+ c->strength.stat[0].scale = FE_SCALE_RELATIVE;
+ c->strength.stat[0].uvalue = sig;
+ } else {
+ c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ }
+
+ /* CNR */
+ if (state->fe_status & FE_HAS_VITERBI) {
+ cnr = cx24120_readreg(state, CX24120_REG_QUALITY_H) << 8;
+ cnr |= cx24120_readreg(state, CX24120_REG_QUALITY_L);
+ dev_dbg(&state->i2c->dev, "read SNR index = %d\n", cnr);
+
+ /* guessed - seems about right */
+ cnr = cnr * 100;
+
+ c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+ c->cnr.stat[0].svalue = cnr;
+ } else {
+ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ }
+
+ /* BER & UCB require lock */
+ if (!(state->fe_status & FE_HAS_LOCK)) {
+ c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ return;
+ }
+
+ /* BER */
+ if (time_after(jiffies, state->ber_jiffies_stats)) {
+ msecs = (state->berw_usecs + 500) / 1000;
+ state->ber_jiffies_stats = jiffies + msecs_to_jiffies(msecs);
+
+ ber = cx24120_readreg(state, CX24120_REG_BER_HH) << 24;
+ ber |= cx24120_readreg(state, CX24120_REG_BER_HL) << 16;
+ ber |= cx24120_readreg(state, CX24120_REG_BER_LH) << 8;
+ ber |= cx24120_readreg(state, CX24120_REG_BER_LL);
+ dev_dbg(&state->i2c->dev, "read BER index = %d\n", ber);
+
+ c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+ c->post_bit_error.stat[0].uvalue += ber;
+
+ c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+ c->post_bit_count.stat[0].uvalue += CX24120_BER_WSIZE;
+ }
+
+ /* UCB */
+ if (time_after(jiffies, state->per_jiffies_stats)) {
+ state->per_jiffies_stats = jiffies + msecs_to_jiffies(1000);
+
+ ucb = cx24120_readreg(state, CX24120_REG_UCB_H) << 8;
+ ucb |= cx24120_readreg(state, CX24120_REG_UCB_L);
+ dev_dbg(&state->i2c->dev, "ucblocks = %d\n", ucb);
+
+ /* handle reset */
+ if (ucb < state->ucb_offset)
+ state->ucb_offset = c->block_error.stat[0].uvalue;
+
+ c->block_error.stat[0].scale = FE_SCALE_COUNTER;
+ c->block_error.stat[0].uvalue = ucb + state->ucb_offset;
+
+ c->block_count.stat[0].scale = FE_SCALE_COUNTER;
+ c->block_count.stat[0].uvalue += state->bitrate / 8 / 208;
+ }
+}
+
+static void cx24120_set_clock_ratios(struct dvb_frontend *fe);
+
+/* Read current tuning status */
+static int cx24120_read_status(struct dvb_frontend *fe, enum fe_status *status)
+{
+ struct cx24120_state *state = fe->demodulator_priv;
+ int lock;
+
+ lock = cx24120_readreg(state, CX24120_REG_STATUS);
+
+ dev_dbg(&state->i2c->dev, "status = 0x%02x\n", lock);
+
+ *status = 0;
+
+ if (lock & CX24120_HAS_SIGNAL)
+ *status = FE_HAS_SIGNAL;
+ if (lock & CX24120_HAS_CARRIER)
+ *status |= FE_HAS_CARRIER;
+ if (lock & CX24120_HAS_VITERBI)
+ *status |= FE_HAS_VITERBI | FE_HAS_SYNC;
+ if (lock & CX24120_HAS_LOCK)
+ *status |= FE_HAS_LOCK;
+
+ /*
+ * TODO: is FE_HAS_SYNC in the right place?
+ * Other cx241xx drivers have this slightly
+ * different
+ */
+
+ state->fe_status = *status;
+ cx24120_get_stats(state);
+
+ /* Set the clock once tuned in */
+ if (state->need_clock_set && *status & FE_HAS_LOCK) {
+ /* Set clock ratios */
+ cx24120_set_clock_ratios(fe);
+
+ /* Old driver would do a msleep(200) here */
+
+ /* Renable mpeg output */
+ if (!state->mpeg_enabled)
+ cx24120_msg_mpeg_output_global_config(state, 1);
+
+ state->need_clock_set = 0;
+ }
+
+ return 0;
+}
+
+/*
+ * FEC & modulation lookup table
+ * Used for decoding the REG_FECMODE register
+ * once tuned in.
+ */
+struct cx24120_modfec {
+ enum fe_delivery_system delsys;
+ enum fe_modulation mod;
+ enum fe_code_rate fec;
+ u8 val;
+};
+
+static const struct cx24120_modfec modfec_lookup_table[] = {
+ /*delsys mod fec val */
+ { SYS_DVBS, QPSK, FEC_1_2, 0x01 },
+ { SYS_DVBS, QPSK, FEC_2_3, 0x02 },
+ { SYS_DVBS, QPSK, FEC_3_4, 0x03 },
+ { SYS_DVBS, QPSK, FEC_4_5, 0x04 },
+ { SYS_DVBS, QPSK, FEC_5_6, 0x05 },
+ { SYS_DVBS, QPSK, FEC_6_7, 0x06 },
+ { SYS_DVBS, QPSK, FEC_7_8, 0x07 },
+
+ { SYS_DVBS2, QPSK, FEC_1_2, 0x04 },
+ { SYS_DVBS2, QPSK, FEC_3_5, 0x05 },
+ { SYS_DVBS2, QPSK, FEC_2_3, 0x06 },
+ { SYS_DVBS2, QPSK, FEC_3_4, 0x07 },
+ { SYS_DVBS2, QPSK, FEC_4_5, 0x08 },
+ { SYS_DVBS2, QPSK, FEC_5_6, 0x09 },
+ { SYS_DVBS2, QPSK, FEC_8_9, 0x0a },
+ { SYS_DVBS2, QPSK, FEC_9_10, 0x0b },
+
+ { SYS_DVBS2, PSK_8, FEC_3_5, 0x0c },
+ { SYS_DVBS2, PSK_8, FEC_2_3, 0x0d },
+ { SYS_DVBS2, PSK_8, FEC_3_4, 0x0e },
+ { SYS_DVBS2, PSK_8, FEC_5_6, 0x0f },
+ { SYS_DVBS2, PSK_8, FEC_8_9, 0x10 },
+ { SYS_DVBS2, PSK_8, FEC_9_10, 0x11 },
+};
+
+/* Retrieve current fec, modulation & pilot values */
+static int cx24120_get_fec(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ struct cx24120_state *state = fe->demodulator_priv;
+ int idx;
+ int ret;
+ int fec;
+
+ ret = cx24120_readreg(state, CX24120_REG_FECMODE);
+ fec = ret & 0x3f; /* Lower 6 bits */
+
+ dev_dbg(&state->i2c->dev, "raw fec = %d\n", fec);
+
+ for (idx = 0; idx < ARRAY_SIZE(modfec_lookup_table); idx++) {
+ if (modfec_lookup_table[idx].delsys != state->dcur.delsys)
+ continue;
+ if (modfec_lookup_table[idx].val != fec)
+ continue;
+
+ break; /* found */
+ }
+
+ if (idx >= ARRAY_SIZE(modfec_lookup_table)) {
+ dev_dbg(&state->i2c->dev, "couldn't find fec!\n");
+ return -EINVAL;
+ }
+
+ /* save values back to cache */
+ c->modulation = modfec_lookup_table[idx].mod;
+ c->fec_inner = modfec_lookup_table[idx].fec;
+ c->pilot = (ret & 0x80) ? PILOT_ON : PILOT_OFF;
+
+ dev_dbg(&state->i2c->dev, "mod(%d), fec(%d), pilot(%d)\n",
+ c->modulation, c->fec_inner, c->pilot);
+
+ return 0;
+}
+
+/* Calculate ber window time */
+static void cx24120_calculate_ber_window(struct cx24120_state *state, u32 rate)
+{
+ struct dvb_frontend *fe = &state->frontend;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ u64 tmp;
+
+ /*
+ * Calculate bitrate from rate in the clock ratios table.
+ * This isn't *exactly* right but close enough.
+ */
+ tmp = (u64)c->symbol_rate * rate;
+ do_div(tmp, 256);
+ state->bitrate = tmp;
+
+ /* usecs per ber window */
+ tmp = 1000000ULL * CX24120_BER_WSIZE;
+ do_div(tmp, state->bitrate);
+ state->berw_usecs = tmp;
+
+ dev_dbg(&state->i2c->dev, "bitrate: %u, berw_usecs: %u\n",
+ state->bitrate, state->berw_usecs);
+}
+
+/*
+ * Clock ratios lookup table
+ *
+ * Values obtained from much larger table in old driver
+ * which had numerous entries which would never match.
+ *
+ * There's probably some way of calculating these but I
+ * can't determine the pattern
+ */
+struct cx24120_clock_ratios_table {
+ enum fe_delivery_system delsys;
+ enum fe_pilot pilot;
+ enum fe_modulation mod;
+ enum fe_code_rate fec;
+ u32 m_rat;
+ u32 n_rat;
+ u32 rate;
+};
+
+static const struct cx24120_clock_ratios_table clock_ratios_table[] = {
+ /*delsys pilot mod fec m_rat n_rat rate */
+ { SYS_DVBS2, PILOT_OFF, QPSK, FEC_1_2, 273088, 254505, 274 },
+ { SYS_DVBS2, PILOT_OFF, QPSK, FEC_3_5, 17272, 13395, 330 },
+ { SYS_DVBS2, PILOT_OFF, QPSK, FEC_2_3, 24344, 16967, 367 },
+ { SYS_DVBS2, PILOT_OFF, QPSK, FEC_3_4, 410788, 254505, 413 },
+ { SYS_DVBS2, PILOT_OFF, QPSK, FEC_4_5, 438328, 254505, 440 },
+ { SYS_DVBS2, PILOT_OFF, QPSK, FEC_5_6, 30464, 16967, 459 },
+ { SYS_DVBS2, PILOT_OFF, QPSK, FEC_8_9, 487832, 254505, 490 },
+ { SYS_DVBS2, PILOT_OFF, QPSK, FEC_9_10, 493952, 254505, 496 },
+ { SYS_DVBS2, PILOT_OFF, PSK_8, FEC_3_5, 328168, 169905, 494 },
+ { SYS_DVBS2, PILOT_OFF, PSK_8, FEC_2_3, 24344, 11327, 550 },
+ { SYS_DVBS2, PILOT_OFF, PSK_8, FEC_3_4, 410788, 169905, 618 },
+ { SYS_DVBS2, PILOT_OFF, PSK_8, FEC_5_6, 30464, 11327, 688 },
+ { SYS_DVBS2, PILOT_OFF, PSK_8, FEC_8_9, 487832, 169905, 735 },
+ { SYS_DVBS2, PILOT_OFF, PSK_8, FEC_9_10, 493952, 169905, 744 },
+ { SYS_DVBS2, PILOT_ON, QPSK, FEC_1_2, 273088, 260709, 268 },
+ { SYS_DVBS2, PILOT_ON, QPSK, FEC_3_5, 328168, 260709, 322 },
+ { SYS_DVBS2, PILOT_ON, QPSK, FEC_2_3, 121720, 86903, 358 },
+ { SYS_DVBS2, PILOT_ON, QPSK, FEC_3_4, 410788, 260709, 403 },
+ { SYS_DVBS2, PILOT_ON, QPSK, FEC_4_5, 438328, 260709, 430 },
+ { SYS_DVBS2, PILOT_ON, QPSK, FEC_5_6, 152320, 86903, 448 },
+ { SYS_DVBS2, PILOT_ON, QPSK, FEC_8_9, 487832, 260709, 479 },
+ { SYS_DVBS2, PILOT_ON, QPSK, FEC_9_10, 493952, 260709, 485 },
+ { SYS_DVBS2, PILOT_ON, PSK_8, FEC_3_5, 328168, 173853, 483 },
+ { SYS_DVBS2, PILOT_ON, PSK_8, FEC_2_3, 121720, 57951, 537 },
+ { SYS_DVBS2, PILOT_ON, PSK_8, FEC_3_4, 410788, 173853, 604 },
+ { SYS_DVBS2, PILOT_ON, PSK_8, FEC_5_6, 152320, 57951, 672 },
+ { SYS_DVBS2, PILOT_ON, PSK_8, FEC_8_9, 487832, 173853, 718 },
+ { SYS_DVBS2, PILOT_ON, PSK_8, FEC_9_10, 493952, 173853, 727 },
+ { SYS_DVBS, PILOT_OFF, QPSK, FEC_1_2, 152592, 152592, 256 },
+ { SYS_DVBS, PILOT_OFF, QPSK, FEC_2_3, 305184, 228888, 341 },
+ { SYS_DVBS, PILOT_OFF, QPSK, FEC_3_4, 457776, 305184, 384 },
+ { SYS_DVBS, PILOT_OFF, QPSK, FEC_5_6, 762960, 457776, 427 },
+ { SYS_DVBS, PILOT_OFF, QPSK, FEC_7_8, 1068144, 610368, 448 },
+};
+
+/* Set clock ratio from lookup table */
+static void cx24120_set_clock_ratios(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ struct cx24120_state *state = fe->demodulator_priv;
+ struct cx24120_cmd cmd;
+ int ret, idx;
+
+ /* Find fec, modulation, pilot */
+ ret = cx24120_get_fec(fe);
+ if (ret != 0)
+ return;
+
+ /* Find the clock ratios in the lookup table */
+ for (idx = 0; idx < ARRAY_SIZE(clock_ratios_table); idx++) {
+ if (clock_ratios_table[idx].delsys != state->dcur.delsys)
+ continue;
+ if (clock_ratios_table[idx].mod != c->modulation)
+ continue;
+ if (clock_ratios_table[idx].fec != c->fec_inner)
+ continue;
+ if (clock_ratios_table[idx].pilot != c->pilot)
+ continue;
+
+ break; /* found */
+ }
+
+ if (idx >= ARRAY_SIZE(clock_ratios_table)) {
+ info("Clock ratio not found - data reception in danger\n");
+ return;
+ }
+
+ /* Read current values? */
+ cmd.id = CMD_CLOCK_READ;
+ cmd.len = 1;
+ cmd.arg[0] = 0x00;
+ ret = cx24120_message_sendrcv(state, &cmd, 6);
+ if (ret != 0)
+ return;
+ /* in cmd[0]-[5] - result */
+
+ dev_dbg(&state->i2c->dev, "m=%d, n=%d; idx: %d m=%d, n=%d, rate=%d\n",
+ cmd.arg[2] | (cmd.arg[1] << 8) | (cmd.arg[0] << 16),
+ cmd.arg[5] | (cmd.arg[4] << 8) | (cmd.arg[3] << 16),
+ idx,
+ clock_ratios_table[idx].m_rat,
+ clock_ratios_table[idx].n_rat,
+ clock_ratios_table[idx].rate);
+
+ /* Set the clock */
+ cmd.id = CMD_CLOCK_SET;
+ cmd.len = 10;
+ cmd.arg[0] = 0;
+ cmd.arg[1] = 0x10;
+ cmd.arg[2] = (clock_ratios_table[idx].m_rat >> 16) & 0xff;
+ cmd.arg[3] = (clock_ratios_table[idx].m_rat >> 8) & 0xff;
+ cmd.arg[4] = (clock_ratios_table[idx].m_rat >> 0) & 0xff;
+ cmd.arg[5] = (clock_ratios_table[idx].n_rat >> 16) & 0xff;
+ cmd.arg[6] = (clock_ratios_table[idx].n_rat >> 8) & 0xff;
+ cmd.arg[7] = (clock_ratios_table[idx].n_rat >> 0) & 0xff;
+ cmd.arg[8] = (clock_ratios_table[idx].rate >> 8) & 0xff;
+ cmd.arg[9] = (clock_ratios_table[idx].rate >> 0) & 0xff;
+
+ cx24120_message_send(state, &cmd);
+
+ /* Calculate ber window rates for stat work */
+ cx24120_calculate_ber_window(state, clock_ratios_table[idx].rate);
+}
+
+/* Set inversion value */
+static int cx24120_set_inversion(struct cx24120_state *state,
+ enum fe_spectral_inversion inversion)
+{
+ dev_dbg(&state->i2c->dev, "(%d)\n", inversion);
+
+ switch (inversion) {
+ case INVERSION_OFF:
+ state->dnxt.inversion_val = 0x00;
+ break;
+ case INVERSION_ON:
+ state->dnxt.inversion_val = 0x04;
+ break;
+ case INVERSION_AUTO:
+ state->dnxt.inversion_val = 0x0c;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ state->dnxt.inversion = inversion;
+
+ return 0;
+}
+
+/* FEC lookup table for tuning */
+struct cx24120_modfec_table {
+ enum fe_delivery_system delsys;
+ enum fe_modulation mod;
+ enum fe_code_rate fec;
+ u8 val;
+};
+
+static const struct cx24120_modfec_table modfec_table[] = {
+ /*delsys mod fec val */
+ { SYS_DVBS, QPSK, FEC_1_2, 0x2e },
+ { SYS_DVBS, QPSK, FEC_2_3, 0x2f },
+ { SYS_DVBS, QPSK, FEC_3_4, 0x30 },
+ { SYS_DVBS, QPSK, FEC_5_6, 0x31 },
+ { SYS_DVBS, QPSK, FEC_6_7, 0x32 },
+ { SYS_DVBS, QPSK, FEC_7_8, 0x33 },
+
+ { SYS_DVBS2, QPSK, FEC_1_2, 0x04 },
+ { SYS_DVBS2, QPSK, FEC_3_5, 0x05 },
+ { SYS_DVBS2, QPSK, FEC_2_3, 0x06 },
+ { SYS_DVBS2, QPSK, FEC_3_4, 0x07 },
+ { SYS_DVBS2, QPSK, FEC_4_5, 0x08 },
+ { SYS_DVBS2, QPSK, FEC_5_6, 0x09 },
+ { SYS_DVBS2, QPSK, FEC_8_9, 0x0a },
+ { SYS_DVBS2, QPSK, FEC_9_10, 0x0b },
+
+ { SYS_DVBS2, PSK_8, FEC_3_5, 0x0c },
+ { SYS_DVBS2, PSK_8, FEC_2_3, 0x0d },
+ { SYS_DVBS2, PSK_8, FEC_3_4, 0x0e },
+ { SYS_DVBS2, PSK_8, FEC_5_6, 0x0f },
+ { SYS_DVBS2, PSK_8, FEC_8_9, 0x10 },
+ { SYS_DVBS2, PSK_8, FEC_9_10, 0x11 },
+};
+
+/* Set fec_val & fec_mask values from delsys, modulation & fec */
+static int cx24120_set_fec(struct cx24120_state *state, enum fe_modulation mod,
+ enum fe_code_rate fec)
+{
+ int idx;
+
+ dev_dbg(&state->i2c->dev, "(0x%02x,0x%02x)\n", mod, fec);
+
+ state->dnxt.fec = fec;
+
+ /* Lookup fec_val from modfec table */
+ for (idx = 0; idx < ARRAY_SIZE(modfec_table); idx++) {
+ if (modfec_table[idx].delsys != state->dnxt.delsys)
+ continue;
+ if (modfec_table[idx].mod != mod)
+ continue;
+ if (modfec_table[idx].fec != fec)
+ continue;
+
+ /* found */
+ state->dnxt.fec_mask = 0x00;
+ state->dnxt.fec_val = modfec_table[idx].val;
+ return 0;
+ }
+
+ if (state->dnxt.delsys == SYS_DVBS2) {
+ /* DVBS2 auto is 0x00/0x00 */
+ state->dnxt.fec_mask = 0x00;
+ state->dnxt.fec_val = 0x00;
+ } else {
+ /* Set DVB-S to auto */
+ state->dnxt.fec_val = 0x2e;
+ state->dnxt.fec_mask = 0xac;
+ }
+
+ return 0;
+}
+
+/* Set pilot */
+static int cx24120_set_pilot(struct cx24120_state *state, enum fe_pilot pilot)
+{
+ dev_dbg(&state->i2c->dev, "(%d)\n", pilot);
+
+ /* Pilot only valid in DVBS2 */
+ if (state->dnxt.delsys != SYS_DVBS2) {
+ state->dnxt.pilot_val = CX24120_PILOT_OFF;
+ return 0;
+ }
+
+ switch (pilot) {
+ case PILOT_OFF:
+ state->dnxt.pilot_val = CX24120_PILOT_OFF;
+ break;
+ case PILOT_ON:
+ state->dnxt.pilot_val = CX24120_PILOT_ON;
+ break;
+ case PILOT_AUTO:
+ default:
+ state->dnxt.pilot_val = CX24120_PILOT_AUTO;
+ }
+
+ return 0;
+}
+
+/* Set symbol rate */
+static int cx24120_set_symbolrate(struct cx24120_state *state, u32 rate)
+{
+ dev_dbg(&state->i2c->dev, "(%d)\n", rate);
+
+ state->dnxt.symbol_rate = rate;
+
+ /* Check symbol rate */
+ if (rate > 31000000) {
+ state->dnxt.clkdiv = (-(rate < 31000001) & 3) + 2;
+ state->dnxt.ratediv = (-(rate < 31000001) & 6) + 4;
+ } else {
+ state->dnxt.clkdiv = 3;
+ state->dnxt.ratediv = 6;
+ }
+
+ return 0;
+}
+
+/* Overwrite the current tuning params, we are about to tune */
+static void cx24120_clone_params(struct dvb_frontend *fe)
+{
+ struct cx24120_state *state = fe->demodulator_priv;
+
+ state->dcur = state->dnxt;
+}
+
+static int cx24120_set_frontend(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ struct cx24120_state *state = fe->demodulator_priv;
+ struct cx24120_cmd cmd;
+ int ret;
+
+ switch (c->delivery_system) {
+ case SYS_DVBS2:
+ dev_dbg(&state->i2c->dev, "DVB-S2\n");
+ break;
+ case SYS_DVBS:
+ dev_dbg(&state->i2c->dev, "DVB-S\n");
+ break;
+ default:
+ dev_dbg(&state->i2c->dev,
+ "delivery system(%d) not supported\n",
+ c->delivery_system);
+ ret = -EINVAL;
+ break;
+ }
+
+ state->dnxt.delsys = c->delivery_system;
+ state->dnxt.modulation = c->modulation;
+ state->dnxt.frequency = c->frequency;
+ state->dnxt.pilot = c->pilot;
+
+ ret = cx24120_set_inversion(state, c->inversion);
+ if (ret != 0)
+ return ret;
+
+ ret = cx24120_set_fec(state, c->modulation, c->fec_inner);
+ if (ret != 0)
+ return ret;
+
+ ret = cx24120_set_pilot(state, c->pilot);
+ if (ret != 0)
+ return ret;
+
+ ret = cx24120_set_symbolrate(state, c->symbol_rate);
+ if (ret != 0)
+ return ret;
+
+ /* discard the 'current' tuning parameters and prepare to tune */
+ cx24120_clone_params(fe);
+
+ dev_dbg(&state->i2c->dev,
+ "delsys = %d\n", state->dcur.delsys);
+ dev_dbg(&state->i2c->dev,
+ "modulation = %d\n", state->dcur.modulation);
+ dev_dbg(&state->i2c->dev,
+ "frequency = %d\n", state->dcur.frequency);
+ dev_dbg(&state->i2c->dev,
+ "pilot = %d (val = 0x%02x)\n",
+ state->dcur.pilot, state->dcur.pilot_val);
+ dev_dbg(&state->i2c->dev,
+ "symbol_rate = %d (clkdiv/ratediv = 0x%02x/0x%02x)\n",
+ state->dcur.symbol_rate,
+ state->dcur.clkdiv, state->dcur.ratediv);
+ dev_dbg(&state->i2c->dev,
+ "FEC = %d (mask/val = 0x%02x/0x%02x)\n",
+ state->dcur.fec, state->dcur.fec_mask, state->dcur.fec_val);
+ dev_dbg(&state->i2c->dev,
+ "Inversion = %d (val = 0x%02x)\n",
+ state->dcur.inversion, state->dcur.inversion_val);
+
+ /* Flag that clock needs to be set after tune */
+ state->need_clock_set = 1;
+
+ /* Tune in */
+ cmd.id = CMD_TUNEREQUEST;
+ cmd.len = 15;
+ cmd.arg[0] = 0;
+ cmd.arg[1] = (state->dcur.frequency & 0xff0000) >> 16;
+ cmd.arg[2] = (state->dcur.frequency & 0x00ff00) >> 8;
+ cmd.arg[3] = (state->dcur.frequency & 0x0000ff);
+ cmd.arg[4] = ((state->dcur.symbol_rate / 1000) & 0xff00) >> 8;
+ cmd.arg[5] = ((state->dcur.symbol_rate / 1000) & 0x00ff);
+ cmd.arg[6] = state->dcur.inversion;
+ cmd.arg[7] = state->dcur.fec_val | state->dcur.pilot_val;
+ cmd.arg[8] = CX24120_SEARCH_RANGE_KHZ >> 8;
+ cmd.arg[9] = CX24120_SEARCH_RANGE_KHZ & 0xff;
+ cmd.arg[10] = 0; /* maybe rolloff? */
+ cmd.arg[11] = state->dcur.fec_mask;
+ cmd.arg[12] = state->dcur.ratediv;
+ cmd.arg[13] = state->dcur.clkdiv;
+ cmd.arg[14] = 0;
+
+ /* Send tune command */
+ ret = cx24120_message_send(state, &cmd);
+ if (ret != 0)
+ return ret;
+
+ /* Write symbol rate values */
+ ret = cx24120_writereg(state, CX24120_REG_CLKDIV, state->dcur.clkdiv);
+ ret = cx24120_readreg(state, CX24120_REG_RATEDIV);
+ ret &= 0xfffffff0;
+ ret |= state->dcur.ratediv;
+ ret = cx24120_writereg(state, CX24120_REG_RATEDIV, ret);
+
+ return 0;
+}
+
+/* Set vco from config */
+static int cx24120_set_vco(struct cx24120_state *state)
+{
+ struct cx24120_cmd cmd;
+ u32 nxtal_khz, vco;
+ u64 inv_vco;
+ u32 xtal_khz = state->config->xtal_khz;
+
+ nxtal_khz = xtal_khz * 4;
+ vco = nxtal_khz * 10;
+ inv_vco = DIV_ROUND_CLOSEST_ULL(0x400000000ULL, vco);
+
+ dev_dbg(&state->i2c->dev, "xtal=%d, vco=%d, inv_vco=%lld\n",
+ xtal_khz, vco, inv_vco);
+
+ cmd.id = CMD_VCO_SET;
+ cmd.len = 12;
+ cmd.arg[0] = (vco >> 16) & 0xff;
+ cmd.arg[1] = (vco >> 8) & 0xff;
+ cmd.arg[2] = vco & 0xff;
+ cmd.arg[3] = (inv_vco >> 8) & 0xff;
+ cmd.arg[4] = (inv_vco) & 0xff;
+ cmd.arg[5] = 0x03;
+ cmd.arg[6] = (nxtal_khz >> 8) & 0xff;
+ cmd.arg[7] = nxtal_khz & 0xff;
+ cmd.arg[8] = 0x06;
+ cmd.arg[9] = 0x03;
+ cmd.arg[10] = (xtal_khz >> 16) & 0xff;
+ cmd.arg[11] = xtal_khz & 0xff;
+
+ return cx24120_message_send(state, &cmd);
+}
+
+static int cx24120_init(struct dvb_frontend *fe)
+{
+ const struct firmware *fw;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ struct cx24120_state *state = fe->demodulator_priv;
+ struct cx24120_cmd cmd;
+ u8 reg;
+ int ret, i;
+ unsigned char vers[4];
+
+ if (state->cold_init)
+ return 0;
+
+ /* ???? */
+ cx24120_writereg(state, 0xea, 0x00);
+ cx24120_test_rom(state);
+ reg = cx24120_readreg(state, 0xfb) & 0xfe;
+ cx24120_writereg(state, 0xfb, reg);
+ reg = cx24120_readreg(state, 0xfc) & 0xfe;
+ cx24120_writereg(state, 0xfc, reg);
+ cx24120_writereg(state, 0xc3, 0x04);
+ cx24120_writereg(state, 0xc4, 0x04);
+ cx24120_writereg(state, 0xce, 0x00);
+ cx24120_writereg(state, 0xcf, 0x00);
+ reg = cx24120_readreg(state, 0xea) & 0xfe;
+ cx24120_writereg(state, 0xea, reg);
+ cx24120_writereg(state, 0xeb, 0x0c);
+ cx24120_writereg(state, 0xec, 0x06);
+ cx24120_writereg(state, 0xed, 0x05);
+ cx24120_writereg(state, 0xee, 0x03);
+ cx24120_writereg(state, 0xef, 0x05);
+ cx24120_writereg(state, 0xf3, 0x03);
+ cx24120_writereg(state, 0xf4, 0x44);
+
+ for (i = 0; i < 3; i++) {
+ cx24120_writereg(state, 0xf0 + i, 0x04);
+ cx24120_writereg(state, 0xe6 + i, 0x02);
+ }
+
+ cx24120_writereg(state, 0xea, (reg | 0x01));
+ for (i = 0; i < 6; i += 2) {
+ cx24120_writereg(state, 0xc5 + i, 0x00);
+ cx24120_writereg(state, 0xc6 + i, 0x00);
+ }
+
+ cx24120_writereg(state, 0xe4, 0x03);
+ cx24120_writereg(state, 0xeb, 0x0a);
+
+ dev_dbg(&state->i2c->dev, "requesting firmware (%s) to download...\n",
+ CX24120_FIRMWARE);
+
+ ret = state->config->request_firmware(fe, &fw, CX24120_FIRMWARE);
+ if (ret) {
+ err("Could not load firmware (%s): %d\n", CX24120_FIRMWARE,
+ ret);
+ return ret;
+ }
+
+ dev_dbg(&state->i2c->dev,
+ "Firmware found, size %d bytes (%02x %02x .. %02x %02x)\n",
+ (int)fw->size, /* firmware_size in bytes */
+ fw->data[0], /* fw 1st byte */
+ fw->data[1], /* fw 2d byte */
+ fw->data[fw->size - 2], /* fw before last byte */
+ fw->data[fw->size - 1]); /* fw last byte */
+
+ cx24120_test_rom(state);
+ reg = cx24120_readreg(state, 0xfb) & 0xfe;
+ cx24120_writereg(state, 0xfb, reg);
+ cx24120_writereg(state, 0xe0, 0x76);
+ cx24120_writereg(state, 0xf7, 0x81);
+ cx24120_writereg(state, 0xf8, 0x00);
+ cx24120_writereg(state, 0xf9, 0x00);
+ cx24120_writeregs(state, 0xfa, fw->data, (fw->size - 1), 0x00);
+ cx24120_writereg(state, 0xf7, 0xc0);
+ cx24120_writereg(state, 0xe0, 0x00);
+ reg = (fw->size - 2) & 0x00ff;
+ cx24120_writereg(state, 0xf8, reg);
+ reg = ((fw->size - 2) >> 8) & 0x00ff;
+ cx24120_writereg(state, 0xf9, reg);
+ cx24120_writereg(state, 0xf7, 0x00);
+ cx24120_writereg(state, 0xdc, 0x00);
+ cx24120_writereg(state, 0xdc, 0x07);
+ msleep(500);
+
+ /* Check final byte matches final byte of firmware */
+ reg = cx24120_readreg(state, 0xe1);
+ if (reg == fw->data[fw->size - 1]) {
+ dev_dbg(&state->i2c->dev, "Firmware uploaded successfully\n");
+ ret = 0;
+ } else {
+ err("Firmware upload failed. Last byte returned=0x%x\n", ret);
+ ret = -EREMOTEIO;
+ }
+ cx24120_writereg(state, 0xdc, 0x00);
+ release_firmware(fw);
+ if (ret != 0)
+ return ret;
+
+ /* Start tuner */
+ cmd.id = CMD_START_TUNER;
+ cmd.len = 3;
+ cmd.arg[0] = 0x00;
+ cmd.arg[1] = 0x00;
+ cmd.arg[2] = 0x00;
+
+ if (cx24120_message_send(state, &cmd) != 0) {
+ err("Error tuner start! :(\n");
+ return -EREMOTEIO;
+ }
+
+ /* Set VCO */
+ ret = cx24120_set_vco(state);
+ if (ret != 0) {
+ err("Error set VCO! :(\n");
+ return ret;
+ }
+
+ /* set bandwidth */
+ cmd.id = CMD_BANDWIDTH;
+ cmd.len = 12;
+ cmd.arg[0] = 0x00;
+ cmd.arg[1] = 0x00;
+ cmd.arg[2] = 0x00;
+ cmd.arg[3] = 0x00;
+ cmd.arg[4] = 0x05;
+ cmd.arg[5] = 0x02;
+ cmd.arg[6] = 0x02;
+ cmd.arg[7] = 0x00;
+ cmd.arg[8] = 0x05;
+ cmd.arg[9] = 0x02;
+ cmd.arg[10] = 0x02;
+ cmd.arg[11] = 0x00;
+
+ if (cx24120_message_send(state, &cmd)) {
+ err("Error set bandwidth!\n");
+ return -EREMOTEIO;
+ }
+
+ reg = cx24120_readreg(state, 0xba);
+ if (reg > 3) {
+ dev_dbg(&state->i2c->dev, "Reset-readreg 0xba: %x\n", ret);
+ err("Error initialising tuner!\n");
+ return -EREMOTEIO;
+ }
+
+ dev_dbg(&state->i2c->dev, "Tuner initialised correctly.\n");
+
+ /* Initialise mpeg outputs */
+ cx24120_writereg(state, 0xeb, 0x0a);
+ if (cx24120_msg_mpeg_output_global_config(state, 0) ||
+ cx24120_msg_mpeg_output_config(state, 0) ||
+ cx24120_msg_mpeg_output_config(state, 1) ||
+ cx24120_msg_mpeg_output_config(state, 2)) {
+ err("Error initialising mpeg output. :(\n");
+ return -EREMOTEIO;
+ }
+
+ /* Set size of BER window */
+ cmd.id = CMD_BER_CTRL;
+ cmd.len = 3;
+ cmd.arg[0] = 0x00;
+ cmd.arg[1] = CX24120_BER_WINDOW;
+ cmd.arg[2] = CX24120_BER_WINDOW;
+ if (cx24120_message_send(state, &cmd)) {
+ err("Error setting ber window\n");
+ return -EREMOTEIO;
+ }
+
+ /* Firmware CMD 35: Get firmware version */
+ cmd.id = CMD_FWVERSION;
+ cmd.len = 1;
+ for (i = 0; i < 4; i++) {
+ cmd.arg[0] = i;
+ ret = cx24120_message_send(state, &cmd);
+ if (ret != 0)
+ return ret;
+ vers[i] = cx24120_readreg(state, CX24120_REG_MAILBOX);
+ }
+ info("FW version %i.%i.%i.%i\n", vers[0], vers[1], vers[2], vers[3]);
+
+ /* init stats here in order signal app which stats are supported */
+ c->strength.len = 1;
+ c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->cnr.len = 1;
+ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->post_bit_error.len = 1;
+ c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->post_bit_count.len = 1;
+ c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->block_error.len = 1;
+ c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->block_count.len = 1;
+ c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+ state->cold_init = 1;
+
+ return 0;
+}
+
+static int cx24120_tune(struct dvb_frontend *fe, bool re_tune,
+ unsigned int mode_flags, unsigned int *delay,
+ enum fe_status *status)
+{
+ struct cx24120_state *state = fe->demodulator_priv;
+ int ret;
+
+ dev_dbg(&state->i2c->dev, "(%d)\n", re_tune);
+
+ /* TODO: Do we need to set delay? */
+
+ if (re_tune) {
+ ret = cx24120_set_frontend(fe);
+ if (ret)
+ return ret;
+ }
+
+ return cx24120_read_status(fe, status);
+}
+
+static int cx24120_get_algo(struct dvb_frontend *fe)
+{
+ return DVBFE_ALGO_HW;
+}
+
+static int cx24120_sleep(struct dvb_frontend *fe)
+{
+ return 0;
+}
+
+static int cx24120_get_frontend(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ struct cx24120_state *state = fe->demodulator_priv;
+ u8 freq1, freq2, freq3;
+
+ dev_dbg(&state->i2c->dev, "\n");
+
+ /* don't return empty data if we're not tuned in */
+ if ((state->fe_status & FE_HAS_LOCK) == 0)
+ return 0;
+
+ /* Get frequency */
+ freq1 = cx24120_readreg(state, CX24120_REG_FREQ1);
+ freq2 = cx24120_readreg(state, CX24120_REG_FREQ2);
+ freq3 = cx24120_readreg(state, CX24120_REG_FREQ3);
+ c->frequency = (freq3 << 16) | (freq2 << 8) | freq1;
+ dev_dbg(&state->i2c->dev, "frequency = %d\n", c->frequency);
+
+ /* Get modulation, fec, pilot */
+ cx24120_get_fec(fe);
+
+ return 0;
+}
+
+static void cx24120_release(struct dvb_frontend *fe)
+{
+ struct cx24120_state *state = fe->demodulator_priv;
+
+ dev_dbg(&state->i2c->dev, "Clear state structure\n");
+ kfree(state);
+}
+
+static int cx24120_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+ struct cx24120_state *state = fe->demodulator_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+ if (c->block_error.stat[0].scale != FE_SCALE_COUNTER) {
+ *ucblocks = 0;
+ return 0;
+ }
+
+ *ucblocks = c->block_error.stat[0].uvalue - state->ucb_offset;
+
+ return 0;
+}
+
+static struct dvb_frontend_ops cx24120_ops = {
+ .delsys = { SYS_DVBS, SYS_DVBS2 },
+ .info = {
+ .name = "Conexant CX24120/CX24118",
+ .frequency_min = 950000,
+ .frequency_max = 2150000,
+ .frequency_stepsize = 1011, /* kHz for QPSK frontends */
+ .frequency_tolerance = 5000,
+ .symbol_rate_min = 1000000,
+ .symbol_rate_max = 45000000,
+ .caps = FE_CAN_INVERSION_AUTO |
+ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+ FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
+ FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+ FE_CAN_2G_MODULATION |
+ FE_CAN_QPSK | FE_CAN_RECOVER
+ },
+ .release = cx24120_release,
+
+ .init = cx24120_init,
+ .sleep = cx24120_sleep,
+
+ .tune = cx24120_tune,
+ .get_frontend_algo = cx24120_get_algo,
+ .set_frontend = cx24120_set_frontend,
+
+ .get_frontend = cx24120_get_frontend,
+ .read_status = cx24120_read_status,
+ .read_ber = cx24120_read_ber,
+ .read_signal_strength = cx24120_read_signal_strength,
+ .read_snr = cx24120_read_snr,
+ .read_ucblocks = cx24120_read_ucblocks,
+
+ .diseqc_send_master_cmd = cx24120_send_diseqc_msg,
+
+ .diseqc_send_burst = cx24120_diseqc_send_burst,
+ .set_tone = cx24120_set_tone,
+ .set_voltage = cx24120_set_voltage,
+};
+
+MODULE_DESCRIPTION("DVB Frontend module for Conexant CX24120/CX24118 hardware");
+MODULE_AUTHOR("Jemma Denson");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/cx24120.h b/drivers/media/dvb-frontends/cx24120.h
new file mode 100644
index 000000000..f0970423e
--- /dev/null
+++ b/drivers/media/dvb-frontends/cx24120.h
@@ -0,0 +1,58 @@
+/*
+ * Conexant CX24120/CX24118 - DVB-S/S2 demod/tuner driver
+ *
+ * Copyright (C) 2008 Patrick Boettcher <pb@linuxtv.org>
+ * Copyright (C) 2009 Sergey Tyurin <forum.free-x.de>
+ * Updated 2012 by Jannis Achstetter <jannis_achstetter@web.de>
+ * Copyright (C) 2015 Jemma Denson <jdenson@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; 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 CX24120_H
+#define CX24120_H
+
+#include <linux/kconfig.h>
+#include <linux/dvb/frontend.h>
+#include <linux/firmware.h>
+
+struct cx24120_initial_mpeg_config {
+ u8 x1;
+ u8 x2;
+ u8 x3;
+};
+
+struct cx24120_config {
+ u8 i2c_addr;
+ u32 xtal_khz;
+ struct cx24120_initial_mpeg_config initial_mpeg_config;
+
+ int (*request_firmware)(struct dvb_frontend *fe,
+ const struct firmware **fw, char *name);
+
+ /* max bytes I2C provider can write at once */
+ u16 i2c_wr_max;
+};
+
+#if IS_REACHABLE(CONFIG_DVB_CX24120)
+struct dvb_frontend *cx24120_attach(const struct cx24120_config *config,
+ struct i2c_adapter *i2c);
+#else
+static inline
+struct dvb_frontend *cx24120_attach(const struct cx24120_config *config,
+ struct i2c_adapter *i2c)
+{
+ pr_warn("%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif
+
+#endif /* CX24120_H */
diff --git a/drivers/media/dvb-frontends/cx24123.c b/drivers/media/dvb-frontends/cx24123.c
index 7975c6608..e18cf9e11 100644
--- a/drivers/media/dvb-frontends/cx24123.c
+++ b/drivers/media/dvb-frontends/cx24123.c
@@ -290,7 +290,7 @@ static int cx24123_i2c_readreg(struct cx24123_state *state, u8 i2c_addr, u8 reg)
cx24123_i2c_writereg(state, state->config->demod_address, reg, val)
static int cx24123_set_inversion(struct cx24123_state *state,
- fe_spectral_inversion_t inversion)
+ enum fe_spectral_inversion inversion)
{
u8 nom_reg = cx24123_readreg(state, 0x0e);
u8 auto_reg = cx24123_readreg(state, 0x10);
@@ -318,7 +318,7 @@ static int cx24123_set_inversion(struct cx24123_state *state,
}
static int cx24123_get_inversion(struct cx24123_state *state,
- fe_spectral_inversion_t *inversion)
+ enum fe_spectral_inversion *inversion)
{
u8 val;
@@ -335,7 +335,7 @@ static int cx24123_get_inversion(struct cx24123_state *state,
return 0;
}
-static int cx24123_set_fec(struct cx24123_state *state, fe_code_rate_t fec)
+static int cx24123_set_fec(struct cx24123_state *state, enum fe_code_rate fec)
{
u8 nom_reg = cx24123_readreg(state, 0x0e) & ~0x07;
@@ -397,7 +397,7 @@ static int cx24123_set_fec(struct cx24123_state *state, fe_code_rate_t fec)
return 0;
}
-static int cx24123_get_fec(struct cx24123_state *state, fe_code_rate_t *fec)
+static int cx24123_get_fec(struct cx24123_state *state, enum fe_code_rate *fec)
{
int ret;
@@ -720,7 +720,7 @@ static int cx24123_initfe(struct dvb_frontend *fe)
}
static int cx24123_set_voltage(struct dvb_frontend *fe,
- fe_sec_voltage_t voltage)
+ enum fe_sec_voltage voltage)
{
struct cx24123_state *state = fe->demodulator_priv;
u8 val;
@@ -795,7 +795,7 @@ static int cx24123_send_diseqc_msg(struct dvb_frontend *fe,
}
static int cx24123_diseqc_send_burst(struct dvb_frontend *fe,
- fe_sec_mini_cmd_t burst)
+ enum fe_sec_mini_cmd burst)
{
struct cx24123_state *state = fe->demodulator_priv;
int val, tone;
@@ -831,7 +831,7 @@ static int cx24123_diseqc_send_burst(struct dvb_frontend *fe,
return 0;
}
-static int cx24123_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int cx24123_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct cx24123_state *state = fe->demodulator_priv;
int sync = cx24123_readreg(state, 0x14);
@@ -966,7 +966,7 @@ static int cx24123_get_frontend(struct dvb_frontend *fe)
return 0;
}
-static int cx24123_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+static int cx24123_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)
{
struct cx24123_state *state = fe->demodulator_priv;
u8 val;
@@ -995,7 +995,7 @@ static int cx24123_tune(struct dvb_frontend *fe,
bool re_tune,
unsigned int mode_flags,
unsigned int *delay,
- fe_status_t *status)
+ enum fe_status *status)
{
int retval = 0;
diff --git a/drivers/media/dvb-frontends/cx24123.h b/drivers/media/dvb-frontends/cx24123.h
index 758aee5a0..975f3c926 100644
--- a/drivers/media/dvb-frontends/cx24123.h
+++ b/drivers/media/dvb-frontends/cx24123.h
@@ -50,7 +50,7 @@ static inline struct dvb_frontend *cx24123_attach(
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-static struct i2c_adapter *
+static inline struct i2c_adapter *
cx24123_get_tuner_i2c_adapter(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
diff --git a/drivers/media/dvb-frontends/cxd2820r_c.c b/drivers/media/dvb-frontends/cxd2820r_c.c
index 72b0e2db3..42fad6aa3 100644
--- a/drivers/media/dvb-frontends/cxd2820r_c.c
+++ b/drivers/media/dvb-frontends/cxd2820r_c.c
@@ -259,7 +259,7 @@ int cxd2820r_read_ucblocks_c(struct dvb_frontend *fe, u32 *ucblocks)
return 0;
}
-int cxd2820r_read_status_c(struct dvb_frontend *fe, fe_status_t *status)
+int cxd2820r_read_status_c(struct dvb_frontend *fe, enum fe_status *status)
{
struct cxd2820r_priv *priv = fe->demodulator_priv;
int ret;
diff --git a/drivers/media/dvb-frontends/cxd2820r_core.c b/drivers/media/dvb-frontends/cxd2820r_core.c
index 490e09004..def6d21d1 100644
--- a/drivers/media/dvb-frontends/cxd2820r_core.c
+++ b/drivers/media/dvb-frontends/cxd2820r_core.c
@@ -287,7 +287,8 @@ static int cxd2820r_set_frontend(struct dvb_frontend *fe)
err:
return ret;
}
-static int cxd2820r_read_status(struct dvb_frontend *fe, fe_status_t *status)
+
+static int cxd2820r_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct cxd2820r_priv *priv = fe->demodulator_priv;
int ret;
@@ -501,7 +502,7 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe)
struct cxd2820r_priv *priv = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret, i;
- fe_status_t status = 0;
+ enum fe_status status = 0;
dev_dbg(&priv->i2c->dev, "%s: delsys=%d\n", __func__,
fe->dtv_property_cache.delivery_system);
diff --git a/drivers/media/dvb-frontends/cxd2820r_priv.h b/drivers/media/dvb-frontends/cxd2820r_priv.h
index 4b428959b..a0d53f01a 100644
--- a/drivers/media/dvb-frontends/cxd2820r_priv.h
+++ b/drivers/media/dvb-frontends/cxd2820r_priv.h
@@ -48,7 +48,7 @@ struct cxd2820r_priv {
struct gpio_chip gpio_chip;
#endif
- fe_delivery_system_t delivery_system;
+ enum fe_delivery_system delivery_system;
bool last_tune_failed; /* for switch between T and T2 tune */
};
@@ -80,7 +80,7 @@ int cxd2820r_get_frontend_c(struct dvb_frontend *fe);
int cxd2820r_set_frontend_c(struct dvb_frontend *fe);
-int cxd2820r_read_status_c(struct dvb_frontend *fe, fe_status_t *status);
+int cxd2820r_read_status_c(struct dvb_frontend *fe, enum fe_status *status);
int cxd2820r_read_ber_c(struct dvb_frontend *fe, u32 *ber);
@@ -103,7 +103,7 @@ int cxd2820r_get_frontend_t(struct dvb_frontend *fe);
int cxd2820r_set_frontend_t(struct dvb_frontend *fe);
-int cxd2820r_read_status_t(struct dvb_frontend *fe, fe_status_t *status);
+int cxd2820r_read_status_t(struct dvb_frontend *fe, enum fe_status *status);
int cxd2820r_read_ber_t(struct dvb_frontend *fe, u32 *ber);
@@ -126,7 +126,7 @@ int cxd2820r_get_frontend_t2(struct dvb_frontend *fe);
int cxd2820r_set_frontend_t2(struct dvb_frontend *fe);
-int cxd2820r_read_status_t2(struct dvb_frontend *fe, fe_status_t *status);
+int cxd2820r_read_status_t2(struct dvb_frontend *fe, enum fe_status *status);
int cxd2820r_read_ber_t2(struct dvb_frontend *fe, u32 *ber);
diff --git a/drivers/media/dvb-frontends/cxd2820r_t.c b/drivers/media/dvb-frontends/cxd2820r_t.c
index 008cb2ac8..21abf1b4e 100644
--- a/drivers/media/dvb-frontends/cxd2820r_t.c
+++ b/drivers/media/dvb-frontends/cxd2820r_t.c
@@ -349,7 +349,7 @@ int cxd2820r_read_ucblocks_t(struct dvb_frontend *fe, u32 *ucblocks)
return 0;
}
-int cxd2820r_read_status_t(struct dvb_frontend *fe, fe_status_t *status)
+int cxd2820r_read_status_t(struct dvb_frontend *fe, enum fe_status *status)
{
struct cxd2820r_priv *priv = fe->demodulator_priv;
int ret;
diff --git a/drivers/media/dvb-frontends/cxd2820r_t2.c b/drivers/media/dvb-frontends/cxd2820r_t2.c
index 35fe364c7..4e028b41c 100644
--- a/drivers/media/dvb-frontends/cxd2820r_t2.c
+++ b/drivers/media/dvb-frontends/cxd2820r_t2.c
@@ -284,7 +284,7 @@ error:
return ret;
}
-int cxd2820r_read_status_t2(struct dvb_frontend *fe, fe_status_t *status)
+int cxd2820r_read_status_t2(struct dvb_frontend *fe, enum fe_status *status)
{
struct cxd2820r_priv *priv = fe->demodulator_priv;
int ret;
diff --git a/drivers/media/dvb-frontends/dib0070.c b/drivers/media/dvb-frontends/dib0070.c
index 3b024bfe9..0b8fb5dd1 100644
--- a/drivers/media/dvb-frontends/dib0070.c
+++ b/drivers/media/dvb-frontends/dib0070.c
@@ -58,10 +58,10 @@ struct dib0070_state {
u16 wbd_ff_offset;
u8 revision;
- enum frontend_tune_state tune_state;
- u32 current_rf;
+ enum frontend_tune_state tune_state;
+ u32 current_rf;
- /* for the captrim binary search */
+ /* for the captrim binary search */
s8 step;
u16 adc_diff;
@@ -72,7 +72,7 @@ struct dib0070_state {
const struct dib0070_tuning *current_tune_table_index;
const struct dib0070_lna_match *lna_match;
- u8 wbd_gain_current;
+ u8 wbd_gain_current;
u16 wbd_offset_3_3[2];
/* for the I2C transfer */
@@ -151,31 +151,31 @@ static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
} while (0)
static int dib0070_set_bandwidth(struct dvb_frontend *fe)
-{
- struct dib0070_state *state = fe->tuner_priv;
- u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
-
- if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 7000)
- tmp |= (0 << 14);
- else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 6000)
- tmp |= (1 << 14);
- else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 5000)
- tmp |= (2 << 14);
- else
- tmp |= (3 << 14);
-
- dib0070_write_reg(state, 0x02, tmp);
-
- /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */
- if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) {
- u16 value = dib0070_read_reg(state, 0x17);
-
- dib0070_write_reg(state, 0x17, value & 0xfffc);
- tmp = dib0070_read_reg(state, 0x01) & 0x01ff;
- dib0070_write_reg(state, 0x01, tmp | (60 << 9));
-
- dib0070_write_reg(state, 0x17, value);
- }
+ {
+ struct dib0070_state *state = fe->tuner_priv;
+ u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
+
+ if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 7000)
+ tmp |= (0 << 14);
+ else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 6000)
+ tmp |= (1 << 14);
+ else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 5000)
+ tmp |= (2 << 14);
+ else
+ tmp |= (3 << 14);
+
+ dib0070_write_reg(state, 0x02, tmp);
+
+ /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */
+ if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) {
+ u16 value = dib0070_read_reg(state, 0x17);
+
+ dib0070_write_reg(state, 0x17, value & 0xfffc);
+ tmp = dib0070_read_reg(state, 0x01) & 0x01ff;
+ dib0070_write_reg(state, 0x01, tmp | (60 << 9));
+
+ dib0070_write_reg(state, 0x17, value);
+ }
return 0;
}
@@ -186,7 +186,6 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state
int ret = 0;
if (*tune_state == CT_TUNER_STEP_0) {
-
dib0070_write_reg(state, 0x0f, 0xed10);
dib0070_write_reg(state, 0x17, 0x0034);
@@ -195,7 +194,7 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state
state->adc_diff = 3000;
ret = 20;
- *tune_state = CT_TUNER_STEP_1;
+ *tune_state = CT_TUNER_STEP_1;
} else if (*tune_state == CT_TUNER_STEP_1) {
state->step /= 2;
dib0070_write_reg(state, 0x14, state->lo4 | state->captrim);
@@ -220,9 +219,6 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state
dprintk("CAPTRIM=%hd is closer to target (%hd/%hd)", state->captrim, adc, state->adc_diff);
state->adc_diff = adc;
state->fcaptrim = state->captrim;
-
-
-
}
state->captrim += (step_sign * state->step);
@@ -243,7 +239,8 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state
static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt)
{
struct dib0070_state *state = fe->tuner_priv;
- u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
+ u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
+
dprintk("CTRL_LO5: 0x%x", lo5);
return dib0070_write_reg(state, 0x15, lo5);
}
@@ -257,281 +254,282 @@ void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)
dib0070_write_reg(state, 0x1a, 0x0000);
} else {
dib0070_write_reg(state, 0x1b, 0x4112);
- if (state->cfg->vga_filter != 0) {
- dib0070_write_reg(state, 0x1a, state->cfg->vga_filter);
- dprintk("vga filter register is set to %x", state->cfg->vga_filter);
- } else
- dib0070_write_reg(state, 0x1a, 0x0009);
+ if (state->cfg->vga_filter != 0) {
+ dib0070_write_reg(state, 0x1a, state->cfg->vga_filter);
+ dprintk("vga filter register is set to %x", state->cfg->vga_filter);
+ } else
+ dib0070_write_reg(state, 0x1a, 0x0009);
}
}
EXPORT_SYMBOL(dib0070_ctrl_agc_filter);
struct dib0070_tuning {
- u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
- u8 switch_trim;
- u8 vco_band;
- u8 hfdiv;
- u8 vco_multi;
- u8 presc;
- u8 wbdmux;
- u16 tuner_enable;
+ u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
+ u8 switch_trim;
+ u8 vco_band;
+ u8 hfdiv;
+ u8 vco_multi;
+ u8 presc;
+ u8 wbdmux;
+ u16 tuner_enable;
};
struct dib0070_lna_match {
- u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
- u8 lna_band;
+ u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
+ u8 lna_band;
};
static const struct dib0070_tuning dib0070s_tuning_table[] = {
- { 570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800 }, /* UHF */
- { 700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800 },
- { 863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800 },
- { 1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND */
- { 1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
- { 2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
- { 0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000 }, /* SBAND */
+ { 570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800 }, /* UHF */
+ { 700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800 },
+ { 863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800 },
+ { 1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND */
+ { 1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
+ { 2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
+ { 0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000 }, /* SBAND */
};
static const struct dib0070_tuning dib0070_tuning_table[] = {
- { 115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 }, /* FM below 92MHz cannot be tuned */
- { 179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 }, /* VHF */
- { 189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 },
- { 250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 },
- { 569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800 }, /* UHF */
- { 699999, 2, 0, 1, 4, 2, 2, 0x4000 | 0x0800 },
- { 863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800 },
- { 0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND or everything higher than UHF */
+ { 115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 }, /* FM below 92MHz cannot be tuned */
+ { 179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 }, /* VHF */
+ { 189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 },
+ { 250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 },
+ { 569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800 }, /* UHF */
+ { 699999, 2, 0, 1, 4, 2, 2, 0x4000 | 0x0800 },
+ { 863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800 },
+ { 0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND or everything higher than UHF */
};
static const struct dib0070_lna_match dib0070_lna_flip_chip[] = {
- { 180000, 0 }, /* VHF */
- { 188000, 1 },
- { 196400, 2 },
- { 250000, 3 },
- { 550000, 0 }, /* UHF */
- { 590000, 1 },
- { 666000, 3 },
- { 864000, 5 },
- { 1500000, 0 }, /* LBAND or everything higher than UHF */
- { 1600000, 1 },
- { 2000000, 3 },
- { 0xffffffff, 7 },
+ { 180000, 0 }, /* VHF */
+ { 188000, 1 },
+ { 196400, 2 },
+ { 250000, 3 },
+ { 550000, 0 }, /* UHF */
+ { 590000, 1 },
+ { 666000, 3 },
+ { 864000, 5 },
+ { 1500000, 0 }, /* LBAND or everything higher than UHF */
+ { 1600000, 1 },
+ { 2000000, 3 },
+ { 0xffffffff, 7 },
};
static const struct dib0070_lna_match dib0070_lna[] = {
- { 180000, 0 }, /* VHF */
- { 188000, 1 },
- { 196400, 2 },
- { 250000, 3 },
- { 550000, 2 }, /* UHF */
- { 650000, 3 },
- { 750000, 5 },
- { 850000, 6 },
- { 864000, 7 },
- { 1500000, 0 }, /* LBAND or everything higher than UHF */
- { 1600000, 1 },
- { 2000000, 3 },
- { 0xffffffff, 7 },
+ { 180000, 0 }, /* VHF */
+ { 188000, 1 },
+ { 196400, 2 },
+ { 250000, 3 },
+ { 550000, 2 }, /* UHF */
+ { 650000, 3 },
+ { 750000, 5 },
+ { 850000, 6 },
+ { 864000, 7 },
+ { 1500000, 0 }, /* LBAND or everything higher than UHF */
+ { 1600000, 1 },
+ { 2000000, 3 },
+ { 0xffffffff, 7 },
};
#define LPF 100
static int dib0070_tune_digital(struct dvb_frontend *fe)
{
- struct dib0070_state *state = fe->tuner_priv;
+ struct dib0070_state *state = fe->tuner_priv;
- const struct dib0070_tuning *tune;
- const struct dib0070_lna_match *lna_match;
+ const struct dib0070_tuning *tune;
+ const struct dib0070_lna_match *lna_match;
- enum frontend_tune_state *tune_state = &state->tune_state;
- int ret = 10; /* 1ms is the default delay most of the time */
+ enum frontend_tune_state *tune_state = &state->tune_state;
+ int ret = 10; /* 1ms is the default delay most of the time */
- u8 band = (u8)BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency/1000);
- u32 freq = fe->dtv_property_cache.frequency/1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf);
+ u8 band = (u8)BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency/1000);
+ u32 freq = fe->dtv_property_cache.frequency/1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf);
#ifdef CONFIG_SYS_ISDBT
- if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1)
- if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2)
- && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
- || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
- && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == (state->fe->dtv_property_cache.isdbt_sb_segment_count / 2)))
- || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
- && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))))
- freq += 850;
+ if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1)
+ if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2)
+ && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
+ || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
+ && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == (state->fe->dtv_property_cache.isdbt_sb_segment_count / 2)))
+ || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
+ && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))))
+ freq += 850;
#endif
- if (state->current_rf != freq) {
-
- switch (state->revision) {
- case DIB0070S_P1A:
- tune = dib0070s_tuning_table;
- lna_match = dib0070_lna;
- break;
- default:
- tune = dib0070_tuning_table;
- if (state->cfg->flip_chip)
- lna_match = dib0070_lna_flip_chip;
- else
- lna_match = dib0070_lna;
- break;
- }
- while (freq > tune->max_freq) /* find the right one */
- tune++;
- while (freq > lna_match->max_freq) /* find the right one */
- lna_match++;
-
- state->current_tune_table_index = tune;
- state->lna_match = lna_match;
- }
-
- if (*tune_state == CT_TUNER_START) {
- dprintk("Tuning for Band: %hd (%d kHz)", band, freq);
if (state->current_rf != freq) {
- u8 REFDIV;
- u32 FBDiv, Rest, FREF, VCOF_kHz;
- u8 Den;
-
- state->current_rf = freq;
- state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
-
-
- dib0070_write_reg(state, 0x17, 0x30);
-
-
- VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
-
- switch (band) {
- case BAND_VHF:
- REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000);
- break;
- case BAND_FM:
- REFDIV = (u8) ((state->cfg->clock_khz) / 1000);
- break;
- default:
- REFDIV = (u8) (state->cfg->clock_khz / 10000);
- break;
- }
- FREF = state->cfg->clock_khz / REFDIV;
-
-
switch (state->revision) {
case DIB0070S_P1A:
- FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF);
- Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF;
- break;
-
- case DIB0070_P1G:
- case DIB0070_P1F:
+ tune = dib0070s_tuning_table;
+ lna_match = dib0070_lna;
+ break;
default:
- FBDiv = (freq / (FREF / 2));
- Rest = 2 * freq - FBDiv * FREF;
- break;
- }
-
- if (Rest < LPF)
- Rest = 0;
- else if (Rest < 2 * LPF)
- Rest = 2 * LPF;
- else if (Rest > (FREF - LPF)) {
- Rest = 0;
- FBDiv += 1;
- } else if (Rest > (FREF - 2 * LPF))
- Rest = FREF - 2 * LPF;
- Rest = (Rest * 6528) / (FREF / 10);
-
- Den = 1;
- if (Rest > 0) {
- state->lo4 |= (1 << 14) | (1 << 12);
- Den = 255;
+ tune = dib0070_tuning_table;
+ if (state->cfg->flip_chip)
+ lna_match = dib0070_lna_flip_chip;
+ else
+ lna_match = dib0070_lna;
+ break;
}
+ while (freq > tune->max_freq) /* find the right one */
+ tune++;
+ while (freq > lna_match->max_freq) /* find the right one */
+ lna_match++;
+ state->current_tune_table_index = tune;
+ state->lna_match = lna_match;
+ }
- dib0070_write_reg(state, 0x11, (u16)FBDiv);
- dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV);
- dib0070_write_reg(state, 0x13, (u16) Rest);
-
- if (state->revision == DIB0070S_P1A) {
-
- if (band == BAND_SBAND) {
- dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
- dib0070_write_reg(state, 0x1d, 0xFFFF);
- } else
- dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1);
+ if (*tune_state == CT_TUNER_START) {
+ dprintk("Tuning for Band: %hd (%d kHz)", band, freq);
+ if (state->current_rf != freq) {
+ u8 REFDIV;
+ u32 FBDiv, Rest, FREF, VCOF_kHz;
+ u8 Den;
+
+ state->current_rf = freq;
+ state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
+
+
+ dib0070_write_reg(state, 0x17, 0x30);
+
+
+ VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
+
+ switch (band) {
+ case BAND_VHF:
+ REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000);
+ break;
+ case BAND_FM:
+ REFDIV = (u8) ((state->cfg->clock_khz) / 1000);
+ break;
+ default:
+ REFDIV = (u8) (state->cfg->clock_khz / 10000);
+ break;
+ }
+ FREF = state->cfg->clock_khz / REFDIV;
+
+
+
+ switch (state->revision) {
+ case DIB0070S_P1A:
+ FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF);
+ Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF;
+ break;
+
+ case DIB0070_P1G:
+ case DIB0070_P1F:
+ default:
+ FBDiv = (freq / (FREF / 2));
+ Rest = 2 * freq - FBDiv * FREF;
+ break;
+ }
+
+ if (Rest < LPF)
+ Rest = 0;
+ else if (Rest < 2 * LPF)
+ Rest = 2 * LPF;
+ else if (Rest > (FREF - LPF)) {
+ Rest = 0;
+ FBDiv += 1;
+ } else if (Rest > (FREF - 2 * LPF))
+ Rest = FREF - 2 * LPF;
+ Rest = (Rest * 6528) / (FREF / 10);
+
+ Den = 1;
+ if (Rest > 0) {
+ state->lo4 |= (1 << 14) | (1 << 12);
+ Den = 255;
+ }
+
+
+ dib0070_write_reg(state, 0x11, (u16)FBDiv);
+ dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV);
+ dib0070_write_reg(state, 0x13, (u16) Rest);
+
+ if (state->revision == DIB0070S_P1A) {
+
+ if (band == BAND_SBAND) {
+ dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
+ dib0070_write_reg(state, 0x1d, 0xFFFF);
+ } else
+ dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1);
+ }
+
+ dib0070_write_reg(state, 0x20,
+ 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
+
+ dprintk("REFDIV: %hd, FREF: %d", REFDIV, FREF);
+ dprintk("FBDIV: %d, Rest: %d", FBDiv, Rest);
+ dprintk("Num: %hd, Den: %hd, SD: %hd", (u16) Rest, Den, (state->lo4 >> 12) & 0x1);
+ dprintk("HFDIV code: %hd", state->current_tune_table_index->hfdiv);
+ dprintk("VCO = %hd", state->current_tune_table_index->vco_band);
+ dprintk("VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq);
+
+ *tune_state = CT_TUNER_STEP_0;
+ } else { /* we are already tuned to this frequency - the configuration is correct */
+ ret = 50; /* wakeup time */
+ *tune_state = CT_TUNER_STEP_5;
}
+ } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
- dib0070_write_reg(state, 0x20,
- 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
-
- dprintk("REFDIV: %hd, FREF: %d", REFDIV, FREF);
- dprintk("FBDIV: %d, Rest: %d", FBDiv, Rest);
- dprintk("Num: %hd, Den: %hd, SD: %hd", (u16) Rest, Den, (state->lo4 >> 12) & 0x1);
- dprintk("HFDIV code: %hd", state->current_tune_table_index->hfdiv);
- dprintk("VCO = %hd", state->current_tune_table_index->vco_band);
- dprintk("VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq);
-
- *tune_state = CT_TUNER_STEP_0;
- } else { /* we are already tuned to this frequency - the configuration is correct */
- ret = 50; /* wakeup time */
- *tune_state = CT_TUNER_STEP_5;
- }
- } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
-
- ret = dib0070_captrim(state, tune_state);
+ ret = dib0070_captrim(state, tune_state);
- } else if (*tune_state == CT_TUNER_STEP_4) {
- const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
- if (tmp != NULL) {
- while (freq/1000 > tmp->freq) /* find the right one */
- tmp++;
- dib0070_write_reg(state, 0x0f,
- (0 << 15) | (1 << 14) | (3 << 12)
- | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7)
- | (state->current_tune_table_index->wbdmux << 0));
- state->wbd_gain_current = tmp->wbd_gain_val;
- } else {
+ } else if (*tune_state == CT_TUNER_STEP_4) {
+ const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
+ if (tmp != NULL) {
+ while (freq/1000 > tmp->freq) /* find the right one */
+ tmp++;
dib0070_write_reg(state, 0x0f,
- (0 << 15) | (1 << 14) | (3 << 12) | (6 << 9) | (0 << 8) | (1 << 7) | (state->current_tune_table_index->
- wbdmux << 0));
- state->wbd_gain_current = 6;
- }
+ (0 << 15) | (1 << 14) | (3 << 12)
+ | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7)
+ | (state->current_tune_table_index->wbdmux << 0));
+ state->wbd_gain_current = tmp->wbd_gain_val;
+ } else {
+ dib0070_write_reg(state, 0x0f,
+ (0 << 15) | (1 << 14) | (3 << 12)
+ | (6 << 9) | (0 << 8) | (1 << 7)
+ | (state->current_tune_table_index->wbdmux << 0));
+ state->wbd_gain_current = 6;
+ }
- dib0070_write_reg(state, 0x06, 0x3fff);
+ dib0070_write_reg(state, 0x06, 0x3fff);
dib0070_write_reg(state, 0x07,
(state->current_tune_table_index->switch_trim << 11) | (7 << 8) | (state->lna_match->lna_band << 3) | (3 << 0));
- dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127));
- dib0070_write_reg(state, 0x0d, 0x0d80);
+ dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127));
+ dib0070_write_reg(state, 0x0d, 0x0d80);
- dib0070_write_reg(state, 0x18, 0x07ff);
- dib0070_write_reg(state, 0x17, 0x0033);
+ dib0070_write_reg(state, 0x18, 0x07ff);
+ dib0070_write_reg(state, 0x17, 0x0033);
- *tune_state = CT_TUNER_STEP_5;
- } else if (*tune_state == CT_TUNER_STEP_5) {
- dib0070_set_bandwidth(fe);
- *tune_state = CT_TUNER_STOP;
- } else {
- ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */
- }
- return ret;
+ *tune_state = CT_TUNER_STEP_5;
+ } else if (*tune_state == CT_TUNER_STEP_5) {
+ dib0070_set_bandwidth(fe);
+ *tune_state = CT_TUNER_STOP;
+ } else {
+ ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */
+ }
+ return ret;
}
static int dib0070_tune(struct dvb_frontend *fe)
{
- struct dib0070_state *state = fe->tuner_priv;
- uint32_t ret;
+ struct dib0070_state *state = fe->tuner_priv;
+ uint32_t ret;
- state->tune_state = CT_TUNER_START;
+ state->tune_state = CT_TUNER_START;
- do {
- ret = dib0070_tune_digital(fe);
- if (ret != FE_CALLBACK_TIME_NEVER)
- msleep(ret/10);
- else
- break;
- } while (state->tune_state != CT_TUNER_STOP);
+ do {
+ ret = dib0070_tune_digital(fe);
+ if (ret != FE_CALLBACK_TIME_NEVER)
+ msleep(ret/10);
+ else
+ break;
+ } while (state->tune_state != CT_TUNER_STOP);
- return 0;
+ return 0;
}
static int dib0070_wakeup(struct dvb_frontend *fe)
@@ -610,48 +608,48 @@ static const u16 dib0070_p1f_defaults[] =
static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain)
{
- u16 tuner_en = dib0070_read_reg(state, 0x20);
- u16 offset;
-
- dib0070_write_reg(state, 0x18, 0x07ff);
- dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
- dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0));
- msleep(9);
- offset = dib0070_read_reg(state, 0x19);
- dib0070_write_reg(state, 0x20, tuner_en);
- return offset;
+ u16 tuner_en = dib0070_read_reg(state, 0x20);
+ u16 offset;
+
+ dib0070_write_reg(state, 0x18, 0x07ff);
+ dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
+ dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0));
+ msleep(9);
+ offset = dib0070_read_reg(state, 0x19);
+ dib0070_write_reg(state, 0x20, tuner_en);
+ return offset;
}
static void dib0070_wbd_offset_calibration(struct dib0070_state *state)
{
- u8 gain;
- for (gain = 6; gain < 8; gain++) {
- state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2);
- dprintk("Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain-6]);
- }
+ u8 gain;
+ for (gain = 6; gain < 8; gain++) {
+ state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2);
+ dprintk("Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain-6]);
+ }
}
u16 dib0070_wbd_offset(struct dvb_frontend *fe)
{
- struct dib0070_state *state = fe->tuner_priv;
- const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
- u32 freq = fe->dtv_property_cache.frequency/1000;
-
- if (tmp != NULL) {
- while (freq/1000 > tmp->freq) /* find the right one */
- tmp++;
- state->wbd_gain_current = tmp->wbd_gain_val;
+ struct dib0070_state *state = fe->tuner_priv;
+ const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
+ u32 freq = fe->dtv_property_cache.frequency/1000;
+
+ if (tmp != NULL) {
+ while (freq/1000 > tmp->freq) /* find the right one */
+ tmp++;
+ state->wbd_gain_current = tmp->wbd_gain_val;
} else
- state->wbd_gain_current = 6;
+ state->wbd_gain_current = 6;
- return state->wbd_offset_3_3[state->wbd_gain_current - 6];
+ return state->wbd_offset_3_3[state->wbd_gain_current - 6];
}
EXPORT_SYMBOL(dib0070_wbd_offset);
#define pgm_read_word(w) (*w)
static int dib0070_reset(struct dvb_frontend *fe)
{
- struct dib0070_state *state = fe->tuner_priv;
+ struct dib0070_state *state = fe->tuner_priv;
u16 l, r, *n;
HARD_RESET(state);
@@ -664,7 +662,7 @@ static int dib0070_reset(struct dvb_frontend *fe)
#else
#warning forcing SBAND
#endif
- state->revision = DIB0070S_P1A;
+ state->revision = DIB0070S_P1A;
/* P1F or not */
dprintk("Revision: %x", state->revision);
@@ -703,24 +701,25 @@ static int dib0070_reset(struct dvb_frontend *fe)
dib0070_write_reg(state, 0x02, r | (1 << 5));
}
- if (state->revision == DIB0070S_P1A)
- dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
- else
- dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump, state->cfg->enable_third_order_filter);
+ if (state->revision == DIB0070S_P1A)
+ dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
+ else
+ dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump,
+ state->cfg->enable_third_order_filter);
dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
- dib0070_wbd_offset_calibration(state);
+ dib0070_wbd_offset_calibration(state);
- return 0;
+ return 0;
}
static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency)
{
- struct dib0070_state *state = fe->tuner_priv;
+ struct dib0070_state *state = fe->tuner_priv;
- *frequency = 1000 * state->current_rf;
- return 0;
+ *frequency = 1000 * state->current_rf;
+ return 0;
}
static int dib0070_release(struct dvb_frontend *fe)
diff --git a/drivers/media/dvb-frontends/dib0090.c b/drivers/media/dvb-frontends/dib0090.c
index 68e2af265..47cb72243 100644
--- a/drivers/media/dvb-frontends/dib0090.c
+++ b/drivers/media/dvb-frontends/dib0090.c
@@ -1696,12 +1696,10 @@ static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum front
if (state->identity.p1g)
state->dc = dc_p1g_table;
- *tune_state = CT_TUNER_STEP_0;
/* fall through */
-
case CT_TUNER_STEP_0:
- dprintk("Sart/continue DC calibration for %s path", (state->dc->i == 1) ? "I" : "Q");
+ dprintk("Start/continue DC calibration for %s path", (state->dc->i == 1) ? "I" : "Q");
dib0090_write_reg(state, 0x01, state->dc->bb1);
dib0090_write_reg(state, 0x07, state->bb7 | (state->dc->i << 7));
diff --git a/drivers/media/dvb-frontends/dib3000mb.c b/drivers/media/dvb-frontends/dib3000mb.c
index af91e0c92..7a61172d0 100644
--- a/drivers/media/dvb-frontends/dib3000mb.c
+++ b/drivers/media/dvb-frontends/dib3000mb.c
@@ -118,7 +118,7 @@ static int dib3000mb_set_frontend(struct dvb_frontend *fe, int tuner)
{
struct dib3000_state* state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- fe_code_rate_t fe_cr = FEC_NONE;
+ enum fe_code_rate fe_cr = FEC_NONE;
int search_state, seq;
if (tuner && fe->ops.tuner_ops.set_params) {
@@ -454,7 +454,7 @@ static int dib3000mb_get_frontend(struct dvb_frontend* fe)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct dib3000_state* state = fe->demodulator_priv;
- fe_code_rate_t *cr;
+ enum fe_code_rate *cr;
u16 tps_val;
int inv_test1,inv_test2;
u32 dds_val, threshold = 0x800000;
@@ -611,7 +611,8 @@ static int dib3000mb_get_frontend(struct dvb_frontend* fe)
return 0;
}
-static int dib3000mb_read_status(struct dvb_frontend* fe, fe_status_t *stat)
+static int dib3000mb_read_status(struct dvb_frontend *fe,
+ enum fe_status *stat)
{
struct dib3000_state* state = fe->demodulator_priv;
diff --git a/drivers/media/dvb-frontends/dib3000mc.c b/drivers/media/dvb-frontends/dib3000mc.c
index ffad181a9..583d6b7fa 100644
--- a/drivers/media/dvb-frontends/dib3000mc.c
+++ b/drivers/media/dvb-frontends/dib3000mc.c
@@ -131,7 +131,7 @@ static int dib3000mc_set_timing(struct dib3000mc_state *state, s16 nfft, u32 bw,
static int dib3000mc_setup_pwm_state(struct dib3000mc_state *state)
{
u16 reg_51, reg_52 = state->cfg->agc->setup & 0xfefb;
- if (state->cfg->pwm3_inversion) {
+ if (state->cfg->pwm3_inversion) {
reg_51 = (2 << 14) | (0 << 10) | (7 << 6) | (2 << 2) | (2 << 0);
reg_52 |= (1 << 2);
} else {
@@ -141,12 +141,12 @@ static int dib3000mc_setup_pwm_state(struct dib3000mc_state *state)
dib3000mc_write_word(state, 51, reg_51);
dib3000mc_write_word(state, 52, reg_52);
- if (state->cfg->use_pwm3)
+ if (state->cfg->use_pwm3)
dib3000mc_write_word(state, 245, (1 << 3) | (1 << 0));
else
dib3000mc_write_word(state, 245, 0);
- dib3000mc_write_word(state, 1040, 0x3);
+ dib3000mc_write_word(state, 1040, 0x3);
return 0;
}
@@ -417,7 +417,7 @@ static int dib3000mc_sleep(struct dvb_frontend *demod)
dib3000mc_write_word(state, 1032, 0xFFFF);
dib3000mc_write_word(state, 1033, 0xFFF0);
- return 0;
+ return 0;
}
static void dib3000mc_set_adp_cfg(struct dib3000mc_state *state, s16 qam)
@@ -447,10 +447,14 @@ static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state,
dib3000mc_set_bandwidth(state, bw);
dib3000mc_set_timing(state, ch->transmission_mode, bw, 0);
-// if (boost)
-// dib3000mc_write_word(state, 100, (11 << 6) + 6);
-// else
+#if 1
+ dib3000mc_write_word(state, 100, (16 << 6) + 9);
+#else
+ if (boost)
+ dib3000mc_write_word(state, 100, (11 << 6) + 6);
+ else
dib3000mc_write_word(state, 100, (16 << 6) + 9);
+#endif
dib3000mc_write_word(state, 1027, 0x0800);
dib3000mc_write_word(state, 1027, 0x0000);
@@ -732,7 +736,7 @@ static int dib3000mc_set_frontend(struct dvb_frontend *fe)
return ret;
}
-static int dib3000mc_read_status(struct dvb_frontend *fe, fe_status_t *stat)
+static int dib3000mc_read_status(struct dvb_frontend *fe, enum fe_status *stat)
{
struct dib3000mc_state *state = fe->demodulator_priv;
u16 lock = dib3000mc_read_word(state, 509);
diff --git a/drivers/media/dvb-frontends/dib7000m.c b/drivers/media/dvb-frontends/dib7000m.c
index dcb9a15ef..35eb71fe3 100644
--- a/drivers/media/dvb-frontends/dib7000m.c
+++ b/drivers/media/dvb-frontends/dib7000m.c
@@ -1256,7 +1256,7 @@ static int dib7000m_set_frontend(struct dvb_frontend *fe)
return ret;
}
-static int dib7000m_read_status(struct dvb_frontend *fe, fe_status_t *stat)
+static int dib7000m_read_status(struct dvb_frontend *fe, enum fe_status *stat)
{
struct dib7000m_state *state = fe->demodulator_priv;
u16 lock = dib7000m_read_word(state, 535);
diff --git a/drivers/media/dvb-frontends/dib7000p.c b/drivers/media/dvb-frontends/dib7000p.c
index c505d696f..33be5d6b9 100644
--- a/drivers/media/dvb-frontends/dib7000p.c
+++ b/drivers/media/dvb-frontends/dib7000p.c
@@ -1558,9 +1558,9 @@ static int dib7000p_set_frontend(struct dvb_frontend *fe)
return ret;
}
-static int dib7000p_get_stats(struct dvb_frontend *fe, fe_status_t stat);
+static int dib7000p_get_stats(struct dvb_frontend *fe, enum fe_status stat);
-static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t * stat)
+static int dib7000p_read_status(struct dvb_frontend *fe, enum fe_status *stat)
{
struct dib7000p_state *state = fe->demodulator_priv;
u16 lock = dib7000p_read_word(state, 509);
@@ -1877,7 +1877,7 @@ static u32 dib7000p_get_time_us(struct dvb_frontend *demod)
return time_us;
}
-static int dib7000p_get_stats(struct dvb_frontend *demod, fe_status_t stat)
+static int dib7000p_get_stats(struct dvb_frontend *demod, enum fe_status stat)
{
struct dib7000p_state *state = demod->demodulator_priv;
struct dtv_frontend_properties *c = &demod->dtv_property_cache;
diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c
index 8c6663b63..94c26270f 100644
--- a/drivers/media/dvb-frontends/dib8000.c
+++ b/drivers/media/dvb-frontends/dib8000.c
@@ -3380,13 +3380,13 @@ static int dib8000_sleep(struct dvb_frontend *fe)
return dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF) | dib8000_set_adc_state(state, DIBX000_ADC_OFF);
}
-static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat);
+static int dib8000_read_status(struct dvb_frontend *fe, enum fe_status *stat);
static int dib8000_get_frontend(struct dvb_frontend *fe)
{
struct dib8000_state *state = fe->demodulator_priv;
u16 i, val = 0;
- fe_status_t stat = 0;
+ enum fe_status stat = 0;
u8 index_frontend, sub_index_frontend;
fe->dtv_property_cache.bandwidth_hz = 6000000;
@@ -3733,9 +3733,9 @@ static int dib8000_set_frontend(struct dvb_frontend *fe)
return 0;
}
-static int dib8000_get_stats(struct dvb_frontend *fe, fe_status_t stat);
+static int dib8000_get_stats(struct dvb_frontend *fe, enum fe_status stat);
-static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
+static int dib8000_read_status(struct dvb_frontend *fe, enum fe_status *stat)
{
struct dib8000_state *state = fe->demodulator_priv;
u16 lock_slave = 0, lock;
@@ -4089,7 +4089,7 @@ static u32 dib8000_get_time_us(struct dvb_frontend *fe, int layer)
return time_us;
}
-static int dib8000_get_stats(struct dvb_frontend *fe, fe_status_t stat)
+static int dib8000_get_stats(struct dvb_frontend *fe, enum fe_status stat)
{
struct dib8000_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
diff --git a/drivers/media/dvb-frontends/dib8000.h b/drivers/media/dvb-frontends/dib8000.h
index 780c37bdc..2b8b4b165 100644
--- a/drivers/media/dvb-frontends/dib8000.h
+++ b/drivers/media/dvb-frontends/dib8000.h
@@ -66,7 +66,7 @@ struct dib8000_ops {
#if IS_REACHABLE(CONFIG_DVB_DIB8000)
void *dib8000_attach(struct dib8000_ops *ops);
#else
-static inline int dib8000_attach(struct dib8000_ops *ops)
+static inline void *dib8000_attach(struct dib8000_ops *ops)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
diff --git a/drivers/media/dvb-frontends/dib9000.c b/drivers/media/dvb-frontends/dib9000.c
index f75dec443..8f92aca0b 100644
--- a/drivers/media/dvb-frontends/dib9000.c
+++ b/drivers/media/dvb-frontends/dib9000.c
@@ -1893,7 +1893,7 @@ static int dib9000_get_frontend(struct dvb_frontend *fe)
{
struct dib9000_state *state = fe->demodulator_priv;
u8 index_frontend, sub_index_frontend;
- fe_status_t stat;
+ enum fe_status stat;
int ret = 0;
if (state->get_frontend_internal == 0) {
@@ -2161,7 +2161,7 @@ static u16 dib9000_read_lock(struct dvb_frontend *fe)
return dib9000_read_word(state, 535);
}
-static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
+static int dib9000_read_status(struct dvb_frontend *fe, enum fe_status *stat)
{
struct dib9000_state *state = fe->demodulator_priv;
u8 index_frontend;
diff --git a/drivers/media/dvb-frontends/drx39xyj/drxj.c b/drivers/media/dvb-frontends/drx39xyj/drxj.c
index f6a5f31b0..a90947479 100644
--- a/drivers/media/dvb-frontends/drx39xyj/drxj.c
+++ b/drivers/media/dvb-frontends/drx39xyj/drxj.c
@@ -210,7 +210,7 @@ DEFINES
/**
* \def DRXJ_DEF_I2C_ADDR
-* \brief Default I2C addres of a demodulator instance.
+* \brief Default I2C address of a demodulator instance.
*/
#define DRXJ_DEF_I2C_ADDR (0x52)
@@ -336,7 +336,7 @@ DEFINES
* MICROCODE RELATED DEFINES
*/
-/* Magic word for checking correct Endianess of microcode data */
+/* Magic word for checking correct Endianness of microcode data */
#define DRX_UCODE_MAGIC_WORD ((((u16)'H')<<8)+((u16)'L'))
/* CRC flag in ucode header, flags field. */
@@ -847,9 +847,9 @@ static struct drx_common_attr drxj_default_comm_attr_g = {
static clockrate is selected */
DRX_MPEG_STR_WIDTH_1 /* MPEG Start width in clock cycles */
},
- /* Initilisations below can be ommited, they require no user input and
+ /* Initilisations below can be omitted, they require no user input and
are initialy 0, NULL or false. The compiler will initialize them to these
- values when ommited. */
+ values when omitted. */
false, /* is_opened */
/* SCAN */
@@ -1175,7 +1175,7 @@ static u32 log1_times100(u32 x)
Now x has binary point between bit[scale] and bit[scale-1]
and 1.0 <= x < 2.0 */
- /* correction for divison: log(x) = log(x/y)+log(y) */
+ /* correction for division: log(x) = log(x/y)+log(y) */
y = k * ((((u32) 1) << scale) * 200);
/* remove integer part */
@@ -1653,7 +1653,7 @@ static int drxdap_fasi_write_block(struct i2c_device_addr *dev_addr,
sequense will be visible: (1) write address {i2c addr,
4 bytes chip address} (2) write data {i2c addr, 4 bytes data }
(3) write address (4) write data etc...
- Addres must be rewriten because HI is reset after data transport and
+ Address must be rewriten because HI is reset after data transport and
expects an address.
*/
todo = (block_size < datasize ? block_size : datasize);
@@ -2971,7 +2971,7 @@ ctrl_set_cfg_mpeg_output(struct drx_demod_instance *demod, struct drx_cfg_mpeg_o
} /* ext_attr->standard */
}
- if (cfg_data->enable_parallel == true) { /* MPEG data output is paralel -> clear ipr_mode[0] */
+ if (cfg_data->enable_parallel == true) { /* MPEG data output is parallel -> clear ipr_mode[0] */
fec_oc_reg_ipr_mode &= (~(FEC_OC_IPR_MODE_SERIAL__M));
} else { /* MPEG data output is serial -> set ipr_mode[0] */
fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_SERIAL__M;
@@ -3157,7 +3157,7 @@ ctrl_set_cfg_mpeg_output(struct drx_demod_instance *demod, struct drx_cfg_mpeg_o
pr_err("error %d\n", rc);
goto rw_error;
}
- if (cfg_data->enable_parallel == true) { /* MPEG data output is paralel -> set MD1 to MD7 to output mode */
+ if (cfg_data->enable_parallel == true) { /* MPEG data output is parallel -> set MD1 to MD7 to output mode */
sio_pdr_md_cfg =
MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH <<
SIO_PDR_MD0_CFG_DRIVE__B | 0x03 <<
@@ -4320,7 +4320,7 @@ static int adc_synchronization(struct drx_demod_instance *demod)
}
if (count == 1) {
- /* Try sampling on a diffrent edge */
+ /* Try sampling on a different edge */
u16 clk_neg = 0;
rc = drxj_dap_read_reg16(dev_addr, IQM_AF_CLKNEG__A, &clk_neg, 0);
@@ -6461,7 +6461,7 @@ set_qam_measurement(struct drx_demod_instance *demod,
enum drx_modulation constellation, u32 symbol_rate)
{
struct i2c_device_addr *dev_addr = NULL; /* device address for I2C writes */
- struct drxj_data *ext_attr = NULL; /* Global data container for DRXJ specif data */
+ struct drxj_data *ext_attr = NULL; /* Global data container for DRXJ specific data */
int rc;
u32 fec_bits_desired = 0; /* BER accounting period */
u16 fec_rs_plen = 0; /* defines RS BER measurement period */
@@ -8864,7 +8864,7 @@ qam64auto(struct drx_demod_instance *demod,
u32 timeout_ofs = 0;
u16 data = 0;
- /* external attributes for storing aquired channel constellation */
+ /* external attributes for storing acquired channel constellation */
*lock_status = DRX_NOT_LOCKED;
start_time = jiffies_to_msecs(jiffies);
lck_state = NO_LOCK;
@@ -9011,7 +9011,7 @@ qam256auto(struct drx_demod_instance *demod,
u32 d_locked_time = 0;
u32 timeout_ofs = DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME;
- /* external attributes for storing aquired channel constellation */
+ /* external attributes for storing acquired channel constellation */
*lock_status = DRX_NOT_LOCKED;
start_time = jiffies_to_msecs(jiffies);
lck_state = NO_LOCK;
@@ -9087,7 +9087,7 @@ set_qam_channel(struct drx_demod_instance *demod,
enum drx_lock_status lock_status = DRX_NOT_LOCKED;
bool auto_flag = false;
- /* external attributes for storing aquired channel constellation */
+ /* external attributes for storing acquired channel constellation */
ext_attr = (struct drxj_data *) demod->my_ext_attr;
/* set QAM channel constellation */
@@ -9431,7 +9431,7 @@ rw_error:
/**
* \fn int ctrl_get_qam_sig_quality()
-* \brief Retreive QAM signal quality from device.
+* \brief Retrieve QAM signal quality from device.
* \param devmod Pointer to demodulator instance.
* \param sig_quality Pointer to signal quality data.
* \return int.
@@ -9541,7 +9541,7 @@ ctrl_get_qam_sig_quality(struct drx_demod_instance *demod)
/* ----------------------------------------- */
/* Pre Viterbi Symbol Error Rate Calculation */
/* ----------------------------------------- */
- /* pre viterbi SER is good if it is bellow 0.025 */
+ /* pre viterbi SER is good if it is below 0.025 */
/* get the register value */
/* no of quadrature symbol errors */
@@ -10647,7 +10647,7 @@ rw_error:
/**
* \fn int ctrl_sig_quality()
-* \brief Retreive signal quality form device.
+* \brief Retrieve signal quality form device.
* \param devmod Pointer to demodulator instance.
* \param sig_quality Pointer to signal quality data.
* \return int.
@@ -10763,7 +10763,7 @@ rw_error:
/**
* \fn int ctrl_lock_status()
-* \brief Retreive lock status .
+* \brief Retrieve lock status .
* \param dev_addr Pointer to demodulator device address.
* \param lock_stat Pointer to lock status structure.
* \return int.
@@ -10815,7 +10815,7 @@ ctrl_lock_status(struct drx_demod_instance *demod, enum drx_lock_status *lock_st
return -EIO;
}
- /* define the SCU command paramters and execute the command */
+ /* define the SCU command parameters and execute the command */
cmd_scu.parameter_len = 0;
cmd_scu.result_len = 2;
cmd_scu.parameter = NULL;
@@ -11489,7 +11489,7 @@ static int drxj_open(struct drx_demod_instance *demod)
}
/* Stamp driver version number in SCU data RAM in BCD code
- Done to enable field application engineers to retreive drxdriver version
+ Done to enable field application engineers to retrieve drxdriver version
via I2C from SCU RAM
*/
driver_version = (VERSION_MAJOR / 100) % 10;
@@ -11892,7 +11892,7 @@ release:
return rc;
}
-/* caller is expeced to check if lna is supported before enabling */
+/* caller is expected to check if lna is supported before enabling */
static int drxj_set_lna_state(struct drx_demod_instance *demod, bool state)
{
struct drxuio_cfg uio_cfg;
@@ -11946,7 +11946,7 @@ static int drx39xxj_set_powerstate(struct dvb_frontend *fe, int enable)
return 0;
}
-static int drx39xxj_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int drx39xxj_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct drx39xxj_state *state = fe->demodulator_priv;
struct drx_demod_instance *demod = state->demod;
diff --git a/drivers/media/dvb-frontends/drxd_hard.c b/drivers/media/dvb-frontends/drxd_hard.c
index 25b1731ce..632fbfbc5 100644
--- a/drivers/media/dvb-frontends/drxd_hard.c
+++ b/drivers/media/dvb-frontends/drxd_hard.c
@@ -2805,7 +2805,7 @@ static int drxd_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
return 0;
}
-static int drxd_read_status(struct dvb_frontend *fe, fe_status_t * status)
+static int drxd_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct drxd_state *state = fe->demodulator_priv;
u32 lock;
diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c
index bde292b2d..314ccd5e4 100644
--- a/drivers/media/dvb-frontends/drxk_hard.c
+++ b/drivers/media/dvb-frontends/drxk_hard.c
@@ -544,7 +544,7 @@ error:
static int init_state(struct drxk_state *state)
{
/*
- * FIXME: most (all?) of the values bellow should be moved into
+ * FIXME: most (all?) of the values below should be moved into
* struct drxk_config, as they are probably board-specific
*/
u32 ul_vsb_if_agc_mode = DRXK_AGC_CTRL_AUTO;
@@ -3262,6 +3262,7 @@ static int dvbt_sc_command(struct drxk_state *state,
}
/* Write needed parameters and the command */
+ status = 0;
switch (cmd) {
/* All commands using 5 parameters */
/* All commands using 4 parameters */
@@ -3270,16 +3271,16 @@ static int dvbt_sc_command(struct drxk_state *state,
case OFDM_SC_RA_RAM_CMD_PROC_START:
case OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM:
case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM:
- status = write16(state, OFDM_SC_RA_RAM_PARAM1__A, param1);
+ status |= write16(state, OFDM_SC_RA_RAM_PARAM1__A, param1);
/* All commands using 1 parameters */
case OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING:
case OFDM_SC_RA_RAM_CMD_USER_IO:
- status = write16(state, OFDM_SC_RA_RAM_PARAM0__A, param0);
+ status |= write16(state, OFDM_SC_RA_RAM_PARAM0__A, param0);
/* All commands using 0 parameters */
case OFDM_SC_RA_RAM_CMD_GET_OP_PARAM:
case OFDM_SC_RA_RAM_CMD_NULL:
/* Write command */
- status = write16(state, OFDM_SC_RA_RAM_CMD__A, cmd);
+ status |= write16(state, OFDM_SC_RA_RAM_CMD__A, cmd);
break;
default:
/* Unknown command */
@@ -6639,7 +6640,7 @@ error:
}
-static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int drxk_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct drxk_state *state = fe->demodulator_priv;
int rc;
diff --git a/drivers/media/dvb-frontends/drxk_hard.h b/drivers/media/dvb-frontends/drxk_hard.h
index bae9c71dc..9ed88e014 100644
--- a/drivers/media/dvb-frontends/drxk_hard.h
+++ b/drivers/media/dvb-frontends/drxk_hard.h
@@ -350,7 +350,7 @@ struct drxk_state {
bool antenna_dvbt;
u16 antenna_gpio;
- fe_status_t fe_status;
+ enum fe_status fe_status;
/* Firmware */
const char *microcode_name;
diff --git a/drivers/media/dvb-frontends/ds3000.c b/drivers/media/dvb-frontends/ds3000.c
index 6dfad0147..d329c0cf0 100644
--- a/drivers/media/dvb-frontends/ds3000.c
+++ b/drivers/media/dvb-frontends/ds3000.c
@@ -402,7 +402,8 @@ static int ds3000_load_firmware(struct dvb_frontend *fe,
return ret;
}
-static int ds3000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+static int ds3000_set_voltage(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage)
{
struct ds3000_state *state = fe->demodulator_priv;
u8 data;
@@ -429,7 +430,7 @@ static int ds3000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
return 0;
}
-static int ds3000_read_status(struct dvb_frontend *fe, fe_status_t* status)
+static int ds3000_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct ds3000_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
@@ -664,7 +665,7 @@ static int ds3000_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
return 0;
}
-static int ds3000_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+static int ds3000_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)
{
struct ds3000_state *state = fe->demodulator_priv;
u8 data;
@@ -764,7 +765,7 @@ static int ds3000_send_diseqc_msg(struct dvb_frontend *fe,
/* Send DiSEqC burst */
static int ds3000_diseqc_send_burst(struct dvb_frontend *fe,
- fe_sec_mini_cmd_t burst)
+ enum fe_sec_mini_cmd burst)
{
struct ds3000_state *state = fe->demodulator_priv;
int i;
@@ -903,7 +904,7 @@ static int ds3000_set_frontend(struct dvb_frontend *fe)
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int i;
- fe_status_t status;
+ enum fe_status status;
s32 offset_khz;
u32 frequency;
u16 value;
@@ -1043,7 +1044,7 @@ static int ds3000_tune(struct dvb_frontend *fe,
bool re_tune,
unsigned int mode_flags,
unsigned int *delay,
- fe_status_t *status)
+ enum fe_status *status)
{
if (re_tune) {
int ret = ds3000_set_frontend(fe);
diff --git a/drivers/media/dvb-frontends/dvb_dummy_fe.c b/drivers/media/dvb-frontends/dvb_dummy_fe.c
index d5acc3047..14e996d45 100644
--- a/drivers/media/dvb-frontends/dvb_dummy_fe.c
+++ b/drivers/media/dvb-frontends/dvb_dummy_fe.c
@@ -33,7 +33,8 @@ struct dvb_dummy_fe_state {
};
-static int dvb_dummy_fe_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int dvb_dummy_fe_read_status(struct dvb_frontend *fe,
+ enum fe_status *status)
{
*status = FE_HAS_SIGNAL
| FE_HAS_CARRIER
@@ -97,12 +98,14 @@ static int dvb_dummy_fe_init(struct dvb_frontend* fe)
return 0;
}
-static int dvb_dummy_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+static int dvb_dummy_fe_set_tone(struct dvb_frontend *fe,
+ enum fe_sec_tone_mode tone)
{
return 0;
}
-static int dvb_dummy_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+static int dvb_dummy_fe_set_voltage(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage)
{
return 0;
}
diff --git a/drivers/media/dvb-frontends/ec100.c b/drivers/media/dvb-frontends/ec100.c
index 9d424809d..c9012e677 100644
--- a/drivers/media/dvb-frontends/ec100.c
+++ b/drivers/media/dvb-frontends/ec100.c
@@ -174,7 +174,7 @@ static int ec100_get_tune_settings(struct dvb_frontend *fe,
return 0;
}
-static int ec100_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int ec100_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct ec100_state *state = fe->demodulator_priv;
int ret;
diff --git a/drivers/media/dvb-frontends/hd29l2.c b/drivers/media/dvb-frontends/hd29l2.c
index 67c8e6df4..40e359f2d 100644
--- a/drivers/media/dvb-frontends/hd29l2.c
+++ b/drivers/media/dvb-frontends/hd29l2.c
@@ -211,7 +211,7 @@ err:
return ret;
}
-static int hd29l2_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int hd29l2_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
int ret;
struct hd29l2_priv *priv = fe->demodulator_priv;
diff --git a/drivers/media/dvb-frontends/hd29l2_priv.h b/drivers/media/dvb-frontends/hd29l2_priv.h
index 4d571a228..6dc225c4b 100644
--- a/drivers/media/dvb-frontends/hd29l2_priv.h
+++ b/drivers/media/dvb-frontends/hd29l2_priv.h
@@ -67,7 +67,7 @@ struct hd29l2_priv {
struct hd29l2_config cfg;
u8 tuner_i2c_addr_programmed:1;
- fe_status_t fe_status;
+ enum fe_status fe_status;
};
static const struct reg_mod_vals reg_mod_vals_tab[] = {
diff --git a/drivers/media/dvb-frontends/isl6405.c b/drivers/media/dvb-frontends/isl6405.c
index 0c642a5bf..b46450a10 100644
--- a/drivers/media/dvb-frontends/isl6405.c
+++ b/drivers/media/dvb-frontends/isl6405.c
@@ -43,7 +43,8 @@ struct isl6405 {
u8 i2c_addr;
};
-static int isl6405_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+static int isl6405_set_voltage(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage)
{
struct isl6405 *isl6405 = (struct isl6405 *) fe->sec_priv;
struct i2c_msg msg = { .addr = isl6405->i2c_addr, .flags = 0,
diff --git a/drivers/media/dvb-frontends/isl6421.c b/drivers/media/dvb-frontends/isl6421.c
index c77002fcc..3a4d4606a 100644
--- a/drivers/media/dvb-frontends/isl6421.c
+++ b/drivers/media/dvb-frontends/isl6421.c
@@ -43,7 +43,8 @@ struct isl6421 {
u8 i2c_addr;
};
-static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+static int isl6421_set_voltage(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage)
{
struct isl6421 *isl6421 = (struct isl6421 *) fe->sec_priv;
struct i2c_msg msg = { .addr = isl6421->i2c_addr, .flags = 0,
@@ -89,7 +90,8 @@ static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO;
}
-static int isl6421_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+static int isl6421_set_tone(struct dvb_frontend *fe,
+ enum fe_sec_tone_mode tone)
{
struct isl6421 *isl6421 = (struct isl6421 *) fe->sec_priv;
struct i2c_msg msg = { .addr = isl6421->i2c_addr, .flags = 0,
diff --git a/drivers/media/dvb-frontends/l64781.c b/drivers/media/dvb-frontends/l64781.c
index ddf866c46..097787123 100644
--- a/drivers/media/dvb-frontends/l64781.c
+++ b/drivers/media/dvb-frontends/l64781.c
@@ -359,7 +359,7 @@ static int get_frontend(struct dvb_frontend *fe)
return 0;
}
-static int l64781_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int l64781_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct l64781_state* state = fe->demodulator_priv;
int sync = l64781_readreg (state, 0x32);
diff --git a/drivers/media/dvb-frontends/lg2160.c b/drivers/media/dvb-frontends/lg2160.c
index 99efeba3c..7880f71cc 100644
--- a/drivers/media/dvb-frontends/lg2160.c
+++ b/drivers/media/dvb-frontends/lg2160.c
@@ -1203,7 +1203,7 @@ static int lg216x_read_lock_status(struct lg216x_state *state,
#endif
}
-static int lg216x_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int lg216x_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct lg216x_state *state = fe->demodulator_priv;
int ret, acq_lock, sync_lock;
diff --git a/drivers/media/dvb-frontends/lgdt3305.c b/drivers/media/dvb-frontends/lgdt3305.c
index d08570af1..471218661 100644
--- a/drivers/media/dvb-frontends/lgdt3305.c
+++ b/drivers/media/dvb-frontends/lgdt3305.c
@@ -60,7 +60,7 @@ struct lgdt3305_state {
struct dvb_frontend frontend;
- fe_modulation_t current_modulation;
+ enum fe_modulation current_modulation;
u32 current_frequency;
u32 snr;
};
@@ -912,7 +912,7 @@ fail:
return ret;
}
-static int lgdt3305_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int lgdt3305_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct lgdt3305_state *state = fe->demodulator_priv;
u8 val;
diff --git a/drivers/media/dvb-frontends/lgdt3306a.c b/drivers/media/dvb-frontends/lgdt3306a.c
index d9a2b0e76..721fbc07e 100644
--- a/drivers/media/dvb-frontends/lgdt3306a.c
+++ b/drivers/media/dvb-frontends/lgdt3306a.c
@@ -62,7 +62,7 @@ struct lgdt3306a_state {
struct dvb_frontend frontend;
- fe_modulation_t current_modulation;
+ enum fe_modulation current_modulation;
u32 current_frequency;
u32 snr;
};
@@ -1558,7 +1558,8 @@ lgdt3306a_qam_lock_poll(struct lgdt3306a_state *state)
return LG3306_UNLOCK;
}
-static int lgdt3306a_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int lgdt3306a_read_status(struct dvb_frontend *fe,
+ enum fe_status *status)
{
struct lgdt3306a_state *state = fe->demodulator_priv;
u16 strength = 0;
@@ -1705,7 +1706,7 @@ static int lgdt3306a_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
static int lgdt3306a_tune(struct dvb_frontend *fe, bool re_tune,
unsigned int mode_flags, unsigned int *delay,
- fe_status_t *status)
+ enum fe_status *status)
{
int ret = 0;
struct lgdt3306a_state *state = fe->demodulator_priv;
@@ -1735,7 +1736,7 @@ static int lgdt3306a_get_tune_settings(struct dvb_frontend *fe,
static int lgdt3306a_search(struct dvb_frontend *fe)
{
- fe_status_t status = 0;
+ enum fe_status status = 0;
int i, ret;
/* set frontend */
@@ -2101,7 +2102,7 @@ static void lgdt3306a_DumpRegs(struct lgdt3306a_state *state)
lgdt3306a_read_reg(state, regtab[i], &regval1[i]);
if (regval1[i] != regval2[i]) {
lg_debug(" %04X = %02X\n", regtab[i], regval1[i]);
- regval2[i] = regval1[i];
+ regval2[i] = regval1[i];
}
}
debug = sav_debug;
diff --git a/drivers/media/dvb-frontends/lgdt330x.c b/drivers/media/dvb-frontends/lgdt330x.c
index 2e1a61893..cf3cc2051 100644
--- a/drivers/media/dvb-frontends/lgdt330x.c
+++ b/drivers/media/dvb-frontends/lgdt330x.c
@@ -67,7 +67,7 @@ struct lgdt330x_state
struct dvb_frontend frontend;
/* Demodulator private data */
- fe_modulation_t current_modulation;
+ enum fe_modulation current_modulation;
u32 snr; /* Result of last SNR calculation */
/* Tuner private data */
@@ -447,7 +447,8 @@ static int lgdt330x_get_frontend(struct dvb_frontend *fe)
return 0;
}
-static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int lgdt3302_read_status(struct dvb_frontend *fe,
+ enum fe_status *status)
{
struct lgdt330x_state* state = fe->demodulator_priv;
u8 buf[3];
@@ -505,7 +506,8 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
return 0;
}
-static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int lgdt3303_read_status(struct dvb_frontend *fe,
+ enum fe_status *status)
{
struct lgdt330x_state* state = fe->demodulator_priv;
int err;
diff --git a/drivers/media/dvb-frontends/lgs8gl5.c b/drivers/media/dvb-frontends/lgs8gl5.c
index 416cce3fe..7bbb2c18c 100644
--- a/drivers/media/dvb-frontends/lgs8gl5.c
+++ b/drivers/media/dvb-frontends/lgs8gl5.c
@@ -249,7 +249,7 @@ lgs8gl5_init(struct dvb_frontend *fe)
static int
-lgs8gl5_read_status(struct dvb_frontend *fe, fe_status_t *status)
+lgs8gl5_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct lgs8gl5_state *state = fe->demodulator_priv;
u8 level = lgs8gl5_read_reg(state, REG_STRENGTH);
diff --git a/drivers/media/dvb-frontends/lgs8gxx.c b/drivers/media/dvb-frontends/lgs8gxx.c
index ceb0e4942..5db5dfc09 100644
--- a/drivers/media/dvb-frontends/lgs8gxx.c
+++ b/drivers/media/dvb-frontends/lgs8gxx.c
@@ -732,7 +732,8 @@ int lgs8gxx_get_tune_settings(struct dvb_frontend *fe,
return 0;
}
-static int lgs8gxx_read_status(struct dvb_frontend *fe, fe_status_t *fe_status)
+static int lgs8gxx_read_status(struct dvb_frontend *fe,
+ enum fe_status *fe_status)
{
struct lgs8gxx_state *priv = fe->demodulator_priv;
s8 ret;
diff --git a/drivers/media/dvb-frontends/lnbp21.c b/drivers/media/dvb-frontends/lnbp21.c
index f3ba7b5fa..4aca0fb9a 100644
--- a/drivers/media/dvb-frontends/lnbp21.c
+++ b/drivers/media/dvb-frontends/lnbp21.c
@@ -45,7 +45,7 @@ struct lnbp21 {
};
static int lnbp21_set_voltage(struct dvb_frontend *fe,
- fe_sec_voltage_t voltage)
+ enum fe_sec_voltage voltage)
{
struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
struct i2c_msg msg = { .addr = lnbp21->i2c_addr, .flags = 0,
@@ -92,7 +92,7 @@ static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
}
static int lnbp21_set_tone(struct dvb_frontend *fe,
- fe_sec_tone_mode_t tone)
+ enum fe_sec_tone_mode tone)
{
struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
struct i2c_msg msg = { .addr = lnbp21->i2c_addr, .flags = 0,
diff --git a/drivers/media/dvb-frontends/lnbp22.c b/drivers/media/dvb-frontends/lnbp22.c
index c463da7f6..d7ca0fdd0 100644
--- a/drivers/media/dvb-frontends/lnbp22.c
+++ b/drivers/media/dvb-frontends/lnbp22.c
@@ -48,7 +48,8 @@ struct lnbp22 {
struct i2c_adapter *i2c;
};
-static int lnbp22_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+static int lnbp22_set_voltage(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage)
{
struct lnbp22 *lnbp22 = (struct lnbp22 *)fe->sec_priv;
struct i2c_msg msg = {
diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c
index 8fcbe7d9d..2172c0239 100644
--- a/drivers/media/dvb-frontends/m88ds3103.c
+++ b/drivers/media/dvb-frontends/m88ds3103.c
@@ -1,5 +1,5 @@
/*
- * Montage M88DS3103/M88RS6000 demodulator driver
+ * Montage Technology M88DS3103/M88RS6000 demodulator driver
*
* Copyright (C) 2013 Antti Palosaari <crope@iki.fi>
*
@@ -18,149 +18,15 @@
static struct dvb_frontend_ops m88ds3103_ops;
-/* write multiple registers */
-static int m88ds3103_wr_regs(struct m88ds3103_priv *priv,
- u8 reg, const u8 *val, int len)
-{
-#define MAX_WR_LEN 32
-#define MAX_WR_XFER_LEN (MAX_WR_LEN + 1)
- int ret;
- u8 buf[MAX_WR_XFER_LEN];
- struct i2c_msg msg[1] = {
- {
- .addr = priv->cfg->i2c_addr,
- .flags = 0,
- .len = 1 + len,
- .buf = buf,
- }
- };
-
- if (WARN_ON(len > MAX_WR_LEN))
- return -EINVAL;
-
- buf[0] = reg;
- memcpy(&buf[1], val, len);
-
- mutex_lock(&priv->i2c_mutex);
- ret = i2c_transfer(priv->i2c, msg, 1);
- mutex_unlock(&priv->i2c_mutex);
- if (ret == 1) {
- ret = 0;
- } else {
- dev_warn(&priv->i2c->dev,
- "%s: i2c wr failed=%d reg=%02x len=%d\n",
- KBUILD_MODNAME, ret, reg, len);
- ret = -EREMOTEIO;
- }
-
- return ret;
-}
-
-/* read multiple registers */
-static int m88ds3103_rd_regs(struct m88ds3103_priv *priv,
- u8 reg, u8 *val, int len)
-{
-#define MAX_RD_LEN 3
-#define MAX_RD_XFER_LEN (MAX_RD_LEN)
- int ret;
- u8 buf[MAX_RD_XFER_LEN];
- struct i2c_msg msg[2] = {
- {
- .addr = priv->cfg->i2c_addr,
- .flags = 0,
- .len = 1,
- .buf = &reg,
- }, {
- .addr = priv->cfg->i2c_addr,
- .flags = I2C_M_RD,
- .len = len,
- .buf = buf,
- }
- };
-
- if (WARN_ON(len > MAX_RD_LEN))
- return -EINVAL;
-
- mutex_lock(&priv->i2c_mutex);
- ret = i2c_transfer(priv->i2c, msg, 2);
- mutex_unlock(&priv->i2c_mutex);
- if (ret == 2) {
- memcpy(val, buf, len);
- ret = 0;
- } else {
- dev_warn(&priv->i2c->dev,
- "%s: i2c rd failed=%d reg=%02x len=%d\n",
- KBUILD_MODNAME, ret, reg, len);
- ret = -EREMOTEIO;
- }
-
- return ret;
-}
-
-/* write single register */
-static int m88ds3103_wr_reg(struct m88ds3103_priv *priv, u8 reg, u8 val)
-{
- return m88ds3103_wr_regs(priv, reg, &val, 1);
-}
-
-/* read single register */
-static int m88ds3103_rd_reg(struct m88ds3103_priv *priv, u8 reg, u8 *val)
-{
- return m88ds3103_rd_regs(priv, reg, val, 1);
-}
-
-/* write single register with mask */
-static int m88ds3103_wr_reg_mask(struct m88ds3103_priv *priv,
- u8 reg, u8 val, u8 mask)
-{
- int ret;
- u8 u8tmp;
-
- /* no need for read if whole reg is written */
- if (mask != 0xff) {
- ret = m88ds3103_rd_regs(priv, reg, &u8tmp, 1);
- if (ret)
- return ret;
-
- val &= mask;
- u8tmp &= ~mask;
- val |= u8tmp;
- }
-
- return m88ds3103_wr_regs(priv, reg, &val, 1);
-}
-
-/* read single register with mask */
-static int m88ds3103_rd_reg_mask(struct m88ds3103_priv *priv,
- u8 reg, u8 *val, u8 mask)
-{
- int ret, i;
- u8 u8tmp;
-
- ret = m88ds3103_rd_regs(priv, reg, &u8tmp, 1);
- if (ret)
- return ret;
-
- u8tmp &= mask;
-
- /* find position of the first bit */
- for (i = 0; i < 8; i++) {
- if ((mask >> i) & 0x01)
- break;
- }
- *val = u8tmp >> i;
-
- return 0;
-}
-
/* write reg val table using reg addr auto increment */
-static int m88ds3103_wr_reg_val_tab(struct m88ds3103_priv *priv,
+static int m88ds3103_wr_reg_val_tab(struct m88ds3103_dev *dev,
const struct m88ds3103_reg_val *tab, int tab_len)
{
+ struct i2c_client *client = dev->client;
int ret, i, j;
u8 buf[83];
- dev_dbg(&priv->i2c->dev, "%s: tab_len=%d\n", __func__, tab_len);
+ dev_dbg(&client->dev, "tab_len=%d\n", tab_len);
if (tab_len > 86) {
ret = -EINVAL;
@@ -171,8 +37,8 @@ static int m88ds3103_wr_reg_val_tab(struct m88ds3103_priv *priv,
buf[j] = tab[i].val;
if (i == tab_len - 1 || tab[i].reg != tab[i + 1].reg - 1 ||
- !((j + 1) % (priv->cfg->i2c_wr_max - 1))) {
- ret = m88ds3103_wr_regs(priv, tab[i].reg - j, buf, j + 1);
+ !((j + 1) % (dev->cfg->i2c_wr_max - 1))) {
+ ret = regmap_bulk_write(dev->regmap, tab[i].reg - j, buf, j + 1);
if (ret)
goto err;
@@ -182,66 +48,238 @@ static int m88ds3103_wr_reg_val_tab(struct m88ds3103_priv *priv,
return 0;
err:
- dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+ dev_dbg(&client->dev, "failed=%d\n", ret);
+ return ret;
+}
+
+/*
+ * Get the demodulator AGC PWM voltage setting supplied to the tuner.
+ */
+int m88ds3103_get_agc_pwm(struct dvb_frontend *fe, u8 *_agc_pwm)
+{
+ struct m88ds3103_dev *dev = fe->demodulator_priv;
+ unsigned tmp;
+ int ret;
+
+ ret = regmap_read(dev->regmap, 0x3f, &tmp);
+ if (ret == 0)
+ *_agc_pwm = tmp;
return ret;
}
+EXPORT_SYMBOL(m88ds3103_get_agc_pwm);
-static int m88ds3103_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int m88ds3103_read_status(struct dvb_frontend *fe,
+ enum fe_status *status)
{
- struct m88ds3103_priv *priv = fe->demodulator_priv;
+ struct m88ds3103_dev *dev = fe->demodulator_priv;
+ struct i2c_client *client = dev->client;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- int ret;
- u8 u8tmp;
+ int ret, i, itmp;
+ unsigned int utmp;
+ u8 buf[3];
*status = 0;
- if (!priv->warm) {
+ if (!dev->warm) {
ret = -EAGAIN;
goto err;
}
switch (c->delivery_system) {
case SYS_DVBS:
- ret = m88ds3103_rd_reg_mask(priv, 0xd1, &u8tmp, 0x07);
+ ret = regmap_read(dev->regmap, 0xd1, &utmp);
if (ret)
goto err;
- if (u8tmp == 0x07)
+ if ((utmp & 0x07) == 0x07)
*status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
FE_HAS_VITERBI | FE_HAS_SYNC |
FE_HAS_LOCK;
break;
case SYS_DVBS2:
- ret = m88ds3103_rd_reg_mask(priv, 0x0d, &u8tmp, 0x8f);
+ ret = regmap_read(dev->regmap, 0x0d, &utmp);
if (ret)
goto err;
- if (u8tmp == 0x8f)
+ if ((utmp & 0x8f) == 0x8f)
*status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
FE_HAS_VITERBI | FE_HAS_SYNC |
FE_HAS_LOCK;
break;
default:
- dev_dbg(&priv->i2c->dev, "%s: invalid delivery_system\n",
- __func__);
+ dev_dbg(&client->dev, "invalid delivery_system\n");
ret = -EINVAL;
goto err;
}
- priv->fe_status = *status;
+ dev->fe_status = *status;
+ dev_dbg(&client->dev, "lock=%02x status=%02x\n", utmp, *status);
+
+ /* CNR */
+ if (dev->fe_status & FE_HAS_VITERBI) {
+ unsigned int cnr, noise, signal, noise_tot, signal_tot;
+
+ cnr = 0;
+ /* more iterations for more accurate estimation */
+ #define M88DS3103_SNR_ITERATIONS 3
+
+ switch (c->delivery_system) {
+ case SYS_DVBS:
+ itmp = 0;
+
+ for (i = 0; i < M88DS3103_SNR_ITERATIONS; i++) {
+ ret = regmap_read(dev->regmap, 0xff, &utmp);
+ if (ret)
+ goto err;
+
+ itmp += utmp;
+ }
+
+ /* use of single register limits max value to 15 dB */
+ /* SNR(X) dB = 10 * ln(X) / ln(10) dB */
+ itmp = DIV_ROUND_CLOSEST(itmp, 8 * M88DS3103_SNR_ITERATIONS);
+ if (itmp)
+ cnr = div_u64((u64) 10000 * intlog2(itmp), intlog2(10));
+ break;
+ case SYS_DVBS2:
+ noise_tot = 0;
+ signal_tot = 0;
+
+ for (i = 0; i < M88DS3103_SNR_ITERATIONS; i++) {
+ ret = regmap_bulk_read(dev->regmap, 0x8c, buf, 3);
+ if (ret)
+ goto err;
+
+ noise = buf[1] << 6; /* [13:6] */
+ noise |= buf[0] & 0x3f; /* [5:0] */
+ noise >>= 2;
+ signal = buf[2] * buf[2];
+ signal >>= 1;
+
+ noise_tot += noise;
+ signal_tot += signal;
+ }
+
+ noise = noise_tot / M88DS3103_SNR_ITERATIONS;
+ signal = signal_tot / M88DS3103_SNR_ITERATIONS;
+
+ /* SNR(X) dB = 10 * log10(X) dB */
+ if (signal > noise) {
+ itmp = signal / noise;
+ cnr = div_u64((u64) 10000 * intlog10(itmp), (1 << 24));
+ }
+ break;
+ default:
+ dev_dbg(&client->dev, "invalid delivery_system\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (cnr) {
+ c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+ c->cnr.stat[0].svalue = cnr;
+ } else {
+ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ }
+ } else {
+ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ }
+
+ /* BER */
+ if (dev->fe_status & FE_HAS_LOCK) {
+ unsigned int utmp, post_bit_error, post_bit_count;
- dev_dbg(&priv->i2c->dev, "%s: lock=%02x status=%02x\n",
- __func__, u8tmp, *status);
+ switch (c->delivery_system) {
+ case SYS_DVBS:
+ ret = regmap_write(dev->regmap, 0xf9, 0x04);
+ if (ret)
+ goto err;
+
+ ret = regmap_read(dev->regmap, 0xf8, &utmp);
+ if (ret)
+ goto err;
+
+ /* measurement ready? */
+ if (!(utmp & 0x10)) {
+ ret = regmap_bulk_read(dev->regmap, 0xf6, buf, 2);
+ if (ret)
+ goto err;
+
+ post_bit_error = buf[1] << 8 | buf[0] << 0;
+ post_bit_count = 0x800000;
+ dev->post_bit_error += post_bit_error;
+ dev->post_bit_count += post_bit_count;
+ dev->dvbv3_ber = post_bit_error;
+
+ /* restart measurement */
+ utmp |= 0x10;
+ ret = regmap_write(dev->regmap, 0xf8, utmp);
+ if (ret)
+ goto err;
+ }
+ break;
+ case SYS_DVBS2:
+ ret = regmap_bulk_read(dev->regmap, 0xd5, buf, 3);
+ if (ret)
+ goto err;
+
+ utmp = buf[2] << 16 | buf[1] << 8 | buf[0] << 0;
+
+ /* enough data? */
+ if (utmp > 4000) {
+ ret = regmap_bulk_read(dev->regmap, 0xf7, buf, 2);
+ if (ret)
+ goto err;
+
+ post_bit_error = buf[1] << 8 | buf[0] << 0;
+ post_bit_count = 32 * utmp; /* TODO: FEC */
+ dev->post_bit_error += post_bit_error;
+ dev->post_bit_count += post_bit_count;
+ dev->dvbv3_ber = post_bit_error;
+
+ /* restart measurement */
+ ret = regmap_write(dev->regmap, 0xd1, 0x01);
+ if (ret)
+ goto err;
+
+ ret = regmap_write(dev->regmap, 0xf9, 0x01);
+ if (ret)
+ goto err;
+
+ ret = regmap_write(dev->regmap, 0xf9, 0x00);
+ if (ret)
+ goto err;
+
+ ret = regmap_write(dev->regmap, 0xd1, 0x00);
+ if (ret)
+ goto err;
+ }
+ break;
+ default:
+ dev_dbg(&client->dev, "invalid delivery_system\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+ c->post_bit_error.stat[0].uvalue = dev->post_bit_error;
+ c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+ c->post_bit_count.stat[0].uvalue = dev->post_bit_count;
+ } else {
+ c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ }
return 0;
err:
- dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+ dev_dbg(&client->dev, "failed=%d\n", ret);
return ret;
}
static int m88ds3103_set_frontend(struct dvb_frontend *fe)
{
- struct m88ds3103_priv *priv = fe->demodulator_priv;
+ struct m88ds3103_dev *dev = fe->demodulator_priv;
+ struct i2c_client *client = dev->client;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret, len;
const struct m88ds3103_reg_val *init;
@@ -251,29 +289,28 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
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,
- c->modulation, c->frequency, c->symbol_rate,
- c->inversion, c->pilot, c->rolloff);
+ dev_dbg(&client->dev,
+ "delivery_system=%d modulation=%d frequency=%u symbol_rate=%d inversion=%d pilot=%d rolloff=%d\n",
+ c->delivery_system, c->modulation, c->frequency, c->symbol_rate,
+ c->inversion, c->pilot, c->rolloff);
- if (!priv->warm) {
+ if (!dev->warm) {
ret = -EAGAIN;
goto err;
}
/* reset */
- ret = m88ds3103_wr_reg(priv, 0x07, 0x80);
+ ret = regmap_write(dev->regmap, 0x07, 0x80);
if (ret)
goto err;
- ret = m88ds3103_wr_reg(priv, 0x07, 0x00);
+ ret = regmap_write(dev->regmap, 0x07, 0x00);
if (ret)
goto err;
/* Disable demod clock path */
- if (priv->chip_id == M88RS6000_CHIP_ID) {
- ret = m88ds3103_wr_reg(priv, 0x06, 0xe0);
+ if (dev->chip_id == M88RS6000_CHIP_ID) {
+ ret = regmap_write(dev->regmap, 0x06, 0xe0);
if (ret)
goto err;
}
@@ -299,11 +336,11 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
}
/* select M88RS6000 demod main mclk and ts mclk from tuner die. */
- if (priv->chip_id == M88RS6000_CHIP_ID) {
+ if (dev->chip_id == M88RS6000_CHIP_ID) {
if (c->symbol_rate > 45010000)
- priv->mclk_khz = 110250;
+ dev->mclk_khz = 110250;
else
- priv->mclk_khz = 96000;
+ dev->mclk_khz = 96000;
if (c->delivery_system == SYS_DVBS)
target_mclk = 96000;
@@ -311,18 +348,18 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
target_mclk = 144000;
/* Enable demod clock path */
- ret = m88ds3103_wr_reg(priv, 0x06, 0x00);
+ ret = regmap_write(dev->regmap, 0x06, 0x00);
if (ret)
goto err;
usleep_range(10000, 20000);
} else {
/* set M88DS3103 mclk and ts mclk. */
- priv->mclk_khz = 96000;
+ dev->mclk_khz = 96000;
- switch (priv->cfg->ts_mode) {
+ switch (dev->cfg->ts_mode) {
case M88DS3103_TS_SERIAL:
case M88DS3103_TS_SERIAL_D7:
- target_mclk = priv->cfg->ts_clk;
+ target_mclk = dev->cfg->ts_clk;
break;
case M88DS3103_TS_PARALLEL:
case M88DS3103_TS_CI:
@@ -338,8 +375,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
}
break;
default:
- dev_dbg(&priv->i2c->dev, "%s: invalid ts_mode\n",
- __func__);
+ dev_dbg(&client->dev, "invalid ts_mode\n");
ret = -EINVAL;
goto err;
}
@@ -358,25 +394,25 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
u8tmp2 = 0x00; /* 0b00 */
break;
}
- ret = m88ds3103_wr_reg_mask(priv, 0x22, u8tmp1 << 6, 0xc0);
+ ret = regmap_update_bits(dev->regmap, 0x22, 0xc0, u8tmp1 << 6);
if (ret)
goto err;
- ret = m88ds3103_wr_reg_mask(priv, 0x24, u8tmp2 << 6, 0xc0);
+ ret = regmap_update_bits(dev->regmap, 0x24, 0xc0, u8tmp2 << 6);
if (ret)
goto err;
}
- ret = m88ds3103_wr_reg(priv, 0xb2, 0x01);
+ ret = regmap_write(dev->regmap, 0xb2, 0x01);
if (ret)
goto err;
- ret = m88ds3103_wr_reg(priv, 0x00, 0x01);
+ ret = regmap_write(dev->regmap, 0x00, 0x01);
if (ret)
goto err;
switch (c->delivery_system) {
case SYS_DVBS:
- if (priv->chip_id == M88RS6000_CHIP_ID) {
+ if (dev->chip_id == M88RS6000_CHIP_ID) {
len = ARRAY_SIZE(m88rs6000_dvbs_init_reg_vals);
init = m88rs6000_dvbs_init_reg_vals;
} else {
@@ -385,7 +421,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
}
break;
case SYS_DVBS2:
- if (priv->chip_id == M88RS6000_CHIP_ID) {
+ if (dev->chip_id == M88RS6000_CHIP_ID) {
len = ARRAY_SIZE(m88rs6000_dvbs2_init_reg_vals);
init = m88rs6000_dvbs2_init_reg_vals;
} else {
@@ -394,44 +430,43 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
}
break;
default:
- dev_dbg(&priv->i2c->dev, "%s: invalid delivery_system\n",
- __func__);
+ dev_dbg(&client->dev, "invalid delivery_system\n");
ret = -EINVAL;
goto err;
}
/* program init table */
- if (c->delivery_system != priv->delivery_system) {
- ret = m88ds3103_wr_reg_val_tab(priv, init, len);
+ if (c->delivery_system != dev->delivery_system) {
+ ret = m88ds3103_wr_reg_val_tab(dev, init, len);
if (ret)
goto err;
}
- if (priv->chip_id == M88RS6000_CHIP_ID) {
+ if (dev->chip_id == M88RS6000_CHIP_ID) {
if ((c->delivery_system == SYS_DVBS2)
&& ((c->symbol_rate / 1000) <= 5000)) {
- ret = m88ds3103_wr_reg(priv, 0xc0, 0x04);
+ ret = regmap_write(dev->regmap, 0xc0, 0x04);
if (ret)
goto err;
buf[0] = 0x09;
buf[1] = 0x22;
buf[2] = 0x88;
- ret = m88ds3103_wr_regs(priv, 0x8a, buf, 3);
+ ret = regmap_bulk_write(dev->regmap, 0x8a, buf, 3);
if (ret)
goto err;
}
- ret = m88ds3103_wr_reg_mask(priv, 0x9d, 0x08, 0x08);
+ ret = regmap_update_bits(dev->regmap, 0x9d, 0x08, 0x08);
if (ret)
goto err;
- ret = m88ds3103_wr_reg(priv, 0xf1, 0x01);
+ ret = regmap_write(dev->regmap, 0xf1, 0x01);
if (ret)
goto err;
- ret = m88ds3103_wr_reg_mask(priv, 0x30, 0x80, 0x80);
+ ret = regmap_update_bits(dev->regmap, 0x30, 0x80, 0x80);
if (ret)
goto err;
}
- switch (priv->cfg->ts_mode) {
+ switch (dev->cfg->ts_mode) {
case M88DS3103_TS_SERIAL:
u8tmp1 = 0x00;
u8tmp = 0x06;
@@ -447,39 +482,39 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
u8tmp = 0x03;
break;
default:
- dev_dbg(&priv->i2c->dev, "%s: invalid ts_mode\n", __func__);
+ dev_dbg(&client->dev, "invalid ts_mode\n");
ret = -EINVAL;
goto err;
}
- if (priv->cfg->ts_clk_pol)
+ if (dev->cfg->ts_clk_pol)
u8tmp |= 0x40;
/* TS mode */
- ret = m88ds3103_wr_reg(priv, 0xfd, u8tmp);
+ ret = regmap_write(dev->regmap, 0xfd, u8tmp);
if (ret)
goto err;
- switch (priv->cfg->ts_mode) {
+ switch (dev->cfg->ts_mode) {
case M88DS3103_TS_SERIAL:
case M88DS3103_TS_SERIAL_D7:
- ret = m88ds3103_wr_reg_mask(priv, 0x29, u8tmp1, 0x20);
+ ret = regmap_update_bits(dev->regmap, 0x29, 0x20, u8tmp1);
if (ret)
goto err;
u8tmp1 = 0;
u8tmp2 = 0;
break;
default:
- if (priv->cfg->ts_clk) {
- divide_ratio = DIV_ROUND_UP(target_mclk, priv->cfg->ts_clk);
+ if (dev->cfg->ts_clk) {
+ divide_ratio = DIV_ROUND_UP(target_mclk, dev->cfg->ts_clk);
u8tmp1 = divide_ratio / 2;
u8tmp2 = DIV_ROUND_UP(divide_ratio, 2);
}
}
- dev_dbg(&priv->i2c->dev,
- "%s: target_mclk=%d ts_clk=%d divide_ratio=%d\n",
- __func__, target_mclk, priv->cfg->ts_clk, divide_ratio);
+ dev_dbg(&client->dev,
+ "target_mclk=%d ts_clk=%d divide_ratio=%d\n",
+ target_mclk, dev->cfg->ts_clk, divide_ratio);
u8tmp1--;
u8tmp2--;
@@ -488,17 +523,17 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
/* u8tmp2[5:0] => ea[5:0] */
u8tmp2 &= 0x3f;
- ret = m88ds3103_rd_reg(priv, 0xfe, &u8tmp);
+ ret = regmap_bulk_read(dev->regmap, 0xfe, &u8tmp, 1);
if (ret)
goto err;
u8tmp = ((u8tmp & 0xf0) << 0) | u8tmp1 >> 2;
- ret = m88ds3103_wr_reg(priv, 0xfe, u8tmp);
+ ret = regmap_write(dev->regmap, 0xfe, u8tmp);
if (ret)
goto err;
u8tmp = ((u8tmp1 & 0x03) << 6) | u8tmp2 >> 0;
- ret = m88ds3103_wr_reg(priv, 0xea, u8tmp);
+ ret = regmap_write(dev->regmap, 0xea, u8tmp);
if (ret)
goto err;
@@ -509,250 +544,254 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
else
u8tmp = 0x06;
- ret = m88ds3103_wr_reg(priv, 0xc3, 0x08);
+ ret = regmap_write(dev->regmap, 0xc3, 0x08);
if (ret)
goto err;
- ret = m88ds3103_wr_reg(priv, 0xc8, u8tmp);
+ ret = regmap_write(dev->regmap, 0xc8, u8tmp);
if (ret)
goto err;
- ret = m88ds3103_wr_reg(priv, 0xc4, 0x08);
+ ret = regmap_write(dev->regmap, 0xc4, 0x08);
if (ret)
goto err;
- ret = m88ds3103_wr_reg(priv, 0xc7, 0x00);
+ ret = regmap_write(dev->regmap, 0xc7, 0x00);
if (ret)
goto err;
- u16tmp = DIV_ROUND_CLOSEST((c->symbol_rate / 1000) << 15, priv->mclk_khz / 2);
+ u16tmp = DIV_ROUND_CLOSEST((c->symbol_rate / 1000) << 15, dev->mclk_khz / 2);
buf[0] = (u16tmp >> 0) & 0xff;
buf[1] = (u16tmp >> 8) & 0xff;
- ret = m88ds3103_wr_regs(priv, 0x61, buf, 2);
+ ret = regmap_bulk_write(dev->regmap, 0x61, buf, 2);
if (ret)
goto err;
- ret = m88ds3103_wr_reg_mask(priv, 0x4d, priv->cfg->spec_inv << 1, 0x02);
+ ret = regmap_update_bits(dev->regmap, 0x4d, 0x02, dev->cfg->spec_inv << 1);
if (ret)
goto err;
- ret = m88ds3103_wr_reg_mask(priv, 0x30, priv->cfg->agc_inv << 4, 0x10);
+ ret = regmap_update_bits(dev->regmap, 0x30, 0x10, dev->cfg->agc_inv << 4);
if (ret)
goto err;
- ret = m88ds3103_wr_reg(priv, 0x33, priv->cfg->agc);
+ ret = regmap_write(dev->regmap, 0x33, dev->cfg->agc);
if (ret)
goto err;
- dev_dbg(&priv->i2c->dev, "%s: carrier offset=%d\n", __func__,
- (tuner_frequency - c->frequency));
+ dev_dbg(&client->dev, "carrier offset=%d\n",
+ (tuner_frequency - c->frequency));
s32tmp = 0x10000 * (tuner_frequency - c->frequency);
- s32tmp = DIV_ROUND_CLOSEST(s32tmp, priv->mclk_khz);
+ s32tmp = DIV_ROUND_CLOSEST(s32tmp, dev->mclk_khz);
if (s32tmp < 0)
s32tmp += 0x10000;
buf[0] = (s32tmp >> 0) & 0xff;
buf[1] = (s32tmp >> 8) & 0xff;
- ret = m88ds3103_wr_regs(priv, 0x5e, buf, 2);
+ ret = regmap_bulk_write(dev->regmap, 0x5e, buf, 2);
if (ret)
goto err;
- ret = m88ds3103_wr_reg(priv, 0x00, 0x00);
+ ret = regmap_write(dev->regmap, 0x00, 0x00);
if (ret)
goto err;
- ret = m88ds3103_wr_reg(priv, 0xb2, 0x00);
+ ret = regmap_write(dev->regmap, 0xb2, 0x00);
if (ret)
goto err;
- priv->delivery_system = c->delivery_system;
+ dev->delivery_system = c->delivery_system;
return 0;
err:
- dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+ dev_dbg(&client->dev, "failed=%d\n", ret);
return ret;
}
static int m88ds3103_init(struct dvb_frontend *fe)
{
- struct m88ds3103_priv *priv = fe->demodulator_priv;
+ struct m88ds3103_dev *dev = fe->demodulator_priv;
+ struct i2c_client *client = dev->client;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret, len, remaining;
+ unsigned int utmp;
const struct firmware *fw = NULL;
u8 *fw_file;
- u8 u8tmp;
- dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+ dev_dbg(&client->dev, "\n");
/* set cold state by default */
- priv->warm = false;
+ dev->warm = false;
/* wake up device from sleep */
- ret = m88ds3103_wr_reg_mask(priv, 0x08, 0x01, 0x01);
+ ret = regmap_update_bits(dev->regmap, 0x08, 0x01, 0x01);
if (ret)
goto err;
-
- ret = m88ds3103_wr_reg_mask(priv, 0x04, 0x00, 0x01);
+ ret = regmap_update_bits(dev->regmap, 0x04, 0x01, 0x00);
if (ret)
goto err;
-
- ret = m88ds3103_wr_reg_mask(priv, 0x23, 0x00, 0x10);
+ ret = regmap_update_bits(dev->regmap, 0x23, 0x10, 0x00);
if (ret)
goto err;
/* firmware status */
- ret = m88ds3103_rd_reg(priv, 0xb9, &u8tmp);
+ ret = regmap_read(dev->regmap, 0xb9, &utmp);
if (ret)
goto err;
- dev_dbg(&priv->i2c->dev, "%s: firmware=%02x\n", __func__, u8tmp);
+ dev_dbg(&client->dev, "firmware=%02x\n", utmp);
- if (u8tmp)
+ if (utmp)
goto skip_fw_download;
/* global reset, global diseqc reset, golbal fec reset */
- ret = m88ds3103_wr_reg(priv, 0x07, 0xe0);
+ ret = regmap_write(dev->regmap, 0x07, 0xe0);
if (ret)
goto err;
-
- ret = m88ds3103_wr_reg(priv, 0x07, 0x00);
+ ret = regmap_write(dev->regmap, 0x07, 0x00);
if (ret)
goto err;
/* cold state - try to download firmware */
- dev_info(&priv->i2c->dev, "%s: found a '%s' in cold state\n",
- KBUILD_MODNAME, m88ds3103_ops.info.name);
+ dev_info(&client->dev, "found a '%s' in cold state\n",
+ m88ds3103_ops.info.name);
- if (priv->chip_id == M88RS6000_CHIP_ID)
+ if (dev->chip_id == M88RS6000_CHIP_ID)
fw_file = M88RS6000_FIRMWARE;
else
fw_file = M88DS3103_FIRMWARE;
/* request the firmware, this will block and timeout */
- ret = reject_firmware(&fw, fw_file, priv->i2c->dev.parent);
+ ret = reject_firmware(&fw, fw_file, &client->dev);
if (ret) {
- dev_err(&priv->i2c->dev, "%s: firmware file '%s' not found\n",
- KBUILD_MODNAME, fw_file);
+ dev_err(&client->dev, "firmare file '%s' not found\n", fw_file);
goto err;
}
- dev_info(&priv->i2c->dev, "%s: downloading firmware from file '%s'\n",
- KBUILD_MODNAME, fw_file);
+ dev_info(&client->dev, "downloading firmware from file '%s'\n",
+ fw_file);
- ret = m88ds3103_wr_reg(priv, 0xb2, 0x01);
+ ret = regmap_write(dev->regmap, 0xb2, 0x01);
if (ret)
goto error_fw_release;
for (remaining = fw->size; remaining > 0;
- remaining -= (priv->cfg->i2c_wr_max - 1)) {
+ remaining -= (dev->cfg->i2c_wr_max - 1)) {
len = remaining;
- if (len > (priv->cfg->i2c_wr_max - 1))
- len = (priv->cfg->i2c_wr_max - 1);
+ if (len > (dev->cfg->i2c_wr_max - 1))
+ len = (dev->cfg->i2c_wr_max - 1);
- ret = m88ds3103_wr_regs(priv, 0xb0,
+ ret = regmap_bulk_write(dev->regmap, 0xb0,
&fw->data[fw->size - remaining], len);
if (ret) {
- dev_err(&priv->i2c->dev,
- "%s: firmware download failed=%d\n",
- KBUILD_MODNAME, ret);
+ dev_err(&client->dev, "firmware download failed=%d\n",
+ ret);
goto error_fw_release;
}
}
- ret = m88ds3103_wr_reg(priv, 0xb2, 0x00);
+ ret = regmap_write(dev->regmap, 0xb2, 0x00);
if (ret)
goto error_fw_release;
release_firmware(fw);
fw = NULL;
- ret = m88ds3103_rd_reg(priv, 0xb9, &u8tmp);
+ ret = regmap_read(dev->regmap, 0xb9, &utmp);
if (ret)
goto err;
- if (!u8tmp) {
- dev_info(&priv->i2c->dev, "%s: firmware did not run\n",
- KBUILD_MODNAME);
+ if (!utmp) {
+ dev_info(&client->dev, "firmware did not run\n");
ret = -EFAULT;
goto err;
}
- dev_info(&priv->i2c->dev, "%s: found a '%s' in warm state\n",
- KBUILD_MODNAME, m88ds3103_ops.info.name);
- dev_info(&priv->i2c->dev, "%s: firmware version %X.%X\n",
- KBUILD_MODNAME, (u8tmp >> 4) & 0xf, (u8tmp >> 0 & 0xf));
+ dev_info(&client->dev, "found a '%s' in warm state\n",
+ m88ds3103_ops.info.name);
+ dev_info(&client->dev, "firmware version: %X.%X\n",
+ (utmp >> 4) & 0xf, (utmp >> 0 & 0xf));
skip_fw_download:
/* warm state */
- priv->warm = true;
+ dev->warm = true;
- return 0;
+ /* init stats here in order signal app which stats are supported */
+ c->cnr.len = 1;
+ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->post_bit_error.len = 1;
+ c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->post_bit_count.len = 1;
+ c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ return 0;
error_fw_release:
release_firmware(fw);
err:
- dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+ dev_dbg(&client->dev, "failed=%d\n", ret);
return ret;
}
static int m88ds3103_sleep(struct dvb_frontend *fe)
{
- struct m88ds3103_priv *priv = fe->demodulator_priv;
+ struct m88ds3103_dev *dev = fe->demodulator_priv;
+ struct i2c_client *client = dev->client;
int ret;
- u8 u8tmp;
+ unsigned int utmp;
- dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+ dev_dbg(&client->dev, "\n");
- priv->delivery_system = SYS_UNDEFINED;
+ dev->fe_status = 0;
+ dev->delivery_system = SYS_UNDEFINED;
/* TS Hi-Z */
- if (priv->chip_id == M88RS6000_CHIP_ID)
- u8tmp = 0x29;
+ if (dev->chip_id == M88RS6000_CHIP_ID)
+ utmp = 0x29;
else
- u8tmp = 0x27;
- ret = m88ds3103_wr_reg_mask(priv, u8tmp, 0x00, 0x01);
+ utmp = 0x27;
+ ret = regmap_update_bits(dev->regmap, utmp, 0x01, 0x00);
if (ret)
goto err;
/* sleep */
- ret = m88ds3103_wr_reg_mask(priv, 0x08, 0x00, 0x01);
+ ret = regmap_update_bits(dev->regmap, 0x08, 0x01, 0x00);
if (ret)
goto err;
-
- ret = m88ds3103_wr_reg_mask(priv, 0x04, 0x01, 0x01);
+ ret = regmap_update_bits(dev->regmap, 0x04, 0x01, 0x01);
if (ret)
goto err;
-
- ret = m88ds3103_wr_reg_mask(priv, 0x23, 0x10, 0x10);
+ ret = regmap_update_bits(dev->regmap, 0x23, 0x10, 0x10);
if (ret)
goto err;
return 0;
err:
- dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+ dev_dbg(&client->dev, "failed=%d\n", ret);
return ret;
}
static int m88ds3103_get_frontend(struct dvb_frontend *fe)
{
- struct m88ds3103_priv *priv = fe->demodulator_priv;
+ struct m88ds3103_dev *dev = fe->demodulator_priv;
+ struct i2c_client *client = dev->client;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret;
u8 buf[3];
- dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+ dev_dbg(&client->dev, "\n");
- if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
- ret = -EAGAIN;
+ if (!dev->warm || !(dev->fe_status & FE_HAS_LOCK)) {
+ ret = 0;
goto err;
}
switch (c->delivery_system) {
case SYS_DVBS:
- ret = m88ds3103_rd_reg(priv, 0xe0, &buf[0]);
+ ret = regmap_bulk_read(dev->regmap, 0xe0, &buf[0], 1);
if (ret)
goto err;
- ret = m88ds3103_rd_reg(priv, 0xe6, &buf[1]);
+ ret = regmap_bulk_read(dev->regmap, 0xe6, &buf[1], 1);
if (ret)
goto err;
@@ -782,23 +821,22 @@ static int m88ds3103_get_frontend(struct dvb_frontend *fe)
c->fec_inner = FEC_1_2;
break;
default:
- dev_dbg(&priv->i2c->dev, "%s: invalid fec_inner\n",
- __func__);
+ dev_dbg(&client->dev, "invalid fec_inner\n");
}
c->modulation = QPSK;
break;
case SYS_DVBS2:
- ret = m88ds3103_rd_reg(priv, 0x7e, &buf[0]);
+ ret = regmap_bulk_read(dev->regmap, 0x7e, &buf[0], 1);
if (ret)
goto err;
- ret = m88ds3103_rd_reg(priv, 0x89, &buf[1]);
+ ret = regmap_bulk_read(dev->regmap, 0x89, &buf[1], 1);
if (ret)
goto err;
- ret = m88ds3103_rd_reg(priv, 0xf2, &buf[2]);
+ ret = regmap_bulk_read(dev->regmap, 0xf2, &buf[2], 1);
if (ret)
goto err;
@@ -831,8 +869,7 @@ static int m88ds3103_get_frontend(struct dvb_frontend *fe)
c->fec_inner = FEC_9_10;
break;
default:
- dev_dbg(&priv->i2c->dev, "%s: invalid fec_inner\n",
- __func__);
+ dev_dbg(&client->dev, "invalid fec_inner\n");
}
switch ((buf[0] >> 5) & 0x01) {
@@ -858,8 +895,7 @@ static int m88ds3103_get_frontend(struct dvb_frontend *fe)
c->modulation = APSK_32;
break;
default:
- dev_dbg(&priv->i2c->dev, "%s: invalid modulation\n",
- __func__);
+ dev_dbg(&client->dev, "invalid modulation\n");
}
switch ((buf[1] >> 7) & 0x01) {
@@ -882,201 +918,60 @@ static int m88ds3103_get_frontend(struct dvb_frontend *fe)
c->rolloff = ROLLOFF_20;
break;
default:
- dev_dbg(&priv->i2c->dev, "%s: invalid rolloff\n",
- __func__);
+ dev_dbg(&client->dev, "invalid rolloff\n");
}
break;
default:
- dev_dbg(&priv->i2c->dev, "%s: invalid delivery_system\n",
- __func__);
+ dev_dbg(&client->dev, "invalid delivery_system\n");
ret = -EINVAL;
goto err;
}
- ret = m88ds3103_rd_regs(priv, 0x6d, buf, 2);
+ ret = regmap_bulk_read(dev->regmap, 0x6d, buf, 2);
if (ret)
goto err;
c->symbol_rate = 1ull * ((buf[1] << 8) | (buf[0] << 0)) *
- priv->mclk_khz * 1000 / 0x10000;
+ dev->mclk_khz * 1000 / 0x10000;
return 0;
err:
- dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+ dev_dbg(&client->dev, "failed=%d\n", ret);
return ret;
}
static int m88ds3103_read_snr(struct dvb_frontend *fe, u16 *snr)
{
- struct m88ds3103_priv *priv = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- int ret, i, tmp;
- 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 */
-
- /* more iterations for more accurate estimation */
- #define M88DS3103_SNR_ITERATIONS 3
-
- switch (c->delivery_system) {
- case SYS_DVBS:
- tmp = 0;
- for (i = 0; i < M88DS3103_SNR_ITERATIONS; i++) {
- ret = m88ds3103_rd_reg(priv, 0xff, &buf[0]);
- if (ret)
- goto err;
-
- tmp += buf[0];
- }
-
- /* use of one register limits max value to 15 dB */
- /* SNR(X) dB = 10 * ln(X) / ln(10) dB */
- tmp = DIV_ROUND_CLOSEST(tmp, 8 * M88DS3103_SNR_ITERATIONS);
- if (tmp)
- *snr = div_u64((u64) 100 * intlog2(tmp), intlog2(10));
- else
- *snr = 0;
- break;
- case SYS_DVBS2:
- noise_tot = 0;
- signal_tot = 0;
-
- for (i = 0; i < M88DS3103_SNR_ITERATIONS; i++) {
- ret = m88ds3103_rd_regs(priv, 0x8c, buf, 3);
- if (ret)
- goto err;
-
- noise = buf[1] << 6; /* [13:6] */
- noise |= buf[0] & 0x3f; /* [5:0] */
- noise >>= 2;
- signal = buf[2] * buf[2];
- signal >>= 1;
-
- noise_tot += noise;
- signal_tot += signal;
- }
-
- noise = noise_tot / M88DS3103_SNR_ITERATIONS;
- signal = signal_tot / M88DS3103_SNR_ITERATIONS;
-
- /* SNR(X) dB = 10 * log10(X) dB */
- if (signal > noise) {
- tmp = signal / noise;
- *snr = div_u64((u64) 100 * intlog10(tmp), (1 << 24));
- } else {
- *snr = 0;
- }
- break;
- default:
- dev_dbg(&priv->i2c->dev, "%s: invalid delivery_system\n",
- __func__);
- ret = -EINVAL;
- goto err;
- }
+ if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL)
+ *snr = div_s64(c->cnr.stat[0].svalue, 100);
+ else
+ *snr = 0;
return 0;
-err:
- dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
- return ret;
}
static int m88ds3103_read_ber(struct dvb_frontend *fe, u32 *ber)
{
- struct m88ds3103_priv *priv = fe->demodulator_priv;
- struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- int ret;
- unsigned int utmp;
- u8 buf[3], u8tmp;
-
- dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
-
- switch (c->delivery_system) {
- case SYS_DVBS:
- ret = m88ds3103_wr_reg(priv, 0xf9, 0x04);
- if (ret)
- goto err;
-
- ret = m88ds3103_rd_reg(priv, 0xf8, &u8tmp);
- if (ret)
- goto err;
-
- if (!(u8tmp & 0x10)) {
- u8tmp |= 0x10;
-
- ret = m88ds3103_rd_regs(priv, 0xf6, buf, 2);
- if (ret)
- goto err;
-
- priv->ber = (buf[1] << 8) | (buf[0] << 0);
-
- /* restart counters */
- ret = m88ds3103_wr_reg(priv, 0xf8, u8tmp);
- if (ret)
- goto err;
- }
- break;
- case SYS_DVBS2:
- ret = m88ds3103_rd_regs(priv, 0xd5, buf, 3);
- if (ret)
- goto err;
-
- utmp = (buf[2] << 16) | (buf[1] << 8) | (buf[0] << 0);
-
- if (utmp > 3000) {
- ret = m88ds3103_rd_regs(priv, 0xf7, buf, 2);
- if (ret)
- goto err;
-
- priv->ber = (buf[1] << 8) | (buf[0] << 0);
-
- /* restart counters */
- ret = m88ds3103_wr_reg(priv, 0xd1, 0x01);
- if (ret)
- goto err;
-
- ret = m88ds3103_wr_reg(priv, 0xf9, 0x01);
- if (ret)
- goto err;
-
- ret = m88ds3103_wr_reg(priv, 0xf9, 0x00);
- if (ret)
- goto err;
-
- ret = m88ds3103_wr_reg(priv, 0xd1, 0x00);
- if (ret)
- goto err;
- }
- break;
- default:
- dev_dbg(&priv->i2c->dev, "%s: invalid delivery_system\n",
- __func__);
- ret = -EINVAL;
- goto err;
- }
+ struct m88ds3103_dev *dev = fe->demodulator_priv;
- *ber = priv->ber;
+ *ber = dev->dvbv3_ber;
return 0;
-err:
- dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
- return ret;
}
static int m88ds3103_set_tone(struct dvb_frontend *fe,
- fe_sec_tone_mode_t fe_sec_tone_mode)
+ enum fe_sec_tone_mode fe_sec_tone_mode)
{
- struct m88ds3103_priv *priv = fe->demodulator_priv;
+ struct m88ds3103_dev *dev = fe->demodulator_priv;
+ struct i2c_client *client = dev->client;
int ret;
- u8 u8tmp, tone, reg_a1_mask;
+ unsigned int utmp, tone, reg_a1_mask;
- dev_dbg(&priv->i2c->dev, "%s: fe_sec_tone_mode=%d\n", __func__,
- fe_sec_tone_mode);
+ dev_dbg(&client->dev, "fe_sec_tone_mode=%d\n", fe_sec_tone_mode);
- if (!priv->warm) {
+ if (!dev->warm) {
ret = -EAGAIN;
goto err;
}
@@ -1091,40 +986,39 @@ static int m88ds3103_set_tone(struct dvb_frontend *fe,
reg_a1_mask = 0x00;
break;
default:
- dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_tone_mode\n",
- __func__);
+ dev_dbg(&client->dev, "invalid fe_sec_tone_mode\n");
ret = -EINVAL;
goto err;
}
- u8tmp = tone << 7 | priv->cfg->envelope_mode << 5;
- ret = m88ds3103_wr_reg_mask(priv, 0xa2, u8tmp, 0xe0);
+ utmp = tone << 7 | dev->cfg->envelope_mode << 5;
+ ret = regmap_update_bits(dev->regmap, 0xa2, 0xe0, utmp);
if (ret)
goto err;
- u8tmp = 1 << 2;
- ret = m88ds3103_wr_reg_mask(priv, 0xa1, u8tmp, reg_a1_mask);
+ utmp = 1 << 2;
+ ret = regmap_update_bits(dev->regmap, 0xa1, reg_a1_mask, utmp);
if (ret)
goto err;
return 0;
err:
- dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+ dev_dbg(&client->dev, "failed=%d\n", ret);
return ret;
}
static int m88ds3103_set_voltage(struct dvb_frontend *fe,
- fe_sec_voltage_t fe_sec_voltage)
+ enum fe_sec_voltage fe_sec_voltage)
{
- struct m88ds3103_priv *priv = fe->demodulator_priv;
+ struct m88ds3103_dev *dev = fe->demodulator_priv;
+ struct i2c_client *client = dev->client;
int ret;
- u8 u8tmp;
+ unsigned int utmp;
bool voltage_sel, voltage_dis;
- dev_dbg(&priv->i2c->dev, "%s: fe_sec_voltage=%d\n", __func__,
- fe_sec_voltage);
+ dev_dbg(&client->dev, "fe_sec_voltage=%d\n", fe_sec_voltage);
- if (!priv->warm) {
+ if (!dev->warm) {
ret = -EAGAIN;
goto err;
}
@@ -1143,38 +1037,39 @@ static int m88ds3103_set_voltage(struct dvb_frontend *fe,
voltage_dis = true;
break;
default:
- dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_voltage\n",
- __func__);
+ dev_dbg(&client->dev, "invalid fe_sec_voltage\n");
ret = -EINVAL;
goto err;
}
/* output pin polarity */
- voltage_sel ^= priv->cfg->lnb_hv_pol;
- voltage_dis ^= priv->cfg->lnb_en_pol;
+ voltage_sel ^= dev->cfg->lnb_hv_pol;
+ voltage_dis ^= dev->cfg->lnb_en_pol;
- u8tmp = voltage_dis << 1 | voltage_sel << 0;
- ret = m88ds3103_wr_reg_mask(priv, 0xa2, u8tmp, 0x03);
+ utmp = voltage_dis << 1 | voltage_sel << 0;
+ ret = regmap_update_bits(dev->regmap, 0xa2, 0x03, utmp);
if (ret)
goto err;
return 0;
err:
- dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+ dev_dbg(&client->dev, "failed=%d\n", 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;
+ struct m88ds3103_dev *dev = fe->demodulator_priv;
+ struct i2c_client *client = dev->client;
+ int ret;
+ unsigned int utmp;
+ unsigned long timeout;
- dev_dbg(&priv->i2c->dev, "%s: msg=%*ph\n", __func__,
- diseqc_cmd->msg_len, diseqc_cmd->msg);
+ dev_dbg(&client->dev, "msg=%*ph\n",
+ diseqc_cmd->msg_len, diseqc_cmd->msg);
- if (!priv->warm) {
+ if (!dev->warm) {
ret = -EAGAIN;
goto err;
}
@@ -1184,75 +1079,80 @@ static int m88ds3103_diseqc_send_master_cmd(struct dvb_frontend *fe,
goto err;
}
- u8tmp = priv->cfg->envelope_mode << 5;
- ret = m88ds3103_wr_reg_mask(priv, 0xa2, u8tmp, 0xe0);
+ utmp = dev->cfg->envelope_mode << 5;
+ ret = regmap_update_bits(dev->regmap, 0xa2, 0xe0, utmp);
if (ret)
goto err;
- ret = m88ds3103_wr_regs(priv, 0xa3, diseqc_cmd->msg,
+ ret = regmap_bulk_write(dev->regmap, 0xa3, diseqc_cmd->msg,
diseqc_cmd->msg_len);
if (ret)
goto err;
- ret = m88ds3103_wr_reg(priv, 0xa1,
+ ret = regmap_write(dev->regmap, 0xa1,
(diseqc_cmd->msg_len - 1) << 3 | 0x07);
if (ret)
goto err;
- /* DiSEqC message typical period is 54 ms */
- usleep_range(40000, 60000);
-
/* wait DiSEqC TX ready */
- for (i = 20, u8tmp = 1; i && u8tmp; i--) {
- usleep_range(5000, 10000);
+ #define SEND_MASTER_CMD_TIMEOUT 120
+ timeout = jiffies + msecs_to_jiffies(SEND_MASTER_CMD_TIMEOUT);
+
+ /* DiSEqC message typical period is 54 ms */
+ usleep_range(50000, 54000);
- ret = m88ds3103_rd_reg_mask(priv, 0xa1, &u8tmp, 0x40);
+ for (utmp = 1; !time_after(jiffies, timeout) && utmp;) {
+ ret = regmap_read(dev->regmap, 0xa1, &utmp);
if (ret)
goto err;
+ utmp = (utmp >> 6) & 0x1;
}
- dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
-
- if (i == 0) {
- dev_dbg(&priv->i2c->dev, "%s: diseqc tx timeout\n", __func__);
+ if (utmp == 0) {
+ dev_dbg(&client->dev, "diseqc tx took %u ms\n",
+ jiffies_to_msecs(jiffies) -
+ (jiffies_to_msecs(timeout) - SEND_MASTER_CMD_TIMEOUT));
+ } else {
+ dev_dbg(&client->dev, "diseqc tx timeout\n");
- ret = m88ds3103_wr_reg_mask(priv, 0xa1, 0x40, 0xc0);
+ ret = regmap_update_bits(dev->regmap, 0xa1, 0xc0, 0x40);
if (ret)
goto err;
}
- ret = m88ds3103_wr_reg_mask(priv, 0xa2, 0x80, 0xc0);
+ ret = regmap_update_bits(dev->regmap, 0xa2, 0xc0, 0x80);
if (ret)
goto err;
- if (i == 0) {
+ if (utmp == 1) {
ret = -ETIMEDOUT;
goto err;
}
return 0;
err:
- dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+ dev_dbg(&client->dev, "failed=%d\n", ret);
return ret;
}
static int m88ds3103_diseqc_send_burst(struct dvb_frontend *fe,
- fe_sec_mini_cmd_t fe_sec_mini_cmd)
+ enum fe_sec_mini_cmd fe_sec_mini_cmd)
{
- struct m88ds3103_priv *priv = fe->demodulator_priv;
- int ret, i;
- u8 u8tmp, burst;
+ struct m88ds3103_dev *dev = fe->demodulator_priv;
+ struct i2c_client *client = dev->client;
+ int ret;
+ unsigned int utmp, burst;
+ unsigned long timeout;
- dev_dbg(&priv->i2c->dev, "%s: fe_sec_mini_cmd=%d\n", __func__,
- fe_sec_mini_cmd);
+ dev_dbg(&client->dev, "fe_sec_mini_cmd=%d\n", fe_sec_mini_cmd);
- if (!priv->warm) {
+ if (!dev->warm) {
ret = -EAGAIN;
goto err;
}
- u8tmp = priv->cfg->envelope_mode << 5;
- ret = m88ds3103_wr_reg_mask(priv, 0xa2, u8tmp, 0xe0);
+ utmp = dev->cfg->envelope_mode << 5;
+ ret = regmap_update_bits(dev->regmap, 0xa2, 0xe0, utmp);
if (ret)
goto err;
@@ -1264,43 +1164,53 @@ static int m88ds3103_diseqc_send_burst(struct dvb_frontend *fe,
burst = 0x01;
break;
default:
- dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_mini_cmd\n",
- __func__);
+ dev_dbg(&client->dev, "invalid fe_sec_mini_cmd\n");
ret = -EINVAL;
goto err;
}
- ret = m88ds3103_wr_reg(priv, 0xa1, burst);
+ ret = regmap_write(dev->regmap, 0xa1, burst);
if (ret)
goto err;
- /* DiSEqC ToneBurst period is 12.5 ms */
- usleep_range(11000, 20000);
-
/* wait DiSEqC TX ready */
- for (i = 5, u8tmp = 1; i && u8tmp; i--) {
- usleep_range(800, 2000);
+ #define SEND_BURST_TIMEOUT 40
+ timeout = jiffies + msecs_to_jiffies(SEND_BURST_TIMEOUT);
- ret = m88ds3103_rd_reg_mask(priv, 0xa1, &u8tmp, 0x40);
+ /* DiSEqC ToneBurst period is 12.5 ms */
+ usleep_range(8500, 12500);
+
+ for (utmp = 1; !time_after(jiffies, timeout) && utmp;) {
+ ret = regmap_read(dev->regmap, 0xa1, &utmp);
if (ret)
goto err;
+ utmp = (utmp >> 6) & 0x1;
}
- dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
+ if (utmp == 0) {
+ dev_dbg(&client->dev, "diseqc tx took %u ms\n",
+ jiffies_to_msecs(jiffies) -
+ (jiffies_to_msecs(timeout) - SEND_BURST_TIMEOUT));
+ } else {
+ dev_dbg(&client->dev, "diseqc tx timeout\n");
- ret = m88ds3103_wr_reg_mask(priv, 0xa2, 0x80, 0xc0);
+ ret = regmap_update_bits(dev->regmap, 0xa1, 0xc0, 0x40);
+ if (ret)
+ goto err;
+ }
+
+ ret = regmap_update_bits(dev->regmap, 0xa2, 0xc0, 0x80);
if (ret)
goto err;
- if (i == 0) {
- dev_dbg(&priv->i2c->dev, "%s: diseqc tx timeout\n", __func__);
+ if (utmp == 1) {
ret = -ETIMEDOUT;
goto err;
}
return 0;
err:
- dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+ dev_dbg(&client->dev, "failed=%d\n", ret);
return ret;
}
@@ -1314,192 +1224,289 @@ 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;
+ struct m88ds3103_dev *dev = fe->demodulator_priv;
+ struct i2c_client *client = dev->client;
- i2c_del_mux_adapter(priv->i2c_adapter);
- kfree(priv);
+ i2c_unregister_device(client);
}
static int m88ds3103_select(struct i2c_adapter *adap, void *mux_priv, u32 chan)
{
- struct m88ds3103_priv *priv = mux_priv;
+ struct m88ds3103_dev *dev = mux_priv;
+ struct i2c_client *client = dev->client;
int ret;
- struct i2c_msg gate_open_msg[1] = {
- {
- .addr = priv->cfg->i2c_addr,
- .flags = 0,
- .len = 2,
- .buf = "\x03\x11",
- }
+ struct i2c_msg msg = {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 2,
+ .buf = "\x03\x11",
};
- mutex_lock(&priv->i2c_mutex);
-
- /* open tuner I2C repeater for 1 xfer, closes automatically */
- ret = __i2c_transfer(priv->i2c, gate_open_msg, 1);
+ /* Open tuner I2C repeater for 1 xfer, closes automatically */
+ ret = __i2c_transfer(client->adapter, &msg, 1);
if (ret != 1) {
- dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d\n",
- KBUILD_MODNAME, ret);
+ dev_warn(&client->dev, "i2c wr failed=%d\n", ret);
if (ret >= 0)
ret = -EREMOTEIO;
-
return ret;
}
return 0;
}
-static int m88ds3103_deselect(struct i2c_adapter *adap, void *mux_priv,
- u32 chan)
+/*
+ * XXX: That is wrapper to m88ds3103_probe() via driver core in order to provide
+ * proper I2C client for legacy media attach binding.
+ * New users must use I2C client binding directly!
+ */
+struct dvb_frontend *m88ds3103_attach(const struct m88ds3103_config *cfg,
+ struct i2c_adapter *i2c, struct i2c_adapter **tuner_i2c_adapter)
{
- struct m88ds3103_priv *priv = mux_priv;
+ struct i2c_client *client;
+ struct i2c_board_info board_info;
+ struct m88ds3103_platform_data pdata;
+
+ pdata.clk = cfg->clock;
+ pdata.i2c_wr_max = cfg->i2c_wr_max;
+ pdata.ts_mode = cfg->ts_mode;
+ pdata.ts_clk = cfg->ts_clk;
+ pdata.ts_clk_pol = cfg->ts_clk_pol;
+ pdata.spec_inv = cfg->spec_inv;
+ pdata.agc = cfg->agc;
+ pdata.agc_inv = cfg->agc_inv;
+ pdata.clk_out = cfg->clock_out;
+ pdata.envelope_mode = cfg->envelope_mode;
+ pdata.lnb_hv_pol = cfg->lnb_hv_pol;
+ pdata.lnb_en_pol = cfg->lnb_en_pol;
+ pdata.attach_in_use = true;
+
+ memset(&board_info, 0, sizeof(board_info));
+ strlcpy(board_info.type, "m88ds3103", I2C_NAME_SIZE);
+ board_info.addr = cfg->i2c_addr;
+ board_info.platform_data = &pdata;
+ client = i2c_new_device(i2c, &board_info);
+ if (!client || !client->dev.driver)
+ return NULL;
+
+ *tuner_i2c_adapter = pdata.get_i2c_adapter(client);
+ return pdata.get_dvb_frontend(client);
+}
+EXPORT_SYMBOL(m88ds3103_attach);
+
+static struct dvb_frontend_ops m88ds3103_ops = {
+ .delsys = {SYS_DVBS, SYS_DVBS2},
+ .info = {
+ .name = "Montage Technology M88DS3103",
+ .frequency_min = 950000,
+ .frequency_max = 2150000,
+ .frequency_tolerance = 5000,
+ .symbol_rate_min = 1000000,
+ .symbol_rate_max = 45000000,
+ .caps = FE_CAN_INVERSION_AUTO |
+ FE_CAN_FEC_1_2 |
+ FE_CAN_FEC_2_3 |
+ FE_CAN_FEC_3_4 |
+ FE_CAN_FEC_4_5 |
+ FE_CAN_FEC_5_6 |
+ FE_CAN_FEC_6_7 |
+ FE_CAN_FEC_7_8 |
+ FE_CAN_FEC_8_9 |
+ FE_CAN_FEC_AUTO |
+ FE_CAN_QPSK |
+ FE_CAN_RECOVER |
+ FE_CAN_2G_MODULATION
+ },
- mutex_unlock(&priv->i2c_mutex);
+ .release = m88ds3103_release,
- return 0;
+ .get_tune_settings = m88ds3103_get_tune_settings,
+
+ .init = m88ds3103_init,
+ .sleep = m88ds3103_sleep,
+
+ .set_frontend = m88ds3103_set_frontend,
+ .get_frontend = m88ds3103_get_frontend,
+
+ .read_status = m88ds3103_read_status,
+ .read_snr = m88ds3103_read_snr,
+ .read_ber = m88ds3103_read_ber,
+
+ .diseqc_send_master_cmd = m88ds3103_diseqc_send_master_cmd,
+ .diseqc_send_burst = m88ds3103_diseqc_send_burst,
+
+ .set_tone = m88ds3103_set_tone,
+ .set_voltage = m88ds3103_set_voltage,
+};
+
+static struct dvb_frontend *m88ds3103_get_dvb_frontend(struct i2c_client *client)
+{
+ struct m88ds3103_dev *dev = i2c_get_clientdata(client);
+
+ dev_dbg(&client->dev, "\n");
+
+ return &dev->fe;
}
-struct dvb_frontend *m88ds3103_attach(const struct m88ds3103_config *cfg,
- struct i2c_adapter *i2c, struct i2c_adapter **tuner_i2c_adapter)
+static struct i2c_adapter *m88ds3103_get_i2c_adapter(struct i2c_client *client)
+{
+ struct m88ds3103_dev *dev = i2c_get_clientdata(client);
+
+ dev_dbg(&client->dev, "\n");
+
+ return dev->i2c_adapter;
+}
+
+static int m88ds3103_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
+ struct m88ds3103_dev *dev;
+ struct m88ds3103_platform_data *pdata = client->dev.platform_data;
int ret;
- struct m88ds3103_priv *priv;
- u8 chip_id, u8tmp;
+ unsigned int utmp;
- /* allocate memory for the internal priv */
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (!priv) {
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev) {
ret = -ENOMEM;
- dev_err(&i2c->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME);
goto err;
}
- priv->cfg = cfg;
- priv->i2c = i2c;
- mutex_init(&priv->i2c_mutex);
+ dev->client = client;
+ dev->config.clock = pdata->clk;
+ dev->config.i2c_wr_max = pdata->i2c_wr_max;
+ dev->config.ts_mode = pdata->ts_mode;
+ dev->config.ts_clk = pdata->ts_clk;
+ dev->config.ts_clk_pol = pdata->ts_clk_pol;
+ dev->config.spec_inv = pdata->spec_inv;
+ dev->config.agc_inv = pdata->agc_inv;
+ dev->config.clock_out = pdata->clk_out;
+ dev->config.envelope_mode = pdata->envelope_mode;
+ dev->config.agc = pdata->agc;
+ dev->config.lnb_hv_pol = pdata->lnb_hv_pol;
+ dev->config.lnb_en_pol = pdata->lnb_en_pol;
+ dev->cfg = &dev->config;
+ /* create regmap */
+ dev->regmap_config.reg_bits = 8,
+ dev->regmap_config.val_bits = 8,
+ dev->regmap_config.lock_arg = dev,
+ dev->regmap = devm_regmap_init_i2c(client, &dev->regmap_config);
+ if (IS_ERR(dev->regmap)) {
+ ret = PTR_ERR(dev->regmap);
+ goto err_kfree;
+ }
/* 0x00: chip id[6:0], 0x01: chip ver[7:0], 0x02: chip ver[15:8] */
- ret = m88ds3103_rd_reg(priv, 0x00, &chip_id);
+ ret = regmap_read(dev->regmap, 0x00, &utmp);
if (ret)
- goto err;
+ goto err_kfree;
- chip_id >>= 1;
- dev_info(&priv->i2c->dev, "%s: chip_id=%02x\n", __func__, chip_id);
+ dev->chip_id = utmp >> 1;
+ dev_dbg(&client->dev, "chip_id=%02x\n", dev->chip_id);
- switch (chip_id) {
+ switch (dev->chip_id) {
case M88RS6000_CHIP_ID:
case M88DS3103_CHIP_ID:
break;
default:
- goto err;
+ goto err_kfree;
}
- priv->chip_id = chip_id;
- switch (priv->cfg->clock_out) {
+ switch (dev->cfg->clock_out) {
case M88DS3103_CLOCK_OUT_DISABLED:
- u8tmp = 0x80;
+ utmp = 0x80;
break;
case M88DS3103_CLOCK_OUT_ENABLED:
- u8tmp = 0x00;
+ utmp = 0x00;
break;
case M88DS3103_CLOCK_OUT_ENABLED_DIV2:
- u8tmp = 0x10;
+ utmp = 0x10;
break;
default:
- goto err;
+ ret = -EINVAL;
+ goto err_kfree;
}
/* 0x29 register is defined differently for m88rs6000. */
/* set internal tuner address to 0x21 */
- if (chip_id == M88RS6000_CHIP_ID)
- u8tmp = 0x00;
+ if (dev->chip_id == M88RS6000_CHIP_ID)
+ utmp = 0x00;
- ret = m88ds3103_wr_reg(priv, 0x29, u8tmp);
+ ret = regmap_write(dev->regmap, 0x29, utmp);
if (ret)
- goto err;
+ goto err_kfree;
/* sleep */
- ret = m88ds3103_wr_reg_mask(priv, 0x08, 0x00, 0x01);
+ ret = regmap_update_bits(dev->regmap, 0x08, 0x01, 0x00);
if (ret)
- goto err;
-
- ret = m88ds3103_wr_reg_mask(priv, 0x04, 0x01, 0x01);
+ goto err_kfree;
+ ret = regmap_update_bits(dev->regmap, 0x04, 0x01, 0x01);
if (ret)
- goto err;
-
- ret = m88ds3103_wr_reg_mask(priv, 0x23, 0x10, 0x10);
+ goto err_kfree;
+ ret = regmap_update_bits(dev->regmap, 0x23, 0x10, 0x10);
if (ret)
- goto err;
+ goto err_kfree;
/* create mux i2c adapter for tuner */
- priv->i2c_adapter = i2c_add_mux_adapter(i2c, &i2c->dev, priv, 0, 0, 0,
- m88ds3103_select, m88ds3103_deselect);
- if (priv->i2c_adapter == NULL)
- goto err;
-
- *tuner_i2c_adapter = priv->i2c_adapter;
+ dev->i2c_adapter = i2c_add_mux_adapter(client->adapter, &client->dev,
+ dev, 0, 0, 0, m88ds3103_select,
+ NULL);
+ if (dev->i2c_adapter == NULL) {
+ ret = -ENOMEM;
+ goto err_kfree;
+ }
/* create dvb_frontend */
- memcpy(&priv->fe.ops, &m88ds3103_ops, sizeof(struct dvb_frontend_ops));
- if (priv->chip_id == M88RS6000_CHIP_ID)
- strncpy(priv->fe.ops.info.name,
- "Montage M88RS6000", sizeof(priv->fe.ops.info.name));
- priv->fe.demodulator_priv = priv;
-
- return &priv->fe;
+ memcpy(&dev->fe.ops, &m88ds3103_ops, sizeof(struct dvb_frontend_ops));
+ if (dev->chip_id == M88RS6000_CHIP_ID)
+ strncpy(dev->fe.ops.info.name, "Montage Technology M88RS6000",
+ sizeof(dev->fe.ops.info.name));
+ if (!pdata->attach_in_use)
+ dev->fe.ops.release = NULL;
+ dev->fe.demodulator_priv = dev;
+ i2c_set_clientdata(client, dev);
+
+ /* setup callbacks */
+ pdata->get_dvb_frontend = m88ds3103_get_dvb_frontend;
+ pdata->get_i2c_adapter = m88ds3103_get_i2c_adapter;
+ return 0;
+err_kfree:
+ kfree(dev);
err:
- dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
- kfree(priv);
- return NULL;
+ dev_dbg(&client->dev, "failed=%d\n", ret);
+ return ret;
}
-EXPORT_SYMBOL(m88ds3103_attach);
-
-static struct dvb_frontend_ops m88ds3103_ops = {
- .delsys = { SYS_DVBS, SYS_DVBS2 },
- .info = {
- .name = "Montage M88DS3103",
- .frequency_min = 950000,
- .frequency_max = 2150000,
- .frequency_tolerance = 5000,
- .symbol_rate_min = 1000000,
- .symbol_rate_max = 45000000,
- .caps = FE_CAN_INVERSION_AUTO |
- FE_CAN_FEC_1_2 |
- FE_CAN_FEC_2_3 |
- FE_CAN_FEC_3_4 |
- FE_CAN_FEC_4_5 |
- FE_CAN_FEC_5_6 |
- FE_CAN_FEC_6_7 |
- FE_CAN_FEC_7_8 |
- FE_CAN_FEC_8_9 |
- FE_CAN_FEC_AUTO |
- FE_CAN_QPSK |
- FE_CAN_RECOVER |
- FE_CAN_2G_MODULATION
- },
- .release = m88ds3103_release,
+static int m88ds3103_remove(struct i2c_client *client)
+{
+ struct m88ds3103_dev *dev = i2c_get_clientdata(client);
- .get_tune_settings = m88ds3103_get_tune_settings,
+ dev_dbg(&client->dev, "\n");
- .init = m88ds3103_init,
- .sleep = m88ds3103_sleep,
+ i2c_del_mux_adapter(dev->i2c_adapter);
- .set_frontend = m88ds3103_set_frontend,
- .get_frontend = m88ds3103_get_frontend,
-
- .read_status = m88ds3103_read_status,
- .read_snr = m88ds3103_read_snr,
- .read_ber = m88ds3103_read_ber,
+ kfree(dev);
+ return 0;
+}
- .diseqc_send_master_cmd = m88ds3103_diseqc_send_master_cmd,
- .diseqc_send_burst = m88ds3103_diseqc_send_burst,
+static const struct i2c_device_id m88ds3103_id_table[] = {
+ {"m88ds3103", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, m88ds3103_id_table);
- .set_tone = m88ds3103_set_tone,
- .set_voltage = m88ds3103_set_voltage,
+static struct i2c_driver m88ds3103_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "m88ds3103",
+ .suppress_bind_attrs = true,
+ },
+ .probe = m88ds3103_probe,
+ .remove = m88ds3103_remove,
+ .id_table = m88ds3103_id_table,
};
+module_i2c_driver(m88ds3103_driver);
+
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("Montage M88DS3103 DVB-S/S2 demodulator driver");
+MODULE_DESCRIPTION("Montage Technology M88DS3103 DVB-S/S2 demodulator driver");
MODULE_LICENSE("GPL");
/*(DEBLOBBED)*/
diff --git a/drivers/media/dvb-frontends/m88ds3103.h b/drivers/media/dvb-frontends/m88ds3103.h
index 9b3b4962d..04b355a00 100644
--- a/drivers/media/dvb-frontends/m88ds3103.h
+++ b/drivers/media/dvb-frontends/m88ds3103.h
@@ -1,5 +1,5 @@
/*
- * Montage M88DS3103 demodulator driver
+ * Montage Technology M88DS3103/M88RS6000 demodulator driver
*
* Copyright (C) 2013 Antti Palosaari <crope@iki.fi>
*
@@ -19,6 +19,63 @@
#include <linux/dvb/frontend.h>
+/*
+ * I2C address
+ * 0x68,
+ */
+
+/**
+ * struct m88ds3103_platform_data - Platform data for the m88ds3103 driver
+ * @clk: Clock frequency.
+ * @i2c_wr_max: Max bytes I2C adapter can write at once.
+ * @ts_mode: TS mode.
+ * @ts_clk: TS clock (KHz).
+ * @ts_clk_pol: TS clk polarity. 1-active at falling edge; 0-active at rising
+ * edge.
+ * @spec_inv: Input spectrum inversion.
+ * @agc: AGC configuration.
+ * @agc_inv: AGC polarity.
+ * @clk_out: Clock output.
+ * @envelope_mode: DiSEqC envelope mode.
+ * @lnb_hv_pol: LNB H/V pin polarity. 0: pin high set to VOLTAGE_18, pin low to
+ * set VOLTAGE_13. 1: pin high set to VOLTAGE_13, pin low to set VOLTAGE_18.
+ * @lnb_en_pol: LNB enable pin polarity. 0: pin high to disable, pin low to
+ * enable. 1: pin high to enable, pin low to disable.
+ * @get_dvb_frontend: Get DVB frontend.
+ * @get_i2c_adapter: Get I2C adapter.
+ */
+
+struct m88ds3103_platform_data {
+ u32 clk;
+ u16 i2c_wr_max;
+#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 /* TS Parallel mode */
+#define M88DS3103_TS_CI 3 /* TS CI Mode */
+ u8 ts_mode:2;
+ u32 ts_clk;
+ u8 ts_clk_pol:1;
+ u8 spec_inv:1;
+ u8 agc;
+ u8 agc_inv:1;
+#define M88DS3103_CLOCK_OUT_DISABLED 0
+#define M88DS3103_CLOCK_OUT_ENABLED 1
+#define M88DS3103_CLOCK_OUT_ENABLED_DIV2 2
+ u8 clk_out:2;
+ u8 envelope_mode:1;
+ u8 lnb_hv_pol:1;
+ u8 lnb_en_pol:1;
+
+ struct dvb_frontend* (*get_dvb_frontend)(struct i2c_client *);
+ struct i2c_adapter* (*get_i2c_adapter)(struct i2c_client *);
+
+/* private: For legacy media attach wrapper. Do not set value. */
+ u8 attach_in_use:1;
+};
+
+/*
+ * Do not add new m88ds3103_attach() users! Use I2C bindings instead.
+ */
struct m88ds3103_config {
/*
* I2C address
@@ -113,18 +170,13 @@ struct m88ds3103_config {
u8 lnb_en_pol:1;
};
-/*
- * Driver implements own I2C-adapter for tuner I2C access. That's since chip
- * has I2C-gate control which closes gate automatically after I2C transfer.
- * Using own I2C adapter we can workaround that.
- */
-
#if defined(CONFIG_DVB_M88DS3103) || \
(defined(CONFIG_DVB_M88DS3103_MODULE) && defined(MODULE))
extern struct dvb_frontend *m88ds3103_attach(
const struct m88ds3103_config *config,
struct i2c_adapter *i2c,
struct i2c_adapter **tuner_i2c);
+extern int m88ds3103_get_agc_pwm(struct dvb_frontend *fe, u8 *_agc_pwm);
#else
static inline struct dvb_frontend *m88ds3103_attach(
const struct m88ds3103_config *config,
@@ -134,6 +186,7 @@ static inline struct dvb_frontend *m88ds3103_attach(
pr_warn("%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
+#define m88ds3103_get_agc_pwm NULL
#endif
#endif
diff --git a/drivers/media/dvb-frontends/m88ds3103_priv.h b/drivers/media/dvb-frontends/m88ds3103_priv.h
index 5cbb0fe93..4c60e894b 100644
--- a/drivers/media/dvb-frontends/m88ds3103_priv.h
+++ b/drivers/media/dvb-frontends/m88ds3103_priv.h
@@ -1,5 +1,5 @@
/*
- * Montage M88DS3103 demodulator driver
+ * Montage Technology M88DS3103/M88RS6000 demodulator driver
*
* Copyright (C) 2013 Antti Palosaari <crope@iki.fi>
*
@@ -22,6 +22,7 @@
#include "dvb_math.h"
#include <linux/firmware.h>
#include <linux/i2c-mux.h>
+#include <linux/regmap.h>
#include <linux/math64.h>
#define M88DS3103_FIRMWARE "/*(DEBLOBBED)*/"
@@ -30,21 +31,24 @@
#define M88RS6000_CHIP_ID 0x74
#define M88DS3103_CHIP_ID 0x70
-struct m88ds3103_priv {
- struct i2c_adapter *i2c;
- /* mutex needed due to own tuner I2C adapter */
- struct mutex i2c_mutex;
+struct m88ds3103_dev {
+ struct i2c_client *client;
+ struct regmap_config regmap_config;
+ struct regmap *regmap;
+ struct m88ds3103_config config;
const struct m88ds3103_config *cfg;
struct dvb_frontend fe;
- fe_delivery_system_t delivery_system;
- fe_status_t fe_status;
- u32 ber;
+ enum fe_delivery_system delivery_system;
+ enum fe_status fe_status;
+ u32 dvbv3_ber; /* for old DVBv3 API read_ber */
bool warm; /* FW running */
struct i2c_adapter *i2c_adapter;
/* auto detect chip id to do different config */
u8 chip_id;
/* main mclk is calculated for M88RS6000 dynamically */
u32 mclk_khz;
+ u64 post_bit_error;
+ u64 post_bit_count;
};
struct m88ds3103_reg_val {
diff --git a/drivers/media/dvb-frontends/m88rs2000.c b/drivers/media/dvb-frontends/m88rs2000.c
index d63bc9c13..9b6f464c4 100644
--- a/drivers/media/dvb-frontends/m88rs2000.c
+++ b/drivers/media/dvb-frontends/m88rs2000.c
@@ -41,7 +41,7 @@ struct m88rs2000_state {
u8 no_lock_count;
u32 tuner_frequency;
u32 symbol_rate;
- fe_code_rate_t fec_inner;
+ enum fe_code_rate fec_inner;
u8 tuner_level;
int errmode;
};
@@ -247,7 +247,7 @@ static int m88rs2000_send_diseqc_msg(struct dvb_frontend *fe,
}
static int m88rs2000_send_diseqc_burst(struct dvb_frontend *fe,
- fe_sec_mini_cmd_t burst)
+ enum fe_sec_mini_cmd burst)
{
struct m88rs2000_state *state = fe->demodulator_priv;
u8 reg0, reg1;
@@ -264,7 +264,8 @@ static int m88rs2000_send_diseqc_burst(struct dvb_frontend *fe,
return 0;
}
-static int m88rs2000_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+static int m88rs2000_set_tone(struct dvb_frontend *fe,
+ enum fe_sec_tone_mode tone)
{
struct m88rs2000_state *state = fe->demodulator_priv;
u8 reg0, reg1;
@@ -412,7 +413,8 @@ static int m88rs2000_tab_set(struct m88rs2000_state *state,
return 0;
}
-static int m88rs2000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
+static int m88rs2000_set_voltage(struct dvb_frontend *fe,
+ enum fe_sec_voltage volt)
{
struct m88rs2000_state *state = fe->demodulator_priv;
u8 data;
@@ -462,7 +464,8 @@ static int m88rs2000_sleep(struct dvb_frontend *fe)
return ret;
}
-static int m88rs2000_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int m88rs2000_read_status(struct dvb_frontend *fe,
+ enum fe_status *status)
{
struct m88rs2000_state *state = fe->demodulator_priv;
u8 reg = m88rs2000_readreg(state, 0x8c);
@@ -539,7 +542,7 @@ static int m88rs2000_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
}
static int m88rs2000_set_fec(struct m88rs2000_state *state,
- fe_code_rate_t fec)
+ enum fe_code_rate fec)
{
u8 fec_set, reg;
int ret;
@@ -574,7 +577,7 @@ static int m88rs2000_set_fec(struct m88rs2000_state *state,
return ret;
}
-static fe_code_rate_t m88rs2000_get_fec(struct m88rs2000_state *state)
+static enum fe_code_rate m88rs2000_get_fec(struct m88rs2000_state *state)
{
u8 reg;
m88rs2000_writereg(state, 0x9a, 0x30);
@@ -606,7 +609,7 @@ static int m88rs2000_set_frontend(struct dvb_frontend *fe)
{
struct m88rs2000_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- fe_status_t status;
+ enum fe_status status;
int i, ret = 0;
u32 tuner_freq;
s16 offset = 0;
diff --git a/drivers/media/dvb-frontends/mb86a16.c b/drivers/media/dvb-frontends/mb86a16.c
index 3ddea4471..79bc671e8 100644
--- a/drivers/media/dvb-frontends/mb86a16.c
+++ b/drivers/media/dvb-frontends/mb86a16.c
@@ -593,7 +593,7 @@ err:
return -EREMOTEIO;
}
-static int mb86a16_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int mb86a16_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
u8 stat, stat2;
struct mb86a16_state *state = fe->demodulator_priv;
@@ -1562,7 +1562,8 @@ err:
return -EREMOTEIO;
}
-static int mb86a16_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst)
+static int mb86a16_send_diseqc_burst(struct dvb_frontend *fe,
+ enum fe_sec_mini_cmd burst)
{
struct mb86a16_state *state = fe->demodulator_priv;
@@ -1590,7 +1591,7 @@ err:
return -EREMOTEIO;
}
-static int mb86a16_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+static int mb86a16_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)
{
struct mb86a16_state *state = fe->demodulator_priv;
diff --git a/drivers/media/dvb-frontends/mb86a16.h b/drivers/media/dvb-frontends/mb86a16.h
index e486dc0d8..dbd5f43fa 100644
--- a/drivers/media/dvb-frontends/mb86a16.h
+++ b/drivers/media/dvb-frontends/mb86a16.h
@@ -28,7 +28,8 @@
struct mb86a16_config {
u8 demod_address;
- int (*set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
+ int (*set_voltage)(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage);
};
diff --git a/drivers/media/dvb-frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c
index 8f54c39ca..cfc005ee1 100644
--- a/drivers/media/dvb-frontends/mb86a20s.c
+++ b/drivers/media/dvb-frontends/mb86a20s.c
@@ -294,7 +294,7 @@ static int mb86a20s_i2c_readreg(struct mb86a20s_state *state,
* The functions below assume that gateway lock has already obtained
*/
-static int mb86a20s_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int mb86a20s_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct mb86a20s_state *state = fe->demodulator_priv;
int val;
@@ -1951,7 +1951,7 @@ static int mb86a20s_set_frontend(struct dvb_frontend *fe)
}
static int mb86a20s_read_status_and_stats(struct dvb_frontend *fe,
- fe_status_t *status)
+ enum fe_status *status)
{
struct mb86a20s_state *state = fe->demodulator_priv;
int rc, status_nr;
@@ -2042,7 +2042,7 @@ static int mb86a20s_tune(struct dvb_frontend *fe,
bool re_tune,
unsigned int mode_flags,
unsigned int *delay,
- fe_status_t *status)
+ enum fe_status *status)
{
struct mb86a20s_state *state = fe->demodulator_priv;
int rc = 0;
diff --git a/drivers/media/dvb-frontends/mb86a20s.h b/drivers/media/dvb-frontends/mb86a20s.h
index f749c8ac5..a113282d6 100644
--- a/drivers/media/dvb-frontends/mb86a20s.h
+++ b/drivers/media/dvb-frontends/mb86a20s.h
@@ -45,7 +45,7 @@ static inline struct dvb_frontend *mb86a20s_attach(
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-static struct i2c_adapter *
+static inline struct i2c_adapter *
mb86a20s_get_tuner_i2c_adapter(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
diff --git a/drivers/media/dvb-frontends/mt312.c b/drivers/media/dvb-frontends/mt312.c
index 2163490c1..c36e6764e 100644
--- a/drivers/media/dvb-frontends/mt312.c
+++ b/drivers/media/dvb-frontends/mt312.c
@@ -156,7 +156,7 @@ static int mt312_reset(struct mt312_state *state, const u8 full)
}
static int mt312_get_inversion(struct mt312_state *state,
- fe_spectral_inversion_t *i)
+ enum fe_spectral_inversion *i)
{
int ret;
u8 vit_mode;
@@ -225,9 +225,9 @@ static int mt312_get_symbol_rate(struct mt312_state *state, u32 *sr)
return 0;
}
-static int mt312_get_code_rate(struct mt312_state *state, fe_code_rate_t *cr)
+static int mt312_get_code_rate(struct mt312_state *state, enum fe_code_rate *cr)
{
- const fe_code_rate_t fec_tab[8] =
+ const enum fe_code_rate fec_tab[8] =
{ FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_6_7, FEC_7_8,
FEC_AUTO, FEC_AUTO };
@@ -380,7 +380,8 @@ static int mt312_send_master_cmd(struct dvb_frontend *fe,
return 0;
}
-static int mt312_send_burst(struct dvb_frontend *fe, const fe_sec_mini_cmd_t c)
+static int mt312_send_burst(struct dvb_frontend *fe,
+ const enum fe_sec_mini_cmd c)
{
struct mt312_state *state = fe->demodulator_priv;
const u8 mini_tab[2] = { 0x02, 0x03 };
@@ -403,7 +404,8 @@ static int mt312_send_burst(struct dvb_frontend *fe, const fe_sec_mini_cmd_t c)
return 0;
}
-static int mt312_set_tone(struct dvb_frontend *fe, const fe_sec_tone_mode_t t)
+static int mt312_set_tone(struct dvb_frontend *fe,
+ const enum fe_sec_tone_mode t)
{
struct mt312_state *state = fe->demodulator_priv;
const u8 tone_tab[2] = { 0x01, 0x00 };
@@ -426,7 +428,8 @@ static int mt312_set_tone(struct dvb_frontend *fe, const fe_sec_tone_mode_t t)
return 0;
}
-static int mt312_set_voltage(struct dvb_frontend *fe, const fe_sec_voltage_t v)
+static int mt312_set_voltage(struct dvb_frontend *fe,
+ const enum fe_sec_voltage v)
{
struct mt312_state *state = fe->demodulator_priv;
const u8 volt_tab[3] = { 0x00, 0x40, 0x00 };
@@ -442,7 +445,7 @@ static int mt312_set_voltage(struct dvb_frontend *fe, const fe_sec_voltage_t v)
return mt312_writereg(state, DISEQC_MODE, val);
}
-static int mt312_read_status(struct dvb_frontend *fe, fe_status_t *s)
+static int mt312_read_status(struct dvb_frontend *fe, enum fe_status *s)
{
struct mt312_state *state = fe->demodulator_priv;
int ret;
diff --git a/drivers/media/dvb-frontends/mt352.c b/drivers/media/dvb-frontends/mt352.c
index 2c3b50e82..123bb2f8e 100644
--- a/drivers/media/dvb-frontends/mt352.c
+++ b/drivers/media/dvb-frontends/mt352.c
@@ -417,7 +417,7 @@ static int mt352_get_parameters(struct dvb_frontend* fe)
return 0;
}
-static int mt352_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int mt352_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct mt352_state* state = fe->demodulator_priv;
int s0, s1, s3;
diff --git a/drivers/media/dvb-frontends/nxt200x.c b/drivers/media/dvb-frontends/nxt200x.c
index d91734c35..ea6c3f9ad 100644
--- a/drivers/media/dvb-frontends/nxt200x.c
+++ b/drivers/media/dvb-frontends/nxt200x.c
@@ -767,7 +767,7 @@ static int nxt200x_setup_frontend_parameters(struct dvb_frontend *fe)
return 0;
}
-static int nxt200x_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int nxt200x_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct nxt200x_state* state = fe->demodulator_priv;
u8 lock;
diff --git a/drivers/media/dvb-frontends/nxt6000.c b/drivers/media/dvb-frontends/nxt6000.c
index 90ae6c72c..73f950536 100644
--- a/drivers/media/dvb-frontends/nxt6000.c
+++ b/drivers/media/dvb-frontends/nxt6000.c
@@ -109,7 +109,8 @@ static int nxt6000_set_bandwidth(struct nxt6000_state *state, u32 bandwidth)
return nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_2, (nominal_rate >> 8) & 0xFF);
}
-static int nxt6000_set_guard_interval(struct nxt6000_state* state, fe_guard_interval_t guard_interval)
+static int nxt6000_set_guard_interval(struct nxt6000_state *state,
+ enum fe_guard_interval guard_interval)
{
switch (guard_interval) {
@@ -131,7 +132,8 @@ static int nxt6000_set_guard_interval(struct nxt6000_state* state, fe_guard_inte
}
}
-static int nxt6000_set_inversion(struct nxt6000_state* state, fe_spectral_inversion_t inversion)
+static int nxt6000_set_inversion(struct nxt6000_state *state,
+ enum fe_spectral_inversion inversion)
{
switch (inversion) {
@@ -147,7 +149,9 @@ static int nxt6000_set_inversion(struct nxt6000_state* state, fe_spectral_invers
}
}
-static int nxt6000_set_transmission_mode(struct nxt6000_state* state, fe_transmit_mode_t transmission_mode)
+static int
+nxt6000_set_transmission_mode(struct nxt6000_state *state,
+ enum fe_transmit_mode transmission_mode)
{
int result;
@@ -416,7 +420,7 @@ static void nxt6000_dump_status(struct nxt6000_state *state)
printk("\n");
}
-static int nxt6000_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int nxt6000_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
u8 core_status;
struct nxt6000_state* state = fe->demodulator_priv;
diff --git a/drivers/media/dvb-frontends/or51132.c b/drivers/media/dvb-frontends/or51132.c
index 4f3c73f82..76c032162 100644
--- a/drivers/media/dvb-frontends/or51132.c
+++ b/drivers/media/dvb-frontends/or51132.c
@@ -58,7 +58,7 @@ struct or51132_state
struct dvb_frontend frontend;
/* Demodulator private data */
- fe_modulation_t current_modulation;
+ enum fe_modulation current_modulation;
u32 snr; /* Result of last SNR calculation */
/* Tuner private data */
@@ -287,7 +287,7 @@ static int or51132_setmode(struct dvb_frontend* fe)
#define MOD_FWCLASS_UNKNOWN 0
#define MOD_FWCLASS_VSB 1
#define MOD_FWCLASS_QAM 2
-static int modulation_fw_class(fe_modulation_t modulation)
+static int modulation_fw_class(enum fe_modulation modulation)
{
switch(modulation) {
case VSB_8:
@@ -410,7 +410,7 @@ start:
return 0;
}
-static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int or51132_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct or51132_state* state = fe->demodulator_priv;
int reg;
diff --git a/drivers/media/dvb-frontends/or51211.c b/drivers/media/dvb-frontends/or51211.c
index 10f9c6a01..f12b85f60 100644
--- a/drivers/media/dvb-frontends/or51211.c
+++ b/drivers/media/dvb-frontends/or51211.c
@@ -231,7 +231,7 @@ static int or51211_set_parameters(struct dvb_frontend *fe)
return 0;
}
-static int or51211_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int or51211_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct or51211_state* state = fe->demodulator_priv;
unsigned char rec_buf[2];
diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c
index e1b8df62b..3d01f4f22 100644
--- a/drivers/media/dvb-frontends/rtl2830.c
+++ b/drivers/media/dvb-frontends/rtl2830.c
@@ -392,7 +392,7 @@ err:
return ret;
}
-static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int rtl2830_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct i2c_client *client = fe->demodulator_priv;
struct rtl2830_dev *dev = i2c_get_clientdata(client);
diff --git a/drivers/media/dvb-frontends/rtl2830_priv.h b/drivers/media/dvb-frontends/rtl2830_priv.h
index d50d5376c..cf793f39a 100644
--- a/drivers/media/dvb-frontends/rtl2830_priv.h
+++ b/drivers/media/dvb-frontends/rtl2830_priv.h
@@ -34,7 +34,7 @@ struct rtl2830_dev {
bool sleeping;
unsigned long filters;
struct delayed_work stat_work;
- fe_status_t fe_status;
+ enum fe_status fe_status;
u64 post_bit_error_prev; /* for old DVBv3 read_ber() calculation */
u64 post_bit_error;
u64 post_bit_count;
diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c
index b400f7b3c..822ea4b7a 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -358,6 +358,10 @@ static int rtl2832_init(struct dvb_frontend *fe)
dev_dbg(&client->dev, "load settings for tuner=%02x\n",
dev->pdata->tuner);
switch (dev->pdata->tuner) {
+ case RTL2832_TUNER_FC2580:
+ len = ARRAY_SIZE(rtl2832_tuner_init_fc2580);
+ init = rtl2832_tuner_init_fc2580;
+ break;
case RTL2832_TUNER_FC0012:
case RTL2832_TUNER_FC0013:
len = ARRAY_SIZE(rtl2832_tuner_init_fc0012);
@@ -376,6 +380,10 @@ static int rtl2832_init(struct dvb_frontend *fe)
len = ARRAY_SIZE(rtl2832_tuner_init_r820t);
init = rtl2832_tuner_init_r820t;
break;
+ case RTL2832_TUNER_SI2157:
+ len = ARRAY_SIZE(rtl2832_tuner_init_si2157);
+ init = rtl2832_tuner_init_si2157;
+ break;
default:
ret = -EINVAL;
goto err;
@@ -680,7 +688,7 @@ err:
return ret;
}
-static int rtl2832_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int rtl2832_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct rtl2832_dev *dev = fe->demodulator_priv;
struct i2c_client *client = dev->client;
diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h
index a8e912e67..c29a4c2bf 100644
--- a/drivers/media/dvb-frontends/rtl2832.h
+++ b/drivers/media/dvb-frontends/rtl2832.h
@@ -41,12 +41,14 @@ struct rtl2832_platform_data {
/*
* XXX: This list must be kept sync with dvb_usb_rtl28xxu USB IF driver.
*/
+#define RTL2832_TUNER_FC2580 0x21
#define RTL2832_TUNER_TUA9001 0x24
#define RTL2832_TUNER_FC0012 0x26
#define RTL2832_TUNER_E4000 0x27
#define RTL2832_TUNER_FC0013 0x29
#define RTL2832_TUNER_R820T 0x2a
#define RTL2832_TUNER_R828D 0x2b
+#define RTL2832_TUNER_SI2157 0x2c
u8 tuner;
struct dvb_frontend* (*get_dvb_frontend)(struct i2c_client *);
diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h
index c3a922c37..5dcd3a41d 100644
--- a/drivers/media/dvb-frontends/rtl2832_priv.h
+++ b/drivers/media/dvb-frontends/rtl2832_priv.h
@@ -39,7 +39,7 @@ struct rtl2832_dev {
struct i2c_adapter *i2c_adapter_tuner;
struct dvb_frontend fe;
struct delayed_work stat_work;
- fe_status_t fe_status;
+ enum fe_status fe_status;
u64 post_bit_error_prev; /* for old DVBv3 read_ber() calculation */
u64 post_bit_error;
u64 post_bit_count;
@@ -252,6 +252,30 @@ enum DVBT_REG_BIT_NAME {
DVBT_REG_BIT_NAME_ITEM_TERMINATOR,
};
+static const struct rtl2832_reg_value rtl2832_tuner_init_fc2580[] = {
+ {DVBT_DAGC_TRG_VAL, 0x39},
+ {DVBT_AGC_TARG_VAL_0, 0x0},
+ {DVBT_AGC_TARG_VAL_8_1, 0x5a},
+ {DVBT_AAGC_LOOP_GAIN, 0x16},
+ {DVBT_LOOP_GAIN2_3_0, 0x6},
+ {DVBT_LOOP_GAIN2_4, 0x1},
+ {DVBT_LOOP_GAIN3, 0x16},
+ {DVBT_VTOP1, 0x35},
+ {DVBT_VTOP2, 0x21},
+ {DVBT_VTOP3, 0x21},
+ {DVBT_KRF1, 0x0},
+ {DVBT_KRF2, 0x40},
+ {DVBT_KRF3, 0x10},
+ {DVBT_KRF4, 0x10},
+ {DVBT_IF_AGC_MIN, 0x80},
+ {DVBT_IF_AGC_MAX, 0x7f},
+ {DVBT_RF_AGC_MIN, 0x9c},
+ {DVBT_RF_AGC_MAX, 0x7f},
+ {DVBT_POLAR_RF_AGC, 0x0},
+ {DVBT_POLAR_IF_AGC, 0x0},
+ {DVBT_AD7_SETTING, 0xe9f4},
+};
+
static const struct rtl2832_reg_value rtl2832_tuner_init_tua9001[] = {
{DVBT_DAGC_TRG_VAL, 0x39},
{DVBT_AGC_TARG_VAL_0, 0x0},
@@ -377,4 +401,29 @@ static const struct rtl2832_reg_value rtl2832_tuner_init_r820t[] = {
{DVBT_SPEC_INV, 0x1},
};
+static const struct rtl2832_reg_value rtl2832_tuner_init_si2157[] = {
+ {DVBT_DAGC_TRG_VAL, 0x39},
+ {DVBT_AGC_TARG_VAL_0, 0x0},
+ {DVBT_AGC_TARG_VAL_8_1, 0x40},
+ {DVBT_AAGC_LOOP_GAIN, 0x16},
+ {DVBT_LOOP_GAIN2_3_0, 0x8},
+ {DVBT_LOOP_GAIN2_4, 0x1},
+ {DVBT_LOOP_GAIN3, 0x18},
+ {DVBT_VTOP1, 0x35},
+ {DVBT_VTOP2, 0x21},
+ {DVBT_VTOP3, 0x21},
+ {DVBT_KRF1, 0x0},
+ {DVBT_KRF2, 0x40},
+ {DVBT_KRF3, 0x10},
+ {DVBT_KRF4, 0x10},
+ {DVBT_IF_AGC_MIN, 0x80},
+ {DVBT_IF_AGC_MAX, 0x7f},
+ {DVBT_RF_AGC_MIN, 0x80},
+ {DVBT_RF_AGC_MAX, 0x7f},
+ {DVBT_POLAR_RF_AGC, 0x0},
+ {DVBT_POLAR_IF_AGC, 0x0},
+ {DVBT_AD7_SETTING, 0xe9f4},
+ {DVBT_SPEC_INV, 0x0},
+};
+
#endif /* RTL2832_PRIV_H */
diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c
index 3ff8806ca..7edb885ae 100644
--- a/drivers/media/dvb-frontends/rtl2832_sdr.c
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.c
@@ -39,6 +39,10 @@ static bool rtl2832_sdr_emulated_fmt;
module_param_named(emulated_formats, rtl2832_sdr_emulated_fmt, bool, 0644);
MODULE_PARM_DESC(emulated_formats, "enable emulated formats (disappears in future)");
+/* Original macro does not contain enough null pointer checks for our need */
+#define V4L2_SUBDEV_HAS_OP(sd, o, f) \
+ ((sd) && (sd)->ops && (sd)->ops->o && (sd)->ops->o->f)
+
#define MAX_BULK_BUFS (10)
#define BULK_BUFFER_SIZE (128 * 512)
@@ -108,14 +112,15 @@ struct rtl2832_sdr_frame_buf {
};
struct rtl2832_sdr_dev {
-#define POWER_ON (1 << 1)
-#define URB_BUF (1 << 2)
+#define POWER_ON 0 /* BIT(0) */
+#define URB_BUF 1 /* BIT(1) */
unsigned long flags;
struct platform_device *pdev;
struct video_device vdev;
struct v4l2_device v4l2_dev;
+ struct v4l2_subdev *v4l2_subdev;
/* videobuf2 queue and queued buffers list */
struct vb2_queue vb_queue;
@@ -351,7 +356,7 @@ static int rtl2832_sdr_free_stream_bufs(struct rtl2832_sdr_dev *dev)
{
struct platform_device *pdev = dev->pdev;
- if (dev->flags & USB_STATE_URB_BUF) {
+ if (test_bit(URB_BUF, &dev->flags)) {
while (dev->buf_num) {
dev->buf_num--;
dev_dbg(&pdev->dev, "free buf=%d\n", dev->buf_num);
@@ -360,7 +365,7 @@ static int rtl2832_sdr_free_stream_bufs(struct rtl2832_sdr_dev *dev)
dev->dma_addr[dev->buf_num]);
}
}
- dev->flags &= ~USB_STATE_URB_BUF;
+ clear_bit(URB_BUF, &dev->flags);
return 0;
}
@@ -389,7 +394,7 @@ static int rtl2832_sdr_alloc_stream_bufs(struct rtl2832_sdr_dev *dev)
dev_dbg(&pdev->dev, "alloc buf=%d %p (dma %llu)\n",
dev->buf_num, dev->buf_list[dev->buf_num],
(long long)dev->dma_addr[dev->buf_num]);
- dev->flags |= USB_STATE_URB_BUF;
+ set_bit(URB_BUF, &dev->flags);
}
return 0;
@@ -742,6 +747,29 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev *dev)
ret = rtl2832_sdr_wr_regs(dev, 0x00e, "\xfc", 1);
ret = rtl2832_sdr_wr_regs(dev, 0x011, "\xf4", 1);
break;
+ case RTL2832_SDR_TUNER_FC2580:
+ ret = rtl2832_sdr_wr_regs(dev, 0x112, "\x39", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x102, "\x40", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x103, "\x5a", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x1c7, "\x2c", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x104, "\xcc", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x105, "\xbe", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x1c8, "\x16", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x106, "\x35", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x1c9, "\x21", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x1ca, "\x21", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x1cb, "\x00", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x107, "\x40", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x1cd, "\x10", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x1ce, "\x10", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x108, "\x80", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x109, "\x7f", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x10a, "\x9c", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x10b, "\x7f", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x00e, "\xfc", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x00e, "\xfc", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x011, "\xe9\xf4", 2);
+ break;
default:
dev_notice(&pdev->dev, "Unsupported tuner\n");
}
@@ -832,8 +860,10 @@ static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_dev *dev)
if (!test_bit(POWER_ON, &dev->flags))
return 0;
- if (fe->ops.tuner_ops.set_params)
- fe->ops.tuner_ops.set_params(fe);
+ if (!V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, tuner, s_frequency)) {
+ if (fe->ops.tuner_ops.set_params)
+ fe->ops.tuner_ops.set_params(fe);
+ }
return 0;
};
@@ -891,7 +921,11 @@ static int rtl2832_sdr_start_streaming(struct vb2_queue *vq, unsigned int count)
set_bit(POWER_ON, &dev->flags);
- ret = rtl2832_sdr_set_tuner(dev);
+ /* wake-up tuner */
+ if (V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, core, s_power))
+ ret = v4l2_subdev_call(dev->v4l2_subdev, core, s_power, 1);
+ else
+ ret = rtl2832_sdr_set_tuner(dev);
if (ret)
goto err;
@@ -939,7 +973,12 @@ static void rtl2832_sdr_stop_streaming(struct vb2_queue *vq)
rtl2832_sdr_free_stream_bufs(dev);
rtl2832_sdr_cleanup_queued_bufs(dev);
rtl2832_sdr_unset_adc(dev);
- rtl2832_sdr_unset_tuner(dev);
+
+ /* sleep tuner */
+ if (V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, core, s_power))
+ v4l2_subdev_call(dev->v4l2_subdev, core, s_power, 0);
+ else
+ rtl2832_sdr_unset_tuner(dev);
clear_bit(POWER_ON, &dev->flags);
@@ -968,6 +1007,7 @@ static int rtl2832_sdr_g_tuner(struct file *file, void *priv,
{
struct rtl2832_sdr_dev *dev = video_drvdata(file);
struct platform_device *pdev = dev->pdev;
+ int ret;
dev_dbg(&pdev->dev, "index=%d type=%d\n", v->index, v->type);
@@ -977,17 +1017,21 @@ static int rtl2832_sdr_g_tuner(struct file *file, void *priv,
v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
v->rangelow = 300000;
v->rangehigh = 3200000;
+ ret = 0;
+ } else if (v->index == 1 &&
+ V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, tuner, g_tuner)) {
+ ret = v4l2_subdev_call(dev->v4l2_subdev, tuner, g_tuner, v);
} else if (v->index == 1) {
strlcpy(v->name, "RF: <unknown>", sizeof(v->name));
v->type = V4L2_TUNER_RF;
v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
v->rangelow = 50000000;
v->rangehigh = 2000000000;
+ ret = 0;
} else {
- return -EINVAL;
+ ret = -EINVAL;
}
-
- return 0;
+ return ret;
}
static int rtl2832_sdr_s_tuner(struct file *file, void *priv,
@@ -995,12 +1039,21 @@ static int rtl2832_sdr_s_tuner(struct file *file, void *priv,
{
struct rtl2832_sdr_dev *dev = video_drvdata(file);
struct platform_device *pdev = dev->pdev;
+ int ret;
dev_dbg(&pdev->dev, "\n");
- if (v->index > 1)
- return -EINVAL;
- return 0;
+ if (v->index == 0) {
+ ret = 0;
+ } else if (v->index == 1 &&
+ V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, tuner, s_tuner)) {
+ ret = v4l2_subdev_call(dev->v4l2_subdev, tuner, s_tuner, v);
+ } else if (v->index == 1) {
+ ret = 0;
+ } else {
+ ret = -EINVAL;
+ }
+ return ret;
}
static int rtl2832_sdr_enum_freq_bands(struct file *file, void *priv,
@@ -1008,6 +1061,7 @@ static int rtl2832_sdr_enum_freq_bands(struct file *file, void *priv,
{
struct rtl2832_sdr_dev *dev = video_drvdata(file);
struct platform_device *pdev = dev->pdev;
+ int ret;
dev_dbg(&pdev->dev, "tuner=%d type=%d index=%d\n",
band->tuner, band->type, band->index);
@@ -1017,16 +1071,20 @@ static int rtl2832_sdr_enum_freq_bands(struct file *file, void *priv,
return -EINVAL;
*band = bands_adc[band->index];
+ ret = 0;
+ } else if (band->tuner == 1 &&
+ V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, tuner, enum_freq_bands)) {
+ ret = v4l2_subdev_call(dev->v4l2_subdev, tuner, enum_freq_bands, band);
} else if (band->tuner == 1) {
if (band->index >= ARRAY_SIZE(bands_fm))
return -EINVAL;
*band = bands_fm[band->index];
+ ret = 0;
} else {
- return -EINVAL;
+ ret = -EINVAL;
}
-
- return 0;
+ return ret;
}
static int rtl2832_sdr_g_frequency(struct file *file, void *priv,
@@ -1034,20 +1092,25 @@ static int rtl2832_sdr_g_frequency(struct file *file, void *priv,
{
struct rtl2832_sdr_dev *dev = video_drvdata(file);
struct platform_device *pdev = dev->pdev;
- int ret = 0;
+ int ret;
dev_dbg(&pdev->dev, "tuner=%d type=%d\n", f->tuner, f->type);
if (f->tuner == 0) {
f->frequency = dev->f_adc;
f->type = V4L2_TUNER_ADC;
+ ret = 0;
+ } else if (f->tuner == 1 &&
+ V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, tuner, g_frequency)) {
+ f->type = V4L2_TUNER_RF;
+ ret = v4l2_subdev_call(dev->v4l2_subdev, tuner, g_frequency, f);
} else if (f->tuner == 1) {
f->frequency = dev->f_tuner;
f->type = V4L2_TUNER_RF;
+ ret = 0;
} else {
- return -EINVAL;
+ ret = -EINVAL;
}
-
return ret;
}
@@ -1074,11 +1137,14 @@ static int rtl2832_sdr_s_frequency(struct file *file, void *priv,
band = 2;
dev->f_adc = clamp_t(unsigned int, f->frequency,
- bands_adc[band].rangelow,
- bands_adc[band].rangehigh);
+ bands_adc[band].rangelow,
+ bands_adc[band].rangehigh);
dev_dbg(&pdev->dev, "ADC frequency=%u Hz\n", dev->f_adc);
ret = rtl2832_sdr_set_adc(dev);
+ } else if (f->tuner == 1 &&
+ V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, tuner, s_frequency)) {
+ ret = v4l2_subdev_call(dev->v4l2_subdev, tuner, s_frequency, f);
} else if (f->tuner == 1) {
dev->f_tuner = clamp_t(unsigned int, f->frequency,
bands_fm[0].rangelow,
@@ -1089,7 +1155,6 @@ static int rtl2832_sdr_s_frequency(struct file *file, void *priv,
} else {
ret = -EINVAL;
}
-
return ret;
}
@@ -1329,6 +1394,7 @@ static int rtl2832_sdr_probe(struct platform_device *pdev)
/* setup the state */
subdev = pdata->v4l2_subdev;
+ dev->v4l2_subdev = pdata->v4l2_subdev;
dev->pdev = pdev;
dev->udev = pdata->dvb_usb_device->udev;
dev->f_adc = bands_adc[0].rangelow;
@@ -1388,6 +1454,12 @@ static int rtl2832_sdr_probe(struct platform_device *pdev)
6000000);
v4l2_ctrl_auto_cluster(2, &dev->bandwidth_auto, 0, false);
break;
+ case RTL2832_SDR_TUNER_FC2580:
+ v4l2_ctrl_handler_init(&dev->hdl, 2);
+ if (subdev)
+ v4l2_ctrl_add_handler(&dev->hdl, subdev->ctrl_handler,
+ NULL);
+ break;
default:
v4l2_ctrl_handler_init(&dev->hdl, 0);
dev_err(&pdev->dev, "Unsupported tuner\n");
diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.h b/drivers/media/dvb-frontends/rtl2832_sdr.h
index d2594768b..342ea8486 100644
--- a/drivers/media/dvb-frontends/rtl2832_sdr.h
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.h
@@ -47,6 +47,7 @@ struct rtl2832_sdr_platform_data {
/*
* XXX: This list must be kept sync with dvb_usb_rtl28xxu USB IF driver.
*/
+#define RTL2832_SDR_TUNER_FC2580 0x21
#define RTL2832_SDR_TUNER_TUA9001 0x24
#define RTL2832_SDR_TUNER_FC0012 0x26
#define RTL2832_SDR_TUNER_E4000 0x27
diff --git a/drivers/media/dvb-frontends/s5h1409.c b/drivers/media/dvb-frontends/s5h1409.c
index 5ff474a7f..10964848a 100644
--- a/drivers/media/dvb-frontends/s5h1409.c
+++ b/drivers/media/dvb-frontends/s5h1409.c
@@ -38,7 +38,7 @@ struct s5h1409_state {
struct dvb_frontend frontend;
/* previous uncorrected block counter */
- fe_modulation_t current_modulation;
+ enum fe_modulation current_modulation;
u32 current_frequency;
int if_freq;
@@ -400,7 +400,7 @@ static int s5h1409_set_spectralinversion(struct dvb_frontend *fe, int inverted)
}
static int s5h1409_enable_modulation(struct dvb_frontend *fe,
- fe_modulation_t m)
+ enum fe_modulation m)
{
struct s5h1409_state *state = fe->demodulator_priv;
@@ -755,7 +755,7 @@ static int s5h1409_init(struct dvb_frontend *fe)
return 0;
}
-static int s5h1409_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int s5h1409_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct s5h1409_state *state = fe->demodulator_priv;
u16 reg;
diff --git a/drivers/media/dvb-frontends/s5h1411.c b/drivers/media/dvb-frontends/s5h1411.c
index 64f35fed7..9afc3f422 100644
--- a/drivers/media/dvb-frontends/s5h1411.c
+++ b/drivers/media/dvb-frontends/s5h1411.c
@@ -37,7 +37,7 @@ struct s5h1411_state {
struct dvb_frontend frontend;
- fe_modulation_t current_modulation;
+ enum fe_modulation current_modulation;
unsigned int first_tune:1;
u32 current_frequency;
@@ -484,7 +484,7 @@ static int s5h1411_set_serialmode(struct dvb_frontend *fe, int serial)
}
static int s5h1411_enable_modulation(struct dvb_frontend *fe,
- fe_modulation_t m)
+ enum fe_modulation m)
{
struct s5h1411_state *state = fe->demodulator_priv;
@@ -659,7 +659,7 @@ static int s5h1411_init(struct dvb_frontend *fe)
return 0;
}
-static int s5h1411_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int s5h1411_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct s5h1411_state *state = fe->demodulator_priv;
u16 reg;
diff --git a/drivers/media/dvb-frontends/s5h1420.c b/drivers/media/dvb-frontends/s5h1420.c
index 0b4f8fe6b..9c22a4c70 100644
--- a/drivers/media/dvb-frontends/s5h1420.c
+++ b/drivers/media/dvb-frontends/s5h1420.c
@@ -52,7 +52,7 @@ struct s5h1420_state {
u8 postlocked:1;
u32 fclk;
u32 tunedfreq;
- fe_code_rate_t fec_inner;
+ enum fe_code_rate fec_inner;
u32 symbol_rate;
/* FIXME: ugly workaround for flexcop's incapable i2c-controller
@@ -124,7 +124,8 @@ static int s5h1420_writereg (struct s5h1420_state* state, u8 reg, u8 data)
return 0;
}
-static int s5h1420_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+static int s5h1420_set_voltage(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage)
{
struct s5h1420_state* state = fe->demodulator_priv;
@@ -149,7 +150,8 @@ static int s5h1420_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
return 0;
}
-static int s5h1420_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+static int s5h1420_set_tone(struct dvb_frontend *fe,
+ enum fe_sec_tone_mode tone)
{
struct s5h1420_state* state = fe->demodulator_priv;
@@ -270,7 +272,8 @@ exit:
return result;
}
-static int s5h1420_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
+static int s5h1420_send_burst(struct dvb_frontend *fe,
+ enum fe_sec_mini_cmd minicmd)
{
struct s5h1420_state* state = fe->demodulator_priv;
u8 val;
@@ -307,10 +310,10 @@ static int s5h1420_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minicm
return result;
}
-static fe_status_t s5h1420_get_status_bits(struct s5h1420_state* state)
+static enum fe_status s5h1420_get_status_bits(struct s5h1420_state *state)
{
u8 val;
- fe_status_t status = 0;
+ enum fe_status status = 0;
val = s5h1420_readreg(state, 0x14);
if (val & 0x02)
@@ -328,7 +331,8 @@ static fe_status_t s5h1420_get_status_bits(struct s5h1420_state* state)
return status;
}
-static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int s5h1420_read_status(struct dvb_frontend *fe,
+ enum fe_status *status)
{
struct s5h1420_state* state = fe->demodulator_priv;
u8 val;
@@ -561,27 +565,33 @@ static void s5h1420_setfec_inversion(struct s5h1420_state* state,
} else {
switch (p->fec_inner) {
case FEC_1_2:
- vit08 = 0x01; vit09 = 0x10;
+ vit08 = 0x01;
+ vit09 = 0x10;
break;
case FEC_2_3:
- vit08 = 0x02; vit09 = 0x11;
+ vit08 = 0x02;
+ vit09 = 0x11;
break;
case FEC_3_4:
- vit08 = 0x04; vit09 = 0x12;
+ vit08 = 0x04;
+ vit09 = 0x12;
break;
case FEC_5_6:
- vit08 = 0x08; vit09 = 0x13;
+ vit08 = 0x08;
+ vit09 = 0x13;
break;
case FEC_6_7:
- vit08 = 0x10; vit09 = 0x14;
+ vit08 = 0x10;
+ vit09 = 0x14;
break;
case FEC_7_8:
- vit08 = 0x20; vit09 = 0x15;
+ vit08 = 0x20;
+ vit09 = 0x15;
break;
default:
@@ -595,7 +605,7 @@ static void s5h1420_setfec_inversion(struct s5h1420_state* state,
dprintk("leave %s\n", __func__);
}
-static fe_code_rate_t s5h1420_getfec(struct s5h1420_state* state)
+static enum fe_code_rate s5h1420_getfec(struct s5h1420_state *state)
{
switch(s5h1420_readreg(state, 0x32) & 0x07) {
case 0:
@@ -620,7 +630,8 @@ static fe_code_rate_t s5h1420_getfec(struct s5h1420_state* state)
return FEC_NONE;
}
-static fe_spectral_inversion_t s5h1420_getinversion(struct s5h1420_state* state)
+static enum fe_spectral_inversion
+s5h1420_getinversion(struct s5h1420_state *state)
{
if (s5h1420_readreg(state, 0x32) & 0x08)
return INVERSION_ON;
diff --git a/drivers/media/dvb-frontends/s5h1432.c b/drivers/media/dvb-frontends/s5h1432.c
index 6ec16a243..4215652f8 100644
--- a/drivers/media/dvb-frontends/s5h1432.c
+++ b/drivers/media/dvb-frontends/s5h1432.c
@@ -36,7 +36,7 @@ struct s5h1432_state {
struct dvb_frontend frontend;
- fe_modulation_t current_modulation;
+ enum fe_modulation current_modulation;
unsigned int first_tune:1;
u32 current_frequency;
@@ -302,7 +302,7 @@ static int s5h1432_init(struct dvb_frontend *fe)
return 0;
}
-static int s5h1432_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int s5h1432_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
return 0;
}
diff --git a/drivers/media/dvb-frontends/s921.c b/drivers/media/dvb-frontends/s921.c
index 69862e1fd..b2d9fe13e 100644
--- a/drivers/media/dvb-frontends/s921.c
+++ b/drivers/media/dvb-frontends/s921.c
@@ -348,7 +348,7 @@ static int s921_initfe(struct dvb_frontend *fe)
return 0;
}
-static int s921_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int s921_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct s921_state *state = fe->demodulator_priv;
int regstatus, rc;
@@ -389,7 +389,7 @@ static int s921_read_status(struct dvb_frontend *fe, fe_status_t *status)
static int s921_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
{
- fe_status_t status;
+ enum fe_status status;
struct s921_state *state = fe->demodulator_priv;
int rc;
@@ -449,7 +449,7 @@ static int s921_tune(struct dvb_frontend *fe,
bool re_tune,
unsigned int mode_flags,
unsigned int *delay,
- fe_status_t *status)
+ enum fe_status *status)
{
int rc = 0;
diff --git a/drivers/media/dvb-frontends/s921.h b/drivers/media/dvb-frontends/s921.h
index 7d3999a4e..f5b722d80 100644
--- a/drivers/media/dvb-frontends/s921.h
+++ b/drivers/media/dvb-frontends/s921.h
@@ -36,7 +36,7 @@ static inline struct dvb_frontend *s921_attach(
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-static struct i2c_adapter *
+static inline struct i2c_adapter *
s921_get_tuner_i2c_adapter(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
diff --git a/drivers/media/dvb-frontends/si2165.c b/drivers/media/dvb-frontends/si2165.c
index b1e9b17cc..062063bf5 100644
--- a/drivers/media/dvb-frontends/si2165.c
+++ b/drivers/media/dvb-frontends/si2165.c
@@ -698,7 +698,7 @@ static int si2165_sleep(struct dvb_frontend *fe)
return 0;
}
-static int si2165_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int si2165_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
int ret;
u8 fec_lock = 0;
diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c
index 35a502910..694d57957 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -18,23 +18,53 @@
static const struct dvb_frontend_ops si2168_ops;
+/* Own I2C adapter locking is needed because of I2C gate logic. */
+static int si2168_i2c_master_send_unlocked(const struct i2c_client *client,
+ const char *buf, int count)
+{
+ int ret;
+ struct i2c_msg msg = {
+ .addr = client->addr,
+ .flags = 0,
+ .len = count,
+ .buf = (char *)buf,
+ };
+
+ ret = __i2c_transfer(client->adapter, &msg, 1);
+ return (ret == 1) ? count : ret;
+}
+
+static int si2168_i2c_master_recv_unlocked(const struct i2c_client *client,
+ char *buf, int count)
+{
+ int ret;
+ struct i2c_msg msg = {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = count,
+ .buf = buf,
+ };
+
+ ret = __i2c_transfer(client->adapter, &msg, 1);
+ return (ret == 1) ? count : ret;
+}
+
/* execute firmware command */
-static int si2168_cmd_execute(struct i2c_client *client, struct si2168_cmd *cmd)
+static int si2168_cmd_execute_unlocked(struct i2c_client *client,
+ struct si2168_cmd *cmd)
{
- struct si2168_dev *dev = i2c_get_clientdata(client);
int ret;
unsigned long timeout;
- mutex_lock(&dev->i2c_mutex);
-
if (cmd->wlen) {
/* write cmd and args for firmware */
- ret = i2c_master_send(client, cmd->args, cmd->wlen);
+ ret = si2168_i2c_master_send_unlocked(client, cmd->args,
+ cmd->wlen);
if (ret < 0) {
- goto err_mutex_unlock;
+ goto err;
} else if (ret != cmd->wlen) {
ret = -EREMOTEIO;
- goto err_mutex_unlock;
+ goto err;
}
}
@@ -43,12 +73,13 @@ static int si2168_cmd_execute(struct i2c_client *client, struct si2168_cmd *cmd)
#define TIMEOUT 70
timeout = jiffies + msecs_to_jiffies(TIMEOUT);
while (!time_after(jiffies, timeout)) {
- ret = i2c_master_recv(client, cmd->args, cmd->rlen);
+ ret = si2168_i2c_master_recv_unlocked(client, cmd->args,
+ cmd->rlen);
if (ret < 0) {
- goto err_mutex_unlock;
+ goto err;
} else if (ret != cmd->rlen) {
ret = -EREMOTEIO;
- goto err_mutex_unlock;
+ goto err;
}
/* firmware ready? */
@@ -60,22 +91,36 @@ static int si2168_cmd_execute(struct i2c_client *client, struct si2168_cmd *cmd)
jiffies_to_msecs(jiffies) -
(jiffies_to_msecs(timeout) - TIMEOUT));
+ /* error bit set? */
+ if ((cmd->args[0] >> 6) & 0x01) {
+ ret = -EREMOTEIO;
+ goto err;
+ }
+
if (!((cmd->args[0] >> 7) & 0x01)) {
ret = -ETIMEDOUT;
- goto err_mutex_unlock;
+ goto err;
}
}
- mutex_unlock(&dev->i2c_mutex);
return 0;
-
-err_mutex_unlock:
- mutex_unlock(&dev->i2c_mutex);
+err:
dev_dbg(&client->dev, "failed=%d\n", ret);
return ret;
}
-static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int si2168_cmd_execute(struct i2c_client *client, struct si2168_cmd *cmd)
+{
+ int ret;
+
+ i2c_lock_adapter(client->adapter);
+ ret = si2168_cmd_execute_unlocked(client, cmd);
+ i2c_unlock_adapter(client->adapter);
+
+ return ret;
+}
+
+static int si2168_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct i2c_client *client = fe->demodulator_priv;
struct si2168_dev *dev = i2c_get_clientdata(client);
@@ -508,6 +553,8 @@ static int si2168_init(struct dvb_frontend *fe)
/* set ts mode */
memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6);
cmd.args[4] |= dev->ts_mode;
+ if (dev->ts_clock_gapped)
+ cmd.args[4] |= 0x40;
cmd.wlen = 6;
cmd.rlen = 4;
ret = si2168_cmd_execute(client, &cmd);
@@ -561,60 +608,46 @@ static int si2168_get_tune_settings(struct dvb_frontend *fe,
/*
* I2C gate logic
- * We must use unlocked i2c_transfer() here because I2C lock is already taken
- * by tuner driver.
+ * We must use unlocked I2C I/O because I2C adapter lock is already taken
+ * by the caller (usually tuner driver).
*/
static int si2168_select(struct i2c_adapter *adap, void *mux_priv, u32 chan)
{
struct i2c_client *client = mux_priv;
- struct si2168_dev *dev = i2c_get_clientdata(client);
int ret;
- struct i2c_msg gate_open_msg = {
- .addr = client->addr,
- .flags = 0,
- .len = 3,
- .buf = "\xc0\x0d\x01",
- };
-
- mutex_lock(&dev->i2c_mutex);
+ struct si2168_cmd cmd;
- /* open tuner I2C gate */
- ret = __i2c_transfer(client->adapter, &gate_open_msg, 1);
- if (ret != 1) {
- dev_warn(&client->dev, "i2c write failed=%d\n", ret);
- if (ret >= 0)
- ret = -EREMOTEIO;
- } else {
- ret = 0;
- }
+ /* open I2C gate */
+ memcpy(cmd.args, "\xc0\x0d\x01", 3);
+ cmd.wlen = 3;
+ cmd.rlen = 0;
+ ret = si2168_cmd_execute_unlocked(client, &cmd);
+ if (ret)
+ goto err;
+ return 0;
+err:
+ dev_dbg(&client->dev, "failed=%d\n", ret);
return ret;
}
static int si2168_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan)
{
struct i2c_client *client = mux_priv;
- struct si2168_dev *dev = i2c_get_clientdata(client);
int ret;
- struct i2c_msg gate_close_msg = {
- .addr = client->addr,
- .flags = 0,
- .len = 3,
- .buf = "\xc0\x0d\x00",
- };
-
- /* close tuner I2C gate */
- ret = __i2c_transfer(client->adapter, &gate_close_msg, 1);
- if (ret != 1) {
- dev_warn(&client->dev, "i2c write failed=%d\n", ret);
- if (ret >= 0)
- ret = -EREMOTEIO;
- } else {
- ret = 0;
- }
+ struct si2168_cmd cmd;
- mutex_unlock(&dev->i2c_mutex);
+ /* close I2C gate */
+ memcpy(cmd.args, "\xc0\x0d\x00", 3);
+ cmd.wlen = 3;
+ cmd.rlen = 0;
+ ret = si2168_cmd_execute_unlocked(client, &cmd);
+ if (ret)
+ goto err;
+ return 0;
+err:
+ dev_dbg(&client->dev, "failed=%d\n", ret);
return ret;
}
@@ -671,8 +704,6 @@ static int si2168_probe(struct i2c_client *client,
goto err;
}
- mutex_init(&dev->i2c_mutex);
-
/* create mux i2c adapter for tuner */
dev->adapter = i2c_add_mux_adapter(client->adapter, &client->dev,
client, 0, 0, 0, si2168_select, si2168_deselect);
@@ -688,6 +719,7 @@ static int si2168_probe(struct i2c_client *client,
*config->fe = &dev->fe;
dev->ts_mode = config->ts_mode;
dev->ts_clock_inv = config->ts_clock_inv;
+ dev->ts_clock_gapped = config->ts_clock_gapped;
dev->fw_loaded = false;
i2c_set_clientdata(client, dev);
diff --git a/drivers/media/dvb-frontends/si2168.h b/drivers/media/dvb-frontends/si2168.h
index 70d702ae6..3225d0cc9 100644
--- a/drivers/media/dvb-frontends/si2168.h
+++ b/drivers/media/dvb-frontends/si2168.h
@@ -42,6 +42,9 @@ struct si2168_config {
/* TS clock inverted */
bool ts_clock_inv;
+
+ /* TS clock gapped */
+ bool ts_clock_gapped;
};
#endif
diff --git a/drivers/media/dvb-frontends/si2168_priv.h b/drivers/media/dvb-frontends/si2168_priv.h
index de5b865ba..d06b5bc6d 100644
--- a/drivers/media/dvb-frontends/si2168_priv.h
+++ b/drivers/media/dvb-frontends/si2168_priv.h
@@ -30,14 +30,14 @@
/* state struct */
struct si2168_dev {
struct i2c_adapter *adapter;
- struct mutex i2c_mutex;
struct dvb_frontend fe;
- fe_delivery_system_t delivery_system;
- fe_status_t fe_status;
+ enum fe_delivery_system delivery_system;
+ enum fe_status fe_status;
bool active;
bool fw_loaded;
u8 ts_mode;
bool ts_clock_inv;
+ bool ts_clock_gapped;
};
/* firmware command struct */
diff --git a/drivers/media/dvb-frontends/si21xx.c b/drivers/media/dvb-frontends/si21xx.c
index 16850e2bf..62ad7a7be 100644
--- a/drivers/media/dvb-frontends/si21xx.c
+++ b/drivers/media/dvb-frontends/si21xx.c
@@ -410,7 +410,7 @@ static int si21xx_send_diseqc_msg(struct dvb_frontend *fe,
}
static int si21xx_send_diseqc_burst(struct dvb_frontend *fe,
- fe_sec_mini_cmd_t burst)
+ enum fe_sec_mini_cmd burst)
{
struct si21xx_state *state = fe->demodulator_priv;
u8 val;
@@ -434,7 +434,7 @@ static int si21xx_send_diseqc_burst(struct dvb_frontend *fe,
return 0;
}
/* 30.06.2008 */
-static int si21xx_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+static int si21xx_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)
{
struct si21xx_state *state = fe->demodulator_priv;
u8 val;
@@ -454,7 +454,7 @@ static int si21xx_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
}
}
-static int si21xx_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
+static int si21xx_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage volt)
{
struct si21xx_state *state = fe->demodulator_priv;
@@ -536,7 +536,7 @@ static int si21xx_init(struct dvb_frontend *fe)
}
-static int si21_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int si21_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct si21xx_state *state = fe->demodulator_priv;
u8 regs_read[2];
@@ -641,7 +641,7 @@ static int si21_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
/* initiates a channel acquisition sequence
using the specified symbol rate and code rate */
static int si21xx_setacquire(struct dvb_frontend *fe, int symbrate,
- fe_code_rate_t crate)
+ enum fe_code_rate crate)
{
struct si21xx_state *state = fe->demodulator_priv;
diff --git a/drivers/media/dvb-frontends/sp8870.c b/drivers/media/dvb-frontends/sp8870.c
index bd84c4c68..7a17b3ee1 100644
--- a/drivers/media/dvb-frontends/sp8870.c
+++ b/drivers/media/dvb-frontends/sp8870.c
@@ -344,7 +344,8 @@ static int sp8870_init (struct dvb_frontend* fe)
return 0;
}
-static int sp8870_read_status (struct dvb_frontend* fe, fe_status_t * fe_status)
+static int sp8870_read_status(struct dvb_frontend *fe,
+ enum fe_status *fe_status)
{
struct sp8870_state* state = fe->demodulator_priv;
int status;
diff --git a/drivers/media/dvb-frontends/sp887x.c b/drivers/media/dvb-frontends/sp887x.c
index a6250036c..85015ea3b 100644
--- a/drivers/media/dvb-frontends/sp887x.c
+++ b/drivers/media/dvb-frontends/sp887x.c
@@ -410,7 +410,7 @@ static int sp887x_setup_frontend_parameters(struct dvb_frontend *fe)
return 0;
}
-static int sp887x_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int sp887x_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct sp887x_state* state = fe->demodulator_priv;
u16 snr12 = sp887x_readreg(state, 0xf16);
diff --git a/drivers/media/dvb-frontends/stb0899_drv.c b/drivers/media/dvb-frontends/stb0899_drv.c
index c73899d3a..756650f15 100644
--- a/drivers/media/dvb-frontends/stb0899_drv.c
+++ b/drivers/media/dvb-frontends/stb0899_drv.c
@@ -792,7 +792,8 @@ static int stb0899_wait_diseqc_txidle(struct stb0899_state *state, int timeout)
return 0;
}
-static int stb0899_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst)
+static int stb0899_send_diseqc_burst(struct dvb_frontend *fe,
+ enum fe_sec_mini_cmd burst)
{
struct stb0899_state *state = fe->demodulator_priv;
u8 reg, old_state;
@@ -1178,7 +1179,8 @@ static int stb0899_read_ber(struct dvb_frontend *fe, u32 *ber)
return 0;
}
-static int stb0899_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+static int stb0899_set_voltage(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage)
{
struct stb0899_state *state = fe->demodulator_priv;
@@ -1205,7 +1207,7 @@ static int stb0899_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage
return 0;
}
-static int stb0899_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+static int stb0899_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)
{
struct stb0899_state *state = fe->demodulator_priv;
struct stb0899_internal *internal = &state->internal;
diff --git a/drivers/media/dvb-frontends/stv0288.c b/drivers/media/dvb-frontends/stv0288.c
index 632b25156..c93d9a45f 100644
--- a/drivers/media/dvb-frontends/stv0288.c
+++ b/drivers/media/dvb-frontends/stv0288.c
@@ -44,7 +44,7 @@ struct stv0288_state {
u8 initialised:1;
u32 tuner_frequency;
u32 symbol_rate;
- fe_code_rate_t fec_inner;
+ enum fe_code_rate fec_inner;
int errmode;
};
@@ -134,20 +134,20 @@ static int stv0288_set_symbolrate(struct dvb_frontend *fe, u32 srate)
temp = (unsigned int)srate / 1000;
- temp = temp * 32768;
- temp = temp / 25;
- temp = temp / 125;
- b[0] = (unsigned char)((temp >> 12) & 0xff);
- b[1] = (unsigned char)((temp >> 4) & 0xff);
- b[2] = (unsigned char)((temp << 4) & 0xf0);
- stv0288_writeregI(state, 0x28, 0x80); /* SFRH */
- stv0288_writeregI(state, 0x29, 0); /* SFRM */
- stv0288_writeregI(state, 0x2a, 0); /* SFRL */
-
- stv0288_writeregI(state, 0x28, b[0]);
- stv0288_writeregI(state, 0x29, b[1]);
- stv0288_writeregI(state, 0x2a, b[2]);
- dprintk("stv0288: stv0288_set_symbolrate\n");
+ temp = temp * 32768;
+ temp = temp / 25;
+ temp = temp / 125;
+ b[0] = (unsigned char)((temp >> 12) & 0xff);
+ b[1] = (unsigned char)((temp >> 4) & 0xff);
+ b[2] = (unsigned char)((temp << 4) & 0xf0);
+ stv0288_writeregI(state, 0x28, 0x80); /* SFRH */
+ stv0288_writeregI(state, 0x29, 0); /* SFRM */
+ stv0288_writeregI(state, 0x2a, 0); /* SFRL */
+
+ stv0288_writeregI(state, 0x28, b[0]);
+ stv0288_writeregI(state, 0x29, b[1]);
+ stv0288_writeregI(state, 0x2a, b[2]);
+ dprintk("stv0288: stv0288_set_symbolrate\n");
return 0;
}
@@ -174,7 +174,7 @@ static int stv0288_send_diseqc_msg(struct dvb_frontend *fe,
}
static int stv0288_send_diseqc_burst(struct dvb_frontend *fe,
- fe_sec_mini_cmd_t burst)
+ enum fe_sec_mini_cmd burst)
{
struct stv0288_state *state = fe->demodulator_priv;
@@ -193,7 +193,7 @@ static int stv0288_send_diseqc_burst(struct dvb_frontend *fe,
return 0;
}
-static int stv0288_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+static int stv0288_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)
{
struct stv0288_state *state = fe->demodulator_priv;
@@ -323,7 +323,8 @@ static u8 stv0288_inittab[] = {
0xff, 0xff,
};
-static int stv0288_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
+static int stv0288_set_voltage(struct dvb_frontend *fe,
+ enum fe_sec_voltage volt)
{
dprintk("%s: %s\n", __func__,
volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
@@ -361,7 +362,7 @@ static int stv0288_init(struct dvb_frontend *fe)
return 0;
}
-static int stv0288_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int stv0288_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct stv0288_state *state = fe->demodulator_priv;
diff --git a/drivers/media/dvb-frontends/stv0297.c b/drivers/media/dvb-frontends/stv0297.c
index d40f22616..75b4d8b25 100644
--- a/drivers/media/dvb-frontends/stv0297.c
+++ b/drivers/media/dvb-frontends/stv0297.c
@@ -136,10 +136,10 @@ static u32 stv0297_get_symbolrate(struct stv0297_state *state)
{
u64 tmp;
- tmp = stv0297_readreg(state, 0x55);
- tmp |= stv0297_readreg(state, 0x56) << 8;
- tmp |= stv0297_readreg(state, 0x57) << 16;
- tmp |= stv0297_readreg(state, 0x58) << 24;
+ tmp = (u64)(stv0297_readreg(state, 0x55)
+ | (stv0297_readreg(state, 0x56) << 8)
+ | (stv0297_readreg(state, 0x57) << 16)
+ | (stv0297_readreg(state, 0x58) << 24));
tmp *= STV0297_CLOCK_KHZ;
tmp >>= 32;
@@ -233,7 +233,8 @@ static void stv0297_set_initialdemodfreq(struct stv0297_state *state, long freq)
stv0297_writereg(state, 0x20, tmp);
}
-static int stv0297_set_qam(struct stv0297_state *state, fe_modulation_t modulation)
+static int stv0297_set_qam(struct stv0297_state *state,
+ enum fe_modulation modulation)
{
int val = 0;
@@ -267,7 +268,8 @@ static int stv0297_set_qam(struct stv0297_state *state, fe_modulation_t modulati
return 0;
}
-static int stv0297_set_inversion(struct stv0297_state *state, fe_spectral_inversion_t inversion)
+static int stv0297_set_inversion(struct stv0297_state *state,
+ enum fe_spectral_inversion inversion)
{
int val = 0;
@@ -325,7 +327,8 @@ static int stv0297_sleep(struct dvb_frontend *fe)
return 0;
}
-static int stv0297_read_status(struct dvb_frontend *fe, fe_status_t * status)
+static int stv0297_read_status(struct dvb_frontend *fe,
+ enum fe_status *status)
{
struct stv0297_state *state = fe->demodulator_priv;
@@ -415,7 +418,7 @@ static int stv0297_set_frontend(struct dvb_frontend *fe)
int sweeprate;
int carrieroffset;
unsigned long timeout;
- fe_spectral_inversion_t inversion;
+ enum fe_spectral_inversion inversion;
switch (p->modulation) {
case QAM_16:
diff --git a/drivers/media/dvb-frontends/stv0299.c b/drivers/media/dvb-frontends/stv0299.c
index b57ecf42e..a8177807f 100644
--- a/drivers/media/dvb-frontends/stv0299.c
+++ b/drivers/media/dvb-frontends/stv0299.c
@@ -44,6 +44,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/ktime.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/slab.h>
@@ -61,7 +62,7 @@ struct stv0299_state {
u8 initialised:1;
u32 tuner_frequency;
u32 symbol_rate;
- fe_code_rate_t fec_inner;
+ enum fe_code_rate fec_inner;
int errmode;
u32 ucblocks;
u8 mcr_reg;
@@ -134,7 +135,7 @@ static int stv0299_readregs (struct stv0299_state* state, u8 reg1, u8 *b, u8 len
return ret == 2 ? 0 : ret;
}
-static int stv0299_set_FEC (struct stv0299_state* state, fe_code_rate_t fec)
+static int stv0299_set_FEC(struct stv0299_state *state, enum fe_code_rate fec)
{
dprintk ("%s\n", __func__);
@@ -170,10 +171,10 @@ static int stv0299_set_FEC (struct stv0299_state* state, fe_code_rate_t fec)
}
}
-static fe_code_rate_t stv0299_get_fec (struct stv0299_state* state)
+static enum fe_code_rate stv0299_get_fec(struct stv0299_state *state)
{
- static fe_code_rate_t fec_tab [] = { FEC_2_3, FEC_3_4, FEC_5_6,
- FEC_7_8, FEC_1_2 };
+ static enum fe_code_rate fec_tab[] = { FEC_2_3, FEC_3_4, FEC_5_6,
+ FEC_7_8, FEC_1_2 };
u8 index;
dprintk ("%s\n", __func__);
@@ -302,7 +303,8 @@ static int stv0299_send_diseqc_msg (struct dvb_frontend* fe,
return 0;
}
-static int stv0299_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
+static int stv0299_send_diseqc_burst(struct dvb_frontend *fe,
+ enum fe_sec_mini_cmd burst)
{
struct stv0299_state* state = fe->demodulator_priv;
u8 val;
@@ -329,7 +331,8 @@ static int stv0299_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t
return 0;
}
-static int stv0299_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+static int stv0299_set_tone(struct dvb_frontend *fe,
+ enum fe_sec_tone_mode tone)
{
struct stv0299_state* state = fe->demodulator_priv;
u8 val;
@@ -351,7 +354,8 @@ static int stv0299_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
}
}
-static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+static int stv0299_set_voltage(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage)
{
struct stv0299_state* state = fe->demodulator_priv;
u8 reg0x08;
@@ -404,8 +408,8 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long
u8 lv_mask = 0x40;
u8 last = 1;
int i;
- struct timeval nexttime;
- struct timeval tv[10];
+ ktime_t nexttime;
+ ktime_t tv[10];
reg0x08 = stv0299_readreg (state, 0x08);
reg0x0c = stv0299_readreg (state, 0x0c);
@@ -418,7 +422,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long
if (debug_legacy_dish_switch)
printk ("%s switch command: 0x%04lx\n",__func__, cmd);
- do_gettimeofday (&nexttime);
+ nexttime = ktime_get_real();
if (debug_legacy_dish_switch)
tv[0] = nexttime;
stv0299_writeregI (state, 0x0c, reg0x0c | 0x50); /* set LNB to 18V */
@@ -427,7 +431,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long
for (i=0; i<9; i++) {
if (debug_legacy_dish_switch)
- do_gettimeofday (&tv[i+1]);
+ tv[i+1] = ktime_get_real();
if((cmd & 0x01) != last) {
/* set voltage to (last ? 13V : 18V) */
stv0299_writeregI (state, 0x0c, reg0x0c | (last ? lv_mask : 0x50));
@@ -443,7 +447,8 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long
printk ("%s(%d): switch delay (should be 32k followed by all 8k\n",
__func__, fe->dvb->num);
for (i = 1; i < 10; i++)
- printk ("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
+ printk("%d: %d\n", i,
+ (int) ktime_us_delta(tv[i], tv[i-1]));
}
return 0;
@@ -476,7 +481,8 @@ static int stv0299_init (struct dvb_frontend* fe)
return 0;
}
-static int stv0299_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int stv0299_read_status(struct dvb_frontend *fe,
+ enum fe_status *status)
{
struct stv0299_state* state = fe->demodulator_priv;
diff --git a/drivers/media/dvb-frontends/stv0367.c b/drivers/media/dvb-frontends/stv0367.c
index b31ff265f..ec3e18e5f 100644
--- a/drivers/media/dvb-frontends/stv0367.c
+++ b/drivers/media/dvb-frontends/stv0367.c
@@ -59,7 +59,7 @@ struct stv0367cab_state {
int locked; /* channel found */
u32 freq_khz; /* found frequency (in kHz) */
u32 symbol_rate; /* found symbol rate (in Bds) */
- fe_spectral_inversion_t spect_inv; /* Spectrum Inversion */
+ enum fe_spectral_inversion spect_inv; /* Spectrum Inversion */
};
struct stv0367ter_state {
@@ -67,10 +67,10 @@ struct stv0367ter_state {
enum stv0367_ter_signal_type state;
enum stv0367_ter_if_iq_mode if_iq_mode;
enum stv0367_ter_mode mode;/* mode 2K or 8K */
- fe_guard_interval_t guard;
+ enum fe_guard_interval guard;
enum stv0367_ter_hierarchy hierarchy;
u32 frequency;
- fe_spectral_inversion_t sense; /* current search spectrum */
+ enum fe_spectral_inversion sense; /* current search spectrum */
u8 force; /* force mode/guard */
u8 bw; /* channel width 6, 7 or 8 in MHz */
u8 pBW; /* channel width used during previous lock */
@@ -2074,7 +2074,8 @@ static int stv0367ter_status(struct dvb_frontend *fe)
return locked;
}
#endif
-static int stv0367ter_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int stv0367ter_read_status(struct dvb_frontend *fe,
+ enum fe_status *status)
{
struct stv0367_state *state = fe->demodulator_priv;
@@ -2716,7 +2717,8 @@ static u32 stv0367cab_GetSymbolRate(struct stv0367_state *state, u32 mclk_hz)
return regsym;
}
-static int stv0367cab_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int stv0367cab_read_status(struct dvb_frontend *fe,
+ enum fe_status *status)
{
struct stv0367_state *state = fe->demodulator_priv;
diff --git a/drivers/media/dvb-frontends/stv0367_priv.h b/drivers/media/dvb-frontends/stv0367_priv.h
index 995db0689..89bf6f64b 100644
--- a/drivers/media/dvb-frontends/stv0367_priv.h
+++ b/drivers/media/dvb-frontends/stv0367_priv.h
@@ -188,7 +188,7 @@ struct stv0367_cab_signal_info {
u32 frequency; /* kHz */
u32 symbol_rate; /* Mbds */
enum stv0367cab_mod modulation;
- fe_spectral_inversion_t spect_inv;
+ enum fe_spectral_inversion spect_inv;
s32 Power_dBmx10; /* Power of the RF signal (dBm x 10) */
u32 CN_dBx10; /* Carrier to noise ratio (dB x 10) */
u32 BER; /* Bit error rate (x 10000000) */
diff --git a/drivers/media/dvb-frontends/stv0900_core.c b/drivers/media/dvb-frontends/stv0900_core.c
index 2c88abfab..fe31dd541 100644
--- a/drivers/media/dvb-frontends/stv0900_core.c
+++ b/drivers/media/dvb-frontends/stv0900_core.c
@@ -1744,7 +1744,8 @@ static int stv0900_send_master_cmd(struct dvb_frontend *fe,
state->demod);
}
-static int stv0900_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst)
+static int stv0900_send_burst(struct dvb_frontend *fe,
+ enum fe_sec_mini_cmd burst)
{
struct stv0900_state *state = fe->demodulator_priv;
struct stv0900_internal *intp = state->internal;
@@ -1793,7 +1794,8 @@ static int stv0900_recv_slave_reply(struct dvb_frontend *fe,
return 0;
}
-static int stv0900_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t toneoff)
+static int stv0900_set_tone(struct dvb_frontend *fe,
+ enum fe_sec_tone_mode toneoff)
{
struct stv0900_state *state = fe->demodulator_priv;
struct stv0900_internal *intp = state->internal;
diff --git a/drivers/media/dvb-frontends/stv0900_sw.c b/drivers/media/dvb-frontends/stv0900_sw.c
index a0a7b1664..fa63a9e92 100644
--- a/drivers/media/dvb-frontends/stv0900_sw.c
+++ b/drivers/media/dvb-frontends/stv0900_sw.c
@@ -1556,8 +1556,8 @@ static u32 stv0900_search_srate_fine(struct dvb_frontend *fe)
}
symbcomp = 13 * (coarse_srate / 10);
- coarse_freq = (stv0900_read_reg(intp, CFR2) << 8)
- | stv0900_read_reg(intp, CFR1);
+ coarse_freq = (stv0900_read_reg(intp, CFR2) << 8)
+ | stv0900_read_reg(intp, CFR1);
if (symbcomp < intp->symbol_rate[demod])
coarse_srate = 0;
@@ -2009,7 +2009,7 @@ enum fe_stv0900_signal_type stv0900_algo(struct dvb_frontend *fe)
signal_type = STV0900_NODATA;
no_signal = stv0900_check_signal_presence(intp, demod);
- intp->result[demod].locked = FALSE;
+ intp->result[demod].locked = FALSE;
}
}
diff --git a/drivers/media/dvb-frontends/stv090x.c b/drivers/media/dvb-frontends/stv090x.c
index 0b2a934f5..25bdf6e0f 100644
--- a/drivers/media/dvb-frontends/stv090x.c
+++ b/drivers/media/dvb-frontends/stv090x.c
@@ -3732,7 +3732,7 @@ static int stv090x_read_cnr(struct dvb_frontend *fe, u16 *cnr)
return 0;
}
-static int stv090x_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+static int stv090x_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)
{
struct stv090x_state *state = fe->demodulator_priv;
u32 reg;
@@ -3822,7 +3822,8 @@ err:
return -1;
}
-static int stv090x_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst)
+static int stv090x_send_diseqc_burst(struct dvb_frontend *fe,
+ enum fe_sec_mini_cmd burst)
{
struct stv090x_state *state = fe->demodulator_priv;
u32 reg, idle = 0, fifo_full = 1;
diff --git a/drivers/media/dvb-frontends/stv6110.c b/drivers/media/dvb-frontends/stv6110.c
index b1425830a..91c6dcf65 100644
--- a/drivers/media/dvb-frontends/stv6110.c
+++ b/drivers/media/dvb-frontends/stv6110.c
@@ -158,7 +158,7 @@ static int stv6110_sleep(struct dvb_frontend *fe)
return 0;
}
-static u32 carrier_width(u32 symbol_rate, fe_rolloff_t rolloff)
+static u32 carrier_width(u32 symbol_rate, enum fe_rolloff rolloff)
{
u32 rlf;
diff --git a/drivers/media/dvb-frontends/tc90522.c b/drivers/media/dvb-frontends/tc90522.c
index dce22ce35..456cdc7fb 100644
--- a/drivers/media/dvb-frontends/tc90522.c
+++ b/drivers/media/dvb-frontends/tc90522.c
@@ -130,7 +130,7 @@ static int tc90522t_set_layers(struct dvb_frontend *fe)
/* frontend ops */
-static int tc90522s_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int tc90522s_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct tc90522_state *state;
int ret;
@@ -158,7 +158,7 @@ static int tc90522s_read_status(struct dvb_frontend *fe, fe_status_t *status)
return 0;
}
-static int tc90522t_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int tc90522t_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct tc90522_state *state;
int ret;
@@ -194,7 +194,7 @@ static int tc90522t_read_status(struct dvb_frontend *fe, fe_status_t *status)
return 0;
}
-static const fe_code_rate_t fec_conv_sat[] = {
+static const enum fe_code_rate 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 */
@@ -238,7 +238,10 @@ static int tc90522s_get_frontend(struct dvb_frontend *fe)
c->layer[1].segment_count = 0;
else
c->layer[1].segment_count = val[4] & 0x3f; /* slots */
- /* actually, BPSK if v==1, but not defined in fe_modulation_t */
+ /*
+ * actually, BPSK if v==1, but not defined in
+ * enum fe_modulation
+ */
c->layer[1].modulation = QPSK;
layers = (v > 0) ? 2 : 1;
}
@@ -319,18 +322,18 @@ static int tc90522s_get_frontend(struct dvb_frontend *fe)
}
-static const fe_transmit_mode_t tm_conv[] = {
+static const enum fe_transmit_mode tm_conv[] = {
TRANSMISSION_MODE_2K,
TRANSMISSION_MODE_4K,
TRANSMISSION_MODE_8K,
0
};
-static const fe_code_rate_t fec_conv_ter[] = {
+static const enum fe_code_rate 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[] = {
+static const enum fe_modulation mod_conv[] = {
DQPSK, QPSK, QAM_16, QAM_64, 0, 0, 0, 0
};
diff --git a/drivers/media/dvb-frontends/tda10021.c b/drivers/media/dvb-frontends/tda10021.c
index 1bff7f457..a684424e6 100644
--- a/drivers/media/dvb-frontends/tda10021.c
+++ b/drivers/media/dvb-frontends/tda10021.c
@@ -129,8 +129,8 @@ static int unlock_tuner(struct tda10021_state* state)
return 0;
}
-static int tda10021_setup_reg0 (struct tda10021_state* state, u8 reg0,
- fe_spectral_inversion_t inversion)
+static int tda10021_setup_reg0(struct tda10021_state *state, u8 reg0,
+ enum fe_spectral_inversion inversion)
{
reg0 |= state->reg0 & 0x63;
@@ -258,7 +258,7 @@ static int tda10021_set_parameters(struct dvb_frontend *fe)
}
/*
- * gcc optimizes the code bellow the same way as it would code:
+ * gcc optimizes the code below the same way as it would code:
* "if (qam > 5) return -EINVAL;"
* Yet, the code is clearer, as it shows what QAM standards are
* supported by the driver, and avoids the usage of magic numbers on
@@ -308,7 +308,8 @@ static int tda10021_set_parameters(struct dvb_frontend *fe)
return 0;
}
-static int tda10021_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int tda10021_read_status(struct dvb_frontend *fe,
+ enum fe_status *status)
{
struct tda10021_state* state = fe->demodulator_priv;
int sync;
diff --git a/drivers/media/dvb-frontends/tda10023.c b/drivers/media/dvb-frontends/tda10023.c
index ca1e0d54b..44a556560 100644
--- a/drivers/media/dvb-frontends/tda10023.c
+++ b/drivers/media/dvb-frontends/tda10023.c
@@ -331,7 +331,7 @@ static int tda10023_set_parameters(struct dvb_frontend *fe)
}
/*
- * gcc optimizes the code bellow the same way as it would code:
+ * gcc optimizes the code below the same way as it would code:
* "if (qam > 5) return -EINVAL;"
* Yet, the code is clearer, as it shows what QAM standards are
* supported by the driver, and avoids the usage of magic numbers on
@@ -376,7 +376,8 @@ static int tda10023_set_parameters(struct dvb_frontend *fe)
return 0;
}
-static int tda10023_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int tda10023_read_status(struct dvb_frontend *fe,
+ enum fe_status *status)
{
struct tda10023_state* state = fe->demodulator_priv;
int sync;
diff --git a/drivers/media/dvb-frontends/tda10048.c b/drivers/media/dvb-frontends/tda10048.c
index 919968609..fa6dfb394 100644
--- a/drivers/media/dvb-frontends/tda10048.c
+++ b/drivers/media/dvb-frontends/tda10048.c
@@ -792,7 +792,7 @@ static int tda10048_init(struct dvb_frontend *fe)
return ret;
}
-static int tda10048_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int tda10048_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct tda10048_state *state = fe->demodulator_priv;
u8 reg;
diff --git a/drivers/media/dvb-frontends/tda1004x.c b/drivers/media/dvb-frontends/tda1004x.c
index cfe80e4a9..4f4c8b1e5 100644
--- a/drivers/media/dvb-frontends/tda1004x.c
+++ b/drivers/media/dvb-frontends/tda1004x.c
@@ -642,7 +642,7 @@ static int tda10046_init(struct dvb_frontend* fe)
if (tda10046_fwupload(fe)) {
printk("tda1004x: firmware upload failed\n");
- return -EIO;
+ return -EIO;
}
// tda setup
@@ -997,7 +997,8 @@ static int tda1004x_get_fe(struct dvb_frontend *fe)
return 0;
}
-static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status)
+static int tda1004x_read_status(struct dvb_frontend *fe,
+ enum fe_status *fe_status)
{
struct tda1004x_state* state = fe->demodulator_priv;
int status;
diff --git a/drivers/media/dvb-frontends/tda10071.c b/drivers/media/dvb-frontends/tda10071.c
index c6708d472..3475cbcca 100644
--- a/drivers/media/dvb-frontends/tda10071.c
+++ b/drivers/media/dvb-frontends/tda10071.c
@@ -203,7 +203,7 @@ error:
}
static int tda10071_set_tone(struct dvb_frontend *fe,
- fe_sec_tone_mode_t fe_sec_tone_mode)
+ enum fe_sec_tone_mode fe_sec_tone_mode)
{
struct tda10071_priv *priv = fe->demodulator_priv;
struct tda10071_cmd cmd;
@@ -249,7 +249,7 @@ error:
}
static int tda10071_set_voltage(struct dvb_frontend *fe,
- fe_sec_voltage_t fe_sec_voltage)
+ enum fe_sec_voltage fe_sec_voltage)
{
struct tda10071_priv *priv = fe->demodulator_priv;
struct tda10071_cmd cmd;
@@ -413,7 +413,7 @@ error:
}
static int tda10071_diseqc_send_burst(struct dvb_frontend *fe,
- fe_sec_mini_cmd_t fe_sec_mini_cmd)
+ enum fe_sec_mini_cmd fe_sec_mini_cmd)
{
struct tda10071_priv *priv = fe->demodulator_priv;
struct tda10071_cmd cmd;
@@ -476,7 +476,7 @@ error:
return ret;
}
-static int tda10071_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int tda10071_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct tda10071_priv *priv = fe->demodulator_priv;
int ret;
@@ -668,7 +668,7 @@ static int tda10071_set_frontend(struct dvb_frontend *fe)
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret, i;
u8 mode, rolloff, pilot, inversion, div;
- fe_modulation_t modulation;
+ enum fe_modulation modulation;
dev_dbg(&priv->i2c->dev,
"%s: delivery_system=%d modulation=%d frequency=%d symbol_rate=%d inversion=%d pilot=%d rolloff=%d\n",
@@ -1313,6 +1313,113 @@ static struct dvb_frontend_ops tda10071_ops = {
.set_voltage = tda10071_set_voltage,
};
+static struct dvb_frontend *tda10071_get_dvb_frontend(struct i2c_client *client)
+{
+ struct tda10071_priv *dev = i2c_get_clientdata(client);
+
+ dev_dbg(&client->dev, "\n");
+
+ return &dev->fe;
+}
+
+static int tda10071_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct tda10071_priv *dev;
+ struct tda10071_platform_data *pdata = client->dev.platform_data;
+ int ret;
+ u8 u8tmp;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ dev->client = client;
+ dev->i2c = client->adapter;
+ dev->cfg.demod_i2c_addr = client->addr;
+ dev->cfg.i2c_wr_max = pdata->i2c_wr_max;
+ dev->cfg.ts_mode = pdata->ts_mode;
+ dev->cfg.spec_inv = pdata->spec_inv;
+ dev->cfg.xtal = pdata->clk;
+ dev->cfg.pll_multiplier = pdata->pll_multiplier;
+ dev->cfg.tuner_i2c_addr = pdata->tuner_i2c_addr;
+
+ /* chip ID */
+ ret = tda10071_rd_reg(dev, 0xff, &u8tmp);
+ if (ret)
+ goto err_kfree;
+ if (u8tmp != 0x0f) {
+ ret = -ENODEV;
+ goto err_kfree;
+ }
+
+ /* chip type */
+ ret = tda10071_rd_reg(dev, 0xdd, &u8tmp);
+ if (ret)
+ goto err_kfree;
+ if (u8tmp != 0x00) {
+ ret = -ENODEV;
+ goto err_kfree;
+ }
+
+ /* chip version */
+ ret = tda10071_rd_reg(dev, 0xfe, &u8tmp);
+ if (ret)
+ goto err_kfree;
+ if (u8tmp != 0x01) {
+ ret = -ENODEV;
+ goto err_kfree;
+ }
+
+ /* create dvb_frontend */
+ memcpy(&dev->fe.ops, &tda10071_ops, sizeof(struct dvb_frontend_ops));
+ dev->fe.ops.release = NULL;
+ dev->fe.demodulator_priv = dev;
+ i2c_set_clientdata(client, dev);
+
+ /* setup callbacks */
+ pdata->get_dvb_frontend = tda10071_get_dvb_frontend;
+
+ dev_info(&client->dev, "NXP TDA10071 successfully identified\n");
+ return 0;
+err_kfree:
+ kfree(dev);
+err:
+ dev_dbg(&client->dev, "failed=%d\n", ret);
+ return ret;
+}
+
+static int tda10071_remove(struct i2c_client *client)
+{
+ struct tda10071_dev *dev = i2c_get_clientdata(client);
+
+ dev_dbg(&client->dev, "\n");
+
+ kfree(dev);
+ return 0;
+}
+
+static const struct i2c_device_id tda10071_id_table[] = {
+ {"tda10071_cx24118", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, tda10071_id_table);
+
+static struct i2c_driver tda10071_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "tda10071",
+ .suppress_bind_attrs = true,
+ },
+ .probe = tda10071_probe,
+ .remove = tda10071_remove,
+ .id_table = tda10071_id_table,
+};
+
+module_i2c_driver(tda10071_driver);
+
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
MODULE_DESCRIPTION("NXP TDA10071 DVB-S/S2 demodulator driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/tda10071.h b/drivers/media/dvb-frontends/tda10071.h
index da89f4249..0ffbfa5b2 100644
--- a/drivers/media/dvb-frontends/tda10071.h
+++ b/drivers/media/dvb-frontends/tda10071.h
@@ -24,6 +24,35 @@
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
+/*
+ * I2C address
+ * 0x55,
+ */
+
+/**
+ * struct tda10071_platform_data - Platform data for the tda10071 driver
+ * @clk: Clock frequency.
+ * @i2c_wr_max: Max bytes I2C adapter can write at once.
+ * @ts_mode: TS mode.
+ * @spec_inv: Input spectrum inversion.
+ * @pll_multiplier: PLL multiplier.
+ * @tuner_i2c_addr: CX24118A tuner I2C address (0x14, 0x54, ...).
+ * @get_dvb_frontend: Get DVB frontend.
+ */
+
+struct tda10071_platform_data {
+ u32 clk;
+ u16 i2c_wr_max;
+#define TDA10071_TS_SERIAL 0
+#define TDA10071_TS_PARALLEL 1
+ u8 ts_mode;
+ bool spec_inv;
+ u8 pll_multiplier;
+ u8 tuner_i2c_addr;
+
+ struct dvb_frontend* (*get_dvb_frontend)(struct i2c_client *);
+};
+
struct tda10071_config {
/* Demodulator I2C address.
* Default: none, must set
diff --git a/drivers/media/dvb-frontends/tda10071_priv.h b/drivers/media/dvb-frontends/tda10071_priv.h
index 341662860..a0ea864b3 100644
--- a/drivers/media/dvb-frontends/tda10071_priv.h
+++ b/drivers/media/dvb-frontends/tda10071_priv.h
@@ -28,20 +28,21 @@
struct tda10071_priv {
struct i2c_adapter *i2c;
struct dvb_frontend fe;
+ struct i2c_client *client;
struct tda10071_config cfg;
u8 meas_count[2];
u32 ber;
u32 ucb;
- fe_status_t fe_status;
- fe_delivery_system_t delivery_system;
+ enum fe_status fe_status;
+ enum fe_delivery_system delivery_system;
bool warm; /* FW running */
};
static struct tda10071_modcod {
- fe_delivery_system_t delivery_system;
- fe_modulation_t modulation;
- fe_code_rate_t fec;
+ enum fe_delivery_system delivery_system;
+ enum fe_modulation modulation;
+ enum fe_code_rate fec;
u8 val;
} TDA10071_MODCOD[] = {
/* NBC-QPSK */
diff --git a/drivers/media/dvb-frontends/tda10086.c b/drivers/media/dvb-frontends/tda10086.c
index fcfe2e080..95a33e187 100644
--- a/drivers/media/dvb-frontends/tda10086.c
+++ b/drivers/media/dvb-frontends/tda10086.c
@@ -185,7 +185,8 @@ static void tda10086_diseqc_wait(struct tda10086_state *state)
}
}
-static int tda10086_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+static int tda10086_set_tone(struct dvb_frontend *fe,
+ enum fe_sec_tone_mode tone)
{
struct tda10086_state* state = fe->demodulator_priv;
u8 t22k_off = 0x80;
@@ -238,7 +239,8 @@ static int tda10086_send_master_cmd (struct dvb_frontend* fe,
return 0;
}
-static int tda10086_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
+static int tda10086_send_burst(struct dvb_frontend *fe,
+ enum fe_sec_mini_cmd minicmd)
{
struct tda10086_state* state = fe->demodulator_priv;
u8 oldval = tda10086_read_byte(state, 0x36);
@@ -472,8 +474,8 @@ static int tda10086_get_frontend(struct dvb_frontend *fe)
return -EINVAL;
/* calculate the updated frequency (note: we convert from Hz->kHz) */
- tmp64 = tda10086_read_byte(state, 0x52);
- tmp64 |= (tda10086_read_byte(state, 0x51) << 8);
+ tmp64 = ((u64)tda10086_read_byte(state, 0x52)
+ | (tda10086_read_byte(state, 0x51) << 8));
if (tmp64 & 0x8000)
tmp64 |= 0xffffffffffff0000ULL;
tmp64 = (tmp64 * (SACLK/1000ULL));
@@ -551,7 +553,8 @@ static int tda10086_get_frontend(struct dvb_frontend *fe)
return 0;
}
-static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status)
+static int tda10086_read_status(struct dvb_frontend *fe,
+ enum fe_status *fe_status)
{
struct tda10086_state* state = fe->demodulator_priv;
u8 val;
diff --git a/drivers/media/dvb-frontends/tda8083.c b/drivers/media/dvb-frontends/tda8083.c
index 69e62f42e..796543fa2 100644
--- a/drivers/media/dvb-frontends/tda8083.c
+++ b/drivers/media/dvb-frontends/tda8083.c
@@ -97,7 +97,8 @@ static inline u8 tda8083_readreg (struct tda8083_state* state, u8 reg)
return val;
}
-static int tda8083_set_inversion (struct tda8083_state* state, fe_spectral_inversion_t inversion)
+static int tda8083_set_inversion(struct tda8083_state *state,
+ enum fe_spectral_inversion inversion)
{
/* XXX FIXME: implement other modes than FEC_AUTO */
if (inversion == INVERSION_AUTO)
@@ -106,7 +107,7 @@ static int tda8083_set_inversion (struct tda8083_state* state, fe_spectral_inver
return -EINVAL;
}
-static int tda8083_set_fec (struct tda8083_state* state, fe_code_rate_t fec)
+static int tda8083_set_fec(struct tda8083_state *state, enum fe_code_rate fec)
{
if (fec == FEC_AUTO)
return tda8083_writereg (state, 0x07, 0xff);
@@ -117,11 +118,13 @@ static int tda8083_set_fec (struct tda8083_state* state, fe_code_rate_t fec)
return -EINVAL;
}
-static fe_code_rate_t tda8083_get_fec (struct tda8083_state* state)
+static enum fe_code_rate tda8083_get_fec(struct tda8083_state *state)
{
u8 index;
- static fe_code_rate_t fec_tab [] = { FEC_8_9, FEC_1_2, FEC_2_3, FEC_3_4,
- FEC_4_5, FEC_5_6, FEC_6_7, FEC_7_8 };
+ static enum fe_code_rate fec_tab[] = {
+ FEC_8_9, FEC_1_2, FEC_2_3, FEC_3_4,
+ FEC_4_5, FEC_5_6, FEC_6_7, FEC_7_8
+ };
index = tda8083_readreg(state, 0x0e) & 0x07;
@@ -178,7 +181,8 @@ static void tda8083_wait_diseqc_fifo (struct tda8083_state* state, int timeout)
}
}
-static int tda8083_set_tone (struct tda8083_state* state, fe_sec_tone_mode_t tone)
+static int tda8083_set_tone(struct tda8083_state *state,
+ enum fe_sec_tone_mode tone)
{
tda8083_writereg (state, 0x26, 0xf1);
@@ -192,7 +196,8 @@ static int tda8083_set_tone (struct tda8083_state* state, fe_sec_tone_mode_t ton
}
}
-static int tda8083_set_voltage (struct tda8083_state* state, fe_sec_voltage_t voltage)
+static int tda8083_set_voltage(struct tda8083_state *state,
+ enum fe_sec_voltage voltage)
{
switch (voltage) {
case SEC_VOLTAGE_13:
@@ -204,7 +209,8 @@ static int tda8083_set_voltage (struct tda8083_state* state, fe_sec_voltage_t vo
}
}
-static int tda8083_send_diseqc_burst (struct tda8083_state* state, fe_sec_mini_cmd_t burst)
+static int tda8083_send_diseqc_burst(struct tda8083_state *state,
+ enum fe_sec_mini_cmd burst)
{
switch (burst) {
case SEC_MINI_A:
@@ -222,8 +228,8 @@ static int tda8083_send_diseqc_burst (struct tda8083_state* state, fe_sec_mini_c
return 0;
}
-static int tda8083_send_diseqc_msg (struct dvb_frontend* fe,
- struct dvb_diseqc_master_cmd *m)
+static int tda8083_send_diseqc_msg(struct dvb_frontend *fe,
+ struct dvb_diseqc_master_cmd *m)
{
struct tda8083_state* state = fe->demodulator_priv;
int i;
@@ -240,7 +246,8 @@ static int tda8083_send_diseqc_msg (struct dvb_frontend* fe,
return 0;
}
-static int tda8083_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int tda8083_read_status(struct dvb_frontend *fe,
+ enum fe_status *status)
{
struct tda8083_state* state = fe->demodulator_priv;
@@ -372,7 +379,8 @@ static int tda8083_init(struct dvb_frontend* fe)
return 0;
}
-static int tda8083_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
+static int tda8083_diseqc_send_burst(struct dvb_frontend *fe,
+ enum fe_sec_mini_cmd burst)
{
struct tda8083_state* state = fe->demodulator_priv;
@@ -383,7 +391,8 @@ static int tda8083_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
return 0;
}
-static int tda8083_diseqc_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+static int tda8083_diseqc_set_tone(struct dvb_frontend *fe,
+ enum fe_sec_tone_mode tone)
{
struct tda8083_state* state = fe->demodulator_priv;
@@ -394,7 +403,8 @@ static int tda8083_diseqc_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t t
return 0;
}
-static int tda8083_diseqc_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+static int tda8083_diseqc_set_voltage(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage)
{
struct tda8083_state* state = fe->demodulator_priv;
diff --git a/drivers/media/dvb-frontends/ts2020.c b/drivers/media/dvb-frontends/ts2020.c
index 90164a38c..f61b143a0 100644
--- a/drivers/media/dvb-frontends/ts2020.c
+++ b/drivers/media/dvb-frontends/ts2020.c
@@ -21,23 +21,32 @@
#include "dvb_frontend.h"
#include "ts2020.h"
+#include <linux/regmap.h>
+#include <linux/math64.h>
#define TS2020_XTAL_FREQ 27000 /* in kHz */
#define FREQ_OFFSET_LOW_SYM_RATE 3000
struct ts2020_priv {
+ struct i2c_client *client;
+ struct mutex regmap_mutex;
+ struct regmap_config regmap_config;
+ struct regmap *regmap;
struct dvb_frontend *fe;
+ struct delayed_work stat_work;
+ int (*get_agc_pwm)(struct dvb_frontend *fe, u8 *_agc_pwm);
/* i2c details */
- int i2c_address;
struct i2c_adapter *i2c;
+ int i2c_address;
+ bool loop_through:1;
u8 clk_out:2;
u8 clk_out_div:5;
- u32 frequency;
- u32 frequency_div;
+ bool dont_poll:1;
+ u32 frequency_div; /* LO output divider switch frequency */
+ u32 frequency_khz; /* actual used LO frequency */
#define TS2020_M88TS2020 0
#define TS2020_M88TS2022 1
u8 tuner;
- u8 loop_through:1;
};
struct ts2020_reg_val {
@@ -45,84 +54,23 @@ struct ts2020_reg_val {
u8 val;
};
-static int ts2020_release(struct dvb_frontend *fe)
-{
- kfree(fe->tuner_priv);
- fe->tuner_priv = NULL;
- return 0;
-}
+static void ts2020_stat_work(struct work_struct *work);
-static int ts2020_writereg(struct dvb_frontend *fe, int reg, int data)
+static int ts2020_release(struct dvb_frontend *fe)
{
struct ts2020_priv *priv = fe->tuner_priv;
- u8 buf[] = { reg, data };
- struct i2c_msg msg[] = {
- {
- .addr = priv->i2c_address,
- .flags = 0,
- .buf = buf,
- .len = 2
- }
- };
- int err;
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
-
- err = i2c_transfer(priv->i2c, msg, 1);
- if (err != 1) {
- printk(KERN_ERR
- "%s: writereg error(err == %i, reg == 0x%02x, value == 0x%02x)\n",
- __func__, err, reg, data);
- return -EREMOTEIO;
- }
+ struct i2c_client *client = priv->client;
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
+ dev_dbg(&client->dev, "\n");
+ i2c_unregister_device(client);
return 0;
}
-static int ts2020_readreg(struct dvb_frontend *fe, u8 reg)
-{
- struct ts2020_priv *priv = fe->tuner_priv;
- int ret;
- u8 b0[] = { reg };
- u8 b1[] = { 0 };
- struct i2c_msg msg[] = {
- {
- .addr = priv->i2c_address,
- .flags = 0,
- .buf = b0,
- .len = 1
- }, {
- .addr = priv->i2c_address,
- .flags = I2C_M_RD,
- .buf = b1,
- .len = 1
- }
- };
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
-
- ret = i2c_transfer(priv->i2c, msg, 2);
-
- if (ret != 2) {
- printk(KERN_ERR "%s: reg=0x%x(error=%d)\n",
- __func__, reg, ret);
- return ret;
- }
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
-
- return b1[0];
-}
-
static int ts2020_sleep(struct dvb_frontend *fe)
{
struct ts2020_priv *priv = fe->tuner_priv;
+ int ret;
u8 u8tmp;
if (priv->tuner == TS2020_M88TS2020)
@@ -130,24 +78,32 @@ static int ts2020_sleep(struct dvb_frontend *fe)
else
u8tmp = 0x00;
- return ts2020_writereg(fe, u8tmp, 0x00);
+ ret = regmap_write(priv->regmap, u8tmp, 0x00);
+ if (ret < 0)
+ return ret;
+
+ /* stop statistics polling */
+ if (!priv->dont_poll)
+ cancel_delayed_work_sync(&priv->stat_work);
+ return 0;
}
static int ts2020_init(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct ts2020_priv *priv = fe->tuner_priv;
int i;
u8 u8tmp;
if (priv->tuner == TS2020_M88TS2020) {
- ts2020_writereg(fe, 0x42, 0x73);
- ts2020_writereg(fe, 0x05, priv->clk_out_div);
- ts2020_writereg(fe, 0x20, 0x27);
- ts2020_writereg(fe, 0x07, 0x02);
- ts2020_writereg(fe, 0x11, 0xff);
- ts2020_writereg(fe, 0x60, 0xf9);
- ts2020_writereg(fe, 0x08, 0x01);
- ts2020_writereg(fe, 0x00, 0x41);
+ regmap_write(priv->regmap, 0x42, 0x73);
+ regmap_write(priv->regmap, 0x05, priv->clk_out_div);
+ regmap_write(priv->regmap, 0x20, 0x27);
+ regmap_write(priv->regmap, 0x07, 0x02);
+ regmap_write(priv->regmap, 0x11, 0xff);
+ regmap_write(priv->regmap, 0x60, 0xf9);
+ regmap_write(priv->regmap, 0x08, 0x01);
+ regmap_write(priv->regmap, 0x00, 0x41);
} else {
static const struct ts2020_reg_val reg_vals[] = {
{0x7d, 0x9d},
@@ -163,8 +119,8 @@ static int ts2020_init(struct dvb_frontend *fe)
{0x12, 0xa0},
};
- ts2020_writereg(fe, 0x00, 0x01);
- ts2020_writereg(fe, 0x00, 0x03);
+ regmap_write(priv->regmap, 0x00, 0x01);
+ regmap_write(priv->regmap, 0x00, 0x03);
switch (priv->clk_out) {
case TS2020_CLK_OUT_DISABLED:
@@ -172,7 +128,7 @@ static int ts2020_init(struct dvb_frontend *fe)
break;
case TS2020_CLK_OUT_ENABLED:
u8tmp = 0x70;
- ts2020_writereg(fe, 0x05, priv->clk_out_div);
+ regmap_write(priv->regmap, 0x05, priv->clk_out_div);
break;
case TS2020_CLK_OUT_ENABLED_XTALOUT:
u8tmp = 0x6c;
@@ -182,50 +138,61 @@ static int ts2020_init(struct dvb_frontend *fe)
break;
}
- ts2020_writereg(fe, 0x42, u8tmp);
+ regmap_write(priv->regmap, 0x42, u8tmp);
if (priv->loop_through)
u8tmp = 0xec;
else
u8tmp = 0x6c;
- ts2020_writereg(fe, 0x62, u8tmp);
+ regmap_write(priv->regmap, 0x62, u8tmp);
for (i = 0; i < ARRAY_SIZE(reg_vals); i++)
- ts2020_writereg(fe, reg_vals[i].reg, reg_vals[i].val);
+ regmap_write(priv->regmap, reg_vals[i].reg,
+ reg_vals[i].val);
}
+ /* Initialise v5 stats here */
+ c->strength.len = 1;
+ c->strength.stat[0].scale = FE_SCALE_DECIBEL;
+ c->strength.stat[0].uvalue = 0;
+
+ /* Start statistics polling by invoking the work function */
+ ts2020_stat_work(&priv->stat_work.work);
return 0;
}
static int ts2020_tuner_gate_ctrl(struct dvb_frontend *fe, u8 offset)
{
+ struct ts2020_priv *priv = fe->tuner_priv;
int ret;
- ret = ts2020_writereg(fe, 0x51, 0x1f - offset);
- ret |= ts2020_writereg(fe, 0x51, 0x1f);
- ret |= ts2020_writereg(fe, 0x50, offset);
- ret |= ts2020_writereg(fe, 0x50, 0x00);
+ ret = regmap_write(priv->regmap, 0x51, 0x1f - offset);
+ ret |= regmap_write(priv->regmap, 0x51, 0x1f);
+ ret |= regmap_write(priv->regmap, 0x50, offset);
+ ret |= regmap_write(priv->regmap, 0x50, 0x00);
msleep(20);
return ret;
}
static int ts2020_set_tuner_rf(struct dvb_frontend *fe)
{
- int reg;
-
- reg = ts2020_readreg(fe, 0x3d);
- reg &= 0x7f;
- if (reg < 0x16)
- reg = 0xa1;
- else if (reg == 0x16)
- reg = 0x99;
+ struct ts2020_priv *dev = fe->tuner_priv;
+ int ret;
+ unsigned int utmp;
+
+ ret = regmap_read(dev->regmap, 0x3d, &utmp);
+ utmp &= 0x7f;
+ if (utmp < 0x16)
+ utmp = 0xa1;
+ else if (utmp == 0x16)
+ utmp = 0x99;
else
- reg = 0xf9;
+ utmp = 0xf9;
- ts2020_writereg(fe, 0x60, reg);
- reg = ts2020_tuner_gate_ctrl(fe, 0x08);
+ regmap_write(dev->regmap, 0x60, utmp);
+ ret = ts2020_tuner_gate_ctrl(fe, 0x08);
- return reg;
+ return ret;
}
static int ts2020_set_params(struct dvb_frontend *fe)
@@ -233,45 +200,62 @@ static int ts2020_set_params(struct dvb_frontend *fe)
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct ts2020_priv *priv = fe->tuner_priv;
int ret;
- u32 frequency = c->frequency;
- s32 offset_khz;
- u32 symbol_rate = (c->symbol_rate / 1000);
+ unsigned int utmp;
u32 f3db, gdiv28;
- u16 value, ndiv, lpf_coeff;
- u8 lpf_mxdiv, mlpf_max, mlpf_min, nlpf;
- u8 lo = 0x01, div4 = 0x0;
-
- /* Calculate frequency divider */
- if (frequency < priv->frequency_div) {
- lo |= 0x10;
- div4 = 0x1;
- ndiv = (frequency * 14 * 4) / TS2020_XTAL_FREQ;
- } else
- ndiv = (frequency * 14 * 2) / TS2020_XTAL_FREQ;
- ndiv = ndiv + ndiv % 2;
- ndiv = ndiv - 1024;
+ u16 u16tmp, value, lpf_coeff;
+ u8 buf[3], reg10, lpf_mxdiv, mlpf_max, mlpf_min, nlpf;
+ unsigned int f_ref_khz, f_vco_khz, div_ref, div_out, pll_n;
+ unsigned int frequency_khz = c->frequency;
+
+ /*
+ * Integer-N PLL synthesizer
+ * kHz is used for all calculations to keep calculations within 32-bit
+ */
+ f_ref_khz = TS2020_XTAL_FREQ;
+ div_ref = DIV_ROUND_CLOSEST(f_ref_khz, 2000);
+
+ /* select LO output divider */
+ if (frequency_khz < priv->frequency_div) {
+ div_out = 4;
+ reg10 = 0x10;
+ } else {
+ div_out = 2;
+ reg10 = 0x00;
+ }
+
+ f_vco_khz = frequency_khz * div_out;
+ pll_n = f_vco_khz * div_ref / f_ref_khz;
+ pll_n += pll_n % 2;
+ priv->frequency_khz = pll_n * f_ref_khz / div_ref / div_out;
+
+ pr_debug("frequency=%u offset=%d f_vco_khz=%u pll_n=%u div_ref=%u div_out=%u\n",
+ priv->frequency_khz, priv->frequency_khz - c->frequency,
+ f_vco_khz, pll_n, div_ref, div_out);
if (priv->tuner == TS2020_M88TS2020) {
lpf_coeff = 2766;
- ret = ts2020_writereg(fe, 0x10, 0x80 | lo);
+ reg10 |= 0x01;
+ ret = regmap_write(priv->regmap, 0x10, reg10);
} else {
lpf_coeff = 3200;
- ret = ts2020_writereg(fe, 0x10, 0x0b);
- ret |= ts2020_writereg(fe, 0x11, 0x40);
+ reg10 |= 0x0b;
+ ret = regmap_write(priv->regmap, 0x10, reg10);
+ ret |= regmap_write(priv->regmap, 0x11, 0x40);
}
- /* Set frequency divider */
- ret |= ts2020_writereg(fe, 0x01, (ndiv >> 8) & 0xf);
- ret |= ts2020_writereg(fe, 0x02, ndiv & 0xff);
+ u16tmp = pll_n - 1024;
+ buf[0] = (u16tmp >> 8) & 0xff;
+ buf[1] = (u16tmp >> 0) & 0xff;
+ buf[2] = div_ref - 8;
+
+ ret |= regmap_write(priv->regmap, 0x01, buf[0]);
+ ret |= regmap_write(priv->regmap, 0x02, buf[1]);
+ ret |= regmap_write(priv->regmap, 0x03, buf[2]);
- ret |= ts2020_writereg(fe, 0x03, 0x06);
ret |= ts2020_tuner_gate_ctrl(fe, 0x10);
if (ret < 0)
return -ENODEV;
- /* Tuner Frequency Range */
- ret = ts2020_writereg(fe, 0x10, lo);
-
ret |= ts2020_tuner_gate_ctrl(fe, 0x08);
/* Tuner RF */
@@ -279,28 +263,26 @@ static int ts2020_set_params(struct dvb_frontend *fe)
ret |= ts2020_set_tuner_rf(fe);
gdiv28 = (TS2020_XTAL_FREQ / 1000 * 1694 + 500) / 1000;
- ret |= ts2020_writereg(fe, 0x04, gdiv28 & 0xff);
+ ret |= regmap_write(priv->regmap, 0x04, gdiv28 & 0xff);
ret |= ts2020_tuner_gate_ctrl(fe, 0x04);
if (ret < 0)
return -ENODEV;
if (priv->tuner == TS2020_M88TS2022) {
- ret = ts2020_writereg(fe, 0x25, 0x00);
- ret |= ts2020_writereg(fe, 0x27, 0x70);
- ret |= ts2020_writereg(fe, 0x41, 0x09);
- ret |= ts2020_writereg(fe, 0x08, 0x0b);
+ ret = regmap_write(priv->regmap, 0x25, 0x00);
+ ret |= regmap_write(priv->regmap, 0x27, 0x70);
+ ret |= regmap_write(priv->regmap, 0x41, 0x09);
+ ret |= regmap_write(priv->regmap, 0x08, 0x0b);
if (ret < 0)
return -ENODEV;
}
- value = ts2020_readreg(fe, 0x26);
+ regmap_read(priv->regmap, 0x26, &utmp);
+ value = utmp;
- f3db = (symbol_rate * 135) / 200 + 2000;
- f3db += FREQ_OFFSET_LOW_SYM_RATE;
- if (f3db < 7000)
- f3db = 7000;
- if (f3db > 40000)
- f3db = 40000;
+ f3db = (c->bandwidth_hz / 1000 / 2) + 2000;
+ f3db += FREQ_OFFSET_LOW_SYM_RATE; /* FIXME: ~always too wide filter */
+ f3db = clamp(f3db, 7000U, 40000U);
gdiv28 = gdiv28 * 207 / (value * 2 + 151);
mlpf_max = gdiv28 * 135 / 100;
@@ -327,19 +309,14 @@ static int ts2020_set_params(struct dvb_frontend *fe)
if (lpf_mxdiv > mlpf_max)
lpf_mxdiv = mlpf_max;
- ret = ts2020_writereg(fe, 0x04, lpf_mxdiv);
- ret |= ts2020_writereg(fe, 0x06, nlpf);
+ ret = regmap_write(priv->regmap, 0x04, lpf_mxdiv);
+ ret |= regmap_write(priv->regmap, 0x06, nlpf);
ret |= ts2020_tuner_gate_ctrl(fe, 0x04);
ret |= ts2020_tuner_gate_ctrl(fe, 0x01);
msleep(80);
- /* calculate offset assuming 96000kHz*/
- offset_khz = (ndiv - ndiv % 2 + 1024) * TS2020_XTAL_FREQ
- / (6 + 8) / (div4 + 1) / 2;
-
- priv->frequency = offset_khz;
return (ret < 0) ? -EINVAL : 0;
}
@@ -347,8 +324,8 @@ static int ts2020_set_params(struct dvb_frontend *fe)
static int ts2020_get_frequency(struct dvb_frontend *fe, u32 *frequency)
{
struct ts2020_priv *priv = fe->tuner_priv;
- *frequency = priv->frequency;
+ *frequency = priv->frequency_khz;
return 0;
}
@@ -358,28 +335,164 @@ static int ts2020_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
return 0;
}
-/* read TS2020 signal strength */
-static int ts2020_read_signal_strength(struct dvb_frontend *fe,
- u16 *signal_strength)
+/*
+ * Get the tuner gain.
+ * @fe: The front end for which we're determining the gain
+ * @v_agc: The voltage of the AGC from the demodulator (0-2600mV)
+ * @_gain: Where to store the gain (in 0.001dB units)
+ *
+ * Returns 0 or a negative error code.
+ */
+static int ts2020_read_tuner_gain(struct dvb_frontend *fe, unsigned v_agc,
+ __s64 *_gain)
+{
+ struct ts2020_priv *priv = fe->tuner_priv;
+ unsigned long gain1, gain2, gain3;
+ unsigned utmp;
+ int ret;
+
+ /* Read the RF gain */
+ ret = regmap_read(priv->regmap, 0x3d, &utmp);
+ if (ret < 0)
+ return ret;
+ gain1 = utmp & 0x1f;
+
+ /* Read the baseband gain */
+ ret = regmap_read(priv->regmap, 0x21, &utmp);
+ if (ret < 0)
+ return ret;
+ gain2 = utmp & 0x1f;
+
+ switch (priv->tuner) {
+ case TS2020_M88TS2020:
+ gain1 = clamp_t(long, gain1, 0, 15);
+ gain2 = clamp_t(long, gain2, 0, 13);
+ v_agc = clamp_t(long, v_agc, 400, 1100);
+
+ *_gain = -(gain1 * 2330 +
+ gain2 * 3500 +
+ v_agc * 24 / 10 * 10 +
+ 10000);
+ /* gain in range -19600 to -116850 in units of 0.001dB */
+ break;
+
+ case TS2020_M88TS2022:
+ ret = regmap_read(priv->regmap, 0x66, &utmp);
+ if (ret < 0)
+ return ret;
+ gain3 = (utmp >> 3) & 0x07;
+
+ gain1 = clamp_t(long, gain1, 0, 15);
+ gain2 = clamp_t(long, gain2, 2, 16);
+ gain3 = clamp_t(long, gain3, 0, 6);
+ v_agc = clamp_t(long, v_agc, 600, 1600);
+
+ *_gain = -(gain1 * 2650 +
+ gain2 * 3380 +
+ gain3 * 2850 +
+ v_agc * 176 / 100 * 10 -
+ 30000);
+ /* gain in range -47320 to -158950 in units of 0.001dB */
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * Get the AGC information from the demodulator and use that to calculate the
+ * tuner gain.
+ */
+static int ts2020_get_tuner_gain(struct dvb_frontend *fe, __s64 *_gain)
{
- u16 sig_reading, sig_strength;
- u8 rfgain, bbgain;
+ struct ts2020_priv *priv = fe->tuner_priv;
+ int v_agc = 0, ret;
+ u8 agc_pwm;
- rfgain = ts2020_readreg(fe, 0x3d) & 0x1f;
- bbgain = ts2020_readreg(fe, 0x21) & 0x1f;
+ /* Read the AGC PWM rate from the demodulator */
+ if (priv->get_agc_pwm) {
+ ret = priv->get_agc_pwm(fe, &agc_pwm);
+ if (ret < 0)
+ return ret;
- if (rfgain > 15)
- rfgain = 15;
- if (bbgain > 13)
- bbgain = 13;
+ switch (priv->tuner) {
+ case TS2020_M88TS2020:
+ v_agc = (int)agc_pwm * 20 - 1166;
+ break;
+ case TS2020_M88TS2022:
+ v_agc = (int)agc_pwm * 16 - 670;
+ break;
+ }
- sig_reading = rfgain * 2 + bbgain * 3;
+ if (v_agc < 0)
+ v_agc = 0;
+ }
- sig_strength = 40 + (64 - sig_reading) * 50 / 64 ;
+ return ts2020_read_tuner_gain(fe, v_agc, _gain);
+}
- /* cook the value to be suitable for szap-s2 human readable output */
- *signal_strength = sig_strength * 1000;
+/*
+ * Gather statistics on a regular basis
+ */
+static void ts2020_stat_work(struct work_struct *work)
+{
+ struct ts2020_priv *priv = container_of(work, struct ts2020_priv,
+ stat_work.work);
+ struct i2c_client *client = priv->client;
+ struct dtv_frontend_properties *c = &priv->fe->dtv_property_cache;
+ int ret;
+
+ dev_dbg(&client->dev, "\n");
+
+ ret = ts2020_get_tuner_gain(priv->fe, &c->strength.stat[0].svalue);
+ if (ret < 0)
+ goto err;
+ c->strength.stat[0].scale = FE_SCALE_DECIBEL;
+
+ if (!priv->dont_poll)
+ schedule_delayed_work(&priv->stat_work, msecs_to_jiffies(2000));
+ return;
+err:
+ dev_dbg(&client->dev, "failed=%d\n", ret);
+}
+
+/*
+ * Read TS2020 signal strength in v3 format.
+ */
+static int ts2020_read_signal_strength(struct dvb_frontend *fe,
+ u16 *_signal_strength)
+{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ struct ts2020_priv *priv = fe->tuner_priv;
+ unsigned strength;
+ __s64 gain;
+
+ if (priv->dont_poll)
+ ts2020_stat_work(&priv->stat_work.work);
+
+ if (c->strength.stat[0].scale == FE_SCALE_NOT_AVAILABLE) {
+ *_signal_strength = 0;
+ return 0;
+ }
+
+ gain = c->strength.stat[0].svalue;
+
+ /* Calculate the signal strength based on the total gain of the tuner */
+ if (gain < -85000)
+ /* 0%: no signal or weak signal */
+ strength = 0;
+ else if (gain < -65000)
+ /* 0% - 60%: weak signal */
+ strength = 0 + div64_s64((85000 + gain) * 3, 1000);
+ else if (gain < -45000)
+ /* 60% - 90%: normal signal */
+ strength = 60 + div64_s64((65000 + gain) * 3, 2000);
+ else
+ /* 90% - 99%: strong signal */
+ strength = 90 + div64_s64((45000 + gain), 5000);
+
+ *_signal_strength = strength * 65535 / 100;
return 0;
}
@@ -402,53 +515,50 @@ struct dvb_frontend *ts2020_attach(struct dvb_frontend *fe,
const struct ts2020_config *config,
struct i2c_adapter *i2c)
{
- struct ts2020_priv *priv = NULL;
- u8 buf;
-
- priv = kzalloc(sizeof(struct ts2020_priv), GFP_KERNEL);
- if (priv == NULL)
+ struct i2c_client *client;
+ struct i2c_board_info board_info;
+
+ /* This is only used by ts2020_probe() so can be on the stack */
+ struct ts2020_config pdata;
+
+ memcpy(&pdata, config, sizeof(pdata));
+ pdata.fe = fe;
+ pdata.attach_in_use = true;
+
+ memset(&board_info, 0, sizeof(board_info));
+ strlcpy(board_info.type, "ts2020", I2C_NAME_SIZE);
+ board_info.addr = config->tuner_address;
+ board_info.platform_data = &pdata;
+ client = i2c_new_device(i2c, &board_info);
+ if (!client || !client->dev.driver)
return NULL;
- priv->i2c_address = config->tuner_address;
- priv->i2c = i2c;
- priv->clk_out = config->clk_out;
- priv->clk_out_div = config->clk_out_div;
- priv->frequency_div = config->frequency_div;
- priv->fe = fe;
- fe->tuner_priv = priv;
-
- if (!priv->frequency_div)
- priv->frequency_div = 1060000;
-
- /* Wake Up the tuner */
- if ((0x03 & ts2020_readreg(fe, 0x00)) == 0x00) {
- ts2020_writereg(fe, 0x00, 0x01);
- msleep(2);
- }
+ return fe;
+}
+EXPORT_SYMBOL(ts2020_attach);
- ts2020_writereg(fe, 0x00, 0x03);
- msleep(2);
-
- /* Check the tuner version */
- buf = ts2020_readreg(fe, 0x00);
- if ((buf == 0x01) || (buf == 0x41) || (buf == 0x81)) {
- printk(KERN_INFO "%s: Find tuner TS2020!\n", __func__);
- priv->tuner = TS2020_M88TS2020;
- } else if ((buf == 0x83) || (buf == 0xc3)) {
- printk(KERN_INFO "%s: Find tuner TS2022!\n", __func__);
- priv->tuner = TS2020_M88TS2022;
- } else {
- printk(KERN_ERR "%s: Read tuner reg[0] = %d\n", __func__, buf);
- kfree(priv);
- return NULL;
- }
+/*
+ * We implement own regmap locking due to legacy DVB attach which uses frontend
+ * gate control callback to control I2C bus access. We can open / close gate and
+ * serialize whole open / I2C-operation / close sequence at the same.
+ */
+static void ts2020_regmap_lock(void *__dev)
+{
+ struct ts2020_priv *dev = __dev;
- memcpy(&fe->ops.tuner_ops, &ts2020_tuner_ops,
- sizeof(struct dvb_tuner_ops));
+ mutex_lock(&dev->regmap_mutex);
+ if (dev->fe->ops.i2c_gate_ctrl)
+ dev->fe->ops.i2c_gate_ctrl(dev->fe, 1);
+}
- return fe;
+static void ts2020_regmap_unlock(void *__dev)
+{
+ struct ts2020_priv *dev = __dev;
+
+ if (dev->fe->ops.i2c_gate_ctrl)
+ dev->fe->ops.i2c_gate_ctrl(dev->fe, 0);
+ mutex_unlock(&dev->regmap_mutex);
}
-EXPORT_SYMBOL(ts2020_attach);
static int ts2020_probe(struct i2c_client *client,
const struct i2c_device_id *id)
@@ -467,38 +577,54 @@ static int ts2020_probe(struct i2c_client *client,
goto err;
}
+ /* create regmap */
+ mutex_init(&dev->regmap_mutex);
+ dev->regmap_config.reg_bits = 8,
+ dev->regmap_config.val_bits = 8,
+ dev->regmap_config.lock = ts2020_regmap_lock,
+ dev->regmap_config.unlock = ts2020_regmap_unlock,
+ dev->regmap_config.lock_arg = dev,
+ dev->regmap = regmap_init_i2c(client, &dev->regmap_config);
+ if (IS_ERR(dev->regmap)) {
+ ret = PTR_ERR(dev->regmap);
+ goto err_kfree;
+ }
+
dev->i2c = client->adapter;
dev->i2c_address = client->addr;
+ dev->loop_through = pdata->loop_through;
dev->clk_out = pdata->clk_out;
dev->clk_out_div = pdata->clk_out_div;
+ dev->dont_poll = pdata->dont_poll;
dev->frequency_div = pdata->frequency_div;
dev->fe = fe;
+ dev->get_agc_pwm = pdata->get_agc_pwm;
fe->tuner_priv = dev;
+ dev->client = client;
+ INIT_DELAYED_WORK(&dev->stat_work, ts2020_stat_work);
/* check if the tuner is there */
- ret = ts2020_readreg(fe, 0x00);
- if (ret < 0)
- goto err;
- utmp = ret;
+ ret = regmap_read(dev->regmap, 0x00, &utmp);
+ if (ret)
+ goto err_regmap_exit;
if ((utmp & 0x03) == 0x00) {
- ret = ts2020_writereg(fe, 0x00, 0x01);
+ ret = regmap_write(dev->regmap, 0x00, 0x01);
if (ret)
- goto err;
+ goto err_regmap_exit;
usleep_range(2000, 50000);
}
- ret = ts2020_writereg(fe, 0x00, 0x03);
+ ret = regmap_write(dev->regmap, 0x00, 0x03);
if (ret)
- goto err;
+ goto err_regmap_exit;
usleep_range(2000, 50000);
- ret = ts2020_readreg(fe, 0x00);
- if (ret < 0)
- goto err;
- utmp = ret;
+ ret = regmap_read(dev->regmap, 0x00, &utmp);
+ if (ret)
+ goto err_regmap_exit;
dev_dbg(&client->dev, "chip_id=%02x\n", utmp);
@@ -520,7 +646,7 @@ static int ts2020_probe(struct i2c_client *client,
break;
default:
ret = -ENODEV;
- goto err;
+ goto err_regmap_exit;
}
if (dev->tuner == TS2020_M88TS2022) {
@@ -530,63 +656,64 @@ static int ts2020_probe(struct i2c_client *client,
break;
case TS2020_CLK_OUT_ENABLED:
u8tmp = 0x70;
- ret = ts2020_writereg(fe, 0x05, dev->clk_out_div);
+ ret = regmap_write(dev->regmap, 0x05, dev->clk_out_div);
if (ret)
- goto err;
+ goto err_regmap_exit;
break;
case TS2020_CLK_OUT_ENABLED_XTALOUT:
u8tmp = 0x6c;
break;
default:
ret = -EINVAL;
- goto err;
+ goto err_regmap_exit;
}
- ret = ts2020_writereg(fe, 0x42, u8tmp);
+ ret = regmap_write(dev->regmap, 0x42, u8tmp);
if (ret)
- goto err;
+ goto err_regmap_exit;
if (dev->loop_through)
u8tmp = 0xec;
else
u8tmp = 0x6c;
- ret = ts2020_writereg(fe, 0x62, u8tmp);
+ ret = regmap_write(dev->regmap, 0x62, u8tmp);
if (ret)
- goto err;
+ goto err_regmap_exit;
}
/* sleep */
- ret = ts2020_writereg(fe, 0x00, 0x00);
+ ret = regmap_write(dev->regmap, 0x00, 0x00);
if (ret)
- goto err;
+ goto err_regmap_exit;
dev_info(&client->dev,
"Montage Technology %s successfully identified\n", chip_str);
memcpy(&fe->ops.tuner_ops, &ts2020_tuner_ops,
sizeof(struct dvb_tuner_ops));
- fe->ops.tuner_ops.release = NULL;
+ if (!pdata->attach_in_use)
+ fe->ops.tuner_ops.release = NULL;
i2c_set_clientdata(client, dev);
return 0;
+err_regmap_exit:
+ regmap_exit(dev->regmap);
+err_kfree:
+ kfree(dev);
err:
dev_dbg(&client->dev, "failed=%d\n", ret);
- kfree(dev);
return ret;
}
static int ts2020_remove(struct i2c_client *client)
{
struct ts2020_priv *dev = i2c_get_clientdata(client);
- struct dvb_frontend *fe = dev->fe;
dev_dbg(&client->dev, "\n");
- memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
- fe->tuner_priv = NULL;
+ regmap_exit(dev->regmap);
kfree(dev);
-
return 0;
}
diff --git a/drivers/media/dvb-frontends/ts2020.h b/drivers/media/dvb-frontends/ts2020.h
index 1714af94e..9220e5cf0 100644
--- a/drivers/media/dvb-frontends/ts2020.h
+++ b/drivers/media/dvb-frontends/ts2020.h
@@ -32,7 +32,7 @@ struct ts2020_config {
/*
* RF loop-through
*/
- u8 loop_through:1;
+ bool loop_through:1;
/*
* clock output
@@ -48,14 +48,27 @@ struct ts2020_config {
*/
u8 clk_out_div:5;
+ /* Set to true to suppress stat polling */
+ bool dont_poll:1;
+
/*
* pointer to DVB frontend
*/
struct dvb_frontend *fe;
+
+ /*
+ * driver private, do not set value
+ */
+ u8 attach_in_use:1;
+
+ /* Operation to be called by the ts2020 driver to get the value of the
+ * AGC PWM tuner input as theoretically output by the demodulator.
+ */
+ int (*get_agc_pwm)(struct dvb_frontend *fe, u8 *_agc_pwm);
};
+/* Do not add new ts2020_attach() users! Use I2C bindings instead. */
#if IS_REACHABLE(CONFIG_DVB_TS2020)
-
extern struct dvb_frontend *ts2020_attach(
struct dvb_frontend *fe,
const struct ts2020_config *config,
diff --git a/drivers/media/dvb-frontends/ves1820.c b/drivers/media/dvb-frontends/ves1820.c
index bb42b563c..aacfdda3e 100644
--- a/drivers/media/dvb-frontends/ves1820.c
+++ b/drivers/media/dvb-frontends/ves1820.c
@@ -90,7 +90,8 @@ static u8 ves1820_readreg(struct ves1820_state *state, u8 reg)
return b1[0];
}
-static int ves1820_setup_reg0(struct ves1820_state *state, u8 reg0, fe_spectral_inversion_t inversion)
+static int ves1820_setup_reg0(struct ves1820_state *state,
+ u8 reg0, enum fe_spectral_inversion inversion)
{
reg0 |= state->reg0 & 0x62;
@@ -237,7 +238,8 @@ static int ves1820_set_parameters(struct dvb_frontend *fe)
return 0;
}
-static int ves1820_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int ves1820_read_status(struct dvb_frontend *fe,
+ enum fe_status *status)
{
struct ves1820_state* state = fe->demodulator_priv;
int sync;
diff --git a/drivers/media/dvb-frontends/ves1x93.c b/drivers/media/dvb-frontends/ves1x93.c
index 9c17eacae..526952396 100644
--- a/drivers/media/dvb-frontends/ves1x93.c
+++ b/drivers/media/dvb-frontends/ves1x93.c
@@ -41,7 +41,7 @@ struct ves1x93_state {
struct dvb_frontend frontend;
/* previous uncorrected block counter */
- fe_spectral_inversion_t inversion;
+ enum fe_spectral_inversion inversion;
u8 *init_1x93_tab;
u8 *init_1x93_wtab;
u8 tab_size;
@@ -130,7 +130,8 @@ static int ves1x93_clr_bit (struct ves1x93_state* state)
return 0;
}
-static int ves1x93_set_inversion (struct ves1x93_state* state, fe_spectral_inversion_t inversion)
+static int ves1x93_set_inversion(struct ves1x93_state *state,
+ enum fe_spectral_inversion inversion)
{
u8 val;
@@ -156,7 +157,7 @@ static int ves1x93_set_inversion (struct ves1x93_state* state, fe_spectral_inver
return ves1x93_writereg (state, 0x0c, (state->init_1x93_tab[0x0c] & 0x3f) | val);
}
-static int ves1x93_set_fec (struct ves1x93_state* state, fe_code_rate_t fec)
+static int ves1x93_set_fec(struct ves1x93_state *state, enum fe_code_rate fec)
{
if (fec == FEC_AUTO)
return ves1x93_writereg (state, 0x0d, 0x08);
@@ -166,7 +167,7 @@ static int ves1x93_set_fec (struct ves1x93_state* state, fe_code_rate_t fec)
return ves1x93_writereg (state, 0x0d, fec - FEC_1_2);
}
-static fe_code_rate_t ves1x93_get_fec (struct ves1x93_state* state)
+static enum fe_code_rate ves1x93_get_fec(struct ves1x93_state *state)
{
return FEC_1_2 + ((ves1x93_readreg (state, 0x0d) >> 4) & 0x7);
}
@@ -281,7 +282,8 @@ static int ves1x93_init (struct dvb_frontend* fe)
return 0;
}
-static int ves1x93_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+static int ves1x93_set_voltage(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage)
{
struct ves1x93_state* state = fe->demodulator_priv;
@@ -297,7 +299,8 @@ static int ves1x93_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
}
}
-static int ves1x93_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int ves1x93_read_status(struct dvb_frontend *fe,
+ enum fe_status *status)
{
struct ves1x93_state* state = fe->demodulator_priv;
diff --git a/drivers/media/dvb-frontends/zl10353.c b/drivers/media/dvb-frontends/zl10353.c
index 82946cd51..ef9764a02 100644
--- a/drivers/media/dvb-frontends/zl10353.c
+++ b/drivers/media/dvb-frontends/zl10353.c
@@ -462,7 +462,7 @@ static int zl10353_get_parameters(struct dvb_frontend *fe)
return 0;
}
-static int zl10353_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int zl10353_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct zl10353_state *state = fe->demodulator_priv;
int s6, s7, s8;
@@ -533,13 +533,13 @@ static int zl10353_read_snr(struct dvb_frontend *fe, u16 *snr)
static int zl10353_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
{
struct zl10353_state *state = fe->demodulator_priv;
- u32 ubl = 0;
+ u32 ubl = 0;
- ubl = zl10353_read_register(state, RS_UBC_1) << 8 |
- zl10353_read_register(state, RS_UBC_0);
+ ubl = zl10353_read_register(state, RS_UBC_1) << 8 |
+ zl10353_read_register(state, RS_UBC_0);
- state->ucblocks += ubl;
- *ucblocks = state->ucblocks;
+ state->ucblocks += ubl;
+ *ucblocks = state->ucblocks;
return 0;
}