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

Commit 3a2a776a authored by Shubhraprakash Das's avatar Shubhraprakash Das
Browse files

msm: ispif: Soc changes for ispif



Use common functions to query clock information from dtsi
in ispif driver so that it can be easily ported to other
platforms.

CRs-Fixed: 998900
Change-Id: I9c06258234a88e6581ebfc6da9c121cfd276985f
Signed-off-by: default avatarShubhraprakash Das <sadas@codeaurora.org>
parent 46c479f8
Loading
Loading
Loading
Loading
+124 −179
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include "msm_sd.h"
#include "msm_camera_io_util.h"
#include "cam_hw_ops.h"
#include "cam_soc_api.h"

#ifdef CONFIG_MSM_ISPIF_V1
#include "msm_ispif_hwreg_v1.h"
@@ -58,9 +59,7 @@
static int msm_ispif_clk_ahb_enable(struct ispif_device *ispif, int enable);
static int ispif_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh);
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);
	struct platform_device *pdev);

static void msm_ispif_io_dump_reg(struct ispif_device *ispif)
{
@@ -96,9 +95,6 @@ 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_ahb_clk_info[ISPIF_CLK_INFO_MAX];
static struct msm_cam_clk_info ispif_clk_info[ISPIF_CLK_INFO_MAX];

static void msm_ispif_put_regulator(struct ispif_device *ispif_dev)
{
	int i;
@@ -231,13 +227,13 @@ static int msm_ispif_reset_hw(struct ispif_device *ispif)
	if (rc < 0)
		return rc;

	rc = msm_cam_clk_enable(&ispif->pdev->dev,
		ispif_clk_info, ispif->clk,
	rc = msm_camera_clk_enable(&ispif->pdev->dev,
		ispif->clk_info, ispif->clks,
		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,
		rc = msm_camera_clk_enable(&ispif->pdev->dev,
			ispif_8626_reset_clk_info, reset_clk1,
			ARRAY_SIZE(ispif_8626_reset_clk_info), 1);
		if (rc < 0) {
@@ -284,13 +280,13 @@ static int msm_ispif_reset_hw(struct ispif_device *ispif)

clk_disable:
	if (ispif->clk_idx == 1) {
		rc = rc ? rc : msm_cam_clk_enable(&ispif->pdev->dev,
			ispif_clk_info, ispif->clk,
		rc = rc ? rc : msm_camera_clk_enable(&ispif->pdev->dev,
			ispif->clk_info, ispif->clks,
			ispif->num_clk, 0);
	}

	if (ispif->clk_idx == 2) {
		rc = rc ? rc :  msm_cam_clk_enable(&ispif->pdev->dev,
		rc = rc ? rc :  msm_camera_clk_enable(&ispif->pdev->dev,
			ispif_8626_reset_clk_info, reset_clk1,
			ARRAY_SIZE(ispif_8626_reset_clk_info), 0);
	}
@@ -302,86 +298,76 @@ reg_disable:
}

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)
	struct platform_device *pdev)
{
	uint32_t count, num_ahb_clk = 0, non_ahb_clk = 0;
	uint32_t num_ahb_clk = 0, non_ahb_clk = 0;
	size_t num_clks;
	int i, rc;
	uint32_t rates[ISPIF_CLK_INFO_MAX];
	const char *clk_ctl = NULL;
	const char *clk_name = NULL;
	struct msm_cam_clk_info *clk_temp;
	int j;
	struct clk **clks, **temp_clks;
	struct msm_cam_clk_info *clk_info, *temp_clk_info;

	struct device_node *of_node;
	of_node = pdev->dev.of_node;

	count = of_property_count_strings(of_node, "clock-names");

	CDBG("count = %d\n", count);
	if (count == 0) {
		pr_err("no clocks found in device tree, count=%d", count);
		return 0;
	}

	if (count > ISPIF_CLK_INFO_MAX) {
		pr_err("invalid count=%d, max is %d\n", count,
			ISPIF_CLK_INFO_MAX);
		return -EINVAL;
	}
	rc = msm_camera_get_clk_info(pdev, &clk_info,
			&clks, &num_clks);

	rc = of_property_read_u32_array(of_node, "qcom,clock-rates",
		rates, count);
	if (rc < 0) {
		pr_err("%s failed %d\n", __func__, __LINE__);
	if (rc)
		return rc;
	}

	for (i = 0; i < count; i++) {
		rc = of_property_read_string_index(of_node, "clock-names",
				i, &clk_name);
		if (rc < 0) {
			pr_err("%s reading clock-name failed index %d\n",
				__func__, i);
			return rc;
	/*
	 * reshuffle the clock arrays so that the ahb clocks are
	 * at the beginning of array
	 */
	temp_clks = kcalloc(num_clks, sizeof(struct clk *),
				GFP_KERNEL);
	temp_clk_info = kcalloc(num_clks, sizeof(struct msm_cam_clk_info),
				GFP_KERNEL);
	if (!temp_clks || !temp_clk_info) {
		rc = -ENOMEM;
		kfree(temp_clk_info);
		kfree(temp_clks);
		goto alloc_fail;
	}
	j = 0;
	for (i = 0; i < num_clks; i++) {
		if (strnstr(clk_info[i].clk_name,
			"ahb", strlen(clk_info[i].clk_name))) {
			temp_clk_info[j] = clk_info[i];
			temp_clks[j] = clks[i];
			j++;
			num_ahb_clk++;
		}

		rc = of_property_read_string_index(of_node,
			"qcom,clock-control", i, &clk_ctl);
		if (rc < 0) {
			pr_err("%s reading clock-control failed index %d\n",
				__func__, i);
			return rc;
	}

		if (strnstr(clk_name, "ahb", strlen(clk_name))) {
			clk_temp = &ahb_clk_info[num_ahb_clk];
			num_ahb_clk++;
		} else {
			clk_temp = &clk_info[non_ahb_clk];
	for (i = 0; i < num_clks; i++) {
		if (!strnstr(clk_info[i].clk_name,
			"ahb", strlen(clk_info[i].clk_name))) {
			temp_clk_info[j] = clk_info[i];
			temp_clks[j] = clks[i];
			j++;
			non_ahb_clk++;
		}

		clk_temp->clk_name = clk_name;
		if (!strcmp(clk_ctl, "NO_SET_RATE"))
			clk_temp->clk_rate = NO_SET_RATE;
		else if (!strcmp(clk_ctl, "INIT_RATE"))
			clk_temp->clk_rate = INIT_RATE;
		else if (!strcmp(clk_ctl, "SET_RATE"))
			clk_temp->clk_rate = rates[i];
		else {
			pr_err("%s: error: clock control has invalid value\n",
				 __func__);
			return -EBUSY;
	}

		CDBG("%s: clock-name= %s, clk_rate = %ld clock-control = %s\n",
			__func__, clk_temp->clk_name, clk_temp->clk_rate,
			clk_ctl);
	for (i = 0; i < num_clks; i++) {
		clk_info[i] = temp_clk_info[i];
		clks[i] = temp_clks[i];
	}
	kfree(temp_clk_info);
	kfree(temp_clks);

	ispif_dev->ahb_clk = clks;
	ispif_dev->ahb_clk_info = clk_info;
	ispif_dev->num_ahb_clk = num_ahb_clk;
	ispif_dev->clk_info = clk_info + num_ahb_clk;
	ispif_dev->clks = clks + num_ahb_clk;
	ispif_dev->num_clk = non_ahb_clk;

	return 0;
alloc_fail:
	msm_camera_put_clk_info(pdev, &clk_info, &clks, num_clks);
	return rc;
}

static int msm_ispif_clk_ahb_enable(struct ispif_device *ispif, int enable)
@@ -389,7 +375,7 @@ static int msm_ispif_clk_ahb_enable(struct ispif_device *ispif, int enable)
	int rc = 0;

	rc = msm_cam_clk_enable(&ispif->pdev->dev,
		ispif_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",
@@ -934,8 +920,8 @@ static int msm_ispif_restart_frame_boundary(struct ispif_device *ispif,
	if (rc < 0)
		return -EFAULT;

	rc = msm_cam_clk_enable(&ispif->pdev->dev,
		ispif_clk_info, ispif->clk,
	rc = msm_camera_clk_enable(&ispif->pdev->dev,
		ispif->clk_info, ispif->clks,
		ispif->num_clk, 1);
	if (rc < 0)
		goto disable_regulator;
@@ -969,8 +955,8 @@ static int msm_ispif_restart_frame_boundary(struct ispif_device *ispif,
	}

	pr_info("%s: ISPIF reset hw done, Restarting", __func__);
	rc = msm_cam_clk_enable(&ispif->pdev->dev,
		ispif_clk_info, ispif->clk,
	rc = msm_camera_clk_enable(&ispif->pdev->dev,
		ispif->clk_info, ispif->clks,
		ispif->num_clk, 0);
	if (rc < 0)
		goto disable_regulator;
@@ -1026,8 +1012,8 @@ static int msm_ispif_restart_frame_boundary(struct ispif_device *ispif,
	return rc;

disable_clk:
	msm_cam_clk_enable(&ispif->pdev->dev,
		ispif_clk_info, ispif->clk,
	msm_camera_clk_enable(&ispif->pdev->dev,
		ispif->clk_info, ispif->clks,
		ispif->num_clk, 0);
disable_regulator:
	/* Turn OFF regulators */
@@ -1325,41 +1311,18 @@ static int msm_ispif_init(struct ispif_device *ispif,

	ispif->csid_version = csid_version;

	if (ispif->csid_version >= CSID_VERSION_V30) {
		if (!ispif->clk_mux_mem || !ispif->clk_mux_io) {
			pr_err("%s csi clk mux mem %pK io %pK\n", __func__,
				ispif->clk_mux_mem, ispif->clk_mux_io);
			rc = -ENOMEM;
			return rc;
		}
		ispif->clk_mux_base = ioremap(ispif->clk_mux_mem->start,
			resource_size(ispif->clk_mux_mem));
		if (!ispif->clk_mux_base) {
			pr_err("%s: clk_mux_mem ioremap failed\n", __func__);
			rc = -ENOMEM;
			return rc;
		}
	}

	ispif->base = ioremap(ispif->mem->start,
		resource_size(ispif->mem));
	if (!ispif->base) {
		rc = -ENOMEM;
		pr_err("%s: nomem\n", __func__);
		goto end;
	}
	rc = request_irq(ispif->irq->start, msm_io_ispif_irq,
		IRQF_TRIGGER_RISING, "ispif", ispif);
	if (rc) {
		pr_err("%s: request_irq error = %d\n", __func__, rc);
		goto error_irq;
	if (ispif->csid_version >= CSID_VERSION_V30 && !ispif->clk_mux_base) {
		ispif->clk_mux_base = msm_camera_get_reg_base(ispif->pdev,
							"csi_clk_mux", 1);
		if (!ispif->clk_mux_base)
			return -ENOMEM;
	}

	rc = cam_config_ahb_clk(NULL, 0,
			CAM_AHB_CLIENT_ISPIF, CAM_AHB_SVS_VOTE);
	if (rc < 0) {
		pr_err("%s: failed to vote for AHB\n", __func__);
		goto ahb_vote_fail;
		return rc;
	}

	rc = msm_ispif_reset_hw(ispif);
@@ -1367,22 +1330,15 @@ static int msm_ispif_init(struct ispif_device *ispif,
		goto error_ahb;

	rc = msm_ispif_reset(ispif);
	if (rc == 0) {
	if (rc)
		goto error_ahb;
	ispif->ispif_state = ISPIF_POWER_UP;
		CDBG("%s: power up done\n", __func__);
		goto end;
	}
	return 0;

error_ahb:
	if (cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_ISPIF,
		CAM_AHB_SUSPEND_VOTE) < 0)
		pr_err("%s: failed to remove vote for AHB\n", __func__);
ahb_vote_fail:
	free_irq(ispif->irq->start, ispif);
error_irq:
	iounmap(ispif->base);

end:
	return rc;
}

@@ -1390,27 +1346,10 @@ static void msm_ispif_release(struct ispif_device *ispif)
{
	BUG_ON(!ispif);

	if (!ispif->base) {
		pr_err("%s: ispif base is NULL\n", __func__);
		return;
	}

	if (ispif->ispif_state != ISPIF_POWER_UP) {
		pr_err("%s: ispif invalid state %d\n", __func__,
			ispif->ispif_state);
		return;
	}

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

	disable_irq(ispif->irq->start);
	free_irq(ispif->irq->start, ispif);

	iounmap(ispif->base);

	iounmap(ispif->clk_mux_base);
	msm_camera_enable_irq(ispif->irq, 0);

	ispif->ispif_state = ISPIF_POWER_DOWN;

@@ -1460,7 +1399,8 @@ static long msm_ispif_cmd(struct v4l2_subdev *sd, void *arg)
		msm_ispif_io_dump_reg(ispif);
		break;
	case ISPIF_RELEASE:
		msm_ispif_release(ispif);
		msm_ispif_reset(ispif);
		msm_ispif_reset_hw(ispif);
		break;
	case ISPIF_SET_VFE_INFO:
		rc = msm_ispif_set_vfe_info(ispif, &pcdata->vfe_info);
@@ -1528,15 +1468,22 @@ static int ispif_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
					ispif->ispif_vdd_count, 1);
		if (rc)
			goto unlock;

		rc = msm_ispif_clk_ahb_enable(ispif, 1);
		if (rc) {
			msm_ispif_set_regulators(ispif->ispif_vdd,
					ispif->ispif_vdd_count, 0);
			goto unlock;
		}
		if (rc)
			goto ahb_clk_enable_fail;
		rc = msm_camera_enable_irq(ispif->irq, 1);
		if (rc)
			goto irq_enable_fail;
	}
	/* mem remap is done in init when the clock is on */
	ispif->open_cnt++;
	mutex_unlock(&ispif->mutex);
	return rc;
ahb_clk_enable_fail:
	msm_ispif_set_regulators(ispif->ispif_vdd, ispif->ispif_vdd_count, 0);
irq_enable_fail:
	msm_ispif_clk_ahb_enable(ispif, 0);
unlock:
	mutex_unlock(&ispif->mutex);
	return rc;
@@ -1608,46 +1555,35 @@ static int ispif_probe(struct platform_device *pdev)

	rc = msm_ispif_get_regulator_info(ispif, pdev);
	if (rc < 0)
		return -EFAULT;
		goto regulator_fail;

	rc = msm_ispif_get_clk_info(ispif, pdev,
		ispif_ahb_clk_info, ispif_clk_info);
	rc = msm_ispif_get_clk_info(ispif, pdev);
	if (rc < 0) {
		pr_err("%s: msm_isp_get_clk_info() failed", __func__);
			return -EFAULT;
		rc = -EFAULT;
		goto get_clk_fail;
	}
	mutex_init(&ispif->mutex);
	ispif->mem = platform_get_resource_byname(pdev,
		IORESOURCE_MEM, "ispif");
	if (!ispif->mem) {
		pr_err("%s: no mem resource?\n", __func__);
		rc = -ENODEV;
		goto error;
	ispif->base = msm_camera_get_reg_base(pdev, "ispif", 1);
	if (!ispif->base) {
		rc = -ENOMEM;
		goto reg_base_fail;
	}
	ispif->irq = platform_get_resource_byname(pdev,
		IORESOURCE_IRQ, "ispif");

	ispif->irq = msm_camera_get_irq(pdev, "ispif");
	if (!ispif->irq) {
		pr_err("%s: no irq resource?\n", __func__);
		rc = -ENODEV;
		goto error;
		goto get_irq_fail;
	}
	ispif->io = request_mem_region(ispif->mem->start,
		resource_size(ispif->mem), pdev->name);
	if (!ispif->io) {
		pr_err("%s: no valid mem region\n", __func__);
		rc = -EBUSY;
		goto error;
	}
	ispif->clk_mux_mem = platform_get_resource_byname(pdev,
		IORESOURCE_MEM, "csi_clk_mux");
	if (ispif->clk_mux_mem) {
		ispif->clk_mux_io = request_mem_region(
			ispif->clk_mux_mem->start,
			resource_size(ispif->clk_mux_mem),
			ispif->clk_mux_mem->name);
		if (!ispif->clk_mux_io)
			pr_err("%s: no valid csi_mux region\n", __func__);
	rc = msm_camera_register_irq(pdev, ispif->irq, msm_io_ispif_irq,
			IRQF_TRIGGER_RISING, "ispif", ispif);
	if (rc) {
		rc = -ENODEV;
		goto get_irq_fail;
	}
	rc = msm_camera_enable_irq(ispif->irq, 0);
	if (rc)
		goto sd_reg_fail;

	ispif->pdev = pdev;

@@ -1669,7 +1605,7 @@ static int ispif_probe(struct platform_device *pdev)
	rc = msm_sd_register(&ispif->msm_sd);
	if (rc) {
		pr_err("%s: msm_sd_register error = %d\n", __func__, rc);
		goto error;
		goto sd_reg_fail;
	}
	msm_cam_copy_v4l2_subdev_fops(&msm_ispif_v4l2_subdev_fops);
	msm_ispif_v4l2_subdev_fops.unlocked_ioctl =
@@ -1686,8 +1622,17 @@ static int ispif_probe(struct platform_device *pdev)
	atomic_set(&ispif->reset_trig[VFE1], 0);
	return 0;

error:
sd_reg_fail:
	msm_camera_unregister_irq(pdev, ispif->irq, ispif);
get_irq_fail:
	msm_camera_put_reg_base(pdev, ispif->base, "ispif", 1);
reg_base_fail:
	msm_camera_put_clk_info(pdev, &ispif->ahb_clk_info,
		&ispif->ahb_clk,
		ispif->num_ahb_clk + ispif->num_clk);
get_clk_fail:
	msm_ispif_put_regulator(ispif);
regulator_fail:
	mutex_destroy(&ispif->mutex);
	kfree(ispif);
	return rc;
+5 −7
Original line number Diff line number Diff line
/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2016, 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
@@ -47,11 +47,7 @@ struct ispif_intf_cmd {
struct ispif_device {
	struct platform_device *pdev;
	struct msm_sd_subdev msm_sd;
	struct resource *mem;
	struct resource *clk_mux_mem;
	struct resource *irq;
	struct resource *io;
	struct resource *clk_mux_io;
	void __iomem *base;
	void __iomem *clk_mux_base;
	struct mutex mutex;
@@ -63,8 +59,10 @@ struct ispif_device {
	struct ispif_intf_cmd applied_intf_cmd[VFE_MAX];
	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 clk **ahb_clk;
	struct msm_cam_clk_info *ahb_clk_info;
	struct clk **clks;
	struct msm_cam_clk_info *clk_info;
	struct completion reset_complete[VFE_MAX];
	atomic_t reset_trig[VFE_MAX];
	uint32_t hw_num_isps;