V4L/DVB (5978): tuner: Better tuner radio support
authorTrent Piepho <xyzzy@speakeasy.org>
Fri, 3 Aug 2007 21:32:38 +0000 (18:32 -0300)
committerMauro Carvalho Chehab <mchehab@infradead.org>
Wed, 10 Oct 2007 01:04:34 +0000 (22:04 -0300)
Add radio support for the Thomson DTT7612 tuner.

This tuner uses a different 1st intermediate frequency than the other radio
tuners supported (a lot of NTSC radio tuners probably need this change too).

Add a new tuner-simple parameter, radio_if.  It selects the 1st IF used for
radio reception.  The radio frequency setting code in tuner-simple now uses
this field, instead of a special case select() block for each tuner with radio
support.

The tuner parameters for tuners that used a 33.3 MHz RIF now set radio_if to 1
in tuner-types.c.

The Thomson DTT7612 gets radio_if = 2, also add has_tda9887 = 1 and
fm_gain_normal = 1.

Add some defines for tda9887 bits that control IF setting in radio mode.

Add a new tda9887 config option, TDA9887_RIF_41_3, that selects a 41.3 MHz
radio IF.

Fix the way tda9887 radio options work.  The driver was modifying the default
radio mode config templates based on the TDA9887_XXXX flags.  This means that
_all_ tuners would get the same settings.  If you had a one tuner than used
TDA9887_GAIN_NORMAL and one that didn't, both would get the setting.  Now the
tda9987 driver just checks if tuner mode is radio and then applies the config
settings directly to the data being sent, just like how all the TV mode
settings already work.

The PLL setting math is made a little more accurate.

And a grammar error in a printk is fixed.

Signed-off-by: Trent Piepho <xyzzy@speakeasy.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
drivers/media/video/tda9887.c
drivers/media/video/tuner-simple.c
drivers/media/video/tuner-types.c
include/media/tuner-types.h
include/media/tuner.h

index a8f773274fe3f8188f0e7131f86f27fa74d0a24d..aa311e4f1f61e28c65d682b3be63ea59cc265c36 100644 (file)
@@ -97,6 +97,8 @@ struct tvnorm {
 #define cAudioIF_6_5             0x03    // bit e0:1
 
 
+#define cVideoIFMask           0x1c    // bit e2:4
+/* Video IF selection in TV Mode (bit B3=0) */
 #define cVideoIF_58_75           0x00    // bit e2:4
 #define cVideoIF_45_75           0x04    // bit e2:4
 #define cVideoIF_38_90           0x08    // bit e2:4
@@ -106,6 +108,13 @@ struct tvnorm {
 #define cRadioIF_45_75           0x18    // bit e2:4
 #define cRadioIF_38_90           0x1C    // bit e2:4
 
+/* IF1 selection in Radio Mode (bit B3=1) */
+#define cRadioIF_33_30         0x00    // bit e2,4 (also 0x10,0x14)
+#define cRadioIF_41_30         0x04    // bit e2,4
+
+/* Output of AFC pin in radio mode when bit E7=1 */
+#define cRadioAGC_SIF          0x00    // bit e3
+#define cRadioAGC_FM           0x08    // bit e3
 
 #define cTunerGainNormal         0x00    // bit e5
 #define cTunerGainLow            0x20    // bit e5
@@ -487,9 +496,13 @@ static int tda9887_set_config(struct tuner *t, char *buf)
        if (t->tda9887_config & TDA9887_GATING_18)
                buf[3] &= ~cGating_36;
 
-       if (t->tda9887_config & TDA9887_GAIN_NORMAL) {
-               radio_stereo.e &= ~cTunerGainLow;
-               radio_mono.e &= ~cTunerGainLow;
+       if (t->mode == V4L2_TUNER_RADIO) {
+               if (t->tda9887_config & TDA9887_RIF_41_3) {
+                       buf[3] &= ~cVideoIFMask;
+                       buf[3] |= cRadioIF_41_30;
+               }
+               if (t->tda9887_config & TDA9887_GAIN_NORMAL)
+                       buf[3] &= ~cTunerGainLow;
        }
 
        return 0;
index 2d57e8bc0db3467e406d184d80647582abf2c0c8..10a7d36a26468dc7aab8378e386fecd0ebc2da46 100644 (file)
@@ -402,53 +402,68 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
        u8 buffer[4];
        u16 div;
        int rc, j;
-       enum param_type desired_type = TUNER_PARAM_TYPE_RADIO;
        struct tuner_params *params;
 
        tun = &tuners[t->type];
 
-       for (j = 0; j < tun->count-1; j++) {
-               if (desired_type != tun->params[j].type)
-                       continue;
+       for (j = tun->count-1; j > 0; j--)
+               if (tun->params[j].type == TUNER_PARAM_TYPE_RADIO)
+                       break;
+       /* default params (j=0) will be used if desired type wasn't found */
+       params = &tun->params[j];
+
+       /* Select Radio 1st IF used */
+       switch (params->radio_if) {
+       case 0: /* 10.7 MHz */
+               freq += (unsigned int)(10.7*16000);
                break;
+       case 1: /* 33.3 MHz */
+               freq += (unsigned int)(33.3*16000);
+               break;
+       case 2: /* 41.3 MHz */
+               freq += (unsigned int)(41.3*16000);
+               break;
+       default:
+               tuner_warn("Unsupported radio_if value %d\n", params->radio_if);
+               return;
        }
-       /* use default tuner_params if desired_type not available */
-       if (desired_type != tun->params[j].type)
-               j = 0;
-
-       div = (20 * freq / 16000) + (int)(20*10.7); /* IF 10.7 MHz */
-       params = &tun->params[j];
-       buffer[2] = (params->ranges[0].config & ~TUNER_RATIO_MASK) | TUNER_RATIO_SELECT_50; /* 50 kHz step */
 
+       /* Bandswitch byte */
        switch (t->type) {
        case TUNER_TENA_9533_DI:
        case TUNER_YMEC_TVF_5533MF:
-               tuner_dbg ("This tuner doesn't have FM. Most cards has a TEA5767 for FM\n");
+               tuner_dbg ("This tuner doesn't have FM. Most cards have a TEA5767 for FM\n");
                return;
        case TUNER_PHILIPS_FM1216ME_MK3:
        case TUNER_PHILIPS_FM1236_MK3:
        case TUNER_PHILIPS_FMD1216ME_MK3:
        case TUNER_LG_NTSC_TAPE:
+       case TUNER_PHILIPS_FM1256_IH3:
                buffer[3] = 0x19;
                break;
        case TUNER_TNF_5335MF:
                buffer[3] = 0x11;
                break;
-       case TUNER_PHILIPS_FM1256_IH3:
-               div = (20 * freq) / 16000 + (int)(33.3 * 20);  /* IF 33.3 MHz */
-               buffer[3] = 0x19;
-               break;
        case TUNER_LG_PAL_FM:
                buffer[3] = 0xa5;
                break;
-       case TUNER_MICROTUNE_4049FM5:
-               div = (20 * freq) / 16000 + (int)(33.3 * 20); /* IF 33.3 MHz */
-               buffer[3] = 0xa4;
+       case TUNER_THOMSON_DTT761X:
+               buffer[3] = 0x39;
                break;
+       case TUNER_MICROTUNE_4049FM5:
        default:
                buffer[3] = 0xa4;
                break;
        }
+
+       buffer[2] = (params->ranges[0].config & ~TUNER_RATIO_MASK) |
+                   TUNER_RATIO_SELECT_50; /* 50 kHz step */
+
+       /* Convert from 1/16 kHz V4L steps to 1/20 MHz (=50 kHz) PLL steps
+          freq * (1 Mhz / 16000 V4L steps) * (20 PLL steps / 1 MHz) =
+          freq * (1/800) */
+       div = (freq + 400) / 800;
+
        if (params->cb_first_if_lower_freq && div < t->last_div) {
                buffer[0] = buffer[2];
                buffer[1] = buffer[3];
@@ -475,6 +490,8 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
                        config &= ~TDA9887_PORT1_ACTIVE;*/
                if (params->fm_gain_normal)
                        config |= TDA9887_GAIN_NORMAL;
+               if (params->radio_if == 2)
+                       config |= TDA9887_RIF_41_3;
                i2c_clients_command(c->adapter, TDA9887_SET_CONFIG, &config);
        }
        if (4 != (rc = i2c_master_send(c,buffer,4)))
index 53a99b39387fc948ed29a60bbb5d0856c1d1996a..c6a7934bd5a678f9287c6963344f9e3d1e7c216e 100644 (file)
@@ -652,6 +652,7 @@ static struct tuner_params tuner_microtune_4049_fm5_params[] = {
                .port1_invert_for_secam_lc = 1,
                .default_pll_gating_18 = 1,
                .fm_gain_normal=1,
+               .radio_if = 1, /* 33.3 MHz */
        },
 };
 
@@ -733,6 +734,7 @@ static struct tuner_params tuner_philips_fm1256_ih3_params[] = {
                .type   = TUNER_PARAM_TYPE_PAL,
                .ranges = tuner_fm1236_mk3_ntsc_ranges,
                .count  = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
+               .radio_if = 1, /* 33.3 MHz */
        },
 };
 
@@ -859,6 +861,9 @@ static struct tuner_params tuner_thomson_dtt761x_params[] = {
                .type   = TUNER_PARAM_TYPE_NTSC,
                .ranges = tuner_thomson_dtt761x_ntsc_ranges,
                .count  = ARRAY_SIZE(tuner_thomson_dtt761x_ntsc_ranges),
+               .has_tda9887 = 1,
+               .fm_gain_normal = 1,
+               .radio_if = 2, /* 41.3 MHz */
        },
 };
 
index e5ad3fcfe9845d1ba8a37babcd3871461a141f29..b201371416a0c793473b1fdd96dc9885f06746d5 100644 (file)
@@ -79,6 +79,10 @@ struct tuner_params {
        /* Select 18% (or according to datasheet 0%) L standard PLL gating,
           vs the driver default of 36%. */
        unsigned int default_pll_gating_18:1;
+       /* IF to use in radio mode.  Tuners with a separate radio IF filter
+          seem to use 10.7, while those without use 33.3 for PAL/SECAM tuners
+          and 41.3 for NTSC tuners. 0 = 10.7, 1 = 33.3, 2 = 41.3 */
+       unsigned int radio_if:2;
        /* Default tda9887 TOP value in dB for the low band. Default is 0.
           Range: -16:+15 */
        signed int default_top_low:5;
index 160381c72e4bcdf5c930d0fa9f3db60f3cde86af..c03dceb926051695afbaba9499ce50e56a7c3699 100644 (file)
@@ -146,6 +146,7 @@ extern int tuner_debug;
 #define TDA9887_AUTOMUTE               (1<<18)
 #define TDA9887_GATING_18              (1<<19)
 #define TDA9887_GAIN_NORMAL            (1<<20)
+#define TDA9887_RIF_41_3               (1<<21)  /* radio IF1 41.3 vs 33.3 */
 
 #ifdef __KERNEL__