Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ec7d8eaa authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: camera: isp: Fix for CAMIF error"

parents 33ba495f 81c28689
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -228,13 +228,13 @@
			"csi3_pix_clk", "csi3_rdi_clk",
			"vfe0_clk_src", "camss_vfe_vfe0_clk", "camss_csi_vfe0_clk",
			"vfe1_clk_src", "camss_vfe_vfe1_clk", "camss_csi_vfe1_clk";
		qcom,clock-rates = <0
			240000000 0 0 0
			240000000 0 0 0
			240000000 0 0 0
			240000000 0 0 0
			320000000 0 0
			320000000 0 0>;
		qcom,clock-rates = "-1",
			"266670000", "0", "0", "0",
			"266670000", "0", "0", "0",
			"266670000", "0", "0", "0",
			"266670000", "0", "0", "0",
			"-2", "0", "0",
			"-2", "0", "0";
	};

	qcom,vfe@fda10000 {
+20 −3
Original line number Diff line number Diff line
@@ -251,6 +251,8 @@ static void msm_vfe44_init_hardware_reg(struct vfe_device *vfe_dev)
	msm_camera_io_w_mb(0xFFFFFFFF, vfe_dev->vfe_base + 0x2C);
	msm_camera_io_w(0xFFFFFFFF, vfe_dev->vfe_base + 0x30);
	msm_camera_io_w_mb(0xFFFFFFFF, vfe_dev->vfe_base + 0x34);
	msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x24);

}

static void msm_vfe44_clear_status_reg(struct vfe_device *vfe_dev)
@@ -369,9 +371,11 @@ static void msm_vfe44_process_violation_status(
static void msm_vfe44_process_error_status(struct vfe_device *vfe_dev)
{
	uint32_t error_status1 = vfe_dev->error_info.error_mask1;
	if (error_status1 & (1 << 0))
	if (error_status1 & (1 << 0)) {
		pr_err("%s: camif error status: 0x%x\n",
			__func__, vfe_dev->error_info.camif_status);
		msm_camera_io_dump_2(vfe_dev->vfe_base + 0x2f4, 0x30);
	}
	if (error_status1 & (1 << 1))
		pr_err("%s: stats bhist overwrite\n", __func__);
	if (error_status1 & (1 << 2))
@@ -457,11 +461,18 @@ static void msm_vfe44_process_error_status(struct vfe_device *vfe_dev)
static void msm_vfe44_read_irq_status(struct vfe_device *vfe_dev,
	uint32_t *irq_status0, uint32_t *irq_status1)
{
	uint32_t irq_mask0 = 0, irq_mask1 = 0;
	irq_mask0 = msm_camera_io_r(vfe_dev->vfe_base + 0x28);
	irq_mask1 = msm_camera_io_r(vfe_dev->vfe_base + 0x2C);

	*irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x38);
	*irq_status1 = msm_camera_io_r(vfe_dev->vfe_base + 0x3C);

	msm_camera_io_w(*irq_status0, vfe_dev->vfe_base + 0x30);
	msm_camera_io_w(*irq_status1, vfe_dev->vfe_base + 0x34);
	msm_camera_io_w_mb(1, vfe_dev->vfe_base + 0x24);
	*irq_status0 &= irq_mask0;
	*irq_status1 &= irq_mask1;
	if (*irq_status0 & 0x10000000) {
		pr_err_ratelimited("%s: Protection triggered\n", __func__);
		*irq_status0 &= ~(0x10000000);
@@ -1045,9 +1056,14 @@ static void msm_vfe44_update_camif_state(struct vfe_device *vfe_dev,
		return;

	if (update_state == ENABLE_CAMIF) {
		msm_camera_io_w(0xFFFFFFFF, vfe_dev->vfe_base + 0x30);
		msm_camera_io_w_mb(0xFFFFFFFF, vfe_dev->vfe_base + 0x34);
		msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x24);

		val = msm_camera_io_r(vfe_dev->vfe_base + 0x28);
		val |= 0xF5;
		val |= 0xF7;
		msm_camera_io_w_mb(val, vfe_dev->vfe_base + 0x28);
		msm_camera_io_w_mb(0x140000, vfe_dev->vfe_base + 0x318);

		bus_en =
			((vfe_dev->axi_data.
@@ -1061,7 +1077,7 @@ static void msm_vfe44_update_camif_state(struct vfe_device *vfe_dev,
		msm_camera_io_w(val, vfe_dev->vfe_base + 0x2F8);
		msm_camera_io_w_mb(0x4, vfe_dev->vfe_base + 0x2F4);
		msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x2F4);
		msm_camera_io_w_mb(0x200, vfe_dev->vfe_base + 0x318);

		vfe_dev->axi_data.src_info[VFE_PIX_0].active = 1;
	} else if (update_state == DISABLE_CAMIF) {
		msm_camera_io_w_mb(0x0, vfe_dev->vfe_base + 0x2F4);
@@ -1372,6 +1388,7 @@ static int msm_vfe44_axi_restart(struct vfe_device *vfe_dev,
	msm_camera_io_w(0x7FFFFFFF, vfe_dev->vfe_base + 0x30);
	msm_camera_io_w(0xFEFFFEFF, vfe_dev->vfe_base + 0x34);
	msm_camera_io_w(0x1, vfe_dev->vfe_base + 0x24);
	msm_camera_io_w_mb(0x140000, vfe_dev->vfe_base + 0x318);

	/* Start AXI */
	msm_camera_io_w(0x0, vfe_dev->vfe_base + 0x2C0);
+81 −78
Original line number Diff line number Diff line
@@ -50,6 +50,11 @@
#define CDBG(fmt, args...) do { } while (0)
#endif

int msm_ispif_get_clk_info(struct ispif_device *ispif_dev,
	struct platform_device *pdev,
	struct msm_cam_clk_info *ahb_clk_info,
	struct msm_cam_clk_info *clk_info);

static void msm_ispif_io_dump_reg(struct ispif_device *ispif)
{
	if (!ispif->enb_dump_reg)
@@ -84,45 +89,29 @@ static struct msm_cam_clk_info ispif_8626_reset_clk_info[] = {
	{"camss_csi_vfe_clk", NO_SET_RATE},
};

static struct msm_cam_clk_info ispif_8974_ahb_clk_info[ISPIF_CLK_INFO_MAX];

static struct msm_cam_clk_info ispif_8974_reset_clk_info[] = {
	{"csi0_src_clk", INIT_RATE},
	{"csi0_clk", NO_SET_RATE},
	{"csi0_pix_clk", NO_SET_RATE},
	{"csi0_rdi_clk", NO_SET_RATE},
	{"csi1_src_clk", INIT_RATE},
	{"csi1_clk", NO_SET_RATE},
	{"csi1_pix_clk", NO_SET_RATE},
	{"csi1_rdi_clk", NO_SET_RATE},
	{"csi2_src_clk", INIT_RATE},
	{"csi2_clk", NO_SET_RATE},
	{"csi2_pix_clk", NO_SET_RATE},
	{"csi2_rdi_clk", NO_SET_RATE},
	{"csi3_src_clk", INIT_RATE},
	{"csi3_clk", NO_SET_RATE},
	{"csi3_pix_clk", NO_SET_RATE},
	{"csi3_rdi_clk", NO_SET_RATE},
	{"vfe0_clk_src", INIT_RATE},
	{"camss_vfe_vfe0_clk", NO_SET_RATE},
	{"camss_csi_vfe0_clk", NO_SET_RATE},
	{"vfe1_clk_src", INIT_RATE},
	{"camss_vfe_vfe1_clk", NO_SET_RATE},
	{"camss_csi_vfe1_clk", NO_SET_RATE},
};
static struct msm_cam_clk_info ispif_ahb_clk_info[ISPIF_CLK_INFO_MAX];
static struct msm_cam_clk_info ispif_clk_info[ISPIF_CLK_INFO_MAX];

static int msm_ispif_reset_hw(struct ispif_device *ispif)
{
	int rc = 0;
	long timeout = 0;
	struct clk *reset_clk[ARRAY_SIZE(ispif_8974_reset_clk_info)];
	struct clk *reset_clk1[ARRAY_SIZE(ispif_8626_reset_clk_info)];
	ispif->clk_idx = 0;

	rc = msm_ispif_get_clk_info(ispif, ispif->pdev,
		ispif_ahb_clk_info, ispif_clk_info);
	if (rc < 0) {
		pr_err("%s: msm_isp_get_clk_info() failed", __func__);
			return -EFAULT;
	}

	rc = msm_cam_clk_enable(&ispif->pdev->dev,
		ispif_8974_reset_clk_info, reset_clk,
		ARRAY_SIZE(ispif_8974_reset_clk_info), 1);
		ispif_clk_info, ispif->clk,
		ispif->num_clk, 1);
	if (rc < 0) {
		pr_err("%s: cannot enable clock, error = %d\n",
			__func__, rc);
		rc = msm_cam_clk_enable(&ispif->pdev->dev,
			ispif_8626_reset_clk_info, reset_clk1,
			ARRAY_SIZE(ispif_8626_reset_clk_info), 1);
@@ -145,9 +134,7 @@ static int msm_ispif_reset_hw(struct ispif_device *ispif)
	/* initiate reset of ISPIF */
	msm_camera_io_w(ISPIF_RST_CMD_MASK,
				ispif->base + ISPIF_RST_CMD_ADDR);
	if (ispif->hw_num_isps > 1)
		msm_camera_io_w(ISPIF_RST_CMD_1_MASK,
					ispif->base + ISPIF_RST_CMD_1_ADDR);


	timeout = wait_for_completion_timeout(
			&ispif->reset_complete[VFE0], msecs_to_jiffies(500));
@@ -156,8 +143,8 @@ static int msm_ispif_reset_hw(struct ispif_device *ispif)
	if (timeout <= 0) {
		pr_err("%s: VFE0 reset wait timeout\n", __func__);
		rc = msm_cam_clk_enable(&ispif->pdev->dev,
			ispif_8974_reset_clk_info, reset_clk,
			ARRAY_SIZE(ispif_8974_reset_clk_info), 0);
			ispif_clk_info, ispif->clk,
			ispif->num_clk, 0);
		if (rc < 0) {
			rc = msm_cam_clk_enable(&ispif->pdev->dev,
				ispif_8626_reset_clk_info, reset_clk1,
@@ -170,23 +157,25 @@ static int msm_ispif_reset_hw(struct ispif_device *ispif)
	}

	if (ispif->hw_num_isps > 1) {
		msm_camera_io_w(ISPIF_RST_CMD_1_MASK,
					ispif->base + ISPIF_RST_CMD_1_ADDR);
		timeout = wait_for_completion_timeout(
				&ispif->reset_complete[VFE1],
				msecs_to_jiffies(500));
		CDBG("%s: VFE1 done\n", __func__);
		if (timeout <= 0) {
			pr_err("%s: VFE1 reset wait timeout\n", __func__);
			msm_cam_clk_enable(&ispif->pdev->dev,
				ispif_8974_reset_clk_info, reset_clk,
				ARRAY_SIZE(ispif_8974_reset_clk_info), 0);
		rc = msm_cam_clk_enable(&ispif->pdev->dev,
			ispif_clk_info, ispif->clk,
			ispif->num_clk, 0);
			return -ETIMEDOUT;
		}
	}

	if (ispif->clk_idx == 1) {
		rc = msm_cam_clk_enable(&ispif->pdev->dev,
			ispif_8974_reset_clk_info, reset_clk,
			ARRAY_SIZE(ispif_8974_reset_clk_info), 0);
			ispif_clk_info, ispif->clk,
			ispif->num_clk, 0);
		if (rc < 0) {
			pr_err("%s: cannot disable clock, error = %d",
				__func__, rc);
@@ -206,13 +195,14 @@ static int msm_ispif_reset_hw(struct ispif_device *ispif)
	return rc;
}

int msm_ispif_get_ahb_clk_info(struct ispif_device *ispif_dev,
int msm_ispif_get_clk_info(struct ispif_device *ispif_dev,
	struct platform_device *pdev,
	struct msm_cam_clk_info *ahb_clk_info)
	struct msm_cam_clk_info *ahb_clk_info,
	struct msm_cam_clk_info *clk_info)
{
	uint32_t count, num_ahb_clk = 0;
	const char *rate = NULL;
	int i, rc;
	uint32_t rates[ISPIF_CLK_INFO_MAX];

	struct device_node *of_node;
	of_node = pdev->dev.of_node;
@@ -231,31 +221,47 @@ int msm_ispif_get_ahb_clk_info(struct ispif_device *ispif_dev,
		return -EINVAL;
	}

	rc = of_property_read_u32_array(of_node, "qcom,clock-rates",
		rates, count);
	for (i = 0; i < count; i++) {
		rc = of_property_read_string_index(of_node, "clock-names",
				i, &(clk_info[i].clk_name));
		if (rc < 0) {
		pr_err("%s failed %d\n", __func__, __LINE__);
			pr_err("%s reading clock-name failed index %d\n",
				__func__, i);
			return rc;
		}
	for (i = 0; i < count; i++) {
		rc = of_property_read_string_index(of_node, "clock-names",
				i, &(ahb_clk_info[num_ahb_clk].clk_name));
		CDBG("clock-names[%d] = %s\n",
			 i, ahb_clk_info[i].clk_name);

		rc = of_property_read_string_index(of_node, "qcom,clock-rates",
			i, &rate);
		CDBG("clock-names[%d] = %s, clk_rate = %s\n",
			i, clk_info[i].clk_name, rate);
		if (rc < 0) {
			pr_err("%s failed %d\n", __func__, __LINE__);
			pr_err("%s reading clock-rate failed index %d\n",
				__func__, i);
			return rc;
		}
		if (strnstr(ahb_clk_info[num_ahb_clk].clk_name, "ahb",
			sizeof(ahb_clk_info[num_ahb_clk].clk_name))) {

		if (!strcmp(rate, "-1") || !strcmp(rate, "0"))
			clk_info[i].clk_rate = NO_SET_RATE;
		else if (!strcmp(rate, "-2"))
			clk_info[i].clk_rate = INIT_RATE;
		else
			rc = kstrtol(rate, 10, &clk_info[i].clk_rate);

		if (strnstr(clk_info[i].clk_name, "ahb",
			strlen(clk_info[i].clk_name))) {
			ahb_clk_info[num_ahb_clk].clk_name =
				clk_info[i].clk_name;
			ahb_clk_info[num_ahb_clk].clk_rate =
				(rates[i] == 0) ? (long)-1 : rates[i];
			CDBG("clk_rate[%d] = %ld\n", i,
				ahb_clk_info[i].clk_rate);
				clk_info[i].clk_rate;
			CDBG("clk_name[%d]= %s, clk_rate = %ld\n",
				num_ahb_clk, ahb_clk_info[num_ahb_clk].clk_name,
				ahb_clk_info[num_ahb_clk].clk_rate);
			num_ahb_clk++;
		}
	}
	CDBG("%s: num_ahb_clk %d num_clk %d\n", __func__, num_ahb_clk, count);
	ispif_dev->num_ahb_clk = num_ahb_clk;
	ispif_dev->num_clk = count;
	return 0;
}

@@ -268,15 +274,8 @@ static int msm_ispif_clk_ahb_enable(struct ispif_device *ispif, int enable)
		return 0;
	}

	rc = msm_ispif_get_ahb_clk_info(ispif, ispif->pdev,
		ispif_8974_ahb_clk_info);
	if (rc < 0) {
		pr_err("%s: msm_isp_get_clk_info() failed", __func__);
			return -EFAULT;
	}

	rc = msm_cam_clk_enable(&ispif->pdev->dev,
		ispif_8974_ahb_clk_info, ispif->ahb_clk,
		ispif_ahb_clk_info, ispif->ahb_clk,
		ispif->num_ahb_clk, enable);
	if (rc < 0) {
		pr_err("%s: cannot enable clock, error = %d",
@@ -784,7 +783,6 @@ static int msm_ispif_start_frame_boundary(struct ispif_device *ispif,
		rc = -EINVAL;
		return rc;
	}

	msm_ispif_intf_cmd(ispif, ISPIF_INTF_CMD_ENABLE_FRAME_BOUNDARY, params);

	return rc;
@@ -800,7 +798,6 @@ static int msm_ispif_restart_frame_boundary(struct ispif_device *ispif,
	enum msm_ispif_vfe_intf vfe_intf;
	uint32_t vfe_mask = 0;
	uint32_t intf_addr;
	struct clk *reset_clk[ARRAY_SIZE(ispif_8974_reset_clk_info)];

	if (ispif->ispif_state != ISPIF_POWER_UP) {
		pr_err("%s: ispif invalid state %d\n", __func__,
@@ -826,8 +823,8 @@ static int msm_ispif_restart_frame_boundary(struct ispif_device *ispif,
	}

	rc = msm_cam_clk_enable(&ispif->pdev->dev,
		ispif_8974_reset_clk_info, reset_clk,
		ARRAY_SIZE(ispif_8974_reset_clk_info), 1);
		ispif_clk_info, ispif->clk,
		ispif->num_clk, 1);
	if (rc < 0) {
		pr_err("%s: cannot enable clock, error = %d",
			__func__, rc);
@@ -871,8 +868,8 @@ static int msm_ispif_restart_frame_boundary(struct ispif_device *ispif,

	pr_info("%s: ISPIF reset hw done", __func__);
	rc = msm_cam_clk_enable(&ispif->pdev->dev,
		ispif_8974_reset_clk_info, reset_clk,
		ARRAY_SIZE(ispif_8974_reset_clk_info), 0);
		ispif_clk_info, ispif->clk,
		ispif->num_clk, 0);
	if (rc < 0) {
		pr_err("%s: cannot enable clock, error = %d",
			__func__, rc);
@@ -928,8 +925,8 @@ end:
	return rc;
disable_clk:
	rc = msm_cam_clk_enable(&ispif->pdev->dev,
		ispif_8974_reset_clk_info, reset_clk,
		ARRAY_SIZE(ispif_8974_reset_clk_info), 0);
		ispif_clk_info, ispif->clk,
		ispif->num_clk, 0);
	if (rc < 0) {
		pr_err("%s: cannot enable clock, error = %d",
		__func__, rc);
@@ -1194,14 +1191,14 @@ static int msm_ispif_init(struct ispif_device *ispif,
		goto error_irq;
	}

	msm_ispif_reset_hw(ispif);

	rc = msm_ispif_clk_ahb_enable(ispif, 1);
	if (rc) {
		pr_err("%s: ahb_clk enable failed", __func__);
		goto error_ahb;
	}

	msm_ispif_reset_hw(ispif);

	rc = msm_ispif_reset(ispif);
	if (rc == 0) {
		ispif->ispif_state = ISPIF_POWER_UP;
@@ -1235,7 +1232,7 @@ static void msm_ispif_release(struct ispif_device *ispif)

	/* make sure no streaming going on */
	msm_ispif_reset(ispif);

	msm_ispif_reset_hw(ispif);
	msm_ispif_clk_ahb_enable(ispif, 0);

	free_irq(ispif->irq->start, ispif);
@@ -1245,6 +1242,7 @@ static void msm_ispif_release(struct ispif_device *ispif)
	iounmap(ispif->clk_mux_base);

	ispif->ispif_state = ISPIF_POWER_DOWN;

}

static long msm_ispif_cmd(struct v4l2_subdev *sd, void *arg)
@@ -1340,7 +1338,6 @@ static long msm_ispif_subdev_fops_ioctl(struct file *file, unsigned int cmd,
static int ispif_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
	struct ispif_device *ispif = v4l2_get_subdevdata(sd);

	mutex_lock(&ispif->mutex);
	/* mem remap is done in init when the clock is on */
	ispif->open_cnt++;
@@ -1352,7 +1349,6 @@ static int ispif_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
	int rc = 0;
	struct ispif_device *ispif = v4l2_get_subdevdata(sd);

	if (!ispif) {
		pr_err("%s: invalid input\n", __func__);
		return -EINVAL;
@@ -1409,6 +1405,13 @@ static int ispif_probe(struct platform_device *pdev)
		rc = 0;
	}

	rc = msm_ispif_get_clk_info(ispif, pdev,
		ispif_ahb_clk_info, ispif_clk_info);
	if (rc < 0) {
		pr_err("%s: msm_isp_get_clk_info() failed", __func__);
			return -EFAULT;
	}

	mutex_init(&ispif->mutex);
	ispif->mem = platform_get_resource_byname(pdev,
		IORESOURCE_MEM, "ispif");
+3 −1
Original line number Diff line number Diff line
/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -60,9 +60,11 @@ struct ispif_device {
	enum msm_ispif_state_t ispif_state;
	struct msm_ispif_vfe_info vfe_info;
	struct clk *ahb_clk[ISPIF_CLK_INFO_MAX];
	struct clk *clk[ISPIF_CLK_INFO_MAX];
	struct completion reset_complete[VFE_MAX];
	uint32_t hw_num_isps;
	uint32_t num_ahb_clk;
	uint32_t num_clk;
	uint32_t clk_idx;
};
#endif