V4L/DVB (3269): ioctls cleanups.
[pandora-kernel.git] / drivers / media / video / bttv-driver.c
index 0005741..f3de852 100644 (file)
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/kdev_t.h>
+#include "bttvp.h"
+#include <media/v4l2-common.h>
+
 #include <linux/dma-mapping.h>
 
 #include <asm/io.h>
 #include <asm/byteorder.h>
 
-#include "bttvp.h"
-
 #include "rds.h"
 
 
@@ -210,6 +211,9 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                .vdelay         = 0x20,
                .vbipack        = 255,
                .sram           = 0,
+               /* ITU-R frame line number of the first VBI line
+                  we can capture, of the first and second field. */
+               .vbistart       = { 7,320 },
        },{
                .v4l2_id        = V4L2_STD_NTSC_M,
                .name           = "NTSC",
@@ -226,6 +230,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                .vdelay         = 0x1a,
                .vbipack        = 144,
                .sram           = 1,
+               .vbistart       = { 10, 273 },
        },{
                .v4l2_id        = V4L2_STD_SECAM,
                .name           = "SECAM",
@@ -242,6 +247,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                .vdelay         = 0x20,
                .vbipack        = 255,
                .sram           = 0, /* like PAL, correct? */
+               .vbistart       = { 7, 320 },
        },{
                .v4l2_id        = V4L2_STD_PAL_Nc,
                .name           = "PAL-Nc",
@@ -258,6 +264,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                .vdelay         = 0x1a,
                .vbipack        = 144,
                .sram           = -1,
+               .vbistart       = { 7, 320 },
        },{
                .v4l2_id        = V4L2_STD_PAL_M,
                .name           = "PAL-M",
@@ -274,6 +281,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                .vdelay         = 0x1a,
                .vbipack        = 144,
                .sram           = -1,
+               .vbistart       = { 10, 273 },
        },{
                .v4l2_id        = V4L2_STD_PAL_N,
                .name           = "PAL-N",
@@ -290,6 +298,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                .vdelay         = 0x20,
                .vbipack        = 144,
                .sram           = -1,
+               .vbistart       = { 7, 320},
        },{
                .v4l2_id        = V4L2_STD_NTSC_M_JP,
                .name           = "NTSC-JP",
@@ -306,6 +315,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                .vdelay         = 0x16,
                .vbipack        = 144,
                .sram           = -1,
+               .vbistart       = {10, 273},
        },{
                /* that one hopefully works with the strange timing
                 * which video recorders produce when playing a NTSC
@@ -326,6 +336,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                .vbipack        = 255,
                .vtotal         = 524,
                .sram           = -1,
+               .vbistart       = { 10, 273 },
        }
 };
 static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
@@ -727,71 +738,71 @@ void free_btres(struct bttv *btv, struct bttv_fh *fh, int bits)
 
 static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout)
 {
-        unsigned char fl, fh, fi;
+       unsigned char fl, fh, fi;
 
-        /* prevent overflows */
-        fin/=4;
-        fout/=4;
+       /* prevent overflows */
+       fin/=4;
+       fout/=4;
 
-        fout*=12;
-        fi=fout/fin;
+       fout*=12;
+       fi=fout/fin;
 
-        fout=(fout%fin)*256;
-        fh=fout/fin;
+       fout=(fout%fin)*256;
+       fh=fout/fin;
 
-        fout=(fout%fin)*256;
-        fl=fout/fin;
+       fout=(fout%fin)*256;
+       fl=fout/fin;
 
-        btwrite(fl, BT848_PLL_F_LO);
-        btwrite(fh, BT848_PLL_F_HI);
-        btwrite(fi|BT848_PLL_X, BT848_PLL_XCI);
+       btwrite(fl, BT848_PLL_F_LO);
+       btwrite(fh, BT848_PLL_F_HI);
+       btwrite(fi|BT848_PLL_X, BT848_PLL_XCI);
 }
 
 static void set_pll(struct bttv *btv)
 {
-        int i;
+       int i;
 
-        if (!btv->pll.pll_crystal)
-                return;
+       if (!btv->pll.pll_crystal)
+               return;
 
        if (btv->pll.pll_ofreq == btv->pll.pll_current) {
                dprintk("bttv%d: PLL: no change required\n",btv->c.nr);
-                return;
-        }
+               return;
+       }
 
-        if (btv->pll.pll_ifreq == btv->pll.pll_ofreq) {
-                /* no PLL needed */
-                if (btv->pll.pll_current == 0)
-                        return;
+       if (btv->pll.pll_ifreq == btv->pll.pll_ofreq) {
+               /* no PLL needed */
+               if (btv->pll.pll_current == 0)
+                       return;
                bttv_printk(KERN_INFO "bttv%d: PLL can sleep, using XTAL (%d).\n",
-                           btv->c.nr,btv->pll.pll_ifreq);
-                btwrite(0x00,BT848_TGCTRL);
-                btwrite(0x00,BT848_PLL_XCI);
-                btv->pll.pll_current = 0;
-                return;
-        }
+                       btv->c.nr,btv->pll.pll_ifreq);
+               btwrite(0x00,BT848_TGCTRL);
+               btwrite(0x00,BT848_PLL_XCI);
+               btv->pll.pll_current = 0;
+               return;
+       }
 
        bttv_printk(KERN_INFO "bttv%d: PLL: %d => %d ",btv->c.nr,
-                   btv->pll.pll_ifreq, btv->pll.pll_ofreq);
+               btv->pll.pll_ifreq, btv->pll.pll_ofreq);
        set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq);
 
-        for (i=0; i<10; i++) {
+       for (i=0; i<10; i++) {
                /*  Let other people run while the PLL stabilizes */
                bttv_printk(".");
                msleep(10);
 
-                if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) {
+               if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) {
                        btwrite(0,BT848_DSTATUS);
-                } else {
-                        btwrite(0x08,BT848_TGCTRL);
-                        btv->pll.pll_current = btv->pll.pll_ofreq;
+               } else {
+                       btwrite(0x08,BT848_TGCTRL);
+                       btv->pll.pll_current = btv->pll.pll_ofreq;
                        bttv_printk(" ok\n");
-                        return;
-                }
-        }
-        btv->pll.pll_current = -1;
+                       return;
+               }
+       }
+       btv->pll.pll_current = -1;
        bttv_printk("failed\n");
-        return;
+       return;
 }
 
 /* used to switch between the bt848's analog/digital video capture modes */
@@ -1510,14 +1521,6 @@ static struct videobuf_queue_ops bttv_video_qops = {
        .buf_release  = buffer_release,
 };
 
-static const char *v4l1_ioctls[] = {
-       "?", "CGAP", "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 int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
 {
        switch (cmd) {
@@ -1720,7 +1723,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
                memset(i,0,sizeof(*i));
                i->index    = n;
                i->type     = V4L2_INPUT_TYPE_CAMERA;
-               i->audioset = 1;
+               i->audioset = 0;
                if (i->index == bttv_tvcards[btv->c.type].tuner) {
                        sprintf(i->name, "Television");
                        i->type  = V4L2_INPUT_TYPE_TUNER;
@@ -1771,11 +1774,19 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
                memset(t,0,sizeof(*t));
                strcpy(t->name, "Television");
                t->type       = V4L2_TUNER_ANALOG_TV;
-               t->rangehigh  = 0xffffffffUL;
                t->capability = V4L2_TUNER_CAP_NORM;
                t->rxsubchans = V4L2_TUNER_SUB_MONO;
                if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
                        t->signal = 0xffff;
+               {
+                       struct video_tuner tuner;
+
+                       memset(&tuner, 0, sizeof (tuner));
+                       tuner.rangehigh = 0xffffffffUL;
+                       bttv_call_i2c_clients(btv, VIDIOCGTUNER, &tuner);
+                       t->rangelow = tuner.rangelow;
+                       t->rangehigh = tuner.rangehigh;
+               }
                {
                        /* Hmmm ... */
                        struct video_audio va;
@@ -1853,7 +1864,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
        }
        case VIDIOC_LOG_STATUS:
        {
-               bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, 0);
+               bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, NULL);
                return 0;
        }
 
@@ -1956,7 +1967,7 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv,
        }
 
        down(&fh->cap.lock);
-       kfree(fh->ov.clips);
+               kfree(fh->ov.clips);
        fh->ov.clips    = clips;
        fh->ov.nclips   = n;
 
@@ -2029,19 +2040,33 @@ static int bttv_switch_type(struct bttv_fh *fh, enum v4l2_buf_type type)
        return 0;
 }
 
+static void
+pix_format_set_size     (struct v4l2_pix_format *       f,
+                        const struct bttv_format *     fmt,
+                        unsigned int                   width,
+                        unsigned int                   height)
+{
+       f->width = width;
+       f->height = height;
+
+       if (fmt->flags & FORMAT_FLAGS_PLANAR) {
+               f->bytesperline = width; /* Y plane */
+               f->sizeimage = (width * height * fmt->depth) >> 3;
+       } else {
+               f->bytesperline = (width * fmt->depth) >> 3;
+               f->sizeimage = height * f->bytesperline;
+       }
+}
+
 static int bttv_g_fmt(struct bttv_fh *fh, struct v4l2_format *f)
 {
        switch (f->type) {
        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
                memset(&f->fmt.pix,0,sizeof(struct v4l2_pix_format));
-               f->fmt.pix.width        = fh->width;
-               f->fmt.pix.height       = fh->height;
+               pix_format_set_size (&f->fmt.pix, fh->fmt,
+                                    fh->width, fh->height);
                f->fmt.pix.field        = fh->cap.field;
                f->fmt.pix.pixelformat  = fh->fmt->fourcc;
-               f->fmt.pix.bytesperline =
-                       (f->fmt.pix.width * fh->fmt->depth) >> 3;
-               f->fmt.pix.sizeimage =
-                       f->fmt.pix.height * f->fmt.pix.bytesperline;
                return 0;
        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
                memset(&f->fmt.win,0,sizeof(struct v4l2_window));
@@ -2106,11 +2131,9 @@ static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv,
                        f->fmt.pix.width = maxw;
                if (f->fmt.pix.height > maxh)
                        f->fmt.pix.height = maxh;
-               f->fmt.pix.width &= ~0x03;
-               f->fmt.pix.bytesperline =
-                       (f->fmt.pix.width * fmt->depth) >> 3;
-               f->fmt.pix.sizeimage =
-                       f->fmt.pix.height * f->fmt.pix.bytesperline;
+               pix_format_set_size (&f->fmt.pix, fmt,
+                                    f->fmt.pix.width & ~3,
+                                    f->fmt.pix.height);
 
                return 0;
        }
@@ -2186,22 +2209,9 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
        unsigned long flags;
        int retval = 0;
 
-       if (bttv_debug > 1) {
-               switch (_IOC_TYPE(cmd)) {
-               case 'v':
-                       printk("bttv%d: ioctl 0x%x (v4l1, VIDIOC%s)\n",
-                              btv->c.nr, cmd, (_IOC_NR(cmd) < V4L1_IOCTLS) ?
-                              v4l1_ioctls[_IOC_NR(cmd)] : "???");
-                       break;
-               case 'V':
-                       printk("bttv%d: ioctl 0x%x (v4l2, %s)\n",
-                              btv->c.nr, cmd,  v4l2_ioctl_names[_IOC_NR(cmd)]);
-                       break;
-               default:
-                       printk("bttv%d: ioctl 0x%x (???)\n",
-                              btv->c.nr, cmd);
-               }
-       }
+       if (bttv_debug > 1)
+               v4l_print_ioctl(btv->c.name, cmd);
+
        if (btv->errors)
                bttv_reinit_bt848(btv);
 
@@ -2278,6 +2288,15 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
                        retval = -EINVAL;
                        goto fh_unlock_and_return;
                }
+               if (fmt->flags & FORMAT_FLAGS_RAW) {
+                       /* VIDIOCMCAPTURE uses gbufsize, not RAW_BPL *
+                          RAW_LINES * 2. F1 is stored at offset 0, F2
+                          at buffer size / 2. */
+                       fh->width = RAW_BPL;
+                       fh->height = gbufsize / RAW_BPL;
+                       btv->init.width  = RAW_BPL;
+                       btv->init.height = gbufsize / RAW_BPL;
+               }
                fh->ovfmt   = fmt;
                fh->fmt     = fmt;
                btv->init.ovfmt   = fmt;
@@ -2541,10 +2560,10 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
                fmt->count[0]         = fmt2.fmt.vbi.count[0];
                fmt->start[1]         = fmt2.fmt.vbi.start[1];
                fmt->count[1]         = fmt2.fmt.vbi.count[1];
-               if (fmt2.fmt.vbi.flags & VBI_UNSYNC)
-                       fmt->flags   |= V4L2_VBI_UNSYNC;
-               if (fmt2.fmt.vbi.flags & VBI_INTERLACED)
-                       fmt->flags   |= V4L2_VBI_INTERLACED;
+               if (fmt2.fmt.vbi.flags & V4L2_VBI_UNSYNC)
+                       fmt->flags   |= VBI_UNSYNC;
+               if (fmt2.fmt.vbi.flags & V4L2_VBI_INTERLACED)
+                       fmt->flags   |= VBI_INTERLACED;
                return 0;
        }
        case VIDIOCSVBIFMT:
@@ -2589,9 +2608,11 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
 
                if (0 == v4l2)
                        return -EINVAL;
-               strcpy(cap->driver,"bttv");
-               strlcpy(cap->card,btv->video_dev->name,sizeof(cap->card));
-               sprintf(cap->bus_info,"PCI:%s",pci_name(btv->c.pci));
+               memset(cap, 0, sizeof (*cap));
+               strlcpy(cap->driver, "bttv", sizeof (cap->driver));
+               strlcpy(cap->card, btv->video_dev->name, sizeof (cap->card));
+               snprintf(cap->bus_info, sizeof (cap->bus_info),
+                        "PCI:%s", pci_name(btv->c.pci));
                cap->version = BTTV_VERSION_CODE;
                cap->capabilities =
                        V4L2_CAP_VIDEO_CAPTURE |
@@ -2727,7 +2748,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
                        fh->ov.w.height = fb->fmt.height;
                        btv->init.ov.w.width  = fb->fmt.width;
                        btv->init.ov.w.height = fb->fmt.height;
-                       kfree(fh->ov.clips);
+                               kfree(fh->ov.clips);
                        fh->ov.clips = NULL;
                        fh->ov.nclips = 0;
 
@@ -2952,6 +2973,8 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
                        fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR;
                        field = videobuf_next_field(&fh->cap);
                        if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) {
+                               kfree (fh->cap.read_buf);
+                               fh->cap.read_buf = NULL;
                                up(&fh->cap.lock);
                                return POLLERR;
                        }
@@ -3087,6 +3110,7 @@ static struct file_operations bttv_fops =
        .open     = bttv_open,
        .release  = bttv_release,
        .ioctl    = bttv_ioctl,
+       .compat_ioctl   = v4l_compat_ioctl32,
        .llseek   = no_llseek,
        .read     = bttv_read,
        .mmap     = bttv_mmap,
@@ -3667,6 +3691,10 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
        int handled = 0;
 
        btv=(struct bttv *)dev_id;
+
+       if (btv->custom_irq)
+               handled = btv->custom_irq(btv);
+
        count=0;
        while (1) {
                /* get/clear interrupt status bits */
@@ -3701,9 +3729,9 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
                if (astat&BT848_INT_VSYNC)
                        btv->field_count++;
 
-               if (astat & BT848_INT_GPINT) {
+               if ((astat & BT848_INT_GPINT) && btv->remote) {
                        wake_up(&btv->gpioq);
-                       bttv_gpio_irq(&btv->c);
+                       bttv_input_irq(btv);
                }
 
                if (astat & BT848_INT_I2CDONE) {
@@ -3909,7 +3937,6 @@ static int __devinit bttv_probe(struct pci_dev *dev,
 
        btv->i2c_rc = -1;
        btv->tuner_type  = UNSET;
-       btv->pinnacle_id = UNSET;
        btv->new_input   = UNSET;
        btv->has_radio=radio[btv->c.nr];
 
@@ -4028,11 +4055,11 @@ static int __devinit bttv_probe(struct pci_dev *dev,
        }
 
        /* add subdevices */
-       if (btv->has_remote)
-               bttv_sub_add_device(&btv->c, "remote");
        if (bttv_tvcards[btv->c.type].has_dvb)
                bttv_sub_add_device(&btv->c, "dvb");
 
+       bttv_input_init(btv);
+
        /* everything is fine */
        bttv_num++;
        return 0;
@@ -4067,6 +4094,7 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev)
        /* tell gpio modules we are leaving ... */
        btv->shutdown=1;
        wake_up(&btv->gpioq);
+       bttv_input_fini(btv);
        bttv_sub_del_devices(&btv->c);
 
        /* unregister i2c_bus + input */
@@ -4216,7 +4244,7 @@ static int bttv_init_module(void)
        bttv_check_chipset();
 
        bus_register(&bttv_sub_bus_type);
-       return pci_module_init(&bttv_pci_driver);
+       return pci_register_driver(&bttv_pci_driver);
 }
 
 static void bttv_cleanup_module(void)