diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 6fda40cdc31e..49a80dadd7d1 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -8561,7 +8561,7 @@ int rkcif_do_start_stream(struct rkcif_stream *stream, enum rkcif_stream_mode mo } } if (dev->chip_id >= CHIP_RK1808_CIF) { - if (dev->active_sensor && + if (dev->active_sensor && (dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_DPHY || dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_CPHY || dev->active_sensor->mbus.type == V4L2_MBUS_CCP2)) { @@ -8997,12 +8997,18 @@ void rkcif_stream_init(struct rkcif_device *dev, u32 id) stream->frame_loss = 0; } -static int rkcif_sensor_set_power(struct rkcif_stream *stream, int on) +int rkcif_sensor_set_power(struct rkcif_stream *stream, int on) { struct rkcif_device *cif_dev = stream->cifdev; struct sditf_priv *priv = cif_dev->sditf[0]; int i = 0; + if (!on && atomic_dec_if_positive(&cif_dev->sd_power_cnt)) + return 0; + + if (on && atomic_inc_return(&cif_dev->sd_power_cnt) > 1) + return 0; + if (cif_dev->terminal_sensor.sd) v4l2_subdev_call(cif_dev->terminal_sensor.sd, core, s_power, on); @@ -9068,11 +9074,11 @@ static int rkcif_fh_open(struct file *filp) ret = v4l2_pipeline_pm_get(&vnode->vdev.entity); v4l2_dbg(1, rkcif_debug, vdev, "open video, entity use_count %d\n", vnode->vdev.entity.use_count); + ret = rkcif_sensor_set_power(stream, on); mutex_unlock(&cifdev->stream_lock); if (ret < 0) vb2_fop_release(filp); } - ret = rkcif_sensor_set_power(stream, on); return ret; } @@ -9088,6 +9094,7 @@ static int rkcif_fh_release(struct file *filp) ret = vb2_fop_release(filp); if (!ret) { mutex_lock(&cifdev->stream_lock); + ret = rkcif_sensor_set_power(stream, on); v4l2_pipeline_pm_put(&vnode->vdev.entity); v4l2_dbg(1, rkcif_debug, vdev, "close video, entity use_count %d\n", vnode->vdev.entity.use_count); @@ -9095,7 +9102,6 @@ static int rkcif_fh_release(struct file *filp) } pm_runtime_put_sync(cifdev->dev); - ret = rkcif_sensor_set_power(stream, on); return ret; } @@ -10819,7 +10825,7 @@ void rkcif_irq_oneframe(struct rkcif_device *cif_dev) /* There are two irqs enabled: * - PST_INF_FRAME_END: cif FIFO is ready, this is prior to FRAME_END - * - FRAME_END: cif has saved frame to memory, a frame ready + * - FRAME_END: cif has saved frame to memory, a frame ready */ stream = &cif_dev->stream[RKCIF_STREAM_CIF]; diff --git a/drivers/media/platform/rockchip/cif/dev.c b/drivers/media/platform/rockchip/cif/dev.c index 24b33d0ec9ee..27d7a3da08ca 100644 --- a/drivers/media/platform/rockchip/cif/dev.c +++ b/drivers/media/platform/rockchip/cif/dev.c @@ -2876,6 +2876,7 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int atomic_set(&cif_dev->power_cnt, 0); atomic_set(&cif_dev->streamoff_cnt, 0); atomic_set(&cif_dev->sensor_off, 1); + atomic_set(&cif_dev->sd_power_cnt, 0); cif_dev->is_start_hdr = false; cif_dev->pipe.open = rkcif_pipeline_open; cif_dev->pipe.close = rkcif_pipeline_close; diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index 67bebcee90c9..89522611533e 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -967,6 +967,7 @@ struct rkcif_device { atomic_t power_cnt; atomic_t streamoff_cnt; atomic_t sensor_off; + atomic_t sd_power_cnt; struct mutex stream_lock; /* lock between streams */ struct mutex scale_lock; /* lock between scale dev */ struct mutex tools_lock; /* lock between tools dev */ @@ -1179,4 +1180,6 @@ void rkcif_modify_line_int(struct rkcif_stream *stream, bool en); void rkcif_set_sof(struct rkcif_device *cif_dev, u32 seq); void rkcif_set_sensor_streamon_in_sync_mode(struct rkcif_device *cif_dev); +int rkcif_sensor_set_power(struct rkcif_stream *stream, int on); + #endif diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index ec01bfd83c0e..d88c1f1ddeca 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -1244,6 +1244,7 @@ static int sditf_s_power(struct v4l2_subdev *sd, int on) pm_runtime_put_sync(cif_dev->dev); priv->mode.rdbk_mode = RKISP_VICAP_RDBK_AIQ; } + ret |= rkcif_sensor_set_power(&cif_dev->stream[0], on); v4l2_dbg(1, rkcif_debug, &node->vdev, "s_power %d, entity use_count %d\n", on, node->vdev.entity.use_count); mutex_unlock(&cif_dev->stream_lock);