* [PATCH v3 3/6] si2157: support selection of IF interface
@ 2015-05-03 13:00 Olli Salonen
2015-05-03 13:00 ` [PATCH v3 4/6] rtl28xxu: add I2C read without write Olli Salonen
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Olli Salonen @ 2015-05-03 13:00 UTC (permalink / raw)
To: linux-media; +Cc: Olli Salonen, Antti Palosaari
The chips supported by the si2157 driver have two IF outputs (either
pins 12+13 or pins 9+11). Instead of hardcoding the output to be used
add an option to choose which output shall be used.
As this patch changes the default behaviour, the IF interface is
specified in each driver currently using si2157 driver. This is to
keep bisectability.
Signed-off-by: Olli Salonen <olli.salonen@iki.fi>
---
drivers/media/pci/cx23885/cx23885-dvb.c | 4 ++++
drivers/media/pci/smipcie/smipcie.c | 1 +
drivers/media/tuners/si2157.c | 4 +++-
drivers/media/tuners/si2157.h | 6 ++++++
drivers/media/tuners/si2157_priv.h | 1 +
drivers/media/usb/cx231xx/cx231xx-dvb.c | 2 ++
drivers/media/usb/dvb-usb-v2/af9035.c | 1 +
drivers/media/usb/dvb-usb-v2/dvbsky.c | 2 ++
drivers/media/usb/dvb-usb/cxusb.c | 1 +
drivers/media/usb/em28xx/em28xx-dvb.c | 2 ++
10 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c
index 745caab..37fd013 100644
--- a/drivers/media/pci/cx23885/cx23885-dvb.c
+++ b/drivers/media/pci/cx23885/cx23885-dvb.c
@@ -1912,6 +1912,7 @@ static int dvb_register(struct cx23885_tsport *port)
/* attach tuner */
memset(&si2157_config, 0, sizeof(si2157_config));
si2157_config.fe = fe0->dvb.frontend;
+ si2157_config.if_port = 1;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
info.addr = 0x60;
@@ -1957,6 +1958,7 @@ static int dvb_register(struct cx23885_tsport *port)
/* attach tuner */
memset(&si2157_config, 0, sizeof(si2157_config));
si2157_config.fe = fe0->dvb.frontend;
+ si2157_config.if_port = 1;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
info.addr = 0x60;
@@ -2093,6 +2095,7 @@ static int dvb_register(struct cx23885_tsport *port)
/* attach tuner */
memset(&si2157_config, 0, sizeof(si2157_config));
si2157_config.fe = fe0->dvb.frontend;
+ si2157_config.if_port = 1;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
info.addr = 0x60;
@@ -2172,6 +2175,7 @@ static int dvb_register(struct cx23885_tsport *port)
/* attach tuner */
memset(&si2157_config, 0, sizeof(si2157_config));
si2157_config.fe = fe0->dvb.frontend;
+ si2157_config.if_port = 1;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
info.addr = 0x60;
diff --git a/drivers/media/pci/smipcie/smipcie.c b/drivers/media/pci/smipcie/smipcie.c
index 4115925..143fd78 100644
--- a/drivers/media/pci/smipcie/smipcie.c
+++ b/drivers/media/pci/smipcie/smipcie.c
@@ -657,6 +657,7 @@ static int smi_dvbsky_sit2_fe_attach(struct smi_port *port)
/* attach tuner */
memset(&si2157_config, 0, sizeof(si2157_config));
si2157_config.fe = port->fe;
+ si2157_config.if_port = 1;
memset(&client_info, 0, sizeof(struct i2c_board_info));
strlcpy(client_info.type, "si2157", I2C_NAME_SIZE);
diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c
index d74ae26..cdaf687 100644
--- a/drivers/media/tuners/si2157.c
+++ b/drivers/media/tuners/si2157.c
@@ -298,7 +298,8 @@ static int si2157_set_params(struct dvb_frontend *fe)
if (dev->chiptype == SI2157_CHIPTYPE_SI2146)
memcpy(cmd.args, "\x14\x00\x02\x07\x00\x01", 6);
else
- memcpy(cmd.args, "\x14\x00\x02\x07\x01\x00", 6);
+ memcpy(cmd.args, "\x14\x00\x02\x07\x00\x00", 6);
+ cmd.args[4] = dev->if_port;
cmd.wlen = 6;
cmd.rlen = 4;
ret = si2157_cmd_execute(client, &cmd);
@@ -378,6 +379,7 @@ static int si2157_probe(struct i2c_client *client,
i2c_set_clientdata(client, dev);
dev->fe = cfg->fe;
dev->inversion = cfg->inversion;
+ dev->if_port = cfg->if_port;
dev->fw_loaded = false;
dev->chiptype = (u8)id->driver_data;
dev->if_frequency = 5000000; /* default value of property 0x0706 */
diff --git a/drivers/media/tuners/si2157.h b/drivers/media/tuners/si2157.h
index a564c4a..4db97ab 100644
--- a/drivers/media/tuners/si2157.h
+++ b/drivers/media/tuners/si2157.h
@@ -34,6 +34,12 @@ struct si2157_config {
* Spectral Inversion
*/
bool inversion;
+
+ /*
+ * Port selection
+ * Select the RF interface to use (pins 9+11 or 12+13)
+ */
+ u8 if_port;
};
#endif
diff --git a/drivers/media/tuners/si2157_priv.h b/drivers/media/tuners/si2157_priv.h
index cd8fa5b..71a5f8c 100644
--- a/drivers/media/tuners/si2157_priv.h
+++ b/drivers/media/tuners/si2157_priv.h
@@ -28,6 +28,7 @@ struct si2157_dev {
bool fw_loaded;
bool inversion;
u8 chiptype;
+ u8 if_port;
u32 if_frequency;
};
diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c
index 610d567..66ee161 100644
--- a/drivers/media/usb/cx231xx/cx231xx-dvb.c
+++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c
@@ -797,6 +797,7 @@ static int dvb_init(struct cx231xx *dev)
/* attach tuner */
memset(&si2157_config, 0, sizeof(si2157_config));
si2157_config.fe = dev->dvb->frontend;
+ si2157_config.if_port = 1;
si2157_config.inversion = true;
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
info.addr = 0x60;
@@ -852,6 +853,7 @@ static int dvb_init(struct cx231xx *dev)
/* attach tuner */
memset(&si2157_config, 0, sizeof(si2157_config));
si2157_config.fe = dev->dvb->frontend;
+ si2157_config.if_port = 1;
si2157_config.inversion = true;
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
info.addr = 0x60;
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c
index 80a29f5..7b7f75d 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.c
+++ b/drivers/media/usb/dvb-usb-v2/af9035.c
@@ -1569,6 +1569,7 @@ static int it930x_tuner_attach(struct dvb_usb_adapter *adap)
memset(&si2157_config, 0, sizeof(si2157_config));
si2157_config.fe = adap->fe[0];
+ si2157_config.if_port = 1;
ret = af9035_add_i2c_dev(d, "si2157", 0x63,
&si2157_config, state->i2c_adapter_demod);
diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c
index 0f73b1d..57c8c2d 100644
--- a/drivers/media/usb/dvb-usb-v2/dvbsky.c
+++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c
@@ -549,6 +549,7 @@ static int dvbsky_t680c_attach(struct dvb_usb_adapter *adap)
/* attach tuner */
memset(&si2157_config, 0, sizeof(si2157_config));
si2157_config.fe = adap->fe[0];
+ si2157_config.if_port = 1;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
info.addr = 0x60;
@@ -633,6 +634,7 @@ static int dvbsky_t330_attach(struct dvb_usb_adapter *adap)
/* attach tuner */
memset(&si2157_config, 0, sizeof(si2157_config));
si2157_config.fe = adap->fe[0];
+ si2157_config.if_port = 1;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
info.addr = 0x60;
diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c
index ffc3704..ab71511 100644
--- a/drivers/media/usb/dvb-usb/cxusb.c
+++ b/drivers/media/usb/dvb-usb/cxusb.c
@@ -1350,6 +1350,7 @@ static int cxusb_mygica_t230_frontend_attach(struct dvb_usb_adapter *adap)
/* attach tuner */
memset(&si2157_config, 0, sizeof(si2157_config));
si2157_config.fe = adap->fe_adap[0].fe;
+ si2157_config.if_port = 1;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
info.addr = 0x60;
diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c
index a5b22c5..5b7c7c88 100644
--- a/drivers/media/usb/em28xx/em28xx-dvb.c
+++ b/drivers/media/usb/em28xx/em28xx-dvb.c
@@ -1579,6 +1579,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
/* attach tuner */
memset(&si2157_config, 0, sizeof(si2157_config));
si2157_config.fe = dvb->fe[0];
+ si2157_config.if_port = 1;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
info.addr = 0x60;
@@ -1639,6 +1640,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
/* attach tuner */
memset(&si2157_config, 0, sizeof(si2157_config));
si2157_config.fe = dvb->fe[0];
+ si2157_config.if_port = 0;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2146", I2C_NAME_SIZE);
info.addr = 0x60;
--
1.9.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v3 4/6] rtl28xxu: add I2C read without write
2015-05-03 13:00 [PATCH v3 3/6] si2157: support selection of IF interface Olli Salonen
@ 2015-05-03 13:00 ` Olli Salonen
2015-05-03 13:00 ` [PATCH v3 5/6] si2168: add I2C error handling Olli Salonen
2015-05-03 13:00 ` [PATCH v3 6/6] rtl2832: add support for GoTView MasterHD 3 USB tuner Olli Salonen
2 siblings, 0 replies; 6+ messages in thread
From: Olli Salonen @ 2015-05-03 13:00 UTC (permalink / raw)
To: linux-media; +Cc: Olli Salonen, Antti Palosaari
Add support for I2C read operation without a preceeding write.
While here, change the error code to EOPNOTSUPP in case an
unsupported I2C operation is attempted.
Signed-off-by: Olli Salonen <olli.salonen@iki.fi>
---
drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index f1a7613..5e0c015 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -232,8 +232,14 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
req.data = msg[0].buf;
ret = rtl28xxu_ctrl_msg(d, &req);
}
+ } else if (num == 1 && (msg[0].flags & I2C_M_RD)) {
+ req.value = (msg[0].addr << 1);
+ req.index = CMD_I2C_DA_RD;
+ req.size = msg[0].len;
+ req.data = msg[0].buf;
+ ret = rtl28xxu_ctrl_msg(d, &req);
} else {
- ret = -EINVAL;
+ ret = -EOPNOTSUPP;
}
err_mutex_unlock:
--
1.9.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v3 5/6] si2168: add I2C error handling
2015-05-03 13:00 [PATCH v3 3/6] si2157: support selection of IF interface Olli Salonen
2015-05-03 13:00 ` [PATCH v3 4/6] rtl28xxu: add I2C read without write Olli Salonen
@ 2015-05-03 13:00 ` Olli Salonen
2015-05-07 20:49 ` Antti Palosaari
2015-05-03 13:00 ` [PATCH v3 6/6] rtl2832: add support for GoTView MasterHD 3 USB tuner Olli Salonen
2 siblings, 1 reply; 6+ messages in thread
From: Olli Salonen @ 2015-05-03 13:00 UTC (permalink / raw)
To: linux-media; +Cc: Olli Salonen, Antti Palosaari
Return error from si2168_cmd_execute in case the demodulator returns an
error.
Signed-off-by: Olli Salonen <olli.salonen@iki.fi>
---
drivers/media/dvb-frontends/si2168.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c
index 29a5936..b68ab34 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -60,6 +60,12 @@ 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_mutex_unlock;
+ }
+
if (!((cmd->args[0] >> 7) & 0x01)) {
ret = -ETIMEDOUT;
goto err_mutex_unlock;
--
1.9.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v3 6/6] rtl2832: add support for GoTView MasterHD 3 USB tuner
2015-05-03 13:00 [PATCH v3 3/6] si2157: support selection of IF interface Olli Salonen
2015-05-03 13:00 ` [PATCH v3 4/6] rtl28xxu: add I2C read without write Olli Salonen
2015-05-03 13:00 ` [PATCH v3 5/6] si2168: add I2C error handling Olli Salonen
@ 2015-05-03 13:00 ` Olli Salonen
2 siblings, 0 replies; 6+ messages in thread
From: Olli Salonen @ 2015-05-03 13:00 UTC (permalink / raw)
To: linux-media; +Cc: Olli Salonen
GoTView MasterHD 3 is a DVB-T2/C USB 2.0 tuner.
It's based on the following components:
- USB bridge: RTL2832P (contains also DVB-T demodulator)
- Demodulator: Si2168-A30
- Tuner: Si2148-A20
The demodulator and the tuner will need firmwares. The Si2148 uses Si2158
firmware. Antti has the firmwares available for download:
http://palosaari.fi/linux/v4l-dvb/firmware/
Do note that for DVB-T either of the demodulators can be used. DVB-C and
DVB-T2 are only supported by the Si2168 demodulator. The driver will
register 2 frontends for the same adapter. Frontend 0 will be the RTL2832
demodulator and frontend 1 will be the Si2168 demodulator. The same
tuner is used for both.
As a consequence of the above, it's recommended to use application that
does implement proper DVBv5 support.
For some reason, the old I2C write method sporadically fails. Thus the
need for an option to only use the new I2C write method supported by the
RTL2832.
Signed-off-by: Olli Salonen <olli.salonen@iki.fi>
---
drivers/media/dvb-frontends/rtl2832.c | 4 +
drivers/media/dvb-frontends/rtl2832.h | 1 +
drivers/media/dvb-frontends/rtl2832_priv.h | 25 ++++++
drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 117 ++++++++++++++++++++++++++++-
drivers/media/usb/dvb-usb-v2/rtl28xxu.h | 5 ++
5 files changed, 149 insertions(+), 3 deletions(-)
diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c
index 20fa245..08558eb 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -376,6 +376,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;
diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h
index a8e912e..c6cdcc4 100644
--- a/drivers/media/dvb-frontends/rtl2832.h
+++ b/drivers/media/dvb-frontends/rtl2832.h
@@ -47,6 +47,7 @@ struct rtl2832_platform_data {
#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 c3a922c..a973b8a 100644
--- a/drivers/media/dvb-frontends/rtl2832_priv.h
+++ b/drivers/media/dvb-frontends/rtl2832_priv.h
@@ -377,4 +377,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/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index 5e0c015..5cc2f12 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -217,7 +217,7 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
req.data = &msg[0].buf[1];
ret = rtl28xxu_ctrl_msg(d, &req);
}
- } else if (msg[0].len < 23) {
+ } else if ((msg[0].len < 23) && (!dev->new_i2c_write)) {
/* method 2 - old I2C */
req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1);
req.index = CMD_I2C_WR;
@@ -363,6 +363,8 @@ static int rtl2832u_read_config(struct dvb_usb_device *d)
struct rtl28xxu_req req_r828d = {0x0074, CMD_I2C_RD, 1, buf};
struct rtl28xxu_req req_mn88472 = {0xff38, CMD_I2C_RD, 1, buf};
struct rtl28xxu_req req_mn88473 = {0xff38, CMD_I2C_RD, 1, buf};
+ struct rtl28xxu_req req_si2157 = {0x00c0, CMD_I2C_RD, 1, buf};
+ struct rtl28xxu_req req_si2168 = {0x00c8, CMD_I2C_RD, 1, buf};
dev_dbg(&d->intf->dev, "\n");
@@ -483,6 +485,35 @@ static int rtl2832u_read_config(struct dvb_usb_device *d)
goto tuner_found;
}
+ /* GPIO0 and GPIO5 to reset Si2157/Si2168 tuner and demod */
+ ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x00, 0x21);
+ if (ret)
+ goto err;
+
+ ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x00, 0x21);
+ if (ret)
+ goto err;
+
+ msleep(50);
+
+ ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x21, 0x21);
+ if (ret)
+ goto err;
+
+ ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x21, 0x21);
+ if (ret)
+ goto err;
+
+ msleep(50);
+
+ /* check Si2157 ID register; reg=c0 val=80 */
+ ret = rtl28xxu_ctrl_msg(d, &req_si2157);
+ if (ret == 0 && ((buf[0] & 0x80) == 0x80)) {
+ dev->tuner = TUNER_RTL2832_SI2157;
+ dev->tuner_name = "SI2157";
+ goto tuner_found;
+ }
+
tuner_found:
dev_dbg(&d->intf->dev, "tuner=%s\n", dev->tuner_name);
@@ -516,6 +547,15 @@ tuner_found:
goto demod_found;
}
}
+ if (dev->tuner == TUNER_RTL2832_SI2157) {
+ /* check Si2168 ID register; reg=c8 val=80 */
+ ret = rtl28xxu_ctrl_msg(d, &req_si2168);
+ if (ret == 0 && ((buf[0] & 0x80) == 0x80)) {
+ dev_dbg(&d->intf->dev, "Si2168 found\n");
+ dev->slave_demod = SLAVE_DEMOD_SI2168;
+ goto demod_found;
+ }
+ }
demod_found:
/* close demod I2C gate */
@@ -674,6 +714,11 @@ static const struct rtl2832_platform_data rtl2832_r820t_platform_data = {
.tuner = TUNER_RTL2832_R820T,
};
+static const struct rtl2832_platform_data rtl2832_si2157_platform_data = {
+ .clk = 28800000,
+ .tuner = TUNER_RTL2832_SI2157,
+};
+
static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d,
int cmd, int arg)
{
@@ -825,6 +870,9 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
case TUNER_RTL2832_R828D:
*pdata = rtl2832_r820t_platform_data;
break;
+ case TUNER_RTL2832_SI2157:
+ *pdata = rtl2832_si2157_platform_data;
+ break;
default:
dev_err(&d->intf->dev, "unknown tuner %s\n", dev->tuner_name);
ret = -ENODEV;
@@ -892,7 +940,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
}
dev->i2c_client_slave_demod = client;
- } else {
+ } else if (dev->slave_demod == SLAVE_DEMOD_MN88473) {
struct mn88473_config mn88473_config = {};
mn88473_config.fe = &adap->fe[1];
@@ -914,9 +962,37 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
}
dev->i2c_client_slave_demod = client;
+ } else {
+ struct si2168_config si2168_config = {};
+ struct i2c_adapter *adapter;
+
+ si2168_config.i2c_adapter = &adapter;
+ si2168_config.fe = &adap->fe[1];
+ si2168_config.ts_mode = SI2168_TS_SERIAL;
+ si2168_config.ts_clock_inv = false;
+ si2168_config.ts_clock_gapped = true;
+ strlcpy(info.type, "si2168", I2C_NAME_SIZE);
+ info.addr = 0x64;
+ info.platform_data = &si2168_config;
+ request_module(info.type);
+ client = i2c_new_device(&d->i2c_adap, &info);
+ if (client == NULL || client->dev.driver == NULL) {
+ dev->slave_demod = SLAVE_DEMOD_NONE;
+ goto err_slave_demod_failed;
+ }
+
+ if (!try_module_get(client->dev.driver->owner)) {
+ i2c_unregister_device(client);
+ dev->slave_demod = SLAVE_DEMOD_NONE;
+ goto err_slave_demod_failed;
+ }
+
+ dev->i2c_client_slave_demod = client;
+
+ /* for Si2168 devices use only new I2C write method */
+ dev->new_i2c_write = true;
}
}
-
return 0;
err_slave_demod_failed:
err:
@@ -1156,6 +1232,39 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
adap->fe[1]->ops.tuner_ops.get_rf_strength;
}
break;
+ case TUNER_RTL2832_SI2157: {
+ struct si2157_config si2157_config = {
+ .fe = adap->fe[0],
+ .if_port = 0,
+ .inversion = false,
+ };
+
+ strlcpy(info.type, "si2157", I2C_NAME_SIZE);
+ info.addr = 0x60;
+ info.platform_data = &si2157_config;
+ request_module(info.type);
+ client = i2c_new_device(&d->i2c_adap, &info);
+ if (client == NULL || client->dev.driver == NULL)
+ break;
+
+ if (!try_module_get(client->dev.driver->owner)) {
+ i2c_unregister_device(client);
+ break;
+ }
+
+ dev->i2c_client_tuner = client;
+ subdev = i2c_get_clientdata(client);
+
+ /* copy tuner ops for 2nd FE as tuner is shared */
+ if (adap->fe[1]) {
+ adap->fe[1]->tuner_priv =
+ adap->fe[0]->tuner_priv;
+ memcpy(&adap->fe[1]->ops.tuner_ops,
+ &adap->fe[0]->ops.tuner_ops,
+ sizeof(struct dvb_tuner_ops));
+ }
+ }
+ break;
default:
dev_err(&d->intf->dev, "unknown tuner %d\n", dev->tuner);
}
@@ -1772,6 +1881,8 @@ static const struct usb_device_id rtl28xxu_id_table[] = {
/* RTL2832P devices: */
{ DVB_USB_DEVICE(USB_VID_HANFTEK, 0x0131,
&rtl28xxu_props, "Astrometa DVB-T2", NULL) },
+ { DVB_USB_DEVICE(0x5654, 0xca42,
+ &rtl28xxu_props, "GoTView MasterHD 3", NULL) },
{ }
};
MODULE_DEVICE_TABLE(usb, rtl28xxu_id_table);
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
index 1b5d7ff..9f6115a 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
@@ -41,6 +41,8 @@
#include "fc2580.h"
#include "tua9001.h"
#include "r820t.h"
+#include "si2168.h"
+#include "si2157.h"
/*
* USB commands
@@ -76,6 +78,7 @@ struct rtl28xxu_dev {
u8 page; /* integrated demod active register page */
struct i2c_adapter *demod_i2c_adapter;
bool rc_active;
+ bool new_i2c_write;
struct i2c_client *i2c_client_demod;
struct i2c_client *i2c_client_tuner;
struct i2c_client *i2c_client_slave_demod;
@@ -83,6 +86,7 @@ struct rtl28xxu_dev {
#define SLAVE_DEMOD_NONE 0
#define SLAVE_DEMOD_MN88472 1
#define SLAVE_DEMOD_MN88473 2
+ #define SLAVE_DEMOD_SI2168 3
unsigned int slave_demod:2;
union {
struct rtl2830_platform_data rtl2830_platform_data;
@@ -116,6 +120,7 @@ enum rtl28xxu_tuner {
TUNER_RTL2832_FC0013,
TUNER_RTL2832_R820T,
TUNER_RTL2832_R828D,
+ TUNER_RTL2832_SI2157,
};
struct rtl28xxu_req {
--
1.9.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v3 5/6] si2168: add I2C error handling
2015-05-03 13:00 ` [PATCH v3 5/6] si2168: add I2C error handling Olli Salonen
@ 2015-05-07 20:49 ` Antti Palosaari
2015-05-07 23:36 ` Olli Salonen
0 siblings, 1 reply; 6+ messages in thread
From: Antti Palosaari @ 2015-05-07 20:49 UTC (permalink / raw)
To: Olli Salonen, linux-media
Moikka!
I didn't make any tests, but I could guess that error flag is set by
firmware when some unsupported / invalid parameter is given as a
firmware command request.
Anyhow, I am not sure which is proper error code to return. Could you
please study, check from API docs and so, which are suitable error
codes. EINVAL sounds proper code, but imho it is not good as generally
it is returned by driver when invalid parameters are requested and I
would like to see some other code to make difference (between driver and
firmware error).
regards
Antti
On 05/03/2015 04:00 PM, Olli Salonen wrote:
> Return error from si2168_cmd_execute in case the demodulator returns an
> error.
>
> Signed-off-by: Olli Salonen <olli.salonen@iki.fi>
> ---
> drivers/media/dvb-frontends/si2168.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c
> index 29a5936..b68ab34 100644
> --- a/drivers/media/dvb-frontends/si2168.c
> +++ b/drivers/media/dvb-frontends/si2168.c
> @@ -60,6 +60,12 @@ 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_mutex_unlock;
> + }
> +
> if (!((cmd->args[0] >> 7) & 0x01)) {
> ret = -ETIMEDOUT;
> goto err_mutex_unlock;
>
--
http://palosaari.fi/
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3 5/6] si2168: add I2C error handling
2015-05-07 20:49 ` Antti Palosaari
@ 2015-05-07 23:36 ` Olli Salonen
0 siblings, 0 replies; 6+ messages in thread
From: Olli Salonen @ 2015-05-07 23:36 UTC (permalink / raw)
To: Antti Palosaari; +Cc: linux-media
Hi Antti,
I basically used the same code that was used earlier in the same
function in case i2c_master_send/recv returns an unexpected result.
When working with the RTL2832P based Si2168 device I noticed that at
some point, often but not always during firmware loading, the Si2168
started to return error. When that happened any subsequent firmware
commands would fail as well. So it made sense to interrupt the loading
of firmware at the point when the first error is returned by the
demod. The reason for these I2C problems is not known - two hacks (rc
query interval increase and usage of the new I2C write method) were
used to mitigate the issue.
Based on the descriptions in
https://www.kernel.org/doc/Documentation/i2c/fault-codes EIO could be
applicable, though very loosely specified (which isn't necessary
wrong, as I don't have exact knowledge on which cases the error bit is
set):
EIO
This rather vague error means something went wrong when
performing an I/O operation. Use a more specific fault
code when you can.
The description for EINVAL doesn't match when it comes to the "before
any I/O operation was started", but other than that it might be
usable:
EINVAL
This rather vague error means an invalid parameter has been
detected before any I/O operation was started. Use a more
specific fault code when you can.
Looking at other DVB drivers, it seems it's mainly EREMOTEIO or EINVAL
that's used, depending on the case.
Cheers,
-olli
On 7 May 2015 at 22:49, Antti Palosaari <crope@iki.fi> wrote:
> Moikka!
> I didn't make any tests, but I could guess that error flag is set by
> firmware when some unsupported / invalid parameter is given as a firmware
> command request.
>
> Anyhow, I am not sure which is proper error code to return. Could you please
> study, check from API docs and so, which are suitable error codes. EINVAL
> sounds proper code, but imho it is not good as generally it is returned by
> driver when invalid parameters are requested and I would like to see some
> other code to make difference (between driver and firmware error).
>
> regards
> Antti
>
>
> On 05/03/2015 04:00 PM, Olli Salonen wrote:
>>
>> Return error from si2168_cmd_execute in case the demodulator returns an
>> error.
>>
>> Signed-off-by: Olli Salonen <olli.salonen@iki.fi>
>> ---
>> drivers/media/dvb-frontends/si2168.c | 6 ++++++
>> 1 file changed, 6 insertions(+)
>>
>> diff --git a/drivers/media/dvb-frontends/si2168.c
>> b/drivers/media/dvb-frontends/si2168.c
>> index 29a5936..b68ab34 100644
>> --- a/drivers/media/dvb-frontends/si2168.c
>> +++ b/drivers/media/dvb-frontends/si2168.c
>> @@ -60,6 +60,12 @@ 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_mutex_unlock;
>> + }
>> +
>> if (!((cmd->args[0] >> 7) & 0x01)) {
>> ret = -ETIMEDOUT;
>> goto err_mutex_unlock;
>>
>
> --
> http://palosaari.fi/
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2015-05-07 23:36 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-05-03 13:00 [PATCH v3 3/6] si2157: support selection of IF interface Olli Salonen
2015-05-03 13:00 ` [PATCH v3 4/6] rtl28xxu: add I2C read without write Olli Salonen
2015-05-03 13:00 ` [PATCH v3 5/6] si2168: add I2C error handling Olli Salonen
2015-05-07 20:49 ` Antti Palosaari
2015-05-07 23:36 ` Olli Salonen
2015-05-03 13:00 ` [PATCH v3 6/6] rtl2832: add support for GoTView MasterHD 3 USB tuner Olli Salonen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox