[PATCH] v4l: update for tuner cards and some V4L chips
Mauro Carvalho Chehab [Fri, 24 Jun 2005 05:05:07 +0000 (22:05 -0700)]
Tuner improvements and additions.  TEA5767 FM tuner added.  Several small
fixes.

Signed-off-by: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
Signed-off-by: Nickolay V Shmyrev <nshmyrev@yandex.ru>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

16 files changed:
drivers/media/common/ir-common.c
drivers/media/video/bt832.c
drivers/media/video/bt832.h
drivers/media/video/msp3400.c
drivers/media/video/msp3400.h
drivers/media/video/tda7432.c
drivers/media/video/tda9875.c
drivers/media/video/tda9887.c
drivers/media/video/tuner-core.c
drivers/media/video/tuner-simple.c
drivers/media/video/tvaudio.c
drivers/media/video/tvmixer.c
include/media/audiochip.h
include/media/id.h
include/media/ir-common.h
include/media/tuner.h

index e5636ef..4adb284 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ir-common.c,v 1.8 2005/02/22 12:28:40 kraxel Exp $
+ * $Id: ir-common.c,v 1.10 2005/05/22 19:23:39 nsh Exp $
  *
  * some common structs and functions to handle infrared remotes via
  * input layer ...
@@ -131,10 +131,10 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = {
        [ 18 ] = KEY_KP0,
 
        [  0 ] = KEY_POWER,
-       [ 27 ] = KEY_LANGUAGE,  //MTS button
+//      [ 27 ] = MTS button
        [  2 ] = KEY_TUNER,     // TV/FM
        [ 30 ] = KEY_VIDEO,
-       [ 22 ] = KEY_INFO,      //display button
+//      [ 22 ] = display button
        [  4 ] = KEY_VOLUMEUP,
        [  8 ] = KEY_VOLUMEDOWN,
        [ 12 ] = KEY_CHANNELUP,
@@ -142,7 +142,7 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = {
        [  3 ] = KEY_ZOOM,      // fullscreen
        [ 31 ] = KEY_SUBTITLE,  // closed caption/teletext
        [ 32 ] = KEY_SLEEP,
-       [ 41 ] = KEY_SEARCH,    //boss key
+//      [ 41 ] = boss key
        [ 20 ] = KEY_MUTE,
        [ 43 ] = KEY_RED,
        [ 44 ] = KEY_GREEN,
@@ -150,17 +150,17 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = {
        [ 46 ] = KEY_BLUE,
        [ 24 ] = KEY_KPPLUS,    //fine tune +
        [ 25 ] = KEY_KPMINUS,   //fine tune -
-       [ 42 ] = KEY_ANGLE,     //picture in picture
-       [ 33 ] = KEY_KPDOT,
+//      [ 42 ] = picture in picture
+        [ 33 ] = KEY_KPDOT,
        [ 19 ] = KEY_KPENTER,
-       [ 17 ] = KEY_AGAIN,     //recall
+//      [ 17 ] = recall
        [ 34 ] = KEY_BACK,
        [ 35 ] = KEY_PLAYPAUSE,
        [ 36 ] = KEY_NEXT,
-       [ 37 ] = KEY_T,         //time shifting
+//      [ 37 ] = time shifting
        [ 38 ] = KEY_STOP,
-       [ 39 ] = KEY_RECORD,
-       [ 40 ] = KEY_SHUFFLE    //snapshot
+       [ 39 ] = KEY_RECORD
+//      [ 40 ] = snapshot
 };
 EXPORT_SYMBOL_GPL(ir_codes_winfast);
 
@@ -184,18 +184,30 @@ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = {
        [ 0x07 ] = KEY_KP7,             // 7
        [ 0x08 ] = KEY_KP8,             // 8
        [ 0x09 ] = KEY_KP9,             // 9
+       [ 0x0a ] = KEY_TEXT,            // keypad asterisk as well
        [ 0x0b ] = KEY_RED,             // red button
-       [ 0x0c ] = KEY_OPTION,          // black key without text
+       [ 0x0c ] = KEY_RADIO,           // radio
        [ 0x0d ] = KEY_MENU,            // menu
+       [ 0x0e ] = KEY_SUBTITLE,        // also the # key
        [ 0x0f ] = KEY_MUTE,            // mute
        [ 0x10 ] = KEY_VOLUMEUP,        // volume +
        [ 0x11 ] = KEY_VOLUMEDOWN,      // volume -
-       [ 0x1e ] = KEY_NEXT,            // skip >|
+       [ 0x12 ] = KEY_PREVIOUS,        // previous channel
+       [ 0x14 ] = KEY_UP,              // up
+       [ 0x15 ] = KEY_DOWN,            // down
+       [ 0x16 ] = KEY_LEFT,            // left
+       [ 0x17 ] = KEY_RIGHT,           // right
+       [ 0x18 ] = KEY_VIDEO,           // Videos
+       [ 0x19 ] = KEY_AUDIO,           // Music
+       [ 0x1a ] = KEY_MHP,             // Pictures - presume this means "Multimedia Home Platform"- no "PICTURES" key in input.h
+       [ 0x1b ] = KEY_EPG,             // Guide
+       [ 0x1c ] = KEY_TV,              // TV
+       [ 0x1e ] = KEY_NEXTSONG,        // skip >|
        [ 0x1f ] = KEY_EXIT,            // back/exit
        [ 0x20 ] = KEY_CHANNELUP,       // channel / program +
        [ 0x21 ] = KEY_CHANNELDOWN,     // channel / program -
        [ 0x22 ] = KEY_CHANNEL,         // source (old black remote)
-       [ 0x24 ] = KEY_PREVIOUS,        // replay |<
+       [ 0x24 ] = KEY_PREVIOUSSONG,    // replay |<
        [ 0x25 ] = KEY_ENTER,           // OK
        [ 0x26 ] = KEY_SLEEP,           // minimize (old black remote)
        [ 0x29 ] = KEY_BLUE,            // blue key
@@ -412,3 +424,4 @@ EXPORT_SYMBOL_GPL(ir_decode_biphase);
  * c-basic-offset: 8
  * End:
  */
+
index 07f72f6..3bb347d 100644 (file)
@@ -6,7 +6,7 @@
   It outputs an 8-bit 4:2:2 YUV or YCrCb video signal which can be directly
   connected to bt848/bt878 GPIO pins on this purpose.
   (see: VLSI Vision Ltd. www.vvl.co.uk for camera datasheets)
-  
+
   Supported Cards:
   -  Pixelview Rev.4E: 0x8a
                GPIO 0x400000 toggles Bt832 RESET, and the chip changes to i2c 0x88 !
 #include <linux/errno.h>
 #include <linux/slab.h>
 
-#include "id.h"
-#include "audiochip.h"
+#include <media/audiochip.h>
+#include <media/id.h>
 #include "bttv.h"
 #include "bt832.h"
 
 MODULE_LICENSE("GPL");
 
 /* Addresses to scan */
-static unsigned short normal_i2c[] = { I2C_BT832_ALT1>>1, I2C_BT832_ALT2>>1,
-                                      I2C_CLIENT_END };
+static unsigned short normal_i2c[] = {I2C_CLIENT_END};
+static unsigned short normal_i2c_range[] = {I2C_BT832_ALT1>>1,I2C_BT832_ALT2>>1,I2C_CLIENT_END};
 I2C_CLIENT_INSMOD;
 
 /* ---------------------------------------------------------------------- */
@@ -95,7 +95,7 @@ int bt832_init(struct i2c_client *i2c_client_s)
 
        buf=kmalloc(65,GFP_KERNEL);
        bt832_hexdump(i2c_client_s,buf);
-       
+
        if(buf[0x40] != 0x31) {
                printk("bt832: this i2c chip is no bt832 (id=%02x). Detaching.\n",buf[0x40]);
                kfree(buf);
@@ -135,7 +135,7 @@ int bt832_init(struct i2c_client *i2c_client_s)
        buf[1]= 0x27 & (~0x01); // Default | !skip
        if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
                 printk("bt832: i2c i/o error EO: rc == %d (should be 2)\n",rc);
-       
+
         bt832_hexdump(i2c_client_s,buf);
 
 #if 0
@@ -168,8 +168,7 @@ int bt832_init(struct i2c_client *i2c_client_s)
 
 
 
-static int bt832_attach(struct i2c_adapter *adap, int addr,
-                         unsigned short flags, int kind)
+static int bt832_attach(struct i2c_adapter *adap, int addr, int kind)
 {
        struct bt832 *t;
 
@@ -184,27 +183,32 @@ static int bt832_attach(struct i2c_adapter *adap, int addr,
                 return -ENOMEM;
        memset(t,0,sizeof(*t));
        t->client = client_template;
-        t->client.data = t;
+        i2c_set_clientdata(&t->client, t);
         i2c_attach_client(&t->client);
 
        if(! bt832_init(&t->client)) {
                bt832_detach(&t->client);
                return -1;
        }
-        
+
        return 0;
 }
 
 static int bt832_probe(struct i2c_adapter *adap)
 {
+#ifdef I2C_CLASS_TV_ANALOG
        if (adap->class & I2C_CLASS_TV_ANALOG)
                return i2c_probe(adap, &addr_data, bt832_attach);
+#else
+       if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
+               return i2c_probe(adap, &addr_data, bt832_attach);
+#endif
        return 0;
 }
 
 static int bt832_detach(struct i2c_client *client)
 {
-       struct bt832 *t = (struct bt832*)client->data;
+       struct bt832 *t = i2c_get_clientdata(client);
 
        printk("bt832: detach.\n");
        i2c_detach_client(client);
@@ -215,7 +219,7 @@ static int bt832_detach(struct i2c_client *client)
 static int
 bt832_command(struct i2c_client *client, unsigned int cmd, void *arg)
 {
-       struct bt832 *t = (struct bt832*)client->data;
+       struct bt832 *t = i2c_get_clientdata(client);
 
        printk("bt832: command %x\n",cmd);
 
@@ -249,19 +253,18 @@ static struct i2c_driver driver = {
 };
 static struct i2c_client client_template =
 {
-        .name   = "bt832",
-       .flags  = I2C_CLIENT_ALLOW_USE,
-        .driver = &driver,
+       I2C_DEVNAME("bt832"),
+       .flags      = I2C_CLIENT_ALLOW_USE,
+        .driver     = &driver,
 };
 
 
-int bt832_init_module(void)
+static int __init bt832_init_module(void)
 {
-       i2c_add_driver(&driver);
-       return 0;
+       return i2c_add_driver(&driver);
 }
 
-static void bt832_cleanup_module(void)
+static void __exit bt832_cleanup_module(void)
 {
        i2c_del_driver(&driver);
 }
@@ -269,3 +272,10 @@ static void bt832_cleanup_module(void)
 module_init(bt832_init_module);
 module_exit(bt832_cleanup_module);
 
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
index 7a98c06..9b6a8d2 100644 (file)
@@ -1,6 +1,6 @@
 /* Bt832 CMOS Camera Video Processor (VP)
 
- The Bt832 CMOS Camera Video Processor chip connects a Quartsight CMOS 
+ The Bt832 CMOS Camera Video Processor chip connects a Quartsight CMOS
   color digital camera directly to video capture devices via an 8-bit,
   4:2:2 YUV or YCrCb video interface.
 
@@ -85,7 +85,7 @@
 #define BT832_DEVICE_ID                63
 # define BT832_DEVICE_ID__31           0x31 // Bt832 has ID 0x31
 
-/* STMicroelectronivcs VV5404 camera module 
+/* STMicroelectronivcs VV5404 camera module
    i2c: 0x20: sensor address
    i2c: 0xa0: eeprom for ccd defect map
  */
@@ -256,26 +256,26 @@ For the CCIR-601 standards, the sampling is based on a static orthogonal samplin
 //===========================================================================
 // Timing generator SRAM table values for CCIR601 720x480 NTSC
 //===========================================================================
-// For NTSC CCIR656 
+// For NTSC CCIR656
 BYTE BtCard::SRAMTable_NTSC[] =
 {
     // SRAM Timing Table for NTSC
-    0x0c, 0xc0, 0x00, 
-    0x00, 0x90, 0xc2, 
-    0x03, 0x10, 0x03, 
-    0x06, 0x10, 0x34, 
-    0x12, 0x12, 0x65, 
-    0x02, 0x13, 0x24, 
-    0x19, 0x00, 0x24, 
-    0x39, 0x00, 0x96, 
-    0x59, 0x08, 0x93, 
+    0x0c, 0xc0, 0x00,
+    0x00, 0x90, 0xc2,
+    0x03, 0x10, 0x03,
+    0x06, 0x10, 0x34,
+    0x12, 0x12, 0x65,
+    0x02, 0x13, 0x24,
+    0x19, 0x00, 0x24,
+    0x39, 0x00, 0x96,
+    0x59, 0x08, 0x93,
     0x83, 0x08, 0x97,
-    0x03, 0x50, 0x30, 
-    0xc0, 0x40, 0x30, 
-    0x86, 0x01, 0x01, 
-    0xa6, 0x0d, 0x62, 
-    0x03, 0x11, 0x61, 
-    0x05, 0x37, 0x30, 
+    0x03, 0x50, 0x30,
+    0xc0, 0x40, 0x30,
+    0x86, 0x01, 0x01,
+    0xa6, 0x0d, 0x62,
+    0x03, 0x11, 0x61,
+    0x05, 0x37, 0x30,
     0xac, 0x21, 0x50
 };
 
index 09464d6..05b83fa 100644 (file)
@@ -147,6 +147,7 @@ static unsigned short normal_i2c[] = {
        I2C_MSP3400C_ALT  >> 1,
        I2C_CLIENT_END
 };
+static unsigned short normal_i2c_range[] = {I2C_CLIENT_END,I2C_CLIENT_END};
 I2C_CLIENT_INSMOD;
 
 /* ----------------------------------------------------------------------- */
@@ -735,7 +736,6 @@ static int msp34xx_sleep(struct msp3400c *msp, int timeout)
 {
        DECLARE_WAITQUEUE(wait, current);
 
-again:
        add_wait_queue(&msp->wq, &wait);
        if (!kthread_should_stop()) {
                if (timeout < 0) {
@@ -751,12 +751,9 @@ again:
 #endif
                }
        }
-
+       if (current->flags & PF_FREEZE)
+               refrigerator(PF_FREEZE);
        remove_wait_queue(&msp->wq, &wait);
-
-       if (try_to_freeze(PF_FREEZE))
-               goto again;
-
        return msp->restart;
 }
 
@@ -1436,7 +1433,7 @@ static int msp_detach(struct i2c_client *client);
 static int msp_probe(struct i2c_adapter *adap);
 static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg);
 
-static int msp_suspend(struct device * dev, pm_message_t state, u32 level);
+static int msp_suspend(struct device * dev, u32 state, u32 level);
 static int msp_resume(struct device * dev, u32 level);
 
 static void msp_wake_thread(struct i2c_client *client);
@@ -1841,7 +1838,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
        return 0;
 }
 
-static int msp_suspend(struct device * dev, pm_message_t state, u32 level)
+static int msp_suspend(struct device * dev, u32 state, u32 level)
 {
        struct i2c_client *c = container_of(dev, struct i2c_client, dev);
 
index d70a954..023f330 100644 (file)
@@ -1,3 +1,7 @@
+/*
+ * $Id: msp3400.h,v 1.3 2005/06/12 04:19:19 mchehab Exp $
+ */
+
 #ifndef MSP3400_H
 #define MSP3400_H
 
index 07ba6d3..376a4a4 100644 (file)
@@ -74,6 +74,7 @@ static unsigned short normal_i2c[] = {
        I2C_TDA7432 >> 1,
        I2C_CLIENT_END,
 };
+static unsigned short normal_i2c_range[] = { I2C_CLIENT_END, I2C_CLIENT_END };
 I2C_CLIENT_INSMOD;
 
 /* Structure of address and subaddresses for the tda7432 */
index 97b113e..4f1114c 100644 (file)
@@ -44,6 +44,7 @@ static unsigned short normal_i2c[] =  {
     I2C_TDA9875 >> 1,
     I2C_CLIENT_END
 };
+static unsigned short normal_i2c_range[] = {I2C_CLIENT_END};
 I2C_CLIENT_INSMOD;
 
 /* This is a superset of the TDA9875 */
index 7e6e6dd..33d6ee6 100644 (file)
@@ -33,6 +33,7 @@ static unsigned short normal_i2c[] = {
        0x96 >>1,
        I2C_CLIENT_END,
 };
+static unsigned short normal_i2c_range[] = {I2C_CLIENT_END,I2C_CLIENT_END};
 I2C_CLIENT_INSMOD;
 
 /* insmod options */
@@ -53,6 +54,7 @@ struct tda9887 {
        unsigned int       config;
        unsigned int       pinnacle_id;
        unsigned int       using_v4l2;
+       unsigned int       radio_mode;
 };
 
 struct tvnorm {
@@ -212,12 +214,22 @@ static struct tvnorm tvnorms[] = {
        }
 };
 
-static struct tvnorm radio = {
-       .name = "radio",
+static struct tvnorm radio_stereo = {
+       .name = "Radio Stereo",
+       .b    = ( cFmRadio       |
+                 cQSS           ),
+       .c    = ( cDeemphasisOFF |
+                 cAudioGain6 ),
+       .e    = ( cAudioIF_5_5   |
+                 cRadioIF_38_90 ),
+};
+
+static struct tvnorm radio_mono = {
+       .name = "Radio Mono",
        .b    = ( cFmRadio       |
                  cQSS           ),
        .c    = ( cDeemphasisON  |
-                 cDeemphasis50  ),
+                 cDeemphasis50),
        .e    = ( cAudioIF_5_5   |
                  cRadioIF_38_90 ),
 };
@@ -354,7 +366,10 @@ static int tda9887_set_tvnorm(struct tda9887 *t, char *buf)
        int i;
 
        if (t->radio) {
-               norm = &radio;
+               if (t->radio_mode == V4L2_TUNER_MODE_MONO)
+                       norm = &radio_mono;
+               else
+                       norm = &radio_stereo;
        } else {
                for (i = 0; i < ARRAY_SIZE(tvnorms); i++) {
                        if (tvnorms[i].std & t->std) {
@@ -545,11 +560,14 @@ static int tda9887_configure(struct tda9887 *t)
 
        memset(buf,0,sizeof(buf));
        tda9887_set_tvnorm(t,buf);
+
        buf[1] |= cOutputPort1Inactive;
        buf[1] |= cOutputPort2Inactive;
+
        if (UNSET != t->pinnacle_id) {
                tda9887_set_pinnacle(t,buf);
        }
+
        tda9887_set_config(t,buf);
        tda9887_set_insmod(t,buf);
 
@@ -592,9 +610,12 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind)
         if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL)))
                 return -ENOMEM;
        memset(t,0,sizeof(*t));
+
        t->client      = client_template;
        t->std         = 0;
        t->pinnacle_id = UNSET;
+       t->radio_mode = V4L2_TUNER_MODE_STEREO;
+
         i2c_set_clientdata(&t->client, t);
         i2c_attach_client(&t->client);
 
@@ -733,6 +754,16 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
                }
                break;
        }
+       case VIDIOC_S_TUNER:
+       {
+               struct v4l2_tuner* tuner = arg;
+
+               if (t->radio) {
+                       t->radio_mode = tuner->audmode;
+                       tda9887_configure (t);
+               }
+               break;
+       }
        default:
                /* nothing */
                break;
@@ -740,7 +771,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
        return 0;
 }
 
-static int tda9887_suspend(struct device * dev, pm_message_t state, u32 level)
+static int tda9887_suspend(struct device * dev, u32 state, u32 level)
 {
        dprintk("tda9887: suspend\n");
        return 0;
index 71423ae..ba13bfa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: tuner-core.c,v 1.7 2005/05/30 02:02:47 mchehab Exp $
+ * $Id: tuner-core.c,v 1.15 2005/06/12 01:36:14 mchehab Exp $
  *
  * i2c tv tuner chip device driver
  * core core, i.e. kernel interfaces, registering and so on
 /*
  * comment line bellow to return to old behavor, where only one I2C device is supported
  */
-/* #define CONFIG_TUNER_MULTI_I2C */
+#define CONFIG_TUNER_MULTI_I2C /**/
 
 #define UNSET (-1U)
 
 /* standard i2c insmod options */
 static unsigned short normal_i2c[] = {
        0x4b, /* tda8290 */
-       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
-       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+       I2C_CLIENT_END
+};
+static unsigned short normal_i2c_range[] = {
+       0x60, 0x6f,
        I2C_CLIENT_END
 };
 I2C_CLIENT_INSMOD;
@@ -59,7 +61,7 @@ MODULE_LICENSE("GPL");
 
 static int this_adap;
 #ifdef CONFIG_TUNER_MULTI_I2C
-static unsigned short tv_tuner, radio_tuner;
+static unsigned short first_tuner, tv_tuner, radio_tuner;
 #endif
 
 static struct i2c_driver driver;
@@ -67,7 +69,7 @@ static struct i2c_client client_template;
 
 /* ---------------------------------------------------------------------- */
 
-// Set tuner frequency,  freq in Units of 62.5kHz = 1/16MHz
+/* Set tuner frequency,  freq in Units of 62.5kHz = 1/16MHz */
 static void set_tv_freq(struct i2c_client *c, unsigned int freq)
 {
        struct tuner *t = i2c_get_clientdata(c);
@@ -81,14 +83,26 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq)
                return;
        }
        if (freq < tv_range[0]*16 || freq > tv_range[1]*16) {
-               /* FIXME: better do that chip-specific, but
-                  right now we don't have that in the config
-                  struct and this way is still better than no
-                  check at all */
-               tuner_info("TV freq (%d.%02d) out of range (%d-%d)\n",
-                          freq/16,freq%16*100/16,tv_range[0],tv_range[1]);
-               return;
+
+               if (freq >= tv_range[0]*16364 && freq <= tv_range[1]*16384) {
+                       /* V4L2_TUNER_CAP_LOW frequency */
+
+                       tuner_dbg("V4L2_TUNER_CAP_LOW freq selected for TV. Tuners yet doesn't support converting it to valid freq.\n");
+
+                       t->tv_freq(c,freq>>10);
+
+                       return;
+                } else {
+                       /* FIXME: better do that chip-specific, but
+                          right now we don't have that in the config
+                          struct and this way is still better than no
+                          check at all */
+                       tuner_info("TV freq (%d.%02d) out of range (%d-%d)\n",
+                                  freq/16,freq%16*100/16,tv_range[0],tv_range[1]);
+                       return;
+               }
        }
+       tuner_dbg("62.5 Khz freq step selected for TV.\n");
        t->tv_freq(c,freq);
 }
 
@@ -105,11 +119,29 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq)
                return;
        }
        if (freq < radio_range[0]*16 || freq > radio_range[1]*16) {
-               tuner_info("radio freq (%d.%02d) out of range (%d-%d)\n",
+               if (freq >= tv_range[0]*16364 && freq <= tv_range[1]*16384) {
+                       /* V4L2_TUNER_CAP_LOW frequency */
+                       if (t->type == TUNER_TEA5767) {
+                               tuner_info("radio freq step 62.5Hz (%d.%06d)\n",(freq>>14),freq%(1<<14)*10000);
+                               t->radio_freq(c,freq>>10);
+                               return;
+                       }
+
+                       tuner_dbg("V4L2_TUNER_CAP_LOW freq selected for Radio. Tuners yet doesn't support converting it to valid freq.\n");
+
+                       tuner_info("radio freq (%d.%06d)\n",(freq>>14),freq%(1<<14)*10000);
+
+                       t->radio_freq(c,freq>>10);
+                       return;
+
+                } else {
+                       tuner_info("radio freq (%d.%02d) out of range (%d-%d)\n",
                           freq/16,freq%16*100/16,
-                          radio_range[0],radio_range[1]);
-               return;
+                                  radio_range[0],radio_range[1]);
+                       return;
+               }
        }
+       tuner_dbg("62.5 Khz freq step selected for Radio.\n");
        t->radio_freq(c,freq);
 }
 
@@ -133,34 +165,13 @@ static void set_freq(struct i2c_client *c, unsigned long freq)
        t->freq = freq;
 }
 
-#ifdef CONFIG_TUNER_MULTI_I2C
-static void set_addr(struct i2c_client *c, struct tuner_addr *tun_addr)
-{
-       struct tuner *t = i2c_get_clientdata(c);
-
-       switch (tun_addr->type) {
-       case V4L2_TUNER_RADIO:
-               radio_tuner=tun_addr->addr;
-               tuner_dbg("radio tuner set to I2C address 0x%02x\n",radio_tuner<<1);
-
-               break;
-       default:
-               tv_tuner=tun_addr->addr;
-               tuner_dbg("TV tuner set to I2C address 0x%02x\n",tv_tuner<<1);
-               break;
-       }
-}
-#else
-#define set_addr(c,tun_addr) \
-               tuner_warn("It is recommended to enable CONFIG_TUNER_MULTI_I2C for this card.\n");
-#endif
-
 static void set_type(struct i2c_client *c, unsigned int type)
 {
        struct tuner *t = i2c_get_clientdata(c);
 
+       tuner_dbg ("I2C addr 0x%02x with type %d\n",c->addr<<1,type);
        /* sanity check */
-       if (type == UNSET  ||  type == TUNER_ABSENT)
+       if (type == UNSET || type == TUNER_ABSENT)
                return;
        if (type >= tuner_count)
                return;
@@ -175,6 +186,7 @@ static void set_type(struct i2c_client *c, unsigned int type)
                return;
 
        t->initialized = 1;
+
        t->type = type;
        switch (t->type) {
        case TUNER_MT2032:
@@ -189,6 +201,53 @@ static void set_type(struct i2c_client *c, unsigned int type)
        }
 }
 
+#ifdef CONFIG_TUNER_MULTI_I2C
+#define CHECK_ADDR(tp,cmd,tun) if (client->addr!=tp) { \
+                         return 0; } else \
+                         tuner_info ("Cmd %s accepted to "tun"\n",cmd);
+#define CHECK_MODE(cmd)        if (t->mode == V4L2_TUNER_RADIO) { \
+                       CHECK_ADDR(radio_tuner,cmd,"radio") } else \
+                       { CHECK_ADDR(tv_tuner,cmd,"TV"); }
+#else
+#define CHECK_ADDR(tp,cmd,tun) tuner_info ("Cmd %s accepted to "tun"\n",cmd);
+#define CHECK_MODE(cmd) tuner_info ("Cmd %s accepted\n",cmd);
+#endif
+
+#ifdef CONFIG_TUNER_MULTI_I2C
+
+static void set_addr(struct i2c_client *c, struct tuner_addr *tun_addr)
+{
+       /* ADDR_UNSET defaults to first available tuner */
+       if ( tun_addr->addr == ADDR_UNSET ) {
+               if (first_tuner != c->addr)
+                       return;
+               switch (tun_addr->v4l2_tuner) {
+               case V4L2_TUNER_RADIO:
+                       radio_tuner=c->addr;
+                       break;
+               default:
+                       tv_tuner=c->addr;
+                       break;
+               }
+       } else {
+               /* Sets tuner to its configured value */
+               switch (tun_addr->v4l2_tuner) {
+               case V4L2_TUNER_RADIO:
+                       radio_tuner=tun_addr->addr;
+                       if ( tun_addr->addr == c->addr ) set_type(c,tun_addr->type);
+                       return;
+               default:
+                       tv_tuner=tun_addr->addr;
+                       if ( tun_addr->addr == c->addr ) set_type(c,tun_addr->type);
+                       return;
+               }
+       }
+       set_type(c,tun_addr->type);
+}
+#else
+#define set_addr(c,tun_addr) set_type(c,(tun_addr)->type)
+#endif
+
 static char pal[] = "-";
 module_param_string(pal, pal, sizeof(pal), 0644);
 
@@ -233,6 +292,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
 #else
        /* by default, first I2C card is both tv and radio tuner */
        if (this_adap == 0) {
+               first_tuner = addr;
                tv_tuner = addr;
                radio_tuner = addr;
        }
@@ -249,11 +309,12 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
         memcpy(&t->i2c,&client_template,sizeof(struct i2c_client));
        i2c_set_clientdata(&t->i2c, t);
        t->type       = UNSET;
-       t->radio_if2  = 10700*1000; // 10.7MHz - FM radio
+       t->radio_if2  = 10700*1000; /* 10.7MHz - FM radio */
 
         i2c_attach_client(&t->i2c);
        tuner_info("chip found @ 0x%x (%s)\n",
                   addr << 1, adap->name);
+
        set_type(&t->i2c, t->type);
        return 0;
 }
@@ -261,12 +322,14 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
 static int tuner_probe(struct i2c_adapter *adap)
 {
        if (0 != addr) {
-               normal_i2c[0] = addr;
-               normal_i2c[1] = I2C_CLIENT_END;
+               normal_i2c[0]       = addr;
+               normal_i2c_range[0] = addr;
+               normal_i2c_range[1] = addr;
        }
        this_adap = 0;
 
 #ifdef CONFIG_TUNER_MULTI_I2C
+       first_tuner = 0;
        tv_tuner = 0;
        radio_tuner = 0;
 #endif
@@ -298,17 +361,6 @@ static int tuner_detach(struct i2c_client *client)
                          tuner_info("ignore v4l1 call\n"); \
                          return 0; }
 
-#ifdef CONFIG_TUNER_MULTI_I2C
-#define CHECK_ADDR(tp,cmd)     if (client->addr!=tp) { \
-                         tuner_info ("Cmd %s to addr 0x%02x rejected.\n",cmd,client->addr<<1); \
-                         return 0; }
-#define CHECK_MODE(cmd)        if (t->mode == V4L2_TUNER_RADIO) { \
-                         CHECK_ADDR(radio_tuner,cmd) } else { CHECK_ADDR(tv_tuner,cmd); }
-#else
-#define CHECK_ADDR(tp,cmd)
-#define CHECK_MODE(cmd)
-#endif
-
 static int
 tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
 {
@@ -320,19 +372,19 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
        case TUNER_SET_TYPE:
                set_type(client,*iarg);
                break;
-       case TUNER_SET_ADDR:
+       case TUNER_SET_TYPE_ADDR:
                set_addr(client,(struct tuner_addr *)arg);
                break;
        case AUDC_SET_RADIO:
-               CHECK_ADDR(radio_tuner,"AUDC_SET_RADIO");
+               t->mode = V4L2_TUNER_RADIO;
+               CHECK_ADDR(tv_tuner,"AUDC_SET_RADIO","TV");
 
                if (V4L2_TUNER_RADIO != t->mode) {
                        set_tv_freq(client,400 * 16);
-                       t->mode = V4L2_TUNER_RADIO;
                }
                break;
        case AUDC_CONFIG_PINNACLE:
-               CHECK_ADDR(tv_tuner,"AUDC_CONFIG_PINNACLE");
+               CHECK_ADDR(tv_tuner,"AUDC_CONFIG_PINNACLE","TV");
                switch (*iarg) {
                case 2:
                        tuner_dbg("pinnacle pal\n");
@@ -360,9 +412,10 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                };
                struct video_channel *vc = arg;
 
-               CHECK_ADDR(tv_tuner,"VIDIOCSCHAN");
                CHECK_V4L2;
                t->mode = V4L2_TUNER_ANALOG_TV;
+               CHECK_ADDR(tv_tuner,"VIDIOCSCHAN","TV");
+
                if (vc->norm < ARRAY_SIZE(map))
                        t->std = map[vc->norm];
                tuner_fixup_std(t);
@@ -383,17 +436,27 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
        {
                struct video_tuner *vt = arg;
 
-               CHECK_ADDR(radio_tuner,"VIDIOCGTUNER:");
+               CHECK_ADDR(radio_tuner,"VIDIOCGTUNER","radio");
                CHECK_V4L2;
-               if (V4L2_TUNER_RADIO == t->mode  &&  t->has_signal)
-                       vt->signal = t->has_signal(client);
+               if (V4L2_TUNER_RADIO == t->mode) {
+                       if (t->has_signal)
+                               vt->signal = t->has_signal(client);
+                       if (t->is_stereo) {
+                               if (t->is_stereo(client))
+                                       vt-> flags |= VIDEO_TUNER_STEREO_ON;
+                               else
+                                       vt-> flags &= 0xffff ^ VIDEO_TUNER_STEREO_ON;
+                       }
+                       vt->flags |= V4L2_TUNER_CAP_LOW; /* Allow freqs at 62.5 Hz */
+               }
+
                return 0;
        }
        case VIDIOCGAUDIO:
        {
                struct video_audio *va = arg;
 
-               CHECK_ADDR(radio_tuner,"VIDIOCGAUDIO");
+               CHECK_ADDR(radio_tuner,"VIDIOCGAUDIO","radio");
                CHECK_V4L2;
                if (V4L2_TUNER_RADIO == t->mode  &&  t->is_stereo)
                        va->mode = t->is_stereo(client)
@@ -406,9 +469,10 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
        {
                v4l2_std_id *id = arg;
 
-               CHECK_ADDR(tv_tuner,"VIDIOC_S_STD");
                SWITCH_V4L2;
                t->mode = V4L2_TUNER_ANALOG_TV;
+               CHECK_ADDR(tv_tuner,"VIDIOC_S_STD","TV");
+
                t->std = *id;
                tuner_fixup_std(t);
                if (t->freq)
@@ -444,13 +508,27 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
 
                CHECK_MODE("VIDIOC_G_TUNER");
                SWITCH_V4L2;
-               if (V4L2_TUNER_RADIO == t->mode  &&  t->has_signal)
-                       tuner->signal = t->has_signal(client);
+               if (V4L2_TUNER_RADIO == t->mode) {
+                       if (t->has_signal)
+                               tuner -> signal = t->has_signal(client);
+                       if (t->is_stereo) {
+                               if (t->is_stereo(client)) {
+                                       tuner -> capability |= V4L2_TUNER_CAP_STEREO;
+                                       tuner -> rxsubchans |= V4L2_TUNER_SUB_STEREO;
+                               } else {
+                                       tuner -> rxsubchans &= 0xffff ^ V4L2_TUNER_SUB_STEREO;
+                               }
+                       }
+               }
+               /* Wow to deal with V4L2_TUNER_CAP_LOW ? For now, it accepts from low at 62.5KHz step  to high at 62.5 Hz */
                tuner->rangelow = tv_range[0] * 16;
-               tuner->rangehigh = tv_range[1] * 16;
+//             tuner->rangehigh = tv_range[1] * 16;
+//             tuner->rangelow = tv_range[0] * 16384;
+               tuner->rangehigh = tv_range[1] * 16384;
                break;
        }
        default:
+               tuner_dbg ("Unimplemented IOCTL 0x%08x called to tuner.\n", cmd);
                /* nothing */
                break;
        }
@@ -458,7 +536,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
        return 0;
 }
 
-static int tuner_suspend(struct device * dev, pm_message_t state, u32 level)
+static int tuner_suspend(struct device * dev, u32 state, u32 level)
 {
        struct i2c_client *c = container_of(dev, struct i2c_client, dev);
        struct tuner *t = i2c_get_clientdata(c);
index 866f18d..539f305 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: tuner-simple.c,v 1.14 2005/05/30 02:02:47 mchehab Exp $
+ * $Id: tuner-simple.c,v 1.21 2005/06/10 19:53:26 nsh Exp $
  *
  * i2c tv tuner chip device driver
  * controls all those simple 4-control-bytes style tuners.
@@ -220,7 +220,17 @@ static struct tunertype tuners[] = {
 
        { "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC,
          16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732},
+       { "Tena TNF9533-D/IF", LGINNOTEK, PAL,
+         16*160.25, 16*464.25, 0x01,0x02,0x08,0x8e,623},
+
+       /*
+        * This entry is for TEA5767 FM radio only chip used on several boards
+        * w/TV tuner
+        */
+       { TEA5767_TUNER_NAME, Philips, RADIO,
+         -1, -1, 0, 0, 0, TEA5767_LOW_LO_32768,0},
 };
+
 unsigned const int tuner_count = ARRAY_SIZE(tuners);
 
 /* ---------------------------------------------------------------------- */
@@ -231,6 +241,7 @@ static int tuner_getstatus(struct i2c_client *c)
 
        if (1 != i2c_master_recv(c,&byte,1))
                return 0;
+
        return byte;
 }
 
@@ -239,17 +250,33 @@ static int tuner_getstatus(struct i2c_client *c)
 #define TUNER_MODE      0x38
 #define TUNER_AFC       0x07
 
-#define TUNER_STEREO    0x10 /* radio mode */
-#define TUNER_SIGNAL    0x07 /* radio mode */
+#define TUNER_STEREO       0x10 /* radio mode */
+#define TUNER_STEREO_MK3   0x04 /* radio mode */
+#define TUNER_SIGNAL       0x07 /* radio mode */
 
 static int tuner_signal(struct i2c_client *c)
 {
-       return (tuner_getstatus(c) & TUNER_SIGNAL)<<13;
+       return (tuner_getstatus(c) & TUNER_SIGNAL) << 13;
 }
 
 static int tuner_stereo(struct i2c_client *c)
 {
-       return (tuner_getstatus (c) & TUNER_STEREO);
+       int stereo, status;
+       struct tuner *t = i2c_get_clientdata(c);
+
+       status = tuner_getstatus (c);
+
+       switch (t->type) {
+               case TUNER_PHILIPS_FM1216ME_MK3:
+               case TUNER_PHILIPS_FM1236_MK3:
+               case TUNER_PHILIPS_FM1256_IH3:
+                       stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
+                       break;
+               default:
+                       stereo = status & TUNER_STEREO;
+       }
+
+       return stereo;
 }
 
 #if 0 /* unused */
@@ -432,6 +459,7 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
        buffer[2] = tun->config;
 
        switch (t->type) {
+       case TUNER_TENA_9533_DI:
        case TUNER_YMEC_TVF_5533MF:
 
                /*These values are empirically determinated */
@@ -473,20 +501,6 @@ int default_tuner_init(struct i2c_client *c)
                   t->type, tuners[t->type].name);
        strlcpy(c->name, tuners[t->type].name, sizeof(c->name));
 
-       switch (t->type) {
-       case TUNER_YMEC_TVF_5533MF:
-               {
-                       struct tuner_addr tun_addr = { V4L2_TUNER_ANALOG_TV, 0xc2>>1 };
-
-                       if (c->driver->command) {
-                               c->driver->command(c, TUNER_SET_ADDR, &tun_addr);
-                       } else {
-                               tuner_warn("Couldn't set TV tuner I2C address to 0x%02x\n",tun_addr.addr<<1);
-                       }
-                       break;
-               }
-       }
-
        t->tv_freq    = default_set_tv_freq;
        t->radio_freq = default_set_radio_freq;
        t->has_signal = tuner_signal;
index 41b635e..6f5828a 100644 (file)
@@ -148,6 +148,7 @@ static unsigned short normal_i2c[] = {
        I2C_TDA9874   >> 1,
        I2C_PIC16C54  >> 1,
        I2C_CLIENT_END };
+static unsigned short normal_i2c_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
 I2C_CLIENT_INSMOD;
 
 static struct i2c_driver driver;
@@ -285,7 +286,6 @@ static int chip_thread(void *data)
                        schedule();
                }
                remove_wait_queue(&chip->wq, &wait);
-               try_to_freeze(PF_FREEZE);
                if (chip->done || signal_pending(current))
                        break;
                dprintk("%s: thread wakeup\n", i2c_clientname(&chip->c));
index eafd706..51b99cd 100644 (file)
@@ -1,3 +1,7 @@
+/*
+ * $Id: tvmixer.c,v 1.8 2005/06/12 04:19:19 mchehab Exp $
+ */
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
index d3e9e30..f345a61 100644 (file)
@@ -1,3 +1,7 @@
+/*
+ * $Id: audiochip.h,v 1.3 2005/06/12 04:19:19 mchehab Exp $
+ */
+
 #ifndef AUDIOCHIP_H
 #define AUDIOCHIP_H
 
index 1b0320d..a39a642 100644 (file)
@@ -1,3 +1,7 @@
+/*
+ * $Id: id.h,v 1.4 2005/06/12 04:19:19 mchehab Exp $
+ */
+
 /* FIXME: this temporarely, until these are included in linux/i2c-id.h */
 
 /* drivers */
index b5fa6c5..6986705 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ir-common.h,v 1.8 2005/02/22 12:28:40 kraxel Exp $
+ * $Id: ir-common.h,v 1.9 2005/05/15 19:01:26 mchehab Exp $
  *
  * some common structs and functions to handle infrared remotes via
  * input layer ...
index cb75f48..2dd8310 100644 (file)
@@ -25,6 +25,8 @@
 
 #include "id.h"
 
+#define ADDR_UNSET (255)
+
 #define TUNER_TEMIC_PAL     0        /* 4002 FH5 (3X 7756, 9483) */
 #define TUNER_PHILIPS_PAL_I 1
 #define TUNER_PHILIPS_NTSC  2
 
 #define TUNER_YMEC_TVF_8531MF 58
 #define TUNER_YMEC_TVF_5533MF 59       /* Pixelview Pro Ultra NTSC */
+#define TUNER_THOMSON_DTT7611 60
+#define TUNER_TENA_9533_DI    61
+#define TUNER_TEA5767         62       /* Only FM Radio Tuner */
+
+#define TEA5767_TUNER_NAME "Philips TEA5767HN FM Radio"
 
 #define TUNER_THOMSON_DTT7611    60
 
 #define NTSC    3
 #define SECAM   4
 #define ATSC    5
+#define RADIO  6
 
 #define NoTuner 0
 #define Philips 1
 #define TCL     11
 #define THOMSON 12
 
+enum v4l_radio_tuner {
+        TEA5767_LOW_LO_32768    = 0,
+        TEA5767_HIGH_LO_32768   = 1,
+        TEA5767_LOW_LO_13MHz    = 2,
+        TEA5767_HIGH_LO_13MHz   = 3,
+};
+
+
 #define TUNER_SET_TYPE               _IOW('t',1,int)    /* set tuner type */
 #define TUNER_SET_TVFREQ             _IOW('t',2,int)    /* set tv freq */
-#define TUNER_SET_ADDR               _IOW('T',3,int)   /* Chooses tuner I2C address */
+#define TUNER_SET_TYPE_ADDR          _IOW('T',3,int)   /* set tuner type and I2C addr */
 
 #define  TDA9887_SET_CONFIG          _IOW('t',5,int)
 
 #define I2C_ADDR_TDA8275        0x61
 
 struct tuner_addr {
-       enum v4l2_tuner_type type;
-       unsigned short addr;
+       enum v4l2_tuner_type    v4l2_tuner;
+       unsigned int            type;
+       unsigned short          addr;
 };
 
 struct tuner {