Commit 2da8c87f authored by Michael Hunold's avatar Michael Hunold Committed by Linus Torvalds

[PATCH] DVB: update saa7146

- [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: default avatarMichael Hunold <hunold@linuxtv.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 8c4accad
...@@ -133,8 +133,6 @@ static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages) ...@@ -133,8 +133,6 @@ static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages)
/********************************************************************************/ /********************************************************************************/
/* common page table functions */ /* common page table functions */
#define SAA7146_PGTABLE_SIZE 4096
char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt) char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt)
{ {
int pages = (length+PAGE_SIZE-1)/PAGE_SIZE; int pages = (length+PAGE_SIZE-1)/PAGE_SIZE;
...@@ -182,11 +180,11 @@ int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt) ...@@ -182,11 +180,11 @@ int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
u32 *cpu; u32 *cpu;
dma_addr_t dma_addr; 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) { if (NULL == cpu) {
return -ENOMEM; return -ENOMEM;
} }
pt->size = SAA7146_PGTABLE_SIZE; pt->size = PAGE_SIZE;
pt->cpu = cpu; pt->cpu = cpu;
pt->dma = dma_addr; pt->dma = dma_addr;
...@@ -201,11 +199,7 @@ int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt ...@@ -201,11 +199,7 @@ int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt
int i,p; int i,p;
BUG_ON( 0 == sglen); BUG_ON( 0 == sglen);
BUG_ON(list->offset > PAGE_SIZE);
if (list->offset > PAGE_SIZE) {
DEB_D(("offset > PAGE_SIZE. this should not happen."));
return -EINVAL;
}
/* if we have a user buffer, the first page may not be /* if we have a user buffer, the first page may not be
aligned to a page boundary. */ aligned to a page boundary. */
...@@ -217,7 +211,7 @@ int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt ...@@ -217,7 +211,7 @@ int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt
printk("i:%d, adr:0x%08x, len:%d, offset:%d\n", i,sg_dma_address(list), sg_dma_len(list), list->offset); 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++) { 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++; nr_pages++;
} }
} }
......
...@@ -88,10 +88,7 @@ int saa7146_buffer_queue(struct saa7146_dev *dev, ...@@ -88,10 +88,7 @@ int saa7146_buffer_queue(struct saa7146_dev *dev,
#endif #endif
DEB_EE(("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf)); DEB_EE(("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf));
if( NULL == q ) { BUG_ON(!q);
ERR(("internal error: fatal NULL pointer for q.\n"));
return 0;
}
if (NULL == q->curr) { if (NULL == q->curr) {
q->curr = buf; q->curr = buf;
...@@ -112,14 +109,11 @@ void saa7146_buffer_finish(struct saa7146_dev *dev, ...@@ -112,14 +109,11 @@ void saa7146_buffer_finish(struct saa7146_dev *dev,
#ifdef DEBUG_SPINLOCKS #ifdef DEBUG_SPINLOCKS
BUG_ON(!spin_is_locked(&dev->slock)); BUG_ON(!spin_is_locked(&dev->slock));
#endif #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(("dev:%p, dmaq:%p, state:%d\n", dev, q, state));
DEB_EE(("q->curr:%p\n",q->curr)); DEB_EE(("q->curr:%p\n",q->curr));
BUG_ON(!q->curr);
/* finish current buffer */ /* finish current buffer */
if (NULL == q->curr) { if (NULL == q->curr) {
DEB_D(("aiii. no current buffer\n")); DEB_D(("aiii. no current buffer\n"));
...@@ -138,10 +132,7 @@ void saa7146_buffer_next(struct saa7146_dev *dev, ...@@ -138,10 +132,7 @@ void saa7146_buffer_next(struct saa7146_dev *dev,
{ {
struct saa7146_buf *buf,*next = NULL; struct saa7146_buf *buf,*next = NULL;
if( NULL == q ) { BUG_ON(!q);
ERR(("internal error: fatal NULL pointer for q.\n"));
return;
}
DEB_INT(("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi)); DEB_INT(("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi));
...@@ -515,45 +506,58 @@ int saa7146_vv_release(struct saa7146_dev* dev) ...@@ -515,45 +506,58 @@ int saa7146_vv_release(struct saa7146_dev* dev)
return 0; 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 saa7146_vv *vv = dev->vv_data;
struct video_device *vfd;
DEB_EE(("dev:%p, name:'%s', type:%d\n",dev,name,type)); DEB_EE(("dev:%p, name:'%s', type:%d\n",dev,name,type));
*vid = device_template; // released by vfd->release
strlcpy(vid->name, name, sizeof(vid->name)); vfd = video_device_alloc();
vid->priv = dev; 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"); // 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")); ERR(("cannot register v4l2 device. skipping.\n"));
return -1; return -1;
} }
if( VFL_TYPE_GRABBER == type ) { if( VFL_TYPE_GRABBER == type ) {
vv->video_minor = vid->minor; vv->video_minor = vfd->minor;
INFO(("%s: registered device video%d [v4l2]\n", dev->name,vid->minor & 0x1f)); INFO(("%s: registered device video%d [v4l2]\n",
dev->name, vfd->minor & 0x1f));
} else { } else {
vv->vbi_minor = vid->minor; vv->vbi_minor = vfd->minor;
INFO(("%s: registered device vbi%d [v4l2]\n", dev->name,vid->minor & 0x1f)); INFO(("%s: registered device vbi%d [v4l2]\n",
dev->name, vfd->minor & 0x1f));
} }
*vid = vfd;
return 0; 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; struct saa7146_vv *vv = dev->vv_data;
DEB_EE(("dev:%p\n",dev)); DEB_EE(("dev:%p\n",dev));
if( VFL_TYPE_GRABBER == vid->type ) { if( VFL_TYPE_GRABBER == (*vid)->type ) {
vv->video_minor = -1; vv->video_minor = -1;
} else { } else {
vv->vbi_minor = -1; vv->vbi_minor = -1;
} }
video_unregister_device(vid);
video_unregister_device(*vid);
*vid = NULL;
return 0; return 0;
} }
......
...@@ -413,10 +413,10 @@ static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct sa ...@@ -413,10 +413,10 @@ static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct sa
/* fill up cliptable */ /* fill up cliptable */
for(i = 0; i < cnt_pixel; i++) { 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++) { 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 */ /* fill up cliptable with the display infos */
...@@ -430,7 +430,7 @@ static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct sa ...@@ -430,7 +430,7 @@ static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct sa
if( pixel_list[i] < (x[j] + w[j])) { if( pixel_list[i] < (x[j] + w[j])) {
if ( pixel_list[i] >= x[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_rect(struct saa7146_dev *dev, struct sa ...@@ -442,7 +442,7 @@ static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct sa
if( line_list[i] < (y[j] + h[j]) ) { if( line_list[i] < (y[j] + h[j]) ) {
if( line_list[i] >= y[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 saa7146_dev *dev, int width, int height, e ...@@ -560,9 +560,10 @@ static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, e
} }
/* calculate the new memory offsets for a desired position */ /* 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_vv *vv = dev->vv_data;
struct saa7146_format *sfmt = format_by_fourcc(dev, pixelformat);
int b_depth = vv->ov_fmt->depth; int b_depth = vv->ov_fmt->depth;
int b_bpl = vv->ov_fb.fmt.bytesperline; int b_bpl = vv->ov_fb.fmt.bytesperline;
...@@ -601,7 +602,7 @@ static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int ...@@ -601,7 +602,7 @@ static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int
vdma1.pitch *= -1; 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; vdma1.num_line_byte = (vv->standard->v_field<<16)+vv->standard->h_pixels;
saa7146_write_out_dma(dev, 1, &vdma1); saa7146_write_out_dma(dev, 1, &vdma1);
...@@ -657,7 +658,7 @@ int saa7146_enable_overlay(struct saa7146_fh *fh) ...@@ -657,7 +658,7 @@ int saa7146_enable_overlay(struct saa7146_fh *fh)
struct saa7146_vv *vv = dev->vv_data; 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_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_output_format(dev, vv->ov_fmt->trans);
saa7146_set_clipping_rect(fh); saa7146_set_clipping_rect(fh);
...@@ -727,7 +728,7 @@ static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa71 ...@@ -727,7 +728,7 @@ static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa71
vdma1.pitch = (width*depth*2)/8; vdma1.pitch = (width*depth*2)/8;
} }
vdma1.num_line_byte = ((vv->standard->v_field<<16) + vv->standard->h_pixels); 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 ) { if( 0 != vv->vflip ) {
vdma1.prot_addr = buf->pt[0].offset; vdma1.prot_addr = buf->pt[0].offset;
......
...@@ -393,7 +393,7 @@ static struct i2c_algorithm saa7146_algo = { ...@@ -393,7 +393,7 @@ static struct i2c_algorithm saa7146_algo = {
.functionality = saa7146_i2c_func, .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)); DEB_EE(("bitrate: 0x%08x\n",bitrate));
...@@ -404,13 +404,11 @@ int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c ...@@ -404,13 +404,11 @@ int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c
saa7146_i2c_reset(dev); saa7146_i2c_reset(dev);
if( NULL != i2c_adapter ) { 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)) #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
i2c_adapter->data = dev; i2c_adapter->data = dev;
#else #else
BUG_ON(!i2c_adapter->class);
i2c_set_adapdata(i2c_adapter,dev); i2c_set_adapdata(i2c_adapter,dev);
i2c_adapter->class = class;
#endif #endif
i2c_adapter->algo = &saa7146_algo; i2c_adapter->algo = &saa7146_algo;
i2c_adapter->algo_data = NULL; i2c_adapter->algo_data = NULL;
......
...@@ -37,6 +37,13 @@ static struct saa7146_format formats[] = { ...@@ -37,6 +37,13 @@ static struct saa7146_format formats[] = {
.trans = RGB32_COMPOSED, .trans = RGB32_COMPOSED,
.depth = 32, .depth = 32,
.flags = 0, .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", .name = "Greyscale-8",
.pixelformat = V4L2_PIX_FMT_GREY, .pixelformat = V4L2_PIX_FMT_GREY,
...@@ -634,7 +641,7 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu ...@@ -634,7 +641,7 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
/* walk all pages, copy all page addresses to ptr1 */ /* walk all pages, copy all page addresses to ptr1 */
for (i = 0; i < length; i++, list++) { for (i = 0; i < length; i++, list++) {
for (p = 0; p * 4096 < list->length; p++, ptr1++) { 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);
} }
} }
/* /*
......
...@@ -154,7 +154,7 @@ struct saa7146_dev ...@@ -154,7 +154,7 @@ struct saa7146_dev
}; };
/* from saa7146_i2c.c */ /* 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); int saa7146_i2c_transfer(struct saa7146_dev *saa, const struct i2c_msg msgs[], int num, int retries);
/* from saa7146_core.c */ /* from saa7146_core.c */
......
...@@ -35,6 +35,7 @@ struct saa7146_format { ...@@ -35,6 +35,7 @@ struct saa7146_format {
u32 trans; u32 trans;
u8 depth; u8 depth;
u8 flags; u8 flags;
u8 swap;
}; };
struct saa7146_standard struct saa7146_standard
...@@ -188,8 +189,8 @@ struct saa7146_use_ops { ...@@ -188,8 +189,8 @@ struct saa7146_use_ops {
}; };
/* from saa7146_fops.c */ /* from saa7146_fops.c */
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);
int saa7146_unregister_device(struct video_device *vid, struct saa7146_dev* dev); 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_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); 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); int saa7146_buffer_queue(struct saa7146_dev *dev, struct saa7146_dmaqueue *q, struct saa7146_buf *buf);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment