media: rockchip: vicap add pipe power control and do reset after power on

Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
Change-Id: Ia5723fd08d4d70feef131976f30e31755c9d2ff3
This commit is contained in:
Zefa Chen
2022-05-30 20:14:24 +08:00
committed by Tao Huang
parent 074d4e99d0
commit b9b5037f47
6 changed files with 38 additions and 55 deletions

View File

@@ -3177,7 +3177,7 @@ static void rkcif_do_cru_reset(struct rkcif_device *dev)
}
}
static void rkcif_do_soft_reset(struct rkcif_device *dev)
void rkcif_do_soft_reset(struct rkcif_device *dev)
{
if (dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_DPHY ||
dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_CPHY ||
@@ -4803,20 +4803,6 @@ static int rkcif_fh_open(struct file *filp)
ret);
return ret;
}
/*
* Soft reset via CRU.
* Because CRU would reset iommu too, so there's not chance
* to reset cif once we hold buffers after buf queued
*/
if (cifdev->chip_id >= CHIP_RK1808_CIF) {
mutex_lock(&cifdev->stream_lock);
if (!atomic_read(&cifdev->fh_cnt))
rkcif_soft_reset(cifdev, true);
atomic_inc(&cifdev->fh_cnt);
mutex_unlock(&cifdev->stream_lock);
} else {
rkcif_soft_reset(cifdev, true);
}
ret = v4l2_fh_open(filp);
if (!ret) {
@@ -4840,13 +4826,6 @@ static int rkcif_fh_release(struct file *filp)
if (!ret)
v4l2_pipeline_pm_put(&vnode->vdev.entity);
mutex_lock(&cifdev->stream_lock);
if (!atomic_dec_return(&cifdev->fh_cnt))
rkcif_soft_reset(cifdev, true);
else if (atomic_read(&cifdev->fh_cnt) < 0)
atomic_set(&cifdev->fh_cnt, 0);
mutex_unlock(&cifdev->stream_lock);
pm_runtime_put_sync(cifdev->dev);
return ret;
}

View File

@@ -430,12 +430,6 @@ static int rkcif_scale_fh_open(struct file *file)
v4l2_err(&cifdev->v4l2_dev, "Failed to get runtime pm, %d\n",
ret);
mutex_lock(&cifdev->stream_lock);
if (!atomic_read(&cifdev->fh_cnt))
rkcif_soft_reset(cifdev, true);
atomic_inc(&cifdev->fh_cnt);
mutex_unlock(&cifdev->stream_lock);
ret = v4l2_fh_open(file);
if (!ret) {
ret = v4l2_pipeline_pm_get(&vnode->vdev.entity);

View File

@@ -1116,6 +1116,25 @@ err_stream_off:
return ret;
}
static int rkcif_pipeline_set_power(struct rkcif_pipeline *p, bool on)
{
int i, ret;
/* phy -> sensor */
for (i = 0; i < p->num_subdevs; i++) {
ret = v4l2_subdev_call(p->subdevs[i], core, s_power, on);
if (on && ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
goto err_power_off;
}
return 0;
err_power_off:
for (--i; i >= 0; --i)
v4l2_subdev_call(p->subdevs[i], core, s_power, false);
return ret;
}
static int rkcif_create_link(struct rkcif_device *dev,
struct rkcif_sensor_info *sensor,
u32 stream_num,
@@ -1569,25 +1588,6 @@ static irqreturn_t rkcif_irq_lite_handler(int irq, struct rkcif_device *cif_dev)
return IRQ_HANDLED;
}
void rkcif_soft_reset(struct rkcif_device *cif_dev, bool is_rst_iommu)
{
struct rkcif_hw *hw_dev = cif_dev->hw_dev;
bool can_reset = true;
int i;
if (!cif_dev->hw_dev)
return;
for (i = 0; i < hw_dev->dev_num; i++)
if (atomic_read(&hw_dev->cif_dev[i]->pipe.stream_cnt) != 0) {
can_reset = false;
break;
}
if (can_reset)
rkcif_hw_soft_reset(cif_dev->hw_dev, is_rst_iommu);
}
int rkcif_attach_hw(struct rkcif_device *cif_dev)
{
struct device_node *np;
@@ -1755,7 +1755,7 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int
spin_lock_init(&cif_dev->reset_watchdog_timer.csi2_err_lock);
atomic_set(&cif_dev->pipe.power_cnt, 0);
atomic_set(&cif_dev->pipe.stream_cnt, 0);
atomic_set(&cif_dev->fh_cnt, 0);
atomic_set(&cif_dev->power_cnt, 0);
cif_dev->is_start_hdr = false;
cif_dev->pipe.open = rkcif_pipeline_open;
cif_dev->pipe.close = rkcif_pipeline_close;
@@ -1982,9 +1982,9 @@ static int __maybe_unused rkcif_runtime_suspend(struct device *dev)
struct rkcif_device *cif_dev = dev_get_drvdata(dev);
int ret = 0;
if (atomic_dec_return(&cif_dev->hw_dev->power_cnt))
if (atomic_dec_return(&cif_dev->power_cnt))
return 0;
rkcif_pipeline_set_power(&cif_dev->pipe, false);
mutex_lock(&cif_dev->hw_dev->dev_lock);
ret = pm_runtime_put_sync(cif_dev->hw_dev->dev);
mutex_unlock(&cif_dev->hw_dev->dev_lock);
@@ -1996,11 +1996,15 @@ static int __maybe_unused rkcif_runtime_resume(struct device *dev)
struct rkcif_device *cif_dev = dev_get_drvdata(dev);
int ret = 0;
if (atomic_inc_return(&cif_dev->hw_dev->power_cnt) > 1)
if (atomic_inc_return(&cif_dev->power_cnt) > 1)
return 0;
ret = rkcif_pipeline_set_power(&cif_dev->pipe, true);
if (ret)
return ret;
mutex_lock(&cif_dev->hw_dev->dev_lock);
ret = pm_runtime_resume_and_get(cif_dev->hw_dev->dev);
mutex_unlock(&cif_dev->hw_dev->dev_lock);
rkcif_do_soft_reset(cif_dev);
return (ret > 0) ? 0 : ret;
}

View File

@@ -699,7 +699,7 @@ struct rkcif_device {
int num_channels;
int chip_id;
atomic_t stream_cnt;
atomic_t fh_cnt;
atomic_t power_cnt;
struct mutex stream_lock; /* lock between streams */
struct mutex scale_lock; /* lock between scale dev */
enum rkcif_workmode workmode;
@@ -776,8 +776,6 @@ void rkcif_irq_pingpong(struct rkcif_device *cif_dev);
void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev);
unsigned int rkcif_irq_global(struct rkcif_device *cif_dev);
void rkcif_irq_handle_toisp(struct rkcif_device *cif_dev, unsigned int intstat_glb);
void rkcif_soft_reset(struct rkcif_device *cif_dev,
bool is_rst_iommu);
int rkcif_register_lvds_subdev(struct rkcif_device *dev);
void rkcif_unregister_lvds_subdev(struct rkcif_device *dev);
int rkcif_register_dvp_sof_subdev(struct rkcif_device *dev);
@@ -802,6 +800,8 @@ int rkcif_set_fmt(struct rkcif_stream *stream,
bool try);
void rkcif_enable_dma_capture(struct rkcif_stream *stream);
void rkcif_do_soft_reset(struct rkcif_device *dev);
u32 rkcif_mbus_pixelcode_to_v4l2(u32 pixelcode);
#endif

View File

@@ -1238,6 +1238,7 @@ static int rkcif_plat_hw_probe(struct platform_device *pdev)
cif_hw->is_dma_contig = true;
mutex_init(&cif_hw->dev_lock);
spin_lock_init(&cif_hw->group_lock);
atomic_set(&cif_hw->power_cnt, 0);
cif_hw->iommu_en = is_iommu_enable(dev);
ret = of_reserved_mem_device_init(dev);
@@ -1328,6 +1329,8 @@ static int __maybe_unused rkcif_runtime_suspend(struct device *dev)
{
struct rkcif_hw *cif_hw = dev_get_drvdata(dev);
if (atomic_dec_return(&cif_hw->power_cnt))
return 0;
rkcif_disable_sys_clk(cif_hw);
return pinctrl_pm_select_sleep_state(dev);
@@ -1338,10 +1341,13 @@ static int __maybe_unused rkcif_runtime_resume(struct device *dev)
struct rkcif_hw *cif_hw = dev_get_drvdata(dev);
int ret;
if (atomic_inc_return(&cif_hw->power_cnt) > 1)
return 0;
ret = pinctrl_pm_select_default_state(dev);
if (ret < 0)
return ret;
rkcif_enable_sys_clk(cif_hw);
rkcif_hw_soft_reset(cif_hw, true);
return 0;
}

View File

@@ -560,7 +560,7 @@ static int sditf_s_power(struct v4l2_subdev *sd, int on)
if (on)
ret = pm_runtime_resume_and_get(cif_dev->dev);
else
pm_runtime_put(cif_dev->dev);
pm_runtime_put_sync(cif_dev->dev);
}
return ret;
}