V4L/DVB (8523): v4l2-dev: remove unused type and type2 field from video_device
[linux-3.10.git] / drivers / media / video / saa7134 / saa7134-core.c
index 1434785..75d6184 100644 (file)
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/module.h>
-#include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/kmod.h>
 #include <linux/sound.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/dma-mapping.h>
+#include <linux/pm.h>
 
 #include "saa7134-reg.h"
 #include "saa7134.h"
@@ -41,133 +42,65 @@ MODULE_LICENSE("GPL");
 
 /* ------------------------------------------------------------------ */
 
-static unsigned int irq_debug = 0;
+static unsigned int irq_debug;
 module_param(irq_debug, int, 0644);
 MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]");
 
-static unsigned int core_debug = 0;
+static unsigned int core_debug;
 module_param(core_debug, int, 0644);
 MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
 
-static unsigned int gpio_tracking = 0;
+static unsigned int gpio_tracking;
 module_param(gpio_tracking, int, 0644);
 MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]");
 
-static unsigned int oss = 0;
-module_param(oss, int, 0444);
-MODULE_PARM_DESC(oss,"register oss devices (default: no)");
+static unsigned int alsa;
+module_param(alsa, int, 0644);
+MODULE_PARM_DESC(alsa,"enable ALSA DMA sound [dmasound]");
 
-static unsigned int alsa = 0;
-module_param(alsa, int, 0444);
-MODULE_PARM_DESC(alsa,"register alsa devices (default: no)");
+static unsigned int oss;
+module_param(oss, int, 0644);
+MODULE_PARM_DESC(oss,"enable OSS DMA sound [dmasound]");
 
 static unsigned int latency = UNSET;
 module_param(latency, int, 0444);
 MODULE_PARM_DESC(latency,"pci latency timer");
 
+int saa7134_no_overlay=-1;
+module_param_named(no_overlay, saa7134_no_overlay, int, 0444);
+MODULE_PARM_DESC(no_overlay,"allow override overlay default (0 disables, 1 enables)"
+               " [some VIA/SIS chipsets are known to have problem with overlay]");
+
 static unsigned int video_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
 static unsigned int vbi_nr[]   = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
 static unsigned int radio_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
-static unsigned int dsp_nr[]   = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
-static unsigned int mixer_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);
-module_param_array(dsp_nr,   int, NULL, 0444);
-module_param_array(mixer_nr, int, NULL, 0444);
 module_param_array(tuner,    int, NULL, 0444);
 module_param_array(card,     int, NULL, 0444);
 
 MODULE_PARM_DESC(video_nr, "video device number");
 MODULE_PARM_DESC(vbi_nr,   "vbi device number");
 MODULE_PARM_DESC(radio_nr, "radio device number");
-MODULE_PARM_DESC(dsp_nr,   "oss dsp device number");
-MODULE_PARM_DESC(mixer_nr, "oss mixer device number");
 MODULE_PARM_DESC(tuner,    "tuner type");
 MODULE_PARM_DESC(card,     "card type");
 
-static DECLARE_MUTEX(devlist_lock);
+static DEFINE_MUTEX(devlist_lock);
 LIST_HEAD(saa7134_devlist);
 static LIST_HEAD(mops_list);
 static unsigned int saa7134_devcount;
 
+int (*saa7134_dmasound_init)(struct saa7134_dev *dev);
+int (*saa7134_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,61 +117,59 @@ void saa7134_track_gpio(struct saa7134_dev *dev, char *msg)
               dev->name, mode, (~mode) & status, mode & status, msg);
 }
 
+void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value)
+{
+       u32 index, bitval;
+
+       index = 1 << bit_no;
+       switch (value) {
+       case 0: /* static value */
+       case 1: dprintk("setting GPIO%d to static %d\n", bit_no, value);
+               /* turn sync mode off if necessary */
+               if (index & 0x00c00000)
+                       saa_andorb(SAA7134_VIDEO_PORT_CTRL6, 0x0f, 0x00);
+               if (value)
+                       bitval = index;
+               else
+                       bitval = 0;
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, index, index);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, index, bitval);
+               break;
+       case 3: /* tristate */
+               dprintk("setting GPIO%d to tristate\n", bit_no);
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, index, 0);
+               break;
+       }
+}
+
 /* ------------------------------------------------------------------ */
 
 
 /* ----------------------------------------------------------- */
 /* delayed request_module                                      */
 
-#ifdef CONFIG_MODULES
-
-static int need_empress;
-static int need_dvb;
-static int need_alsa;
-
-static int pending_call(struct notifier_block *self, unsigned long state,
-                       void *module)
-{
-       if (module != THIS_MODULE || state != MODULE_STATE_LIVE)
-               return NOTIFY_DONE;
+#if defined(CONFIG_MODULES) && defined(MODULE)
 
-       if (need_empress)
+static void request_module_async(struct work_struct *work){
+       struct saa7134_dev* dev = container_of(work, struct saa7134_dev, request_module_wk);
+       if (card_is_empress(dev))
                request_module("saa7134-empress");
-       if (need_dvb)
+       if (card_is_dvb(dev))
                request_module("saa7134-dvb");
-       if (need_alsa)
+       if (alsa)
                request_module("saa7134-alsa");
-       return NOTIFY_DONE;
+       if (oss)
+               request_module("saa7134-oss");
 }
 
-static int pending_registered;
-static struct notifier_block pending_notifier = {
-       .notifier_call = pending_call,
-};
-
-static void request_module_depend(char *name, int *flag)
+static void request_submodules(struct saa7134_dev *dev)
 {
-       switch (THIS_MODULE->state) {
-       case MODULE_STATE_COMING:
-               if (!pending_registered) {
-                       register_module_notifier(&pending_notifier);
-                       pending_registered = 1;
-               }
-               *flag = 1;
-               break;
-       case MODULE_STATE_LIVE:
-               request_module(name);
-               break;
-       default:
-               /* nothing */;
-               break;
-       }
+       INIT_WORK(&dev->request_module_wk, request_module_async);
+       schedule_work(&dev->request_module_wk);
 }
 
 #else
-
-#define request_module_depend(name,flag)
-
+#define request_submodules(dev)
 #endif /* CONFIG_MODULES */
 
 /* ------------------------------------------------------------------ */
@@ -272,9 +203,10 @@ int saa7134_buffer_startpage(struct saa7134_buf *buf)
 unsigned long saa7134_buffer_base(struct saa7134_buf *buf)
 {
        unsigned long base;
+       struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
 
        base  = saa7134_buffer_startpage(buf) * 4096;
-       base += buf->vb.dma.sglist[0].offset;
+       base += dma->sglist[0].offset;
        return base;
 }
 
@@ -320,15 +252,15 @@ void saa7134_pgtable_free(struct pci_dev *pci, struct saa7134_pgtable *pt)
 
 /* ------------------------------------------------------------------ */
 
-void saa7134_dma_free(struct saa7134_dev *dev,struct saa7134_buf *buf)
+void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf)
 {
-       if (in_interrupt())
-               BUG();
+       struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+       BUG_ON(in_interrupt());
 
        videobuf_waiton(&buf->vb,0,0);
-       videobuf_dma_pci_unmap(dev->pci, &buf->vb.dma);
-       videobuf_dma_free(&buf->vb.dma);
-       buf->vb.state = STATE_NEEDS_INIT;
+       videobuf_dma_unmap(q, dma);
+       videobuf_dma_free(dma);
+       buf->vb.state = VIDEOBUF_NEEDS_INIT;
 }
 
 /* ------------------------------------------------------------------ */
@@ -347,7 +279,7 @@ int saa7134_buffer_queue(struct saa7134_dev *dev,
                        buf->activate(dev,buf,NULL);
                } else if (list_empty(&q->queue)) {
                        list_add_tail(&buf->vb.queue,&q->queue);
-                       buf->vb.state = STATE_QUEUED;
+                       buf->vb.state = VIDEOBUF_QUEUED;
                } else {
                        next = list_entry(q->queue.next,struct saa7134_buf,
                                          vb.queue);
@@ -356,7 +288,7 @@ int saa7134_buffer_queue(struct saa7134_dev *dev,
                }
        } else {
                list_add_tail(&buf->vb.queue,&q->queue);
-               buf->vb.state = STATE_QUEUED;
+               buf->vb.state = VIDEOBUF_QUEUED;
        }
        return 0;
 }
@@ -421,12 +353,38 @@ void saa7134_buffer_timeout(unsigned long data)
           try to start over with the next one. */
        if (q->curr) {
                dprintk("timeout on %p\n",q->curr);
-               saa7134_buffer_finish(dev,q,STATE_ERROR);
+               saa7134_buffer_finish(dev,q,VIDEOBUF_ERROR);
        }
        saa7134_buffer_next(dev,q);
        spin_unlock_irqrestore(&dev->slock,flags);
 }
 
+/* resends a current buffer in queue after resume */
+
+static int saa7134_buffer_requeue(struct saa7134_dev *dev,
+                                 struct saa7134_dmaqueue *q)
+{
+       struct saa7134_buf *buf, *next;
+
+       assert_spin_locked(&dev->slock);
+
+       buf  = q->curr;
+       next = buf;
+       dprintk("buffer_requeue\n");
+
+       if (!buf)
+               return 0;
+
+       dprintk("buffer_requeue : resending active buffers \n");
+
+       if (!list_empty(&q->queue))
+               next = list_entry(q->queue.next, struct saa7134_buf,
+                                         vb.queue);
+       buf->activate(dev, buf, next);
+
+       return 0;
+}
+
 /* ------------------------------------------------------------------ */
 
 int saa7134_set_dmabits(struct saa7134_dev *dev)
@@ -437,6 +395,9 @@ int saa7134_set_dmabits(struct saa7134_dev *dev)
 
        assert_spin_locked(&dev->slock);
 
+       if (dev->insuspend)
+               return 0;
+
        /* video capture -- dma 0 + video task A */
        if (dev->video_q.curr) {
                task |= 0x01;
@@ -562,28 +523,34 @@ static void print_irqstatus(struct saa7134_dev *dev, int loop,
        printk("\n");
 }
 
-static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t saa7134_irq(int irq, void *dev_id)
 {
        struct saa7134_dev *dev = (struct saa7134_dev*) dev_id;
        unsigned long report,status;
        int loop, handled = 0;
 
+       if (dev->insuspend)
+               goto out;
+
        for (loop = 0; loop < 10; loop++) {
                report = saa_readl(SAA7134_IRQ_REPORT);
                status = saa_readl(SAA7134_IRQ_STATUS);
-               if (0 == report) {
+
+               /* If dmasound support is active and we get a sound report,
+                * mask out the report and let the saa7134-alsa module deal
+                * with it */
+               if ((report & SAA7134_IRQ_REPORT_DONE_RA3) &&
+                       (dev->dmasound.priv_data != NULL) )
+               {
                        if (irq_debug > 1)
-                               printk(KERN_DEBUG "%s/irq: no (more) work\n",
+                               printk(KERN_DEBUG "%s/irq: preserving DMA sound interrupt\n",
                                       dev->name);
-                       goto out;
+                       report &= ~SAA7134_IRQ_REPORT_DONE_RA3;
                }
 
-               /* If alsa support is active and we get a sound report, exit
-                  and let the saa7134-alsa module deal with it */
-
-               if ((report & SAA7134_IRQ_REPORT_DONE_RA3) && alsa)  {
+               if (0 == report) {
                        if (irq_debug > 1)
-                               printk(KERN_DEBUG "%s/irq: ignoring interrupt for ALSA\n",
+                               printk(KERN_DEBUG "%s/irq: no (more) work\n",
                                       dev->name);
                        goto out;
                }
@@ -594,8 +561,10 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
                        print_irqstatus(dev,loop,report,status);
 
 
-               if (report & SAA7134_IRQ_REPORT_RDCAP /* _INTL */)
-                       saa7134_irq_video_intl(dev);
+               if ((report & SAA7134_IRQ_REPORT_RDCAP) ||
+                       (report & SAA7134_IRQ_REPORT_INTL))
+                               saa7134_irq_video_signalchange(dev);
+
 
                if ((report & SAA7134_IRQ_REPORT_DONE_RA0) &&
                    (status & 0x60) == 0)
@@ -609,17 +578,42 @@ 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_DONE_RA3))  {
-                       if (oss) {
-                               saa7134_irq_oss_done(dev,status);
+               if (report & SAA7134_IRQ_REPORT_GPIO16) {
+                       switch (dev->has_remote) {
+                               case SAA7134_REMOTE_GPIO:
+                                       if (!dev->remote)
+                                               break;
+                                       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_GPIO16 |
-                              SAA7134_IRQ_REPORT_GPIO18)) &&
-                   dev->remote)
-                       saa7134_input_irq(dev);
-
+               if (report & SAA7134_IRQ_REPORT_GPIO18) {
+                       switch (dev->has_remote) {
+                               case SAA7134_REMOTE_GPIO:
+                                       if (!dev->remote)
+                                               break;
+                                       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) {
@@ -629,13 +623,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 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 GPIO enable bits\n",dev->name);
-                       saa_clearl(SAA7134_IRQ2, (SAA7134_IRQ2_INTE_GPIO16 |
-                                                 SAA7134_IRQ2_INTE_GPIO18));
+                              "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 -- "
@@ -652,13 +649,46 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
 /* ------------------------------------------------------------------ */
 
 /* early init (no i2c, no irq) */
+
+static int saa7134_hw_enable1(struct saa7134_dev *dev)
+{
+       /* RAM FIFO config */
+       saa_writel(SAA7134_FIFO_SIZE, 0x08070503);
+       saa_writel(SAA7134_THRESHOULD, 0x02020202);
+
+       /* enable audio + video processing */
+       saa_writel(SAA7134_MAIN_CTRL,
+                       SAA7134_MAIN_CTRL_VPLLE |
+                       SAA7134_MAIN_CTRL_APLLE |
+                       SAA7134_MAIN_CTRL_EXOSC |
+                       SAA7134_MAIN_CTRL_EVFE1 |
+                       SAA7134_MAIN_CTRL_EVFE2 |
+                       SAA7134_MAIN_CTRL_ESFE  |
+                       SAA7134_MAIN_CTRL_EBDAC);
+
+       /*
+       * Initialize OSS _after_ enabling audio clock PLL and audio processing.
+       * OSS initialization writes to registers via the audio DSP; these
+       * writes will fail unless the audio clock has been started.  At worst,
+       * audio will not work.
+       */
+
+       /* enable peripheral devices */
+       saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
+
+       /* set vertical line numbering start (vbi needs this) */
+       saa_writeb(SAA7134_SOURCE_TIMING2, 0x20);
+
+       return 0;
+}
+
 static int saa7134_hwinit1(struct saa7134_dev *dev)
 {
        dprintk("hwinit1\n");
 
        saa_writel(SAA7134_IRQ1, 0);
        saa_writel(SAA7134_IRQ2, 0);
-       init_MUTEX(&dev->lock);
+       mutex_init(&dev->lock);
        spin_lock_init(&dev->slock);
 
        saa7134_track_gpio(dev,"pre-init");
@@ -668,52 +698,16 @@ static int saa7134_hwinit1(struct saa7134_dev *dev)
                saa7134_ts_init1(dev);
        saa7134_input_init1(dev);
 
-       /* RAM FIFO config */
-       saa_writel(SAA7134_FIFO_SIZE, 0x08070503);
-       saa_writel(SAA7134_THRESHOULD,0x02020202);
-
-       /* enable audio + video processing */
-       saa_writel(SAA7134_MAIN_CTRL,
-                  SAA7134_MAIN_CTRL_VPLLE |
-                  SAA7134_MAIN_CTRL_APLLE |
-                  SAA7134_MAIN_CTRL_EXOSC |
-                  SAA7134_MAIN_CTRL_EVFE1 |
-                  SAA7134_MAIN_CTRL_EVFE2 |
-                  SAA7134_MAIN_CTRL_ESFE  |
-                  SAA7134_MAIN_CTRL_EBDAC);
-
-       /*
-        * Initialize OSS _after_ enabling audio clock PLL and audio processing.
-        * OSS initialization writes to registers via the audio DSP; these
-        * writes will fail unless the audio clock has been started.  At worst,
-        * audio will not work.
-        */
-
-       switch (dev->pci->device) {
-       case PCI_DEVICE_ID_PHILIPS_SAA7134:
-       case PCI_DEVICE_ID_PHILIPS_SAA7133:
-       case PCI_DEVICE_ID_PHILIPS_SAA7135:
-               saa7134_oss_init1(dev);
-               break;
-       }
-
-       /* enable peripheral devices */
-       saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
-
-       /* set vertical line numbering start (vbi needs this) */
-       saa_writeb(SAA7134_SOURCE_TIMING2, 0x20);
+       saa7134_hw_enable1(dev);
 
        return 0;
 }
 
 /* late init (with i2c + irq) */
-static int saa7134_hwinit2(struct saa7134_dev *dev)
+static int saa7134_hw_enable2(struct saa7134_dev *dev)
 {
-       unsigned int irq2_mask;
-       dprintk("hwinit2\n");
 
-       saa7134_video_init2(dev);
-       saa7134_tvaudio_init2(dev);
+       unsigned int irq2_mask;
 
        /* enable IRQ's */
        irq2_mask =
@@ -724,10 +718,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 && dev->remote) {
+               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);
@@ -735,23 +733,29 @@ static int saa7134_hwinit2(struct saa7134_dev *dev)
        return 0;
 }
 
+static int saa7134_hwinit2(struct saa7134_dev *dev)
+{
+
+       dprintk("hwinit2\n");
+
+       saa7134_video_init2(dev);
+       saa7134_tvaudio_init2(dev);
+
+       saa7134_hw_enable2(dev);
+
+       return 0;
+}
+
+
 /* shutdown */
 static int saa7134_hwfini(struct saa7134_dev *dev)
 {
        dprintk("hwfini\n");
 
-       switch (dev->pci->device) {
-       case PCI_DEVICE_ID_PHILIPS_SAA7134:
-       case PCI_DEVICE_ID_PHILIPS_SAA7133:
-       case PCI_DEVICE_ID_PHILIPS_SAA7135:
-               saa7134_oss_fini(dev);
-               break;
-       }
        if (card_has_mpeg(dev))
                saa7134_ts_fini(dev);
        saa7134_input_fini(dev);
        saa7134_vbi_fini(dev);
-       saa7134_video_fini(dev);
        saa7134_tvaudio_fini(dev);
        return 0;
 }
@@ -794,8 +798,9 @@ static struct video_device *vdev_init(struct saa7134_dev *dev,
                return NULL;
        *vfd = *template;
        vfd->minor   = -1;
-       vfd->dev     = &dev->pci->dev;
+       vfd->parent  = &dev->pci->dev;
        vfd->release = video_device_release;
+       vfd->debug   = video_debug;
        snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
                 dev->name, type, saa7134_boards[dev->board].name);
        return vfd;
@@ -856,14 +861,15 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
                                     const struct pci_device_id *pci_id)
 {
        struct saa7134_dev *dev;
-       struct list_head *item;
        struct saa7134_mpeg_ops *mops;
        int err;
 
-       dev = kmalloc(sizeof(*dev),GFP_KERNEL);
+       if (saa7134_devcount == SAA7134_MAXBOARDS)
+               return -ENOMEM;
+
+       dev = kzalloc(sizeof(*dev),GFP_KERNEL);
        if (NULL == dev)
                return -ENOMEM;
-       memset(dev,0,sizeof(*dev));
 
        /* pci init */
        dev->pci = pci_dev;
@@ -892,6 +898,22 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
                        latency = 0x0A;
                }
 #endif
+               if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL)) {
+                       printk(KERN_INFO "%s: quirk: this driver and your "
+                                       "chipset may not work together"
+                                       " in overlay mode.\n",dev->name);
+                       if (!saa7134_no_overlay) {
+                               printk(KERN_INFO "%s: quirk: overlay "
+                                               "mode will be disabled.\n",
+                                               dev->name);
+                               saa7134_no_overlay = 1;
+                       } else {
+                               printk(KERN_INFO "%s: quirk: overlay "
+                                               "mode will be forced. Use this"
+                                               " option at your own risk.\n",
+                                               dev->name);
+                       }
+               }
        }
        if (UNSET != latency) {
                printk(KERN_INFO "%s: setting pci latency timer to %d\n",
@@ -903,11 +925,11 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
        pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev);
        pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER,  &dev->pci_lat);
        printk(KERN_INFO "%s: found at %s, rev: %d, irq: %d, "
-              "latency: %d, mmio: 0x%lx\n", dev->name,
+              "latency: %d, mmio: 0x%llx\n", dev->name,
               pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
-              dev->pci_lat,pci_resource_start(pci_dev,0));
+              dev->pci_lat,(unsigned long long)pci_resource_start(pci_dev,0));
        pci_set_master(pci_dev);
-       if (!pci_dma_supported(pci_dev,0xffffffff)) {
+       if (!pci_dma_supported(pci_dev, DMA_32BIT_MASK)) {
                printk("%s: Oops: no 32bit PCI DMA ???\n",dev->name);
                err = -EIO;
                goto fail1;
@@ -922,23 +944,25 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
                must_configure_manually();
                dev->board = SAA7134_BOARD_UNKNOWN;
        }
-       dev->tuner_type   = saa7134_boards[dev->board].tuner_type;
+       dev->autodetected = card[dev->nr] != dev->board;
+       dev->tuner_type = saa7134_boards[dev->board].tuner_type;
+       dev->tuner_addr = saa7134_boards[dev->board].tuner_addr;
        dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf;
        if (UNSET != tuner[dev->nr])
                dev->tuner_type = tuner[dev->nr];
        printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
-              dev->name,pci_dev->subsystem_vendor,
-              pci_dev->subsystem_device,saa7134_boards[dev->board].name,
-              dev->board, card[dev->nr] == dev->board ?
-              "insmod option" : "autodetected");
+               dev->name,pci_dev->subsystem_vendor,
+               pci_dev->subsystem_device,saa7134_boards[dev->board].name,
+               dev->board, dev->autodetected ?
+               "autodetected" : "insmod option");
 
        /* get mmio */
        if (!request_mem_region(pci_resource_start(pci_dev,0),
                                pci_resource_len(pci_dev,0),
                                dev->name)) {
                err = -EBUSY;
-               printk(KERN_ERR "%s: can't get MMIO memory @ 0x%lx\n",
-                      dev->name,pci_resource_start(pci_dev,0));
+               printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n",
+                      dev->name,(unsigned long long)pci_resource_start(pci_dev,0));
                goto fail1;
        }
        dev->lmmio = ioremap(pci_resource_start(pci_dev,0), 0x1000);
@@ -956,7 +980,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
 
        /* get irq */
        err = request_irq(pci_dev->irq, saa7134_irq,
-                         SA_SHIRQ | SA_INTERRUPT, dev->name, dev);
+                         IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
        if (err < 0) {
                printk(KERN_ERR "%s: can't get IRQ %d\n",
                       dev->name,pci_dev->irq);
@@ -968,31 +992,25 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
        saa7134_i2c_register(dev);
 
        /* initialize hardware #2 */
+       if (TUNER_ABSENT != dev->tuner_type)
+               request_module("tuner");
        saa7134_board_init2(dev);
+
        saa7134_hwinit2(dev);
 
        /* load i2c helpers */
-       if (TUNER_ABSENT != dev->tuner_type)
-               request_module("tuner");
-       if (dev->tda9887_conf)
-               request_module("tda9887");
        if (card_is_empress(dev)) {
                request_module("saa6752hs");
-               request_module_depend("saa7134-empress",&need_empress);
-       }
-
-       if (card_is_dvb(dev))
-               request_module_depend("saa7134-dvb",&need_dvb);
-
-       if (!oss && alsa) {
-               dprintk("Requesting ALSA module\n");
-               request_module_depend("saa7134-alsa",&need_alsa);
        }
 
+       request_submodules(dev);
 
        v4l2_prio_init(&dev->prio);
 
        /* register v4l devices */
+       if (saa7134_no_overlay > 0)
+               printk(KERN_INFO "%s: Overlay support disabled.\n", dev->name);
+
        dev->video_dev = vdev_init(dev,&saa7134_video_template,"video");
        err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
                                    video_nr[dev->nr]);
@@ -1004,7 +1022,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
        printk(KERN_INFO "%s: registered device video%d [v4l2]\n",
               dev->name,dev->video_dev->minor & 0x1f);
 
-       dev->vbi_dev = vdev_init(dev,&saa7134_vbi_template,"vbi");
+       dev->vbi_dev = vdev_init(dev, &saa7134_video_template, "vbi");
+
        err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
                                    vbi_nr[dev->nr]);
        if (err < 0)
@@ -1022,58 +1041,28 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
                       dev->name,dev->radio_dev->minor & 0x1f);
        }
 
-       /* register oss devices */
-       switch (dev->pci->device) {
-       case PCI_DEVICE_ID_PHILIPS_SAA7134:
-       case PCI_DEVICE_ID_PHILIPS_SAA7133:
-       case PCI_DEVICE_ID_PHILIPS_SAA7135:
-               if (oss) {
-                       err = dev->dmasound.minor_dsp =
-                               register_sound_dsp(&saa7134_dsp_fops,
-                                                  dsp_nr[dev->nr]);
-                       if (err < 0) {
-                               goto fail4;
-                       }
-                       printk(KERN_INFO "%s: registered device dsp%d\n",
-                              dev->name,dev->dmasound.minor_dsp >> 4);
-
-                       err = dev->dmasound.minor_mixer =
-                               register_sound_mixer(&saa7134_mixer_fops,
-                                                    mixer_nr[dev->nr]);
-                       if (err < 0)
-                               goto fail5;
-                       printk(KERN_INFO "%s: registered device mixer%d\n",
-                              dev->name,dev->dmasound.minor_mixer >> 4);
-               }
-               break;
-       }
-
        /* everything worked */
        pci_set_drvdata(pci_dev,dev);
        saa7134_devcount++;
 
-       down(&devlist_lock);
-       list_for_each(item,&mops_list) {
-               mops = list_entry(item, struct saa7134_mpeg_ops, next);
+       mutex_lock(&devlist_lock);
+       list_for_each_entry(mops, &mops_list, next)
                mpeg_ops_attach(mops, dev);
-       }
        list_add_tail(&dev->devlist,&saa7134_devlist);
-       up(&devlist_lock);
+       mutex_unlock(&devlist_lock);
 
        /* check for signal */
-       saa7134_irq_video_intl(dev);
+       saa7134_irq_video_signalchange(dev);
+
+       if (saa7134_dmasound_init && !dev->dmasound.priv_data) {
+               saa7134_dmasound_init(dev);
+       }
+
+       if (TUNER_ABSENT != dev->tuner_type)
+               saa7134_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL);
 
        return 0;
 
- fail5:
-       switch (dev->pci->device) {
-       case PCI_DEVICE_ID_PHILIPS_SAA7134:
-       case PCI_DEVICE_ID_PHILIPS_SAA7133:
-       case PCI_DEVICE_ID_PHILIPS_SAA7135:
-               if (oss)
-                       unregister_sound_dsp(dev->dmasound.minor_dsp);
-               break;
-       }
  fail4:
        saa7134_unregister_video(dev);
        saa7134_i2c_unregister(dev);
@@ -1092,9 +1081,13 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
 static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
 {
        struct saa7134_dev *dev = pci_get_drvdata(pci_dev);
-       struct list_head *item;
        struct saa7134_mpeg_ops *mops;
 
+       /* Release DMA sound modules if present */
+       if (saa7134_dmasound_exit && dev->dmasound.priv_data) {
+               saa7134_dmasound_exit(dev);
+       }
+
        /* debugging ... */
        if (irq_debug) {
                u32 report = saa_readl(SAA7134_IRQ_REPORT);
@@ -1114,29 +1107,26 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
        saa7134_hwfini(dev);
 
        /* unregister */
-       down(&devlist_lock);
+       mutex_lock(&devlist_lock);
        list_del(&dev->devlist);
-       list_for_each(item,&mops_list) {
-               mops = list_entry(item, struct saa7134_mpeg_ops, next);
+       list_for_each_entry(mops, &mops_list, next)
                mpeg_ops_detach(mops, dev);
-       }
-       up(&devlist_lock);
+       mutex_unlock(&devlist_lock);
        saa7134_devcount--;
 
        saa7134_i2c_unregister(dev);
-       switch (dev->pci->device) {
-       case PCI_DEVICE_ID_PHILIPS_SAA7134:
-       case PCI_DEVICE_ID_PHILIPS_SAA7133:
-       case PCI_DEVICE_ID_PHILIPS_SAA7135:
-               if (oss) {
-                       unregister_sound_mixer(dev->dmasound.minor_mixer);
-                       unregister_sound_dsp(dev->dmasound.minor_dsp);
-               }
-               break;
-       }
        saa7134_unregister_video(dev);
 
-       /* release ressources */
+
+       /* the DMA sound modules should be unloaded before reaching
+          this, but just in case they are still present... */
+       if (dev->dmasound.priv_data != NULL) {
+               free_irq(pci_dev->irq, &dev->dmasound);
+               dev->dmasound.priv_data = NULL;
+       }
+
+
+       /* release resources */
        free_irq(pci_dev->irq, dev);
        iounmap(dev->lmmio);
        release_mem_region(pci_resource_start(pci_dev,0),
@@ -1148,35 +1138,125 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
        kfree(dev);
 }
 
+#ifdef CONFIG_PM
+static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state)
+{
+
+       struct saa7134_dev *dev = pci_get_drvdata(pci_dev);
+
+       /* disable overlay - apps should enable it explicitly on resume*/
+       dev->ovenable = 0;
+
+       /* Disable interrupts, DMA, and rest of the chip*/
+       saa_writel(SAA7134_IRQ1, 0);
+       saa_writel(SAA7134_IRQ2, 0);
+       saa_writel(SAA7134_MAIN_CTRL, 0);
+
+       dev->insuspend = 1;
+       synchronize_irq(pci_dev->irq);
+
+       /* ACK interrupts once more, just in case,
+               since the IRQ handler won't ack them anymore*/
+
+       saa_writel(SAA7134_IRQ_REPORT, saa_readl(SAA7134_IRQ_REPORT));
+
+       /* Disable timeout timers - if we have active buffers, we will
+          fill them on resume*/
+
+       del_timer(&dev->video_q.timeout);
+       del_timer(&dev->vbi_q.timeout);
+       del_timer(&dev->ts_q.timeout);
+
+       if (dev->remote)
+               saa7134_ir_stop(dev);
+
+       pci_save_state(pci_dev);
+       pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state));
+
+       return 0;
+}
+
+static int saa7134_resume(struct pci_dev *pci_dev)
+{
+       struct saa7134_dev *dev = pci_get_drvdata(pci_dev);
+       unsigned long flags;
+
+       pci_set_power_state(pci_dev, PCI_D0);
+       pci_restore_state(pci_dev);
+
+       /* Do things that are done in saa7134_initdev ,
+               except of initializing memory structures.*/
+
+       saa7134_board_init1(dev);
+
+       /* saa7134_hwinit1 */
+       if (saa7134_boards[dev->board].video_out)
+               saa7134_videoport_init(dev);
+       if (card_has_mpeg(dev))
+               saa7134_ts_init_hw(dev);
+       if (dev->remote)
+               saa7134_ir_start(dev, dev->remote);
+       saa7134_hw_enable1(dev);
+
+       msleep(100);
+
+       saa7134_board_init2(dev);
+
+       /*saa7134_hwinit2*/
+       saa7134_set_tvnorm_hw(dev);
+       saa7134_tvaudio_setmute(dev);
+       saa7134_tvaudio_setvolume(dev, dev->ctl_volume);
+       saa7134_tvaudio_init(dev);
+       saa7134_tvaudio_do_scan(dev);
+       saa7134_enable_i2s(dev);
+       saa7134_hw_enable2(dev);
+
+       saa7134_irq_video_signalchange(dev);
+
+       /*resume unfinished buffer(s)*/
+       spin_lock_irqsave(&dev->slock, flags);
+       saa7134_buffer_requeue(dev, &dev->video_q);
+       saa7134_buffer_requeue(dev, &dev->vbi_q);
+       saa7134_buffer_requeue(dev, &dev->ts_q);
+
+       /* FIXME: Disable DMA audio sound - temporary till proper support
+                 is implemented*/
+
+       dev->dmasound.dma_running = 0;
+
+       /* start DMA now*/
+       dev->insuspend = 0;
+       smp_wmb();
+       saa7134_set_dmabits(dev);
+       spin_unlock_irqrestore(&dev->slock, flags);
+
+       return 0;
+}
+#endif
+
 /* ----------------------------------------------------------- */
 
 int saa7134_ts_register(struct saa7134_mpeg_ops *ops)
 {
-       struct list_head *item;
        struct saa7134_dev *dev;
 
-       down(&devlist_lock);
-       list_for_each(item,&saa7134_devlist) {
-               dev = list_entry(item, struct saa7134_dev, devlist);
+       mutex_lock(&devlist_lock);
+       list_for_each_entry(dev, &saa7134_devlist, devlist)
                mpeg_ops_attach(ops, dev);
-       }
        list_add_tail(&ops->next,&mops_list);
-       up(&devlist_lock);
+       mutex_unlock(&devlist_lock);
        return 0;
 }
 
 void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops)
 {
-       struct list_head *item;
        struct saa7134_dev *dev;
 
-       down(&devlist_lock);
+       mutex_lock(&devlist_lock);
        list_del(&ops->next);
-       list_for_each(item,&saa7134_devlist) {
-               dev = list_entry(item, struct saa7134_dev, devlist);
+       list_for_each_entry(dev, &saa7134_devlist, devlist)
                mpeg_ops_detach(ops, dev);
-       }
-       up(&devlist_lock);
+       mutex_unlock(&devlist_lock);
 }
 
 EXPORT_SYMBOL(saa7134_ts_register);
@@ -1189,6 +1269,10 @@ static struct pci_driver saa7134_pci_driver = {
        .id_table = saa7134_pci_tbl,
        .probe    = saa7134_initdev,
        .remove   = __devexit_p(saa7134_finidev),
+#ifdef CONFIG_PM
+       .suspend  = saa7134_suspend,
+       .resume   = saa7134_resume
+#endif
 };
 
 static int saa7134_init(void)
@@ -1202,15 +1286,11 @@ 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 (pending_registered)
-               unregister_module_notifier(&pending_notifier);
-#endif
        pci_unregister_driver(&saa7134_pci_driver);
 }
 
@@ -1219,13 +1299,15 @@ module_exit(saa7134_fini);
 
 /* ----------------------------------------------------------- */
 
-EXPORT_SYMBOL(saa7134_print_ioctl);
+EXPORT_SYMBOL(saa7134_set_gpio);
 EXPORT_SYMBOL(saa7134_i2c_call_clients);
 EXPORT_SYMBOL(saa7134_devlist);
 EXPORT_SYMBOL(saa7134_boards);
 
-/* ----------------- For ALSA -------------------------------- */
+/* ----------------- for the DMA sound modules --------------- */
 
+EXPORT_SYMBOL(saa7134_dmasound_init);
+EXPORT_SYMBOL(saa7134_dmasound_exit);
 EXPORT_SYMBOL(saa7134_pgtable_free);
 EXPORT_SYMBOL(saa7134_pgtable_build);
 EXPORT_SYMBOL(saa7134_pgtable_alloc);