{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 */
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;
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");
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);
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 */
.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)
{
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;
}
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];
}
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:
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);
}
/* 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);