mirror of https://gitee.com/openkylin/linux.git
media: camss: ispif: Correctly reset based on the VFE ID
Resetting the ISPIF VFE0 context is wrong if we are using the VFE1 for dual-camera or simply because a secondary camera is connected to it: in this case the reset will always happen on the VFE0 ctx of the ISPIF, which is .. useless. Fix this usecase by adding the ISPIF_RST_CMD_1 address and choose where to do the (or what to) reset based on the VFE line id. Signed-off-by: AngeloGioacchino Del Regno <kholk11@gmail.com> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
This commit is contained in:
parent
cea357bc25
commit
864ed874d7
|
@ -26,6 +26,7 @@
|
|||
#define MSM_ISPIF_NAME "msm_ispif"
|
||||
|
||||
#define ISPIF_RST_CMD_0 0x008
|
||||
#define ISPIF_RST_CMD_1 0x00c
|
||||
#define ISPIF_RST_CMD_0_STROBED_RST_EN (1 << 0)
|
||||
#define ISPIF_RST_CMD_0_MISC_LOGIC_RST (1 << 1)
|
||||
#define ISPIF_RST_CMD_0_SW_REG_RST (1 << 2)
|
||||
|
@ -179,7 +180,10 @@ static irqreturn_t ispif_isr_8x96(int irq, void *dev)
|
|||
writel(0x1, ispif->base + ISPIF_IRQ_GLOBAL_CLEAR_CMD);
|
||||
|
||||
if ((value0 >> 27) & 0x1)
|
||||
complete(&ispif->reset_complete);
|
||||
complete(&ispif->reset_complete[0]);
|
||||
|
||||
if ((value3 >> 27) & 0x1)
|
||||
complete(&ispif->reset_complete[1]);
|
||||
|
||||
if (unlikely(value0 & ISPIF_VFE_m_IRQ_STATUS_0_PIX0_OVERFLOW))
|
||||
dev_err_ratelimited(to_device(ispif), "VFE0 pix0 overflow\n");
|
||||
|
@ -237,7 +241,7 @@ static irqreturn_t ispif_isr_8x16(int irq, void *dev)
|
|||
writel(0x1, ispif->base + ISPIF_IRQ_GLOBAL_CLEAR_CMD);
|
||||
|
||||
if ((value0 >> 27) & 0x1)
|
||||
complete(&ispif->reset_complete);
|
||||
complete(&ispif->reset_complete[0]);
|
||||
|
||||
if (unlikely(value0 & ISPIF_VFE_m_IRQ_STATUS_0_PIX0_OVERFLOW))
|
||||
dev_err_ratelimited(to_device(ispif), "VFE0 pix0 overflow\n");
|
||||
|
@ -257,33 +261,18 @@ static irqreturn_t ispif_isr_8x16(int irq, void *dev)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* ispif_reset - Trigger reset on ISPIF module and wait to complete
|
||||
* @ispif: ISPIF device
|
||||
*
|
||||
* Return 0 on success or a negative error code otherwise
|
||||
*/
|
||||
static int ispif_reset(struct ispif_device *ispif)
|
||||
static int ispif_vfe_reset(struct ispif_device *ispif, u8 vfe_id)
|
||||
{
|
||||
unsigned long time;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
ret = camss_pm_domain_on(to_camss(ispif), PM_DOMAIN_VFE0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (vfe_id > (to_camss(ispif)->vfe_num - 1)) {
|
||||
dev_err(to_device(ispif),
|
||||
"Error: asked reset for invalid VFE%d\n", vfe_id);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
ret = camss_pm_domain_on(to_camss(ispif), PM_DOMAIN_VFE1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = camss_enable_clocks(ispif->nclocks_for_reset,
|
||||
ispif->clock_for_reset,
|
||||
to_device(ispif));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
reinit_completion(&ispif->reset_complete);
|
||||
reinit_completion(&ispif->reset_complete[vfe_id]);
|
||||
|
||||
val = ISPIF_RST_CMD_0_STROBED_RST_EN |
|
||||
ISPIF_RST_CMD_0_MISC_LOGIC_RST |
|
||||
|
@ -303,15 +292,50 @@ static int ispif_reset(struct ispif_device *ispif)
|
|||
ISPIF_RST_CMD_0_RDI_OUTPUT_1_MISR_RST |
|
||||
ISPIF_RST_CMD_0_RDI_OUTPUT_2_MISR_RST;
|
||||
|
||||
writel_relaxed(val, ispif->base + ISPIF_RST_CMD_0);
|
||||
if (vfe_id == 1)
|
||||
writel_relaxed(val, ispif->base + ISPIF_RST_CMD_1);
|
||||
else
|
||||
writel_relaxed(val, ispif->base + ISPIF_RST_CMD_0);
|
||||
|
||||
time = wait_for_completion_timeout(&ispif->reset_complete,
|
||||
time = wait_for_completion_timeout(&ispif->reset_complete[vfe_id],
|
||||
msecs_to_jiffies(ISPIF_RESET_TIMEOUT_MS));
|
||||
if (!time) {
|
||||
dev_err(to_device(ispif), "ISPIF reset timeout\n");
|
||||
ret = -EIO;
|
||||
dev_err(to_device(ispif),
|
||||
"ISPIF for VFE%d reset timeout\n", vfe_id);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ispif_reset - Trigger reset on ISPIF module and wait to complete
|
||||
* @ispif: ISPIF device
|
||||
*
|
||||
* Return 0 on success or a negative error code otherwise
|
||||
*/
|
||||
static int ispif_reset(struct ispif_device *ispif, u8 vfe_id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = camss_pm_domain_on(to_camss(ispif), PM_DOMAIN_VFE0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = camss_pm_domain_on(to_camss(ispif), PM_DOMAIN_VFE1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = camss_enable_clocks(ispif->nclocks_for_reset,
|
||||
ispif->clock_for_reset,
|
||||
to_device(ispif));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ispif_vfe_reset(ispif, vfe_id);
|
||||
if (ret)
|
||||
dev_dbg(to_device(ispif), "ISPIF Reset failed\n");
|
||||
|
||||
camss_disable_clocks(ispif->nclocks_for_reset, ispif->clock_for_reset);
|
||||
|
||||
camss_pm_domain_off(to_camss(ispif), PM_DOMAIN_VFE0);
|
||||
|
@ -355,7 +379,7 @@ static int ispif_set_power(struct v4l2_subdev *sd, int on)
|
|||
goto exit;
|
||||
}
|
||||
|
||||
ret = ispif_reset(ispif);
|
||||
ret = ispif_reset(ispif, line->vfe_id);
|
||||
if (ret < 0) {
|
||||
pm_runtime_put_sync(dev);
|
||||
camss_disable_clocks(ispif->nclocks, ispif->clock);
|
||||
|
@ -1192,7 +1216,8 @@ int msm_ispif_subdev_init(struct ispif_device *ispif,
|
|||
|
||||
mutex_init(&ispif->config_lock);
|
||||
|
||||
init_completion(&ispif->reset_complete);
|
||||
for (i = 0; i < MSM_ISPIF_VFE_NUM; i++)
|
||||
init_completion(&ispif->reset_complete[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ struct ispif_device {
|
|||
int nclocks;
|
||||
struct camss_clock *clock_for_reset;
|
||||
int nclocks_for_reset;
|
||||
struct completion reset_complete;
|
||||
struct completion reset_complete[MSM_ISPIF_VFE_NUM];
|
||||
int power_count;
|
||||
struct mutex power_lock;
|
||||
struct ispif_intf_cmd_reg intf_cmd[MSM_ISPIF_VFE_NUM];
|
||||
|
|
Loading…
Reference in New Issue