V4L/DVB (6088): cx2341x: some controls can't be changed while the device is busy
The driver should now pass the 'busy' state of the device to the cx2341x
module whenever controls are set or tried. -EBUSY will be returned if
the device is busy and the user attempts to modify certain 'dangerous'
controls. It concerns controls that change the audio or video
compression mode and bitrates.
The cx88-blackbird and pvrusb2 drivers currently always pass '0' (not busy)
to the cx2341x, effectively keeping the old behavior for now.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c
index 904bba0..6230425 100644
--- a/drivers/media/video/cx2341x.c
+++ b/drivers/media/video/cx2341x.c
@@ -190,17 +190,21 @@
/* Map the control ID to the correct field in the cx2341x_mpeg_params
struct. Return -EINVAL if the ID is unknown, else return 0. */
-static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params,
+static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy,
struct v4l2_ext_control *ctrl)
{
switch (ctrl->id) {
case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+ if (busy)
+ return -EBUSY;
params->audio_sampling_freq = ctrl->value;
break;
case V4L2_CID_MPEG_AUDIO_ENCODING:
params->audio_encoding = ctrl->value;
break;
case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+ if (busy)
+ return -EBUSY;
params->audio_l2_bitrate = ctrl->value;
break;
case V4L2_CID_MPEG_AUDIO_MODE:
@@ -245,6 +249,8 @@
params->video_gop_closure = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+ if (busy)
+ return -EBUSY;
/* MPEG-1 only allows CBR */
if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&
ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
@@ -252,9 +258,13 @@
params->video_bitrate_mode = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_BITRATE:
+ if (busy)
+ return -EBUSY;
params->video_bitrate = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+ if (busy)
+ return -EBUSY;
params->video_bitrate_peak = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
@@ -267,6 +277,8 @@
params->video_mute_yuv = ctrl->value;
break;
case V4L2_CID_MPEG_STREAM_TYPE:
+ if (busy)
+ return -EBUSY;
params->stream_type = ctrl->value;
params->video_encoding =
(params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
@@ -631,7 +643,7 @@
(params->audio_crc << 14);
}
-int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params,
+int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,
struct v4l2_ext_controls *ctrls, unsigned int cmd)
{
int err = 0;
@@ -663,7 +675,7 @@
err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
if (err)
break;
- err = cx2341x_set_ctrl(params, ctrl);
+ err = cx2341x_set_ctrl(params, busy, ctrl);
if (err)
break;
}