aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/tuner-xc2028.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2007-11-25 17:26:36 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-01-25 16:02:58 -0500
commit66c2d53db28276fe49b49745230b7ac8d8fd5f47 (patch)
treea9cad146ff33ea21b0a48dd6146ee9a147b66088 /drivers/media/video/tuner-xc2028.c
parentb542dfdc9f6e6eaf3cc2ede27dbaf50425f8b4b5 (diff)
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>
Diffstat (limited to 'drivers/media/video/tuner-xc2028.c')
-rw-r--r--drivers/media/video/tuner-xc2028.c88
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);
50struct firmware_description { 50struct 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
567static int load_scode(struct dvb_frontend *fe, unsigned int type, 576static 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
611static int check_firmware(struct dvb_frontend *fe, unsigned int type, 637static 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
725check_device: 752check_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
812static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, 839static 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
917static 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
930static int xc2028_set_params(struct dvb_frontend *fe, 945static 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
990static int xc2028_sleep(struct dvb_frontend *fe) 1004static int xc2028_sleep(struct dvb_frontend *fe)