aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael H. Schimek <mschimek@gmx.at>2006-01-09 12:25:27 -0500
committerMauro Carvalho Chehab <mchehab@brturbo.com.br>2006-01-09 12:25:27 -0500
commit67f1570a0659abba5efbf55cc986187af61bdd52 (patch)
treea7c0fe1bbfecfcd418c6549e9eee82b79106f0ba
parent7e57819169d4f9a1d7af55fb645ece3fb981e2e3 (diff)
V4L/DVB (3178): bttv VBI fixes
- V4L2_(G|S|TRY)_FMT returned incorrect VBI start lines for PAL-M, NTSC-JP, and PAL-60. They also returned an inaccurate VBI offset. - V4L2_(G|S)_FMT and V4L2_TRY_FMT disagreed about the start of VBI capturing in PAL and SECAM second field. Note the start line fixes may break applications using VIDIOCSVBIFMT because this ioctl fails when the driver does not support exactly the requested parameters. - V4L2_TRY_FMT did not clear the reserved field in struct v4l2_vbi_format. - V4L2_(S|TRY)_FMT did not expect very large or small VBI start or count values, returning wrong (but safe) counts due to an overflow. - VIDIOCGVBIFMT confused V4L and V4L2 VBI flags. However this had no effect because the flags have the same value and bttv never sets them. - In v4l_compat_translate_ioctl() the VIDIOC(G|S)VBIFMT code did not expect V4L2 drivers supporting VBI formats besides V4L2_PIX_FMT_GREY. Signed-off-by: Michael H. Schimek <mschimek@gmx.at> Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
-rw-r--r--drivers/media/video/bttv-driver.c18
-rw-r--r--drivers/media/video/bttv-vbi.c57
-rw-r--r--drivers/media/video/bttvp.h5
-rw-r--r--drivers/media/video/v4l1-compat.c11
4 files changed, 51 insertions, 40 deletions
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
index 8bee7d5796dd..4e25c92ac8c4 100644
--- a/drivers/media/video/bttv-driver.c
+++ b/drivers/media/video/bttv-driver.c
@@ -210,6 +210,9 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
210 .vdelay = 0x20, 210 .vdelay = 0x20,
211 .vbipack = 255, 211 .vbipack = 255,
212 .sram = 0, 212 .sram = 0,
213 /* ITU-R frame line number of the first VBI line
214 we can capture, of the first and second field. */
215 .vbistart = { 7,320 },
213 },{ 216 },{
214 .v4l2_id = V4L2_STD_NTSC_M, 217 .v4l2_id = V4L2_STD_NTSC_M,
215 .name = "NTSC", 218 .name = "NTSC",
@@ -226,6 +229,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
226 .vdelay = 0x1a, 229 .vdelay = 0x1a,
227 .vbipack = 144, 230 .vbipack = 144,
228 .sram = 1, 231 .sram = 1,
232 .vbistart = { 10, 273 },
229 },{ 233 },{
230 .v4l2_id = V4L2_STD_SECAM, 234 .v4l2_id = V4L2_STD_SECAM,
231 .name = "SECAM", 235 .name = "SECAM",
@@ -242,6 +246,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
242 .vdelay = 0x20, 246 .vdelay = 0x20,
243 .vbipack = 255, 247 .vbipack = 255,
244 .sram = 0, /* like PAL, correct? */ 248 .sram = 0, /* like PAL, correct? */
249 .vbistart = { 7, 320 },
245 },{ 250 },{
246 .v4l2_id = V4L2_STD_PAL_Nc, 251 .v4l2_id = V4L2_STD_PAL_Nc,
247 .name = "PAL-Nc", 252 .name = "PAL-Nc",
@@ -258,6 +263,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
258 .vdelay = 0x1a, 263 .vdelay = 0x1a,
259 .vbipack = 144, 264 .vbipack = 144,
260 .sram = -1, 265 .sram = -1,
266 .vbistart = { 7, 320 },
261 },{ 267 },{
262 .v4l2_id = V4L2_STD_PAL_M, 268 .v4l2_id = V4L2_STD_PAL_M,
263 .name = "PAL-M", 269 .name = "PAL-M",
@@ -274,6 +280,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
274 .vdelay = 0x1a, 280 .vdelay = 0x1a,
275 .vbipack = 144, 281 .vbipack = 144,
276 .sram = -1, 282 .sram = -1,
283 .vbistart = { 10, 273 },
277 },{ 284 },{
278 .v4l2_id = V4L2_STD_PAL_N, 285 .v4l2_id = V4L2_STD_PAL_N,
279 .name = "PAL-N", 286 .name = "PAL-N",
@@ -290,6 +297,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
290 .vdelay = 0x20, 297 .vdelay = 0x20,
291 .vbipack = 144, 298 .vbipack = 144,
292 .sram = -1, 299 .sram = -1,
300 .vbistart = { 7, 320},
293 },{ 301 },{
294 .v4l2_id = V4L2_STD_NTSC_M_JP, 302 .v4l2_id = V4L2_STD_NTSC_M_JP,
295 .name = "NTSC-JP", 303 .name = "NTSC-JP",
@@ -306,6 +314,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
306 .vdelay = 0x16, 314 .vdelay = 0x16,
307 .vbipack = 144, 315 .vbipack = 144,
308 .sram = -1, 316 .sram = -1,
317 .vbistart = {10, 273},
309 },{ 318 },{
310 /* that one hopefully works with the strange timing 319 /* that one hopefully works with the strange timing
311 * which video recorders produce when playing a NTSC 320 * which video recorders produce when playing a NTSC
@@ -326,6 +335,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
326 .vbipack = 255, 335 .vbipack = 255,
327 .vtotal = 524, 336 .vtotal = 524,
328 .sram = -1, 337 .sram = -1,
338 .vbistart = { 10, 273 },
329 } 339 }
330}; 340};
331static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms); 341static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
@@ -2570,10 +2580,10 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
2570 fmt->count[0] = fmt2.fmt.vbi.count[0]; 2580 fmt->count[0] = fmt2.fmt.vbi.count[0];
2571 fmt->start[1] = fmt2.fmt.vbi.start[1]; 2581 fmt->start[1] = fmt2.fmt.vbi.start[1];
2572 fmt->count[1] = fmt2.fmt.vbi.count[1]; 2582 fmt->count[1] = fmt2.fmt.vbi.count[1];
2573 if (fmt2.fmt.vbi.flags & VBI_UNSYNC) 2583 if (fmt2.fmt.vbi.flags & V4L2_VBI_UNSYNC)
2574 fmt->flags |= V4L2_VBI_UNSYNC; 2584 fmt->flags |= VBI_UNSYNC;
2575 if (fmt2.fmt.vbi.flags & VBI_INTERLACED) 2585 if (fmt2.fmt.vbi.flags & V4L2_VBI_INTERLACED)
2576 fmt->flags |= V4L2_VBI_INTERLACED; 2586 fmt->flags |= VBI_INTERLACED;
2577 return 0; 2587 return 0;
2578 } 2588 }
2579 case VIDIOCSVBIFMT: 2589 case VIDIOCSVBIFMT:
diff --git a/drivers/media/video/bttv-vbi.c b/drivers/media/video/bttv-vbi.c
index f4f58c60f152..72afdd64b882 100644
--- a/drivers/media/video/bttv-vbi.c
+++ b/drivers/media/video/bttv-vbi.c
@@ -31,6 +31,12 @@
31#include <asm/io.h> 31#include <asm/io.h>
32#include "bttvp.h" 32#include "bttvp.h"
33 33
34/* Offset from line sync pulse leading edge (0H) in 1 / sampling_rate:
35 bt8x8 /HRESET pulse starts at 0H and has length 64 / fCLKx1 (E|O_VTC
36 HSFMT = 0). VBI_HDELAY (always 0) is an offset from the trailing edge
37 of /HRESET in 1 / fCLKx1, and the sampling_rate tvnorm->Fsc is fCLKx2. */
38#define VBI_OFFSET ((64 + 0) * 2)
39
34#define VBI_DEFLINES 16 40#define VBI_DEFLINES 16
35#define VBI_MAXLINES 32 41#define VBI_MAXLINES 32
36 42
@@ -163,40 +169,30 @@ void bttv_vbi_setlines(struct bttv_fh *fh, struct bttv *btv, int lines)
163void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f) 169void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f)
164{ 170{
165 const struct bttv_tvnorm *tvnorm; 171 const struct bttv_tvnorm *tvnorm;
166 u32 start0,start1; 172 s64 count0,count1,count;
167 s32 count0,count1,count;
168 173
169 tvnorm = &bttv_tvnorms[fh->btv->tvnorm]; 174 tvnorm = &bttv_tvnorms[fh->btv->tvnorm];
170 f->type = V4L2_BUF_TYPE_VBI_CAPTURE; 175 f->type = V4L2_BUF_TYPE_VBI_CAPTURE;
171 f->fmt.vbi.sampling_rate = tvnorm->Fsc; 176 f->fmt.vbi.sampling_rate = tvnorm->Fsc;
172 f->fmt.vbi.samples_per_line = 2048; 177 f->fmt.vbi.samples_per_line = 2048;
173 f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; 178 f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
174 f->fmt.vbi.offset = 244; 179 f->fmt.vbi.offset = VBI_OFFSET;
175 f->fmt.vbi.flags = 0; 180 f->fmt.vbi.flags = 0;
176 switch (fh->btv->tvnorm) {
177 case 1: /* NTSC */
178 start0 = 10;
179 start1 = 273;
180 break;
181 case 0: /* PAL */
182 case 2: /* SECAM */
183 default:
184 start0 = 7;
185 start1 = 320;
186 }
187 181
188 count0 = (f->fmt.vbi.start[0] + f->fmt.vbi.count[0]) - start0; 182 /* s64 to prevent overflow. */
189 count1 = (f->fmt.vbi.start[1] + f->fmt.vbi.count[1]) - start1; 183 count0 = (s64) f->fmt.vbi.start[0] + f->fmt.vbi.count[0]
190 count = max(count0,count1); 184 - tvnorm->vbistart[0];
191 if (count > VBI_MAXLINES) 185 count1 = (s64) f->fmt.vbi.start[1] + f->fmt.vbi.count[1]
192 count = VBI_MAXLINES; 186 - tvnorm->vbistart[1];
193 if (count < 1) 187 count = clamp (max (count0, count1), 1LL, (s64) VBI_MAXLINES);
194 count = 1;
195 188
196 f->fmt.vbi.start[0] = start0; 189 f->fmt.vbi.start[0] = tvnorm->vbistart[0];
197 f->fmt.vbi.start[1] = start1; 190 f->fmt.vbi.start[1] = tvnorm->vbistart[1];
198 f->fmt.vbi.count[0] = count; 191 f->fmt.vbi.count[0] = count;
199 f->fmt.vbi.count[1] = count; 192 f->fmt.vbi.count[1] = count;
193
194 f->fmt.vbi.reserved[0] = 0;
195 f->fmt.vbi.reserved[1] = 0;
200} 196}
201 197
202void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f) 198void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f)
@@ -209,21 +205,12 @@ void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f)
209 f->fmt.vbi.sampling_rate = tvnorm->Fsc; 205 f->fmt.vbi.sampling_rate = tvnorm->Fsc;
210 f->fmt.vbi.samples_per_line = 2048; 206 f->fmt.vbi.samples_per_line = 2048;
211 f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; 207 f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
212 f->fmt.vbi.offset = 244; 208 f->fmt.vbi.offset = VBI_OFFSET;
209 f->fmt.vbi.start[0] = tvnorm->vbistart[0];
210 f->fmt.vbi.start[1] = tvnorm->vbistart[1];
213 f->fmt.vbi.count[0] = fh->lines; 211 f->fmt.vbi.count[0] = fh->lines;
214 f->fmt.vbi.count[1] = fh->lines; 212 f->fmt.vbi.count[1] = fh->lines;
215 f->fmt.vbi.flags = 0; 213 f->fmt.vbi.flags = 0;
216 switch (fh->btv->tvnorm) {
217 case 1: /* NTSC */
218 f->fmt.vbi.start[0] = 10;
219 f->fmt.vbi.start[1] = 273;
220 break;
221 case 0: /* PAL */
222 case 2: /* SECAM */
223 default:
224 f->fmt.vbi.start[0] = 7;
225 f->fmt.vbi.start[1] = 319;
226 }
227} 214}
228 215
229/* ----------------------------------------------------------------------- */ 216/* ----------------------------------------------------------------------- */
diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h
index 55759f698e02..dd00c20ab95e 100644
--- a/drivers/media/video/bttvp.h
+++ b/drivers/media/video/bttvp.h
@@ -73,6 +73,8 @@
73 73
74#define UNSET (-1U) 74#define UNSET (-1U)
75 75
76#define clamp(x, low, high) min (max (low, x), high)
77
76/* ---------------------------------------------------------- */ 78/* ---------------------------------------------------------- */
77 79
78struct bttv_tvnorm { 80struct bttv_tvnorm {
@@ -88,6 +90,9 @@ struct bttv_tvnorm {
88 u8 vbipack; 90 u8 vbipack;
89 u16 vtotal; 91 u16 vtotal;
90 int sram; 92 int sram;
93 /* ITU-R frame line number of the first VBI line we can
94 capture, of the first and second field. */
95 u16 vbistart[2];
91}; 96};
92extern const struct bttv_tvnorm bttv_tvnorms[]; 97extern const struct bttv_tvnorm bttv_tvnorms[];
93 98
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
index 4134549d11a8..2ab5b4093800 100644
--- a/drivers/media/video/v4l1-compat.c
+++ b/drivers/media/video/v4l1-compat.c
@@ -951,6 +951,10 @@ v4l_compat_translate_ioctl(struct inode *inode,
951 dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err); 951 dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err);
952 break; 952 break;
953 } 953 }
954 if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) {
955 err = -EINVAL;
956 break;
957 }
954 memset(fmt, 0, sizeof(*fmt)); 958 memset(fmt, 0, sizeof(*fmt));
955 fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line; 959 fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line;
956 fmt->sampling_rate = fmt2->fmt.vbi.sampling_rate; 960 fmt->sampling_rate = fmt2->fmt.vbi.sampling_rate;
@@ -966,6 +970,11 @@ v4l_compat_translate_ioctl(struct inode *inode,
966 { 970 {
967 struct vbi_format *fmt = arg; 971 struct vbi_format *fmt = arg;
968 972
973 if (VIDEO_PALETTE_RAW != fmt->sample_format) {
974 err = -EINVAL;
975 break;
976 }
977
969 fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL); 978 fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
970 memset(fmt2, 0, sizeof(*fmt2)); 979 memset(fmt2, 0, sizeof(*fmt2));
971 980
@@ -986,7 +995,7 @@ v4l_compat_translate_ioctl(struct inode *inode,
986 995
987 if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line || 996 if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line ||
988 fmt2->fmt.vbi.sampling_rate != fmt->sampling_rate || 997 fmt2->fmt.vbi.sampling_rate != fmt->sampling_rate ||
989 VIDEO_PALETTE_RAW != fmt->sample_format || 998 fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY ||
990 fmt2->fmt.vbi.start[0] != fmt->start[0] || 999 fmt2->fmt.vbi.start[0] != fmt->start[0] ||
991 fmt2->fmt.vbi.count[0] != fmt->count[0] || 1000 fmt2->fmt.vbi.count[0] != fmt->count[0] ||
992 fmt2->fmt.vbi.start[1] != fmt->start[1] || 1001 fmt2->fmt.vbi.start[1] != fmt->start[1] ||