From: Michael Hunold <hunold@linuxtv.org>

- [DVB] fix videodev has no release callback

- [DVB] use PAGE_SIZE for pagetables, not home-brewn SAA7146_PGTABLE_SIZE

- [DVB] use cpu_to_le32() at various places for endianess independency

- [DVB] turn some error checks into BUG()s

- [DVB] make saa7146_i2c_adapter_prepare() support an adapter class

- [DVB] add support for V4L2_PIX_FMT_RGB32 pixelformat

- [DVB] replace generic saa7146 i2c name by card specific name, suggested by
  Uli Luckas <luckas@musoft.de>

Signed-off-by: Michael Hunold <hunold@linuxtv.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/media/common/saa7146_core.c  |   14 ++-----
 25-akpm/drivers/media/common/saa7146_fops.c  |   54 ++++++++++++++-------------
 25-akpm/drivers/media/common/saa7146_hlp.c   |   17 ++++----
 25-akpm/drivers/media/common/saa7146_i2c.c   |    6 +--
 25-akpm/drivers/media/common/saa7146_video.c |    9 ++++
 25-akpm/include/media/saa7146.h              |    2 -
 25-akpm/include/media/saa7146_vv.h           |    5 +-
 7 files changed, 56 insertions(+), 51 deletions(-)

diff -puN drivers/media/common/saa7146_core.c~DVB-update-saa7146 drivers/media/common/saa7146_core.c
--- 25/drivers/media/common/saa7146_core.c~DVB-update-saa7146	2004-09-20 11:22:24.684898288 -0700
+++ 25-akpm/drivers/media/common/saa7146_core.c	2004-09-20 11:22:24.697896312 -0700
@@ -133,8 +133,6 @@ static struct scatterlist* vmalloc_to_sg
 /********************************************************************************/
 /* common page table functions */
 
-#define SAA7146_PGTABLE_SIZE 4096
-
 char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt)
 {
 	int pages = (length+PAGE_SIZE-1)/PAGE_SIZE;
@@ -182,11 +180,11 @@ int saa7146_pgtable_alloc(struct pci_dev
         u32          *cpu;
         dma_addr_t   dma_addr;
 
-	cpu = pci_alloc_consistent(pci, SAA7146_PGTABLE_SIZE, &dma_addr);
+	cpu = pci_alloc_consistent(pci, PAGE_SIZE, &dma_addr);
 	if (NULL == cpu) {
 		return -ENOMEM;
 	}
-	pt->size = SAA7146_PGTABLE_SIZE;
+	pt->size = PAGE_SIZE;
 	pt->cpu  = cpu;
 	pt->dma  = dma_addr;
 
@@ -201,11 +199,7 @@ int saa7146_pgtable_build_single(struct 
 	int   i,p;
 
 	BUG_ON( 0 == sglen);
-
-	if (list->offset > PAGE_SIZE) {
-		DEB_D(("offset > PAGE_SIZE. this should not happen."));
-		return -EINVAL;
-	}
+	BUG_ON(list->offset > PAGE_SIZE);
 	
 	/* if we have a user buffer, the first page may not be
 	   aligned to a page boundary. */
@@ -217,7 +211,7 @@ int saa7146_pgtable_build_single(struct 
 		printk("i:%d, adr:0x%08x, len:%d, offset:%d\n", i,sg_dma_address(list), sg_dma_len(list), list->offset);
 */
 		for (p = 0; p * 4096 < list->length; p++, ptr++) {
-			*ptr = sg_dma_address(list) + p * 4096;
+			*ptr = cpu_to_le32(sg_dma_address(list) + p * 4096);
 			nr_pages++;
 		}
 	}
diff -puN drivers/media/common/saa7146_fops.c~DVB-update-saa7146 drivers/media/common/saa7146_fops.c
--- 25/drivers/media/common/saa7146_fops.c~DVB-update-saa7146	2004-09-20 11:22:24.686897984 -0700
+++ 25-akpm/drivers/media/common/saa7146_fops.c	2004-09-20 11:22:24.698896160 -0700
@@ -88,10 +88,7 @@ int saa7146_buffer_queue(struct saa7146_
 #endif
 	DEB_EE(("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf));
 
-	if( NULL == q ) {
-		ERR(("internal error: fatal NULL pointer for q.\n"));
-		return 0;
-	}
+	BUG_ON(!q);
 
 	if (NULL == q->curr) {
 		q->curr = buf;
@@ -112,14 +109,11 @@ void saa7146_buffer_finish(struct saa714
 #ifdef DEBUG_SPINLOCKS
 	BUG_ON(!spin_is_locked(&dev->slock));
 #endif
-	if( NULL == q->curr ) {
-		ERR(("internal error: fatal NULL pointer for q->curr.\n"));
-		return;
-	}
-
 	DEB_EE(("dev:%p, dmaq:%p, state:%d\n", dev, q, state));
 	DEB_EE(("q->curr:%p\n",q->curr));
 
+	BUG_ON(!q->curr);
+
 	/* finish current buffer */
 	if (NULL == q->curr) {
 		DEB_D(("aiii. no current buffer\n"));
@@ -138,10 +132,7 @@ void saa7146_buffer_next(struct saa7146_
 {
 	struct saa7146_buf *buf,*next = NULL;
 
-	if( NULL == q ) {
-		ERR(("internal error: fatal NULL pointer for q.\n"));
-		return;
-	}
+	BUG_ON(!q);
 
 	DEB_INT(("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi));
 
@@ -515,45 +506,58 @@ int saa7146_vv_release(struct saa7146_de
 	return 0;
 }
 
-int saa7146_register_device(struct video_device *vid, struct saa7146_dev* dev, char *name, int type)
+int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
+			    char *name, int type)
 {
 	struct saa7146_vv *vv = dev->vv_data;
+	struct video_device *vfd;
 
 	DEB_EE(("dev:%p, name:'%s', type:%d\n",dev,name,type));
  
- 	*vid = device_template;
-	strlcpy(vid->name, name, sizeof(vid->name));
-	vid->priv = dev;
+	// released by vfd->release
+ 	vfd = video_device_alloc();
+	if (vfd == NULL)
+		return -ENOMEM;
+
+	memcpy(vfd, &device_template, sizeof(struct video_device));
+	strlcpy(vfd->name, name, sizeof(vfd->name));
+	vfd->release = video_device_release;
+	vfd->priv = dev;
 
 	// fixme: -1 should be an insmod parameter *for the extension* (like "video_nr");
-	if (video_register_device(vid,type,-1) < 0) {
+	if (video_register_device(vfd, type, -1) < 0) {
 		ERR(("cannot register v4l2 device. skipping.\n"));
 		return -1;
 	}
 
 	if( VFL_TYPE_GRABBER == type ) {
-		vv->video_minor = vid->minor;
-		INFO(("%s: registered device video%d [v4l2]\n", dev->name,vid->minor & 0x1f));
+		vv->video_minor = vfd->minor;
+		INFO(("%s: registered device video%d [v4l2]\n",
+			dev->name, vfd->minor & 0x1f));
 	} else {
-		vv->vbi_minor = vid->minor;
-		INFO(("%s: registered device vbi%d [v4l2]\n", dev->name,vid->minor & 0x1f));
+		vv->vbi_minor = vfd->minor;
+		INFO(("%s: registered device vbi%d [v4l2]\n",
+			dev->name, vfd->minor & 0x1f));
 	}
 
+	*vid = vfd;
 	return 0;
 }
 
-int saa7146_unregister_device(struct video_device *vid, struct saa7146_dev* dev)
+int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev)
 {
 	struct saa7146_vv *vv = dev->vv_data;
 	
 	DEB_EE(("dev:%p\n",dev));
 
-	if( VFL_TYPE_GRABBER == vid->type ) {
+	if( VFL_TYPE_GRABBER == (*vid)->type ) {
 		vv->video_minor = -1;
 	} else {
 		vv->vbi_minor = -1;
 	}
-	video_unregister_device(vid);
+
+	video_unregister_device(*vid);
+	*vid = NULL;
 
 	return 0;
 }
diff -puN drivers/media/common/saa7146_hlp.c~DVB-update-saa7146 drivers/media/common/saa7146_hlp.c
--- 25/drivers/media/common/saa7146_hlp.c~DVB-update-saa7146	2004-09-20 11:22:24.687897832 -0700
+++ 25-akpm/drivers/media/common/saa7146_hlp.c	2004-09-20 11:22:24.699896008 -0700
@@ -413,10 +413,10 @@ static void calculate_clipping_registers
 
 	/* fill up cliptable */
 	for(i = 0; i < cnt_pixel; i++) {
-		clipping[2*i] |= (pixel_list[i] << 16);
+		clipping[2*i] |= cpu_to_le32(pixel_list[i] << 16);
 	}
 	for(i = 0; i < cnt_line; i++) {
-		clipping[(2*i)+1] |= (line_list[i] << 16);
+		clipping[(2*i)+1] |= cpu_to_le32(line_list[i] << 16);
 	}
 
 	/* fill up cliptable with the display infos */
@@ -430,7 +430,7 @@ static void calculate_clipping_registers
 			if( pixel_list[i] < (x[j] + w[j])) {
 			
 				if ( pixel_list[i] >= x[j] ) {
-					clipping[2*i] |= (1 << j);			
+					clipping[2*i] |= cpu_to_le32(1 << j);
 				}
 			}
 		}
@@ -442,7 +442,7 @@ static void calculate_clipping_registers
 			if( line_list[i] < (y[j] + h[j]) ) {
 
 				if( line_list[i] >= y[j] ) {
-					clipping[(2*i)+1] |= (1 << j);			
+					clipping[(2*i)+1] |= cpu_to_le32(1 << j);
 				}
 			}
 		}
@@ -560,9 +560,10 @@ static void saa7146_set_window(struct sa
 }
 
 /* calculate the new memory offsets for a desired position */
-static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field)
+static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field, u32 pixelformat)
 {	
 	struct saa7146_vv *vv = dev->vv_data;
+	struct saa7146_format *sfmt = format_by_fourcc(dev, pixelformat);
 
 	int b_depth = vv->ov_fmt->depth;
 	int b_bpl = vv->ov_fb.fmt.bytesperline;
@@ -601,7 +602,7 @@ static void saa7146_set_position(struct 
 		vdma1.pitch *= -1;
 	}
 		
-	vdma1.base_page = 0;
+	vdma1.base_page = sfmt->swap;
 	vdma1.num_line_byte = (vv->standard->v_field<<16)+vv->standard->h_pixels;
 
 	saa7146_write_out_dma(dev, 1, &vdma1);
@@ -657,7 +658,7 @@ int saa7146_enable_overlay(struct saa714
 	struct saa7146_vv *vv = dev->vv_data;
 
 	saa7146_set_window(dev, fh->ov.win.w.width, fh->ov.win.w.height, fh->ov.win.field);
-	saa7146_set_position(dev, fh->ov.win.w.left, fh->ov.win.w.top, fh->ov.win.w.height, fh->ov.win.field);
+	saa7146_set_position(dev, fh->ov.win.w.left, fh->ov.win.w.top, fh->ov.win.w.height, fh->ov.win.field, vv->ov_fmt->pixelformat);
 	saa7146_set_output_format(dev, vv->ov_fmt->trans);
 	saa7146_set_clipping_rect(fh);
 
@@ -727,7 +728,7 @@ static int calculate_video_dma_grab_pack
 	vdma1.pitch		= (width*depth*2)/8;
 	}
 	vdma1.num_line_byte	= ((vv->standard->v_field<<16) + vv->standard->h_pixels);
-	vdma1.base_page		= buf->pt[0].dma | ME1;
+	vdma1.base_page		= buf->pt[0].dma | ME1 | sfmt->swap;
 	
 	if( 0 != vv->vflip ) {
 		vdma1.prot_addr	= buf->pt[0].offset;
diff -puN drivers/media/common/saa7146_i2c.c~DVB-update-saa7146 drivers/media/common/saa7146_i2c.c
--- 25/drivers/media/common/saa7146_i2c.c~DVB-update-saa7146	2004-09-20 11:22:24.688897680 -0700
+++ 25-akpm/drivers/media/common/saa7146_i2c.c	2004-09-20 11:22:24.700895856 -0700
@@ -393,7 +393,7 @@ static struct i2c_algorithm saa7146_algo
 	.functionality	= saa7146_i2c_func,
 };
 
-int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, unsigned int class, u32 bitrate)
+int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate)
 {
 	DEB_EE(("bitrate: 0x%08x\n",bitrate));
 	
@@ -404,13 +404,11 @@ int saa7146_i2c_adapter_prepare(struct s
 	saa7146_i2c_reset(dev);
 
 	if( NULL != i2c_adapter ) {
-		memset(i2c_adapter,0,sizeof(struct i2c_adapter));
-		strcpy(i2c_adapter->name, dev->name);	
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
 		i2c_adapter->data = dev;
 #else
+		BUG_ON(!i2c_adapter->class);
 		i2c_set_adapdata(i2c_adapter,dev);
-		i2c_adapter->class = class;
 #endif
 		i2c_adapter->algo	   = &saa7146_algo;
 		i2c_adapter->algo_data     = NULL;
diff -puN drivers/media/common/saa7146_video.c~DVB-update-saa7146 drivers/media/common/saa7146_video.c
--- 25/drivers/media/common/saa7146_video.c~DVB-update-saa7146	2004-09-20 11:22:24.690897376 -0700
+++ 25-akpm/drivers/media/common/saa7146_video.c	2004-09-20 11:22:24.701895704 -0700
@@ -38,6 +38,13 @@ static struct saa7146_format formats[] =
 		.depth		= 32,
 		.flags		= 0,
 	}, {
+		.name 		= "RGB-32 (R-G-B)",
+		.pixelformat	= V4L2_PIX_FMT_RGB32,
+		.trans 		= RGB32_COMPOSED,
+		.depth		= 32,
+		.flags		= 0,
+		.swap		= 0x2,
+	}, {
 		.name 		= "Greyscale-8",
 		.pixelformat	= V4L2_PIX_FMT_GREY,
 		.trans 		= Y8,
@@ -634,7 +641,7 @@ static int saa7146_pgtable_build(struct 
 		/* walk all pages, copy all page addresses to ptr1 */
 		for (i = 0; i < length; i++, list++) {
 			for (p = 0; p * 4096 < list->length; p++, ptr1++) {
-				*ptr1 = sg_dma_address(list) - list->offset;
+				*ptr1 = cpu_to_le32(sg_dma_address(list) - list->offset);
 			}
 		}
 /*
diff -puN include/media/saa7146.h~DVB-update-saa7146 include/media/saa7146.h
--- 25/include/media/saa7146.h~DVB-update-saa7146	2004-09-20 11:22:24.692897072 -0700
+++ 25-akpm/include/media/saa7146.h	2004-09-20 11:22:24.702895552 -0700
@@ -154,7 +154,7 @@ struct saa7146_dev
 };
 
 /* from saa7146_i2c.c */
-int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, unsigned int class, u32 bitrate);
+int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate);
 int saa7146_i2c_transfer(struct saa7146_dev *saa, const struct i2c_msg msgs[], int num,  int retries);
 
 /* from saa7146_core.c */
diff -puN include/media/saa7146_vv.h~DVB-update-saa7146 include/media/saa7146_vv.h
--- 25/include/media/saa7146_vv.h~DVB-update-saa7146	2004-09-20 11:22:24.693896920 -0700
+++ 25-akpm/include/media/saa7146_vv.h	2004-09-20 11:22:24.703895400 -0700
@@ -35,6 +35,7 @@ struct saa7146_format {
 	u32	trans;
 	u8	depth;
 	u8	flags;
+	u8	swap;
 };
 
 struct saa7146_standard
@@ -188,8 +189,8 @@ struct saa7146_use_ops  {
 };
 
 /* from saa7146_fops.c */
-int saa7146_register_device(struct video_device *vid, struct saa7146_dev* dev, char *name, int type);
-int saa7146_unregister_device(struct video_device *vid, struct saa7146_dev* dev);
+int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, char *name, int type);
+int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev);
 void saa7146_buffer_finish(struct saa7146_dev *dev, struct saa7146_dmaqueue *q, int state);
 void saa7146_buffer_next(struct saa7146_dev *dev, struct saa7146_dmaqueue *q,int vbi);
 int saa7146_buffer_queue(struct saa7146_dev *dev, struct saa7146_dmaqueue *q, struct saa7146_buf *buf);
_