Skip to content

Commit

Permalink
media: camss: ispif: Correctly reset based on the VFE ID
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Robert Foss <[email protected]>
Signed-off-by: Hans Verkuil <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
  • Loading branch information
kholk authored and mchehab committed Nov 25, 2020
1 parent cea357b commit 864ed87
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 31 deletions.
85 changes: 55 additions & 30 deletions drivers/media/platform/qcom/camss/camss-ispif.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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");
Expand All @@ -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;

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;
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;
}

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 |
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/media/platform/qcom/camss/camss-ispif.h
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down

0 comments on commit 864ed87

Please sign in to comment.