From f9411f6ddc7998112b5d287e9ab1de134358cb33 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Jul 2007 18:22:06 +0200 Subject: ivtv: fix DMA timeout when capturing VBI + another stream From: Hans Verkuil The VBI DMA is handled in a special way and is marked with a bit. However, that bit was set at the wrong time and could be cleared by mistake if a PCM (or other) DMA request would arrive before the VBI DMA was completed. So on completion of the VBI DMA the driver no longer knew that that DMA transfer was for VBI data. And this in turn caused havoc with the card's DMA engine. Signed-off-by: Hans Verkuil --- linux/drivers/media/video/ivtv/ivtv-irq.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ivtv/ivtv-irq.c b/linux/drivers/media/video/ivtv/ivtv-irq.c index 7996371ec..a7fe4c51e 100644 --- a/linux/drivers/media/video/ivtv/ivtv-irq.c +++ b/linux/drivers/media/video/ivtv/ivtv-irq.c @@ -409,6 +409,11 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s) /* Mark last buffer size for Interrupt flag */ s->SGarray[s->SG_length - 1].size |= cpu_to_le32(0x80000000); + if (s->type == IVTV_ENC_STREAM_TYPE_VBI) + set_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); + else + clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); + if (ivtv_use_pio(s)) { for (i = 0; i < s->SG_length; i++) { s->PIOarray[i].src = le32_to_cpu(s->SGarray[i].src); @@ -603,7 +608,6 @@ static void ivtv_irq_enc_start_cap(struct ivtv *itv) data[0], data[1], data[2]); return; } - clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); s = &itv->streams[ivtv_stream_map[data[0]]]; if (!stream_enc_dma_append(s, data)) { set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags); @@ -640,7 +644,6 @@ static void ivtv_irq_enc_vbi_cap(struct ivtv *itv) then start a DMA request for just the VBI data. */ if (!stream_enc_dma_append(s, data) && !test_bit(IVTV_F_S_STREAMING, &s_mpg->s_flags)) { - set_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags); } } -- cgit v1.2.3 From 29b613e242a791a94b820ca6c69ae2548452ebe5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Jul 2007 09:53:36 +0200 Subject: Add check for valid control ID to v4l2_ctrl_next. From: Hans Verkuil If v4l2_ctrl_next is called without the V4L2_CTRL_FLAG_NEXT_CTRL then it should check whether the passed control ID is valid and return 0 if it isn't. Otherwise a for-loop over the control IDs will never end. Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-common.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index eb6286bc4..78b251022 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -1566,16 +1566,25 @@ int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qc When no more controls are available 0 is returned. */ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id) { - u32 ctrl_class; + u32 ctrl_class = V4L2_CTRL_ID2CLASS(id); const u32 *pctrl; - /* if no query is desired, then just return the control ID */ - if ((id & V4L2_CTRL_FLAG_NEXT_CTRL) == 0) - return id; if (ctrl_classes == NULL) return 0; + + /* if no query is desired, then check if the ID is part of ctrl_classes */ + if ((id & V4L2_CTRL_FLAG_NEXT_CTRL) == 0) { + /* find class */ + while (*ctrl_classes && V4L2_CTRL_ID2CLASS(**ctrl_classes) != ctrl_class) + ctrl_classes++; + if (*ctrl_classes == NULL) + return 0; + pctrl = *ctrl_classes; + /* find control ID */ + while (*pctrl && *pctrl != id) pctrl++; + return *pctrl ? id : 0; + } id &= V4L2_CTRL_ID_MASK; - ctrl_class = V4L2_CTRL_ID2CLASS(id); id++; /* select next control */ /* find first class that matches (or is greater than) the class of the ID */ -- cgit v1.2.3