V4L/DVB (9162): ivtv: fix raw/sliced VBI mixup
The service_set field was used in saa7115 and cx25840 to determine whether raw or sliced VBI was desired. This is incorrect since it is perfectly valid to select sliced VBI with a service_set of 0. Instead these drivers should checked on VIDIOC_S_FMT whether the type field matches the raw or sliced VBI type. Updated ivtv accordingly. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
3c7b933bea
commit
a8b864354e
|
@ -141,10 +141,11 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
|
||||||
u8 lcr[24];
|
u8 lcr[24];
|
||||||
|
|
||||||
fmt = arg;
|
fmt = arg;
|
||||||
if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
|
if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE &&
|
||||||
|
fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
svbi = &fmt->fmt.sliced;
|
svbi = &fmt->fmt.sliced;
|
||||||
if (svbi->service_set == 0) {
|
if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
|
||||||
/* raw VBI */
|
/* raw VBI */
|
||||||
memset(svbi, 0, sizeof(*svbi));
|
memset(svbi, 0, sizeof(*svbi));
|
||||||
|
|
||||||
|
|
|
@ -720,7 +720,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
|
||||||
itv->speed = 1000;
|
itv->speed = 1000;
|
||||||
|
|
||||||
/* VBI */
|
/* VBI */
|
||||||
itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
|
itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
|
||||||
itv->vbi.sliced_in = &itv->vbi.in.fmt.sliced;
|
itv->vbi.sliced_in = &itv->vbi.in.fmt.sliced;
|
||||||
|
|
||||||
/* Init the sg table for osd/yuv output */
|
/* Init the sg table for osd/yuv output */
|
||||||
|
|
|
@ -750,6 +750,12 @@ void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv);
|
||||||
/* First-open initialization: load firmware, init cx25840, etc. */
|
/* First-open initialization: load firmware, init cx25840, etc. */
|
||||||
int ivtv_init_on_first_open(struct ivtv *itv);
|
int ivtv_init_on_first_open(struct ivtv *itv);
|
||||||
|
|
||||||
|
/* Test if the current VBI mode is raw (1) or sliced (0) */
|
||||||
|
static inline int ivtv_raw_vbi(const struct ivtv *itv)
|
||||||
|
{
|
||||||
|
return itv->vbi.in.type == V4L2_BUF_TYPE_VBI_CAPTURE;
|
||||||
|
}
|
||||||
|
|
||||||
/* This is a PCI post thing, where if the pci register is not read, then
|
/* This is a PCI post thing, where if the pci register is not read, then
|
||||||
the write doesn't always take effect right away. By reading back the
|
the write doesn't always take effect right away. By reading back the
|
||||||
register any pending PCI writes will be performed (in order), and so
|
register any pending PCI writes will be performed (in order), and so
|
||||||
|
|
|
@ -78,7 +78,7 @@ static int ivtv_claim_stream(struct ivtv_open_id *id, int type)
|
||||||
if (type == IVTV_DEC_STREAM_TYPE_MPG) {
|
if (type == IVTV_DEC_STREAM_TYPE_MPG) {
|
||||||
vbi_type = IVTV_DEC_STREAM_TYPE_VBI;
|
vbi_type = IVTV_DEC_STREAM_TYPE_VBI;
|
||||||
} else if (type == IVTV_ENC_STREAM_TYPE_MPG &&
|
} else if (type == IVTV_ENC_STREAM_TYPE_MPG &&
|
||||||
itv->vbi.insert_mpeg && itv->vbi.sliced_in->service_set) {
|
itv->vbi.insert_mpeg && !ivtv_raw_vbi(itv)) {
|
||||||
vbi_type = IVTV_ENC_STREAM_TYPE_VBI;
|
vbi_type = IVTV_ENC_STREAM_TYPE_VBI;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -305,7 +305,7 @@ static size_t ivtv_copy_buf_to_user(struct ivtv_stream *s, struct ivtv_buffer *b
|
||||||
|
|
||||||
if (len > ucount) len = ucount;
|
if (len > ucount) len = ucount;
|
||||||
if (itv->vbi.insert_mpeg && s->type == IVTV_ENC_STREAM_TYPE_MPG &&
|
if (itv->vbi.insert_mpeg && s->type == IVTV_ENC_STREAM_TYPE_MPG &&
|
||||||
itv->vbi.sliced_in->service_set && buf != &itv->vbi.sliced_mpeg_buf) {
|
!ivtv_raw_vbi(itv) && buf != &itv->vbi.sliced_mpeg_buf) {
|
||||||
const char *start = buf->buf + buf->readpos;
|
const char *start = buf->buf + buf->readpos;
|
||||||
const char *p = start + 1;
|
const char *p = start + 1;
|
||||||
const u8 *q;
|
const u8 *q;
|
||||||
|
@ -372,7 +372,7 @@ static ssize_t ivtv_read(struct ivtv_stream *s, char __user *ubuf, size_t tot_co
|
||||||
/* Each VBI buffer is one frame, the v4l2 API says that for VBI the frames should
|
/* Each VBI buffer is one frame, the v4l2 API says that for VBI the frames should
|
||||||
arrive one-by-one, so make sure we never output more than one VBI frame at a time */
|
arrive one-by-one, so make sure we never output more than one VBI frame at a time */
|
||||||
if (s->type == IVTV_DEC_STREAM_TYPE_VBI ||
|
if (s->type == IVTV_DEC_STREAM_TYPE_VBI ||
|
||||||
(s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set))
|
(s->type == IVTV_ENC_STREAM_TYPE_VBI && !ivtv_raw_vbi(itv)))
|
||||||
single_frame = 1;
|
single_frame = 1;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
|
@ -575,8 +575,11 @@ static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f
|
||||||
{
|
{
|
||||||
struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
|
struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
|
||||||
|
|
||||||
|
if (!ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)
|
||||||
|
return -EBUSY;
|
||||||
itv->vbi.sliced_in->service_set = 0;
|
itv->vbi.sliced_in->service_set = 0;
|
||||||
itv->video_dec_func(itv, VIDIOC_S_FMT, &itv->vbi.in);
|
itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
|
||||||
|
itv->video_dec_func(itv, VIDIOC_S_FMT, fmt);
|
||||||
return ivtv_g_fmt_vbi_cap(file, fh, fmt);
|
return ivtv_g_fmt_vbi_cap(file, fh, fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,8 +594,9 @@ static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
check_service_set(vbifmt, itv->is_50hz);
|
check_service_set(vbifmt, itv->is_50hz);
|
||||||
if (atomic_read(&itv->capturing) > 0)
|
if (ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
|
||||||
itv->video_dec_func(itv, VIDIOC_S_FMT, fmt);
|
itv->video_dec_func(itv, VIDIOC_S_FMT, fmt);
|
||||||
memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in));
|
memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in));
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -334,7 +334,7 @@ void ivtv_streams_cleanup(struct ivtv *itv, int unregister)
|
||||||
|
|
||||||
static void ivtv_vbi_setup(struct ivtv *itv)
|
static void ivtv_vbi_setup(struct ivtv *itv)
|
||||||
{
|
{
|
||||||
int raw = itv->vbi.sliced_in->service_set == 0;
|
int raw = ivtv_raw_vbi(itv);
|
||||||
u32 data[CX2341X_MBOX_MAX_DATA];
|
u32 data[CX2341X_MBOX_MAX_DATA];
|
||||||
int lines;
|
int lines;
|
||||||
int i;
|
int i;
|
||||||
|
|
|
@ -334,7 +334,7 @@ void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
|
||||||
int y;
|
int y;
|
||||||
|
|
||||||
/* Raw VBI data */
|
/* Raw VBI data */
|
||||||
if (streamtype == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set == 0) {
|
if (streamtype == IVTV_ENC_STREAM_TYPE_VBI && ivtv_raw_vbi(itv)) {
|
||||||
u8 type;
|
u8 type;
|
||||||
|
|
||||||
ivtv_buf_swap(buf);
|
ivtv_buf_swap(buf);
|
||||||
|
|
|
@ -1057,7 +1057,7 @@ static void saa711x_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo
|
||||||
for (i = 0; i <= 23; i++)
|
for (i = 0; i <= 23; i++)
|
||||||
lcr[i] = 0xff;
|
lcr[i] = 0xff;
|
||||||
|
|
||||||
if (fmt->service_set == 0) {
|
if (fmt == NULL) {
|
||||||
/* raw VBI */
|
/* raw VBI */
|
||||||
if (is_50hz)
|
if (is_50hz)
|
||||||
for (i = 6; i <= 23; i++)
|
for (i = 6; i <= 23; i++)
|
||||||
|
@ -1113,7 +1113,7 @@ static void saa711x_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo
|
||||||
}
|
}
|
||||||
|
|
||||||
/* enable/disable raw VBI capturing */
|
/* enable/disable raw VBI capturing */
|
||||||
saa711x_writeregs(client, fmt->service_set == 0 ?
|
saa711x_writeregs(client, fmt == NULL ?
|
||||||
saa7115_cfg_vbi_on :
|
saa7115_cfg_vbi_on :
|
||||||
saa7115_cfg_vbi_off);
|
saa7115_cfg_vbi_off);
|
||||||
}
|
}
|
||||||
|
@ -1153,6 +1153,10 @@ static int saa711x_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt
|
||||||
saa711x_set_lcr(client, &fmt->fmt.sliced);
|
saa711x_set_lcr(client, &fmt->fmt.sliced);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
|
||||||
|
saa711x_set_lcr(client, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
|
if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue