]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/media/video/msp3400.c
[PATCH] v4l: 885: second round of i2c ids redefinition cleanup
[mv-sheeva.git] / drivers / media / video / msp3400.c
index 4689dee882f38f6d8faba0a1dab9fd83920362ee..d603229c9f2f9ccd4689872bba477572e4d92e4a 100644 (file)
@@ -54,7 +54,6 @@
 #include <asm/pgtable.h>
 
 #include <media/audiochip.h>
-#include <media/id.h>
 #include "msp3400.h"
 
 #define OPMODE_AUTO    -1
@@ -192,7 +191,7 @@ static int msp3400c_reset(struct i2c_client *client)
             (2 != i2c_transfer(client->adapter,test,2)) ) {
                printk(KERN_ERR "msp3400: chip reset failed\n");
                return -1;
-        }
+       }
        return 0;
 }
 
@@ -200,16 +199,16 @@ static int msp3400c_read(struct i2c_client *client, int dev, int addr)
 {
        int err,retval;
 
-        unsigned char write[3];
-        unsigned char read[2];
-        struct i2c_msg msgs[2] = {
-                { client->addr, 0,        3, write },
-                { client->addr, I2C_M_RD, 2, read  }
-        };
+       unsigned char write[3];
+       unsigned char read[2];
+       struct i2c_msg msgs[2] = {
+               { client->addr, 0,        3, write },
+               { client->addr, I2C_M_RD, 2, read  }
+       };
 
-        write[0] = dev+1;
-        write[1] = addr >> 8;
-        write[2] = addr & 0xff;
+       write[0] = dev+1;
+       write[1] = addr >> 8;
+       write[2] = addr & 0xff;
 
        for (err = 0; err < 3;) {
                if (2 == i2c_transfer(client->adapter,msgs,2))
@@ -236,13 +235,13 @@ static int msp3400c_read(struct i2c_client *client, int dev, int addr)
 static int msp3400c_write(struct i2c_client *client, int dev, int addr, int val)
 {
        int err;
-        unsigned char buffer[5];
+       unsigned char buffer[5];
 
-        buffer[0] = dev;
-        buffer[1] = addr >> 8;
-        buffer[2] = addr &  0xff;
-        buffer[3] = val  >> 8;
-        buffer[4] = val  &  0xff;
+       buffer[0] = dev;
+       buffer[1] = addr >> 8;
+       buffer[2] = addr &  0xff;
+       buffer[3] = val  >> 8;
+       buffer[4] = val  &  0xff;
 
        dprintk_trace("trace: msp3400c_write(0x%x, 0x%x, 0x%x)\n", dev, addr,
                      val);
@@ -649,6 +648,30 @@ msp3400c_print_mode(struct msp3400c *msp)
        }
 }
 
+#define MSP3400_MAX 4
+static struct i2c_client *msps[MSP3400_MAX];
+static void msp3400c_restore_dfp(struct i2c_client *client)
+{
+       struct msp3400c *msp = i2c_get_clientdata(client);
+       int i;
+
+       for (i = 0; i < DFP_COUNT; i++) {
+               if (-1 == msp->dfp_regs[i])
+                       continue;
+               msp3400c_write(client, I2C_MSP3400C_DFP, i, msp->dfp_regs[i]);
+       }
+}
+
+/* if the dfp_regs is set, set what's in there. Otherwise, set the default value */
+static int msp3400c_write_dfp_with_default(struct i2c_client *client,
+                                       int addr, int default_value)
+{
+       struct msp3400c *msp = i2c_get_clientdata(client);
+       int value = default_value;
+       if (addr < DFP_COUNT && -1 != msp->dfp_regs[addr])
+               value = msp->dfp_regs[addr];
+       return msp3400c_write(client, I2C_MSP3400C_DFP, addr, value);
+}
 
 /* ----------------------------------------------------------------------- */
 
@@ -788,7 +811,7 @@ static void watch_stereo(struct i2c_client *client)
                else if (msp->stereo & VIDEO_SOUND_LANG1)
                        msp3400c_setstereo(client, V4L2_TUNER_MODE_LANG1);
                else
-                       msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO);
+                       msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO);
        }
 
        if (once)
@@ -834,7 +857,8 @@ static int msp3400c_thread(void *data)
                        goto restart;
 
                /* carrier detect pass #1 -- main carrier */
-               cd = carrier_detect_main; count = CARRIER_COUNT(carrier_detect_main);
+               cd = carrier_detect_main;
+               count = CARRIER_COUNT(carrier_detect_main);
 
                if (amsound && (msp->norm == VIDEO_MODE_SECAM)) {
                        /* autodetect doesn't work well with AM ... */
@@ -868,13 +892,16 @@ static int msp3400c_thread(void *data)
                case 0: /* 4.5 */
                case 2: /* 6.0 */
                default:
-                       cd = NULL; count = 0;
+                       cd = NULL;
+                       count = 0;
                        break;
                }
 
                if (amsound && (msp->norm == VIDEO_MODE_SECAM)) {
                        /* autodetect doesn't work well with AM ... */
-                       cd = NULL; count = 0; max2 = 0;
+                       cd = NULL;
+                       count = 0;
+                       max2 = 0;
                }
                for (this = 0; this < count; this++) {
                        msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo);
@@ -962,6 +989,8 @@ static int msp3400c_thread(void *data)
 
                /* unmute */
                msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
+               msp3400c_restore_dfp(client);
+
                if (debug)
                        msp3400c_print_mode(msp);
 
@@ -1207,6 +1236,7 @@ static int msp3410d_thread(void *data)
                msp3400c_settreble(client, msp->treble);
                msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
                msp3400c_write(client, I2C_MSP3400C_DFP, 0x0013, msp->acb);
+               msp3400c_restore_dfp(client);
 
                /* monitor tv audio mode */
                while (msp->watch_stereo) {
@@ -1230,7 +1260,7 @@ static void msp34xxg_set_source(struct i2c_client *client, int source);
 /* (re-)initialize the msp34xxg, according to the current norm in msp->norm
  * return 0 if it worked, -1 if it failed
  */
-static int msp34xxg_init(struct i2c_client *client)
+static int msp34xxg_reset(struct i2c_client *client)
 {
        struct msp3400c *msp = i2c_get_clientdata(client);
        int modus,std;
@@ -1257,7 +1287,7 @@ static int msp34xxg_init(struct i2c_client *client)
                return -1;
        if (msp3400c_write(client,
                           I2C_MSP3400C_DEM,
-                          0x20/*stanard*/,
+                          0x20/*standard*/,
                           std))
                return -1;
 
@@ -1265,21 +1295,18 @@ static int msp34xxg_init(struct i2c_client *client)
           standard/audio autodetection right now */
        msp34xxg_set_source(client, msp->source);
 
-       if (msp3400c_write(client, I2C_MSP3400C_DFP,
-                          0x0e, /* AM/FM Prescale */
-                          0x3000 /* default: [15:8] 75khz deviation */))
+       if (msp3400c_write_dfp_with_default(client, 0x0e,       /* AM/FM Prescale */
+                                           0x3000
+                                           /* default: [15:8] 75khz deviation */
+           ))
                return -1;
 
-       if (msp3400c_write(client, I2C_MSP3400C_DFP,
-                          0x10, /* NICAM Prescale */
-                          0x5a00 /* default: 9db gain (as recommended) */))
+       if (msp3400c_write_dfp_with_default(client, 0x10,       /* NICAM Prescale */
+                                           0x5a00
+                                           /* default: 9db gain (as recommended) */
+           ))
                return -1;
 
-       if (msp3400c_write(client,
-                          I2C_MSP3400C_DEM,
-                          0x20, /* STANDARD SELECT  */
-                          standard /* default: 0x01 for automatic standard select*/))
-               return -1;
        return 0;
 }
 
@@ -1303,7 +1330,7 @@ static int msp34xxg_thread(void *data)
                        break;
 
                /* setup the chip*/
-               msp34xxg_init(client);
+               msp34xxg_reset(client);
                std = standard;
                if (std != 0x01)
                        goto unmute;
@@ -1484,32 +1511,36 @@ static struct i2c_client client_template =
 static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
 {
        struct msp3400c *msp;
-        struct i2c_client *c;
+       struct i2c_client *c;
        int (*thread_func)(void *data) = NULL;
+       int i;
 
-        client_template.adapter = adap;
-        client_template.addr = addr;
+       client_template.adapter = adap;
+       client_template.addr = addr;
 
-        if (-1 == msp3400c_reset(&client_template)) {
-                dprintk("msp34xx: no chip found\n");
-                return -1;
-        }
+       if (-1 == msp3400c_reset(&client_template)) {
+               dprintk("msp34xx: no chip found\n");
+               return -1;
+       }
 
-        if (NULL == (c = kmalloc(sizeof(struct i2c_client),GFP_KERNEL)))
-                return -ENOMEM;
-        memcpy(c,&client_template,sizeof(struct i2c_client));
+       if (NULL == (c = kmalloc(sizeof(struct i2c_client),GFP_KERNEL)))
+               return -ENOMEM;
+       memcpy(c,&client_template,sizeof(struct i2c_client));
        if (NULL == (msp = kmalloc(sizeof(struct msp3400c),GFP_KERNEL))) {
                kfree(c);
                return -ENOMEM;
        }
 
        memset(msp,0,sizeof(struct msp3400c));
+       msp->norm = VIDEO_MODE_NTSC;
        msp->left = 58880;      /* 0db gain */
        msp->right = 58880;     /* 0db gain */
        msp->bass = 32768;
        msp->treble = 32768;
        msp->input = -1;
        msp->muted = 0;
+       for (i = 0; i < DFP_COUNT; i++)
+               msp->dfp_regs[i] = -1;
 
        i2c_set_clientdata(c, msp);
        init_waitqueue_head(&msp->wq);
@@ -1579,13 +1610,22 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
        /* startup control thread if needed */
        if (thread_func) {
                msp->kthread = kthread_run(thread_func, c, "msp34xx");
+
                if (NULL == msp->kthread)
                        printk(KERN_WARNING "msp34xx: kernel_thread() failed\n");
                msp_wake_thread(c);
        }
 
        /* done */
-        i2c_attach_client(c);
+       i2c_attach_client(c);
+
+       /* update our own array */
+       for (i = 0; i < MSP3400_MAX; i++) {
+               if (NULL == msps[i]) {
+                       msps[i] = c;
+                       break;
+               }
+       }
 
        return 0;
 }
@@ -1593,15 +1633,25 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
 static int msp_detach(struct i2c_client *client)
 {
        struct msp3400c *msp  = i2c_get_clientdata(client);
+       int i;
 
        /* shutdown control thread */
        if (msp->kthread) {
                msp->restart = 1;
                kthread_stop(msp->kthread);
        }
-       msp3400c_reset(client);
+       msp3400c_reset(client);
+
+       /* update our own array */
+       for (i = 0; i < MSP3400_MAX; i++) {
+               if (client == msps[i]) {
+                       msps[i] = NULL;
+                       break;
+               }
+       }
 
        i2c_detach_client(client);
+
        kfree(msp);
        kfree(client);
        return 0;
@@ -1688,7 +1738,7 @@ static void msp_any_set_audmode(struct i2c_client *client, int audmode)
 static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
 {
        struct msp3400c *msp  = i2c_get_clientdata(client);
-        __u16           *sarg = arg;
+       __u16           *sarg = arg;
        int scart = 0;
 
        switch (cmd) {
@@ -1737,6 +1787,9 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
                dprintk("msp34xx: AUDC_SET_RADIO\n");
                msp->norm = VIDEO_MODE_RADIO;
                dprintk("msp34xx: switching to radio mode\n");
+               if (IS_MSP34XX_G(msp))
+                       msp34xxg_reset(client);
+
                msp->watch_stereo = 0;
                switch (msp->opmode) {
                case OPMODE_MANUAL:
@@ -1753,6 +1806,30 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
                        break;
                }
                break;
+               /* work-in-progress:  hook to control the DFP registers */
+       case MSP_SET_DFPREG:
+       {
+               struct msp_dfpreg *r = arg;
+               int i;
+
+               if (r->reg < 0 || r->reg >= DFP_COUNT)
+                       return -EINVAL;
+               for (i = 0; i < sizeof(bl_dfp) / sizeof(int); i++)
+                       if (r->reg == bl_dfp[i])
+                               return -EINVAL;
+               msp->dfp_regs[r->reg] = r->value;
+               msp3400c_write(client, I2C_MSP3400C_DFP, r->reg, r->value);
+               return 0;
+       }
+       case MSP_GET_DFPREG:
+       {
+               struct msp_dfpreg *r = arg;
+
+               if (r->reg < 0 || r->reg >= DFP_COUNT)
+                       return -EINVAL;
+               r->value = msp3400c_read(client, I2C_MSP3400C_DFP, r->reg);
+               return 0;
+       }
 
        /* --- v4l ioctls --- */
        /* take care: bttv does userspace copying, we'll get a
@@ -1827,6 +1904,9 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
 
                dprintk("msp34xx: VIDIOCSCHAN (norm=%d)\n",vc->norm);
                msp->norm = vc->norm;
+               if (IS_MSP34XX_G(msp))
+                       msp34xxg_reset(client);
+
                msp_wake_thread(client);
                break;
        }
@@ -1836,6 +1916,9 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
        {
                /* new channel -- kick audio carrier scan */
                dprintk("msp34xx: VIDIOCSFREQ\n");
+               if (IS_MSP34XX_G(msp))
+                       msp34xxg_reset(client);
+
                msp_wake_thread(client);
                break;
        }
@@ -1882,7 +1965,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
                }
 
                msp_any_detect_stereo(client);
-               if (msp->audmode == V4L2_TUNER_MODE_STEREO) {
+               if (msp->audmode == V4L2_TUNER_MODE_STEREO) {
                        a->capability=V4L2_AUDCAP_STEREO;
                }
 
@@ -1918,7 +2001,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
                        msp3400c_set_scart(client,scart,0);
                        msp3400c_write(client,I2C_MSP3400C_DFP,0x000d,0x1900);
                }
-               if (sarg->capability==V4L2_AUDCAP_STEREO) {
+               if (sarg->capability==V4L2_AUDCAP_STEREO) {
                        msp->audmode = V4L2_TUNER_MODE_STEREO;
                } else {
                        msp->audmode &= ~V4L2_TUNER_MODE_STEREO;