[media] ivtv: implement new decoder command ioctls

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Hans Verkuil 2011-11-24 09:58:53 -03:00 коммит произвёл Mauro Carvalho Chehab
Родитель 6b4f12523d
Коммит da8ec560e3
4 изменённых файлов: 71 добавлений и 43 удалений

Просмотреть файл

@ -1375,7 +1375,7 @@ static void ivtv_remove(struct pci_dev *pdev)
else else
type = IVTV_DEC_STREAM_TYPE_MPG; type = IVTV_DEC_STREAM_TYPE_MPG;
ivtv_stop_v4l2_decode_stream(&itv->streams[type], ivtv_stop_v4l2_decode_stream(&itv->streams[type],
VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY, 0);
} }
ivtv_halt_firmware(itv); ivtv_halt_firmware(itv);
} }

Просмотреть файл

@ -900,7 +900,7 @@ int ivtv_v4l2_close(struct file *filp)
if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) { if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) {
struct ivtv_stream *s_vout = &itv->streams[IVTV_DEC_STREAM_TYPE_VOUT]; struct ivtv_stream *s_vout = &itv->streams[IVTV_DEC_STREAM_TYPE_VOUT];
ivtv_stop_decoding(id, VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); ivtv_stop_decoding(id, V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY, 0);
/* If all output streams are closed, and if the user doesn't have /* If all output streams are closed, and if the user doesn't have
IVTV_DEC_STREAM_TYPE_VOUT open, then disable CC on TV-out. */ IVTV_DEC_STREAM_TYPE_VOUT open, then disable CC on TV-out. */

Просмотреть файл

@ -246,34 +246,40 @@ static int ivtv_validate_speed(int cur_speed, int new_speed)
} }
static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id, static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id,
struct video_command *vc, int try) struct v4l2_decoder_cmd *dc, int try)
{ {
struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG];
if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
return -EINVAL; return -EINVAL;
switch (vc->cmd) { switch (dc->cmd) {
case VIDEO_CMD_PLAY: { case V4L2_DEC_CMD_START: {
vc->flags = 0; dc->flags &= V4L2_DEC_CMD_START_MUTE_AUDIO;
vc->play.speed = ivtv_validate_speed(itv->speed, vc->play.speed); dc->start.speed = ivtv_validate_speed(itv->speed, dc->start.speed);
if (vc->play.speed < 0) if (dc->start.speed < 0)
vc->play.format = VIDEO_PLAY_FMT_GOP; dc->start.format = V4L2_DEC_START_FMT_GOP;
else
dc->start.format = V4L2_DEC_START_FMT_NONE;
if (dc->start.speed != 500 && dc->start.speed != 1500)
dc->flags = dc->start.speed == 1000 ? 0 :
V4L2_DEC_CMD_START_MUTE_AUDIO;
if (try) break; if (try) break;
itv->speed_mute_audio = dc->flags & V4L2_DEC_CMD_START_MUTE_AUDIO;
if (ivtv_set_output_mode(itv, OUT_MPG) != OUT_MPG) if (ivtv_set_output_mode(itv, OUT_MPG) != OUT_MPG)
return -EBUSY; return -EBUSY;
if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) { if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) {
/* forces ivtv_set_speed to be called */ /* forces ivtv_set_speed to be called */
itv->speed = 0; itv->speed = 0;
} }
return ivtv_start_decoding(id, vc->play.speed); return ivtv_start_decoding(id, dc->start.speed);
} }
case VIDEO_CMD_STOP: case V4L2_DEC_CMD_STOP:
vc->flags &= VIDEO_CMD_STOP_IMMEDIATELY|VIDEO_CMD_STOP_TO_BLACK; dc->flags &= V4L2_DEC_CMD_STOP_IMMEDIATELY | V4L2_DEC_CMD_STOP_TO_BLACK;
if (vc->flags & VIDEO_CMD_STOP_IMMEDIATELY) if (dc->flags & V4L2_DEC_CMD_STOP_IMMEDIATELY)
vc->stop.pts = 0; dc->stop.pts = 0;
if (try) break; if (try) break;
if (atomic_read(&itv->decoding) == 0) if (atomic_read(&itv->decoding) == 0)
return 0; return 0;
@ -281,22 +287,22 @@ static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id,
return -EBUSY; return -EBUSY;
itv->output_mode = OUT_NONE; itv->output_mode = OUT_NONE;
return ivtv_stop_v4l2_decode_stream(s, vc->flags, vc->stop.pts); return ivtv_stop_v4l2_decode_stream(s, dc->flags, dc->stop.pts);
case VIDEO_CMD_FREEZE: case V4L2_DEC_CMD_PAUSE:
vc->flags &= VIDEO_CMD_FREEZE_TO_BLACK; dc->flags &= V4L2_DEC_CMD_PAUSE_TO_BLACK;
if (try) break; if (try) break;
if (itv->output_mode != OUT_MPG) if (itv->output_mode != OUT_MPG)
return -EBUSY; return -EBUSY;
if (atomic_read(&itv->decoding) > 0) { if (atomic_read(&itv->decoding) > 0) {
ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1,
(vc->flags & VIDEO_CMD_FREEZE_TO_BLACK) ? 1 : 0); (dc->flags & V4L2_DEC_CMD_PAUSE_TO_BLACK) ? 1 : 0);
set_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags); set_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags);
} }
break; break;
case VIDEO_CMD_CONTINUE: case V4L2_DEC_CMD_RESUME:
vc->flags = 0; dc->flags = 0;
if (try) break; if (try) break;
if (itv->output_mode != OUT_MPG) if (itv->output_mode != OUT_MPG)
return -EBUSY; return -EBUSY;
@ -1575,6 +1581,24 @@ static int ivtv_log_status(struct file *file, void *fh)
return 0; return 0;
} }
static int ivtv_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec)
{
struct ivtv_open_id *id = fh2id(file->private_data);
struct ivtv *itv = id->itv;
IVTV_DEBUG_IOCTL("VIDIOC_DECODER_CMD %d\n", dec->cmd);
return ivtv_video_command(itv, id, dec, false);
}
static int ivtv_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec)
{
struct ivtv_open_id *id = fh2id(file->private_data);
struct ivtv *itv = id->itv;
IVTV_DEBUG_IOCTL("VIDIOC_TRY_DECODER_CMD %d\n", dec->cmd);
return ivtv_video_command(itv, id, dec, true);
}
static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
{ {
struct ivtv_open_id *id = fh2id(filp->private_data); struct ivtv_open_id *id = fh2id(filp->private_data);
@ -1669,52 +1693,54 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
} }
case VIDEO_PLAY: { case VIDEO_PLAY: {
struct video_command vc; struct v4l2_decoder_cmd dc;
IVTV_DEBUG_IOCTL("VIDEO_PLAY\n"); IVTV_DEBUG_IOCTL("VIDEO_PLAY\n");
memset(&vc, 0, sizeof(vc)); memset(&dc, 0, sizeof(dc));
vc.cmd = VIDEO_CMD_PLAY; dc.cmd = V4L2_DEC_CMD_START;
return ivtv_video_command(itv, id, &vc, 0); return ivtv_video_command(itv, id, &dc, 0);
} }
case VIDEO_STOP: { case VIDEO_STOP: {
struct video_command vc; struct v4l2_decoder_cmd dc;
IVTV_DEBUG_IOCTL("VIDEO_STOP\n"); IVTV_DEBUG_IOCTL("VIDEO_STOP\n");
memset(&vc, 0, sizeof(vc)); memset(&dc, 0, sizeof(dc));
vc.cmd = VIDEO_CMD_STOP; dc.cmd = V4L2_DEC_CMD_STOP;
vc.flags = VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY; dc.flags = V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY;
return ivtv_video_command(itv, id, &vc, 0); return ivtv_video_command(itv, id, &dc, 0);
} }
case VIDEO_FREEZE: { case VIDEO_FREEZE: {
struct video_command vc; struct v4l2_decoder_cmd dc;
IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n"); IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n");
memset(&vc, 0, sizeof(vc)); memset(&dc, 0, sizeof(dc));
vc.cmd = VIDEO_CMD_FREEZE; dc.cmd = V4L2_DEC_CMD_PAUSE;
return ivtv_video_command(itv, id, &vc, 0); return ivtv_video_command(itv, id, &dc, 0);
} }
case VIDEO_CONTINUE: { case VIDEO_CONTINUE: {
struct video_command vc; struct v4l2_decoder_cmd dc;
IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n"); IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n");
memset(&vc, 0, sizeof(vc)); memset(&dc, 0, sizeof(dc));
vc.cmd = VIDEO_CMD_CONTINUE; dc.cmd = V4L2_DEC_CMD_RESUME;
return ivtv_video_command(itv, id, &vc, 0); return ivtv_video_command(itv, id, &dc, 0);
} }
case VIDEO_COMMAND: case VIDEO_COMMAND:
case VIDEO_TRY_COMMAND: { case VIDEO_TRY_COMMAND: {
struct video_command *vc = arg; /* Note: struct v4l2_decoder_cmd has the same layout as
struct video_command */
struct v4l2_decoder_cmd *dc = arg;
int try = (cmd == VIDEO_TRY_COMMAND); int try = (cmd == VIDEO_TRY_COMMAND);
if (try) if (try)
IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", vc->cmd); IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", dc->cmd);
else else
IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", vc->cmd); IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", dc->cmd);
return ivtv_video_command(itv, id, vc, try); return ivtv_video_command(itv, id, dc, try);
} }
case VIDEO_GET_EVENT: { case VIDEO_GET_EVENT: {
@ -1892,6 +1918,8 @@ static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
.vidioc_enum_fmt_vid_cap = ivtv_enum_fmt_vid_cap, .vidioc_enum_fmt_vid_cap = ivtv_enum_fmt_vid_cap,
.vidioc_encoder_cmd = ivtv_encoder_cmd, .vidioc_encoder_cmd = ivtv_encoder_cmd,
.vidioc_try_encoder_cmd = ivtv_try_encoder_cmd, .vidioc_try_encoder_cmd = ivtv_try_encoder_cmd,
.vidioc_decoder_cmd = ivtv_decoder_cmd,
.vidioc_try_decoder_cmd = ivtv_try_decoder_cmd,
.vidioc_enum_fmt_vid_out = ivtv_enum_fmt_vid_out, .vidioc_enum_fmt_vid_out = ivtv_enum_fmt_vid_out,
.vidioc_g_fmt_vid_cap = ivtv_g_fmt_vid_cap, .vidioc_g_fmt_vid_cap = ivtv_g_fmt_vid_cap,
.vidioc_g_fmt_vbi_cap = ivtv_g_fmt_vbi_cap, .vidioc_g_fmt_vbi_cap = ivtv_g_fmt_vbi_cap,

Просмотреть файл

@ -905,7 +905,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts)
IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", (unsigned long long)pts, flags); IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", (unsigned long long)pts, flags);
/* Stop Decoder */ /* Stop Decoder */
if (!(flags & VIDEO_CMD_STOP_IMMEDIATELY) || pts) { if (!(flags & V4L2_DEC_CMD_STOP_IMMEDIATELY) || pts) {
u32 tmp = 0; u32 tmp = 0;
/* Wait until the decoder is no longer running */ /* Wait until the decoder is no longer running */
@ -925,7 +925,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts)
break; break;
} }
} }
ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, flags & VIDEO_CMD_STOP_TO_BLACK, 0, 0); ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, flags & V4L2_DEC_CMD_STOP_TO_BLACK, 0, 0);
/* turn off notification of dual/stereo mode change */ /* turn off notification of dual/stereo mode change */
ivtv_vapi(itv, CX2341X_DEC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_DEC_AUD_MODE_CHG, -1); ivtv_vapi(itv, CX2341X_DEC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_DEC_AUD_MODE_CHG, -1);