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

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

Merge "msm: jpeg: Changes to adapt jpeg driver to soc layer"

parents 8e5b0738 ac29f70e
Loading
Loading
Loading
Loading
+30 −8
Original line number Diff line number Diff line
@@ -471,7 +471,7 @@
		compatible = "qcom,jpeg";
		reg = <0xa1c000 0x4000>,
			<0xa60000 0x3000>;
		reg-names = "jpeg";
		reg-names = "jpeg_hw", "jpeg_vbif";
		interrupts = <0 316 0>;
		interrupt-names = "jpeg";
		mmagic-vdd-supply = <&gdsc_mmagic_camss>;
@@ -497,6 +497,11 @@
			<0x324 0x31>,
			<0x330 0x31>,
			<0x33c 0x0>;
		qcom,msm-bus,name = "msm_camera_jpeg0";
		qcom,msm-bus,num-cases = <2>;
		qcom,msm-bus,num-paths = <1>;
		qcom,msm-bus,vectors-KBps = <62 512 0 0>,
			<62 512 666675 666675>;
		status = "ok";
	};

@@ -505,7 +510,7 @@
		compatible = "qcom,jpeg";
		reg = <0xa24000 0x4000>,
			<0xa60000 0x3000>;
		reg-names = "jpeg";
		reg-names = "jpeg_hw", "jpeg_vbif";
		interrupts = <0 318 0>;
		interrupt-names = "jpeg";
		mmagic-vdd-supply = <&gdsc_mmagic_camss>;
@@ -531,6 +536,11 @@
			<0x324 0x31>,
			<0x330 0x31>,
			<0x33c 0x31>;
		qcom,msm-bus,name = "msm_camera_jpeg2";
		qcom,msm-bus,num-cases = <2>;
		qcom,msm-bus,num-paths = <1>;
		qcom,msm-bus,vectors-KBps = <62 512 0 0>,
			<62 512 666675 666675>;
		status = "ok";
	};

@@ -539,7 +549,7 @@
		compatible = "qcom,jpeg_dma";
		reg = <0xaa0000 0x4000>,
			<0xa60000 0x3000>;
		reg-names = "jpeg";
		reg-names = "jpeg_hw", "jpeg_vbif";
		interrupts = <0 304 0>;
		interrupt-names = "jpeg";
		mmagic-vdd-supply = <&gdsc_mmagic_camss>;
@@ -563,6 +573,11 @@
		qcom,prefetch-reg-settings = <0x18c 0x11>,
			<0x1a0 0x31>,
			<0x1b0 0x31>;
		qcom,msm-bus,name = "msm_camera_jpeg_dma";
		qcom,msm-bus,num-cases = <2>;
		qcom,msm-bus,num-paths = <1>;
		qcom,msm-bus,vectors-KBps = <62 512 0 0>,
			<62 512 666675 666675>;
		status = "ok";
	};

@@ -671,11 +686,18 @@
			"smmu_cpp_axi_clk", "camss_ahb_clk",
			"camss_cpp_axi_clk", "cpp_vbif_ahb_clk",
			"smmu_cpp_ahb_clk";
		clock-rates = <0 0 0 400000000 400000000>,
			<400000000 80000000 0 0 0 0 0>;
		qcom,bus-bandwidth-vectors = <13000000 13000000>,
			<45000000 45000000>,
			<90000000 90000000>;
		qcom,clock-rates =
			<0 0 0 400000000 400000000 0 0 0 0 0 0 0>,
			<0 0 0 400000000 400000000 0 0 0 0 0 0 0>,
			<0 0 0 200000000 200000000 0 0 0 0 0 0 0>,
			<0 0 0 100000000 100000000 0 0 0 0 0 0 0>;
		qcom,msm-bus,name = "msm_camera_fd";
		qcom,msm-bus,num-cases = <4>;
		qcom,msm-bus,num-paths = <1>;
		qcom,msm-bus,vectors-KBps = <106 512 0 0>,
			<106 512 13000 13000>,
			<106 512 13000 13000>,
			<106 512 13000 13000>;
		qcom,fd-vbif-reg-settings = <0x20 0x10000000 0x30000000>,
			<0x24 0x10000000 0x30000000>,
			<0x28 0x10000000 0x30000000>,
+14 −10
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@
#include "msm_fd_dev.h"
#include "msm_fd_hw.h"
#include "msm_fd_regs.h"
#include "cam_hw_ops.h"

#define MSM_FD_DRV_NAME "msm_fd"

@@ -1212,6 +1211,7 @@ static int fd_probe(struct platform_device *pdev)
	spin_lock_init(&fd->slock);
	init_completion(&fd->hw_halt_completion);
	INIT_LIST_HEAD(&fd->buf_queue);
	fd->pdev = pdev;
	fd->dev = &pdev->dev;

	/* Get resources */
@@ -1222,18 +1222,20 @@ static int fd_probe(struct platform_device *pdev)
		goto error_mem_resources;
	}

	ret = msm_fd_hw_get_regulators(fd);
	ret = msm_camera_get_regulator_info(pdev, &fd->vdd,
		&fd->num_reg);
	if (ret < 0) {
		dev_err(&pdev->dev, "Fail to get regulators\n");
		goto error_get_regulator;
	}
	ret = msm_fd_hw_get_clocks(fd);
	ret = msm_camera_get_clk_info_and_rates(pdev, &fd->clk_info,
		&fd->clk, &fd->clk_rates, &fd->clk_rates_num, &fd->clk_num);
	if (ret < 0) {
		dev_err(&pdev->dev, "Fail to get clocks\n");
		goto error_get_clocks;
	}

	ret = msm_fd_hw_get_bus(fd);
	ret = msm_camera_register_bus_client(pdev, CAM_BUS_CLIENT_FD);
	if (ret < 0) {
		dev_err(&pdev->dev, "Fail to get bus\n");
		goto error_get_bus;
@@ -1289,11 +1291,12 @@ error_video_register:
error_v4l2_register:
	msm_fd_hw_release_irq(fd);
error_hw_get_request_irq:
	msm_fd_hw_put_bus(fd);
	msm_camera_unregister_bus_client(CAM_BUS_CLIENT_FD);
error_get_bus:
	msm_fd_hw_put_clocks(fd);
	msm_camera_put_clk_info_and_rates(pdev, &fd->clk_info,
		&fd->clk, &fd->clk_rates, fd->clk_rates_num, fd->clk_num);
error_get_clocks:
	msm_fd_hw_put_regulators(fd);
	msm_camera_put_regulators(pdev, &fd->vdd, fd->num_reg);
error_get_regulator:
	msm_fd_hw_release_mem_resources(fd);
error_mem_resources:
@@ -1317,9 +1320,10 @@ static int fd_device_remove(struct platform_device *pdev)
	video_unregister_device(&fd->video);
	v4l2_device_unregister(&fd->v4l2_dev);
	msm_fd_hw_release_irq(fd);
	msm_fd_hw_put_bus(fd);
	msm_fd_hw_put_clocks(fd);
	msm_fd_hw_put_regulators(fd);
	msm_camera_unregister_bus_client(CAM_BUS_CLIENT_FD);
	msm_camera_put_clk_info_and_rates(pdev, &fd->clk_info,
		&fd->clk, &fd->clk_rates, fd->clk_rates_num, fd->clk_num);
	msm_camera_put_regulators(pdev, &fd->vdd, fd->num_reg);
	msm_fd_hw_release_mem_resources(fd);
	kfree(fd);

+13 −14
Original line number Diff line number Diff line
/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2014-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
@@ -20,6 +20,8 @@
#include <media/msm_fd.h>
#include <linux/dma-buf.h>
#include <linux/msm_ion.h>
#include "cam_soc_api.h"
#include "cam_hw_ops.h"
/* Maximum number of result buffers */
#define MSM_FD_MAX_RESULT_BUFS 5
/* Max number of clocks defined in device tree */
@@ -220,26 +222,23 @@ struct msm_fd_device {
	int ref_count;

	int irq_num;
	struct resource *res_mem[MSM_FD_IOMEM_LAST];
	void __iomem *iomem_base[MSM_FD_IOMEM_LAST];
	struct resource *ioarea[MSM_FD_IOMEM_LAST];
	struct regulator *vdd[MSM_FD_MAX_REGULATOR_NUM];
	unsigned int regulator_num;

	unsigned int clk_num;
	struct clk *clk[MSM_FD_MAX_CLK_NUM];
	unsigned int clk_rates_num;
	unsigned int clk_rates[MSM_FD_MAX_CLK_RATES][MSM_FD_MAX_CLK_NUM];

	struct msm_bus_vectors *bus_vectors;
	struct msm_bus_paths *bus_paths;
	struct msm_bus_scale_pdata bus_scale_data;
	struct msm_cam_clk_info *clk_info;
	struct regulator **vdd;
	int num_reg;
	struct resource *irq;

	size_t clk_num;
	size_t clk_rates_num;
	struct clk **clk;
	uint32_t **clk_rates;
	uint32_t bus_client;

	unsigned int iommu_attached_cnt;

	int iommu_hdl;
	struct device *dev;
	struct platform_device *pdev;
	struct v4l2_device v4l2_dev;
	struct video_device video;

+69 −443
Original line number Diff line number Diff line
/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2014-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
@@ -544,7 +544,7 @@ int msm_fd_hw_request_irq(struct platform_device *pdev,
{
	int ret;

	fd->irq_num = platform_get_irq(pdev, 0);
	fd->irq = msm_camera_get_irq(pdev, "fd");
	if (fd->irq_num < 0) {
		dev_err(fd->dev, "Can not get fd core irq resource\n");
		ret = -ENODEV;
@@ -553,21 +553,19 @@ int msm_fd_hw_request_irq(struct platform_device *pdev,

	/* If vbif is shared we will need wrapper irq for releasing vbif */
	if (msm_fd_hw_misc_irq_supported(fd)) {
		ret = devm_request_irq(fd->dev, fd->irq_num,
			msm_fd_hw_misc_irq, IRQF_TRIGGER_RISING,
			dev_name(&pdev->dev), fd);
		ret = msm_camera_register_irq(pdev,
				fd->irq, msm_fd_hw_misc_irq,
				IRQF_TRIGGER_RISING, "fd", fd);
		if (ret) {
			dev_err(fd->dev, "Can not claim wrapper IRQ %d\n",
				fd->irq_num);
			dev_err(fd->dev, "Can not claim wrapper IRQ\n");
			goto error_irq;
		}
	} else {
		ret = devm_request_irq(fd->dev, fd->irq_num,
			msm_fd_hw_core_irq, IRQF_TRIGGER_RISING,
			dev_name(fd->dev), fd);
		ret = msm_camera_register_irq(pdev,
				fd->irq, msm_fd_hw_core_irq,
				IRQF_TRIGGER_RISING, "fd", fd);
		if (ret) {
			dev_err(&pdev->dev, "Can not claim core IRQ %d\n",
				fd->irq_num);
			dev_err(&pdev->dev, "Can not claim core IRQ\n");
			goto error_irq;
		}

@@ -585,7 +583,7 @@ int msm_fd_hw_request_irq(struct platform_device *pdev,
	return 0;

error_alloc_workqueue:
	devm_free_irq(fd->dev, fd->irq_num, fd);
	msm_camera_unregister_irq(pdev, fd->irq, fd);
error_irq:
	return ret;
}
@@ -596,10 +594,9 @@ error_irq:
 */
void msm_fd_hw_release_irq(struct msm_fd_device *fd)
{
	if (fd->irq_num >= 0) {
		devm_free_irq(fd->dev, fd->irq_num, fd);
		fd->irq_num = -1;
	}
	if (fd->irq)
		msm_camera_unregister_irq(fd->pdev, fd->irq, fd);

	if (fd->work_queue) {
		destroy_workqueue(fd->work_queue);
		fd->work_queue = NULL;
@@ -715,21 +712,12 @@ int msm_fd_hw_set_dt_parms(struct msm_fd_device *fd)
 */
void msm_fd_hw_release_mem_resources(struct msm_fd_device *fd)
{
	int i;

	/* Prepare memory resources */
	for (i = 0; i < MSM_FD_IOMEM_LAST; i++) {
		if (fd->iomem_base[i]) {
			iounmap(fd->iomem_base[i]);
			fd->iomem_base[i] = NULL;
		}
		if (fd->ioarea[i]) {
			release_mem_region(fd->res_mem[i]->start,
				resource_size(fd->res_mem[i]));
			fd->ioarea[i] = NULL;
		}
		fd->res_mem[i] = NULL;
	}
	msm_camera_put_reg_base(fd->pdev,
		fd->iomem_base[MSM_FD_IOMEM_MISC], "fd_misc", true);
	msm_camera_put_reg_base(fd->pdev,
		fd->iomem_base[MSM_FD_IOMEM_CORE], "fd_core", true);
	msm_camera_put_reg_base(fd->pdev,
		fd->iomem_base[MSM_FD_IOMEM_VBIF], "fd_vbif", false);
}

/*
@@ -742,258 +730,59 @@ void msm_fd_hw_release_mem_resources(struct msm_fd_device *fd)
int msm_fd_hw_get_mem_resources(struct platform_device *pdev,
	struct msm_fd_device *fd)
{
	int i;
	int ret = 0;

	/* Prepare memory resources */
	for (i = 0; i < MSM_FD_IOMEM_LAST; i++) {
		/* Get resources */
		fd->res_mem[i] = platform_get_resource(pdev,
			IORESOURCE_MEM, i);
		if (!fd->res_mem[i]) {
			dev_err(fd->dev, "Fail get resource idx %d\n",
				i);
	fd->iomem_base[MSM_FD_IOMEM_CORE] =
		msm_camera_get_reg_base(pdev, "fd_core", true);
	if (!fd->iomem_base[MSM_FD_IOMEM_CORE]) {
		dev_err(fd->dev, "%s can not map fd_core region\n", __func__);
		ret = -ENODEV;
			break;
		goto fd_core_base_failed;
	}

		fd->ioarea[i] = request_mem_region(fd->res_mem[i]->start,
			resource_size(fd->res_mem[i]), fd->res_mem[i]->name);
		if (!fd->ioarea[i]) {
			dev_err(fd->dev, "%s can not request mem\n",
				fd->res_mem[i]->name);
	fd->iomem_base[MSM_FD_IOMEM_MISC] =
		msm_camera_get_reg_base(pdev, "fd_misc", true);
	if (!fd->iomem_base[MSM_FD_IOMEM_MISC]) {
		dev_err(fd->dev, "%s can not map fd_misc region\n", __func__);
		ret = -ENODEV;
			break;
		goto fd_misc_base_failed;
	}

		fd->iomem_base[i] = ioremap(fd->res_mem[i]->start,
			resource_size(fd->res_mem[i]));
		if (!fd->iomem_base[i]) {
			dev_err(fd->dev, "%s can not remap region\n",
				fd->res_mem[i]->name);
	fd->iomem_base[MSM_FD_IOMEM_VBIF] =
		msm_camera_get_reg_base(pdev, "fd_vbif", false);
	if (!fd->iomem_base[MSM_FD_IOMEM_VBIF]) {
		dev_err(fd->dev, "%s can not map fd_vbif region\n", __func__);
		ret = -ENODEV;
			break;
		}
	}

	if (ret < 0)
		msm_fd_hw_release_mem_resources(fd);

	return ret;
}

/*
 * msm_fd_hw_get_regulators - Get fd regulators.
 * @fd: Pointer to fd device.
 *
 * Read regulator information from device tree and perform get regulator.
 */
int msm_fd_hw_get_regulators(struct msm_fd_device *fd)
{
	const char *regulator_name;
	uint32_t cnt;
	int i;
	int ret;

	if (of_get_property(fd->dev->of_node, "qcom,vdd-names", NULL)) {
		cnt = of_property_count_strings(fd->dev->of_node,
						 "qcom,vdd-names");

		if ((cnt == 0) || (cnt == -EINVAL)) {
			dev_err(fd->dev, "no regulators found, count=%d\n",
				 cnt);
			return -EINVAL;
		}

		if (cnt > MSM_FD_MAX_REGULATOR_NUM) {
			dev_err(fd->dev,
				 "Exceed max number of regulators %d\n", cnt);
			return -EINVAL;
		}

		for (i = 0; i < cnt; i++) {
			ret = of_property_read_string_index(fd->dev->of_node,
						"qcom,vdd-names",
						i, &regulator_name);
			if (ret < 0) {
				dev_err(fd->dev,
					 "Cannot read regulator name %d\n", i);
				return ret;
		goto fd_vbif_base_failed;
	}

			fd->vdd[i] = regulator_get(fd->dev, regulator_name);
			if (IS_ERR(fd->vdd[i])) {
				ret = PTR_ERR(fd->vdd[i]);
				fd->vdd[i] = NULL;
				dev_err(fd->dev, "Error regulator get %s\n",
					 regulator_name);
				goto regulator_get_error;
			}
			dev_dbg(fd->dev, "Regulator name idx %d %s\n", i,
				 regulator_name);
		}
		fd->regulator_num = cnt;
	} else {
		fd->regulator_num = 1;
		fd->vdd[0] = regulator_get(fd->dev, "vdd");
		if (IS_ERR(fd->vdd[0])) {
			dev_err(fd->dev, "Fail to get vdd regulator\n");
			ret = PTR_ERR(fd->vdd[0]);
			fd->vdd[0] = NULL;
	return ret;
		}
	}
	return 0;

regulator_get_error:
	for (; i > 0; i--) {
		if (!IS_ERR_OR_NULL(fd->vdd[i - 1]))
			regulator_put(fd->vdd[i - 1]);
	}
fd_vbif_base_failed:
	msm_camera_put_reg_base(pdev,
		fd->iomem_base[MSM_FD_IOMEM_MISC], "fd_misc", true);
fd_misc_base_failed:
	msm_camera_put_reg_base(pdev,
		fd->iomem_base[MSM_FD_IOMEM_CORE], "fd_core", true);
fd_core_base_failed:
	return ret;
}

/*
 * msm_fd_hw_put_regulators - Put fd regulators.
 * @fd: Pointer to fd device.
 */
int msm_fd_hw_put_regulators(struct msm_fd_device *fd)
{
	int i;

	for (i = fd->regulator_num - 1; i >= 0; i--) {
		if (!IS_ERR_OR_NULL(fd->vdd[i]))
			regulator_put(fd->vdd[i]);
	}
	return 0;
}

/*
 * msm_fd_hw_enable_regulators - Prepare and enable fd regulators.
 * msm_fd_hw_bus_request - Request bus for memory access.
 * @fd: Pointer to fd device.
 * @idx: Bus bandwidth array index described in device tree.
 */
static int msm_fd_hw_enable_regulators(struct msm_fd_device *fd)
static int msm_fd_hw_bus_request(struct msm_fd_device *fd, unsigned int idx)
{
	int i;
	int ret;

	for (i = 0; i < fd->regulator_num; i++) {

		ret = regulator_enable(fd->vdd[i]);
	ret = msm_camera_update_bus_vector(CAM_BUS_CLIENT_FD, idx);
	if (ret < 0) {
			dev_err(fd->dev, "regulator enable failed %d\n", i);
			regulator_put(fd->vdd[i]);
			goto error;
		}
	}

	return 0;
error:
	for (; i > 0; i--) {
		if (!IS_ERR_OR_NULL(fd->vdd[i - 1])) {
			regulator_disable(fd->vdd[i - 1]);
			regulator_put(fd->vdd[i - 1]);
		}
	}
	return ret;
}

/*
 * msm_fd_hw_disable_regulators - Disable fd regulator.
 * @fd: Pointer to fd device.
 */
static void msm_fd_hw_disable_regulators(struct msm_fd_device *fd)
{
	int i;

	for (i = fd->regulator_num - 1; i >= 0; i--) {
		if (!IS_ERR_OR_NULL(fd->vdd[i]))
			regulator_disable(fd->vdd[i]);
	}
}

/*
 * msm_fd_hw_get_clocks - Get fd clocks.
 * @fd: Pointer to fd device.
 *
 * Read clock information from device tree and perform get clock.
 */
int msm_fd_hw_get_clocks(struct msm_fd_device *fd)
{
	const char *clk_name;
	size_t cnt;
	int clk_rates;
	int i;
	int ret;

	cnt = of_property_count_strings(fd->dev->of_node, "clock-names");
	if (cnt > MSM_FD_MAX_CLK_NUM) {
		dev_err(fd->dev, "Exceed max number of clocks %zu\n", cnt);
		dev_err(fd->dev, "Fail bus scale update %d\n", ret);
		return -EINVAL;
	}

	clk_rates = 0;
	for (i = 0; i < cnt; i++) {
		ret = of_property_read_string_index(fd->dev->of_node,
			"clock-names", i, &clk_name);
		if (ret < 0) {
			dev_err(fd->dev, "Can not read clock name %d\n", i);
			goto error;
		}

		fd->clk[i] = clk_get(fd->dev, clk_name);
		if (IS_ERR(fd->clk[i])) {
			ret = -ENOENT;
			dev_err(fd->dev, "Error clock get %s\n", clk_name);
			goto error;
		}
		dev_dbg(fd->dev, "Clock name idx %d %s\n", i, clk_name);
	}
	fd->clk_num = cnt;

	cnt = 0;
	for (clk_rates = 0; clk_rates < MSM_FD_MAX_CLK_RATES; clk_rates++) {
		for (i = 0; i < fd->clk_num; i++) {
			ret = of_property_read_u32_index(fd->dev->of_node,
				"clock-rates", cnt++,
				&fd->clk_rates[clk_rates][i]);
			if (ret < 0)
				break;
			dev_dbg(fd->dev, "Clock rate idx %d idx %d value %d\n",
				clk_rates, i, fd->clk_rates[clk_rates][i]);

		}
		if (ret < 0)
			break;
	}
	fd->clk_rates_num = clk_rates;
	if (fd->clk_rates_num == 0) {
		ret = -ENOENT;
		dev_err(fd->dev, "Can not get clock rates\n");
		goto error;
	}

	return 0;
error:
	for (; i > 0; i--)
		clk_put(fd->clk[i - 1]);

	return ret;
}

/*
 * msm_fd_hw_get_clocks - Put fd clocks.
 * @fd: Pointer to fd device.
 */
int msm_fd_hw_put_clocks(struct msm_fd_device *fd)
{
	int i;

	for (i = 0; i < fd->clk_num; i++) {
		if (!IS_ERR_OR_NULL(fd->clk[i]))
			clk_put(fd->clk[i]);
		fd->clk_num = 0;
	}
	return 0;
}

@@ -1006,7 +795,6 @@ static int msm_fd_hw_set_clock_rate_idx(struct msm_fd_device *fd,
		unsigned int idx)
{
	int ret;
	long clk_rate;
	int i;

	if (idx >= fd->clk_rates_num) {
@@ -1015,181 +803,17 @@ static int msm_fd_hw_set_clock_rate_idx(struct msm_fd_device *fd,
	}

	for (i = 0; i < fd->clk_num; i++) {

		clk_rate = clk_round_rate(fd->clk[i], fd->clk_rates[idx][i]);
		if (clk_rate < 0) {
			dev_dbg(fd->dev, "Clk raund rate fail skip %d\n", i);
			continue;
		}

		ret = clk_set_rate(fd->clk[i], clk_rate);
		ret = msm_camera_clk_set_rate(&fd->pdev->dev,
			fd->clk[i], fd->clk_rates[idx][i]);
		if (ret < 0) {
			dev_err(fd->dev, "Fail clock rate %ld\n", clk_rate);
			dev_err(fd->dev, "fail set rate on idx[%u][%u]\n",
				idx, i);
			return -EINVAL;
		}
		dev_dbg(fd->dev, "Clk rate %d-%ld idx %d\n", i, clk_rate, idx);
	}

	return 0;
}
/*
 * msm_fd_hw_enable_clocks - Prepare and enable fd clocks.
 * @fd: Pointer to fd device.
 */
static int msm_fd_hw_enable_clocks(struct msm_fd_device *fd)
{
	int i;
	int ret;

	for (i = 0; i < fd->clk_num; i++) {
		ret = clk_prepare(fd->clk[i]);
		if (ret < 0) {
			dev_err(fd->dev, "clock prepare failed %d\n", i);
			goto error;
		}

		ret = clk_enable(fd->clk[i]);
		if (ret < 0) {
			dev_err(fd->dev, "clock enable %d\n", i);
			clk_unprepare(fd->clk[i]);
			goto error;
		}
	}

	return 0;
error:
	for (; i > 0; i--) {
		clk_disable(fd->clk[i - 1]);
		clk_unprepare(fd->clk[i - 1]);
	}
	return ret;
}
/*
 * msm_fd_hw_disable_clocks - Disable fd clock.
 * @fd: Pointer to fd device.
 */
static void msm_fd_hw_disable_clocks(struct msm_fd_device *fd)
{
	int i;

	for (i = 0; i < fd->clk_num; i++) {
		clk_disable(fd->clk[i]);
		clk_unprepare(fd->clk[i]);
	}
}

/*
 * msm_fd_hw_get_bus - Get bus bandwidth.
 * @fd: Pointer to fd device.
 *
 * Read bus bandwidth information from device tree.
 */
int msm_fd_hw_get_bus(struct msm_fd_device *fd)
{
	size_t cnt;
	unsigned int ab;
	unsigned int ib;
	unsigned int idx;
	int usecase;
	int ret;

	idx = MSM_FD_MAX_CLK_RATES;

	fd->bus_vectors = kzalloc(sizeof(*fd->bus_vectors) * idx, GFP_KERNEL);
	if (!fd->bus_vectors) {
		dev_err(fd->dev, "No memory for bus vectors\n");
		return -ENOMEM;
	}

	fd->bus_paths = kzalloc(sizeof(*fd->bus_paths) * idx, GFP_KERNEL);
	if (!fd->bus_paths) {
		dev_err(fd->dev, "No memory for bus paths\n");
		kfree(fd->bus_vectors);
		fd->bus_vectors = NULL;
		return -ENOMEM;
	}

	cnt = 0;
	for (usecase = 0; usecase < idx; usecase++) {
		ret = of_property_read_u32_index(fd->dev->of_node,
			"qcom,bus-bandwidth-vectors", cnt++, &ab);
		if (ret < 0)
			break;

		ret = of_property_read_u32_index(fd->dev->of_node,
			"qcom,bus-bandwidth-vectors", cnt++, &ib);
		if (ret < 0)
			break;

		fd->bus_vectors[usecase].src = MSM_BUS_MASTER_CPP;
		fd->bus_vectors[usecase].dst = MSM_BUS_SLAVE_EBI_CH0;
		fd->bus_vectors[usecase].ab = ab;
		fd->bus_vectors[usecase].ib = ib;

		fd->bus_paths[usecase].num_paths = 1;
		fd->bus_paths[usecase].vectors = &fd->bus_vectors[usecase];

		dev_dbg(fd->dev, "Bus bandwidth idx %d ab %u ib %u\n",
			usecase, ab, ib);
	}

	fd->bus_scale_data.usecase = fd->bus_paths;
	fd->bus_scale_data.num_usecases = usecase;
	fd->bus_scale_data.name = MSM_FD_BUS_CLIENT_NAME;

	return 0;
}

/*
 * msm_fd_hw_put_bus - Put bus bandwidth.
 * @fd: Pointer to fd device.
 */
void msm_fd_hw_put_bus(struct msm_fd_device *fd)
{
	kfree(fd->bus_vectors);
	fd->bus_vectors = NULL;

	kfree(fd->bus_paths);
	fd->bus_paths = NULL;

	fd->bus_scale_data.num_usecases = 0;
}
/*
 * msm_fd_hw_bus_request - Request bus for memory access.
 * @fd: Pointer to fd device.
 * @idx: Bus bandwidth array index described in device tree.
 */
static int msm_fd_hw_bus_request(struct msm_fd_device *fd, unsigned int idx)
{
	int ret;

	fd->bus_client = msm_bus_scale_register_client(&fd->bus_scale_data);
	if (!fd->bus_client) {
		dev_err(fd->dev, "Fail to register bus client\n");
		return -ENOENT;
	}

	ret = msm_bus_scale_client_update_request(fd->bus_client, idx);
	if (ret < 0) {
		dev_err(fd->dev, "Fail bus scale update %d\n", ret);
		return -EINVAL;
	}

	return 0;
}

/*
 * msm_fd_hw_bus_release - Release memory access bus.
 * @fd: Pointer to fd device.
 */
static void msm_fd_hw_bus_release(struct msm_fd_device *fd)
{
	if (fd->bus_client) {
		msm_bus_scale_unregister_client(fd->bus_client);
		fd->bus_client = 0;
	}
}

/*
 * msm_fd_hw_get - Get fd hw for performing any hw operation.
 * @fd: Pointer to fd device.
@@ -1205,7 +829,8 @@ int msm_fd_hw_get(struct msm_fd_device *fd, unsigned int clock_rate_idx)
	mutex_lock(&fd->lock);

	if (fd->ref_count == 0) {
		ret = msm_fd_hw_enable_regulators(fd);
		ret =
			msm_camera_regulator_enable(fd->vdd, fd->num_reg, true);
		if (ret < 0) {
			dev_err(fd->dev, "Fail to enable vdd\n");
			goto error;
@@ -1216,16 +841,15 @@ int msm_fd_hw_get(struct msm_fd_device *fd, unsigned int clock_rate_idx)
			dev_err(fd->dev, "Fail bus request\n");
			goto error_bus_request;
		}

		ret = msm_fd_hw_set_clock_rate_idx(fd, clock_rate_idx);
		if (ret < 0) {
			dev_err(fd->dev, "Fail to set clock rate idx\n");
			goto error_clocks;
		}

		ret = msm_fd_hw_enable_clocks(fd);
		ret = msm_camera_clk_enable(&fd->pdev->dev, fd->clk_info,
				fd->clk, fd->clk_num, true);
		if (ret < 0) {
			dev_err(fd->dev, "Fail to enable clocks\n");
			dev_err(fd->dev, "Fail clk enable request\n");
			goto error_clocks;
		}

@@ -1245,11 +869,11 @@ int msm_fd_hw_get(struct msm_fd_device *fd, unsigned int clock_rate_idx)
error_set_dt:
	if (msm_fd_hw_misc_irq_supported(fd))
		msm_fd_hw_misc_irq_disable(fd);
	msm_fd_hw_disable_clocks(fd);
	msm_camera_clk_enable(&fd->pdev->dev, fd->clk_info,
		fd->clk, fd->clk_num, false);
error_clocks:
	msm_fd_hw_bus_release(fd);
error_bus_request:
	msm_fd_hw_disable_regulators(fd);
	msm_camera_regulator_enable(fd->vdd, fd->num_reg, false);
error:
	mutex_unlock(&fd->lock);
	return ret;
@@ -1273,9 +897,11 @@ void msm_fd_hw_put(struct msm_fd_device *fd)
		if (msm_fd_hw_misc_irq_supported(fd))
			msm_fd_hw_misc_irq_disable(fd);

		msm_fd_hw_bus_release(fd);
		msm_fd_hw_disable_clocks(fd);
		msm_fd_hw_disable_regulators(fd);
		/* vector index 0 is 0 ab and 0 ib */
		msm_fd_hw_bus_request(fd, 0);
		msm_camera_clk_enable(&fd->pdev->dev, fd->clk_info,
				fd->clk, fd->clk_num, false);
		msm_camera_regulator_enable(fd->vdd, fd->num_reg, false);
	}
	mutex_unlock(&fd->lock);
}
+191 −322

File changed.

Preview size limit exceeded, changes collapsed.

Loading