Commit 864ed874 authored by AngeloGioacchino Del Regno's avatar AngeloGioacchino Del Regno Committed by Mauro Carvalho Chehab
Browse files

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: default avatarAngeloGioacchino Del Regno <kholk11@gmail.com>
Reviewed-by: default avatarRobert Foss <robert.foss@linaro.org>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent cea357bc
Loading
Loading
Loading
Loading
+55 −30
Original line number Diff line number Diff line
@@ -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;

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

	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;
}
+1 −1
Original line number Diff line number Diff line
@@ -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];