Commit 2f3a9893 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

V4L/DVB (6116): ivtv: VBI cleanups and fixes

Besides some VBI cleanups this patch also fixes a subtle problem with the
VBI re-insertion stream where the PIO work handler wasn't called quickly
enough, resulting in occasional corrupt data.

Furthermore the CC output didn't disable CC correctly and at the right time,
causing duplicates to be sent.

An saa7127 fix for VPS output was also added: the wrong data was sent.
Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 26e9d599
......@@ -489,6 +489,15 @@ struct yuv_playback_info
#define IVTV_VBI_FRAMES 32
/* VBI data */
struct vbi_cc {
u8 odd[2]; /* two-byte payload of odd field */
u8 even[2]; /* two-byte payload of even field */;
};
struct vbi_vps {
u8 data[5]; /* five-byte VPS payload */
};
struct vbi_info {
/* VBI general fixed card data */
u32 raw_decoder_line_size; /* raw VBI line size from digitizer */
......@@ -502,15 +511,14 @@ struct vbi_info {
u32 enc_start, enc_size;
int fpi;
u32 frame;
u8 cc_data_odd[256];
u8 cc_data_even[256];
int cc_pos;
u8 cc_no_update;
u8 vps[5];
u8 vps_found;
int wss;
u8 wss_found;
u8 wss_no_update;
struct vbi_cc cc_payload[256]; /* Sliced VBI CC payload array. It is an array to
prevent dropping CC data if they couldn't be
processed fast enough. */
int cc_payload_idx; /* Index in cc_payload */
u8 cc_missing_cnt; /* Counts number of frames without CC for passthrough mode */
int wss_payload; /* Sliced VBI WSS payload */
u8 wss_missing_cnt; /* Counts number of frames without WSS for passthrough mode */
struct vbi_vps vps_payload; /* Sliced VBI VPS payload */
struct v4l2_format in;
/* convenience pointer to sliced struct in vbi_in union */
struct v4l2_sliced_vbi_format *sliced_in;
......
......@@ -563,8 +563,11 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c
/* This stream does not need to start any decoding */
if (s->type == IVTV_DEC_STREAM_TYPE_VOUT) {
int elems = count / sizeof(struct v4l2_sliced_vbi_data);
set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
return ivtv_write_vbi(itv, user_buf, count);
ivtv_write_vbi(itv, (const struct v4l2_sliced_vbi_data *)user_buf, elems);
return elems * sizeof(struct v4l2_sliced_vbi_data);
}
mode = s->type == IVTV_DEC_STREAM_TYPE_MPG ? OUT_MPG : OUT_YUV;
......@@ -828,10 +831,10 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp)
ivtv_stop_decoding(id, VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0);
/* If all output streams are closed, and if the user doesn't have
IVTV_DEC_STREAM_TYPE_VOUT open, then disable VBI on TV-out. */
IVTV_DEC_STREAM_TYPE_VOUT open, then disable CC on TV-out. */
if (itv->output_mode == OUT_NONE && !test_bit(IVTV_F_S_APPL_IO, &s_vout->s_flags)) {
/* disable VBI on TV-out */
ivtv_disable_vbi(itv);
/* disable CC on TV-out */
ivtv_disable_cc(itv);
}
} else {
ivtv_stop_capture(id, 0);
......
......@@ -786,7 +786,10 @@ static void ivtv_irq_vsync(struct ivtv *itv)
wake_up(&s->waitq);
/* Send VBI to saa7127 */
if (frame) {
if (frame && (itv->output_mode == OUT_PASSTHROUGH ||
test_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags) ||
test_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags) ||
test_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags))) {
set_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags);
set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
}
......@@ -809,7 +812,7 @@ static void ivtv_irq_vsync(struct ivtv *itv)
}
}
#define IVTV_IRQ_DMA (IVTV_IRQ_DMA_READ | IVTV_IRQ_ENC_DMA_COMPLETE | IVTV_IRQ_DMA_ERR | IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_VBI_CAP | IVTV_IRQ_DEC_DATA_REQ)
#define IVTV_IRQ_DMA (IVTV_IRQ_DMA_READ | IVTV_IRQ_ENC_DMA_COMPLETE | IVTV_IRQ_DMA_ERR | IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_VBI_CAP | IVTV_IRQ_DEC_DATA_REQ | IVTV_IRQ_DEC_VBI_RE_INSERT)
irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
{
......@@ -942,8 +945,9 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
}
}
if (test_and_clear_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags))
if (test_and_clear_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags)) {
queue_work(itv->irq_work_queues, &itv->irq_work_queue);
}
spin_unlock(&itv->dma_reg_lock);
......
This diff is collapsed.
......@@ -20,11 +20,11 @@
#ifndef IVTV_VBI_H
#define IVTV_VBI_H
ssize_t ivtv_write_vbi(struct ivtv *itv, const char __user *ubuf, size_t count);
void ivtv_write_vbi(struct ivtv *itv, const struct v4l2_sliced_vbi_data *sliced, size_t count);
void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
u64 pts_stamp, int streamtype);
int ivtv_used_line(struct ivtv *itv, int line, int field);
void ivtv_disable_vbi(struct ivtv *itv);
void ivtv_disable_cc(struct ivtv *itv);
void ivtv_set_vbi(unsigned long arg);
void ivtv_vbi_work_handler(struct ivtv *itv);
......
......@@ -332,11 +332,11 @@ static int saa7127_set_vps(struct i2c_client *client, struct v4l2_sliced_vbi_dat
if (!enable)
return 0;
state->vps_data[0] = data->data[4];
state->vps_data[1] = data->data[10];
state->vps_data[2] = data->data[11];
state->vps_data[3] = data->data[12];
state->vps_data[4] = data->data[13];
state->vps_data[0] = data->data[2];
state->vps_data[1] = data->data[8];
state->vps_data[2] = data->data[9];
state->vps_data[3] = data->data[10];
state->vps_data[4] = data->data[11];
v4l_dbg(1, debug, client, "Set VPS data %02x %02x %02x %02x %02x\n",
state->vps_data[0], state->vps_data[1],
state->vps_data[2], state->vps_data[3],
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment