aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDevin Heitmueller <dheitmueller@kernellabs.com>2009-11-24 21:17:25 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-02-26 13:10:32 -0500
commit66d9cbad5330d6df30c82f10ee18b62b096b84ef (patch)
tree47d42a16b56f43df1dc2a535188205e6fc929708
parent6a2071006b72bf887e38c025c60f98d2998ceacb (diff)
V4L/DVB (13932): em28xx: add PAL support for VBI
Make the VBI support work for PAL standards in addition to NTSC. This work was sponsored by EyeMagnet Limited. Thanks go out to Andy Walls for providing a CD containing test PAL/VBI captures and to Steven Toth for providing a PVR-350 to do signal generation with. Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/em28xx/em28xx-core.c19
-rw-r--r--drivers/media/video/em28xx/em28xx-vbi.c17
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c58
-rw-r--r--drivers/media/video/em28xx/em28xx.h3
4 files changed, 66 insertions, 31 deletions
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index b311d4514bd..5a37eccbd7d 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -691,9 +691,15 @@ int em28xx_set_outfmt(struct em28xx *dev)
691 if (em28xx_vbi_supported(dev) == 1) { 691 if (em28xx_vbi_supported(dev) == 1) {
692 vinctrl |= EM28XX_VINCTRL_VBI_RAW; 692 vinctrl |= EM28XX_VINCTRL_VBI_RAW;
693 em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00); 693 em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00);
694 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09); 694 em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, dev->vbi_width/4);
695 em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, 0xb4); 695 em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, dev->vbi_height);
696 em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, 0x0c); 696 if (dev->norm & V4L2_STD_525_60) {
697 /* NTSC */
698 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09);
699 } else if (dev->norm & V4L2_STD_625_50) {
700 /* PAL */
701 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x07);
702 }
697 } 703 }
698 704
699 return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl); 705 return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl);
@@ -760,6 +766,13 @@ int em28xx_resolution_set(struct em28xx *dev)
760 width = norm_maxw(dev); 766 width = norm_maxw(dev);
761 height = norm_maxh(dev); 767 height = norm_maxh(dev);
762 768
769 /* Properly setup VBI */
770 dev->vbi_width = 720;
771 if (dev->norm & V4L2_STD_525_60)
772 dev->vbi_height = 12;
773 else
774 dev->vbi_height = 18;
775
763 if (!dev->progressive) 776 if (!dev->progressive)
764 height >>= norm_maxh(dev); 777 height >>= norm_maxh(dev);
765 778
diff --git a/drivers/media/video/em28xx/em28xx-vbi.c b/drivers/media/video/em28xx/em28xx-vbi.c
index 94943e5a152..c7dce39823d 100644
--- a/drivers/media/video/em28xx/em28xx-vbi.c
+++ b/drivers/media/video/em28xx/em28xx-vbi.c
@@ -71,7 +71,11 @@ free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf)
71static int 71static int
72vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) 72vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
73{ 73{
74 *size = 720 * 12 * 2; 74 struct em28xx_fh *fh = q->priv_data;
75 struct em28xx *dev = fh->dev;
76
77 *size = dev->vbi_width * dev->vbi_height * 2;
78
75 if (0 == *count) 79 if (0 == *count)
76 *count = vbibufs; 80 *count = vbibufs;
77 if (*count < 2) 81 if (*count < 2)
@@ -85,19 +89,18 @@ static int
85vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, 89vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
86 enum v4l2_field field) 90 enum v4l2_field field)
87{ 91{
92 struct em28xx_fh *fh = q->priv_data;
93 struct em28xx *dev = fh->dev;
88 struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); 94 struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
89 int rc = 0; 95 int rc = 0;
90 unsigned int size;
91
92 size = 720 * 12 * 2;
93 96
94 buf->vb.size = size; 97 buf->vb.size = dev->vbi_width * dev->vbi_height * 2;
95 98
96 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) 99 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
97 return -EINVAL; 100 return -EINVAL;
98 101
99 buf->vb.width = 720; 102 buf->vb.width = dev->vbi_width;
100 buf->vb.height = 12; 103 buf->vb.height = dev->vbi_height;
101 buf->vb.field = field; 104 buf->vb.field = field;
102 105
103 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { 106 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 849b18c9403..ac2bd935927 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -282,7 +282,7 @@ static void em28xx_copy_vbi(struct em28xx *dev,
282{ 282{
283 void *startwrite, *startread; 283 void *startwrite, *startread;
284 int offset; 284 int offset;
285 int bytesperline = 720; 285 int bytesperline = dev->vbi_width;
286 286
287 if (dev == NULL) { 287 if (dev == NULL) {
288 em28xx_isocdbg("dev is null\n"); 288 em28xx_isocdbg("dev is null\n");
@@ -323,8 +323,8 @@ static void em28xx_copy_vbi(struct em28xx *dev,
323 323
324 /* Make sure the bottom field populates the second half of the frame */ 324 /* Make sure the bottom field populates the second half of the frame */
325 if (buf->top_field == 0) { 325 if (buf->top_field == 0) {
326 startwrite += bytesperline * 0x0c; 326 startwrite += bytesperline * dev->vbi_height;
327 offset += bytesperline * 0x0c; 327 offset += bytesperline * dev->vbi_height;
328 } 328 }
329 329
330 memcpy(startwrite, startread, len); 330 memcpy(startwrite, startread, len);
@@ -578,8 +578,7 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb)
578 dev->cur_field = p[2]; 578 dev->cur_field = p[2];
579 } 579 }
580 580
581 /* FIXME: get rid of hard-coded value */ 581 vbi_size = dev->vbi_width * dev->vbi_height;
582 vbi_size = 720 * 0x0c;
583 582
584 if (dev->capture_type == 0) { 583 if (dev->capture_type == 0) {
585 if (dev->vbi_read >= vbi_size) { 584 if (dev->vbi_read >= vbi_size) {
@@ -1850,18 +1849,27 @@ static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv,
1850static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, 1849static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
1851 struct v4l2_format *format) 1850 struct v4l2_format *format)
1852{ 1851{
1853 format->fmt.vbi.samples_per_line = 720; 1852 struct em28xx_fh *fh = priv;
1853 struct em28xx *dev = fh->dev;
1854
1855 format->fmt.vbi.samples_per_line = dev->vbi_width;
1854 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; 1856 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
1855 format->fmt.vbi.offset = 0; 1857 format->fmt.vbi.offset = 0;
1856 format->fmt.vbi.flags = 0; 1858 format->fmt.vbi.flags = 0;
1859 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
1860 format->fmt.vbi.count[0] = dev->vbi_height;
1861 format->fmt.vbi.count[1] = dev->vbi_height;
1857 1862
1858 /* Varies by video standard (NTSC, PAL, etc.) */ 1863 /* Varies by video standard (NTSC, PAL, etc.) */
1859 /* FIXME: hard-coded for NTSC support */ 1864 if (dev->norm & V4L2_STD_525_60) {
1860 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; /* FIXME: ??? */ 1865 /* NTSC */
1861 format->fmt.vbi.count[0] = 12; 1866 format->fmt.vbi.start[0] = 10;
1862 format->fmt.vbi.count[1] = 12; 1867 format->fmt.vbi.start[1] = 273;
1863 format->fmt.vbi.start[0] = 10; 1868 } else if (dev->norm & V4L2_STD_625_50) {
1864 format->fmt.vbi.start[1] = 273; 1869 /* PAL */
1870 format->fmt.vbi.start[0] = 6;
1871 format->fmt.vbi.start[1] = 318;
1872 }
1865 1873
1866 return 0; 1874 return 0;
1867} 1875}
@@ -1869,18 +1877,27 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
1869static int vidioc_s_fmt_vbi_cap(struct file *file, void *priv, 1877static int vidioc_s_fmt_vbi_cap(struct file *file, void *priv,
1870 struct v4l2_format *format) 1878 struct v4l2_format *format)
1871{ 1879{
1872 format->fmt.vbi.samples_per_line = 720; 1880 struct em28xx_fh *fh = priv;
1881 struct em28xx *dev = fh->dev;
1882
1883 format->fmt.vbi.samples_per_line = dev->vbi_width;
1873 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; 1884 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
1874 format->fmt.vbi.offset = 0; 1885 format->fmt.vbi.offset = 0;
1875 format->fmt.vbi.flags = 0; 1886 format->fmt.vbi.flags = 0;
1887 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
1888 format->fmt.vbi.count[0] = dev->vbi_height;
1889 format->fmt.vbi.count[1] = dev->vbi_height;
1876 1890
1877 /* Varies by video standard (NTSC, PAL, etc.) */ 1891 /* Varies by video standard (NTSC, PAL, etc.) */
1878 /* FIXME: hard-coded for NTSC support */ 1892 if (dev->norm & V4L2_STD_525_60) {
1879 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; /* FIXME: ??? */ 1893 /* NTSC */
1880 format->fmt.vbi.count[0] = 12; 1894 format->fmt.vbi.start[0] = 10;
1881 format->fmt.vbi.count[1] = 12; 1895 format->fmt.vbi.start[1] = 273;
1882 format->fmt.vbi.start[0] = 10; 1896 } else if (dev->norm & V4L2_STD_625_50) {
1883 format->fmt.vbi.start[1] = 273; 1897 /* PAL */
1898 format->fmt.vbi.start[0] = 6;
1899 format->fmt.vbi.start[1] = 318;
1900 }
1884 1901
1885 return 0; 1902 return 0;
1886} 1903}
@@ -1922,7 +1939,8 @@ static int vidioc_querybuf(struct file *file, void *priv,
1922 At a minimum, it causes a crash in zvbi since it does 1939 At a minimum, it causes a crash in zvbi since it does
1923 a memcpy based on the source buffer length */ 1940 a memcpy based on the source buffer length */
1924 int result = videobuf_querybuf(&fh->vb_vbiq, b); 1941 int result = videobuf_querybuf(&fh->vb_vbiq, b);
1925 b->length = 17280; 1942 b->length = dev->vbi_width * dev->vbi_height * 2;
1943
1926 return result; 1944 return result;
1927 } 1945 }
1928} 1946}
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index 80d9b4fa1b9..71e90dc6658 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -552,7 +552,8 @@ struct em28xx {
552 int capture_type; 552 int capture_type;
553 int vbi_read; 553 int vbi_read;
554 unsigned char cur_field; 554 unsigned char cur_field;
555 555 unsigned int vbi_width;
556 unsigned int vbi_height; /* lines per field */
556 557
557 struct work_struct request_module_wk; 558 struct work_struct request_module_wk;
558 559