Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[safe/jmp/linux-2.6] / drivers / media / video / zoran_driver.c
index b2c6e01..5394d7a 100644 (file)
@@ -44,7 +44,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/config.h>
 #include <linux/version.h>
 #include <linux/init.h>
 #include <linux/module.h>
@@ -53,7 +52,6 @@
 #include <linux/pci.h>
 #include <linux/vmalloc.h>
 #include <linux/wait.h>
-#include <linux/byteorder/generic.h>
 
 #include <linux/interrupt.h>
 #include <linux/i2c.h>
@@ -61,7 +59,6 @@
 
 #include <linux/spinlock.h>
 #define     MAP_NR(x)       virt_to_page(x)
-#define     ZORAN_HARDWARE  VID_HARDWARE_ZR36067
 #define     ZORAN_VID_TYPE  ( \
                                VID_TYPE_CAPTURE | \
                                VID_TYPE_OVERLAY | \
                             )
 
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include "videocodec.h"
 
+#include <asm/byteorder.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/proc_fs.h>
@@ -86,7 +85,6 @@
 #include "zoran_device.h"
 #include "zoran_card.h"
 
-#ifdef HAVE_V4L2
        /* we declare some card type definitions here, they mean
         * the same as the v4l1 ZORAN_VID_TYPE above, except it's v4l2 */
 #define ZORAN_V4L2_VID_FLAGS ( \
                                V4L2_CAP_VIDEO_CAPTURE |\
                                V4L2_CAP_VIDEO_OUTPUT |\
                                V4L2_CAP_VIDEO_OVERLAY \
-                              )
-#endif
+                             )
 
 #include <asm/byteorder.h>
 
-const struct zoran_format zoran_formats[] = {
-       {
-               .name = "15-bit RGB",
-               .palette = VIDEO_PALETTE_RGB555,
-#ifdef HAVE_V4L2
-#ifdef __LITTLE_ENDIAN
-               .fourcc = V4L2_PIX_FMT_RGB555,
+#if defined(CONFIG_VIDEO_V4L1_COMPAT)
+#define ZFMT(pal, fcc, cs) \
+       .palette = (pal), .fourcc = (fcc), .colorspace = (cs)
 #else
-               .fourcc = V4L2_PIX_FMT_RGB555X,
-#endif
-               .colorspace = V4L2_COLORSPACE_SRGB,
+#define ZFMT(pal, fcc, cs) \
+       .fourcc = (fcc), .colorspace = (cs)
 #endif
+
+const struct zoran_format zoran_formats[] = {
+       {
+               .name = "15-bit RGB LE",
+               ZFMT(VIDEO_PALETTE_RGB555,
+                    V4L2_PIX_FMT_RGB555, V4L2_COLORSPACE_SRGB),
                .depth = 15,
                .flags = ZORAN_FORMAT_CAPTURE |
                         ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_RGB555|ZR36057_VFESPFR_ErrDif|
+                          ZR36057_VFESPFR_LittleEndian,
        }, {
-               .name = "16-bit RGB",
-               .palette = VIDEO_PALETTE_RGB565,
-#ifdef HAVE_V4L2
-#ifdef __LITTLE_ENDIAN
-               .fourcc = V4L2_PIX_FMT_RGB565,
-#else
-               .fourcc = V4L2_PIX_FMT_RGB565X,
-#endif
-               .colorspace = V4L2_COLORSPACE_SRGB,
-#endif
+               .name = "15-bit RGB BE",
+               ZFMT(-1,
+                    V4L2_PIX_FMT_RGB555X, V4L2_COLORSPACE_SRGB),
+               .depth = 15,
+               .flags = ZORAN_FORMAT_CAPTURE |
+                        ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_RGB555|ZR36057_VFESPFR_ErrDif,
+       }, {
+               .name = "16-bit RGB LE",
+               ZFMT(VIDEO_PALETTE_RGB565,
+                    V4L2_PIX_FMT_RGB565, V4L2_COLORSPACE_SRGB),
                .depth = 16,
                .flags = ZORAN_FORMAT_CAPTURE |
                         ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_RGB565|ZR36057_VFESPFR_ErrDif|
+                          ZR36057_VFESPFR_LittleEndian,
+       }, {
+               .name = "16-bit RGB BE",
+               ZFMT(-1,
+                    V4L2_PIX_FMT_RGB565, V4L2_COLORSPACE_SRGB),
+               .depth = 16,
+               .flags = ZORAN_FORMAT_CAPTURE |
+                        ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_RGB565|ZR36057_VFESPFR_ErrDif,
        }, {
                .name = "24-bit RGB",
-               .palette = VIDEO_PALETTE_RGB24,
-#ifdef HAVE_V4L2
-#ifdef __LITTLE_ENDIAN
-               .fourcc = V4L2_PIX_FMT_BGR24,
-#else
-               .fourcc = V4L2_PIX_FMT_RGB24,
-#endif
-               .colorspace = V4L2_COLORSPACE_SRGB,
-#endif
+               ZFMT(VIDEO_PALETTE_RGB24,
+                    V4L2_PIX_FMT_BGR24, V4L2_COLORSPACE_SRGB),
                .depth = 24,
                .flags = ZORAN_FORMAT_CAPTURE |
                         ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_RGB888|ZR36057_VFESPFR_Pack24,
        }, {
-               .name = "32-bit RGB",
-               .palette = VIDEO_PALETTE_RGB32,
-#ifdef HAVE_V4L2
-#ifdef __LITTLE_ENDIAN
-               .fourcc = V4L2_PIX_FMT_BGR32,
-#else
-               .fourcc = V4L2_PIX_FMT_RGB32,
-#endif
-               .colorspace = V4L2_COLORSPACE_SRGB,
-#endif
+               .name = "32-bit RGB LE",
+               ZFMT(VIDEO_PALETTE_RGB32,
+                    V4L2_PIX_FMT_BGR32, V4L2_COLORSPACE_SRGB),
+               .depth = 32,
+               .flags = ZORAN_FORMAT_CAPTURE |
+                        ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_RGB888|ZR36057_VFESPFR_LittleEndian,
+       }, {
+               .name = "32-bit RGB BE",
+               ZFMT(-1,
+                    V4L2_PIX_FMT_RGB32, V4L2_COLORSPACE_SRGB),
                .depth = 32,
                .flags = ZORAN_FORMAT_CAPTURE |
                         ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_RGB888,
        }, {
                .name = "4:2:2, packed, YUYV",
-               .palette = VIDEO_PALETTE_YUV422,
-#ifdef HAVE_V4L2
-               .fourcc = V4L2_PIX_FMT_YUYV,
-               .colorspace = V4L2_COLORSPACE_SMPTE170M,
-#endif
+               ZFMT(VIDEO_PALETTE_YUV422,
+                    V4L2_PIX_FMT_YUYV, V4L2_COLORSPACE_SMPTE170M),
+               .depth = 16,
+               .flags = ZORAN_FORMAT_CAPTURE |
+                        ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_YUV422,
+       }, {
+               .name = "4:2:2, packed, UYVY",
+               ZFMT(VIDEO_PALETTE_UYVY,
+                    V4L2_PIX_FMT_UYVY, V4L2_COLORSPACE_SMPTE170M),
                .depth = 16,
                .flags = ZORAN_FORMAT_CAPTURE |
-                        ZORAN_FORMAT_OVERLAY,
+                        ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_YUV422|ZR36057_VFESPFR_LittleEndian,
        }, {
                .name = "Hardware-encoded Motion-JPEG",
-               .palette = -1,
-#ifdef HAVE_V4L2
-               .fourcc = V4L2_PIX_FMT_MJPEG,
-               .colorspace = V4L2_COLORSPACE_SMPTE170M,
-#endif
+               ZFMT(-1,
+                    V4L2_PIX_FMT_MJPEG, V4L2_COLORSPACE_SMPTE170M),
                .depth = 0,
                .flags = ZORAN_FORMAT_CAPTURE |
                         ZORAN_FORMAT_PLAYBACK |
                         ZORAN_FORMAT_COMPRESSED,
        }
 };
-static const int zoran_num_formats =
-    (sizeof(zoran_formats) / sizeof(struct zoran_format));
+#define NUM_FORMATS ARRAY_SIZE(zoran_formats)
 
 // RJ: Test only - want to test BUZ_USE_HIMEM even when CONFIG_BIGPHYS_AREA is defined
-#if !defined(CONFIG_BIGPHYS_AREA)
-//#undef CONFIG_BIGPHYS_AREA
-#define BUZ_USE_HIMEM
-#endif
 
-#if defined(CONFIG_BIGPHYS_AREA)
-#   include <linux/bigphysarea.h>
-#endif
-
-extern int *zr_debug;
-
-#define dprintk(num, format, args...) \
-       do { \
-               if (*zr_debug >= num) \
-                       printk(format, ##args); \
-       } while (0)
 
 extern int v4l_nbufs;
 extern int v4l_bufsize;
@@ -206,11 +200,10 @@ extern int jpg_nbufs;
 extern int jpg_bufsize;
 extern int pass_through;
 
-static int lock_norm = 0;      /* 1=Don't change TV standard (norm) */
-module_param(lock_norm, int, 0);
-MODULE_PARM_DESC(lock_norm, "Users can't change norm");
+static int lock_norm;  /* 0 = default 1 = Don't change TV standard (norm) */
+module_param(lock_norm, int, 0644);
+MODULE_PARM_DESC(lock_norm, "Prevent norm changes (1 = ignore, >1 = fail)");
 
-#ifdef HAVE_V4L2
        /* small helper function for calculating buffersizes for v4l2
         * we calculate the nearest higher power-of-two, which
         * will be the recommended buffersize */
@@ -233,7 +226,6 @@ zoran_v4l2_calc_bufsize (struct zoran_jpg_settings *settings)
                return 8192;
        return result;
 }
-#endif
 
 /* forward references */
 static void v4l_fbuffer_free(struct file *file);
@@ -250,7 +242,6 @@ static void jpg_fbuffer_free(struct file *file);
  *   Linux with the necessary memory left over).
  */
 
-#if defined(BUZ_USE_HIMEM) && !defined(CONFIG_BIGPHYS_AREA)
 static unsigned long
 get_high_mem (unsigned long size)
 {
@@ -314,7 +305,6 @@ get_high_mem (unsigned long size)
 
        return hi_mem_ph;
 }
-#endif
 
 static int
 v4l_fbuffer_alloc (struct file *file)
@@ -323,9 +313,7 @@ v4l_fbuffer_alloc (struct file *file)
        struct zoran *zr = fh->zr;
        int i, off;
        unsigned char *mem;
-#if defined(BUZ_USE_HIMEM) && !defined(CONFIG_BIGPHYS_AREA)
        unsigned long pmem = 0;
-#endif
 
        /* we might have old buffers lying around... */
        if (fh->v4l_buffers.ready_to_be_freed) {
@@ -343,11 +331,8 @@ v4l_fbuffer_alloc (struct file *file)
                if (fh->v4l_buffers.buffer_size <= MAX_KMALLOC_MEM) {
                        /* Use kmalloc */
 
-                       mem =
-                           (unsigned char *) kmalloc(fh->v4l_buffers.
-                                                     buffer_size,
-                                                     GFP_KERNEL);
-                       if (mem == 0) {
+                       mem = kmalloc(fh->v4l_buffers.buffer_size, GFP_KERNEL);
+                       if (!mem) {
                                dprintk(1,
                                        KERN_ERR
                                        "%s: v4l_fbuffer_alloc() - kmalloc for V4L buf %d failed\n",
@@ -369,39 +354,6 @@ v4l_fbuffer_alloc (struct file *file)
                                ZR_DEVNAME(zr), i, (unsigned long) mem,
                                virt_to_bus(mem));
                } else {
-#if defined(CONFIG_BIGPHYS_AREA)
-                       /* Use bigphysarea_alloc_pages */
-
-                       int n =
-                           (fh->v4l_buffers.buffer_size + PAGE_SIZE -
-                            1) / PAGE_SIZE;
-
-                       mem =
-                           (unsigned char *) bigphysarea_alloc_pages(n, 0,
-                                                                     GFP_KERNEL);
-                       if (mem == 0) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: v4l_fbuffer_alloc() - bigphysarea_alloc_pages for V4L buf %d failed\n",
-                                       ZR_DEVNAME(zr), i);
-                               v4l_fbuffer_free(file);
-                               return -ENOBUFS;
-                       }
-                       fh->v4l_buffers.buffer[i].fbuffer = mem;
-                       fh->v4l_buffers.buffer[i].fbuffer_phys =
-                           virt_to_phys(mem);
-                       fh->v4l_buffers.buffer[i].fbuffer_bus =
-                           virt_to_bus(mem);
-                       dprintk(4,
-                               KERN_INFO
-                               "%s: Bigphysarea frame %d mem 0x%x (bus: 0x%x)\n",
-                               ZR_DEVNAME(zr), i, (unsigned) mem,
-                               (unsigned) virt_to_bus(mem));
-
-                       /* Zero out the allocated memory */
-                       memset(fh->v4l_buffers.buffer[i].fbuffer, 0,
-                              fh->v4l_buffers.buffer_size);
-#elif defined(BUZ_USE_HIMEM)
 
                        /* Use high memory which has been left at boot time */
 
@@ -441,20 +393,6 @@ v4l_fbuffer_alloc (struct file *file)
                                fh->v4l_buffers.buffer[i].fbuffer_bus =
                                    pmem + i * fh->v4l_buffers.buffer_size;
                        }
-#else
-                       /* No bigphysarea present, usage of high memory disabled,
-                        * but user wants buffers of more than MAX_KMALLOC_MEM */
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: v4l_fbuffer_alloc() - no bigphysarea_patch present, usage of high memory disabled,\n",
-                               ZR_DEVNAME(zr));
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: v4l_fbuffer_alloc() - sorry, could not allocate %d V4L buffers of size %d KB.\n",
-                               ZR_DEVNAME(zr), fh->v4l_buffers.num_buffers,
-                               fh->v4l_buffers.buffer_size >> 10);
-                       return -ENOBUFS;
-#endif
                }
        }
 
@@ -485,11 +423,6 @@ v4l_fbuffer_free (struct file *file)
                                ClearPageReserved(MAP_NR(mem + off));
                        kfree((void *) fh->v4l_buffers.buffer[i].fbuffer);
                }
-#if defined(CONFIG_BIGPHYS_AREA)
-               else
-                       bigphysarea_free_pages((void *) fh->v4l_buffers.
-                                              buffer[i].fbuffer);
-#endif
                fh->v4l_buffers.buffer[i].fbuffer = NULL;
        }
 
@@ -562,8 +495,7 @@ jpg_fbuffer_alloc (struct file *file)
                        jpg_fbuffer_free(file);
                        return -ENOBUFS;
                }
-               memset((void *) mem, 0, PAGE_SIZE);
-               fh->jpg_buffers.buffer[i].frag_tab = (u32 *) mem;
+               fh->jpg_buffers.buffer[i].frag_tab = (__le32 *) mem;
                fh->jpg_buffers.buffer[i].frag_tab_bus =
                    virt_to_bus((void *) mem);
 
@@ -670,7 +602,7 @@ jpg_fbuffer_free (struct file *file)
                                                                       j]))));
                                free_page((unsigned long)
                                          bus_to_virt
-                                                 (le32_to_cpu
+                                                 (le32_to_cpu
                                                   (fh->jpg_buffers.
                                                      buffer[i].
                                                      frag_tab[2 * j])));
@@ -832,13 +764,13 @@ v4l_grab (struct file       *file,
        struct zoran *zr = fh->zr;
        int res = 0, i;
 
-       for (i = 0; i < zoran_num_formats; i++) {
+       for (i = 0; i < NUM_FORMATS; i++) {
                if (zoran_formats[i].palette == mp->format &&
                    zoran_formats[i].flags & ZORAN_FORMAT_CAPTURE &&
                    !(zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED))
                        break;
        }
-       if (i == zoran_num_formats || zoran_formats[i].depth == 0) {
+       if (i == NUM_FORMATS || zoran_formats[i].depth == 0) {
                dprintk(1,
                        KERN_ERR
                        "%s: v4l_grab() - wrong bytes-per-pixel format\n",
@@ -1155,12 +1087,10 @@ jpg_sync (struct file       *file,
                frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME];
 
        /* buffer should now be in BUZ_STATE_DONE */
-       if (*zr_debug > 0)
-               if (zr->jpg_buffers.buffer[frame].state != BUZ_STATE_DONE)
-                       dprintk(2,
-                               KERN_ERR
-                               "%s: jpg_sync() - internal state error\n",
-                               ZR_DEVNAME(zr));
+       if (zr->jpg_buffers.buffer[frame].state != BUZ_STATE_DONE)
+               dprintk(2,
+                       KERN_ERR "%s: jpg_sync() - internal state error\n",
+                       ZR_DEVNAME(zr));
 
        *bs = zr->jpg_buffers.buffer[frame].bs;
        bs->frame = frame;
@@ -1237,10 +1167,14 @@ zoran_close_end_session (struct file *file)
 
        /* v4l capture */
        if (fh->v4l_buffers.active != ZORAN_FREE) {
+               unsigned long flags;
+
+               spin_lock_irqsave(&zr->spinlock, flags);
                zr36057_set_memgrab(zr, 0);
                zr->v4l_buffers.allocated = 0;
                zr->v4l_buffers.active = fh->v4l_buffers.active =
                    ZORAN_FREE;
+               spin_unlock_irqrestore(&zr->spinlock, flags);
        }
 
        /* v4l buffers */
@@ -1343,7 +1277,7 @@ zoran_open (struct inode *inode,
        }
 
        dprintk(1, KERN_INFO "%s: zoran_open(%s, pid=[%d]), users(-)=%d\n",
-               ZR_DEVNAME(zr), current->comm, current->pid, zr->user);
+               ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user);
 
        /* now, create the open()-specific file_ops struct */
        fh = kzalloc(sizeof(struct zoran_fh), GFP_KERNEL);
@@ -1416,7 +1350,7 @@ zoran_close (struct inode *inode,
        struct zoran *zr = fh->zr;
 
        dprintk(1, KERN_INFO "%s: zoran_close(%s, pid=[%d]), users(+)=%d\n",
-               ZR_DEVNAME(zr), current->comm, current->pid, zr->user);
+               ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user);
 
        /* kernel locks (fs/device.c), so don't do that ourselves
         * (prevents deadlocks) */
@@ -1434,7 +1368,7 @@ zoran_close (struct inode *inode,
                /* disable interrupts */
                btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR);
 
-               if (*zr_debug > 1)
+               if (zr36067_debug > 1)
                        print_interrupts(zr);
 
                /* Overlay off */
@@ -1512,6 +1446,13 @@ setup_fbuffer (struct file               *file,
        if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
                return -EPERM;
 
+       /* Don't allow frame buffer overlay if PCI or AGP is buggy, or on
+          ALi Magik (that needs very low latency while the card needs a
+          higher value always) */
+
+       if (pci_pci_problems & (PCIPCI_FAIL | PCIAGP_FAIL | PCIPCI_ALIMAGIK))
+               return -ENXIO;
+
        /* we need a bytesperline value, even if not given */
        if (!bytesperline)
                bytesperline = width * ((fmt->depth + 7) & ~7) / 8;
@@ -1761,7 +1702,6 @@ setup_overlay (struct file *file,
        return wait_grab_pending(zr);
 }
 
-#ifdef HAVE_V4L2
        /* get the status of a buffer in the clients buffer queue */
 static int
 zoran_v4l2_buffer_status (struct file        *file,
@@ -1867,11 +1807,10 @@ zoran_v4l2_buffer_status (struct file        *file,
 
        return 0;
 }
-#endif
 
 static int
 zoran_set_norm (struct zoran *zr,
-               int           norm) /* VIDEO_MODE_* */
+               int           norm) /* VIDEO_MODE_* */
 {
        int norm_encoder, on;
 
@@ -2006,9 +1945,9 @@ zoran_set_input (struct zoran *zr,
 
 static int
 zoran_do_ioctl (struct inode *inode,
-               struct file  *file,
-               unsigned int  cmd,
-               void         *arg)
+               struct file  *file,
+               unsigned int  cmd,
+               void         *arg)
 {
        struct zoran_fh *fh = file->private_data;
        struct zoran *zr = fh->zr;
@@ -2028,7 +1967,7 @@ zoran_do_ioctl (struct inode *inode,
         * but moving the free code outside the munmap() handler fixes
         * all this... If someone knows why, please explain me (Ronald)
         */
-       if (!!mutex_trylock(&zr->resource_lock)) {
+       if (mutex_trylock(&zr->resource_lock)) {
                /* we obtained it! Let's try to free some things */
                if (fh->jpg_buffers.ready_to_be_freed)
                        jpg_fbuffer_free(file);
@@ -2047,7 +1986,7 @@ zoran_do_ioctl (struct inode *inode,
                dprintk(3, KERN_DEBUG "%s: VIDIOCGCAP\n", ZR_DEVNAME(zr));
 
                memset(vcap, 0, sizeof(struct video_capability));
-               strncpy(vcap->name, ZR_DEVNAME(zr), sizeof(vcap->name));
+               strncpy(vcap->name, ZR_DEVNAME(zr), sizeof(vcap->name)-1);
                vcap->type = ZORAN_VID_TYPE;
 
                vcap->channels = zr->card.inputs;
@@ -2095,7 +2034,7 @@ zoran_do_ioctl (struct inode *inode,
                break;
 
                /* RJ: the documentation at http://roadrunner.swansea.linux.org.uk/v4lapi.shtml says:
-                * 
+                *
                 * * "The VIDIOCSCHAN ioctl takes an integer argument and switches the capture to this input."
                 * *                                 ^^^^^^^
                 * * The famos BTTV driver has it implemented with a struct video_channel argument
@@ -2164,7 +2103,7 @@ zoran_do_ioctl (struct inode *inode,
                        vpict->colour, vpict->contrast, vpict->depth,
                        vpict->palette);
 
-               for (i = 0; i < zoran_num_formats; i++) {
+               for (i = 0; i < NUM_FORMATS; i++) {
                        const struct zoran_format *fmt = &zoran_formats[i];
 
                        if (fmt->palette != -1 &&
@@ -2173,7 +2112,7 @@ zoran_do_ioctl (struct inode *inode,
                            fmt->depth == vpict->depth)
                                break;
                }
-               if (i == zoran_num_formats) {
+               if (i == NUM_FORMATS) {
                        dprintk(1,
                                KERN_ERR
                                "%s: VIDIOCSPICT - Invalid palette %d\n",
@@ -2277,10 +2216,10 @@ zoran_do_ioctl (struct inode *inode,
                        ZR_DEVNAME(zr), vbuf->base, vbuf->width,
                        vbuf->height, vbuf->depth, vbuf->bytesperline);
 
-               for (i = 0; i < zoran_num_formats; i++)
+               for (i = 0; i < NUM_FORMATS; i++)
                        if (zoran_formats[i].depth == vbuf->depth)
                                break;
-               if (i == zoran_num_formats) {
+               if (i == NUM_FORMATS) {
                        dprintk(1,
                                KERN_ERR
                                "%s: VIDIOCSFBUF - invalid fbuf depth %d\n",
@@ -2676,8 +2615,6 @@ zoran_do_ioctl (struct inode *inode,
        }
                break;
 
-#ifdef HAVE_V4L2
-
                /* The new video4linux2 capture interface - much nicer than video4linux1, since
                 * it allows for integrating the JPEG capturing calls inside standard v4l2
                 */
@@ -2689,8 +2626,8 @@ zoran_do_ioctl (struct inode *inode,
                dprintk(3, KERN_DEBUG "%s: VIDIOC_QUERYCAP\n", ZR_DEVNAME(zr));
 
                memset(cap, 0, sizeof(*cap));
-               strncpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card));
-               strncpy(cap->driver, "zoran", sizeof(cap->driver));
+               strncpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card)-1);
+               strncpy(cap->driver, "zoran", sizeof(cap->driver)-1);
                snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
                         pci_name(zr->pci_dev));
                cap->version =
@@ -2729,20 +2666,20 @@ zoran_do_ioctl (struct inode *inode,
                        return -EINVAL;
                }
 
-               for (i = 0; i < zoran_num_formats; i++) {
+               for (i = 0; i < NUM_FORMATS; i++) {
                        if (zoran_formats[i].flags & flag)
                                num++;
                        if (num == fmt->index)
                                break;
                }
                if (fmt->index < 0 /* late, but not too late */  ||
-                   i == zoran_num_formats)
+                   i == NUM_FORMATS)
                        return -EINVAL;
 
                memset(fmt, 0, sizeof(*fmt));
                fmt->index = index;
                fmt->type = type;
-               strncpy(fmt->description, zoran_formats[i].name, 31);
+               strncpy(fmt->description, zoran_formats[i].name, sizeof(fmt->description)-1);
                fmt->pixelformat = zoran_formats[i].fourcc;
                if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED)
                        fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
@@ -2794,7 +2731,8 @@ zoran_do_ioctl (struct inode *inode,
                                fmt->fmt.pix.height =
                                    fh->v4l_settings.height;
                                fmt->fmt.pix.sizeimage =
-                                   fh->v4l_buffers.buffer_size;
+                                   fh->v4l_settings.bytesperline *
+                                   fh->v4l_settings.height;
                                fmt->fmt.pix.pixelformat =
                                    fh->v4l_settings.format->fourcc;
                                fmt->fmt.pix.colorspace =
@@ -2998,11 +2936,11 @@ zoran_do_ioctl (struct inode *inode,
                        sfmtjpg_unlock_and_return:
                                mutex_unlock(&zr->resource_lock);
                        } else {
-                               for (i = 0; i < zoran_num_formats; i++)
+                               for (i = 0; i < NUM_FORMATS; i++)
                                        if (fmt->fmt.pix.pixelformat ==
                                            zoran_formats[i].fourcc)
                                                break;
-                               if (i == zoran_num_formats) {
+                               if (i == NUM_FORMATS) {
                                        dprintk(1,
                                                KERN_ERR
                                                "%s: VIDIOC_S_FMT - unknown/unsupported format 0x%x (%4.4s)\n",
@@ -3041,8 +2979,9 @@ zoran_do_ioctl (struct inode *inode,
 
                                /* tell the user the
                                 * results/missing stuff */
-                               fmt->fmt.pix.sizeimage = fh->v4l_buffers.buffer_size    /*zr->gbpl * zr->gheight */
-                                   ;
+                               fmt->fmt.pix.sizeimage =
+                                       fh->v4l_settings.height *
+                                       fh->v4l_settings.bytesperline;
                                if (BUZ_MAX_HEIGHT <
                                    (fh->v4l_settings.height * 2))
                                        fmt->fmt.pix.field =
@@ -3110,10 +3049,10 @@ zoran_do_ioctl (struct inode *inode,
                        fb->fmt.bytesperline, fb->fmt.pixelformat,
                        (char *) &printformat);
 
-               for (i = 0; i < zoran_num_formats; i++)
+               for (i = 0; i < NUM_FORMATS; i++)
                        if (zoran_formats[i].fourcc == fb->fmt.pixelformat)
                                break;
-               if (i == zoran_num_formats) {
+               if (i == NUM_FORMATS) {
                        dprintk(1,
                                KERN_ERR
                                "%s: VIDIOC_S_FBUF - format=0x%x (%4.4s) not allowed\n",
@@ -3242,7 +3181,7 @@ zoran_do_ioctl (struct inode *inode,
                        "%s: VIDIOC_QUERYBUF - index=%d, type=%d\n",
                        ZR_DEVNAME(zr), buf->index, buf->type);
 
-               memset(buf, 0, sizeof(buf));
+               memset(buf, 0, sizeof(*buf));
                buf->type = type;
                buf->index = index;
 
@@ -3496,8 +3435,13 @@ zoran_do_ioctl (struct inode *inode,
                                goto strmoff_unlock_and_return;
 
                        /* unload capture */
-                       if (zr->v4l_memgrab_active)
+                       if (zr->v4l_memgrab_active) {
+                               unsigned long flags;
+
+                               spin_lock_irqsave(&zr->spinlock, flags);
                                zr36057_set_memgrab(zr, 0);
+                               spin_unlock_irqrestore(&zr->spinlock, flags);
+                       }
 
                        for (i = 0; i < fh->v4l_buffers.num_buffers; i++)
                                zr->v4l_buffers.buffer[i].state =
@@ -3566,16 +3510,16 @@ zoran_do_ioctl (struct inode *inode,
 
                switch (ctrl->id) {
                case V4L2_CID_BRIGHTNESS:
-                       strncpy(ctrl->name, "Brightness", 31);
+                       strncpy(ctrl->name, "Brightness", sizeof(ctrl->name)-1);
                        break;
                case V4L2_CID_CONTRAST:
-                       strncpy(ctrl->name, "Contrast", 31);
+                       strncpy(ctrl->name, "Contrast", sizeof(ctrl->name)-1);
                        break;
                case V4L2_CID_SATURATION:
-                       strncpy(ctrl->name, "Saturation", 31);
+                       strncpy(ctrl->name, "Saturation", sizeof(ctrl->name)-1);
                        break;
                case V4L2_CID_HUE:
-                       strncpy(ctrl->name, "Hue", 31);
+                       strncpy(ctrl->name, "Hue", sizeof(ctrl->name)-1);
                        break;
                }
 
@@ -3693,7 +3637,7 @@ zoran_do_ioctl (struct inode *inode,
                                        &caps);
                        if (caps.flags & VIDEO_DECODER_AUTO) {
                                std->id = V4L2_STD_ALL;
-                               strncpy(std->name, "Autodetect", 31);
+                               strncpy(std->name, "Autodetect", sizeof(std->name)-1);
                                return 0;
                        } else
                                return -EINVAL;
@@ -3701,21 +3645,21 @@ zoran_do_ioctl (struct inode *inode,
                switch (std->index) {
                case 0:
                        std->id = V4L2_STD_PAL;
-                       strncpy(std->name, "PAL", 31);
+                       strncpy(std->name, "PAL", sizeof(std->name)-1);
                        std->frameperiod.numerator = 1;
                        std->frameperiod.denominator = 25;
                        std->framelines = zr->card.tvn[0]->Ht;
                        break;
                case 1:
                        std->id = V4L2_STD_NTSC;
-                       strncpy(std->name, "NTSC", 31);
+                       strncpy(std->name, "NTSC", sizeof(std->name)-1);
                        std->frameperiod.numerator = 1001;
                        std->frameperiod.denominator = 30000;
                        std->framelines = zr->card.tvn[1]->Ht;
                        break;
                case 2:
                        std->id = V4L2_STD_SECAM;
-                       strncpy(std->name, "SECAM", 31);
+                       strncpy(std->name, "SECAM", sizeof(std->name)-1);
                        std->frameperiod.numerator = 1;
                        std->frameperiod.denominator = 25;
                        std->framelines = zr->card.tvn[2]->Ht;
@@ -3761,11 +3705,11 @@ zoran_do_ioctl (struct inode *inode,
                dprintk(3, KERN_DEBUG "%s: VIDIOC_S_STD - norm=0x%llx\n",
                        ZR_DEVNAME(zr), (unsigned long long)*std);
 
-               if (*std == V4L2_STD_PAL)
+               if ((*std & V4L2_STD_PAL) && !(*std & ~V4L2_STD_PAL))
                        norm = VIDEO_MODE_PAL;
-               else if (*std == V4L2_STD_NTSC)
+               else if ((*std & V4L2_STD_NTSC) && !(*std & ~V4L2_STD_NTSC))
                        norm = VIDEO_MODE_NTSC;
-               else if (*std == V4L2_STD_SECAM)
+               else if ((*std & V4L2_STD_SECAM) && !(*std & ~V4L2_STD_SECAM))
                        norm = VIDEO_MODE_SECAM;
                else if (*std == V4L2_STD_ALL)
                        norm = VIDEO_MODE_AUTO;
@@ -3871,7 +3815,7 @@ zoran_do_ioctl (struct inode *inode,
                memset(outp, 0, sizeof(*outp));
                outp->index = 0;
                outp->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY;
-               strncpy(outp->name, "Autodetect", 31);
+               strncpy(outp->name, "Autodetect", sizeof(outp->name)-1);
 
                return 0;
        }
@@ -4206,11 +4150,11 @@ zoran_do_ioctl (struct inode *inode,
                                   V4L2_BUF_TYPE_VIDEO_CAPTURE) {
                                int i;
 
-                               for (i = 0; i < zoran_num_formats; i++)
+                               for (i = 0; i < NUM_FORMATS; i++)
                                        if (zoran_formats[i].fourcc ==
                                            fmt->fmt.pix.pixelformat)
                                                break;
-                               if (i == zoran_num_formats) {
+                               if (i == NUM_FORMATS) {
                                        res = -EINVAL;
                                        goto tryfmt_unlock_and_return;
                                }
@@ -4242,7 +4186,6 @@ zoran_do_ioctl (struct inode *inode,
                return 0;
        }
                break;
-#endif
 
        default:
                dprintk(1, KERN_DEBUG "%s: UNKNOWN ioctl cmd: 0x%x\n",
@@ -4270,8 +4213,8 @@ zoran_poll (struct file *file,
 {
        struct zoran_fh *fh = file->private_data;
        struct zoran *zr = fh->zr;
-       wait_queue_head_t *queue = NULL;
        int res = 0, frame;
+       unsigned long flags;
 
        /* we should check whether buffers are ready to be synced on
         * (w/o waits - O_NONBLOCK) here
@@ -4285,51 +4228,58 @@ zoran_poll (struct file *file,
 
        switch (fh->map_mode) {
        case ZORAN_MAP_MODE_RAW:
-               if (fh->v4l_buffers.active == ZORAN_FREE ||
-                   zr->v4l_pend_head == zr->v4l_pend_tail) {
-                       dprintk(1,
-                               "%s: zoran_poll() - no buffers queued\n",
-                               ZR_DEVNAME(zr));
-                       res = POLLNVAL;
-                       goto poll_unlock_and_return;
-               }
-               queue = &zr->v4l_capq;
-               frame = zr->v4l_pend[zr->v4l_pend_tail & V4L_MASK_FRAME];
-               poll_wait(file, queue, wait);
-               if (fh->v4l_buffers.buffer[frame].state == BUZ_STATE_DONE)
+               poll_wait(file, &zr->v4l_capq, wait);
+               frame = zr->v4l_pend[zr->v4l_sync_tail & V4L_MASK_FRAME];
+
+               spin_lock_irqsave(&zr->spinlock, flags);
+               dprintk(3,
+                       KERN_DEBUG
+                       "%s: %s() raw - active=%c, sync_tail=%lu/%c, pend_tail=%lu, pend_head=%lu\n",
+                       ZR_DEVNAME(zr), __func__,
+                       "FAL"[fh->v4l_buffers.active], zr->v4l_sync_tail,
+                       "UPMD"[zr->v4l_buffers.buffer[frame].state],
+                       zr->v4l_pend_tail, zr->v4l_pend_head);
+               /* Process is the one capturing? */
+               if (fh->v4l_buffers.active != ZORAN_FREE &&
+                   /* Buffer ready to DQBUF? */
+                   zr->v4l_buffers.buffer[frame].state == BUZ_STATE_DONE)
                        res = POLLIN | POLLRDNORM;
+               spin_unlock_irqrestore(&zr->spinlock, flags);
+
                break;
 
        case ZORAN_MAP_MODE_JPG_REC:
        case ZORAN_MAP_MODE_JPG_PLAY:
-               if (fh->jpg_buffers.active == ZORAN_FREE ||
-                   zr->jpg_que_head == zr->jpg_que_tail) {
-                       dprintk(1,
-                               "%s: zoran_poll() - no buffers queued\n",
-                               ZR_DEVNAME(zr));
-                       res = POLLNVAL;
-                       goto poll_unlock_and_return;
-               }
-               queue = &zr->jpg_capq;
+               poll_wait(file, &zr->jpg_capq, wait);
                frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME];
-               poll_wait(file, queue, wait);
-               if (fh->jpg_buffers.buffer[frame].state == BUZ_STATE_DONE) {
+
+               spin_lock_irqsave(&zr->spinlock, flags);
+               dprintk(3,
+                       KERN_DEBUG
+                       "%s: %s() jpg - active=%c, que_tail=%lu/%c, que_head=%lu, dma=%lu/%lu\n",
+                       ZR_DEVNAME(zr), __func__,
+                       "FAL"[fh->jpg_buffers.active], zr->jpg_que_tail,
+                       "UPMD"[zr->jpg_buffers.buffer[frame].state],
+                       zr->jpg_que_head, zr->jpg_dma_tail, zr->jpg_dma_head);
+               if (fh->jpg_buffers.active != ZORAN_FREE &&
+                   zr->jpg_buffers.buffer[frame].state == BUZ_STATE_DONE) {
                        if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC)
                                res = POLLIN | POLLRDNORM;
                        else
                                res = POLLOUT | POLLWRNORM;
                }
+               spin_unlock_irqrestore(&zr->spinlock, flags);
+
                break;
 
        default:
                dprintk(1,
+                       KERN_ERR
                        "%s: zoran_poll() - internal error, unknown map_mode=%d\n",
                        ZR_DEVNAME(zr), fh->map_mode);
                res = POLLNVAL;
-               goto poll_unlock_and_return;
        }
 
-poll_unlock_and_return:
        mutex_unlock(&zr->resource_lock);
 
        return res;
@@ -4425,11 +4375,15 @@ zoran_vm_close (struct vm_area_struct *vma)
                                mutex_lock(&zr->resource_lock);
 
                                if (fh->v4l_buffers.active != ZORAN_FREE) {
+                                       unsigned long flags;
+
+                                       spin_lock_irqsave(&zr->spinlock, flags);
                                        zr36057_set_memgrab(zr, 0);
                                        zr->v4l_buffers.allocated = 0;
                                        zr->v4l_buffers.active =
                                            fh->v4l_buffers.active =
                                            ZORAN_FREE;
+                                       spin_unlock_irqrestore(&zr->spinlock, flags);
                                }
                                //v4l_fbuffer_free(file);
                                fh->v4l_buffers.allocated = 0;
@@ -4552,7 +4506,7 @@ zoran_mmap (struct file           *file,
                                if (todo > fraglen)
                                        todo = fraglen;
                                pos =
-                                   le32_to_cpu((unsigned long) fh->jpg_buffers.
+                                   le32_to_cpu(fh->jpg_buffers.
                                    buffer[i].frag_tab[2 * j]);
                                /* should just be pos on i386 */
                                page = virt_to_phys(bus_to_virt(pos))
@@ -4673,12 +4627,14 @@ zoran_mmap (struct file           *file,
        return 0;
 }
 
-static struct file_operations zoran_fops = {
+static const struct file_operations zoran_fops = {
        .owner = THIS_MODULE,
        .open = zoran_open,
        .release = zoran_close,
        .ioctl = zoran_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek = no_llseek,
        .read = zoran_read,
        .write = zoran_write,
@@ -4689,10 +4645,7 @@ static struct file_operations zoran_fops = {
 struct video_device zoran_template __devinitdata = {
        .name = ZORAN_NAME,
        .type = ZORAN_VID_TYPE,
-#ifdef HAVE_V4L2
        .type2 = ZORAN_V4L2_VID_FLAGS,
-#endif
-       .hardware = ZORAN_HARDWARE,
        .fops = &zoran_fops,
        .release = &zoran_vdev_release,
        .minor = -1