Loading drivers/media/usb/hdpvr/hdpvr-video.c +137 −378 Original line number Diff line number Diff line Loading @@ -710,335 +710,69 @@ static int vidioc_g_audio(struct file *file, void *private_data, return 0; } static const s32 supported_v4l2_ctrls[] = { V4L2_CID_BRIGHTNESS, V4L2_CID_CONTRAST, V4L2_CID_SATURATION, V4L2_CID_HUE, V4L2_CID_SHARPNESS, V4L2_CID_MPEG_AUDIO_ENCODING, V4L2_CID_MPEG_VIDEO_ENCODING, V4L2_CID_MPEG_VIDEO_BITRATE_MODE, V4L2_CID_MPEG_VIDEO_BITRATE, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, }; static int fill_queryctrl(struct hdpvr_options *opt, struct v4l2_queryctrl *qc, int ac3, int fw_ver) static int hdpvr_try_ctrl(struct v4l2_ctrl *ctrl) { int err; if (fw_ver > 0x15) { switch (qc->id) { case V4L2_CID_BRIGHTNESS: return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); case V4L2_CID_CONTRAST: return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x40); case V4L2_CID_SATURATION: return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x40); case V4L2_CID_HUE: return v4l2_ctrl_query_fill(qc, 0x0, 0x1e, 1, 0xf); case V4L2_CID_SHARPNESS: return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); } } else { switch (qc->id) { case V4L2_CID_BRIGHTNESS: return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x86); case V4L2_CID_CONTRAST: return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); case V4L2_CID_SATURATION: return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); case V4L2_CID_HUE: return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); case V4L2_CID_SHARPNESS: return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); } } switch (qc->id) { case V4L2_CID_MPEG_AUDIO_ENCODING: return v4l2_ctrl_query_fill( qc, V4L2_MPEG_AUDIO_ENCODING_AAC, ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 : V4L2_MPEG_AUDIO_ENCODING_AAC, 1, V4L2_MPEG_AUDIO_ENCODING_AAC); case V4L2_CID_MPEG_VIDEO_ENCODING: return v4l2_ctrl_query_fill( qc, V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 1, V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC); /* case V4L2_CID_MPEG_VIDEO_? maybe keyframe interval: */ /* return v4l2_ctrl_query_fill(qc, 0, 128, 128, 0); */ case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: return v4l2_ctrl_query_fill( qc, V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1, V4L2_MPEG_VIDEO_BITRATE_MODE_CBR); case V4L2_CID_MPEG_VIDEO_BITRATE: return v4l2_ctrl_query_fill(qc, 1000000, 13500000, 100000, 6500000); case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: err = v4l2_ctrl_query_fill(qc, 1100000, 20200000, 100000, 9000000); if (!err && opt->bitrate_mode == HDPVR_CONSTANT) qc->flags |= V4L2_CTRL_FLAG_INACTIVE; return err; default: return -EINVAL; } } static int vidioc_queryctrl(struct file *file, void *private_data, struct v4l2_queryctrl *qc) { struct hdpvr_fh *fh = file->private_data; struct hdpvr_device *dev = fh->dev; int i, next; u32 id = qc->id; memset(qc, 0, sizeof(*qc)); next = !!(id & V4L2_CTRL_FLAG_NEXT_CTRL); qc->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL; for (i = 0; i < ARRAY_SIZE(supported_v4l2_ctrls); i++) { if (next) { if (qc->id < supported_v4l2_ctrls[i]) qc->id = supported_v4l2_ctrls[i]; else continue; } if (qc->id == supported_v4l2_ctrls[i]) return fill_queryctrl(&dev->options, qc, dev->flags & HDPVR_FLAG_AC3_CAP, dev->fw_ver); if (qc->id < supported_v4l2_ctrls[i]) break; } return -EINVAL; } static int vidioc_g_ctrl(struct file *file, void *private_data, struct v4l2_control *ctrl) { struct hdpvr_fh *fh = file->private_data; struct hdpvr_device *dev = fh->dev; struct hdpvr_device *dev = container_of(ctrl->handler, struct hdpvr_device, hdl); switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: ctrl->value = dev->options.brightness; break; case V4L2_CID_CONTRAST: ctrl->value = dev->options.contrast; break; case V4L2_CID_SATURATION: ctrl->value = dev->options.saturation; break; case V4L2_CID_HUE: ctrl->value = dev->options.hue; break; case V4L2_CID_SHARPNESS: ctrl->value = dev->options.sharpness; case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: if (ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR && dev->video_bitrate->val >= dev->video_bitrate_peak->val) dev->video_bitrate_peak->val = dev->video_bitrate->val + 100000; break; default: return -EINVAL; } return 0; } static int vidioc_s_ctrl(struct file *file, void *private_data, struct v4l2_control *ctrl) static int hdpvr_s_ctrl(struct v4l2_ctrl *ctrl) { struct hdpvr_fh *fh = file->private_data; struct hdpvr_device *dev = fh->dev; int retval; struct hdpvr_device *dev = container_of(ctrl->handler, struct hdpvr_device, hdl); struct hdpvr_options *opt = &dev->options; int ret = -EINVAL; switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: retval = hdpvr_config_call(dev, CTRL_BRIGHTNESS, ctrl->value); if (!retval) dev->options.brightness = ctrl->value; ret = hdpvr_config_call(dev, CTRL_BRIGHTNESS, ctrl->val); if (ret) break; dev->options.brightness = ctrl->val; return 0; case V4L2_CID_CONTRAST: retval = hdpvr_config_call(dev, CTRL_CONTRAST, ctrl->value); if (!retval) dev->options.contrast = ctrl->value; ret = hdpvr_config_call(dev, CTRL_CONTRAST, ctrl->val); if (ret) break; dev->options.contrast = ctrl->val; return 0; case V4L2_CID_SATURATION: retval = hdpvr_config_call(dev, CTRL_SATURATION, ctrl->value); if (!retval) dev->options.saturation = ctrl->value; ret = hdpvr_config_call(dev, CTRL_SATURATION, ctrl->val); if (ret) break; dev->options.saturation = ctrl->val; return 0; case V4L2_CID_HUE: retval = hdpvr_config_call(dev, CTRL_HUE, ctrl->value); if (!retval) dev->options.hue = ctrl->value; ret = hdpvr_config_call(dev, CTRL_HUE, ctrl->val); if (ret) break; dev->options.hue = ctrl->val; return 0; case V4L2_CID_SHARPNESS: retval = hdpvr_config_call(dev, CTRL_SHARPNESS, ctrl->value); if (!retval) dev->options.sharpness = ctrl->value; ret = hdpvr_config_call(dev, CTRL_SHARPNESS, ctrl->val); if (ret) break; default: return -EINVAL; } return retval; } static int hdpvr_get_ctrl(struct hdpvr_options *opt, struct v4l2_ext_control *ctrl) { switch (ctrl->id) { case V4L2_CID_MPEG_AUDIO_ENCODING: ctrl->value = opt->audio_codec; break; case V4L2_CID_MPEG_VIDEO_ENCODING: ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC; break; /* case V4L2_CID_MPEG_VIDEO_B_FRAMES: */ /* ctrl->value = (opt->gop_mode & 0x2) ? 0 : 128; */ /* break; */ case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: ctrl->value = opt->bitrate_mode == HDPVR_CONSTANT ? V4L2_MPEG_VIDEO_BITRATE_MODE_CBR : V4L2_MPEG_VIDEO_BITRATE_MODE_VBR; break; case V4L2_CID_MPEG_VIDEO_BITRATE: ctrl->value = opt->bitrate * 100000; break; case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: ctrl->value = opt->peak_bitrate * 100000; break; case V4L2_CID_MPEG_STREAM_TYPE: ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_TS; break; default: return -EINVAL; } dev->options.sharpness = ctrl->val; return 0; } static int vidioc_g_ext_ctrls(struct file *file, void *priv, struct v4l2_ext_controls *ctrls) { struct hdpvr_fh *fh = file->private_data; struct hdpvr_device *dev = fh->dev; int i, err = 0; if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { for (i = 0; i < ctrls->count; i++) { struct v4l2_ext_control *ctrl = ctrls->controls + i; err = hdpvr_get_ctrl(&dev->options, ctrl); if (err) { ctrls->error_idx = i; break; } } return err; } return -EINVAL; } static int hdpvr_try_ctrl(struct v4l2_ext_control *ctrl, int ac3) { int ret = -EINVAL; switch (ctrl->id) { case V4L2_CID_MPEG_AUDIO_ENCODING: if (ctrl->value == V4L2_MPEG_AUDIO_ENCODING_AAC || (ac3 && ctrl->value == V4L2_MPEG_AUDIO_ENCODING_AC3)) ret = 0; break; case V4L2_CID_MPEG_VIDEO_ENCODING: if (ctrl->value == V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC) ret = 0; break; /* case V4L2_CID_MPEG_VIDEO_B_FRAMES: */ /* if (ctrl->value == 0 || ctrl->value == 128) */ /* ret = 0; */ /* break; */ case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR || ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) ret = 0; break; case V4L2_CID_MPEG_VIDEO_BITRATE: { uint bitrate = ctrl->value / 100000; if (bitrate >= 10 && bitrate <= 135) ret = 0; break; } case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: { uint peak_bitrate = ctrl->value / 100000; if (peak_bitrate >= 10 && peak_bitrate <= 202) ret = 0; break; } case V4L2_CID_MPEG_STREAM_TYPE: if (ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_TS) ret = 0; break; default: return -EINVAL; } return ret; } static int vidioc_try_ext_ctrls(struct file *file, void *priv, struct v4l2_ext_controls *ctrls) { struct hdpvr_fh *fh = file->private_data; struct hdpvr_device *dev = fh->dev; int i, err = 0; if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { for (i = 0; i < ctrls->count; i++) { struct v4l2_ext_control *ctrl = ctrls->controls + i; err = hdpvr_try_ctrl(ctrl, dev->flags & HDPVR_FLAG_AC3_CAP); if (err) { ctrls->error_idx = i; break; } } return err; } return -EINVAL; } static int hdpvr_set_ctrl(struct hdpvr_device *dev, struct v4l2_ext_control *ctrl) { struct hdpvr_options *opt = &dev->options; int ret = 0; switch (ctrl->id) { case V4L2_CID_MPEG_AUDIO_ENCODING: if (dev->flags & HDPVR_FLAG_AC3_CAP) { opt->audio_codec = ctrl->value; ret = hdpvr_set_audio(dev, opt->audio_input, opt->audio_codec = ctrl->val; return hdpvr_set_audio(dev, opt->audio_input, opt->audio_codec); } break; return 0; case V4L2_CID_MPEG_VIDEO_ENCODING: break; return 0; /* case V4L2_CID_MPEG_VIDEO_B_FRAMES: */ /* if (ctrl->value == 0 && !(opt->gop_mode & 0x2)) { */ /* opt->gop_mode |= 0x2; */ Loading @@ -1051,79 +785,35 @@ static int hdpvr_set_ctrl(struct hdpvr_device *dev, /* opt->gop_mode); */ /* } */ /* break; */ case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR && opt->bitrate_mode != HDPVR_CONSTANT) { case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: { uint peak_bitrate = dev->video_bitrate_peak->val / 100000; uint bitrate = dev->video_bitrate->val / 100000; if (ctrl->is_new) { if (ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) opt->bitrate_mode = HDPVR_CONSTANT; hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE, opt->bitrate_mode); } if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR && opt->bitrate_mode == HDPVR_CONSTANT) { else opt->bitrate_mode = HDPVR_VARIABLE_AVERAGE; hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE, opt->bitrate_mode); v4l2_ctrl_activate(dev->video_bitrate_peak, ctrl->val != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR); } break; case V4L2_CID_MPEG_VIDEO_BITRATE: { uint bitrate = ctrl->value / 100000; if (dev->video_bitrate_peak->is_new || dev->video_bitrate->is_new) { opt->bitrate = bitrate; if (bitrate >= opt->peak_bitrate) opt->peak_bitrate = bitrate+1; hdpvr_set_bitrate(dev); break; } case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: { uint peak_bitrate = ctrl->value / 100000; if (opt->bitrate_mode == HDPVR_CONSTANT) break; if (opt->bitrate < peak_bitrate) { opt->peak_bitrate = peak_bitrate; hdpvr_set_bitrate(dev); } else ret = -EINVAL; break; } return 0; } case V4L2_CID_MPEG_STREAM_TYPE: break; return 0; default: return -EINVAL; } return ret; } static int vidioc_s_ext_ctrls(struct file *file, void *priv, struct v4l2_ext_controls *ctrls) { struct hdpvr_fh *fh = file->private_data; struct hdpvr_device *dev = fh->dev; int i, err = 0; if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { for (i = 0; i < ctrls->count; i++) { struct v4l2_ext_control *ctrl = ctrls->controls + i; err = hdpvr_try_ctrl(ctrl, dev->flags & HDPVR_FLAG_AC3_CAP); if (err) { ctrls->error_idx = i; break; } err = hdpvr_set_ctrl(dev, ctrl); if (err) { ctrls->error_idx = i; break; } } return err; } return -EINVAL; return ret; } static int vidioc_enum_fmt_vid_cap(struct file *file, void *private_data, Loading Loading @@ -1215,12 +905,6 @@ static const struct v4l2_ioctl_ops hdpvr_ioctl_ops = { .vidioc_enumaudio = vidioc_enumaudio, .vidioc_g_audio = vidioc_g_audio, .vidioc_s_audio = vidioc_s_audio, .vidioc_queryctrl = vidioc_queryctrl, .vidioc_g_ctrl = vidioc_g_ctrl, .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, .vidioc_encoder_cmd = vidioc_encoder_cmd, Loading @@ -1237,6 +921,7 @@ static void hdpvr_device_release(struct video_device *vdev) mutex_unlock(&dev->io_mutex); v4l2_device_unregister(&dev->v4l2_dev); v4l2_ctrl_handler_free(&dev->hdl); /* deregister I2C adapter */ #if IS_ENABLED(CONFIG_I2C) Loading Loading @@ -1264,13 +949,85 @@ static const struct video_device hdpvr_video_template = { V4L2_STD_PAL_60, }; static const struct v4l2_ctrl_ops hdpvr_ctrl_ops = { .try_ctrl = hdpvr_try_ctrl, .s_ctrl = hdpvr_s_ctrl, }; int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, int devnum) { struct v4l2_ctrl_handler *hdl = &dev->hdl; bool ac3 = dev->flags & HDPVR_FLAG_AC3_CAP; int res; v4l2_ctrl_handler_init(hdl, 11); if (dev->fw_ver > 0x15) { v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, V4L2_CID_BRIGHTNESS, 0x0, 0xff, 1, 0x80); v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, V4L2_CID_CONTRAST, 0x0, 0xff, 1, 0x40); v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, V4L2_CID_SATURATION, 0x0, 0xff, 1, 0x40); v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, V4L2_CID_HUE, 0x0, 0x1e, 1, 0xf); v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, V4L2_CID_SHARPNESS, 0x0, 0xff, 1, 0x80); } else { v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, V4L2_CID_BRIGHTNESS, 0x0, 0xff, 1, 0x86); v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, V4L2_CID_CONTRAST, 0x0, 0xff, 1, 0x80); v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, V4L2_CID_SATURATION, 0x0, 0xff, 1, 0x80); v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, V4L2_CID_HUE, 0x0, 0xff, 1, 0x80); v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, V4L2_CID_SHARPNESS, 0x0, 0xff, 1, 0x80); } v4l2_ctrl_new_std_menu(hdl, &hdpvr_ctrl_ops, V4L2_CID_MPEG_STREAM_TYPE, V4L2_MPEG_STREAM_TYPE_MPEG2_TS, 0x1, V4L2_MPEG_STREAM_TYPE_MPEG2_TS); v4l2_ctrl_new_std_menu(hdl, &hdpvr_ctrl_ops, V4L2_CID_MPEG_AUDIO_ENCODING, ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 : V4L2_MPEG_AUDIO_ENCODING_AAC, 0x7, V4L2_MPEG_AUDIO_ENCODING_AAC); v4l2_ctrl_new_std_menu(hdl, &hdpvr_ctrl_ops, V4L2_CID_MPEG_VIDEO_ENCODING, V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 0x3, V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC); dev->video_mode = v4l2_ctrl_new_std_menu(hdl, &hdpvr_ctrl_ops, V4L2_CID_MPEG_VIDEO_BITRATE_MODE, V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0, V4L2_MPEG_VIDEO_BITRATE_MODE_CBR); dev->video_bitrate = v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, V4L2_CID_MPEG_VIDEO_BITRATE, 1000000, 13500000, 100000, 6500000); dev->video_bitrate_peak = v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, 1100000, 20200000, 100000, 9000000); dev->v4l2_dev.ctrl_handler = hdl; if (hdl->error) { res = hdl->error; v4l2_err(&dev->v4l2_dev, "Could not register controls\n"); goto error; } v4l2_ctrl_cluster(3, &dev->video_mode); res = v4l2_ctrl_handler_setup(hdl); if (res < 0) { v4l2_err(&dev->v4l2_dev, "Could not setup controls\n"); goto error; } /* setup and register video device */ dev->video_dev = video_device_alloc(); if (!dev->video_dev) { v4l2_err(&dev->v4l2_dev, "video_device_alloc() failed\n"); res = -ENOMEM; goto error; } Loading @@ -1279,12 +1036,14 @@ int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, dev->video_dev->parent = parent; video_set_drvdata(dev->video_dev, dev); if (video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum)) { res = video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum); if (res < 0) { v4l2_err(&dev->v4l2_dev, "video_device registration failed\n"); goto error; } return 0; error: return -ENOMEM; v4l2_ctrl_handler_free(hdl); return res; } drivers/media/usb/hdpvr/hdpvr.h +8 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include <linux/videodev2.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> #include <media/ir-kbd-i2c.h> #define HDPVR_MAX 8 Loading Loading @@ -65,10 +66,17 @@ struct hdpvr_options { struct hdpvr_device { /* the v4l device for this device */ struct video_device *video_dev; /* the control handler for this device */ struct v4l2_ctrl_handler hdl; /* the usb device for this device */ struct usb_device *udev; /* v4l2-device unused */ struct v4l2_device v4l2_dev; struct { /* video mode/bitrate control cluster */ struct v4l2_ctrl *video_mode; struct v4l2_ctrl *video_bitrate; struct v4l2_ctrl *video_bitrate_peak; }; /* the max packet size of the bulk endpoint */ size_t bulk_in_size; Loading Loading
drivers/media/usb/hdpvr/hdpvr-video.c +137 −378 Original line number Diff line number Diff line Loading @@ -710,335 +710,69 @@ static int vidioc_g_audio(struct file *file, void *private_data, return 0; } static const s32 supported_v4l2_ctrls[] = { V4L2_CID_BRIGHTNESS, V4L2_CID_CONTRAST, V4L2_CID_SATURATION, V4L2_CID_HUE, V4L2_CID_SHARPNESS, V4L2_CID_MPEG_AUDIO_ENCODING, V4L2_CID_MPEG_VIDEO_ENCODING, V4L2_CID_MPEG_VIDEO_BITRATE_MODE, V4L2_CID_MPEG_VIDEO_BITRATE, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, }; static int fill_queryctrl(struct hdpvr_options *opt, struct v4l2_queryctrl *qc, int ac3, int fw_ver) static int hdpvr_try_ctrl(struct v4l2_ctrl *ctrl) { int err; if (fw_ver > 0x15) { switch (qc->id) { case V4L2_CID_BRIGHTNESS: return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); case V4L2_CID_CONTRAST: return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x40); case V4L2_CID_SATURATION: return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x40); case V4L2_CID_HUE: return v4l2_ctrl_query_fill(qc, 0x0, 0x1e, 1, 0xf); case V4L2_CID_SHARPNESS: return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); } } else { switch (qc->id) { case V4L2_CID_BRIGHTNESS: return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x86); case V4L2_CID_CONTRAST: return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); case V4L2_CID_SATURATION: return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); case V4L2_CID_HUE: return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); case V4L2_CID_SHARPNESS: return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); } } switch (qc->id) { case V4L2_CID_MPEG_AUDIO_ENCODING: return v4l2_ctrl_query_fill( qc, V4L2_MPEG_AUDIO_ENCODING_AAC, ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 : V4L2_MPEG_AUDIO_ENCODING_AAC, 1, V4L2_MPEG_AUDIO_ENCODING_AAC); case V4L2_CID_MPEG_VIDEO_ENCODING: return v4l2_ctrl_query_fill( qc, V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 1, V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC); /* case V4L2_CID_MPEG_VIDEO_? maybe keyframe interval: */ /* return v4l2_ctrl_query_fill(qc, 0, 128, 128, 0); */ case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: return v4l2_ctrl_query_fill( qc, V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1, V4L2_MPEG_VIDEO_BITRATE_MODE_CBR); case V4L2_CID_MPEG_VIDEO_BITRATE: return v4l2_ctrl_query_fill(qc, 1000000, 13500000, 100000, 6500000); case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: err = v4l2_ctrl_query_fill(qc, 1100000, 20200000, 100000, 9000000); if (!err && opt->bitrate_mode == HDPVR_CONSTANT) qc->flags |= V4L2_CTRL_FLAG_INACTIVE; return err; default: return -EINVAL; } } static int vidioc_queryctrl(struct file *file, void *private_data, struct v4l2_queryctrl *qc) { struct hdpvr_fh *fh = file->private_data; struct hdpvr_device *dev = fh->dev; int i, next; u32 id = qc->id; memset(qc, 0, sizeof(*qc)); next = !!(id & V4L2_CTRL_FLAG_NEXT_CTRL); qc->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL; for (i = 0; i < ARRAY_SIZE(supported_v4l2_ctrls); i++) { if (next) { if (qc->id < supported_v4l2_ctrls[i]) qc->id = supported_v4l2_ctrls[i]; else continue; } if (qc->id == supported_v4l2_ctrls[i]) return fill_queryctrl(&dev->options, qc, dev->flags & HDPVR_FLAG_AC3_CAP, dev->fw_ver); if (qc->id < supported_v4l2_ctrls[i]) break; } return -EINVAL; } static int vidioc_g_ctrl(struct file *file, void *private_data, struct v4l2_control *ctrl) { struct hdpvr_fh *fh = file->private_data; struct hdpvr_device *dev = fh->dev; struct hdpvr_device *dev = container_of(ctrl->handler, struct hdpvr_device, hdl); switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: ctrl->value = dev->options.brightness; break; case V4L2_CID_CONTRAST: ctrl->value = dev->options.contrast; break; case V4L2_CID_SATURATION: ctrl->value = dev->options.saturation; break; case V4L2_CID_HUE: ctrl->value = dev->options.hue; break; case V4L2_CID_SHARPNESS: ctrl->value = dev->options.sharpness; case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: if (ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR && dev->video_bitrate->val >= dev->video_bitrate_peak->val) dev->video_bitrate_peak->val = dev->video_bitrate->val + 100000; break; default: return -EINVAL; } return 0; } static int vidioc_s_ctrl(struct file *file, void *private_data, struct v4l2_control *ctrl) static int hdpvr_s_ctrl(struct v4l2_ctrl *ctrl) { struct hdpvr_fh *fh = file->private_data; struct hdpvr_device *dev = fh->dev; int retval; struct hdpvr_device *dev = container_of(ctrl->handler, struct hdpvr_device, hdl); struct hdpvr_options *opt = &dev->options; int ret = -EINVAL; switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: retval = hdpvr_config_call(dev, CTRL_BRIGHTNESS, ctrl->value); if (!retval) dev->options.brightness = ctrl->value; ret = hdpvr_config_call(dev, CTRL_BRIGHTNESS, ctrl->val); if (ret) break; dev->options.brightness = ctrl->val; return 0; case V4L2_CID_CONTRAST: retval = hdpvr_config_call(dev, CTRL_CONTRAST, ctrl->value); if (!retval) dev->options.contrast = ctrl->value; ret = hdpvr_config_call(dev, CTRL_CONTRAST, ctrl->val); if (ret) break; dev->options.contrast = ctrl->val; return 0; case V4L2_CID_SATURATION: retval = hdpvr_config_call(dev, CTRL_SATURATION, ctrl->value); if (!retval) dev->options.saturation = ctrl->value; ret = hdpvr_config_call(dev, CTRL_SATURATION, ctrl->val); if (ret) break; dev->options.saturation = ctrl->val; return 0; case V4L2_CID_HUE: retval = hdpvr_config_call(dev, CTRL_HUE, ctrl->value); if (!retval) dev->options.hue = ctrl->value; ret = hdpvr_config_call(dev, CTRL_HUE, ctrl->val); if (ret) break; dev->options.hue = ctrl->val; return 0; case V4L2_CID_SHARPNESS: retval = hdpvr_config_call(dev, CTRL_SHARPNESS, ctrl->value); if (!retval) dev->options.sharpness = ctrl->value; ret = hdpvr_config_call(dev, CTRL_SHARPNESS, ctrl->val); if (ret) break; default: return -EINVAL; } return retval; } static int hdpvr_get_ctrl(struct hdpvr_options *opt, struct v4l2_ext_control *ctrl) { switch (ctrl->id) { case V4L2_CID_MPEG_AUDIO_ENCODING: ctrl->value = opt->audio_codec; break; case V4L2_CID_MPEG_VIDEO_ENCODING: ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC; break; /* case V4L2_CID_MPEG_VIDEO_B_FRAMES: */ /* ctrl->value = (opt->gop_mode & 0x2) ? 0 : 128; */ /* break; */ case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: ctrl->value = opt->bitrate_mode == HDPVR_CONSTANT ? V4L2_MPEG_VIDEO_BITRATE_MODE_CBR : V4L2_MPEG_VIDEO_BITRATE_MODE_VBR; break; case V4L2_CID_MPEG_VIDEO_BITRATE: ctrl->value = opt->bitrate * 100000; break; case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: ctrl->value = opt->peak_bitrate * 100000; break; case V4L2_CID_MPEG_STREAM_TYPE: ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_TS; break; default: return -EINVAL; } dev->options.sharpness = ctrl->val; return 0; } static int vidioc_g_ext_ctrls(struct file *file, void *priv, struct v4l2_ext_controls *ctrls) { struct hdpvr_fh *fh = file->private_data; struct hdpvr_device *dev = fh->dev; int i, err = 0; if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { for (i = 0; i < ctrls->count; i++) { struct v4l2_ext_control *ctrl = ctrls->controls + i; err = hdpvr_get_ctrl(&dev->options, ctrl); if (err) { ctrls->error_idx = i; break; } } return err; } return -EINVAL; } static int hdpvr_try_ctrl(struct v4l2_ext_control *ctrl, int ac3) { int ret = -EINVAL; switch (ctrl->id) { case V4L2_CID_MPEG_AUDIO_ENCODING: if (ctrl->value == V4L2_MPEG_AUDIO_ENCODING_AAC || (ac3 && ctrl->value == V4L2_MPEG_AUDIO_ENCODING_AC3)) ret = 0; break; case V4L2_CID_MPEG_VIDEO_ENCODING: if (ctrl->value == V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC) ret = 0; break; /* case V4L2_CID_MPEG_VIDEO_B_FRAMES: */ /* if (ctrl->value == 0 || ctrl->value == 128) */ /* ret = 0; */ /* break; */ case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR || ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) ret = 0; break; case V4L2_CID_MPEG_VIDEO_BITRATE: { uint bitrate = ctrl->value / 100000; if (bitrate >= 10 && bitrate <= 135) ret = 0; break; } case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: { uint peak_bitrate = ctrl->value / 100000; if (peak_bitrate >= 10 && peak_bitrate <= 202) ret = 0; break; } case V4L2_CID_MPEG_STREAM_TYPE: if (ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_TS) ret = 0; break; default: return -EINVAL; } return ret; } static int vidioc_try_ext_ctrls(struct file *file, void *priv, struct v4l2_ext_controls *ctrls) { struct hdpvr_fh *fh = file->private_data; struct hdpvr_device *dev = fh->dev; int i, err = 0; if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { for (i = 0; i < ctrls->count; i++) { struct v4l2_ext_control *ctrl = ctrls->controls + i; err = hdpvr_try_ctrl(ctrl, dev->flags & HDPVR_FLAG_AC3_CAP); if (err) { ctrls->error_idx = i; break; } } return err; } return -EINVAL; } static int hdpvr_set_ctrl(struct hdpvr_device *dev, struct v4l2_ext_control *ctrl) { struct hdpvr_options *opt = &dev->options; int ret = 0; switch (ctrl->id) { case V4L2_CID_MPEG_AUDIO_ENCODING: if (dev->flags & HDPVR_FLAG_AC3_CAP) { opt->audio_codec = ctrl->value; ret = hdpvr_set_audio(dev, opt->audio_input, opt->audio_codec = ctrl->val; return hdpvr_set_audio(dev, opt->audio_input, opt->audio_codec); } break; return 0; case V4L2_CID_MPEG_VIDEO_ENCODING: break; return 0; /* case V4L2_CID_MPEG_VIDEO_B_FRAMES: */ /* if (ctrl->value == 0 && !(opt->gop_mode & 0x2)) { */ /* opt->gop_mode |= 0x2; */ Loading @@ -1051,79 +785,35 @@ static int hdpvr_set_ctrl(struct hdpvr_device *dev, /* opt->gop_mode); */ /* } */ /* break; */ case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR && opt->bitrate_mode != HDPVR_CONSTANT) { case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: { uint peak_bitrate = dev->video_bitrate_peak->val / 100000; uint bitrate = dev->video_bitrate->val / 100000; if (ctrl->is_new) { if (ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) opt->bitrate_mode = HDPVR_CONSTANT; hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE, opt->bitrate_mode); } if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR && opt->bitrate_mode == HDPVR_CONSTANT) { else opt->bitrate_mode = HDPVR_VARIABLE_AVERAGE; hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE, opt->bitrate_mode); v4l2_ctrl_activate(dev->video_bitrate_peak, ctrl->val != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR); } break; case V4L2_CID_MPEG_VIDEO_BITRATE: { uint bitrate = ctrl->value / 100000; if (dev->video_bitrate_peak->is_new || dev->video_bitrate->is_new) { opt->bitrate = bitrate; if (bitrate >= opt->peak_bitrate) opt->peak_bitrate = bitrate+1; hdpvr_set_bitrate(dev); break; } case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: { uint peak_bitrate = ctrl->value / 100000; if (opt->bitrate_mode == HDPVR_CONSTANT) break; if (opt->bitrate < peak_bitrate) { opt->peak_bitrate = peak_bitrate; hdpvr_set_bitrate(dev); } else ret = -EINVAL; break; } return 0; } case V4L2_CID_MPEG_STREAM_TYPE: break; return 0; default: return -EINVAL; } return ret; } static int vidioc_s_ext_ctrls(struct file *file, void *priv, struct v4l2_ext_controls *ctrls) { struct hdpvr_fh *fh = file->private_data; struct hdpvr_device *dev = fh->dev; int i, err = 0; if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { for (i = 0; i < ctrls->count; i++) { struct v4l2_ext_control *ctrl = ctrls->controls + i; err = hdpvr_try_ctrl(ctrl, dev->flags & HDPVR_FLAG_AC3_CAP); if (err) { ctrls->error_idx = i; break; } err = hdpvr_set_ctrl(dev, ctrl); if (err) { ctrls->error_idx = i; break; } } return err; } return -EINVAL; return ret; } static int vidioc_enum_fmt_vid_cap(struct file *file, void *private_data, Loading Loading @@ -1215,12 +905,6 @@ static const struct v4l2_ioctl_ops hdpvr_ioctl_ops = { .vidioc_enumaudio = vidioc_enumaudio, .vidioc_g_audio = vidioc_g_audio, .vidioc_s_audio = vidioc_s_audio, .vidioc_queryctrl = vidioc_queryctrl, .vidioc_g_ctrl = vidioc_g_ctrl, .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, .vidioc_encoder_cmd = vidioc_encoder_cmd, Loading @@ -1237,6 +921,7 @@ static void hdpvr_device_release(struct video_device *vdev) mutex_unlock(&dev->io_mutex); v4l2_device_unregister(&dev->v4l2_dev); v4l2_ctrl_handler_free(&dev->hdl); /* deregister I2C adapter */ #if IS_ENABLED(CONFIG_I2C) Loading Loading @@ -1264,13 +949,85 @@ static const struct video_device hdpvr_video_template = { V4L2_STD_PAL_60, }; static const struct v4l2_ctrl_ops hdpvr_ctrl_ops = { .try_ctrl = hdpvr_try_ctrl, .s_ctrl = hdpvr_s_ctrl, }; int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, int devnum) { struct v4l2_ctrl_handler *hdl = &dev->hdl; bool ac3 = dev->flags & HDPVR_FLAG_AC3_CAP; int res; v4l2_ctrl_handler_init(hdl, 11); if (dev->fw_ver > 0x15) { v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, V4L2_CID_BRIGHTNESS, 0x0, 0xff, 1, 0x80); v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, V4L2_CID_CONTRAST, 0x0, 0xff, 1, 0x40); v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, V4L2_CID_SATURATION, 0x0, 0xff, 1, 0x40); v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, V4L2_CID_HUE, 0x0, 0x1e, 1, 0xf); v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, V4L2_CID_SHARPNESS, 0x0, 0xff, 1, 0x80); } else { v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, V4L2_CID_BRIGHTNESS, 0x0, 0xff, 1, 0x86); v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, V4L2_CID_CONTRAST, 0x0, 0xff, 1, 0x80); v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, V4L2_CID_SATURATION, 0x0, 0xff, 1, 0x80); v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, V4L2_CID_HUE, 0x0, 0xff, 1, 0x80); v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, V4L2_CID_SHARPNESS, 0x0, 0xff, 1, 0x80); } v4l2_ctrl_new_std_menu(hdl, &hdpvr_ctrl_ops, V4L2_CID_MPEG_STREAM_TYPE, V4L2_MPEG_STREAM_TYPE_MPEG2_TS, 0x1, V4L2_MPEG_STREAM_TYPE_MPEG2_TS); v4l2_ctrl_new_std_menu(hdl, &hdpvr_ctrl_ops, V4L2_CID_MPEG_AUDIO_ENCODING, ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 : V4L2_MPEG_AUDIO_ENCODING_AAC, 0x7, V4L2_MPEG_AUDIO_ENCODING_AAC); v4l2_ctrl_new_std_menu(hdl, &hdpvr_ctrl_ops, V4L2_CID_MPEG_VIDEO_ENCODING, V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 0x3, V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC); dev->video_mode = v4l2_ctrl_new_std_menu(hdl, &hdpvr_ctrl_ops, V4L2_CID_MPEG_VIDEO_BITRATE_MODE, V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0, V4L2_MPEG_VIDEO_BITRATE_MODE_CBR); dev->video_bitrate = v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, V4L2_CID_MPEG_VIDEO_BITRATE, 1000000, 13500000, 100000, 6500000); dev->video_bitrate_peak = v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, 1100000, 20200000, 100000, 9000000); dev->v4l2_dev.ctrl_handler = hdl; if (hdl->error) { res = hdl->error; v4l2_err(&dev->v4l2_dev, "Could not register controls\n"); goto error; } v4l2_ctrl_cluster(3, &dev->video_mode); res = v4l2_ctrl_handler_setup(hdl); if (res < 0) { v4l2_err(&dev->v4l2_dev, "Could not setup controls\n"); goto error; } /* setup and register video device */ dev->video_dev = video_device_alloc(); if (!dev->video_dev) { v4l2_err(&dev->v4l2_dev, "video_device_alloc() failed\n"); res = -ENOMEM; goto error; } Loading @@ -1279,12 +1036,14 @@ int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, dev->video_dev->parent = parent; video_set_drvdata(dev->video_dev, dev); if (video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum)) { res = video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum); if (res < 0) { v4l2_err(&dev->v4l2_dev, "video_device registration failed\n"); goto error; } return 0; error: return -ENOMEM; v4l2_ctrl_handler_free(hdl); return res; }
drivers/media/usb/hdpvr/hdpvr.h +8 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include <linux/videodev2.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> #include <media/ir-kbd-i2c.h> #define HDPVR_MAX 8 Loading Loading @@ -65,10 +66,17 @@ struct hdpvr_options { struct hdpvr_device { /* the v4l device for this device */ struct video_device *video_dev; /* the control handler for this device */ struct v4l2_ctrl_handler hdl; /* the usb device for this device */ struct usb_device *udev; /* v4l2-device unused */ struct v4l2_device v4l2_dev; struct { /* video mode/bitrate control cluster */ struct v4l2_ctrl *video_mode; struct v4l2_ctrl *video_bitrate; struct v4l2_ctrl *video_bitrate_peak; }; /* the max packet size of the bulk endpoint */ size_t bulk_in_size; Loading