]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/media/video/ivtv/ivtv-streams.c
V4L/DVB: ivtv: Timing tweaks and code re-order to try and improve stability
[karo-tx-linux.git] / drivers / media / video / ivtv / ivtv-streams.c
index 1f9387f6ca240d39c03ea805369b8c6e74c7e753..9ecacab4b89b3a63c601d12c3ea6ba1862f115e3 100644 (file)
@@ -42,6 +42,7 @@
 #include "ivtv-yuv.h"
 #include "ivtv-cards.h"
 #include "ivtv-streams.h"
+#include <media/v4l2-event.h>
 
 static const struct v4l2_file_operations ivtv_v4l2_enc_fops = {
        .owner = THIS_MODULE,
@@ -343,7 +344,10 @@ static void ivtv_vbi_setup(struct ivtv *itv)
        ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, 0xffff , 0, 0, 0, 0);
 
        /* setup VBI registers */
-       v4l2_subdev_call(itv->sd_video, video, s_fmt, &itv->vbi.in);
+       if (raw)
+               v4l2_subdev_call(itv->sd_video, vbi, s_raw_fmt, &itv->vbi.in.fmt.vbi);
+       else
+               v4l2_subdev_call(itv->sd_video, vbi, s_sliced_fmt, &itv->vbi.in.fmt.sliced);
 
        /* determine number of lines and total number of VBI bytes.
           A raw line takes 1443 bytes: 2 * 720 + 4 byte frame header - 1
@@ -581,10 +585,9 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
                v4l2_subdev_call(itv->sd_audio, audio, s_stream, 1);
                /* Avoid unpredictable PCI bus hang - disable video clocks */
                v4l2_subdev_call(itv->sd_video, video, s_stream, 0);
-               ivtv_msleep_timeout(150, 1);
+               ivtv_msleep_timeout(300, 1);
                ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0);
                v4l2_subdev_call(itv->sd_video, video, s_stream, 1);
-               ivtv_msleep_timeout(150, 1);
        }
 
        /* begin_capture */
@@ -615,12 +618,17 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
        struct ivtv *itv = s->itv;
        struct cx2341x_mpeg_params *p = &itv->params;
        int datatype;
+       u16 width;
+       u16 height;
 
        if (s->vdev == NULL)
                return -EINVAL;
 
        IVTV_DEBUG_INFO("Setting some initial decoder settings\n");
 
+       width = p->width;
+       height = p->height;
+
        /* set audio mode to left/stereo  for dual/stereo mode. */
        ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
 
@@ -643,7 +651,14 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
           2 = yuv_from_host */
        switch (s->type) {
        case IVTV_DEC_STREAM_TYPE_YUV:
-               datatype = itv->output_mode == OUT_PASSTHROUGH ? 1 : 2;
+               if (itv->output_mode == OUT_PASSTHROUGH) {
+                       datatype = 1;
+               } else {
+                       /* Fake size to avoid switching video standard */
+                       datatype = 2;
+                       width = 720;
+                       height = itv->is_out_50hz ? 576 : 480;
+               }
                IVTV_DEBUG_INFO("Setup DEC YUV Stream data[0] = %d\n", datatype);
                break;
        case IVTV_DEC_STREAM_TYPE_MPG:
@@ -652,9 +667,13 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
                break;
        }
        if (ivtv_vapi(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, datatype,
-                       p->width, p->height, p->audio_properties)) {
+                       width, height, p->audio_properties)) {
                IVTV_DEBUG_WARN("Couldn't initialize decoder source\n");
        }
+
+       /* Decoder sometimes dies here, so wait a moment */
+       ivtv_msleep_timeout(10, 0);
+
        return 0;
 }
 
@@ -694,6 +713,9 @@ int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset)
        /* start playback */
        ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, gop_offset, 0);
 
+       /* Let things settle before we actually start */
+       ivtv_msleep_timeout(10, 0);
+
        /* Clear the following Interrupt mask bits for decoding */
        ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_DECODE);
        IVTV_DEBUG_IRQ("IRQ Mask is now: 0x%08x\n", itv->irqmask);
@@ -830,6 +852,10 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
                ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST);
        }
 
+       /* Raw-passthrough is implied on start. Make sure it's stopped so
+          the encoder will re-initialize when next started */
+       ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, 1, 2, 7);
+
        wake_up(&s->waitq);
 
        return 0;
@@ -837,6 +863,9 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
 
 int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts)
 {
+       static const struct v4l2_event ev = {
+               .type = V4L2_EVENT_EOS,
+       };
        struct ivtv *itv = s->itv;
 
        if (s->vdev == NULL)
@@ -888,6 +917,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts)
 
        set_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags);
        wake_up(&itv->event_waitq);
+       v4l2_event_queue(s->vdev, &ev);
 
        /* wake up wait queues */
        wake_up(&s->waitq);