Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

V4L/DVB (6676): Improve s-code support

s-code tables are related to IF frequency used for video demodulation.

The s-codes for analog are automatically loaded, according with video standard.
However, for digital, they will depend on the IF of the demoduler chip. IF of
the demoduler.

Before this patch, only a few IF's where possible to use. This patch allows
selecting any IF defined at firmware file.

Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>

+66 -51
+3
drivers/media/video/tuner-xc2028-types.h
··· 82 82 #define INPUT2 (1 << 28) 83 83 #define SCODE (1 << 29) 84 84 85 + /* This flag identifies that the scode table has a new format */ 86 + #define HAS_IF (1 << 30) 87 + 85 88 #define SCODE_TYPES (MTS|DTV6|QAM|DTV7|DTV78|DTV8|LCD|NOGD|MONO|ATSC|IF| \ 86 89 LG60|ATI638|OREN538|OREN36|TOYOTA388|TOYOTA794| \ 87 90 DIBCOM52|ZARLINK456|CHINA|F6MHZ|SCODE)
+51 -37
drivers/media/video/tuner-xc2028.c
··· 50 50 struct firmware_description { 51 51 unsigned int type; 52 52 v4l2_std_id id; 53 + __u16 int_freq; 53 54 unsigned char *ptr; 54 55 unsigned int size; 55 56 }; ··· 59 58 unsigned int type; 60 59 v4l2_std_id id; 61 60 v4l2_std_id std_req; 61 + __u16 int_freq; 62 62 unsigned int scode_table; 63 63 int scode_nr; 64 64 }; ··· 303 301 while (p < endp) { 304 302 __u32 type, size; 305 303 v4l2_std_id id; 304 + __u16 int_freq = 0; 306 305 307 306 n++; 308 307 if (n >= n_array) { ··· 323 320 324 321 id = le64_to_cpu(*(v4l2_std_id *) p); 325 322 p += sizeof(id); 323 + 324 + if (type & HAS_IF) { 325 + int_freq = le16_to_cpu(*(__u16 *) p); 326 + p += sizeof(int_freq); 327 + } 326 328 327 329 size = le32_to_cpu(*(__u32 *) p); 328 330 p += sizeof(size); ··· 359 351 priv->firm[n].type = type; 360 352 priv->firm[n].id = id; 361 353 priv->firm[n].size = size; 354 + priv->firm[n].int_freq = int_freq; 362 355 363 356 p += size; 364 357 } ··· 574 565 } 575 566 576 567 static int load_scode(struct dvb_frontend *fe, unsigned int type, 577 - v4l2_std_id *id, int scode) 568 + v4l2_std_id *id, __u16 int_freq, int scode) 578 569 { 579 570 struct xc2028_data *priv = fe->tuner_priv; 580 571 int pos, rc; ··· 582 573 583 574 tuner_dbg("%s called\n", __FUNCTION__); 584 575 585 - pos = seek_firmware(fe, type, id); 586 - if (pos < 0) 587 - return pos; 576 + if (!int_freq) { 577 + pos = seek_firmware(fe, type, id); 578 + if (pos < 0) 579 + return pos; 580 + } else { 581 + for (pos = 0; pos < priv->firm_size; pos++) { 582 + if ((priv->firm[pos].int_freq == int_freq) && 583 + (type & HAS_IF)) 584 + break; 585 + } 586 + if (pos == priv->firm_size) 587 + return -ENOENT; 588 + } 588 589 589 590 p = priv->firm[pos].ptr; 590 591 591 - /* 16 SCODE entries per file; each SCODE entry is 12 bytes and 592 - * has a 2-byte size header in the firmware format. */ 593 - if (priv->firm[pos].size != 14 * 16 || scode >= 16 || 594 - le16_to_cpu(*(__u16 *)(p + 14 * scode)) != 12) 595 - return -EINVAL; 592 + if (type & HAS_IF) { 593 + if (priv->firm[pos].size != 12 * 16 || scode >= 16) 594 + return -EINVAL; 595 + p += 12 * scode; 596 + } else { 597 + /* 16 SCODE entries per file; each SCODE entry is 12 bytes and 598 + * has a 2-byte size header in the firmware format. */ 599 + if (priv->firm[pos].size != 14 * 16 || scode >= 16 || 600 + le16_to_cpu(*(__u16 *)(p + 14 * scode)) != 12) 601 + return -EINVAL; 602 + p += 14 * scode + 2; 603 + } 596 604 597 605 tuner_info("Loading SCODE for type="); 598 606 dump_firm_type(priv->firm[pos].type); ··· 623 597 if (rc < 0) 624 598 return -EIO; 625 599 626 - rc = i2c_send(priv, p + 14 * scode + 2, 12); 600 + rc = i2c_send(priv, p, 12); 627 601 if (rc < 0) 628 602 return -EIO; 629 603 ··· 635 609 } 636 610 637 611 static int check_firmware(struct dvb_frontend *fe, unsigned int type, 638 - v4l2_std_id std) 612 + v4l2_std_id std, __u16 int_freq) 639 613 { 640 614 struct xc2028_data *priv = fe->tuner_priv; 641 615 struct firmware_properties new_fw; ··· 665 639 new_fw.std_req = std; 666 640 new_fw.scode_table = SCODE | priv->ctrl.scode_table; 667 641 new_fw.scode_nr = 0; 642 + new_fw.int_freq = int_freq; 668 643 669 644 tuner_dbg("checking firmware, user requested type="); 670 645 if (debug) { ··· 746 719 /* Load SCODE firmware, if exists */ 747 720 tuner_dbg("Trying to load scode %d\n", new_fw.scode_nr); 748 721 749 - rc = load_scode(fe, new_fw.type | new_fw.scode_table, 750 - &new_fw.id, new_fw.scode_nr); 722 + rc = load_scode(fe, new_fw.type | new_fw.scode_table, &new_fw.id, 723 + new_fw.int_freq, new_fw.scode_nr); 751 724 752 725 check_device: 753 726 if (xc2028_get_reg(priv, 0x0004, &version) < 0 || ··· 837 810 #define DIV 15625 838 811 839 812 static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, 840 - enum tuner_mode new_mode, 841 - unsigned int type, 842 - v4l2_std_id std) 813 + enum tuner_mode new_mode, 814 + unsigned int type, 815 + v4l2_std_id std, 816 + u16 int_freq) 843 817 { 844 818 struct xc2028_data *priv = fe->tuner_priv; 845 819 int rc = -EINVAL; ··· 853 825 854 826 tuner_dbg("should set frequency %d kHz\n", freq / 1000); 855 827 856 - if (check_firmware(fe, type, std) < 0) 828 + if (check_firmware(fe, type, std, int_freq) < 0) 857 829 goto ret; 858 830 859 831 /* On some cases xc2028 can disable video output, if ··· 924 896 if (priv->ctrl.input1) 925 897 type |= INPUT1; 926 898 return generic_set_freq(fe, (625l * p->frequency) / 10, 927 - T_ANALOG_TV, type, 0); 899 + T_ANALOG_TV, type, 0, 0); 928 900 } 929 901 930 902 /* if std is not defined, choose one */ ··· 939 911 p->std |= parse_audio_std_option(); 940 912 941 913 return generic_set_freq(fe, 62500l * p->frequency, 942 - T_ANALOG_TV, type, p->std); 914 + T_ANALOG_TV, type, p->std, 0); 943 915 } 944 - 945 - static unsigned int demod_type [] = { 946 - [XC3028_FE_DEFAULT] = 0, 947 - [XC3028_FE_LG60] = LG60, 948 - [XC3028_FE_ATI638] = ATI638, 949 - [XC3028_FE_OREN538] = OREN538, 950 - [XC3028_FE_OREN36] = OREN36, 951 - [XC3028_FE_TOYOTA388] = TOYOTA388, 952 - [XC3028_FE_TOYOTA794] = TOYOTA794, 953 - [XC3028_FE_DIBCOM52] = DIBCOM52, 954 - [XC3028_FE_ZARLINK456] = ZARLINK456, 955 - [XC3028_FE_CHINA] = CHINA, 956 - }; 957 916 958 917 static int xc2028_set_params(struct dvb_frontend *fe, 959 918 struct dvb_frontend_parameters *p) ··· 993 978 tuner_err("error: bandwidth not supported.\n"); 994 979 }; 995 980 996 - if (priv->ctrl.demod < 0 || priv->ctrl.demod > ARRAY_SIZE(demod_type)) 997 - tuner_err("error: demod type invalid. Assuming default.\n"); 998 - else 999 - type |= demod_type[priv->ctrl.demod]; 981 + /* All S-code tables need a 200kHz shift */ 982 + if (priv->ctrl.demod) 983 + priv->ctrl.demod += 200; 1000 984 1001 985 return generic_set_freq(fe, p->frequency, 1002 - T_DIGITAL_TV, type, 0); 986 + T_DIGITAL_TV, type, 0, priv->ctrl.demod); 1003 987 } 1004 988 1005 989 static int xc2028_sleep(struct dvb_frontend *fe)
+12 -14
drivers/media/video/tuner-xc2028.h
··· 11 11 12 12 #define XC2028_DEFAULT_FIRMWARE "xc3028-v27.fw" 13 13 14 - enum xc2028_demod_types 15 - { 16 - XC3028_FE_DEFAULT = 0, 17 - XC3028_FE_LG60, /* IF = 6.00 MHz */ 18 - XC3028_FE_ATI638, /* IF = 6.38 MHz */ 19 - XC3028_FE_OREN538, /* IF = 5.38 MHz */ 20 - XC3028_FE_OREN36, /* IF = 3.60 MHz */ 21 - XC3028_FE_TOYOTA388, /* IF = 3.88 MHz */ 22 - XC3028_FE_TOYOTA794, /* IF = 7.94 MHz */ 23 - XC3028_FE_DIBCOM52, /* IF = 5.20 MHz */ 24 - XC3028_FE_ZARLINK456, /* IF = 4.56 MHz */ 25 - XC3028_FE_CHINA, /* IF = 5.20 MHz */ 26 - }; 14 + /* Dmoduler IF (kHz) */ 15 + #define XC3028_FE_DEFAULT 0 16 + #define XC3028_FE_LG60 6000 17 + #define XC3028_FE_ATI638 6380 18 + #define XC3028_FE_OREN538 5380 19 + #define XC3028_FE_OREN36 3600 20 + #define XC3028_FE_TOYOTA388 3880 21 + #define XC3028_FE_TOYOTA794 7940 22 + #define XC3028_FE_DIBCOM52 5200 23 + #define XC3028_FE_ZARLINK456 4560 24 + #define XC3028_FE_CHINA 5200 27 25 28 26 struct xc2028_ctrl { 29 27 char *fname; ··· 30 32 unsigned int mts :1; 31 33 unsigned int d2633 :1; 32 34 unsigned int input1:1; 33 - enum xc2028_demod_types demod; 35 + unsigned int demod; 34 36 }; 35 37 36 38 struct xc2028_config {