]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/media/video/saa7134/saa7134-core.c
V4L/DVB (3309): SAA7134: GPIO IRQ improvements
[karo-tx-linux.git] / drivers / media / video / saa7134 / saa7134-core.c
index 4275d2ddb8640af1e02e83b803ba917b5eda0cb1..accbc32725cf9d9fdd190c0ff5590e83d8d97291 100644 (file)
@@ -71,6 +71,7 @@ static unsigned int radio_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
 static unsigned int tuner[]    = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
 static unsigned int card[]     = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
 
+
 module_param_array(video_nr, int, NULL, 0444);
 module_param_array(vbi_nr,   int, NULL, 0444);
 module_param_array(radio_nr, int, NULL, 0444);
@@ -88,80 +89,12 @@ LIST_HEAD(saa7134_devlist);
 static LIST_HEAD(mops_list);
 static unsigned int saa7134_devcount;
 
+int (*dmasound_init)(struct saa7134_dev *dev);
+int (*dmasound_exit)(struct saa7134_dev *dev);
+
 #define dprintk(fmt, arg...)   if (core_debug) \
        printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg)
 
-/* ------------------------------------------------------------------ */
-/* debug help functions                                               */
-
-static const char *v4l1_ioctls[] = {
-       "0", "GCAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT",
-       "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ",
-       "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
-       "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
-       "SMICROCODE", "GVBIFMT", "SVBIFMT" };
-#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
-
-static const char *v4l2_ioctls[] = {
-       "QUERYCAP", "1", "ENUM_PIXFMT", "ENUM_FBUFFMT", "G_FMT", "S_FMT",
-       "G_COMP", "S_COMP", "REQBUFS", "QUERYBUF", "G_FBUF", "S_FBUF",
-       "G_WIN", "S_WIN", "PREVIEW", "QBUF", "16", "DQBUF", "STREAMON",
-       "STREAMOFF", "G_PERF", "G_PARM", "S_PARM", "G_STD", "S_STD",
-       "ENUMSTD", "ENUMINPUT", "G_CTRL", "S_CTRL", "G_TUNER", "S_TUNER",
-       "G_FREQ", "S_FREQ", "G_AUDIO", "S_AUDIO", "35", "QUERYCTRL",
-       "QUERYMENU", "G_INPUT", "S_INPUT", "ENUMCVT", "41", "42", "43",
-       "44", "45",  "G_OUTPUT", "S_OUTPUT", "ENUMOUTPUT", "G_AUDOUT",
-       "S_AUDOUT", "ENUMFX", "G_EFFECT", "S_EFFECT", "G_MODULATOR",
-       "S_MODULATOR"
-};
-#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
-
-static const char *osspcm_ioctls[] = {
-       "RESET", "SYNC", "SPEED", "STEREO", "GETBLKSIZE", "SETFMT",
-       "CHANNELS", "?", "POST", "SUBDIVIDE", "SETFRAGMENT", "GETFMTS",
-       "GETOSPACE", "GETISPACE", "NONBLOCK", "GETCAPS", "GET/SETTRIGGER",
-       "GETIPTR", "GETOPTR", "MAPINBUF", "MAPOUTBUF", "SETSYNCRO",
-       "SETDUPLEX", "GETODELAY"
-};
-#define OSSPCM_IOCTLS ARRAY_SIZE(v4l2_ioctls)
-
-void saa7134_print_ioctl(char *name, unsigned int cmd)
-{
-       char *dir;
-
-       switch (_IOC_DIR(cmd)) {
-       case _IOC_NONE:              dir = "--"; break;
-       case _IOC_READ:              dir = "r-"; break;
-       case _IOC_WRITE:             dir = "-w"; break;
-       case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
-       default:                     dir = "??"; break;
-       }
-       switch (_IOC_TYPE(cmd)) {
-       case 'v':
-               printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l1, %s, VIDIOC%s)\n",
-                      name, cmd, dir, (_IOC_NR(cmd) < V4L1_IOCTLS) ?
-                      v4l1_ioctls[_IOC_NR(cmd)] : "???");
-               break;
-       case 'V':
-               printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l2, %s, VIDIOC_%s)\n",
-                      name, cmd, dir, (_IOC_NR(cmd) < V4L2_IOCTLS) ?
-                      v4l2_ioctls[_IOC_NR(cmd)] : "???");
-               break;
-       case 'P':
-               printk(KERN_DEBUG "%s: ioctl 0x%08x (oss dsp, %s, SNDCTL_DSP_%s)\n",
-                      name, cmd, dir, (_IOC_NR(cmd) < OSSPCM_IOCTLS) ?
-                      osspcm_ioctls[_IOC_NR(cmd)] : "???");
-               break;
-       case 'M':
-               printk(KERN_DEBUG "%s: ioctl 0x%08x (oss mixer, %s, #%d)\n",
-                      name, cmd, dir, _IOC_NR(cmd));
-               break;
-       default:
-               printk(KERN_DEBUG "%s: ioctl 0x%08x (???, %s, #%d)\n",
-                      name, cmd, dir, _IOC_NR(cmd));
-       }
-}
-
 void saa7134_track_gpio(struct saa7134_dev *dev, char *msg)
 {
        unsigned long mode,status;
@@ -184,8 +117,7 @@ void saa7134_track_gpio(struct saa7134_dev *dev, char *msg)
 /* ----------------------------------------------------------- */
 /* delayed request_module                                      */
 
-#ifdef CONFIG_MODULES
-
+#if defined(CONFIG_MODULES) && defined(MODULE)
 static int need_empress;
 static int need_dvb;
 static int need_alsa;
@@ -208,7 +140,7 @@ static int pending_call(struct notifier_block *self, unsigned long state,
        return NOTIFY_DONE;
 }
 
-static int pending_registered;
+static int pending_registered=0;
 static struct notifier_block pending_notifier = {
        .notifier_call = pending_call,
 };
@@ -234,9 +166,7 @@ static void request_module_depend(char *name, int *flag)
 }
 
 #else
-
 #define request_module_depend(name,flag)
-
 #endif /* CONFIG_MODULES */
 
 /* ------------------------------------------------------------------ */
@@ -609,11 +539,38 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
                    card_has_mpeg(dev))
                        saa7134_irq_ts_done(dev,status);
 
-               if ((report & (SAA7134_IRQ_REPORT_GPIO16 |
-                              SAA7134_IRQ_REPORT_GPIO18)) &&
-                   dev->remote)
-                       saa7134_input_irq(dev);
+               if (report & SAA7134_IRQ_REPORT_GPIO16) {
+                       switch (dev->has_remote) {
+                               case SAA7134_REMOTE_GPIO:
+                                       if  (dev->remote->mask_keydown & 0x10000) {
+                                               saa7134_input_irq(dev);
+                                       }
+                                       break;
+
+                               case SAA7134_REMOTE_I2C:
+                                       break;                  /* FIXME: invoke I2C get_key() */
+
+                               default:                        /* GPIO16 not used by IR remote */
+                                       break;
+                       }
+               }
 
+               if (report & SAA7134_IRQ_REPORT_GPIO18) {
+                       switch (dev->has_remote) {
+                               case SAA7134_REMOTE_GPIO:
+                                       if ((dev->remote->mask_keydown & 0x40000) ||
+                                           (dev->remote->mask_keyup & 0x40000)) {
+                                               saa7134_input_irq(dev);
+                                       }
+                                       break;
+
+                               case SAA7134_REMOTE_I2C:
+                                       break;                  /* FIXME: invoke I2C get_key() */
+
+                               default:                        /* GPIO18 not used by IR remote */
+                                       break;
+                       }
+               }
        }
 
        if (10 == loop) {
@@ -623,13 +580,16 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
                        printk(KERN_WARNING "%s/irq: looping -- "
                               "clearing PE (parity error!) enable bit\n",dev->name);
                        saa_clearl(SAA7134_IRQ2,SAA7134_IRQ2_INTE_PE);
-               } else if (report & (SAA7134_IRQ_REPORT_GPIO16 |
-                                    SAA7134_IRQ_REPORT_GPIO18)) {
-                       /* disable gpio IRQs */
+               } else if (report & SAA7134_IRQ_REPORT_GPIO16) {
+                       /* disable gpio16 IRQ */
                        printk(KERN_WARNING "%s/irq: looping -- "
-                              "clearing GPIO enable bits\n",dev->name);
-                       saa_clearl(SAA7134_IRQ2, (SAA7134_IRQ2_INTE_GPIO16 |
-                                                 SAA7134_IRQ2_INTE_GPIO18));
+                              "clearing GPIO16 enable bit\n",dev->name);
+                       saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO16);
+               } else if (report & SAA7134_IRQ_REPORT_GPIO18) {
+                       /* disable gpio18 IRQs */
+                       printk(KERN_WARNING "%s/irq: looping -- "
+                              "clearing GPIO18 enable bit\n",dev->name);
+                       saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18);
                } else {
                        /* disable all irqs */
                        printk(KERN_WARNING "%s/irq: looping -- "
@@ -710,10 +670,14 @@ static int saa7134_hwinit2(struct saa7134_dev *dev)
                SAA7134_IRQ2_INTE_PE      |
                SAA7134_IRQ2_INTE_AR;
 
-       if (dev->has_remote == SAA7134_REMOTE_GPIO)
-               irq2_mask |= (SAA7134_IRQ2_INTE_GPIO18  |
-                             SAA7134_IRQ2_INTE_GPIO18A |
-                             SAA7134_IRQ2_INTE_GPIO16  );
+       if (dev->has_remote == SAA7134_REMOTE_GPIO) {
+               if (dev->remote->mask_keydown & 0x10000)
+                       irq2_mask |= SAA7134_IRQ2_INTE_GPIO16;
+               else if (dev->remote->mask_keydown & 0x40000)
+                       irq2_mask |= SAA7134_IRQ2_INTE_GPIO18;
+               else if (dev->remote->mask_keyup & 0x40000)
+                       irq2_mask |= SAA7134_IRQ2_INTE_GPIO18A;
+       }
 
        saa_writel(SAA7134_IRQ1, 0);
        saa_writel(SAA7134_IRQ2, irq2_mask);
@@ -1017,6 +981,10 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
        /* check for signal */
        saa7134_irq_video_intl(dev);
 
+       if (dmasound_init && !dev->dmasound.priv_data) {
+               dmasound_init(dev);
+       }
+
        return 0;
 
  fail4:
@@ -1040,6 +1008,11 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
        struct list_head *item;
        struct saa7134_mpeg_ops *mops;
 
+       /* Release DMA sound modules if present */
+       if (dmasound_exit && dev->dmasound.priv_data) {
+               dmasound_exit(dev);
+       }
+
        /* debugging ... */
        if (irq_debug) {
                u32 report = saa_readl(SAA7134_IRQ_REPORT);
@@ -1071,6 +1044,7 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
        saa7134_i2c_unregister(dev);
        saa7134_unregister_video(dev);
 
+
        /* the DMA sound modules should be unloaded before reaching
           this, but just in case they are still present... */
        if (dev->dmasound.priv_data != NULL) {
@@ -1078,6 +1052,7 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
                dev->dmasound.priv_data = NULL;
        }
 
+
        /* release resources */
        free_irq(pci_dev->irq, dev);
        iounmap(dev->lmmio);
@@ -1144,15 +1119,15 @@ static int saa7134_init(void)
        printk(KERN_INFO "saa7130/34: snapshot date %04d-%02d-%02d\n",
               SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
 #endif
-       return pci_module_init(&saa7134_pci_driver);
+       return pci_register_driver(&saa7134_pci_driver);
 }
 
 static void saa7134_fini(void)
 {
-#ifdef CONFIG_MODULES
+#if defined(CONFIG_MODULES) && defined(MODULE)
        if (pending_registered)
                unregister_module_notifier(&pending_notifier);
-#endif
+#endif /* CONFIG_MODULES */
        pci_unregister_driver(&saa7134_pci_driver);
 }
 
@@ -1161,13 +1136,14 @@ module_exit(saa7134_fini);
 
 /* ----------------------------------------------------------- */
 
-EXPORT_SYMBOL(saa7134_print_ioctl);
 EXPORT_SYMBOL(saa7134_i2c_call_clients);
 EXPORT_SYMBOL(saa7134_devlist);
 EXPORT_SYMBOL(saa7134_boards);
 
 /* ----------------- for the DMA sound modules --------------- */
 
+EXPORT_SYMBOL(dmasound_init);
+EXPORT_SYMBOL(dmasound_exit);
 EXPORT_SYMBOL(saa7134_pgtable_free);
 EXPORT_SYMBOL(saa7134_pgtable_build);
 EXPORT_SYMBOL(saa7134_pgtable_alloc);