diff options
author | Antti Palosaari <crope@iki.fi> | 2014-08-03 20:47:10 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@osg.samsung.com> | 2014-09-21 18:59:13 -0400 |
commit | f80f2ae2135966dcd21020dcdca066d3fe5f06df (patch) | |
tree | 70d9cc0b31cebcb17d6e008e6b5047a0a0b14875 /drivers/media/usb | |
parent | 3ab779c0399276c82a6a64610e7c9c4d5bb267f2 (diff) |
[media] anysee: convert tda18212 tuner to I2C client
Used tda18212 tuner is implemented as I2C driver. Implement I2C
client to anysee and use it for tda18212.
Signed-off-by: Antti Palosaari <crope@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
Diffstat (limited to 'drivers/media/usb')
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/anysee.c | 185 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/anysee.h | 3 |
2 files changed, 152 insertions, 36 deletions
diff --git a/drivers/media/usb/dvb-usb-v2/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c index e4a2382196f0..d3c5f230e97a 100644 --- a/drivers/media/usb/dvb-usb-v2/anysee.c +++ b/drivers/media/usb/dvb-usb-v2/anysee.c | |||
@@ -332,7 +332,6 @@ static struct tda10023_config anysee_tda10023_tda18212_config = { | |||
332 | }; | 332 | }; |
333 | 333 | ||
334 | static struct tda18212_config anysee_tda18212_config = { | 334 | static struct tda18212_config anysee_tda18212_config = { |
335 | .i2c_address = (0xc0 >> 1), | ||
336 | .if_dvbt_6 = 4150, | 335 | .if_dvbt_6 = 4150, |
337 | .if_dvbt_7 = 4150, | 336 | .if_dvbt_7 = 4150, |
338 | .if_dvbt_8 = 4150, | 337 | .if_dvbt_8 = 4150, |
@@ -340,7 +339,6 @@ static struct tda18212_config anysee_tda18212_config = { | |||
340 | }; | 339 | }; |
341 | 340 | ||
342 | static struct tda18212_config anysee_tda18212_config2 = { | 341 | static struct tda18212_config anysee_tda18212_config2 = { |
343 | .i2c_address = 0x60 /* (0xc0 >> 1) */, | ||
344 | .if_dvbt_6 = 3550, | 342 | .if_dvbt_6 = 3550, |
345 | .if_dvbt_7 = 3700, | 343 | .if_dvbt_7 = 3700, |
346 | .if_dvbt_8 = 4150, | 344 | .if_dvbt_8 = 4150, |
@@ -632,6 +630,92 @@ error: | |||
632 | return ret; | 630 | return ret; |
633 | } | 631 | } |
634 | 632 | ||
633 | static int anysee_add_i2c_dev(struct dvb_usb_device *d, char *type, u8 addr, | ||
634 | void *platform_data) | ||
635 | { | ||
636 | int ret, num; | ||
637 | struct anysee_state *state = d_to_priv(d); | ||
638 | struct i2c_client *client; | ||
639 | struct i2c_adapter *adapter = &d->i2c_adap; | ||
640 | struct i2c_board_info board_info = { | ||
641 | .addr = addr, | ||
642 | .platform_data = platform_data, | ||
643 | }; | ||
644 | |||
645 | strlcpy(board_info.type, type, I2C_NAME_SIZE); | ||
646 | |||
647 | /* find first free client */ | ||
648 | for (num = 0; num < ANYSEE_I2C_CLIENT_MAX; num++) { | ||
649 | if (state->i2c_client[num] == NULL) | ||
650 | break; | ||
651 | } | ||
652 | |||
653 | dev_dbg(&d->udev->dev, "%s: num=%d\n", __func__, num); | ||
654 | |||
655 | if (num == ANYSEE_I2C_CLIENT_MAX) { | ||
656 | dev_err(&d->udev->dev, "%s: I2C client out of index\n", | ||
657 | KBUILD_MODNAME); | ||
658 | ret = -ENODEV; | ||
659 | goto err; | ||
660 | } | ||
661 | |||
662 | request_module(board_info.type); | ||
663 | |||
664 | /* register I2C device */ | ||
665 | client = i2c_new_device(adapter, &board_info); | ||
666 | if (client == NULL || client->dev.driver == NULL) { | ||
667 | ret = -ENODEV; | ||
668 | goto err; | ||
669 | } | ||
670 | |||
671 | /* increase I2C driver usage count */ | ||
672 | if (!try_module_get(client->dev.driver->owner)) { | ||
673 | i2c_unregister_device(client); | ||
674 | ret = -ENODEV; | ||
675 | goto err; | ||
676 | } | ||
677 | |||
678 | state->i2c_client[num] = client; | ||
679 | return 0; | ||
680 | err: | ||
681 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
682 | return ret; | ||
683 | } | ||
684 | |||
685 | static void anysee_del_i2c_dev(struct dvb_usb_device *d) | ||
686 | { | ||
687 | int num; | ||
688 | struct anysee_state *state = d_to_priv(d); | ||
689 | struct i2c_client *client; | ||
690 | |||
691 | /* find last used client */ | ||
692 | num = ANYSEE_I2C_CLIENT_MAX; | ||
693 | while (num--) { | ||
694 | if (state->i2c_client[num] != NULL) | ||
695 | break; | ||
696 | } | ||
697 | |||
698 | dev_dbg(&d->udev->dev, "%s: num=%d\n", __func__, num); | ||
699 | |||
700 | if (num == -1) { | ||
701 | dev_err(&d->udev->dev, "%s: I2C client out of index\n", | ||
702 | KBUILD_MODNAME); | ||
703 | goto err; | ||
704 | } | ||
705 | |||
706 | client = state->i2c_client[num]; | ||
707 | |||
708 | /* decrease I2C driver usage count */ | ||
709 | module_put(client->dev.driver->owner); | ||
710 | |||
711 | /* unregister I2C device */ | ||
712 | i2c_unregister_device(client); | ||
713 | |||
714 | state->i2c_client[num] = NULL; | ||
715 | err: | ||
716 | dev_dbg(&d->udev->dev, "%s: failed\n", __func__); | ||
717 | } | ||
718 | |||
635 | static int anysee_frontend_attach(struct dvb_usb_adapter *adap) | 719 | static int anysee_frontend_attach(struct dvb_usb_adapter *adap) |
636 | { | 720 | { |
637 | struct anysee_state *state = adap_to_priv(adap); | 721 | struct anysee_state *state = adap_to_priv(adap); |
@@ -640,12 +724,12 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) | |||
640 | u8 tmp; | 724 | u8 tmp; |
641 | struct i2c_msg msg[2] = { | 725 | struct i2c_msg msg[2] = { |
642 | { | 726 | { |
643 | .addr = anysee_tda18212_config.i2c_address, | 727 | .addr = 0x60, |
644 | .flags = 0, | 728 | .flags = 0, |
645 | .len = 1, | 729 | .len = 1, |
646 | .buf = "\x00", | 730 | .buf = "\x00", |
647 | }, { | 731 | }, { |
648 | .addr = anysee_tda18212_config.i2c_address, | 732 | .addr = 0x60, |
649 | .flags = I2C_M_RD, | 733 | .flags = I2C_M_RD, |
650 | .len = 1, | 734 | .len = 1, |
651 | .buf = &tmp, | 735 | .buf = &tmp, |
@@ -723,9 +807,11 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) | |||
723 | /* probe TDA18212 */ | 807 | /* probe TDA18212 */ |
724 | tmp = 0; | 808 | tmp = 0; |
725 | ret = i2c_transfer(&d->i2c_adap, msg, 2); | 809 | ret = i2c_transfer(&d->i2c_adap, msg, 2); |
726 | if (ret == 2 && tmp == 0xc7) | 810 | if (ret == 2 && tmp == 0xc7) { |
727 | dev_dbg(&d->udev->dev, "%s: TDA18212 found\n", | 811 | dev_dbg(&d->udev->dev, "%s: TDA18212 found\n", |
728 | __func__); | 812 | __func__); |
813 | state->has_tda18212 = true; | ||
814 | } | ||
729 | else | 815 | else |
730 | tmp = 0; | 816 | tmp = 0; |
731 | 817 | ||
@@ -939,46 +1025,63 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap) | |||
939 | * fails attach old simple PLL. */ | 1025 | * fails attach old simple PLL. */ |
940 | 1026 | ||
941 | /* attach tuner */ | 1027 | /* attach tuner */ |
942 | fe = dvb_attach(tda18212_attach, adap->fe[0], &d->i2c_adap, | 1028 | if (state->has_tda18212) { |
943 | &anysee_tda18212_config); | 1029 | struct tda18212_config tda18212_config = |
1030 | anysee_tda18212_config; | ||
944 | 1031 | ||
945 | if (fe && adap->fe[1]) { | 1032 | tda18212_config.fe = adap->fe[0]; |
946 | /* attach tuner for 2nd FE */ | 1033 | ret = anysee_add_i2c_dev(d, "tda18212", 0x60, |
947 | fe = dvb_attach(tda18212_attach, adap->fe[1], | 1034 | &tda18212_config); |
948 | &d->i2c_adap, &anysee_tda18212_config); | 1035 | if (ret) |
949 | break; | 1036 | goto err; |
950 | } else if (fe) { | 1037 | |
951 | break; | 1038 | /* copy tuner ops for 2nd FE as tuner is shared */ |
952 | } | 1039 | if (adap->fe[1]) { |
953 | 1040 | adap->fe[1]->tuner_priv = | |
954 | /* attach tuner */ | 1041 | adap->fe[0]->tuner_priv; |
955 | fe = dvb_attach(dvb_pll_attach, adap->fe[0], (0xc0 >> 1), | 1042 | memcpy(&adap->fe[1]->ops.tuner_ops, |
956 | &d->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A); | 1043 | &adap->fe[0]->ops.tuner_ops, |
1044 | sizeof(struct dvb_tuner_ops)); | ||
1045 | } | ||
957 | 1046 | ||
958 | if (fe && adap->fe[1]) { | 1047 | return 0; |
959 | /* attach tuner for 2nd FE */ | 1048 | } else { |
960 | fe = dvb_attach(dvb_pll_attach, adap->fe[1], | 1049 | /* attach tuner */ |
1050 | fe = dvb_attach(dvb_pll_attach, adap->fe[0], | ||
961 | (0xc0 >> 1), &d->i2c_adap, | 1051 | (0xc0 >> 1), &d->i2c_adap, |
962 | DVB_PLL_SAMSUNG_DTOS403IH102A); | 1052 | DVB_PLL_SAMSUNG_DTOS403IH102A); |
1053 | |||
1054 | if (fe && adap->fe[1]) { | ||
1055 | /* attach tuner for 2nd FE */ | ||
1056 | fe = dvb_attach(dvb_pll_attach, adap->fe[1], | ||
1057 | (0xc0 >> 1), &d->i2c_adap, | ||
1058 | DVB_PLL_SAMSUNG_DTOS403IH102A); | ||
1059 | } | ||
963 | } | 1060 | } |
964 | 1061 | ||
965 | break; | 1062 | break; |
966 | case ANYSEE_HW_508TC: /* 18 */ | 1063 | case ANYSEE_HW_508TC: /* 18 */ |
967 | case ANYSEE_HW_508PTC: /* 21 */ | 1064 | case ANYSEE_HW_508PTC: /* 21 */ |
1065 | { | ||
968 | /* E7 TC */ | 1066 | /* E7 TC */ |
969 | /* E7 PTC */ | 1067 | /* E7 PTC */ |
1068 | struct tda18212_config tda18212_config = anysee_tda18212_config; | ||
970 | 1069 | ||
971 | /* attach tuner */ | 1070 | tda18212_config.fe = adap->fe[0]; |
972 | fe = dvb_attach(tda18212_attach, adap->fe[0], &d->i2c_adap, | 1071 | ret = anysee_add_i2c_dev(d, "tda18212", 0x60, &tda18212_config); |
973 | &anysee_tda18212_config); | 1072 | if (ret) |
974 | 1073 | goto err; | |
975 | if (fe) { | 1074 | |
976 | /* attach tuner for 2nd FE */ | 1075 | /* copy tuner ops for 2nd FE as tuner is shared */ |
977 | fe = dvb_attach(tda18212_attach, adap->fe[1], | 1076 | if (adap->fe[1]) { |
978 | &d->i2c_adap, &anysee_tda18212_config); | 1077 | adap->fe[1]->tuner_priv = adap->fe[0]->tuner_priv; |
1078 | memcpy(&adap->fe[1]->ops.tuner_ops, | ||
1079 | &adap->fe[0]->ops.tuner_ops, | ||
1080 | sizeof(struct dvb_tuner_ops)); | ||
979 | } | 1081 | } |
980 | 1082 | ||
981 | break; | 1083 | return 0; |
1084 | } | ||
982 | case ANYSEE_HW_508S2: /* 19 */ | 1085 | case ANYSEE_HW_508S2: /* 19 */ |
983 | case ANYSEE_HW_508PS2: /* 22 */ | 1086 | case ANYSEE_HW_508PS2: /* 22 */ |
984 | /* E7 S2 */ | 1087 | /* E7 S2 */ |
@@ -997,13 +1100,18 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap) | |||
997 | break; | 1100 | break; |
998 | 1101 | ||
999 | case ANYSEE_HW_508T2C: /* 20 */ | 1102 | case ANYSEE_HW_508T2C: /* 20 */ |
1103 | { | ||
1000 | /* E7 T2C */ | 1104 | /* E7 T2C */ |
1105 | struct tda18212_config tda18212_config = | ||
1106 | anysee_tda18212_config2; | ||
1001 | 1107 | ||
1002 | /* attach tuner */ | 1108 | tda18212_config.fe = adap->fe[0]; |
1003 | fe = dvb_attach(tda18212_attach, adap->fe[0], &d->i2c_adap, | 1109 | ret = anysee_add_i2c_dev(d, "tda18212", 0x60, &tda18212_config); |
1004 | &anysee_tda18212_config2); | 1110 | if (ret) |
1111 | goto err; | ||
1005 | 1112 | ||
1006 | break; | 1113 | return 0; |
1114 | } | ||
1007 | default: | 1115 | default: |
1008 | fe = NULL; | 1116 | fe = NULL; |
1009 | } | 1117 | } |
@@ -1012,7 +1120,7 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap) | |||
1012 | ret = 0; | 1120 | ret = 0; |
1013 | else | 1121 | else |
1014 | ret = -ENODEV; | 1122 | ret = -ENODEV; |
1015 | 1123 | err: | |
1016 | return ret; | 1124 | return ret; |
1017 | } | 1125 | } |
1018 | 1126 | ||
@@ -1270,6 +1378,11 @@ static int anysee_init(struct dvb_usb_device *d) | |||
1270 | 1378 | ||
1271 | static void anysee_exit(struct dvb_usb_device *d) | 1379 | static void anysee_exit(struct dvb_usb_device *d) |
1272 | { | 1380 | { |
1381 | struct anysee_state *state = d_to_priv(d); | ||
1382 | |||
1383 | if (state->i2c_client[0]) | ||
1384 | anysee_del_i2c_dev(d); | ||
1385 | |||
1273 | return anysee_ci_release(d); | 1386 | return anysee_ci_release(d); |
1274 | } | 1387 | } |
1275 | 1388 | ||
diff --git a/drivers/media/usb/dvb-usb-v2/anysee.h b/drivers/media/usb/dvb-usb-v2/anysee.h index 8f426d9fc6e1..3ca2bca4ebaf 100644 --- a/drivers/media/usb/dvb-usb-v2/anysee.h +++ b/drivers/media/usb/dvb-usb-v2/anysee.h | |||
@@ -55,8 +55,11 @@ struct anysee_state { | |||
55 | u8 buf[64]; | 55 | u8 buf[64]; |
56 | u8 seq; | 56 | u8 seq; |
57 | u8 hw; /* PCB ID */ | 57 | u8 hw; /* PCB ID */ |
58 | #define ANYSEE_I2C_CLIENT_MAX 1 | ||
59 | struct i2c_client *i2c_client[ANYSEE_I2C_CLIENT_MAX]; | ||
58 | u8 fe_id:1; /* frondend ID */ | 60 | u8 fe_id:1; /* frondend ID */ |
59 | u8 has_ci:1; | 61 | u8 has_ci:1; |
62 | u8 has_tda18212:1; | ||
60 | u8 ci_attached:1; | 63 | u8 ci_attached:1; |
61 | struct dvb_ca_en50221 ci; | 64 | struct dvb_ca_en50221 ci; |
62 | unsigned long ci_cam_ready; /* jiffies */ | 65 | unsigned long ci_cam_ready; /* jiffies */ |