media: ov772x: make set_fmt() and s_frame_interval() return -EBUSY while streaming

The ov772x driver is going to offer a V4L2 sub-device interface, so
changing the output data format and the frame interval on this sub-device
can be made anytime.  However, these requests are preferred to fail while
the video stream on the device is active.

Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
This commit is contained in:
Akinobu Mita 2018-05-06 10:19:28 -04:00 committed by Mauro Carvalho Chehab
parent 95f5a45aea
commit 7b9998c936
1 changed files with 33 additions and 10 deletions

View File

@ -424,9 +424,10 @@ struct ov772x_priv {
/* band_filter = COM8[5] ? 256 - BDBASE : 0 */ /* band_filter = COM8[5] ? 256 - BDBASE : 0 */
struct v4l2_ctrl *band_filter_ctrl; struct v4l2_ctrl *band_filter_ctrl;
unsigned int fps; unsigned int fps;
/* lock to protect power_count */ /* lock to protect power_count and streaming */
struct mutex lock; struct mutex lock;
int power_count; int power_count;
int streaming;
#ifdef CONFIG_MEDIA_CONTROLLER #ifdef CONFIG_MEDIA_CONTROLLER
struct media_pad pad; struct media_pad pad;
#endif #endif
@ -603,18 +604,28 @@ static int ov772x_s_stream(struct v4l2_subdev *sd, int enable)
{ {
struct i2c_client *client = v4l2_get_subdevdata(sd); struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov772x_priv *priv = to_ov772x(sd); struct ov772x_priv *priv = to_ov772x(sd);
int ret = 0;
if (!enable) { mutex_lock(&priv->lock);
ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE);
return 0; if (priv->streaming == enable)
goto done;
ret = ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE,
enable ? 0 : SOFT_SLEEP_MODE);
if (ret)
goto done;
if (enable) {
dev_dbg(&client->dev, "format %d, win %s\n",
priv->cfmt->code, priv->win->name);
} }
priv->streaming = enable;
ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0); done:
mutex_unlock(&priv->lock);
dev_dbg(&client->dev, "format %d, win %s\n", return ret;
priv->cfmt->code, priv->win->name);
return 0;
} }
static unsigned int ov772x_select_fps(struct ov772x_priv *priv, static unsigned int ov772x_select_fps(struct ov772x_priv *priv,
@ -743,9 +754,15 @@ static int ov772x_s_frame_interval(struct v4l2_subdev *sd,
unsigned int fps; unsigned int fps;
int ret = 0; int ret = 0;
mutex_lock(&priv->lock);
if (priv->streaming) {
ret = -EBUSY;
goto error;
}
fps = ov772x_select_fps(priv, tpf); fps = ov772x_select_fps(priv, tpf);
mutex_lock(&priv->lock);
/* /*
* If the device is not powered up by the host driver do * If the device is not powered up by the host driver do
* not apply any changes to H/W at this time. Instead * not apply any changes to H/W at this time. Instead
@ -1222,6 +1239,12 @@ static int ov772x_set_fmt(struct v4l2_subdev *sd,
} }
mutex_lock(&priv->lock); mutex_lock(&priv->lock);
if (priv->streaming) {
ret = -EBUSY;
goto error;
}
/* /*
* If the device is not powered up by the host driver do * If the device is not powered up by the host driver do
* not apply any changes to H/W at this time. Instead * not apply any changes to H/W at this time. Instead