diff options
Diffstat (limited to 'drivers/media/video/tuner-xc2028.c')
-rw-r--r-- | drivers/media/video/tuner-xc2028.c | 88 |
1 files changed, 51 insertions, 37 deletions
diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c index 9743331c895c..cf72f22986a4 100644 --- a/drivers/media/video/tuner-xc2028.c +++ b/drivers/media/video/tuner-xc2028.c | |||
@@ -50,6 +50,7 @@ static DEFINE_MUTEX(xc2028_list_mutex); | |||
50 | struct firmware_description { | 50 | struct firmware_description { |
51 | unsigned int type; | 51 | unsigned int type; |
52 | v4l2_std_id id; | 52 | v4l2_std_id id; |
53 | __u16 int_freq; | ||
53 | unsigned char *ptr; | 54 | unsigned char *ptr; |
54 | unsigned int size; | 55 | unsigned int size; |
55 | }; | 56 | }; |
@@ -58,6 +59,7 @@ struct firmware_properties { | |||
58 | unsigned int type; | 59 | unsigned int type; |
59 | v4l2_std_id id; | 60 | v4l2_std_id id; |
60 | v4l2_std_id std_req; | 61 | v4l2_std_id std_req; |
62 | __u16 int_freq; | ||
61 | unsigned int scode_table; | 63 | unsigned int scode_table; |
62 | int scode_nr; | 64 | int scode_nr; |
63 | }; | 65 | }; |
@@ -301,6 +303,7 @@ static int load_all_firmwares(struct dvb_frontend *fe) | |||
301 | while (p < endp) { | 303 | while (p < endp) { |
302 | __u32 type, size; | 304 | __u32 type, size; |
303 | v4l2_std_id id; | 305 | v4l2_std_id id; |
306 | __u16 int_freq = 0; | ||
304 | 307 | ||
305 | n++; | 308 | n++; |
306 | if (n >= n_array) { | 309 | if (n >= n_array) { |
@@ -321,6 +324,11 @@ static int load_all_firmwares(struct dvb_frontend *fe) | |||
321 | id = le64_to_cpu(*(v4l2_std_id *) p); | 324 | id = le64_to_cpu(*(v4l2_std_id *) p); |
322 | p += sizeof(id); | 325 | p += sizeof(id); |
323 | 326 | ||
327 | if (type & HAS_IF) { | ||
328 | int_freq = le16_to_cpu(*(__u16 *) p); | ||
329 | p += sizeof(int_freq); | ||
330 | } | ||
331 | |||
324 | size = le32_to_cpu(*(__u32 *) p); | 332 | size = le32_to_cpu(*(__u32 *) p); |
325 | p += sizeof(size); | 333 | p += sizeof(size); |
326 | 334 | ||
@@ -351,6 +359,7 @@ static int load_all_firmwares(struct dvb_frontend *fe) | |||
351 | priv->firm[n].type = type; | 359 | priv->firm[n].type = type; |
352 | priv->firm[n].id = id; | 360 | priv->firm[n].id = id; |
353 | priv->firm[n].size = size; | 361 | priv->firm[n].size = size; |
362 | priv->firm[n].int_freq = int_freq; | ||
354 | 363 | ||
355 | p += size; | 364 | p += size; |
356 | } | 365 | } |
@@ -565,7 +574,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type, | |||
565 | } | 574 | } |
566 | 575 | ||
567 | static int load_scode(struct dvb_frontend *fe, unsigned int type, | 576 | static int load_scode(struct dvb_frontend *fe, unsigned int type, |
568 | v4l2_std_id *id, int scode) | 577 | v4l2_std_id *id, __u16 int_freq, int scode) |
569 | { | 578 | { |
570 | struct xc2028_data *priv = fe->tuner_priv; | 579 | struct xc2028_data *priv = fe->tuner_priv; |
571 | int pos, rc; | 580 | int pos, rc; |
@@ -573,17 +582,34 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type, | |||
573 | 582 | ||
574 | tuner_dbg("%s called\n", __FUNCTION__); | 583 | tuner_dbg("%s called\n", __FUNCTION__); |
575 | 584 | ||
576 | pos = seek_firmware(fe, type, id); | 585 | if (!int_freq) { |
577 | if (pos < 0) | 586 | pos = seek_firmware(fe, type, id); |
578 | return pos; | 587 | if (pos < 0) |
588 | return pos; | ||
589 | } else { | ||
590 | for (pos = 0; pos < priv->firm_size; pos++) { | ||
591 | if ((priv->firm[pos].int_freq == int_freq) && | ||
592 | (type & HAS_IF)) | ||
593 | break; | ||
594 | } | ||
595 | if (pos == priv->firm_size) | ||
596 | return -ENOENT; | ||
597 | } | ||
579 | 598 | ||
580 | p = priv->firm[pos].ptr; | 599 | p = priv->firm[pos].ptr; |
581 | 600 | ||
582 | /* 16 SCODE entries per file; each SCODE entry is 12 bytes and | 601 | if (type & HAS_IF) { |
583 | * has a 2-byte size header in the firmware format. */ | 602 | if (priv->firm[pos].size != 12 * 16 || scode >= 16) |
584 | if (priv->firm[pos].size != 14 * 16 || scode >= 16 || | 603 | return -EINVAL; |
585 | le16_to_cpu(*(__u16 *)(p + 14 * scode)) != 12) | 604 | p += 12 * scode; |
586 | return -EINVAL; | 605 | } else { |
606 | /* 16 SCODE entries per file; each SCODE entry is 12 bytes and | ||
607 | * has a 2-byte size header in the firmware format. */ | ||
608 | if (priv->firm[pos].size != 14 * 16 || scode >= 16 || | ||
609 | le16_to_cpu(*(__u16 *)(p + 14 * scode)) != 12) | ||
610 | return -EINVAL; | ||
611 | p += 14 * scode + 2; | ||
612 | } | ||
587 | 613 | ||
588 | tuner_info("Loading SCODE for type="); | 614 | tuner_info("Loading SCODE for type="); |
589 | dump_firm_type(priv->firm[pos].type); | 615 | dump_firm_type(priv->firm[pos].type); |
@@ -597,7 +623,7 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type, | |||
597 | if (rc < 0) | 623 | if (rc < 0) |
598 | return -EIO; | 624 | return -EIO; |
599 | 625 | ||
600 | rc = i2c_send(priv, p + 14 * scode + 2, 12); | 626 | rc = i2c_send(priv, p, 12); |
601 | if (rc < 0) | 627 | if (rc < 0) |
602 | return -EIO; | 628 | return -EIO; |
603 | 629 | ||
@@ -609,7 +635,7 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type, | |||
609 | } | 635 | } |
610 | 636 | ||
611 | static int check_firmware(struct dvb_frontend *fe, unsigned int type, | 637 | static int check_firmware(struct dvb_frontend *fe, unsigned int type, |
612 | v4l2_std_id std) | 638 | v4l2_std_id std, __u16 int_freq) |
613 | { | 639 | { |
614 | struct xc2028_data *priv = fe->tuner_priv; | 640 | struct xc2028_data *priv = fe->tuner_priv; |
615 | struct firmware_properties new_fw; | 641 | struct firmware_properties new_fw; |
@@ -639,6 +665,7 @@ retry: | |||
639 | new_fw.std_req = std; | 665 | new_fw.std_req = std; |
640 | new_fw.scode_table = SCODE | priv->ctrl.scode_table; | 666 | new_fw.scode_table = SCODE | priv->ctrl.scode_table; |
641 | new_fw.scode_nr = 0; | 667 | new_fw.scode_nr = 0; |
668 | new_fw.int_freq = int_freq; | ||
642 | 669 | ||
643 | tuner_dbg("checking firmware, user requested type="); | 670 | tuner_dbg("checking firmware, user requested type="); |
644 | if (debug) { | 671 | if (debug) { |
@@ -719,8 +746,8 @@ skip_std_specific: | |||
719 | /* Load SCODE firmware, if exists */ | 746 | /* Load SCODE firmware, if exists */ |
720 | tuner_dbg("Trying to load scode %d\n", new_fw.scode_nr); | 747 | tuner_dbg("Trying to load scode %d\n", new_fw.scode_nr); |
721 | 748 | ||
722 | rc = load_scode(fe, new_fw.type | new_fw.scode_table, | 749 | rc = load_scode(fe, new_fw.type | new_fw.scode_table, &new_fw.id, |
723 | &new_fw.id, new_fw.scode_nr); | 750 | new_fw.int_freq, new_fw.scode_nr); |
724 | 751 | ||
725 | check_device: | 752 | check_device: |
726 | if (xc2028_get_reg(priv, 0x0004, &version) < 0 || | 753 | if (xc2028_get_reg(priv, 0x0004, &version) < 0 || |
@@ -810,9 +837,10 @@ ret: | |||
810 | #define DIV 15625 | 837 | #define DIV 15625 |
811 | 838 | ||
812 | static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, | 839 | static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, |
813 | enum tuner_mode new_mode, | 840 | enum tuner_mode new_mode, |
814 | unsigned int type, | 841 | unsigned int type, |
815 | v4l2_std_id std) | 842 | v4l2_std_id std, |
843 | u16 int_freq) | ||
816 | { | 844 | { |
817 | struct xc2028_data *priv = fe->tuner_priv; | 845 | struct xc2028_data *priv = fe->tuner_priv; |
818 | int rc = -EINVAL; | 846 | int rc = -EINVAL; |
@@ -825,7 +853,7 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, | |||
825 | 853 | ||
826 | tuner_dbg("should set frequency %d kHz\n", freq / 1000); | 854 | tuner_dbg("should set frequency %d kHz\n", freq / 1000); |
827 | 855 | ||
828 | if (check_firmware(fe, type, std) < 0) | 856 | if (check_firmware(fe, type, std, int_freq) < 0) |
829 | goto ret; | 857 | goto ret; |
830 | 858 | ||
831 | /* On some cases xc2028 can disable video output, if | 859 | /* On some cases xc2028 can disable video output, if |
@@ -896,7 +924,7 @@ static int xc2028_set_analog_freq(struct dvb_frontend *fe, | |||
896 | if (priv->ctrl.input1) | 924 | if (priv->ctrl.input1) |
897 | type |= INPUT1; | 925 | type |= INPUT1; |
898 | return generic_set_freq(fe, (625l * p->frequency) / 10, | 926 | return generic_set_freq(fe, (625l * p->frequency) / 10, |
899 | T_ANALOG_TV, type, 0); | 927 | T_ANALOG_TV, type, 0, 0); |
900 | } | 928 | } |
901 | 929 | ||
902 | /* if std is not defined, choose one */ | 930 | /* if std is not defined, choose one */ |
@@ -911,22 +939,9 @@ static int xc2028_set_analog_freq(struct dvb_frontend *fe, | |||
911 | p->std |= parse_audio_std_option(); | 939 | p->std |= parse_audio_std_option(); |
912 | 940 | ||
913 | return generic_set_freq(fe, 62500l * p->frequency, | 941 | return generic_set_freq(fe, 62500l * p->frequency, |
914 | T_ANALOG_TV, type, p->std); | 942 | T_ANALOG_TV, type, p->std, 0); |
915 | } | 943 | } |
916 | 944 | ||
917 | static unsigned int demod_type [] = { | ||
918 | [XC3028_FE_DEFAULT] = 0, | ||
919 | [XC3028_FE_LG60] = LG60, | ||
920 | [XC3028_FE_ATI638] = ATI638, | ||
921 | [XC3028_FE_OREN538] = OREN538, | ||
922 | [XC3028_FE_OREN36] = OREN36, | ||
923 | [XC3028_FE_TOYOTA388] = TOYOTA388, | ||
924 | [XC3028_FE_TOYOTA794] = TOYOTA794, | ||
925 | [XC3028_FE_DIBCOM52] = DIBCOM52, | ||
926 | [XC3028_FE_ZARLINK456] = ZARLINK456, | ||
927 | [XC3028_FE_CHINA] = CHINA, | ||
928 | }; | ||
929 | |||
930 | static int xc2028_set_params(struct dvb_frontend *fe, | 945 | static int xc2028_set_params(struct dvb_frontend *fe, |
931 | struct dvb_frontend_parameters *p) | 946 | struct dvb_frontend_parameters *p) |
932 | { | 947 | { |
@@ -978,13 +993,12 @@ static int xc2028_set_params(struct dvb_frontend *fe, | |||
978 | tuner_err("error: bandwidth not supported.\n"); | 993 | tuner_err("error: bandwidth not supported.\n"); |
979 | }; | 994 | }; |
980 | 995 | ||
981 | if (priv->ctrl.demod < 0 || priv->ctrl.demod > ARRAY_SIZE(demod_type)) | 996 | /* All S-code tables need a 200kHz shift */ |
982 | tuner_err("error: demod type invalid. Assuming default.\n"); | 997 | if (priv->ctrl.demod) |
983 | else | 998 | priv->ctrl.demod += 200; |
984 | type |= demod_type[priv->ctrl.demod]; | ||
985 | 999 | ||
986 | return generic_set_freq(fe, p->frequency, | 1000 | return generic_set_freq(fe, p->frequency, |
987 | T_DIGITAL_TV, type, 0); | 1001 | T_DIGITAL_TV, type, 0, priv->ctrl.demod); |
988 | } | 1002 | } |
989 | 1003 | ||
990 | static int xc2028_sleep(struct dvb_frontend *fe) | 1004 | static int xc2028_sleep(struct dvb_frontend *fe) |