diff options
Diffstat (limited to 'drivers/media/common/tuners/tuner-xc2028.c')
-rw-r--r-- | drivers/media/common/tuners/tuner-xc2028.c | 74 |
1 files changed, 45 insertions, 29 deletions
diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c index 4dd1d2421cc5..b65e6803e6c6 100644 --- a/drivers/media/common/tuners/tuner-xc2028.c +++ b/drivers/media/common/tuners/tuner-xc2028.c | |||
@@ -71,9 +71,6 @@ struct firmware_properties { | |||
71 | struct xc2028_data { | 71 | struct xc2028_data { |
72 | struct list_head hybrid_tuner_instance_list; | 72 | struct list_head hybrid_tuner_instance_list; |
73 | struct tuner_i2c_props i2c_props; | 73 | struct tuner_i2c_props i2c_props; |
74 | int (*tuner_callback) (void *dev, | ||
75 | int command, int arg); | ||
76 | void *video_dev; | ||
77 | __u32 frequency; | 74 | __u32 frequency; |
78 | 75 | ||
79 | struct firmware_description *firm; | 76 | struct firmware_description *firm; |
@@ -492,6 +489,23 @@ ret: | |||
492 | return i; | 489 | return i; |
493 | } | 490 | } |
494 | 491 | ||
492 | static inline int do_tuner_callback(struct dvb_frontend *fe, int cmd, int arg) | ||
493 | { | ||
494 | struct xc2028_data *priv = fe->tuner_priv; | ||
495 | |||
496 | /* analog side (tuner-core) uses i2c_adap->algo_data. | ||
497 | * digital side is not guaranteed to have algo_data defined. | ||
498 | * | ||
499 | * digital side will always have fe->dvb defined. | ||
500 | * analog side (tuner-core) doesn't (yet) define fe->dvb. | ||
501 | */ | ||
502 | |||
503 | return (!fe->callback) ? -EINVAL : | ||
504 | fe->callback(((fe->dvb) && (fe->dvb->priv)) ? | ||
505 | fe->dvb->priv : priv->i2c_props.adap->algo_data, | ||
506 | DVB_FRONTEND_COMPONENT_TUNER, cmd, arg); | ||
507 | } | ||
508 | |||
495 | static int load_firmware(struct dvb_frontend *fe, unsigned int type, | 509 | static int load_firmware(struct dvb_frontend *fe, unsigned int type, |
496 | v4l2_std_id *id) | 510 | v4l2_std_id *id) |
497 | { | 511 | { |
@@ -530,8 +544,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type, | |||
530 | 544 | ||
531 | if (!size) { | 545 | if (!size) { |
532 | /* Special callback command received */ | 546 | /* Special callback command received */ |
533 | rc = priv->tuner_callback(priv->video_dev, | 547 | rc = do_tuner_callback(fe, XC2028_TUNER_RESET, 0); |
534 | XC2028_TUNER_RESET, 0); | ||
535 | if (rc < 0) { | 548 | if (rc < 0) { |
536 | tuner_err("Error at RESET code %d\n", | 549 | tuner_err("Error at RESET code %d\n", |
537 | (*p) & 0x7f); | 550 | (*p) & 0x7f); |
@@ -542,8 +555,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type, | |||
542 | if (size >= 0xff00) { | 555 | if (size >= 0xff00) { |
543 | switch (size) { | 556 | switch (size) { |
544 | case 0xff00: | 557 | case 0xff00: |
545 | rc = priv->tuner_callback(priv->video_dev, | 558 | rc = do_tuner_callback(fe, XC2028_RESET_CLK, 0); |
546 | XC2028_RESET_CLK, 0); | ||
547 | if (rc < 0) { | 559 | if (rc < 0) { |
548 | tuner_err("Error at RESET code %d\n", | 560 | tuner_err("Error at RESET code %d\n", |
549 | (*p) & 0x7f); | 561 | (*p) & 0x7f); |
@@ -715,8 +727,7 @@ retry: | |||
715 | memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); | 727 | memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); |
716 | 728 | ||
717 | /* Reset is needed before loading firmware */ | 729 | /* Reset is needed before loading firmware */ |
718 | rc = priv->tuner_callback(priv->video_dev, | 730 | rc = do_tuner_callback(fe, XC2028_TUNER_RESET, 0); |
719 | XC2028_TUNER_RESET, 0); | ||
720 | if (rc < 0) | 731 | if (rc < 0) |
721 | goto fail; | 732 | goto fail; |
722 | 733 | ||
@@ -933,7 +944,7 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, | |||
933 | The reset CLK is needed only with tm6000. | 944 | The reset CLK is needed only with tm6000. |
934 | Driver should work fine even if this fails. | 945 | Driver should work fine even if this fails. |
935 | */ | 946 | */ |
936 | priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1); | 947 | do_tuner_callback(fe, XC2028_RESET_CLK, 1); |
937 | 948 | ||
938 | msleep(10); | 949 | msleep(10); |
939 | 950 | ||
@@ -1002,11 +1013,6 @@ static int xc2028_set_params(struct dvb_frontend *fe, | |||
1002 | 1013 | ||
1003 | tuner_dbg("%s called\n", __func__); | 1014 | tuner_dbg("%s called\n", __func__); |
1004 | 1015 | ||
1005 | if (priv->ctrl.d2633) | ||
1006 | type |= D2633; | ||
1007 | else | ||
1008 | type |= D2620; | ||
1009 | |||
1010 | switch(fe->ops.info.type) { | 1016 | switch(fe->ops.info.type) { |
1011 | case FE_OFDM: | 1017 | case FE_OFDM: |
1012 | bw = p->u.ofdm.bandwidth; | 1018 | bw = p->u.ofdm.bandwidth; |
@@ -1021,10 +1027,8 @@ static int xc2028_set_params(struct dvb_frontend *fe, | |||
1021 | break; | 1027 | break; |
1022 | case FE_ATSC: | 1028 | case FE_ATSC: |
1023 | bw = BANDWIDTH_6_MHZ; | 1029 | bw = BANDWIDTH_6_MHZ; |
1024 | /* The only ATSC firmware (at least on v2.7) is D2633, | 1030 | /* The only ATSC firmware (at least on v2.7) is D2633 */ |
1025 | so overrides ctrl->d2633 */ | 1031 | type |= ATSC | D2633; |
1026 | type |= ATSC| D2633; | ||
1027 | type &= ~D2620; | ||
1028 | break; | 1032 | break; |
1029 | /* DVB-S is not supported */ | 1033 | /* DVB-S is not supported */ |
1030 | default: | 1034 | default: |
@@ -1057,6 +1061,28 @@ static int xc2028_set_params(struct dvb_frontend *fe, | |||
1057 | tuner_err("error: bandwidth not supported.\n"); | 1061 | tuner_err("error: bandwidth not supported.\n"); |
1058 | }; | 1062 | }; |
1059 | 1063 | ||
1064 | /* | ||
1065 | Selects between D2633 or D2620 firmware. | ||
1066 | It doesn't make sense for ATSC, since it should be D2633 on all cases | ||
1067 | */ | ||
1068 | if (fe->ops.info.type != FE_ATSC) { | ||
1069 | switch (priv->ctrl.type) { | ||
1070 | case XC2028_D2633: | ||
1071 | type |= D2633; | ||
1072 | break; | ||
1073 | case XC2028_D2620: | ||
1074 | type |= D2620; | ||
1075 | break; | ||
1076 | case XC2028_AUTO: | ||
1077 | default: | ||
1078 | /* Zarlink seems to need D2633 */ | ||
1079 | if (priv->ctrl.demod == XC3028_FE_ZARLINK456) | ||
1080 | type |= D2633; | ||
1081 | else | ||
1082 | type |= D2620; | ||
1083 | } | ||
1084 | } | ||
1085 | |||
1060 | /* All S-code tables need a 200kHz shift */ | 1086 | /* All S-code tables need a 200kHz shift */ |
1061 | if (priv->ctrl.demod) | 1087 | if (priv->ctrl.demod) |
1062 | demod = priv->ctrl.demod + 200; | 1088 | demod = priv->ctrl.demod + 200; |
@@ -1177,20 +1203,10 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, | |||
1177 | break; | 1203 | break; |
1178 | case 1: | 1204 | case 1: |
1179 | /* new tuner instance */ | 1205 | /* new tuner instance */ |
1180 | priv->tuner_callback = cfg->callback; | ||
1181 | priv->ctrl.max_len = 13; | 1206 | priv->ctrl.max_len = 13; |
1182 | 1207 | ||
1183 | mutex_init(&priv->lock); | 1208 | mutex_init(&priv->lock); |
1184 | 1209 | ||
1185 | /* analog side (tuner-core) uses i2c_adap->algo_data. | ||
1186 | * digital side is not guaranteed to have algo_data defined. | ||
1187 | * | ||
1188 | * digital side will always have fe->dvb defined. | ||
1189 | * analog side (tuner-core) doesn't (yet) define fe->dvb. | ||
1190 | */ | ||
1191 | priv->video_dev = ((fe->dvb) && (fe->dvb->priv)) ? | ||
1192 | fe->dvb->priv : cfg->i2c_adap->algo_data; | ||
1193 | |||
1194 | fe->tuner_priv = priv; | 1210 | fe->tuner_priv = priv; |
1195 | break; | 1211 | break; |
1196 | case 2: | 1212 | case 2: |