diff options
Diffstat (limited to 'linux/drivers/media/common/saa7146_hlp.c')
-rw-r--r-- | linux/drivers/media/common/saa7146_hlp.c | 141 |
1 files changed, 105 insertions, 36 deletions
diff --git a/linux/drivers/media/common/saa7146_hlp.c b/linux/drivers/media/common/saa7146_hlp.c index 884ba270c..e3cfddb42 100644 --- a/linux/drivers/media/common/saa7146_hlp.c +++ b/linux/drivers/media/common/saa7146_hlp.c @@ -796,6 +796,73 @@ int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa7146_buf } static +int calc_planar_422(struct saa7146_vv *vv, struct saa7146_buf *buf, struct saa7146_video_dma *vdma2, struct saa7146_video_dma *vdma3) +{ + int height = buf->fmt->height; + int width = buf->fmt->width; + + vdma2->pitch = width; + vdma3->pitch = width; + + if( 0 != vv->vflip ) { + vdma2->prot_addr = buf->pt[1].offset; + vdma2->base_even = ((vdma2->pitch/2)*height)+buf->pt[1].offset; + vdma2->base_odd = vdma2->base_even - (vdma2->pitch/2); + + vdma3->prot_addr = buf->pt[2].offset; + vdma3->base_even = ((vdma3->pitch/2)*height)+buf->pt[2].offset; + vdma3->base_odd = vdma3->base_even - (vdma3->pitch/2); + + } else { + vdma3->base_even = buf->pt[2].offset; + vdma3->base_odd = vdma3->base_even + (vdma3->pitch/2); + vdma3->prot_addr = (vdma3->pitch/2)*height+buf->pt[2].offset; + + vdma2->base_even = buf->pt[1].offset; + vdma2->base_odd = vdma2->base_even + (vdma2->pitch/2); + vdma2->prot_addr = (vdma2->pitch/2)*height+buf->pt[1].offset; + } + + return 0; +} + +static +int calc_planar_420(struct saa7146_vv *vv, struct saa7146_buf *buf, struct saa7146_video_dma *vdma2, struct saa7146_video_dma *vdma3) +{ + int height = buf->fmt->height; + int width = buf->fmt->width; + + vdma2->pitch = width/2; + vdma3->pitch = width/2; + + if( 0 != vv->vflip ) { + vdma2->prot_addr = buf->pt[2].offset; + vdma2->base_even = ((vdma2->pitch/2)*height)+buf->pt[2].offset; + vdma2->base_odd = vdma2->base_even - (vdma2->pitch/2); + + vdma3->prot_addr = buf->pt[1].offset; + vdma3->base_even = ((vdma3->pitch/2)*height)+buf->pt[1].offset; + vdma3->base_odd = vdma3->base_even - (vdma3->pitch/2); + + } else { + vdma3->base_even = buf->pt[2].offset; + vdma3->base_odd = vdma3->base_even + (vdma3->pitch); + vdma3->prot_addr = (vdma3->pitch/2)*height+buf->pt[2].offset; + + vdma2->base_even = buf->pt[1].offset; + vdma2->base_odd = vdma2->base_even + (vdma2->pitch); + vdma2->prot_addr = (vdma2->pitch/2)*height+buf->pt[1].offset; + + printk("vdma3->base_even: 0x%08x\n",vdma3->base_even); + printk("vdma3->base_odd: 0x%08x\n",vdma3->base_odd); + printk("vdma3->prot_addr: 0x%08x\n",vdma3->prot_addr); + + } + return 0; +} + + +static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa7146_buf *buf) { struct saa7146_vv *vv = dev->vv_data; @@ -803,6 +870,8 @@ int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa7146_buf struct saa7146_video_dma vdma2; struct saa7146_video_dma vdma3; + struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat); + int width = buf->fmt->width; int height = buf->fmt->height; enum v4l2_field field = buf->fmt->field; @@ -814,53 +883,49 @@ int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa7146_buf DEB_CAP(("[size=%dx%d,fields=%s]\n", width,height,v4l2_field_names[field])); - vdma1.pitch = width*2; - vdma1.num_line_byte = ((vv->standard->v_field<<16) + vv->standard->h_pixels); - vdma1.base_page = buf->pt[0].dma | ME1; - - /* fscking saa7146! due to the "byte-swap bug", video-dma2 - writes the v data and not the u data, video-dma3 writes - the u data, not the v data. but because we have a planar - format, we can simply switch the video-dmas... */ - - vdma3.pitch = width; - vdma3.num_line_byte = 0; /* unused */ - vdma3.base_page = buf->pt[1].dma | ME1; - - vdma2.pitch = width; - vdma2.num_line_byte = 0; /* unused */ - vdma2.base_page = buf->pt[2].dma | ME1; - /* fixme: what happens for user space buffers here?. The offsets are most likely wrong, this version here only works for page-aligned buffers, modifications to the pagetable-functions are necessary...*/ + vdma1.pitch = width*2; + vdma1.num_line_byte = ((vv->standard->v_field<<16) + vv->standard->h_pixels); + vdma1.base_page = buf->pt[0].dma | ME1; + if( 0 != vv->vflip ) { vdma1.prot_addr = buf->pt[0].offset; vdma1.base_even = ((vdma1.pitch/2)*height)+buf->pt[0].offset; vdma1.base_odd = vdma1.base_even - (vdma1.pitch/2); - - vdma2.prot_addr = buf->pt[2].offset; - vdma2.base_even = ((vdma2.pitch/2)*height)+buf->pt[2].offset; - vdma2.base_odd = vdma2.base_even - (vdma2.pitch/2); - - vdma3.prot_addr = buf->pt[1].offset; - vdma3.base_even = ((vdma3.pitch/2)*height)+buf->pt[1].offset; - vdma3.base_odd = vdma3.base_even - (vdma3.pitch/2); - } else { vdma1.base_even = buf->pt[0].offset; vdma1.base_odd = vdma1.base_even + (vdma1.pitch/2); vdma1.prot_addr = (vdma1.pitch/2)*height+buf->pt[0].offset; + } + + /* fixme */ +/* + vdma1.base_even = 0; // buf->pt[0].offset; + vdma1.base_odd = 0; // vdma1.base_even + (vdma1.pitch/2); + vdma1.prot_addr = 0; // (vdma1.pitch/2)*height+buf->pt[0].offset; +*/ + + vdma2.num_line_byte = 0; /* unused */ + vdma2.base_page = buf->pt[1].dma | ME1; - /* switched, see above */ - vdma3.base_even = buf->pt[1].offset; - vdma3.base_odd = vdma3.base_even + (vdma3.pitch/2); - vdma3.prot_addr = (vdma3.pitch/2)*height+buf->pt[1].offset; + vdma3.num_line_byte = 0; /* unused */ + vdma3.base_page = buf->pt[2].dma | ME1; - vdma2.base_even = buf->pt[2].offset; - vdma2.base_odd = vdma2.base_even + (vdma2.pitch/2); - vdma2.prot_addr = (vdma2.pitch/2)*height+buf->pt[2].offset; + switch( sfmt->depth ) { + case 12: { + calc_planar_420(vv,buf,&vdma2,&vdma3); + break; + } + case 16: { + calc_planar_422(vv,buf,&vdma2,&vdma3); + break; + } + default: { + return -1; + } } if (V4L2_FIELD_HAS_BOTH(field)) { @@ -890,9 +955,13 @@ int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa7146_buf } saa7146_write_out_dma(dev, 1, &vdma1); - saa7146_write_out_dma(dev, 2, &vdma2); - saa7146_write_out_dma(dev, 3, &vdma3); - + if( sfmt->swap != 0 ) { + saa7146_write_out_dma(dev, 3, &vdma2); + saa7146_write_out_dma(dev, 2, &vdma3); + } else { + saa7146_write_out_dma(dev, 2, &vdma2); + saa7146_write_out_dma(dev, 3, &vdma3); + } return 0; } |