V4L/DVB (10930): zoran: Unify buffer descriptors

The zoran driver had two kinds of buffer descriptors, one for jpg buffers
and one for raw buffers.  They were mostly the same with only a couple

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
diff --git a/drivers/media/video/zoran/zoran.h b/drivers/media/video/zoran/zoran.h
index 8beada9..afecf32 100644
--- a/drivers/media/video/zoran/zoran.h
+++ b/drivers/media/video/zoran/zoran.h
@@ -172,6 +172,8 @@
 #endif
 #define   V4L_MASK_FRAME   (V4L_MAX_FRAME - 1)
 
+#define MAX_FRAME (BUZ_MAX_FRAME > VIDEO_MAX_FRAME ? BUZ_MAX_FRAME : VIDEO_MAX_FRAME)
+
 #include "zr36057.h"
 
 enum card_type {
@@ -280,21 +282,21 @@
 	int count;
 };
 
-struct zoran_jpg_buffer {
+struct zoran_buffer {
 	struct zoran_mapping *map;
-	__le32 *frag_tab;		/* addresses of frag table */
-	u32 frag_tab_bus;	/* same value cached to save time in ISR */
-	enum zoran_buffer_state state;	/* non-zero if corresponding buffer is in use in grab queue */
-	struct zoran_sync bs;	/* DONE: info to return to application */
-};
-
-struct zoran_v4l_buffer {
-	struct zoran_mapping *map;
-	char *fbuffer;		/* virtual  address of frame buffer */
-	unsigned long fbuffer_phys;	/* physical address of frame buffer */
-	unsigned long fbuffer_bus;	/* bus      address of frame buffer */
-	enum zoran_buffer_state state;	/* state: unused/pending/done */
-	struct zoran_sync bs;	/* DONE: info to return to application */
+	enum zoran_buffer_state state;	/* state: unused/pending/dma/done */
+	struct zoran_sync bs;		/* DONE: info to return to application */
+	union {
+		struct {
+			__le32 *frag_tab;	/* addresses of frag table */
+			u32 frag_tab_bus;	/* same value cached to save time in ISR */
+		} jpg;
+		struct {
+			char *fbuffer;		/* virtual address of frame buffer */
+			unsigned long fbuffer_phys;/* physical address of frame buffer */
+			unsigned long fbuffer_bus;/* bus address of frame buffer */
+		} v4l;
+	};
 };
 
 enum zoran_lock_activity {
@@ -304,19 +306,13 @@
 };
 
 /* buffer collections */
-struct zoran_jpg_struct {
+struct zoran_buffer_col {
 	enum zoran_lock_activity active;	/* feature currently in use? */
-	struct zoran_jpg_buffer buffer[BUZ_MAX_FRAME];	/* buffers */
-	int num_buffers, buffer_size;
+	unsigned int num_buffers, buffer_size;
+	struct zoran_buffer buffer[MAX_FRAME];	/* buffers */
 	u8 allocated;		/* Flag if buffers are allocated  */
 	u8 need_contiguous;	/* Flag if contiguous buffers are needed */
-};
-
-struct zoran_v4l_struct {
-	enum zoran_lock_activity active;	/* feature currently in use? */
-	struct zoran_v4l_buffer buffer[VIDEO_MAX_FRAME];	/* buffers */
-	int num_buffers, buffer_size;
-	u8 allocated;		/* Flag if buffers are allocated  */
+	/* only applies to jpg buffers, raw buffers are always contiguous */
 };
 
 struct zoran;
@@ -325,17 +321,16 @@
 struct zoran_fh {
 	struct zoran *zr;
 
-	enum zoran_map_mode map_mode;	/* Flag which bufferset will map by next mmap() */
+	enum zoran_map_mode map_mode;		/* Flag which bufferset will map by next mmap() */
 
 	struct zoran_overlay_settings overlay_settings;
-	u32 *overlay_mask;	/* overlay mask */
-	enum zoran_lock_activity overlay_active;	/* feature currently in use? */
+	u32 *overlay_mask;			/* overlay mask */
+	enum zoran_lock_activity overlay_active;/* feature currently in use? */
+
+	struct zoran_buffer_col buffers;	/* buffers' info */
 
 	struct zoran_v4l_settings v4l_settings;	/* structure with a lot of things to play with */
-	struct zoran_v4l_struct v4l_buffers;	/* V4L buffers' info */
-
 	struct zoran_jpg_settings jpg_settings;	/* structure with a lot of things to play with */
-	struct zoran_jpg_struct jpg_buffers;	/* MJPEG buffers' info */
 };
 
 struct card_info {
@@ -434,7 +429,7 @@
 	unsigned long v4l_pend_tail;
 	unsigned long v4l_sync_tail;
 	int v4l_pend[V4L_MAX_FRAME];
-	struct zoran_v4l_struct v4l_buffers;	/* V4L buffers' info */
+	struct zoran_buffer_col v4l_buffers;	/* V4L buffers' info */
 
 	/* Buz MJPEG parameters */
 	enum zoran_codec_mode codec_mode;	/* status of codec */
@@ -461,7 +456,7 @@
 	int jpg_pend[BUZ_MAX_FRAME];
 
 	/* array indexed by frame number */
-	struct zoran_jpg_struct jpg_buffers;	/* MJPEG buffers' info */
+	struct zoran_buffer_col jpg_buffers;	/* MJPEG buffers' info */
 
 	/* Additional stuff for testing */
 #ifdef CONFIG_PROC_FS
diff --git a/drivers/media/video/zoran/zoran_device.c b/drivers/media/video/zoran/zoran_device.c
index 49e91b2..4dc9513 100644
--- a/drivers/media/video/zoran/zoran_device.c
+++ b/drivers/media/video/zoran/zoran_device.c
@@ -1125,7 +1125,7 @@
 			if (!(zr->stat_com[i] & cpu_to_le32(1)))
 				break;
 			zr->stat_com[i] =
-			    cpu_to_le32(zr->jpg_buffers.buffer[frame].frag_tab_bus);
+			    cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_bus);
 		} else {
 			/* fill 2 stat_com entries */
 			i = ((zr->jpg_dma_head -
@@ -1133,9 +1133,9 @@
 			if (!(zr->stat_com[i] & cpu_to_le32(1)))
 				break;
 			zr->stat_com[i] =
-			    cpu_to_le32(zr->jpg_buffers.buffer[frame].frag_tab_bus);
+			    cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_bus);
 			zr->stat_com[i + 1] =
-			    cpu_to_le32(zr->jpg_buffers.buffer[frame].frag_tab_bus);
+			    cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_bus);
 		}
 		zr->jpg_buffers.buffer[frame].state = BUZ_STATE_DMA;
 		zr->jpg_dma_head++;
@@ -1155,7 +1155,7 @@
 	u32 stat_com;
 	unsigned int seq;
 	unsigned int dif;
-	struct zoran_jpg_buffer *buffer;
+	struct zoran_buffer *buffer;
 	int frame;
 
 	/* In motion decompress we don't have a hardware frame counter,
@@ -1298,7 +1298,7 @@
 		printk(KERN_INFO "stat_com frames:");
 		for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
 			for (i = 0; i < zr->jpg_buffers.num_buffers; i++) {
-				if (le32_to_cpu(zr->stat_com[j]) == zr->jpg_buffers.buffer[i].frag_tab_bus)
+				if (le32_to_cpu(zr->stat_com[j]) == zr->jpg_buffers.buffer[i].jpg.frag_tab_bus)
 					printk(KERN_CONT "% d->%d", j, i);
 			}
 		}
@@ -1437,7 +1437,7 @@
 
 					/* Buffer address */
 
-					reg = zr->v4l_buffers.buffer[frame].fbuffer_bus;
+					reg = zr->v4l_buffers.buffer[frame].v4l.fbuffer_bus;
 					btwrite(reg, ZR36057_VDTR);
 					if (zr->v4l_settings.height > BUZ_MAX_HEIGHT / 2)
 						reg += zr->v4l_settings.bytesperline;
diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c
index b7f03d1..26be1a8 100644
--- a/drivers/media/video/zoran/zoran_driver.c
+++ b/drivers/media/video/zoran/zoran_driver.c
@@ -193,6 +193,24 @@
 static void v4l_fbuffer_free(struct file *file);
 static void jpg_fbuffer_free(struct file *file);
 
+/* Set mapping mode */
+static void map_mode_raw(struct zoran_fh *fh)
+{
+	fh->map_mode = ZORAN_MAP_MODE_RAW;
+	fh->buffers.buffer_size = v4l_bufsize;
+	fh->buffers.num_buffers = v4l_nbufs;
+}
+static void map_mode_jpg(struct zoran_fh *fh, int play)
+{
+	fh->map_mode = play ? ZORAN_MAP_MODE_JPG_PLAY : ZORAN_MAP_MODE_JPG_REC;
+	fh->buffers.buffer_size = jpg_bufsize;
+	fh->buffers.num_buffers = jpg_nbufs;
+}
+static inline const char *mode_name(enum zoran_map_mode mode)
+{
+	return mode == ZORAN_MAP_MODE_RAW ? "V4L" : "JPG";
+}
+
 /*
  *   Allocate the V4L grab buffers
  *
@@ -207,15 +225,15 @@
 	int i, off;
 	unsigned char *mem;
 
-	for (i = 0; i < fh->v4l_buffers.num_buffers; i++) {
-		if (fh->v4l_buffers.buffer[i].fbuffer)
+	for (i = 0; i < fh->buffers.num_buffers; i++) {
+		if (fh->buffers.buffer[i].v4l.fbuffer)
 			dprintk(2,
 				KERN_WARNING
 				"%s: v4l_fbuffer_alloc() - buffer %d already allocated!?\n",
 				ZR_DEVNAME(zr), i);
 
 		//udelay(20);
-		mem = kmalloc(fh->v4l_buffers.buffer_size, GFP_KERNEL);
+		mem = kmalloc(fh->buffers.buffer_size, GFP_KERNEL);
 		if (!mem) {
 			dprintk(1,
 				KERN_ERR
@@ -224,12 +242,10 @@
 			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);
-		for (off = 0; off < fh->v4l_buffers.buffer_size;
+		fh->buffers.buffer[i].v4l.fbuffer = mem;
+		fh->buffers.buffer[i].v4l.fbuffer_phys = virt_to_phys(mem);
+		fh->buffers.buffer[i].v4l.fbuffer_bus = virt_to_bus(mem);
+		for (off = 0; off < fh->buffers.buffer_size;
 		     off += PAGE_SIZE)
 			SetPageReserved(virt_to_page(mem + off));
 		dprintk(4,
@@ -239,7 +255,7 @@
 			virt_to_bus(mem));
 	}
 
-	fh->v4l_buffers.allocated = 1;
+	fh->buffers.allocated = 1;
 
 	return 0;
 }
@@ -255,19 +271,19 @@
 
 	dprintk(4, KERN_INFO "%s: v4l_fbuffer_free()\n", ZR_DEVNAME(zr));
 
-	for (i = 0; i < fh->v4l_buffers.num_buffers; i++) {
-		if (!fh->v4l_buffers.buffer[i].fbuffer)
+	for (i = 0; i < fh->buffers.num_buffers; i++) {
+		if (!fh->buffers.buffer[i].v4l.fbuffer)
 			continue;
 
-		mem = fh->v4l_buffers.buffer[i].fbuffer;
-		for (off = 0; off < fh->v4l_buffers.buffer_size;
+		mem = fh->buffers.buffer[i].v4l.fbuffer;
+		for (off = 0; off < fh->buffers.buffer_size;
 		     off += PAGE_SIZE)
 			ClearPageReserved(virt_to_page(mem + off));
-		kfree((void *) fh->v4l_buffers.buffer[i].fbuffer);
-		fh->v4l_buffers.buffer[i].fbuffer = NULL;
+		kfree(fh->buffers.buffer[i].v4l.fbuffer);
+		fh->buffers.buffer[i].v4l.fbuffer = NULL;
 	}
 
-	fh->v4l_buffers.allocated = 0;
+	fh->buffers.allocated = 0;
 }
 
 /*
@@ -304,10 +320,10 @@
 	struct zoran_fh *fh = file->private_data;
 	struct zoran *zr = fh->zr;
 	int i, j, off;
-	unsigned long mem;
+	u8 *mem;
 
-	for (i = 0; i < fh->jpg_buffers.num_buffers; i++) {
-		if (fh->jpg_buffers.buffer[i].frag_tab)
+	for (i = 0; i < fh->buffers.num_buffers; i++) {
+		if (fh->buffers.buffer[i].jpg.frag_tab)
 			dprintk(2,
 				KERN_WARNING
 				"%s: jpg_fbuffer_alloc() - buffer %d already allocated!?\n",
@@ -315,7 +331,7 @@
 
 		/* Allocate fragment table for this buffer */
 
-		mem = get_zeroed_page(GFP_KERNEL);
+		mem = (void *)get_zeroed_page(GFP_KERNEL);
 		if (mem == 0) {
 			dprintk(1,
 				KERN_ERR
@@ -324,17 +340,12 @@
 			jpg_fbuffer_free(file);
 			return -ENOBUFS;
 		}
-		fh->jpg_buffers.buffer[i].frag_tab = (__le32 *) mem;
-		fh->jpg_buffers.buffer[i].frag_tab_bus =
-		    virt_to_bus((void *) mem);
+		fh->buffers.buffer[i].jpg.frag_tab = (__le32 *)mem;
+		fh->buffers.buffer[i].jpg.frag_tab_bus = virt_to_bus(mem);
 
-		//if (alloc_contig) {
-		if (fh->jpg_buffers.need_contiguous) {
-			mem =
-			    (unsigned long) kmalloc(fh->jpg_buffers.
-						    buffer_size,
-						    GFP_KERNEL);
-			if (mem == 0) {
+		if (fh->buffers.need_contiguous) {
+			mem = kmalloc(fh->buffers.buffer_size, GFP_KERNEL);
+			if (mem == NULL) {
 				dprintk(1,
 					KERN_ERR
 					"%s: jpg_fbuffer_alloc() - kmalloc failed for buffer %d\n",
@@ -342,20 +353,17 @@
 				jpg_fbuffer_free(file);
 				return -ENOBUFS;
 			}
-			fh->jpg_buffers.buffer[i].frag_tab[0] =
-			    cpu_to_le32(virt_to_bus((void *) mem));
-			fh->jpg_buffers.buffer[i].frag_tab[1] =
-			    cpu_to_le32(((fh->jpg_buffers.buffer_size / 4) << 1) | 1);
-			for (off = 0; off < fh->jpg_buffers.buffer_size;
-			     off += PAGE_SIZE)
+			fh->buffers.buffer[i].jpg.frag_tab[0] =
+				cpu_to_le32(virt_to_bus(mem));
+			fh->buffers.buffer[i].jpg.frag_tab[1] =
+				cpu_to_le32((fh->buffers.buffer_size >> 1) | 1);
+			for (off = 0; off < fh->buffers.buffer_size; off += PAGE_SIZE)
 				SetPageReserved(virt_to_page(mem + off));
 		} else {
 			/* jpg_bufsize is already page aligned */
-			for (j = 0;
-			     j < fh->jpg_buffers.buffer_size / PAGE_SIZE;
-			     j++) {
-				mem = get_zeroed_page(GFP_KERNEL);
-				if (mem == 0) {
+			for (j = 0; j < fh->buffers.buffer_size / PAGE_SIZE; j++) {
+				mem = (void *)get_zeroed_page(GFP_KERNEL);
+				if (mem == NULL) {
 					dprintk(1,
 						KERN_ERR
 						"%s: jpg_fbuffer_alloc() - get_zeroed_page failed for buffer %d\n",
@@ -364,25 +372,23 @@
 					return -ENOBUFS;
 				}
 
-				fh->jpg_buffers.buffer[i].frag_tab[2 * j] =
-				    cpu_to_le32(virt_to_bus((void *) mem));
-				fh->jpg_buffers.buffer[i].frag_tab[2 * j +
-								   1] =
-				    cpu_to_le32((PAGE_SIZE / 4) << 1);
+				fh->buffers.buffer[i].jpg.frag_tab[2 * j] =
+					cpu_to_le32(virt_to_bus(mem));
+				fh->buffers.buffer[i].jpg.frag_tab[2 * j + 1] =
+					cpu_to_le32((PAGE_SIZE >> 2) << 1);
 				SetPageReserved(virt_to_page(mem));
 			}
 
-			fh->jpg_buffers.buffer[i].frag_tab[2 * j - 1] |= cpu_to_le32(1);
+			fh->buffers.buffer[i].jpg.frag_tab[2 * j - 1] |= cpu_to_le32(1);
 		}
 	}
 
 	dprintk(4,
 		KERN_DEBUG "%s: jpg_fbuffer_alloc() - %d KB allocated\n",
 		ZR_DEVNAME(zr),
-		(fh->jpg_buffers.num_buffers *
-		 fh->jpg_buffers.buffer_size) >> 10);
+		(fh->buffers.num_buffers * fh->buffers.buffer_size) >> 10);
 
-	fh->jpg_buffers.allocated = 1;
+	fh->buffers.allocated = 1;
 
 	return 0;
 }
@@ -396,42 +402,44 @@
 	int i, j, off;
 	unsigned char *mem;
 	__le32 frag_tab;
+	struct zoran_buffer *buffer;
 
 	dprintk(4, KERN_DEBUG "%s: jpg_fbuffer_free()\n", ZR_DEVNAME(zr));
 
-	for (i = 0; i < fh->jpg_buffers.num_buffers; i++) {
-		if (!fh->jpg_buffers.buffer[i].frag_tab)
+	for (i = 0, buffer = &fh->buffers.buffer[0];
+	     i < fh->buffers.num_buffers; i++, buffer++) {
+		if (!buffer->jpg.frag_tab)
 			continue;
 
-		if (fh->jpg_buffers.need_contiguous) {
-			frag_tab = fh->jpg_buffers.buffer[i].frag_tab[0];
+		if (fh->buffers.need_contiguous) {
+			frag_tab = buffer->jpg.frag_tab[0];
 
 			if (frag_tab) {
-				mem = (unsigned char *)bus_to_virt(le32_to_cpu(frag_tab));
-				for (off = 0; off < fh->jpg_buffers.buffer_size; off += PAGE_SIZE)
+				mem = bus_to_virt(le32_to_cpu(frag_tab));
+				for (off = 0; off < fh->buffers.buffer_size; off += PAGE_SIZE)
 					ClearPageReserved(virt_to_page(mem + off));
 				kfree(mem);
-				fh->jpg_buffers.buffer[i].frag_tab[0] = 0;
-				fh->jpg_buffers.buffer[i].frag_tab[1] = 0;
+				buffer->jpg.frag_tab[0] = 0;
+				buffer->jpg.frag_tab[1] = 0;
 			}
 		} else {
-			for (j = 0; j < fh->jpg_buffers.buffer_size / PAGE_SIZE; j++) {
-				frag_tab = fh->jpg_buffers.buffer[i].frag_tab[2 * j];
+			for (j = 0; j < fh->buffers.buffer_size / PAGE_SIZE; j++) {
+				frag_tab = buffer->jpg.frag_tab[2 * j];
 
 				if (!frag_tab)
 					break;
 				ClearPageReserved(virt_to_page(bus_to_virt(le32_to_cpu(frag_tab))));
 				free_page((unsigned long)bus_to_virt(le32_to_cpu(frag_tab)));
-				fh->jpg_buffers.buffer[i].frag_tab[2 * j] = 0;
-				fh->jpg_buffers.buffer[i].frag_tab[2 * j + 1] = 0;
+				buffer->jpg.frag_tab[2 * j] = 0;
+				buffer->jpg.frag_tab[2 * j + 1] = 0;
 			}
 		}
 
-		free_page((unsigned long)fh->jpg_buffers.buffer[i].frag_tab);
-		fh->jpg_buffers.buffer[i].frag_tab = NULL;
+		free_page((unsigned long)buffer->jpg.frag_tab);
+		buffer->jpg.frag_tab = NULL;
 	}
 
-	fh->jpg_buffers.allocated = 0;
+	fh->buffers.allocated = 0;
 }
 
 /*
@@ -439,12 +447,11 @@
  */
 
 static int
-zoran_v4l_set_format (struct file               *file,
+zoran_v4l_set_format (struct zoran_fh           *fh,
 		      int                        width,
 		      int                        height,
 		      const struct zoran_format *format)
 {
-	struct zoran_fh *fh = file->private_data;
 	struct zoran *zr = fh->zr;
 	int bpp;
 
@@ -462,11 +469,11 @@
 	bpp = (format->depth + 7) / 8;
 
 	/* Check against available buffer size */
-	if (height * width * bpp > fh->v4l_buffers.buffer_size) {
+	if (height * width * bpp > fh->buffers.buffer_size) {
 		dprintk(1,
 			KERN_ERR
 			"%s: v4l_set_format() - video buffer size (%d kB) is too small\n",
-			ZR_DEVNAME(zr), fh->v4l_buffers.buffer_size >> 10);
+			ZR_DEVNAME(zr), fh->buffers.buffer_size >> 10);
 		return -EINVAL;
 	}
 
@@ -497,7 +504,7 @@
 	unsigned long flags;
 	int res = 0;
 
-	if (!fh->v4l_buffers.allocated) {
+	if (!fh->buffers.allocated) {
 		dprintk(1,
 			KERN_ERR
 			"%s: v4l_queue_frame() - buffers not yet allocated\n",
@@ -506,7 +513,7 @@
 	}
 
 	/* No grabbing outside the buffer range! */
-	if (num >= fh->v4l_buffers.num_buffers || num < 0) {
+	if (num >= fh->buffers.num_buffers || num < 0) {
 		dprintk(1,
 			KERN_ERR
 			"%s: v4l_queue_frame() - buffer %d is out of range\n",
@@ -516,10 +523,10 @@
 
 	spin_lock_irqsave(&zr->spinlock, flags);
 
-	if (fh->v4l_buffers.active == ZORAN_FREE) {
+	if (fh->buffers.active == ZORAN_FREE) {
 		if (zr->v4l_buffers.active == ZORAN_FREE) {
-			zr->v4l_buffers = fh->v4l_buffers;
-			fh->v4l_buffers.active = ZORAN_ACTIVE;
+			zr->v4l_buffers = fh->buffers;
+			fh->buffers.active = ZORAN_ACTIVE;
 		} else {
 			dprintk(1,
 				KERN_ERR
@@ -535,7 +542,7 @@
 		default:
 		case BUZ_STATE_PEND:
 			if (zr->v4l_buffers.active == ZORAN_FREE) {
-				fh->v4l_buffers.active = ZORAN_FREE;
+				fh->buffers.active = ZORAN_FREE;
 				zr->v4l_buffers.allocated = 0;
 			}
 			res = -EBUSY;	/* what are you doing? */
@@ -548,14 +555,12 @@
 		case BUZ_STATE_USER:
 			/* since there is at least one unused buffer there's room for at least
 			 * one more pend[] entry */
-			zr->v4l_pend[zr->v4l_pend_head++ &
-					V4L_MASK_FRAME] = num;
+			zr->v4l_pend[zr->v4l_pend_head++ & V4L_MASK_FRAME] = num;
 			zr->v4l_buffers.buffer[num].state = BUZ_STATE_PEND;
 			zr->v4l_buffers.buffer[num].bs.length =
 			    fh->v4l_settings.bytesperline *
 			    zr->v4l_settings.height;
-			fh->v4l_buffers.buffer[num] =
-			    zr->v4l_buffers.buffer[num];
+			fh->buffers.buffer[num] = zr->v4l_buffers.buffer[num];
 			break;
 		}
 	}
@@ -563,7 +568,7 @@
 	spin_unlock_irqrestore(&zr->spinlock, flags);
 
 	if (!res && zr->v4l_buffers.active == ZORAN_FREE)
-		zr->v4l_buffers.active = fh->v4l_buffers.active;
+		zr->v4l_buffers.active = fh->buffers.active;
 
 	return res;
 }
@@ -580,7 +585,7 @@
 	struct zoran *zr = fh->zr;
 	unsigned long flags;
 
-	if (fh->v4l_buffers.active == ZORAN_FREE) {
+	if (fh->buffers.active == ZORAN_FREE) {
 		dprintk(1,
 			KERN_ERR
 			"%s: v4l_sync() - no grab active for this session\n",
@@ -589,7 +594,7 @@
 	}
 
 	/* check passed-in frame number */
-	if (frame >= fh->v4l_buffers.num_buffers || frame < 0) {
+	if (frame >= fh->buffers.num_buffers || frame < 0) {
 		dprintk(1,
 			KERN_ERR "%s: v4l_sync() - frame %d is invalid\n",
 			ZR_DEVNAME(zr), frame);
@@ -607,8 +612,7 @@
 
 	/* wait on this buffer to get ready */
 	if (!wait_event_interruptible_timeout(zr->v4l_capq,
-				(zr->v4l_buffers.buffer[frame].state != BUZ_STATE_PEND),
-				10*HZ))
+		(zr->v4l_buffers.buffer[frame].state != BUZ_STATE_PEND), 10*HZ))
 		return -ETIME;
 	if (signal_pending(current))
 		return -ERESTARTSYS;
@@ -620,7 +624,7 @@
 			ZR_DEVNAME(zr));
 
 	zr->v4l_buffers.buffer[frame].state = BUZ_STATE_USER;
-	fh->v4l_buffers.buffer[frame] = zr->v4l_buffers.buffer[frame];
+	fh->buffers.buffer[frame] = zr->v4l_buffers.buffer[frame];
 
 	spin_lock_irqsave(&zr->spinlock, flags);
 
@@ -628,8 +632,7 @@
 	if (zr->v4l_pend_tail == zr->v4l_pend_head) {
 		zr36057_set_memgrab(zr, 0);
 		if (zr->v4l_buffers.active == ZORAN_ACTIVE) {
-			fh->v4l_buffers.active = zr->v4l_buffers.active =
-			    ZORAN_FREE;
+			fh->buffers.active = zr->v4l_buffers.active = ZORAN_FREE;
 			zr->v4l_buffers.allocated = 0;
 		}
 	}
@@ -654,7 +657,7 @@
 	int res = 0;
 
 	/* Check if buffers are allocated */
-	if (!fh->jpg_buffers.allocated) {
+	if (!fh->buffers.allocated) {
 		dprintk(1,
 			KERN_ERR
 			"%s: jpg_queue_frame() - buffers not yet allocated\n",
@@ -663,7 +666,7 @@
 	}
 
 	/* No grabbing outside the buffer range! */
-	if (num >= fh->jpg_buffers.num_buffers || num < 0) {
+	if (num >= fh->buffers.num_buffers || num < 0) {
 		dprintk(1,
 			KERN_ERR
 			"%s: jpg_queue_frame() - buffer %d out of range\n",
@@ -683,10 +686,10 @@
 		return -EINVAL;
 	}
 
-	if (fh->jpg_buffers.active == ZORAN_FREE) {
+	if (fh->buffers.active == ZORAN_FREE) {
 		if (zr->jpg_buffers.active == ZORAN_FREE) {
-			zr->jpg_buffers = fh->jpg_buffers;
-			fh->jpg_buffers.active = ZORAN_ACTIVE;
+			zr->jpg_buffers = fh->buffers;
+			fh->buffers.active = ZORAN_ACTIVE;
 		} else {
 			dprintk(1,
 				KERN_ERR
@@ -713,18 +716,16 @@
 		case BUZ_STATE_USER:
 			/* since there is at least one unused buffer there's room for at
 			 *least one more pend[] entry */
-			zr->jpg_pend[zr->jpg_que_head++ & BUZ_MASK_FRAME] =
-			    num;
+			zr->jpg_pend[zr->jpg_que_head++ & BUZ_MASK_FRAME] = num;
 			zr->jpg_buffers.buffer[num].state = BUZ_STATE_PEND;
-			fh->jpg_buffers.buffer[num] =
-			    zr->jpg_buffers.buffer[num];
+			fh->buffers.buffer[num] = zr->jpg_buffers.buffer[num];
 			zoran_feed_stat_com(zr);
 			break;
 		default:
 		case BUZ_STATE_DMA:
 		case BUZ_STATE_PEND:
 			if (zr->jpg_buffers.active == ZORAN_FREE) {
-				fh->jpg_buffers.active = ZORAN_FREE;
+				fh->buffers.active = ZORAN_FREE;
 				zr->jpg_buffers.allocated = 0;
 			}
 			res = -EBUSY;	/* what are you doing? */
@@ -734,9 +735,8 @@
 
 	spin_unlock_irqrestore(&zr->spinlock, flags);
 
-	if (!res && zr->jpg_buffers.active == ZORAN_FREE) {
-		zr->jpg_buffers.active = fh->jpg_buffers.active;
-	}
+	if (!res && zr->jpg_buffers.active == ZORAN_FREE)
+		zr->jpg_buffers.active = fh->buffers.active;
 
 	return res;
 }
@@ -753,15 +753,14 @@
 	/* Does the user want to stop streaming? */
 	if (frame < 0) {
 		if (zr->codec_mode == mode) {
-			if (fh->jpg_buffers.active == ZORAN_FREE) {
+			if (fh->buffers.active == ZORAN_FREE) {
 				dprintk(1,
 					KERN_ERR
 					"%s: jpg_qbuf(-1) - session not active\n",
 					ZR_DEVNAME(zr));
 				return -EINVAL;
 			}
-			fh->jpg_buffers.active = zr->jpg_buffers.active =
-			    ZORAN_FREE;
+			fh->buffers.active = zr->jpg_buffers.active = ZORAN_FREE;
 			zr->jpg_buffers.allocated = 0;
 			zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
 			return 0;
@@ -797,7 +796,7 @@
 	unsigned long flags;
 	int frame;
 
-	if (fh->jpg_buffers.active == ZORAN_FREE) {
+	if (fh->buffers.active == ZORAN_FREE) {
 		dprintk(1,
 			KERN_ERR
 			"%s: jpg_sync() - capture is not currently active\n",
@@ -849,7 +848,7 @@
 	*bs = zr->jpg_buffers.buffer[frame].bs;
 	bs->frame = frame;
 	zr->jpg_buffers.buffer[frame].state = BUZ_STATE_USER;
-	fh->jpg_buffers.buffer[frame] = zr->jpg_buffers.buffer[frame];
+	fh->buffers.buffer[frame] = zr->jpg_buffers.buffer[frame];
 
 	spin_unlock_irqrestore(&zr->spinlock, flags);
 
@@ -864,7 +863,7 @@
 	struct zoran *zr = fh->zr;
 
 	/* Per default, map the V4L Buffers */
-	fh->map_mode = ZORAN_MAP_MODE_RAW;
+	map_mode_raw(fh);
 
 	/* take over the card's current settings */
 	fh->overlay_settings = zr->overlay_settings;
@@ -874,32 +873,17 @@
 
 	/* v4l settings */
 	fh->v4l_settings = zr->v4l_settings;
-
-	/* v4l_buffers */
-	memset(&fh->v4l_buffers, 0, sizeof(struct zoran_v4l_struct));
-	for (i = 0; i < VIDEO_MAX_FRAME; i++) {
-		fh->v4l_buffers.buffer[i].state = BUZ_STATE_USER;	/* nothing going on */
-		fh->v4l_buffers.buffer[i].bs.frame = i;
-	}
-	fh->v4l_buffers.allocated = 0;
-	fh->v4l_buffers.active = ZORAN_FREE;
-	fh->v4l_buffers.buffer_size = v4l_bufsize;
-	fh->v4l_buffers.num_buffers = v4l_nbufs;
-
 	/* jpg settings */
 	fh->jpg_settings = zr->jpg_settings;
 
-	/* jpg_buffers */
-	memset(&fh->jpg_buffers, 0, sizeof(struct zoran_jpg_struct));
-	for (i = 0; i < BUZ_MAX_FRAME; i++) {
-		fh->jpg_buffers.buffer[i].state = BUZ_STATE_USER;	/* nothing going on */
-		fh->jpg_buffers.buffer[i].bs.frame = i;
+	/* buffers */
+	memset(&fh->buffers, 0, sizeof(fh->buffers));
+	for (i = 0; i < MAX_FRAME; i++) {
+		fh->buffers.buffer[i].state = BUZ_STATE_USER;	/* nothing going on */
+		fh->buffers.buffer[i].bs.frame = i;
 	}
-	fh->jpg_buffers.need_contiguous = zr->jpg_buffers.need_contiguous;
-	fh->jpg_buffers.allocated = 0;
-	fh->jpg_buffers.active = ZORAN_FREE;
-	fh->jpg_buffers.buffer_size = jpg_bufsize;
-	fh->jpg_buffers.num_buffers = jpg_nbufs;
+	fh->buffers.allocated = 0;
+	fh->buffers.active = ZORAN_FREE;
 }
 
 static void
@@ -917,33 +901,33 @@
 		zr->overlay_mask = NULL;
 	}
 
-	/* v4l capture */
-	if (fh->v4l_buffers.active != ZORAN_FREE) {
-		unsigned long flags;
+	if (fh->map_mode == ZORAN_MAP_MODE_RAW) {
+		/* v4l capture */
+		if (fh->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);
+			spin_lock_irqsave(&zr->spinlock, flags);
+			zr36057_set_memgrab(zr, 0);
+			zr->v4l_buffers.allocated = 0;
+			zr->v4l_buffers.active = fh->buffers.active = ZORAN_FREE;
+			spin_unlock_irqrestore(&zr->spinlock, flags);
+		}
+
+		/* v4l buffers */
+		if (fh->buffers.allocated)
+			v4l_fbuffer_free(file);
+	} else {
+		/* jpg capture */
+		if (fh->buffers.active != ZORAN_FREE) {
+			zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
+			zr->jpg_buffers.allocated = 0;
+			zr->jpg_buffers.active = fh->buffers.active = ZORAN_FREE;
+		}
+
+		/* jpg buffers */
+		if (fh->buffers.allocated)
+			jpg_fbuffer_free(file);
 	}
-
-	/* v4l buffers */
-	if (fh->v4l_buffers.allocated)
-		v4l_fbuffer_free(file);
-
-	/* jpg capture */
-	if (fh->jpg_buffers.active != ZORAN_FREE) {
-		zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
-		zr->jpg_buffers.allocated = 0;
-		zr->jpg_buffers.active = fh->jpg_buffers.active =
-		    ZORAN_FREE;
-	}
-
-	/* jpg buffers */
-	if (fh->jpg_buffers.allocated)
-		jpg_fbuffer_free(file);
 }
 
 /*
@@ -1382,15 +1366,15 @@
 			  int                 num)
 {
 	struct zoran *zr = fh->zr;
+	unsigned long flags;
 
 	buf->flags = V4L2_BUF_FLAG_MAPPED;
 
 	switch (fh->map_mode) {
 	case ZORAN_MAP_MODE_RAW:
-
 		/* check range */
-		if (num < 0 || num >= fh->v4l_buffers.num_buffers ||
-		    !fh->v4l_buffers.allocated) {
+		if (num < 0 || num >= fh->buffers.num_buffers ||
+		    !fh->buffers.allocated) {
 			dprintk(1,
 				KERN_ERR
 				"%s: v4l2_buffer_status() - wrong number or buffers not allocated\n",
@@ -1398,17 +1382,26 @@
 			return -EINVAL;
 		}
 
+		spin_lock_irqsave(&zr->spinlock, flags);
+		dprintk(3,
+			KERN_DEBUG
+			"%s: %s() - raw active=%c, buffer %d: state=%c, map=%c\n",
+			ZR_DEVNAME(zr), __func__,
+			"FAL"[fh->buffers.active], num,
+			"UPMD"[zr->v4l_buffers.buffer[num].state],
+			fh->buffers.buffer[num].map ? 'Y' : 'N');
+		spin_unlock_irqrestore(&zr->spinlock, flags);
+
 		buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		buf->length = fh->v4l_buffers.buffer_size;
+		buf->length = fh->buffers.buffer_size;
 
 		/* get buffer */
-		buf->bytesused = fh->v4l_buffers.buffer[num].bs.length;
-		if (fh->v4l_buffers.buffer[num].state == BUZ_STATE_DONE ||
-		    fh->v4l_buffers.buffer[num].state == BUZ_STATE_USER) {
-			buf->sequence = fh->v4l_buffers.buffer[num].bs.seq;
+		buf->bytesused = fh->buffers.buffer[num].bs.length;
+		if (fh->buffers.buffer[num].state == BUZ_STATE_DONE ||
+		    fh->buffers.buffer[num].state == BUZ_STATE_USER) {
+			buf->sequence = fh->buffers.buffer[num].bs.seq;
 			buf->flags |= V4L2_BUF_FLAG_DONE;
-			buf->timestamp =
-			    fh->v4l_buffers.buffer[num].bs.timestamp;
+			buf->timestamp = fh->buffers.buffer[num].bs.timestamp;
 		} else {
 			buf->flags |= V4L2_BUF_FLAG_QUEUED;
 		}
@@ -1424,8 +1417,8 @@
 	case ZORAN_MAP_MODE_JPG_PLAY:
 
 		/* check range */
-		if (num < 0 || num >= fh->jpg_buffers.num_buffers ||
-		    !fh->jpg_buffers.allocated) {
+		if (num < 0 || num >= fh->buffers.num_buffers ||
+		    !fh->buffers.allocated) {
 			dprintk(1,
 				KERN_ERR
 				"%s: v4l2_buffer_status() - wrong number or buffers not allocated\n",
@@ -1436,16 +1429,14 @@
 		buf->type = (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) ?
 			      V4L2_BUF_TYPE_VIDEO_CAPTURE :
 			      V4L2_BUF_TYPE_VIDEO_OUTPUT;
-		buf->length = fh->jpg_buffers.buffer_size;
+		buf->length = fh->buffers.buffer_size;
 
 		/* these variables are only written after frame has been captured */
-		if (fh->jpg_buffers.buffer[num].state == BUZ_STATE_DONE ||
-		    fh->jpg_buffers.buffer[num].state == BUZ_STATE_USER) {
-			buf->sequence = fh->jpg_buffers.buffer[num].bs.seq;
-			buf->timestamp =
-			    fh->jpg_buffers.buffer[num].bs.timestamp;
-			buf->bytesused =
-			    fh->jpg_buffers.buffer[num].bs.length;
+		if (fh->buffers.buffer[num].state == BUZ_STATE_DONE ||
+		    fh->buffers.buffer[num].state == BUZ_STATE_USER) {
+			buf->sequence = fh->buffers.buffer[num].bs.seq;
+			buf->timestamp = fh->buffers.buffer[num].bs.timestamp;
+			buf->bytesused = fh->buffers.buffer[num].bs.length;
 			buf->flags |= V4L2_BUF_FLAG_DONE;
 		} else {
 			buf->flags |= V4L2_BUF_FLAG_QUEUED;
@@ -1453,14 +1444,11 @@
 
 		/* which fields are these? */
 		if (fh->jpg_settings.TmpDcm != 1)
-			buf->field =
-			    fh->jpg_settings.
-			    odd_even ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM;
+			buf->field = fh->jpg_settings.odd_even ?
+				V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM;
 		else
-			buf->field =
-			    fh->jpg_settings.
-			    odd_even ? V4L2_FIELD_SEQ_TB :
-			    V4L2_FIELD_SEQ_BT;
+			buf->field = fh->jpg_settings.odd_even ?
+				V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT;
 
 		break;
 
@@ -1743,7 +1731,7 @@
 
 		mutex_lock(&zr->resource_lock);
 
-		if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) {
+		if (fh->buffers.allocated) {
 			dprintk(1,
 				KERN_ERR
 				"%s: BUZIOC_REQBUFS - buffers already allocated\n",
@@ -1752,17 +1740,17 @@
 			goto jpgreqbuf_unlock_and_return;
 		}
 
-		fh->jpg_buffers.num_buffers = breq->count;
-		fh->jpg_buffers.buffer_size = breq->size;
+		/* The next mmap will map the MJPEG buffers - could
+		 * also be *_PLAY, but it doesn't matter here */
+		map_mode_jpg(fh, 0);
+		fh->buffers.num_buffers = breq->count;
+		fh->buffers.buffer_size = breq->size;
 
 		if (jpg_fbuffer_alloc(file)) {
 			res = -ENOMEM;
 			goto jpgreqbuf_unlock_and_return;
 		}
 
-		/* The next mmap will map the MJPEG buffers - could
-		 * also be *_PLAY, but it doesn't matter here */
-		fh->map_mode = ZORAN_MAP_MODE_JPG_REC;
 jpgreqbuf_unlock_and_return:
 		mutex_unlock(&zr->resource_lock);
 
@@ -1805,7 +1793,15 @@
 		dprintk(3, KERN_DEBUG "%s: BUZIOC_SYNC\n", ZR_DEVNAME(zr));
 
 		mutex_lock(&zr->resource_lock);
-		res = jpg_sync(file, bsync);
+
+		if (fh->map_mode == ZORAN_MAP_MODE_RAW) {
+			dprintk(2, KERN_WARNING
+				"%s: %s - not in jpg capture mode\n",
+				ZR_DEVNAME(zr), __func__);
+			res = -EINVAL;
+		} else {
+			res = jpg_sync(file, bsync);
+		}
 		mutex_unlock(&zr->resource_lock);
 
 		return res;
@@ -1884,18 +1880,10 @@
 	struct zoran *zr = fh->zr;
 	int i, res = 0;
 
-	vmbuf->size =
-	    fh->v4l_buffers.num_buffers *
-	    fh->v4l_buffers.buffer_size;
-	vmbuf->frames = fh->v4l_buffers.num_buffers;
-	for (i = 0; i < vmbuf->frames; i++) {
-		vmbuf->offsets[i] =
-		    i * fh->v4l_buffers.buffer_size;
-	}
 
 	mutex_lock(&zr->resource_lock);
 
-	if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) {
+	if (fh->buffers.allocated) {
 		dprintk(1,
 			KERN_ERR
 			"%s: VIDIOCGMBUF - buffers already allocated\n",
@@ -1904,13 +1892,19 @@
 		goto v4l1reqbuf_unlock_and_return;
 	}
 
+	/* The next mmap will map the V4L buffers */
+	map_mode_raw(fh);
+
 	if (v4l_fbuffer_alloc(file)) {
 		res = -ENOMEM;
 		goto v4l1reqbuf_unlock_and_return;
 	}
 
-	/* The next mmap will map the V4L buffers */
-	fh->map_mode = ZORAN_MAP_MODE_RAW;
+	vmbuf->size = fh->buffers.num_buffers * fh->buffers.buffer_size;
+	vmbuf->frames = fh->buffers.num_buffers;
+	for (i = 0; i < vmbuf->frames; i++)
+		vmbuf->offsets[i] = i * fh->buffers.buffer_size;
+
 v4l1reqbuf_unlock_and_return:
 	mutex_unlock(&zr->resource_lock);
 
@@ -2223,15 +2217,15 @@
 
 	mutex_lock(&zr->resource_lock);
 
-	settings = fh->jpg_settings;
-
-	if (fh->v4l_buffers.allocated || fh->jpg_buffers.allocated) {
+	if (fh->buffers.allocated) {
 		dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - cannot change capture mode\n",
-				ZR_DEVNAME(zr));
+			ZR_DEVNAME(zr));
 		res = -EBUSY;
 		goto sfmtjpg_unlock_and_return;
 	}
 
+	settings = fh->jpg_settings;
+
 	/* we actually need to set 'real' parameters now */
 	if (fmt->fmt.pix.height * 2 > BUZ_MAX_HEIGHT)
 		settings.TmpDcm = 1;
@@ -2269,6 +2263,9 @@
 	/* it's ok, so set them */
 	fh->jpg_settings = settings;
 
+	map_mode_jpg(fh, fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	fh->buffers.buffer_size = zoran_v4l2_calc_bufsize(&fh->jpg_settings);
+
 	/* tell the user what we actually did */
 	fmt->fmt.pix.width = settings.img_width / settings.HorDcm;
 	fmt->fmt.pix.height = settings.img_height * 2 /
@@ -2279,15 +2276,10 @@
 	else
 		fmt->fmt.pix.field = (fh->jpg_settings.odd_even ?
 				V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
-	fh->jpg_buffers.buffer_size = zoran_v4l2_calc_bufsize(&fh->jpg_settings);
 	fmt->fmt.pix.bytesperline = 0;
-	fmt->fmt.pix.sizeimage = fh->jpg_buffers.buffer_size;
+	fmt->fmt.pix.sizeimage = fh->buffers.buffer_size;
 	fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
 
-	/* we hereby abuse this variable to show that
-	 * we're gonna do mjpeg capture */
-	fh->map_mode = (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ?
-		ZORAN_MAP_MODE_JPG_REC : ZORAN_MAP_MODE_JPG_PLAY;
 sfmtjpg_unlock_and_return:
 	mutex_unlock(&zr->resource_lock);
 	return res;
@@ -2312,9 +2304,11 @@
 			ZR_DEVNAME(zr), fmt->fmt.pix.pixelformat);
 		return -EINVAL;
 	}
+
 	mutex_lock(&zr->resource_lock);
-	if (fh->jpg_buffers.allocated ||
-		(fh->v4l_buffers.allocated && fh->v4l_buffers.active != ZORAN_FREE)) {
+
+	if ((fh->map_mode != ZORAN_MAP_MODE_RAW && fh->buffers.allocated) ||
+	    fh->buffers.active != ZORAN_FREE) {
 		dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - cannot change capture mode\n",
 				ZR_DEVNAME(zr));
 		res = -EBUSY;
@@ -2325,13 +2319,14 @@
 	if (fmt->fmt.pix.width > BUZ_MAX_WIDTH)
 		fmt->fmt.pix.width = BUZ_MAX_WIDTH;
 
-	res = zoran_v4l_set_format(file, fmt->fmt.pix.width,
-			fmt->fmt.pix.height, &zoran_formats[i]);
+	map_mode_raw(fh);
+
+	res = zoran_v4l_set_format(fh, fmt->fmt.pix.width, fmt->fmt.pix.height,
+				   &zoran_formats[i]);
 	if (res)
 		goto sfmtv4l_unlock_and_return;
 
-	/* tell the user the
-	 * results/missing stuff */
+	/* tell the user the results/missing stuff */
 	fmt->fmt.pix.bytesperline = fh->v4l_settings.bytesperline;
 	fmt->fmt.pix.sizeimage = fh->v4l_settings.height * fh->v4l_settings.bytesperline;
 	fmt->fmt.pix.colorspace = fh->v4l_settings.format->colorspace;
@@ -2340,7 +2335,6 @@
 	else
 		fmt->fmt.pix.field = V4L2_FIELD_TOP;
 
-	fh->map_mode = ZORAN_MAP_MODE_RAW;
 sfmtv4l_unlock_and_return:
 	mutex_unlock(&zr->resource_lock);
 	return res;
@@ -2429,7 +2423,7 @@
 		return zoran_streamoff(file, fh, req->type);
 
 	mutex_lock(&zr->resource_lock);
-	if (fh->v4l_buffers.allocated || fh->jpg_buffers.allocated) {
+	if (fh->buffers.allocated) {
 		dprintk(2,
 				KERN_ERR
 				"%s: VIDIOC_REQBUFS - buffers already allocated\n",
@@ -2439,46 +2433,38 @@
 	}
 
 	if (fh->map_mode == ZORAN_MAP_MODE_RAW &&
-			req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-
+	    req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
 		/* control user input */
 		if (req->count < 2)
 			req->count = 2;
 		if (req->count > v4l_nbufs)
 			req->count = v4l_nbufs;
-		fh->v4l_buffers.num_buffers = req->count;
+
+		/* The next mmap will map the V4L buffers */
+		map_mode_raw(fh);
+		fh->buffers.num_buffers = req->count;
 
 		if (v4l_fbuffer_alloc(file)) {
 			res = -ENOMEM;
 			goto v4l2reqbuf_unlock_and_return;
 		}
-
-		/* The next mmap will map the V4L buffers */
-		fh->map_mode = ZORAN_MAP_MODE_RAW;
-
 	} else if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC ||
-			fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) {
-
+		   fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) {
 		/* we need to calculate size ourselves now */
 		if (req->count < 4)
 			req->count = 4;
 		if (req->count > jpg_nbufs)
 			req->count = jpg_nbufs;
-		fh->jpg_buffers.num_buffers = req->count;
-		fh->jpg_buffers.buffer_size =
-			zoran_v4l2_calc_bufsize(&fh->jpg_settings);
+
+		/* The next mmap will map the MJPEG buffers */
+		map_mode_jpg(fh, req->type == V4L2_BUF_TYPE_VIDEO_OUTPUT);
+		fh->buffers.num_buffers = req->count;
+		fh->buffers.buffer_size = zoran_v4l2_calc_bufsize(&fh->jpg_settings);
 
 		if (jpg_fbuffer_alloc(file)) {
 			res = -ENOMEM;
 			goto v4l2reqbuf_unlock_and_return;
 		}
-
-		/* The next mmap will map the MJPEG buffers */
-		if (req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-			fh->map_mode = ZORAN_MAP_MODE_JPG_REC;
-		else
-			fh->map_mode = ZORAN_MAP_MODE_JPG_PLAY;
-
 	} else {
 		dprintk(1,
 				KERN_ERR
@@ -2527,8 +2513,7 @@
 		res = zoran_v4l_queue_frame(file, buf->index);
 		if (res)
 			goto qbuf_unlock_and_return;
-		if (!zr->v4l_memgrab_active &&
-				fh->v4l_buffers.active == ZORAN_LOCKED)
+		if (!zr->v4l_memgrab_active && fh->buffers.active == ZORAN_LOCKED)
 			zr36057_set_memgrab(zr, 1);
 		break;
 
@@ -2555,9 +2540,9 @@
 		if (res != 0)
 			goto qbuf_unlock_and_return;
 		if (zr->codec_mode == BUZ_MODE_IDLE &&
-				fh->jpg_buffers.active == ZORAN_LOCKED) {
+		    fh->buffers.active == ZORAN_LOCKED)
 			zr36057_enable_jpg(zr, codec_mode);
-		}
+
 		break;
 
 	default:
@@ -2660,12 +2645,12 @@
 	switch (fh->map_mode) {
 	case ZORAN_MAP_MODE_RAW:	/* raw capture */
 		if (zr->v4l_buffers.active != ZORAN_ACTIVE ||
-		    fh->v4l_buffers.active != ZORAN_ACTIVE) {
+		    fh->buffers.active != ZORAN_ACTIVE) {
 			res = -EBUSY;
 			goto strmon_unlock_and_return;
 		}
 
-		zr->v4l_buffers.active = fh->v4l_buffers.active = ZORAN_LOCKED;
+		zr->v4l_buffers.active = fh->buffers.active = ZORAN_LOCKED;
 		zr->v4l_settings = fh->v4l_settings;
 
 		zr->v4l_sync_tail = zr->v4l_pend_tail;
@@ -2679,12 +2664,12 @@
 	case ZORAN_MAP_MODE_JPG_PLAY:
 		/* what is the codec mode right now? */
 		if (zr->jpg_buffers.active != ZORAN_ACTIVE ||
-		    fh->jpg_buffers.active != ZORAN_ACTIVE) {
+		    fh->buffers.active != ZORAN_ACTIVE) {
 			res = -EBUSY;
 			goto strmon_unlock_and_return;
 		}
 
-		zr->jpg_buffers.active = fh->jpg_buffers.active = ZORAN_LOCKED;
+		zr->jpg_buffers.active = fh->buffers.active = ZORAN_LOCKED;
 
 		if (zr->jpg_que_head != zr->jpg_que_tail) {
 			/* Start the jpeg codec when the first frame is queued  */
@@ -2711,12 +2696,13 @@
 	struct zoran_fh *fh = __fh;
 	struct zoran *zr = fh->zr;
 	int i, res = 0;
+	unsigned long flags;
 
 	mutex_lock(&zr->resource_lock);
 
 	switch (fh->map_mode) {
 	case ZORAN_MAP_MODE_RAW:	/* raw capture */
-		if (fh->v4l_buffers.active == ZORAN_FREE &&
+		if (fh->buffers.active == ZORAN_FREE &&
 		    zr->v4l_buffers.active != ZORAN_FREE) {
 			res = -EPERM;	/* stay off other's settings! */
 			goto strmoff_unlock_and_return;
@@ -2724,30 +2710,30 @@
 		if (zr->v4l_buffers.active == ZORAN_FREE)
 			goto strmoff_unlock_and_return;
 
+		spin_lock_irqsave(&zr->spinlock, flags);
 		/* unload capture */
 		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++)
+		for (i = 0; i < fh->buffers.num_buffers; i++)
 			zr->v4l_buffers.buffer[i].state = BUZ_STATE_USER;
-		fh->v4l_buffers = zr->v4l_buffers;
+		fh->buffers = zr->v4l_buffers;
 
-		zr->v4l_buffers.active = fh->v4l_buffers.active = ZORAN_FREE;
+		zr->v4l_buffers.active = fh->buffers.active = ZORAN_FREE;
 
 		zr->v4l_grab_seq = 0;
 		zr->v4l_pend_head = zr->v4l_pend_tail = 0;
 		zr->v4l_sync_tail = 0;
 
+		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 &&
+		if (fh->buffers.active == ZORAN_FREE &&
 		    zr->jpg_buffers.active != ZORAN_FREE) {
 			res = -EPERM;	/* stay off other's settings! */
 			goto strmoff_unlock_and_return;
@@ -3016,7 +3002,7 @@
 
 	mutex_lock(&zr->resource_lock);
 
-	if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) {
+	if (fh->buffers.allocated) {
 		dprintk(1, KERN_ERR
 			"%s: VIDIOC_S_CROP - cannot change settings while active\n",
 			ZR_DEVNAME(zr));
@@ -3094,8 +3080,7 @@
 
 	mutex_lock(&zr->resource_lock);
 
-	if (fh->v4l_buffers.active != ZORAN_FREE ||
-	    fh->jpg_buffers.active != ZORAN_FREE) {
+	if (fh->buffers.active != ZORAN_FREE) {
 		dprintk(1, KERN_WARNING
 			"%s: VIDIOC_S_JPEGCOMP called while in playback/capture mode\n",
 			ZR_DEVNAME(zr));
@@ -3106,9 +3091,9 @@
 	res = zoran_check_jpg_settings(zr, &settings, 0);
 	if (res)
 		goto sjpegc_unlock_and_return;
-	if (!fh->jpg_buffers.allocated)
-		fh->jpg_buffers.buffer_size =
-		    zoran_v4l2_calc_bufsize(&fh->jpg_settings);
+	if (!fh->buffers.allocated)
+		fh->buffers.buffer_size =
+			zoran_v4l2_calc_bufsize(&fh->jpg_settings);
 	fh->jpg_settings.jpg_comp = *params = settings.jpg_comp;
 sjpegc_unlock_and_return:
 	mutex_unlock(&zr->resource_lock);
@@ -3145,11 +3130,11 @@
 			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,
+			"FAL"[fh->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 &&
+		if (fh->buffers.active != ZORAN_FREE &&
 		    /* Buffer ready to DQBUF? */
 		    zr->v4l_buffers.buffer[frame].state == BUZ_STATE_DONE)
 			res = POLLIN | POLLRDNORM;
@@ -3167,10 +3152,10 @@
 			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,
+			"FAL"[fh->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 &&
+		if (fh->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;
@@ -3224,87 +3209,49 @@
 	struct zoran *zr = fh->zr;
 	int i;
 
-	map->count--;
-	if (map->count == 0) {
-		switch (fh->map_mode) {
-		case ZORAN_MAP_MODE_JPG_REC:
-		case ZORAN_MAP_MODE_JPG_PLAY:
+	if (--map->count > 0)
+		return;
 
-			dprintk(3, KERN_INFO "%s: munmap(MJPEG)\n",
-				ZR_DEVNAME(zr));
+	dprintk(3, KERN_INFO "%s: %s - munmap(%s)\n", ZR_DEVNAME(zr),
+		__func__, mode_name(fh->map_mode));
 
-			for (i = 0; i < fh->jpg_buffers.num_buffers; i++) {
-				if (fh->jpg_buffers.buffer[i].map == map) {
-					fh->jpg_buffers.buffer[i].map =
-					    NULL;
-				}
-			}
-			kfree(map);
-
-			for (i = 0; i < fh->jpg_buffers.num_buffers; i++)
-				if (fh->jpg_buffers.buffer[i].map)
-					break;
-			if (i == fh->jpg_buffers.num_buffers) {
-				mutex_lock(&zr->resource_lock);
-
-				if (fh->jpg_buffers.active != ZORAN_FREE) {
-					jpg_qbuf(file, -1, zr->codec_mode);
-					zr->jpg_buffers.allocated = 0;
-					zr->jpg_buffers.active =
-					    fh->jpg_buffers.active =
-					    ZORAN_FREE;
-				}
-				jpg_fbuffer_free(file);
-				mutex_unlock(&zr->resource_lock);
-			}
-
-			break;
-
-		case ZORAN_MAP_MODE_RAW:
-
-			dprintk(3, KERN_INFO "%s: munmap(V4L)\n",
-				ZR_DEVNAME(zr));
-
-			for (i = 0; i < fh->v4l_buffers.num_buffers; i++) {
-				if (fh->v4l_buffers.buffer[i].map == map) {
-					/* unqueue/unmap */
-					fh->v4l_buffers.buffer[i].map =
-					    NULL;
-				}
-			}
-			kfree(map);
-
-			for (i = 0; i < fh->v4l_buffers.num_buffers; i++)
-				if (fh->v4l_buffers.buffer[i].map)
-					break;
-			if (i == fh->v4l_buffers.num_buffers) {
-				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);
-				mutex_unlock(&zr->resource_lock);
-			}
-
-			break;
-
-		default:
-			printk(KERN_ERR
-			       "%s: munmap() - internal error - unknown map mode %d\n",
-			       ZR_DEVNAME(zr), fh->map_mode);
-			break;
-
-		}
+	for (i = 0; i < fh->buffers.num_buffers; i++) {
+		if (fh->buffers.buffer[i].map == map)
+			fh->buffers.buffer[i].map = NULL;
 	}
+	kfree(map);
+
+	/* Any buffers still mapped? */
+	for (i = 0; i < fh->buffers.num_buffers; i++)
+		if (fh->buffers.buffer[i].map)
+			return;
+
+	dprintk(3, KERN_INFO "%s: %s - free %s buffers\n", ZR_DEVNAME(zr),
+		__func__, mode_name(fh->map_mode));
+
+	mutex_lock(&zr->resource_lock);
+
+	if (fh->map_mode == ZORAN_MAP_MODE_RAW) {
+		if (fh->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->buffers.active = ZORAN_FREE;
+			spin_unlock_irqrestore(&zr->spinlock, flags);
+		}
+		v4l_fbuffer_free(file);
+	} else {
+		if (fh->buffers.active != ZORAN_FREE) {
+			jpg_qbuf(file, -1, zr->codec_mode);
+			zr->jpg_buffers.allocated = 0;
+			zr->jpg_buffers.active = fh->buffers.active = ZORAN_FREE;
+		}
+		jpg_fbuffer_free(file);
+	}
+
+	mutex_unlock(&zr->resource_lock);
 }
 
 static struct vm_operations_struct zoran_vm_ops = {
@@ -3329,8 +3276,7 @@
 	dprintk(3,
 		KERN_INFO "%s: mmap(%s) of 0x%08lx-0x%08lx (size=%lu)\n",
 		ZR_DEVNAME(zr),
-		fh->map_mode == ZORAN_MAP_MODE_RAW ? "V4L" : "MJPEG",
-		vma->vm_start, vma->vm_end, size);
+		mode_name(fh->map_mode), vma->vm_start, vma->vm_end, size);
 
 	if (!(vma->vm_flags & VM_SHARED) || !(vma->vm_flags & VM_READ) ||
 	    !(vma->vm_flags & VM_WRITE)) {
@@ -3341,76 +3287,93 @@
 		return -EINVAL;
 	}
 
-	switch (fh->map_mode) {
+	mutex_lock(&zr->resource_lock);
 
-	case ZORAN_MAP_MODE_JPG_REC:
-	case ZORAN_MAP_MODE_JPG_PLAY:
+	if (!fh->buffers.allocated) {
+		dprintk(1,
+			KERN_ERR
+			"%s: zoran_mmap(%s) - buffers not yet allocated\n",
+			ZR_DEVNAME(zr), mode_name(fh->map_mode));
+		res = -ENOMEM;
+		goto mmap_unlock_and_return;
+	}
 
-		/* lock */
-		mutex_lock(&zr->resource_lock);
+	first = offset / fh->buffers.buffer_size;
+	last = first - 1 + size / fh->buffers.buffer_size;
+	if (offset % fh->buffers.buffer_size != 0 ||
+	    size % fh->buffers.buffer_size != 0 || first < 0 ||
+	    last < 0 || first >= fh->buffers.num_buffers ||
+	    last >= fh->buffers.buffer_size) {
+		dprintk(1,
+			KERN_ERR
+			"%s: mmap(%s) - offset=%lu or size=%lu invalid for bufsize=%d and numbufs=%d\n",
+			ZR_DEVNAME(zr), mode_name(fh->map_mode), offset, size,
+			fh->buffers.buffer_size,
+			fh->buffers.num_buffers);
+		res = -EINVAL;
+		goto mmap_unlock_and_return;
+	}
 
-		/* Map the MJPEG buffers */
-		if (!fh->jpg_buffers.allocated) {
+	/* Check if any buffers are already mapped */
+	for (i = first; i <= last; i++) {
+		if (fh->buffers.buffer[i].map) {
 			dprintk(1,
 				KERN_ERR
-				"%s: zoran_mmap(MJPEG) - buffers not yet allocated\n",
-				ZR_DEVNAME(zr));
-			res = -ENOMEM;
-			goto jpg_mmap_unlock_and_return;
+				"%s: mmap(%s) - buffer %d already mapped\n",
+				ZR_DEVNAME(zr), mode_name(fh->map_mode), i);
+			res = -EBUSY;
+			goto mmap_unlock_and_return;
 		}
+	}
 
-		first = offset / fh->jpg_buffers.buffer_size;
-		last = first - 1 + size / fh->jpg_buffers.buffer_size;
-		if (offset % fh->jpg_buffers.buffer_size != 0 ||
-		    size % fh->jpg_buffers.buffer_size != 0 || first < 0 ||
-		    last < 0 || first >= fh->jpg_buffers.num_buffers ||
-		    last >= fh->jpg_buffers.num_buffers) {
-			dprintk(1,
-				KERN_ERR
-				"%s: mmap(MJPEG) - offset=%lu or size=%lu invalid for bufsize=%d and numbufs=%d\n",
-				ZR_DEVNAME(zr), offset, size,
-				fh->jpg_buffers.buffer_size,
-				fh->jpg_buffers.num_buffers);
-			res = -EINVAL;
-			goto jpg_mmap_unlock_and_return;
-		}
+	/* map these buffers */
+	map = kmalloc(sizeof(struct zoran_mapping), GFP_KERNEL);
+	if (!map) {
+		res = -ENOMEM;
+		goto mmap_unlock_and_return;
+	}
+	map->file = file;
+	map->count = 1;
+
+	vma->vm_ops = &zoran_vm_ops;
+	vma->vm_flags |= VM_DONTEXPAND;
+	vma->vm_private_data = map;
+
+	if (fh->map_mode == ZORAN_MAP_MODE_RAW) {
 		for (i = first; i <= last; i++) {
-			if (fh->jpg_buffers.buffer[i].map) {
+			todo = size;
+			if (todo > fh->buffers.buffer_size)
+				todo = fh->buffers.buffer_size;
+			page = fh->buffers.buffer[i].v4l.fbuffer_phys;
+			if (remap_pfn_range(vma, start, page >> PAGE_SHIFT,
+							todo, PAGE_SHARED)) {
 				dprintk(1,
 					KERN_ERR
-					"%s: mmap(MJPEG) - buffer %d already mapped\n",
-					ZR_DEVNAME(zr), i);
-				res = -EBUSY;
-				goto jpg_mmap_unlock_and_return;
+					"%s: zoran_mmap(V4L) - remap_pfn_range failed\n",
+					ZR_DEVNAME(zr));
+				res = -EAGAIN;
+				goto mmap_unlock_and_return;
 			}
+			size -= todo;
+			start += todo;
+			fh->buffers.buffer[i].map = map;
+			if (size == 0)
+				break;
 		}
-
-		/* map these buffers (v4l_buffers[i]) */
-		map = kmalloc(sizeof(struct zoran_mapping), GFP_KERNEL);
-		if (!map) {
-			res = -ENOMEM;
-			goto jpg_mmap_unlock_and_return;
-		}
-		map->file = file;
-		map->count = 1;
-
-		vma->vm_ops = &zoran_vm_ops;
-		vma->vm_flags |= VM_DONTEXPAND;
-		vma->vm_private_data = map;
-
+	} else {
 		for (i = first; i <= last; i++) {
 			for (j = 0;
-			     j < fh->jpg_buffers.buffer_size / PAGE_SIZE;
+			     j < fh->buffers.buffer_size / PAGE_SIZE;
 			     j++) {
 				fraglen =
-				    (le32_to_cpu(fh->jpg_buffers.buffer[i].
+				    (le32_to_cpu(fh->buffers.buffer[i].jpg.
 				     frag_tab[2 * j + 1]) & ~1) << 1;
 				todo = size;
 				if (todo > fraglen)
 					todo = fraglen;
 				pos =
-				    le32_to_cpu(fh->jpg_buffers.
-				    buffer[i].frag_tab[2 * j]);
+				    le32_to_cpu(fh->buffers.
+				    buffer[i].jpg.frag_tab[2 * j]);
 				/* should just be pos on i386 */
 				page = virt_to_phys(bus_to_virt(pos))
 								>> PAGE_SHIFT;
@@ -3421,112 +3384,26 @@
 						"%s: zoran_mmap(V4L) - remap_pfn_range failed\n",
 						ZR_DEVNAME(zr));
 					res = -EAGAIN;
-					goto jpg_mmap_unlock_and_return;
+					goto mmap_unlock_and_return;
 				}
 				size -= todo;
 				start += todo;
 				if (size == 0)
 					break;
-				if (le32_to_cpu(fh->jpg_buffers.buffer[i].
+				if (le32_to_cpu(fh->buffers.buffer[i].jpg.
 				    frag_tab[2 * j + 1]) & 1)
 					break;	/* was last fragment */
 			}
-			fh->jpg_buffers.buffer[i].map = map;
+			fh->buffers.buffer[i].map = map;
 			if (size == 0)
 				break;
 
 		}
-	jpg_mmap_unlock_and_return:
-		mutex_unlock(&zr->resource_lock);
-
-		break;
-
-	case ZORAN_MAP_MODE_RAW:
-
-		mutex_lock(&zr->resource_lock);
-
-		/* Map the V4L buffers */
-		if (!fh->v4l_buffers.allocated) {
-			dprintk(1,
-				KERN_ERR
-				"%s: zoran_mmap(V4L) - buffers not yet allocated\n",
-				ZR_DEVNAME(zr));
-			res = -ENOMEM;
-			goto v4l_mmap_unlock_and_return;
-		}
-
-		first = offset / fh->v4l_buffers.buffer_size;
-		last = first - 1 + size / fh->v4l_buffers.buffer_size;
-		if (offset % fh->v4l_buffers.buffer_size != 0 ||
-		    size % fh->v4l_buffers.buffer_size != 0 || first < 0 ||
-		    last < 0 || first >= fh->v4l_buffers.num_buffers ||
-		    last >= fh->v4l_buffers.buffer_size) {
-			dprintk(1,
-				KERN_ERR
-				"%s: mmap(V4L) - offset=%lu or size=%lu invalid for bufsize=%d and numbufs=%d\n",
-				ZR_DEVNAME(zr), offset, size,
-				fh->v4l_buffers.buffer_size,
-				fh->v4l_buffers.num_buffers);
-			res = -EINVAL;
-			goto v4l_mmap_unlock_and_return;
-		}
-		for (i = first; i <= last; i++) {
-			if (fh->v4l_buffers.buffer[i].map) {
-				dprintk(1,
-					KERN_ERR
-					"%s: mmap(V4L) - buffer %d already mapped\n",
-					ZR_DEVNAME(zr), i);
-				res = -EBUSY;
-				goto v4l_mmap_unlock_and_return;
-			}
-		}
-
-		/* map these buffers (v4l_buffers[i]) */
-		map = kmalloc(sizeof(struct zoran_mapping), GFP_KERNEL);
-		if (!map) {
-			res = -ENOMEM;
-			goto v4l_mmap_unlock_and_return;
-		}
-		map->file = file;
-		map->count = 1;
-
-		vma->vm_ops = &zoran_vm_ops;
-		vma->vm_flags |= VM_DONTEXPAND;
-		vma->vm_private_data = map;
-
-		for (i = first; i <= last; i++) {
-			todo = size;
-			if (todo > fh->v4l_buffers.buffer_size)
-				todo = fh->v4l_buffers.buffer_size;
-			page = fh->v4l_buffers.buffer[i].fbuffer_phys;
-			if (remap_pfn_range(vma, start, page >> PAGE_SHIFT,
-							todo, PAGE_SHARED)) {
-				dprintk(1,
-					KERN_ERR
-					"%s: zoran_mmap(V4L)i - remap_pfn_range failed\n",
-					ZR_DEVNAME(zr));
-				res = -EAGAIN;
-				goto v4l_mmap_unlock_and_return;
-			}
-			size -= todo;
-			start += todo;
-			fh->v4l_buffers.buffer[i].map = map;
-			if (size == 0)
-				break;
-		}
-	v4l_mmap_unlock_and_return:
-		mutex_unlock(&zr->resource_lock);
-
-		break;
-
-	default:
-		dprintk(1,
-			KERN_ERR
-			"%s: zoran_mmap() - internal error - unknown map mode %d\n",
-			ZR_DEVNAME(zr), fh->map_mode);
-		break;
 	}
 
+mmap_unlock_and_return:
+	mutex_unlock(&zr->resource_lock);
+
 	return 0;
 }