]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/media/video/tuner-xc2028.c
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzi...
[linux-2.6-omap-h63xx.git] / drivers / media / video / tuner-xc2028.c
index 81cc7f607d4e7d899c381a8a3725e085c5715fa0..50cf876f020f40659929821f5c560fb58b5b8cbf 100644 (file)
@@ -395,6 +395,7 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
 {
        struct xc2028_data *priv = fe->tuner_priv;
        int                 i, best_i = -1, best_nr_matches = 0;
+       unsigned int        ign_firm_type_mask = 0;
 
        tuner_dbg("%s called, want type=", __FUNCTION__);
        if (debug) {
@@ -412,16 +413,18 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
 
        if (type & BASE)
                type &= BASE_TYPES;
-       else if (type & SCODE)
+       else if (type & SCODE) {
                type &= SCODE_TYPES;
-       else if (type & DTV_TYPES)
+               ign_firm_type_mask = HAS_IF;
+       } else if (type & DTV_TYPES)
                type &= DTV_TYPES;
        else if (type & STD_SPECIFIC_TYPES)
                type &= STD_SPECIFIC_TYPES;
 
        /* Seek for exact match */
        for (i = 0; i < priv->firm_size; i++) {
-               if ((type == priv->firm[i].type) && (*id == priv->firm[i].id))
+               if ((type == (priv->firm[i].type & ~ign_firm_type_mask)) &&
+                   (*id == priv->firm[i].id))
                        goto found;
        }
 
@@ -430,7 +433,7 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
                v4l2_std_id match_mask;
                int nr_matches;
 
-               if (type != priv->firm[i].type)
+               if (type != (priv->firm[i].type & ~ign_firm_type_mask))
                        continue;
 
                match_mask = *id & priv->firm[i].id;
@@ -592,7 +595,7 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type,
        } else {
                for (pos = 0; pos < priv->firm_size; pos++) {
                        if ((priv->firm[pos].int_freq == int_freq) &&
-                           (type & HAS_IF))
+                           (priv->firm[pos].type & HAS_IF))
                                break;
                }
                if (pos == priv->firm_size)
@@ -601,7 +604,7 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type,
 
        p = priv->firm[pos].ptr;
 
-       if (type & HAS_IF) {
+       if (priv->firm[pos].type & HAS_IF) {
                if (priv->firm[pos].size != 12 * 16 || scode >= 16)
                        return -EINVAL;
                p += 12 * scode;
@@ -660,7 +663,7 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type,
                        return rc;
        }
 
-       if (priv->ctrl.mts)
+       if (priv->ctrl.mts && !(type & FM))
                type |= MTS;
 
 retry:
@@ -751,6 +754,9 @@ skip_std_specific:
                goto check_device;
        }
 
+       if (new_fw.type & FM)
+               goto check_device;
+
        /* Load SCODE firmware, if exists */
        tuner_dbg("Trying to load scode %d\n", new_fw.scode_nr);
 
@@ -873,9 +879,20 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
         */
        if (new_mode == T_ANALOG_TV) {
                rc = send_seq(priv, {0x00, 0x00});
+       } else if (priv->cur_fw.type & ATSC) {
+               offset = 1750000;
        } else {
                offset = 2750000;
-               if (priv->cur_fw.type & DTV7)
+               /*
+                * We must adjust the offset by 500kHz in two cases in order
+                * to correctly center the IF output:
+                * 1) When the ZARLINK456 or DIBCOM52 tables were explicitly
+                *    selected and a 7MHz channel is tuned;
+                * 2) When tuning a VHF channel with DTV78 firmware.
+                */
+               if (((priv->cur_fw.type & DTV7) &&
+                    (priv->cur_fw.scode_table & (ZARLINK456 | DIBCOM52))) ||
+                   ((priv->cur_fw.type & DTV78) && freq < 470000000))
                        offset -= 500000;
        }
 
@@ -989,20 +1006,27 @@ static int xc2028_set_params(struct dvb_frontend *fe,
                return -EINVAL;
        }
 
-       /* FIXME:
-         There are two Scodes that will never be selected:
-               DTV78 ZARLINK456, DTV78 DIBCOM52
-         When it should opt for DTV78 instead of DTV7 or DTV8?
-       */
        switch (bw) {
        case BANDWIDTH_8_MHZ:
-               type |= DTV8 | F8MHZ;
+               if (p->frequency < 470000000)
+                       priv->ctrl.vhfbw7 = 0;
+               else
+                       priv->ctrl.uhfbw8 = 1;
+               type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV8;
+               type |= F8MHZ;
                break;
        case BANDWIDTH_7_MHZ:
-               type |= DTV7 | F8MHZ;
+               if (p->frequency < 470000000)
+                       priv->ctrl.vhfbw7 = 1;
+               else
+                       priv->ctrl.uhfbw8 = 0;
+               type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV7;
+               type |= F8MHZ;
                break;
        case BANDWIDTH_6_MHZ:
-               type |= DTV6 ;
+               type |= DTV6;
+               priv->ctrl.vhfbw7 = 0;
+               priv->ctrl.uhfbw8 = 0;
                break;
        default:
                tuner_err("error: bandwidth not supported.\n");
@@ -1122,7 +1146,8 @@ static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = {
 
 };
 
-void *xc2028_attach(struct dvb_frontend *fe, struct xc2028_config *cfg)
+struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
+                                  struct xc2028_config *cfg)
 {
        struct xc2028_data *priv;
        void               *video_dev;