summaryrefslogtreecommitdiff
path: root/drivers/media/video/ivtv/ivtv-streams.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/ivtv/ivtv-streams.c')
-rw-r--r--drivers/media/video/ivtv/ivtv-streams.c43
1 files changed, 38 insertions, 5 deletions
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
index 1f9387f6ca24..a937e2ff9b6e 100644
--- a/drivers/media/video/ivtv/ivtv-streams.c
+++ b/drivers/media/video/ivtv/ivtv-streams.c
@@ -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)
@@ -883,11 +912,15 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts)
clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
ivtv_flush_queues(s);
+ /* decoder needs time to settle */
+ ivtv_msleep_timeout(40, 0);
+
/* decrement decoding */
atomic_dec(&itv->decoding);
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);