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 MSM_ISPIF_NAME "msm_ispif"
|
||||||
|
|
||||||
#define ISPIF_RST_CMD_0 0x008
|
#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_STROBED_RST_EN (1 << 0)
|
||||||
#define ISPIF_RST_CMD_0_MISC_LOGIC_RST (1 << 1)
|
#define ISPIF_RST_CMD_0_MISC_LOGIC_RST (1 << 1)
|
||||||
#define ISPIF_RST_CMD_0_SW_REG_RST (1 << 2)
|
#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);
|
writel(0x1, ispif->base + ISPIF_IRQ_GLOBAL_CLEAR_CMD);
|
||||||
|
|
||||||
if ((value0 >> 27) & 0x1)
|
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))
|
if (unlikely(value0 & ISPIF_VFE_m_IRQ_STATUS_0_PIX0_OVERFLOW))
|
||||||
dev_err_ratelimited(to_device(ispif), "VFE0 pix0 overflow\n");
|
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);
|
writel(0x1, ispif->base + ISPIF_IRQ_GLOBAL_CLEAR_CMD);
|
||||||
|
|
||||||
if ((value0 >> 27) & 0x1)
|
if ((value0 >> 27) & 0x1)
|
||||||
complete(&ispif->reset_complete);
|
complete(&ispif->reset_complete[0]);
|
||||||
|
|
||||||
if (unlikely(value0 & ISPIF_VFE_m_IRQ_STATUS_0_PIX0_OVERFLOW))
|
if (unlikely(value0 & ISPIF_VFE_m_IRQ_STATUS_0_PIX0_OVERFLOW))
|
||||||
dev_err_ratelimited(to_device(ispif), "VFE0 pix0 overflow\n");
|
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;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static int ispif_vfe_reset(struct ispif_device *ispif, u8 vfe_id)
|
||||||
* 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)
|
|
||||||
{
|
{
|
||||||
unsigned long time;
|
unsigned long time;
|
||||||
u32 val;
|
u32 val;
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = camss_pm_domain_on(to_camss(ispif), PM_DOMAIN_VFE0);
|
if (vfe_id > (to_camss(ispif)->vfe_num - 1)) {
|
||||||
if (ret < 0)
|
dev_err(to_device(ispif),
|
||||||
return ret;
|
"Error: asked reset for invalid VFE%d\n", vfe_id);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
ret = camss_pm_domain_on(to_camss(ispif), PM_DOMAIN_VFE1);
|
reinit_completion(&ispif->reset_complete[vfe_id]);
|
||||||
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);
|
|
||||||
|
|
||||||
val = ISPIF_RST_CMD_0_STROBED_RST_EN |
|
val = ISPIF_RST_CMD_0_STROBED_RST_EN |
|
||||||
ISPIF_RST_CMD_0_MISC_LOGIC_RST |
|
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_1_MISR_RST |
|
||||||
ISPIF_RST_CMD_0_RDI_OUTPUT_2_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));
|
msecs_to_jiffies(ISPIF_RESET_TIMEOUT_MS));
|
||||||
if (!time) {
|
if (!time) {
|
||||||
dev_err(to_device(ispif), "ISPIF reset timeout\n");
|
dev_err(to_device(ispif),
|
||||||
ret = -EIO;
|
"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_disable_clocks(ispif->nclocks_for_reset, ispif->clock_for_reset);
|
||||||
|
|
||||||
camss_pm_domain_off(to_camss(ispif), PM_DOMAIN_VFE0);
|
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;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ispif_reset(ispif);
|
ret = ispif_reset(ispif, line->vfe_id);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
pm_runtime_put_sync(dev);
|
pm_runtime_put_sync(dev);
|
||||||
camss_disable_clocks(ispif->nclocks, ispif->clock);
|
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);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ struct ispif_device {
|
|||||||
int nclocks;
|
int nclocks;
|
||||||
struct camss_clock *clock_for_reset;
|
struct camss_clock *clock_for_reset;
|
||||||
int nclocks_for_reset;
|
int nclocks_for_reset;
|
||||||
struct completion reset_complete;
|
struct completion reset_complete[MSM_ISPIF_VFE_NUM];
|
||||||
int power_count;
|
int power_count;
|
||||||
struct mutex power_lock;
|
struct mutex power_lock;
|
||||||
struct ispif_intf_cmd_reg intf_cmd[MSM_ISPIF_VFE_NUM];
|
struct ispif_intf_cmd_reg intf_cmd[MSM_ISPIF_VFE_NUM];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user