media: sun6i-csi: Move power management to runtime pm in capture

Let's just enable the module when we start using it (at stream on)
and benefit from runtime pm instead of enabling it at first open.

Also reorder the call to v4l2_pipeline_pm_get.

Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
This commit is contained in:
Paul Kocialkowski 2022-11-03 16:30:53 +00:00 коммит произвёл Mauro Carvalho Chehab
Родитель 85469b9e66
Коммит d0895e0f81
3 изменённых файлов: 22 добавлений и 52 удалений

Просмотреть файл

@ -148,30 +148,6 @@ bool sun6i_csi_is_format_supported(struct sun6i_csi_device *csi_dev,
return false;
}
int sun6i_csi_set_power(struct sun6i_csi_device *csi_dev, bool enable)
{
struct device *dev = csi_dev->dev;
struct regmap *regmap = csi_dev->regmap;
int ret;
if (!enable) {
regmap_update_bits(regmap, SUN6I_CSI_EN_REG,
SUN6I_CSI_EN_CSI_EN, 0);
pm_runtime_put(dev);
return 0;
}
ret = pm_runtime_resume_and_get(dev);
if (ret < 0)
return ret;
regmap_update_bits(regmap, SUN6I_CSI_EN_REG, SUN6I_CSI_EN_CSI_EN,
SUN6I_CSI_EN_CSI_EN);
return 0;
}
static enum csi_input_fmt get_csi_input_format(struct sun6i_csi_device *csi_dev,
u32 mbus_code, u32 pixformat)
{

Просмотреть файл

@ -77,15 +77,6 @@ struct sun6i_csi_variant {
bool sun6i_csi_is_format_supported(struct sun6i_csi_device *csi_dev,
u32 pixformat, u32 mbus_code);
/**
* sun6i_csi_set_power() - power on/off the csi
* @csi_dev: pointer to the csi device
* @enable: on/off
*
* Return: 0 if successful, error code otherwise.
*/
int sun6i_csi_set_power(struct sun6i_csi_device *csi_dev, bool enable);
/**
* sun6i_csi_update_config() - update the csi register settings
* @csi_dev: pointer to the csi device

Просмотреть файл

@ -6,6 +6,7 @@
*/
#include <linux/of.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <media/v4l2-device.h>
@ -141,6 +142,9 @@ static void sun6i_csi_capture_enable(struct sun6i_csi_device *csi_dev)
{
struct regmap *regmap = csi_dev->regmap;
regmap_update_bits(regmap, SUN6I_CSI_EN_REG, SUN6I_CSI_EN_CSI_EN,
SUN6I_CSI_EN_CSI_EN);
regmap_update_bits(regmap, SUN6I_CSI_CAP_REG, SUN6I_CSI_CAP_VCAP_ON,
SUN6I_CSI_CAP_VCAP_ON);
}
@ -150,6 +154,7 @@ static void sun6i_csi_capture_disable(struct sun6i_csi_device *csi_dev)
struct regmap *regmap = csi_dev->regmap;
regmap_update_bits(regmap, SUN6I_CSI_CAP_REG, SUN6I_CSI_CAP_VCAP_ON, 0);
regmap_update_bits(regmap, SUN6I_CSI_EN_REG, SUN6I_CSI_EN_CSI_EN, 0);
}
static void
@ -382,6 +387,7 @@ static int sun6i_csi_capture_start_streaming(struct vb2_queue *queue,
struct sun6i_csi_capture *capture = &csi_dev->capture;
struct sun6i_csi_capture_state *state = &capture->state;
struct video_device *video_dev = &capture->video_dev;
struct device *dev = csi_dev->dev;
struct v4l2_subdev *subdev;
int ret;
@ -402,6 +408,12 @@ static int sun6i_csi_capture_start_streaming(struct vb2_queue *queue,
goto error_media_pipeline;
}
/* PM */
ret = pm_runtime_resume_and_get(dev);
if (ret < 0)
goto error_media_pipeline;
/* Clear */
sun6i_csi_capture_irq_clear(csi_dev);
@ -429,6 +441,8 @@ error_stream:
sun6i_csi_capture_disable(csi_dev);
sun6i_csi_capture_irq_disable(csi_dev);
pm_runtime_put(dev);
error_media_pipeline:
video_device_pipeline_stop(video_dev);
@ -442,6 +456,7 @@ static void sun6i_csi_capture_stop_streaming(struct vb2_queue *queue)
{
struct sun6i_csi_device *csi_dev = vb2_get_drv_priv(queue);
struct sun6i_csi_capture *capture = &csi_dev->capture;
struct device *dev = csi_dev->dev;
struct v4l2_subdev *subdev;
subdev = sun6i_csi_capture_remote_subdev(capture, NULL);
@ -451,6 +466,8 @@ static void sun6i_csi_capture_stop_streaming(struct vb2_queue *queue)
sun6i_csi_capture_disable(csi_dev);
sun6i_csi_capture_irq_disable(csi_dev);
pm_runtime_put(dev);
video_device_pipeline_stop(&capture->video_dev);
sun6i_csi_capture_state_cleanup(csi_dev, true);
@ -635,27 +652,20 @@ static int sun6i_csi_capture_open(struct file *file)
if (mutex_lock_interruptible(&capture->lock))
return -ERESTARTSYS;
ret = v4l2_fh_open(file);
ret = v4l2_pipeline_pm_get(&capture->video_dev.entity);
if (ret < 0)
goto error_lock;
ret = v4l2_pipeline_pm_get(&capture->video_dev.entity);
ret = v4l2_fh_open(file);
if (ret < 0)
goto error_v4l2_fh;
/* Power on at first open. */
if (v4l2_fh_is_singular_file(file)) {
ret = sun6i_csi_set_power(csi_dev, true);
if (ret < 0)
goto error_v4l2_fh;
}
goto error_pipeline;
mutex_unlock(&capture->lock);
return 0;
error_v4l2_fh:
v4l2_fh_release(file);
error_pipeline:
v4l2_pipeline_pm_put(&capture->video_dev.entity);
error_lock:
mutex_unlock(&capture->lock);
@ -667,19 +677,12 @@ static int sun6i_csi_capture_close(struct file *file)
{
struct sun6i_csi_device *csi_dev = video_drvdata(file);
struct sun6i_csi_capture *capture = &csi_dev->capture;
bool last_close;
mutex_lock(&capture->lock);
last_close = v4l2_fh_is_singular_file(file);
_vb2_fop_release(file, NULL);
v4l2_pipeline_pm_put(&capture->video_dev.entity);
/* Power off at last close. */
if (last_close)
sun6i_csi_set_power(csi_dev, false);
mutex_unlock(&capture->lock);
return 0;