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

Commit 703db8f4 authored by Trishansh Bhardwaj's avatar Trishansh Bhardwaj
Browse files

msm: camera: Add support to camera cx ipeak



Adds cx-ipeak support in camera driver.

Change-Id: I75a35d7b4256b5319ec893bc698b6e5a9c1f2c3b
Signed-off-by: default avatarSuresh Vankadara <svankada@codeaurora.org>
Signed-off-by: default avatarTrishansh Bhardwaj <tbhardwa@codeaurora.org>
parent cc2aae71
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -169,6 +169,16 @@ First Level Node - CAM CPAS device
  Definition: Bool property specifying whether Clients are connected
	through CAMNOC for AXI access.

- qcom,cam-cx-ipeak:
  Usage: optional
  Value type: <phandle bit>
	phandle - phandle of CX Ipeak device node
	bit     - Every bit corresponds to a client of CX Ipeak
  Definition: CX Ipeak is a mitigation scheme which throttles camera frequency
	if all the clients are running at their respective threshold
	frequencies to limit CX peak current.
	driver in the relevant register.

===================================================================
Third Level Node - CAM AXI Port properties
===================================================================
@@ -226,6 +236,7 @@ Example:
		src-clock-name = "slow_ahb_clk_src";
		clock-rates = <0 0 0 0 80000000 0>;
		clock-cntl-level = "turbo";
		qcom,cam-cx-ipeak = <&cx_ipeak_lm 2>;
		control-camnoc-axi-clk;
		camnoc-bus-width = <32>;
		camnoc-axi-clk-bw-margin-perc = <10>;
+11 −0
Original line number Diff line number Diff line
@@ -153,6 +153,16 @@ and name of firmware image.
  Value type: <u32>
  Definition: UBWC configuration.

- qcom,cam-cx-ipeak:
  Usage: optional
  Value type: <phandle bit>
	phandle - phandle of CX Ipeak device node
	bit     - Every bit corresponds to a client of CX Ipeak
  Definition: CX Ipeak is a mitigation scheme which throttles camera frequency
	if all the clients are running at their respective threshold
	frequencies to limit CX peak current.
	driver in the relevant register.

Examples:
a5: qcom,a5@ac00000 {
	cell-index = <0>;
@@ -244,6 +254,7 @@ qcom,ipe1 {
		<0 0 0 0 600000000>;
	clock-cntl-level = "lowsvs", "svs",
		"svs_l1", "nominal", "turbo";
	qcom,cam-cx-ipeak = <&cx_ipeak_lm 2>;
};

bps: qcom,bps {
+11 −0
Original line number Diff line number Diff line
@@ -96,6 +96,16 @@ Optional properties:
  Value type: <string>
  Definition: Enable/Disable clk rate control.

- qcom,cam-cx-ipeak:
  Usage: optional
  Value type: <phandle bit>
	phandle - phandle of CX Ipeak device node
	bit     - Every bit corresponds to a client of CX Ipeak
  Definition: CX Ipeak is a mitigation scheme which throttles camera frequency
	if all the clients are running at their respective threshold
	frequencies to limit CX peak current.
	driver in the relevant register.

Example:
	qcom,vfe0@acaf000 {
		cell-index = <0>;
@@ -130,5 +140,6 @@ Example:
		clock-names-option = "ife_dsp_clk";
		clocks-option = <&clock_camcc CAM_CC_IFE_0_DSP_CLK>;
		clock-rates-option = <600000000>;
		qcom,cam-cx-ipeak = <&cx_ipeak_lm 2>;
		status = "ok";
	};
+1 −0
Original line number Diff line number Diff line
@@ -3,3 +3,4 @@ ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr/
ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/

obj-$(CONFIG_SPECTRA_CAMERA) += cam_soc_util.o cam_io_util.o cam_packet_util.o cam_debug_util.o cam_trace.o cam_common_util.o
obj-$(CONFIG_SPECTRA_CAMERA) += cam_cx_ipeak.o
+135 −0
Original line number Diff line number Diff line
/* Copyright (c) 2018, 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
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/of.h>
#include <linux/clk.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <soc/qcom/cx_ipeak.h>
#include "cam_soc_util.h"
#include "cam_debug_util.h"

static struct cx_ipeak_client *cam_cx_ipeak;
static int cx_ipeak_level = CAM_NOMINAL_VOTE;
static int cx_default_ipeak_mask;
static int cx_current_ipeak_mask;
static int cam_cx_client_cnt;

int cam_cx_ipeak_register_cx_ipeak(struct cam_hw_soc_info *soc_info)
{
	int rc = 0;

	soc_info->cam_cx_ipeak_enable = true;
	soc_info->cam_cx_ipeak_bit = 1 << cam_cx_client_cnt++;
	cx_default_ipeak_mask |= soc_info->cam_cx_ipeak_bit;

	if (cam_cx_ipeak)
		goto exit;

	cam_cx_ipeak = cx_ipeak_register(soc_info->dev->of_node,
		"qcom,cam-cx-ipeak");

	if (cam_cx_ipeak) {
		goto exit;
	} else {
		rc = -EINVAL;
		goto exit;
	}

exit:
	CAM_DBG(CAM_UTIL, "cam_cx_ipeak is enabled for %s\n"
		"mask = %x cx_default_ipeak_mask = %x",
		soc_info->dev_name, soc_info->cam_cx_ipeak_bit,
		cx_default_ipeak_mask);
	return rc;
}

int cam_cx_ipeak_update_vote_cx_ipeak(struct cam_hw_soc_info *soc_info,
	int32_t apply_level)
{
	int32_t soc_cx_ipeak_bit = soc_info->cam_cx_ipeak_bit;
	int ret = 0;

	CAM_DBG(CAM_UTIL, "E: apply_level = %d cx_current_ipeak_mask = %x\n"
			"soc_cx_ipeak_bit = %x",
			apply_level, cx_current_ipeak_mask, soc_cx_ipeak_bit);

	if (apply_level < cx_ipeak_level &&
		(cx_current_ipeak_mask & soc_cx_ipeak_bit)) {
		if (cx_current_ipeak_mask == cx_default_ipeak_mask) {
			ret = cx_ipeak_update(cam_cx_ipeak, false);
			if (ret)
				goto exit;
			CAM_DBG(CAM_UTIL,
				"X: apply_level = %d cx_current_ipeak_mask = %x\n"
				"soc_cx_ipeak_bit = %x  %s UNVOTE",
				apply_level, cx_current_ipeak_mask,
				soc_cx_ipeak_bit, soc_info->dev_name);
		}
		cx_current_ipeak_mask &= (~soc_cx_ipeak_bit);
		CAM_DBG(CAM_UTIL,
			"X: apply_level = %d cx_current_ipeak_mask = %x\n"
			"soc_cx_ipeak_bit = %x  %s DISABLE_BIT",
			apply_level, cx_current_ipeak_mask,
			soc_cx_ipeak_bit, soc_info->dev_name);
		goto exit;
	} else if (apply_level < cx_ipeak_level) {
		CAM_DBG(CAM_UTIL,
			"X: apply_level = %d cx_current_ipeak_mask = %x\n"
			"soc_cx_ipeak_bit = %x NO AI",
			apply_level, cx_current_ipeak_mask, soc_cx_ipeak_bit);
		goto exit;
	}

	cx_current_ipeak_mask |= soc_cx_ipeak_bit;
	CAM_DBG(CAM_UTIL,
		"X: apply_level = %d cx_current_ipeak_mask = %x\n"
		"soc_cx_ipeak_bit = %x  %s ENABLE_BIT",
		apply_level, cx_current_ipeak_mask,
		soc_cx_ipeak_bit, soc_info->dev_name);
	if (cx_current_ipeak_mask == cx_default_ipeak_mask) {
		ret = cx_ipeak_update(cam_cx_ipeak, true);
		if (ret)
			goto exit;
		CAM_DBG(CAM_UTIL,
			"X: apply_level = %d cx_current_ipeak_mask = %x\n"
			"soc_cx_ipeak_bit = %x  %s VOTE",
			apply_level, cx_current_ipeak_mask,
			soc_cx_ipeak_bit, soc_info->dev_name);
	}

exit:
	return ret;
}

int cam_cx_ipeak_unvote_cx_ipeak(struct cam_hw_soc_info *soc_info)
{
	int32_t soc_cx_ipeak_bit = soc_info->cam_cx_ipeak_bit;

	CAM_DBG(CAM_UTIL, "E:cx_current_ipeak_mask = %x\n"
		"soc_cx_ipeak_bit = %x",
		cx_current_ipeak_mask, soc_cx_ipeak_bit);
	if (cx_current_ipeak_mask == cx_default_ipeak_mask) {
		if (cam_cx_ipeak)
			cx_ipeak_update(cam_cx_ipeak, false);
		CAM_DBG(CAM_UTIL, "X:cx_current_ipeak_mask = %x\n"
			"soc_cx_ipeak_bit = %x UNVOTE",
			cx_current_ipeak_mask, soc_cx_ipeak_bit);
	}
	cx_current_ipeak_mask &= (~soc_cx_ipeak_bit);
	CAM_DBG(CAM_UTIL, "X:cx_current_ipeak_mask = %x\n"
		"soc_cx_ipeak_bit = %x",
		cx_current_ipeak_mask, soc_cx_ipeak_bit);

	return 0;
}
Loading