|
@@ -274,6 +274,87 @@ static struct i2c_algorithm rtl28xxu_i2c_algo = {
|
|
|
.functionality = rtl28xxu_i2c_func,
|
|
|
};
|
|
|
|
|
|
+static int rtl2831u_read_config(struct dvb_usb_device *d)
|
|
|
+{
|
|
|
+ struct rtl28xxu_priv *priv = d_to_priv(d);
|
|
|
+ int ret;
|
|
|
+ u8 buf[1];
|
|
|
+ /* open RTL2831U/RTL2830 I2C gate */
|
|
|
+ struct rtl28xxu_req req_gate_open = {0x0120, 0x0011, 0x0001, "\x08"};
|
|
|
+ /* tuner probes */
|
|
|
+ struct rtl28xxu_req req_mt2060 = {0x00c0, CMD_I2C_RD, 1, buf};
|
|
|
+ struct rtl28xxu_req req_qt1010 = {0x0fc4, CMD_I2C_RD, 1, buf};
|
|
|
+
|
|
|
+ dev_dbg(&d->udev->dev, "%s:\n", __func__);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * RTL2831U GPIOs
|
|
|
+ * =========================================================
|
|
|
+ * GPIO0 | tuner#0 | 0 off | 1 on | MXL5005S (?)
|
|
|
+ * GPIO2 | LED | 0 off | 1 on |
|
|
|
+ * GPIO4 | tuner#1 | 0 on | 1 off | MT2060
|
|
|
+ */
|
|
|
+
|
|
|
+ /* GPIO direction */
|
|
|
+ ret = rtl28xx_wr_reg(d, SYS_GPIO_DIR, 0x0a);
|
|
|
+ if (ret)
|
|
|
+ goto err;
|
|
|
+
|
|
|
+ /* enable as output GPIO0, GPIO2, GPIO4 */
|
|
|
+ ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_EN, 0x15);
|
|
|
+ if (ret)
|
|
|
+ goto err;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Probe used tuner. We need to know used tuner before demod attach
|
|
|
+ * since there is some demod params needed to set according to tuner.
|
|
|
+ */
|
|
|
+
|
|
|
+ /* demod needs some time to wake up */
|
|
|
+ msleep(20);
|
|
|
+
|
|
|
+ priv->tuner_name = "NONE";
|
|
|
+
|
|
|
+ /* open demod I2C gate */
|
|
|
+ ret = rtl28xxu_ctrl_msg(d, &req_gate_open);
|
|
|
+ if (ret)
|
|
|
+ goto err;
|
|
|
+
|
|
|
+ /* check QT1010 ID(?) register; reg=0f val=2c */
|
|
|
+ ret = rtl28xxu_ctrl_msg(d, &req_qt1010);
|
|
|
+ if (ret == 0 && buf[0] == 0x2c) {
|
|
|
+ priv->tuner = TUNER_RTL2830_QT1010;
|
|
|
+ priv->tuner_name = "QT1010";
|
|
|
+ goto found;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* open demod I2C gate */
|
|
|
+ ret = rtl28xxu_ctrl_msg(d, &req_gate_open);
|
|
|
+ if (ret)
|
|
|
+ goto err;
|
|
|
+
|
|
|
+ /* check MT2060 ID register; reg=00 val=63 */
|
|
|
+ ret = rtl28xxu_ctrl_msg(d, &req_mt2060);
|
|
|
+ if (ret == 0 && buf[0] == 0x63) {
|
|
|
+ priv->tuner = TUNER_RTL2830_MT2060;
|
|
|
+ priv->tuner_name = "MT2060";
|
|
|
+ goto found;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* assume MXL5005S */
|
|
|
+ priv->tuner = TUNER_RTL2830_MXL5005S;
|
|
|
+ priv->tuner_name = "MXL5005S";
|
|
|
+ goto found;
|
|
|
+
|
|
|
+found:
|
|
|
+ dev_dbg(&d->udev->dev, "%s: tuner=%s\n", __func__, priv->tuner_name);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+err:
|
|
|
+ dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
static int rtl2832u_read_config(struct dvb_usb_device *d)
|
|
|
{
|
|
|
struct rtl28xxu_priv *priv = d_to_priv(d);
|
|
@@ -445,97 +526,38 @@ static struct rtl2830_config rtl28xxu_rtl2830_mxl5005s_config = {
|
|
|
|
|
|
static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap)
|
|
|
{
|
|
|
- int ret;
|
|
|
struct dvb_usb_device *d = adap_to_d(adap);
|
|
|
struct rtl28xxu_priv *priv = d_to_priv(d);
|
|
|
- u8 buf[1];
|
|
|
struct rtl2830_config *rtl2830_config;
|
|
|
- /* open RTL2831U/RTL2830 I2C gate */
|
|
|
- struct rtl28xxu_req req_gate = { 0x0120, 0x0011, 0x0001, "\x08" };
|
|
|
- /* for MT2060 tuner probe */
|
|
|
- struct rtl28xxu_req req_mt2060 = { 0x00c0, CMD_I2C_RD, 1, buf };
|
|
|
- /* for QT1010 tuner probe */
|
|
|
- struct rtl28xxu_req req_qt1010 = { 0x0fc4, CMD_I2C_RD, 1, buf };
|
|
|
+ int ret;
|
|
|
|
|
|
dev_dbg(&d->udev->dev, "%s:\n", __func__);
|
|
|
|
|
|
- /*
|
|
|
- * RTL2831U GPIOs
|
|
|
- * =========================================================
|
|
|
- * GPIO0 | tuner#0 | 0 off | 1 on | MXL5005S (?)
|
|
|
- * GPIO2 | LED | 0 off | 1 on |
|
|
|
- * GPIO4 | tuner#1 | 0 on | 1 off | MT2060
|
|
|
- */
|
|
|
-
|
|
|
- /* GPIO direction */
|
|
|
- ret = rtl28xx_wr_reg(d, SYS_GPIO_DIR, 0x0a);
|
|
|
- if (ret)
|
|
|
- goto err;
|
|
|
-
|
|
|
- /* enable as output GPIO0, GPIO2, GPIO4 */
|
|
|
- ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_EN, 0x15);
|
|
|
- if (ret)
|
|
|
- goto err;
|
|
|
-
|
|
|
- /*
|
|
|
- * Probe used tuner. We need to know used tuner before demod attach
|
|
|
- * since there is some demod params needed to set according to tuner.
|
|
|
- */
|
|
|
-
|
|
|
- /* demod needs some time to wake up */
|
|
|
- msleep(20);
|
|
|
-
|
|
|
- /* open demod I2C gate */
|
|
|
- ret = rtl28xxu_ctrl_msg(d, &req_gate);
|
|
|
- if (ret)
|
|
|
- goto err;
|
|
|
-
|
|
|
- /* check QT1010 ID(?) register; reg=0f val=2c */
|
|
|
- ret = rtl28xxu_ctrl_msg(d, &req_qt1010);
|
|
|
- if (ret == 0 && buf[0] == 0x2c) {
|
|
|
- priv->tuner = TUNER_RTL2830_QT1010;
|
|
|
+ switch (priv->tuner) {
|
|
|
+ case TUNER_RTL2830_QT1010:
|
|
|
rtl2830_config = &rtl28xxu_rtl2830_qt1010_config;
|
|
|
- dev_dbg(&d->udev->dev, "%s: QT1010\n", __func__);
|
|
|
- goto found;
|
|
|
- } else {
|
|
|
- dev_dbg(&d->udev->dev, "%s: QT1010 probe failed=%d - %02x\n",
|
|
|
- __func__, ret, buf[0]);
|
|
|
- }
|
|
|
-
|
|
|
- /* open demod I2C gate */
|
|
|
- ret = rtl28xxu_ctrl_msg(d, &req_gate);
|
|
|
- if (ret)
|
|
|
- goto err;
|
|
|
-
|
|
|
- /* check MT2060 ID register; reg=00 val=63 */
|
|
|
- ret = rtl28xxu_ctrl_msg(d, &req_mt2060);
|
|
|
- if (ret == 0 && buf[0] == 0x63) {
|
|
|
- priv->tuner = TUNER_RTL2830_MT2060;
|
|
|
+ break;
|
|
|
+ case TUNER_RTL2830_MT2060:
|
|
|
rtl2830_config = &rtl28xxu_rtl2830_mt2060_config;
|
|
|
- dev_dbg(&d->udev->dev, "%s: MT2060\n", __func__);
|
|
|
- goto found;
|
|
|
- } else {
|
|
|
- dev_dbg(&d->udev->dev, "%s: MT2060 probe failed=%d - %02x\n",
|
|
|
- __func__, ret, buf[0]);
|
|
|
+ break;
|
|
|
+ case TUNER_RTL2830_MXL5005S:
|
|
|
+ rtl2830_config = &rtl28xxu_rtl2830_mxl5005s_config;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ dev_err(&d->udev->dev, "%s: unknown tuner=%s\n",
|
|
|
+ KBUILD_MODNAME, priv->tuner_name);
|
|
|
+ ret = -ENODEV;
|
|
|
+ goto err;
|
|
|
}
|
|
|
|
|
|
- /* assume MXL5005S */
|
|
|
- ret = 0;
|
|
|
- priv->tuner = TUNER_RTL2830_MXL5005S;
|
|
|
- rtl2830_config = &rtl28xxu_rtl2830_mxl5005s_config;
|
|
|
- dev_dbg(&d->udev->dev, "%s: MXL5005S\n", __func__);
|
|
|
- goto found;
|
|
|
-
|
|
|
-found:
|
|
|
/* attach demodulator */
|
|
|
- adap->fe[0] = dvb_attach(rtl2830_attach, rtl2830_config,
|
|
|
- &d->i2c_adap);
|
|
|
- if (adap->fe[0] == NULL) {
|
|
|
+ adap->fe[0] = dvb_attach(rtl2830_attach, rtl2830_config, &d->i2c_adap);
|
|
|
+ if (!adap->fe[0]) {
|
|
|
ret = -ENODEV;
|
|
|
goto err;
|
|
|
}
|
|
|
|
|
|
- return ret;
|
|
|
+ return 0;
|
|
|
err:
|
|
|
dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
|
|
|
return ret;
|
|
@@ -1264,6 +1286,7 @@ static const struct dvb_usb_device_properties rtl2831u_props = {
|
|
|
|
|
|
.power_ctrl = rtl2831u_power_ctrl,
|
|
|
.i2c_algo = &rtl28xxu_i2c_algo,
|
|
|
+ .read_config = rtl2831u_read_config,
|
|
|
.frontend_attach = rtl2831u_frontend_attach,
|
|
|
.tuner_attach = rtl2831u_tuner_attach,
|
|
|
.init = rtl28xxu_init,
|