static int cx18_try_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc) { struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; switch (enc->cmd) { case V4L2_ENC_CMD_START: CX18_DEBUG_IOCTL("V4L2_ENC_CMD_START\n"); enc->flags = 0; break; case V4L2_ENC_CMD_STOP: CX18_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n"); enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END; break; case V4L2_ENC_CMD_PAUSE: CX18_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n"); enc->flags = 0; break; case V4L2_ENC_CMD_RESUME: CX18_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n"); enc->flags = 0; break; default: CX18_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd); return -EINVAL; } return 0; }
static int cx18_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc) { struct cx18_open_id *id = fh; struct cx18 *cx = id->cx; u32 h; switch (enc->cmd) { case V4L2_ENC_CMD_START: CX18_DEBUG_IOCTL("V4L2_ENC_CMD_START\n"); enc->flags = 0; return cx18_start_capture(id); case V4L2_ENC_CMD_STOP: CX18_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n"); enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END; cx18_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END); break; case V4L2_ENC_CMD_PAUSE: CX18_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n"); enc->flags = 0; if (!atomic_read(&cx->ana_capturing)) return -EPERM; if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags)) return 0; h = cx18_find_handle(cx); if (h == CX18_INVALID_TASK_HANDLE) { CX18_ERR("Can't find valid task handle for " "V4L2_ENC_CMD_PAUSE\n"); return -EBADFD; } cx18_mute(cx); cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, h); break; case V4L2_ENC_CMD_RESUME: CX18_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n"); enc->flags = 0; if (!atomic_read(&cx->ana_capturing)) return -EPERM; if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags)) return 0; h = cx18_find_handle(cx); if (h == CX18_INVALID_TASK_HANDLE) { CX18_ERR("Can't find valid task handle for " "V4L2_ENC_CMD_RESUME\n"); return -EBADFD; } cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, h); cx18_unmute(cx); break; default: CX18_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd); return -EINVAL; } return 0; }
static long cx18_default(struct file *file, void *fh, int cmd, void *arg) { struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; switch (cmd) { case VIDIOC_INT_S_AUDIO_ROUTING: { struct v4l2_routing *route = arg; CX18_DEBUG_IOCTL("VIDIOC_INT_S_AUDIO_ROUTING(%d, %d)\n", route->input, route->output); cx18_audio_set_route(cx, route); break; } case VIDIOC_INT_RESET: { u32 val = *(u32 *)arg; if ((val == 0) || (val & 0x01)) cx18_reset_ir_gpio(&cx->i2c_algo_cb_data[0]); break; } default: return -EINVAL; } return 0; }
int cx18_v4l2_close(struct inode *inode, struct file *filp) { struct cx18_open_id *id = filp->private_data; struct cx18 *cx = id->cx; struct cx18_stream *s = &cx->streams[id->type]; CX18_DEBUG_IOCTL("close() of %s\n", s->name); v4l2_prio_close(&cx->prio, &id->prio); /* Easy case first: this stream was never claimed by us */ if (s->id != id->open_id) { kfree(id); return 0; } /* 'Unclaim' this stream */ /* Stop radio */ mutex_lock(&cx->serialize_lock); if (id->type == CX18_ENC_STREAM_TYPE_RAD) { /* Closing radio device, return to TV mode */ cx18_mute(cx); /* Mark that the radio is no longer in use */ clear_bit(CX18_F_I_RADIO_USER, &cx->i_flags); /* Switch tuner to TV */ cx18_call_i2c_clients(cx, VIDIOC_S_STD, &cx->std); /* Select correct audio input (i.e. TV tuner or Line in) */ cx18_audio_set_io(cx); if (atomic_read(&cx->ana_capturing) > 0) { /* Undo video mute */ cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle, cx->params.video_mute | (cx->params.video_mute_yuv << 8)); } /* Done! Unmute and continue. */ cx18_unmute(cx); cx18_release_stream(s); } else { cx18_stop_capture(id, 0); } kfree(id); mutex_unlock(&cx->serialize_lock); return 0; }
static int cx18_g_ctrl(struct cx18 *cx, struct v4l2_control *vctrl) { switch (vctrl->id) { /* Standard V4L2 controls */ case V4L2_CID_BRIGHTNESS: case V4L2_CID_HUE: case V4L2_CID_SATURATION: case V4L2_CID_CONTRAST: return v4l2_subdev_call(cx->sd_av, core, g_ctrl, vctrl); case V4L2_CID_AUDIO_VOLUME: case V4L2_CID_AUDIO_MUTE: case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: case V4L2_CID_AUDIO_LOUDNESS: return v4l2_subdev_call(cx->sd_av, core, g_ctrl, vctrl); default: CX18_DEBUG_IOCTL("invalid control 0x%x\n", vctrl->id); return -EINVAL; } return 0; }
void cx18_stop_capture(struct cx18_open_id *id, int gop_end) { struct cx18 *cx = id->cx; struct cx18_stream *s = &cx->streams[id->type]; CX18_DEBUG_IOCTL("close() of %s\n", s->name); /* 'Unclaim' this stream */ /* Stop capturing */ if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) { struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; CX18_DEBUG_INFO("close stopping capture\n"); /* Special case: a running VBI capture for VBI insertion in the mpeg stream. Need to stop that too. */ if (id->type == CX18_ENC_STREAM_TYPE_MPG && test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) && !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) { CX18_DEBUG_INFO("close stopping embedded VBI capture\n"); cx18_stop_v4l2_encode_stream(s_vbi, 0); } if (id->type == CX18_ENC_STREAM_TYPE_VBI && test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) /* Also used internally, don't stop capturing */ s->id = -1; else cx18_stop_v4l2_encode_stream(s, gop_end); } if (!gop_end) { clear_bit(CX18_F_S_APPL_IO, &s->s_flags); clear_bit(CX18_F_S_STREAMOFF, &s->s_flags); cx18_release_stream(s); } }