diff options
author | Michael Hunold <devnull@localhost> | 2003-03-06 14:30:13 +0000 |
---|---|---|
committer | Michael Hunold <devnull@localhost> | 2003-03-06 14:30:13 +0000 |
commit | fc5e1c1da8c7e1847e01a4d7ad3bf1436e86763d (patch) | |
tree | 08f0707c1190a6b1c1e3f60e43209ff46eb1bace /linux/drivers/media/common | |
parent | 8ec7593ed2e06d4319ff9fb0d83a4a01d0f77296 (diff) | |
download | mediapointer-dvb-s2-fc5e1c1da8c7e1847e01a4d7ad3bf1436e86763d.tar.gz mediapointer-dvb-s2-fc5e1c1da8c7e1847e01a4d7ad3bf1436e86763d.tar.bz2 |
Added some planar yuv modes to the saa7146 driver core:
- V4L2_PIX_FMT_YUV422P: YUV 4:2:2 planar (Y-Cb-Cr)
- V4L2_PIX_FMT_YVU420: YVU 4:2:0 planar (Y-Cb-Cr)
- V4L2_PIX_FMT_YUV420: YUV 4:2:0 planar (Y-Cb-Cr)
Planar modes don't suffer from the saa7146 byte swap bug, so we
can deliver the formats needed by various video encoders, like "mp1e"
or "nvrec".
Added some notes to the TODO file.
Diffstat (limited to 'linux/drivers/media/common')
-rw-r--r-- | linux/drivers/media/common/saa7146_hlp.c | 141 | ||||
-rw-r--r-- | linux/drivers/media/common/saa7146_video.c | 46 | ||||
-rw-r--r-- | linux/drivers/media/common/saa7146_vv.h | 1 |
3 files changed, 142 insertions, 46 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; } diff --git a/linux/drivers/media/common/saa7146_video.c b/linux/drivers/media/common/saa7146_video.c index cdeeada3b..e6bf86e0a 100644 --- a/linux/drivers/media/common/saa7146_video.c +++ b/linux/drivers/media/common/saa7146_video.c @@ -43,12 +43,19 @@ struct saa7146_format formats[] = { .pixelformat = V4L2_PIX_FMT_YUV422P, .trans = YUV422_DECOMPOSED, .depth = 16, + .swap = 1, }, { - .name = "YUV 4:2:0 planar (Y-Cb-Cr)", + .name = "YVU 4:2:0 planar (Y-Cb-Cr)", .pixelformat = V4L2_PIX_FMT_YVU420, .trans = YUV420_DECOMPOSED, .depth = 12, }, { + .name = "YUV 4:2:0 planar (Y-Cb-Cr)", + .pixelformat = V4L2_PIX_FMT_YUV420, + .trans = YUV420_DECOMPOSED, + .depth = 12, + .swap = 1, + }, { .name = "YUV 4:2:2 (U-Y-V-Y)", .pixelformat = V4L2_PIX_FMT_UYVY, .trans = YUV422_COMPOSED, @@ -57,7 +64,7 @@ struct saa7146_format formats[] = { }; /* unfortunately, the saa7146 contains a bug which prevents it from doing on-the-fly byte swaps. - due to this, it's impossible to provide additional formats, which are simply byte swapped + due to this, it's impossible to provide additional *packed* formats, which are simply byte swapped (like V4L2_PIX_FMT_YUYV) ... 8-( */ static @@ -557,8 +564,34 @@ int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf) u32 *ptr1, *ptr2, *ptr3; u32 fill; - int size = ((buf->fmt->width*buf->fmt->height*sfmt->depth)/8)/2; + int size = buf->fmt->width*buf->fmt->height; int i,p,m1,m2,m3,o1,o2; + + switch( sfmt->depth ) { + case 12: { + /* create some offsets inside the page table */ + m1 = ((size+PAGE_SIZE)/PAGE_SIZE)-1; + m2 = ((size+(size/4)+PAGE_SIZE)/PAGE_SIZE)-1; + m3 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1; + o1 = size%PAGE_SIZE; + o2 = (size+(size/4))%PAGE_SIZE; + printk("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2); + break; + } + case 16: { + /* create some offsets inside the page table */ + m1 = ((size+PAGE_SIZE)/PAGE_SIZE)-1; + m2 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1; + m3 = ((2*size+PAGE_SIZE)/PAGE_SIZE)-1; + o1 = size%PAGE_SIZE; + o2 = (size+(size/2))%PAGE_SIZE; + printk("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2); + break; + } + default: { + return -1; + } + } ptr1 = pt1->cpu; ptr2 = pt2->cpu; @@ -576,13 +609,6 @@ int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf) printk("ptr1 %d: 0x%08x\n",j,ptr1[j]); } */ - /* create some offsets inside the page table */ - m1 = ((size+PAGE_SIZE-1)/PAGE_SIZE)-1; - m2 = ((size+(size/2)+PAGE_SIZE-1)/PAGE_SIZE)-1; - m3 = ((2*size+PAGE_SIZE-1)/PAGE_SIZE)-1; - - o1 = size%PAGE_SIZE; - o2 = (size+(size/2))%PAGE_SIZE; /* if we have a user buffer, the first page may not be aligned to a page boundary. */ diff --git a/linux/drivers/media/common/saa7146_vv.h b/linux/drivers/media/common/saa7146_vv.h index 062622329..a22ebe560 100644 --- a/linux/drivers/media/common/saa7146_vv.h +++ b/linux/drivers/media/common/saa7146_vv.h @@ -23,6 +23,7 @@ struct saa7146_format { int pixelformat; u32 trans; u8 depth; + int swap; }; struct saa7146_standard |