diff options
Diffstat (limited to 'drivers/media/video/cx18/cx18-controls.c')
-rw-r--r-- | drivers/media/video/cx18/cx18-controls.c | 285 |
1 files changed, 33 insertions, 252 deletions
diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c index 97d7b7e..282a3d2 100644 --- a/drivers/media/video/cx18/cx18-controls.c +++ b/drivers/media/video/cx18/cx18-controls.c @@ -30,152 +30,11 @@ #include "cx18-mailbox.h" #include "cx18-controls.h" -/* Must be sorted from low to high control ID! */ -static const u32 user_ctrls[] = { - V4L2_CID_USER_CLASS, - V4L2_CID_BRIGHTNESS, - V4L2_CID_CONTRAST, - V4L2_CID_SATURATION, - V4L2_CID_HUE, - V4L2_CID_AUDIO_VOLUME, - V4L2_CID_AUDIO_BALANCE, - V4L2_CID_AUDIO_BASS, - V4L2_CID_AUDIO_TREBLE, - V4L2_CID_AUDIO_MUTE, - V4L2_CID_AUDIO_LOUDNESS, - 0 -}; - -static const u32 *ctrl_classes[] = { - user_ctrls, - cx2341x_mpeg_ctrls, - NULL -}; - -int cx18_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qctrl) -{ - struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; - const char *name; - - qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); - if (qctrl->id == 0) - return -EINVAL; - - switch (qctrl->id) { - /* Standard V4L2 controls */ - case V4L2_CID_USER_CLASS: - return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0); - case V4L2_CID_BRIGHTNESS: - case V4L2_CID_HUE: - case V4L2_CID_SATURATION: - case V4L2_CID_CONTRAST: - if (v4l2_subdev_call(cx->sd_av, core, queryctrl, qctrl)) - qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; - return 0; - - 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: - if (v4l2_subdev_call(cx->sd_av, core, queryctrl, qctrl)) - qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; - return 0; - - default: - if (cx2341x_ctrl_query(&cx->params, qctrl)) - qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; - return 0; - } - strncpy(qctrl->name, name, sizeof(qctrl->name) - 1); - qctrl->name[sizeof(qctrl->name) - 1] = 0; - return 0; -} - -int cx18_querymenu(struct file *file, void *fh, struct v4l2_querymenu *qmenu) +static int cx18_s_stream_vbi_fmt(struct cx2341x_handler *cxhdl, u32 fmt) { - struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; - struct v4l2_queryctrl qctrl; - - qctrl.id = qmenu->id; - cx18_queryctrl(file, fh, &qctrl); - return v4l2_ctrl_query_menu(qmenu, &qctrl, - cx2341x_ctrl_get_menu(&cx->params, qmenu->id)); -} - -static int cx18_try_ctrl(struct file *file, void *fh, - struct v4l2_ext_control *vctrl) -{ - struct v4l2_queryctrl qctrl; - const char * const *menu_items = NULL; - int err; - - qctrl.id = vctrl->id; - err = cx18_queryctrl(file, fh, &qctrl); - if (err) - return err; - if (qctrl.type == V4L2_CTRL_TYPE_MENU) - menu_items = v4l2_ctrl_get_menu(qctrl.id); - return v4l2_ctrl_check(vctrl, &qctrl, menu_items); -} - -static int cx18_s_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, s_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, s_ctrl, vctrl); - - default: - CX18_DEBUG_IOCTL("invalid control 0x%x\n", vctrl->id); - return -EINVAL; - } - 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); + struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl); + int type = cxhdl->stream_type->val; - default: - CX18_DEBUG_IOCTL("invalid control 0x%x\n", vctrl->id); - return -EINVAL; - } - return 0; -} - -static int cx18_setup_vbi_fmt(struct cx18 *cx, - enum v4l2_mpeg_stream_vbi_fmt fmt, - enum v4l2_mpeg_stream_type type) -{ - if (!(cx->v4l2_cap & V4L2_CAP_SLICED_VBI_CAPTURE)) - return -EINVAL; if (atomic_read(&cx->ana_capturing) > 0) return -EBUSY; @@ -230,121 +89,43 @@ static int cx18_setup_vbi_fmt(struct cx18 *cx, return 0; } -int cx18_g_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) +static int cx18_s_video_encoding(struct cx2341x_handler *cxhdl, u32 val) { - struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; - struct v4l2_control ctrl; - - if (c->ctrl_class == V4L2_CTRL_CLASS_USER) { - int i; - int err = 0; - - for (i = 0; i < c->count; i++) { - ctrl.id = c->controls[i].id; - ctrl.value = c->controls[i].value; - err = cx18_g_ctrl(cx, &ctrl); - c->controls[i].value = ctrl.value; - if (err) { - c->error_idx = i; - break; - } - } - return err; - } - if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) - return cx2341x_ext_ctrls(&cx->params, 0, c, VIDIOC_G_EXT_CTRLS); - return -EINVAL; + struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl); + int is_mpeg1 = val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1; + struct v4l2_mbus_framefmt fmt; + + /* fix videodecoder resolution */ + fmt.width = cxhdl->width / (is_mpeg1 ? 2 : 1); + fmt.height = cxhdl->height; + fmt.code = V4L2_MBUS_FMT_FIXED; + v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &fmt); + return 0; } -int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) +static int cx18_s_audio_sampling_freq(struct cx2341x_handler *cxhdl, u32 idx) { - struct cx18_open_id *id = fh; - struct cx18 *cx = id->cx; - int ret; - struct v4l2_control ctrl; - - ret = v4l2_prio_check(&cx->prio, id->prio); - if (ret) - return ret; - - if (c->ctrl_class == V4L2_CTRL_CLASS_USER) { - int i; - int err = 0; - - for (i = 0; i < c->count; i++) { - ctrl.id = c->controls[i].id; - ctrl.value = c->controls[i].value; - err = cx18_s_ctrl(cx, &ctrl); - c->controls[i].value = ctrl.value; - if (err) { - c->error_idx = i; - break; - } - } - return err; - } - if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) { - static u32 freqs[3] = { 44100, 48000, 32000 }; - struct cx18_api_func_private priv; - struct cx2341x_mpeg_params p = cx->params; - int err = cx2341x_ext_ctrls(&p, atomic_read(&cx->ana_capturing), - c, VIDIOC_S_EXT_CTRLS); - unsigned int idx; - - if (err) - return err; + static const u32 freqs[3] = { 44100, 48000, 32000 }; + struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl); - if (p.video_encoding != cx->params.video_encoding) { - int is_mpeg1 = p.video_encoding == - V4L2_MPEG_VIDEO_ENCODING_MPEG_1; - struct v4l2_mbus_framefmt fmt; - - /* fix videodecoder resolution */ - fmt.width = cx->params.width / (is_mpeg1 ? 2 : 1); - fmt.height = cx->params.height; - fmt.code = V4L2_MBUS_FMT_FIXED; - v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &fmt); - } - priv.cx = cx; - priv.s = &cx->streams[id->type]; - err = cx2341x_update(&priv, cx18_api_func, &cx->params, &p); - if (!err && - (cx->params.stream_vbi_fmt != p.stream_vbi_fmt || - cx->params.stream_type != p.stream_type)) - err = cx18_setup_vbi_fmt(cx, p.stream_vbi_fmt, - p.stream_type); - cx->params = p; - cx->dualwatch_stereo_mode = p.audio_properties & 0x0300; - idx = p.audio_properties & 0x03; - /* The audio clock of the digitizer must match the codec sample - rate otherwise you get some very strange effects. */ - if (idx < ARRAY_SIZE(freqs)) - cx18_call_all(cx, audio, s_clock_freq, freqs[idx]); - return err; - } - return -EINVAL; + /* The audio clock of the digitizer must match the codec sample + rate otherwise you get some very strange effects. */ + if (idx < ARRAY_SIZE(freqs)) + cx18_call_all(cx, audio, s_clock_freq, freqs[idx]); + return 0; } -int cx18_try_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) +static int cx18_s_audio_mode(struct cx2341x_handler *cxhdl, u32 val) { - struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; + struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl); - if (c->ctrl_class == V4L2_CTRL_CLASS_USER) { - int i; - int err = 0; - - for (i = 0; i < c->count; i++) { - err = cx18_try_ctrl(file, fh, &c->controls[i]); - if (err) { - c->error_idx = i; - break; - } - } - return err; - } - if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) - return cx2341x_ext_ctrls(&cx->params, - atomic_read(&cx->ana_capturing), - c, VIDIOC_TRY_EXT_CTRLS); - return -EINVAL; + cx->dualwatch_stereo_mode = val; + return 0; } + +struct cx2341x_handler_ops cx18_cxhdl_ops = { + .s_audio_mode = cx18_s_audio_mode, + .s_audio_sampling_freq = cx18_s_audio_sampling_freq, + .s_video_encoding = cx18_s_video_encoding, + .s_stream_vbi_fmt = cx18_s_stream_vbi_fmt, +}; |