Commit dd90caa0 authored by Lad Prabhakar's avatar Lad Prabhakar Committed by Mauro Carvalho Chehab
Browse files

media: i2c: imx219: Balance runtime PM use-count



Move incrementing/decrementing runtime PM count to
imx219_start_streaming()/imx219_stop_streaming() functions respectively.

This fixes an issue of unbalanced runtime PM count in resume callback
error path where streaming is stopped and runtime PM count is left
unbalanced.

Fixes: 1283b3b8 ("media: i2c: Add driver for Sony IMX219 sensor")
Reported-by: default avatarPavel Machek <pavel@denx.de>
Signed-off-by: default avatarLad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent 745d4612
Loading
Loading
Loading
Loading
+17 −15
Original line number Diff line number Diff line
@@ -1035,37 +1035,47 @@ static int imx219_start_streaming(struct imx219 *imx219)
	const struct imx219_reg_list *reg_list;
	int ret;

	ret = pm_runtime_get_sync(&client->dev);
	if (ret < 0) {
		pm_runtime_put_noidle(&client->dev);
		return ret;
	}

	/* Apply default values of current mode */
	reg_list = &imx219->mode->reg_list;
	ret = imx219_write_regs(imx219, reg_list->regs, reg_list->num_of_regs);
	if (ret) {
		dev_err(&client->dev, "%s failed to set mode\n", __func__);
		return ret;
		goto err_rpm_put;
	}

	ret = imx219_set_framefmt(imx219);
	if (ret) {
		dev_err(&client->dev, "%s failed to set frame format: %d\n",
			__func__, ret);
		return ret;
		goto err_rpm_put;
	}

	/* Apply customized values from user */
	ret =  __v4l2_ctrl_handler_setup(imx219->sd.ctrl_handler);
	if (ret)
		return ret;
		goto err_rpm_put;

	/* set stream on register */
	ret = imx219_write_reg(imx219, IMX219_REG_MODE_SELECT,
			       IMX219_REG_VALUE_08BIT, IMX219_MODE_STREAMING);
	if (ret)
		return ret;
		goto err_rpm_put;

	/* vflip and hflip cannot change during streaming */
	__v4l2_ctrl_grab(imx219->vflip, true);
	__v4l2_ctrl_grab(imx219->hflip, true);

	return 0;

err_rpm_put:
	pm_runtime_put(&client->dev);
	return ret;
}

static void imx219_stop_streaming(struct imx219 *imx219)
@@ -1081,12 +1091,13 @@ static void imx219_stop_streaming(struct imx219 *imx219)

	__v4l2_ctrl_grab(imx219->vflip, false);
	__v4l2_ctrl_grab(imx219->hflip, false);

	pm_runtime_put(&client->dev);
}

static int imx219_set_stream(struct v4l2_subdev *sd, int enable)
{
	struct imx219 *imx219 = to_imx219(sd);
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	int ret = 0;

	mutex_lock(&imx219->mutex);
@@ -1096,22 +1107,15 @@ static int imx219_set_stream(struct v4l2_subdev *sd, int enable)
	}

	if (enable) {
		ret = pm_runtime_get_sync(&client->dev);
		if (ret < 0) {
			pm_runtime_put_noidle(&client->dev);
			goto err_unlock;
		}

		/*
		 * Apply default & customized values
		 * and then start streaming.
		 */
		ret = imx219_start_streaming(imx219);
		if (ret)
			goto err_rpm_put;
			goto err_unlock;
	} else {
		imx219_stop_streaming(imx219);
		pm_runtime_put(&client->dev);
	}

	imx219->streaming = enable;
@@ -1120,8 +1124,6 @@ static int imx219_set_stream(struct v4l2_subdev *sd, int enable)

	return ret;

err_rpm_put:
	pm_runtime_put(&client->dev);
err_unlock:
	mutex_unlock(&imx219->mutex);