diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 135 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/rtl28xxu.h | 4 |
2 files changed, 108 insertions, 31 deletions
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 5ea52c7616f1..d9ee1a9c5cbe 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c | |||
@@ -24,6 +24,7 @@ | |||
24 | 24 | ||
25 | #include "rtl2830.h" | 25 | #include "rtl2830.h" |
26 | #include "rtl2832.h" | 26 | #include "rtl2832.h" |
27 | #include "mn88472.h" | ||
27 | 28 | ||
28 | #include "qt1010.h" | 29 | #include "qt1010.h" |
29 | #include "mt2060.h" | 30 | #include "mt2060.h" |
@@ -420,6 +421,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d) | |||
420 | struct rtl28xxu_req req_tda18272 = {0x00c0, CMD_I2C_RD, 2, buf}; | 421 | struct rtl28xxu_req req_tda18272 = {0x00c0, CMD_I2C_RD, 2, buf}; |
421 | struct rtl28xxu_req req_r820t = {0x0034, CMD_I2C_RD, 1, buf}; | 422 | struct rtl28xxu_req req_r820t = {0x0034, CMD_I2C_RD, 1, buf}; |
422 | struct rtl28xxu_req req_r828d = {0x0074, CMD_I2C_RD, 1, buf}; | 423 | struct rtl28xxu_req req_r828d = {0x0074, CMD_I2C_RD, 1, buf}; |
424 | struct rtl28xxu_req req_mn88472 = {0xff38, CMD_I2C_RD, 1, buf}; | ||
423 | 425 | ||
424 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | 426 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
425 | 427 | ||
@@ -449,7 +451,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d) | |||
449 | if (ret == 0 && buf[0] == 0xa1) { | 451 | if (ret == 0 && buf[0] == 0xa1) { |
450 | priv->tuner = TUNER_RTL2832_FC0012; | 452 | priv->tuner = TUNER_RTL2832_FC0012; |
451 | priv->tuner_name = "FC0012"; | 453 | priv->tuner_name = "FC0012"; |
452 | goto found; | 454 | goto tuner_found; |
453 | } | 455 | } |
454 | 456 | ||
455 | /* check FC0013 ID register; reg=00 val=a3 */ | 457 | /* check FC0013 ID register; reg=00 val=a3 */ |
@@ -457,7 +459,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d) | |||
457 | if (ret == 0 && buf[0] == 0xa3) { | 459 | if (ret == 0 && buf[0] == 0xa3) { |
458 | priv->tuner = TUNER_RTL2832_FC0013; | 460 | priv->tuner = TUNER_RTL2832_FC0013; |
459 | priv->tuner_name = "FC0013"; | 461 | priv->tuner_name = "FC0013"; |
460 | goto found; | 462 | goto tuner_found; |
461 | } | 463 | } |
462 | 464 | ||
463 | /* check MT2266 ID register; reg=00 val=85 */ | 465 | /* check MT2266 ID register; reg=00 val=85 */ |
@@ -465,7 +467,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d) | |||
465 | if (ret == 0 && buf[0] == 0x85) { | 467 | if (ret == 0 && buf[0] == 0x85) { |
466 | priv->tuner = TUNER_RTL2832_MT2266; | 468 | priv->tuner = TUNER_RTL2832_MT2266; |
467 | priv->tuner_name = "MT2266"; | 469 | priv->tuner_name = "MT2266"; |
468 | goto found; | 470 | goto tuner_found; |
469 | } | 471 | } |
470 | 472 | ||
471 | /* check FC2580 ID register; reg=01 val=56 */ | 473 | /* check FC2580 ID register; reg=01 val=56 */ |
@@ -473,7 +475,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d) | |||
473 | if (ret == 0 && buf[0] == 0x56) { | 475 | if (ret == 0 && buf[0] == 0x56) { |
474 | priv->tuner = TUNER_RTL2832_FC2580; | 476 | priv->tuner = TUNER_RTL2832_FC2580; |
475 | priv->tuner_name = "FC2580"; | 477 | priv->tuner_name = "FC2580"; |
476 | goto found; | 478 | goto tuner_found; |
477 | } | 479 | } |
478 | 480 | ||
479 | /* check MT2063 ID register; reg=00 val=9e || 9c */ | 481 | /* check MT2063 ID register; reg=00 val=9e || 9c */ |
@@ -481,7 +483,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d) | |||
481 | if (ret == 0 && (buf[0] == 0x9e || buf[0] == 0x9c)) { | 483 | if (ret == 0 && (buf[0] == 0x9e || buf[0] == 0x9c)) { |
482 | priv->tuner = TUNER_RTL2832_MT2063; | 484 | priv->tuner = TUNER_RTL2832_MT2063; |
483 | priv->tuner_name = "MT2063"; | 485 | priv->tuner_name = "MT2063"; |
484 | goto found; | 486 | goto tuner_found; |
485 | } | 487 | } |
486 | 488 | ||
487 | /* check MAX3543 ID register; reg=00 val=38 */ | 489 | /* check MAX3543 ID register; reg=00 val=38 */ |
@@ -489,7 +491,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d) | |||
489 | if (ret == 0 && buf[0] == 0x38) { | 491 | if (ret == 0 && buf[0] == 0x38) { |
490 | priv->tuner = TUNER_RTL2832_MAX3543; | 492 | priv->tuner = TUNER_RTL2832_MAX3543; |
491 | priv->tuner_name = "MAX3543"; | 493 | priv->tuner_name = "MAX3543"; |
492 | goto found; | 494 | goto tuner_found; |
493 | } | 495 | } |
494 | 496 | ||
495 | /* check TUA9001 ID register; reg=7e val=2328 */ | 497 | /* check TUA9001 ID register; reg=7e val=2328 */ |
@@ -497,7 +499,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d) | |||
497 | if (ret == 0 && buf[0] == 0x23 && buf[1] == 0x28) { | 499 | if (ret == 0 && buf[0] == 0x23 && buf[1] == 0x28) { |
498 | priv->tuner = TUNER_RTL2832_TUA9001; | 500 | priv->tuner = TUNER_RTL2832_TUA9001; |
499 | priv->tuner_name = "TUA9001"; | 501 | priv->tuner_name = "TUA9001"; |
500 | goto found; | 502 | goto tuner_found; |
501 | } | 503 | } |
502 | 504 | ||
503 | /* check MXL5007R ID register; reg=d9 val=14 */ | 505 | /* check MXL5007R ID register; reg=d9 val=14 */ |
@@ -505,7 +507,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d) | |||
505 | if (ret == 0 && buf[0] == 0x14) { | 507 | if (ret == 0 && buf[0] == 0x14) { |
506 | priv->tuner = TUNER_RTL2832_MXL5007T; | 508 | priv->tuner = TUNER_RTL2832_MXL5007T; |
507 | priv->tuner_name = "MXL5007T"; | 509 | priv->tuner_name = "MXL5007T"; |
508 | goto found; | 510 | goto tuner_found; |
509 | } | 511 | } |
510 | 512 | ||
511 | /* check E4000 ID register; reg=02 val=40 */ | 513 | /* check E4000 ID register; reg=02 val=40 */ |
@@ -513,7 +515,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d) | |||
513 | if (ret == 0 && buf[0] == 0x40) { | 515 | if (ret == 0 && buf[0] == 0x40) { |
514 | priv->tuner = TUNER_RTL2832_E4000; | 516 | priv->tuner = TUNER_RTL2832_E4000; |
515 | priv->tuner_name = "E4000"; | 517 | priv->tuner_name = "E4000"; |
516 | goto found; | 518 | goto tuner_found; |
517 | } | 519 | } |
518 | 520 | ||
519 | /* check TDA18272 ID register; reg=00 val=c760 */ | 521 | /* check TDA18272 ID register; reg=00 val=c760 */ |
@@ -521,7 +523,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d) | |||
521 | if (ret == 0 && (buf[0] == 0xc7 || buf[1] == 0x60)) { | 523 | if (ret == 0 && (buf[0] == 0xc7 || buf[1] == 0x60)) { |
522 | priv->tuner = TUNER_RTL2832_TDA18272; | 524 | priv->tuner = TUNER_RTL2832_TDA18272; |
523 | priv->tuner_name = "TDA18272"; | 525 | priv->tuner_name = "TDA18272"; |
524 | goto found; | 526 | goto tuner_found; |
525 | } | 527 | } |
526 | 528 | ||
527 | /* check R820T ID register; reg=00 val=69 */ | 529 | /* check R820T ID register; reg=00 val=69 */ |
@@ -529,7 +531,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d) | |||
529 | if (ret == 0 && buf[0] == 0x69) { | 531 | if (ret == 0 && buf[0] == 0x69) { |
530 | priv->tuner = TUNER_RTL2832_R820T; | 532 | priv->tuner = TUNER_RTL2832_R820T; |
531 | priv->tuner_name = "R820T"; | 533 | priv->tuner_name = "R820T"; |
532 | goto found; | 534 | goto tuner_found; |
533 | } | 535 | } |
534 | 536 | ||
535 | /* check R828D ID register; reg=00 val=69 */ | 537 | /* check R828D ID register; reg=00 val=69 */ |
@@ -537,13 +539,37 @@ static int rtl2832u_read_config(struct dvb_usb_device *d) | |||
537 | if (ret == 0 && buf[0] == 0x69) { | 539 | if (ret == 0 && buf[0] == 0x69) { |
538 | priv->tuner = TUNER_RTL2832_R828D; | 540 | priv->tuner = TUNER_RTL2832_R828D; |
539 | priv->tuner_name = "R828D"; | 541 | priv->tuner_name = "R828D"; |
540 | goto found; | 542 | goto tuner_found; |
541 | } | 543 | } |
542 | 544 | ||
543 | 545 | tuner_found: | |
544 | found: | ||
545 | dev_dbg(&d->udev->dev, "%s: tuner=%s\n", __func__, priv->tuner_name); | 546 | dev_dbg(&d->udev->dev, "%s: tuner=%s\n", __func__, priv->tuner_name); |
546 | 547 | ||
548 | /* probe slave demod */ | ||
549 | if (priv->tuner == TUNER_RTL2832_R828D) { | ||
550 | /* power on MN88472 demod on GPIO0 */ | ||
551 | ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x01, 0x01); | ||
552 | if (ret) | ||
553 | goto err; | ||
554 | |||
555 | ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x01); | ||
556 | if (ret) | ||
557 | goto err; | ||
558 | |||
559 | ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x01, 0x01); | ||
560 | if (ret) | ||
561 | goto err; | ||
562 | |||
563 | /* check MN88472 answers */ | ||
564 | ret = rtl28xxu_ctrl_msg(d, &req_mn88472); | ||
565 | if (ret == 0 && buf[0] == 0x02) { | ||
566 | dev_dbg(&d->udev->dev, "%s: MN88472 found\n", __func__); | ||
567 | priv->slave_demod = SLAVE_DEMOD_MN88472; | ||
568 | goto demod_found; | ||
569 | } | ||
570 | } | ||
571 | |||
572 | demod_found: | ||
547 | /* close demod I2C gate */ | 573 | /* close demod I2C gate */ |
548 | ret = rtl28xxu_ctrl_msg(d, &req_gate_close); | 574 | ret = rtl28xxu_ctrl_msg(d, &req_gate_close); |
549 | if (ret < 0) | 575 | if (ret < 0) |
@@ -818,7 +844,44 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) | |||
818 | /* set fe callback */ | 844 | /* set fe callback */ |
819 | adap->fe[0]->callback = rtl2832u_frontend_callback; | 845 | adap->fe[0]->callback = rtl2832u_frontend_callback; |
820 | 846 | ||
847 | if (priv->slave_demod) { | ||
848 | struct i2c_board_info info = {}; | ||
849 | struct i2c_client *client; | ||
850 | |||
851 | /* | ||
852 | * We continue on reduced mode, without DVB-T2/C, using master | ||
853 | * demod, when slave demod fails. | ||
854 | */ | ||
855 | ret = 0; | ||
856 | |||
857 | /* attach slave demodulator */ | ||
858 | if (priv->slave_demod == SLAVE_DEMOD_MN88472) { | ||
859 | struct mn88472_config mn88472_config = {}; | ||
860 | |||
861 | mn88472_config.fe = &adap->fe[1]; | ||
862 | mn88472_config.i2c_wr_max = 22, | ||
863 | strlcpy(info.type, "mn88472", I2C_NAME_SIZE); | ||
864 | info.addr = 0x18; | ||
865 | info.platform_data = &mn88472_config; | ||
866 | request_module(info.type); | ||
867 | client = i2c_new_device(priv->demod_i2c_adapter, &info); | ||
868 | if (client == NULL || client->dev.driver == NULL) { | ||
869 | priv->slave_demod = SLAVE_DEMOD_NONE; | ||
870 | goto err_slave_demod_failed; | ||
871 | } | ||
872 | |||
873 | if (!try_module_get(client->dev.driver->owner)) { | ||
874 | i2c_unregister_device(client); | ||
875 | priv->slave_demod = SLAVE_DEMOD_NONE; | ||
876 | goto err_slave_demod_failed; | ||
877 | } | ||
878 | |||
879 | priv->i2c_client_slave_demod = client; | ||
880 | } | ||
881 | } | ||
882 | |||
821 | return 0; | 883 | return 0; |
884 | err_slave_demod_failed: | ||
822 | err: | 885 | err: |
823 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | 886 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); |
824 | return ret; | 887 | return ret; |
@@ -1024,25 +1087,19 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) | |||
1024 | &rtl28xxu_rtl2832_r820t_config, NULL); | 1087 | &rtl28xxu_rtl2832_r820t_config, NULL); |
1025 | break; | 1088 | break; |
1026 | case TUNER_RTL2832_R828D: | 1089 | case TUNER_RTL2832_R828D: |
1027 | /* power off mn88472 demod on GPIO0 */ | 1090 | fe = dvb_attach(r820t_attach, adap->fe[0], |
1028 | ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x00, 0x01); | 1091 | priv->demod_i2c_adapter, |
1029 | if (ret) | ||
1030 | goto err; | ||
1031 | |||
1032 | ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x01); | ||
1033 | if (ret) | ||
1034 | goto err; | ||
1035 | |||
1036 | ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x01, 0x01); | ||
1037 | if (ret) | ||
1038 | goto err; | ||
1039 | |||
1040 | fe = dvb_attach(r820t_attach, adap->fe[0], &d->i2c_adap, | ||
1041 | &rtl2832u_r828d_config); | 1092 | &rtl2832u_r828d_config); |
1042 | |||
1043 | /* Use tuner to get the signal strength */ | ||
1044 | adap->fe[0]->ops.read_signal_strength = | 1093 | adap->fe[0]->ops.read_signal_strength = |
1045 | adap->fe[0]->ops.tuner_ops.get_rf_strength; | 1094 | adap->fe[0]->ops.tuner_ops.get_rf_strength; |
1095 | |||
1096 | if (adap->fe[1]) { | ||
1097 | fe = dvb_attach(r820t_attach, adap->fe[1], | ||
1098 | priv->demod_i2c_adapter, | ||
1099 | &rtl2832u_r828d_config); | ||
1100 | adap->fe[1]->ops.read_signal_strength = | ||
1101 | adap->fe[1]->ops.tuner_ops.get_rf_strength; | ||
1102 | } | ||
1046 | break; | 1103 | break; |
1047 | default: | 1104 | default: |
1048 | dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME, | 1105 | dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME, |
@@ -1097,11 +1154,19 @@ err: | |||
1097 | static void rtl28xxu_exit(struct dvb_usb_device *d) | 1154 | static void rtl28xxu_exit(struct dvb_usb_device *d) |
1098 | { | 1155 | { |
1099 | struct rtl28xxu_priv *priv = d->priv; | 1156 | struct rtl28xxu_priv *priv = d->priv; |
1100 | struct i2c_client *client = priv->client; | 1157 | struct i2c_client *client; |
1101 | 1158 | ||
1102 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | 1159 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
1103 | 1160 | ||
1104 | /* remove I2C tuner */ | 1161 | /* remove I2C tuner */ |
1162 | client = priv->client; | ||
1163 | if (client) { | ||
1164 | module_put(client->dev.driver->owner); | ||
1165 | i2c_unregister_device(client); | ||
1166 | } | ||
1167 | |||
1168 | /* remove I2C slave demod */ | ||
1169 | client = priv->i2c_client_slave_demod; | ||
1105 | if (client) { | 1170 | if (client) { |
1106 | module_put(client->dev.driver->owner); | 1171 | module_put(client->dev.driver->owner); |
1107 | i2c_unregister_device(client); | 1172 | i2c_unregister_device(client); |
@@ -1235,6 +1300,7 @@ err: | |||
1235 | static int rtl2832u_frontend_ctrl(struct dvb_frontend *fe, int onoff) | 1300 | static int rtl2832u_frontend_ctrl(struct dvb_frontend *fe, int onoff) |
1236 | { | 1301 | { |
1237 | struct dvb_usb_device *d = fe_to_d(fe); | 1302 | struct dvb_usb_device *d = fe_to_d(fe); |
1303 | struct dvb_usb_adapter *adap = fe_to_adap(fe); | ||
1238 | int ret; | 1304 | int ret; |
1239 | u8 val; | 1305 | u8 val; |
1240 | 1306 | ||
@@ -1250,6 +1316,13 @@ static int rtl2832u_frontend_ctrl(struct dvb_frontend *fe, int onoff) | |||
1250 | if (ret) | 1316 | if (ret) |
1251 | goto err; | 1317 | goto err; |
1252 | 1318 | ||
1319 | /* bypass slave demod TS through master demod */ | ||
1320 | if (fe->id == 1 && onoff) { | ||
1321 | ret = rtl2832_enable_external_ts_if(adap->fe[0]); | ||
1322 | if (ret) | ||
1323 | goto err; | ||
1324 | } | ||
1325 | |||
1253 | return 0; | 1326 | return 0; |
1254 | err: | 1327 | err: |
1255 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | 1328 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); |
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h index a26cab10f382..c1b00b9831c9 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h | |||
@@ -58,6 +58,10 @@ struct rtl28xxu_priv { | |||
58 | struct i2c_adapter *demod_i2c_adapter; | 58 | struct i2c_adapter *demod_i2c_adapter; |
59 | bool rc_active; | 59 | bool rc_active; |
60 | struct i2c_client *client; | 60 | struct i2c_client *client; |
61 | struct i2c_client *i2c_client_slave_demod; | ||
62 | #define SLAVE_DEMOD_NONE 0 | ||
63 | #define SLAVE_DEMOD_MN88472 1 | ||
64 | unsigned int slave_demod:1; | ||
61 | }; | 65 | }; |
62 | 66 | ||
63 | enum rtl28xxu_chip_id { | 67 | enum rtl28xxu_chip_id { |