浏览代码

Merge "msm: camera: sensor: Add support for CSIPHY TPG 1.2" into camera-kernel.lnx.5.0

Savita Patted 3 年之前
父节点
当前提交
d8b7b5f0a9

+ 1 - 0
Kbuild

@@ -210,6 +210,7 @@ camera-$(CONFIG_SPECTRA_SENSOR) += \
 	drivers/cam_sensor_module/cam_tpg/cam_tpg_core.o \
 	drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw.o \
 	drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_v_1_0/tpg_hw_v_1_0.o \
+	drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_v_1_2/tpg_hw_v_1_2.o \
 	drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_v_1_3/tpg_hw_v_1_3.o \
 	drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.o \
 	drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.o \

+ 5 - 0
drivers/cam_sensor_module/cam_tpg/cam_tpg_dev.c

@@ -7,6 +7,7 @@
 #include "cam_tpg_core.h"
 #include "camera_main.h"
 #include "tpg_hw/tpg_hw_v_1_0/tpg_hw_v_1_0_data.h"
+#include "tpg_hw/tpg_hw_v_1_2/tpg_hw_v_1_2_data.h"
 #include "tpg_hw/tpg_hw_v_1_3/tpg_hw_v_1_3_data.h"
 
 static int cam_tpg_subdev_close(struct v4l2_subdev *sd,
@@ -369,6 +370,10 @@ static const struct of_device_id cam_tpg_dt_match[] = {
 		.compatible = "qcom,cam-tpg101",
 		.data = &tpg_v_1_0_hw_info,
 	},
+	{
+		.compatible = "qcom,cam-tpg102",
+		.data = &tpg_v_1_2_hw_info,
+	},
 	{
 		.compatible = "qcom,cam-tpg103",
 		.data = &tpg_v_1_3_hw_info,

+ 5 - 0
drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw.c

@@ -379,6 +379,7 @@ int tpg_hw_start(struct tpg_hw *hw)
 		if (hw->hw_info->ops->start)
 			hw->hw_info->ops->start(hw, NULL);
 		break;
+	case TPG_HW_VERSION_1_2:
 	case TPG_HW_VERSION_1_3:
 		if (hw->hw_info->ops->start)
 			hw->hw_info->ops->start(hw, NULL);
@@ -405,6 +406,7 @@ int tpg_hw_stop(struct tpg_hw *hw)
 	switch (hw->hw_info->version) {
 	case TPG_HW_VERSION_1_0:
 	case TPG_HW_VERSION_1_1:
+	case TPG_HW_VERSION_1_2:
 	case TPG_HW_VERSION_1_3:
 		if (hw->hw_info->ops->stop)
 			rc = hw->hw_info->ops->stop(hw, NULL);
@@ -433,6 +435,7 @@ int tpg_hw_acquire(struct tpg_hw *hw,
 	switch (hw->hw_info->version) {
 	case TPG_HW_VERSION_1_0:
 	case TPG_HW_VERSION_1_1:
+	case TPG_HW_VERSION_1_2:
 	case TPG_HW_VERSION_1_3:
 		// Start Cpas and enable required clocks
 		break;
@@ -456,6 +459,7 @@ int tpg_hw_release(struct tpg_hw *hw)
 	switch (hw->hw_info->version) {
 	case TPG_HW_VERSION_1_0:
 	case TPG_HW_VERSION_1_1:
+	case TPG_HW_VERSION_1_2:
 	case TPG_HW_VERSION_1_3:
 		break;
 	default:
@@ -480,6 +484,7 @@ static int tpg_hw_configure_init_settings(
 	switch (hw->hw_info->version) {
 	case TPG_HW_VERSION_1_0:
 	case TPG_HW_VERSION_1_1:
+	case TPG_HW_VERSION_1_2:
 	case TPG_HW_VERSION_1_3:
 		rc = tpg_hw_soc_enable(hw, CAM_SVS_VOTE);
 		if (hw->hw_info->ops->init)

+ 1 - 0
drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw.h

@@ -14,6 +14,7 @@
 #include <media/cam_sensor.h>
 #define TPG_HW_VERSION_1_0 0x10000000
 #define TPG_HW_VERSION_1_1 0x10000001
+#define TPG_HW_VERSION_1_2 0x10000002
 #define TPG_HW_VERSION_1_3 0x10000003
 
 

+ 282 - 0
drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_v_1_2/tpg_hw_v_1_2.c

@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include "tpg_hw_v_1_2.h"
+
+/* TPG HW IDs */
+enum cam_tpg_hw_id {
+    CAM_TPG_0 = 13,
+    CAM_TPG_1,
+    CAM_TPG_MAX,
+};
+
+static struct cam_tpg_ver_1_2_reg_offset cam_tpg102_reg = {
+	.tpg_hw_version = 0x0,
+	.tpg_hw_status = 0x4,
+	.tpg_module_cfg = 0x60,
+	.tpg_cfg0 = 0x68,
+	.tpg_cfg1 = 0x6C,
+	.tpg_cfg2 = 0x70,
+	.tpg_cfg3 = 0x74,
+	.tpg_spare = 0x1FC,
+
+	/* configurations */
+	.major_version = 1,
+	.minor_version = 0,
+	.version_incr = 2,
+	.tpg_en_shift = 0,
+	.tpg_hbi_shift = 20,
+	.tpg_dt_shift = 11,
+	.tpg_rotate_period_shift = 5,
+	.tpg_split_en_shift = 4,
+	.top_mux_reg_offset = 0x90,
+	.tpg_mux_sel_tpg_0_shift = 0,
+	.tpg_mux_sel_tpg_1_shift = 8,
+};
+
+static int configure_global_configs(
+	struct tpg_hw *hw,
+	int num_vcs,
+	struct tpg_global_config_t *configs)
+{
+	uint32_t val;
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_tpg_ver_1_2_reg_offset *tpg_reg = &cam_tpg102_reg;
+
+	if (!hw) {
+		CAM_ERR(CAM_TPG, "invalid params");
+		return -EINVAL;
+	}
+	soc_info = hw->soc_info;
+
+	if (num_vcs <= 0) {
+		CAM_ERR(CAM_TPG, "Invalid vc count");
+		return -EINVAL;
+	}
+
+	/* Program number of frames */
+	val = 0xFFFFF;
+	cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_cfg3);
+	CAM_DBG(CAM_TPG, "TPG[%d] cfg3=0x%x",
+			hw->hw_idx, val);
+
+	val = cam_io_r_mb(soc_info->reg_map[1].mem_base +
+			tpg_reg->top_mux_reg_offset);
+
+	if (hw->hw_idx == CAM_TPG_0)
+		val |= 1 << tpg_reg->tpg_mux_sel_tpg_0_shift;
+	else if (hw->hw_idx == CAM_TPG_1)
+		val |= 1 << tpg_reg->tpg_mux_sel_tpg_1_shift;
+
+	cam_io_w_mb(val,
+			soc_info->reg_map[1].mem_base + tpg_reg->top_mux_reg_offset);
+	CAM_INFO(CAM_TPG, "TPG[%d] Set CPAS top mux: 0x%x",
+			hw->hw_idx, val);
+
+	val = (1 << tpg_reg->tpg_en_shift);
+	cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_module_cfg);
+	CAM_DBG(CAM_TPG, "TPG[%d] tpg_module_cfg=0x%x", hw->hw_idx, val);
+
+	return 0;
+}
+
+static int configure_dt(
+	struct tpg_hw *hw,
+	uint32_t       vc_slot,
+	uint32_t       dt_slot,
+	struct tpg_stream_config_t *stream)
+{
+	uint32_t val;
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_tpg_ver_1_2_reg_offset *tpg_reg = &cam_tpg102_reg;
+	if (!hw) {
+		CAM_ERR(CAM_TPG, "invalid params");
+		return -EINVAL;
+	}
+
+	soc_info = hw->soc_info;
+	CAM_DBG(CAM_TPG, "TPG[%d] slot(%d,%d) <= dt:%d",
+			hw->hw_idx,
+			vc_slot,
+			dt_slot,
+			stream->dt);
+
+	val = (((stream->stream_dimension.width & 0xFFFF) << 16) |
+			(stream->stream_dimension.height & 0xFFFF));
+	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+			tpg_reg->tpg_cfg0);
+	CAM_DBG(CAM_TPG, "TPG[%d] cfg0=0x%x",
+			hw->hw_idx, val);
+
+	val = stream->dt << tpg_reg->tpg_dt_shift;
+	cam_io_w_mb(val,
+			soc_info->reg_map[0].mem_base +
+			tpg_reg->tpg_cfg2);
+	CAM_DBG(CAM_TPG, "TPG[%d] cfg2=0x%x",
+			hw->hw_idx, val);
+
+	return 0;
+}
+
+static int configure_vc(
+	struct tpg_hw *hw,
+	uint32_t       vc_slot,
+	int            num_dts,
+	struct tpg_stream_config_t *stream)
+{
+	uint32_t val = 0;
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_tpg_ver_1_2_reg_offset *tpg_reg = &cam_tpg102_reg;
+	if (!hw) {
+		CAM_ERR(CAM_TPG, "invalid params");
+		return -EINVAL;
+	}
+
+	soc_info = hw->soc_info;
+	if (stream->cb_mode == TPG_COLOR_BAR_MODE_SPLIT)
+		val |= (1 << tpg_reg->tpg_split_en_shift);
+
+	CAM_DBG(CAM_TPG, "TPG[%d] period: %d", hw->hw_idx, stream->rotate_period);
+	val |= ((stream->rotate_period & 0x3F) <<
+			tpg_reg->tpg_rotate_period_shift);
+	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+			tpg_reg->tpg_cfg2);
+	CAM_DBG(CAM_TPG, "TPG[%d] cfg2=0x%x",
+			hw->hw_idx, val);
+
+	val = stream->hbi << tpg_reg->tpg_hbi_shift | stream->vbi;
+	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+			tpg_reg->tpg_cfg1);
+	CAM_DBG(CAM_TPG, "TPG[%d] cfg1=0x%x",
+			hw->hw_idx, val);
+
+	return 0;
+}
+
+static int tpg_hw_v_1_2_reset(
+	struct tpg_hw *hw, void *data)
+{
+	struct cam_hw_soc_info *soc_info = NULL;
+	uint32_t val;
+	struct cam_tpg_ver_1_2_reg_offset *tpg_reg = &cam_tpg102_reg;
+	if (!hw) {
+		CAM_ERR(CAM_TPG, "invalid params");
+		return -EINVAL;
+	}
+
+	soc_info = hw->soc_info;
+
+	/* Clear out tpg_module_cfg before reset */
+	cam_io_w_mb(0, soc_info->reg_map[0].mem_base + tpg_reg->tpg_module_cfg);
+
+	/* Read the version */
+	val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+			tpg_reg->tpg_hw_version);
+	CAM_INFO(CAM_TPG, "TPG[%d] TPG HW version: 0x%x started",
+			hw->hw_idx, val);
+	return 0;
+}
+
+int tpg_hw_v_1_2_process_cmd(
+	struct tpg_hw *hw,
+	uint32_t       cmd,
+	void          *arg)
+{
+	int rc = 0;
+	if (hw == NULL) {
+		CAM_ERR(CAM_TPG, "invalid argument");
+		return -EINVAL;
+	}
+
+	CAM_DBG(CAM_TPG, "TPG[%d] Cmd opcode:0x%x", hw->hw_idx, cmd);
+	switch(cmd) {
+	case TPG_CONFIG_VC:
+	{
+		struct vc_config_args *vc_config =
+			(struct vc_config_args *)arg;
+
+		if (vc_config == NULL) {
+			CAM_ERR(CAM_TPG, "invalid argument");
+			return -EINVAL;
+		}
+		rc = configure_vc(hw,
+			vc_config->vc_slot,
+			vc_config->num_dts,
+			vc_config->stream);
+	}
+	break;
+	case TPG_CONFIG_DT:
+	{
+		struct dt_config_args *dt_config =
+			(struct dt_config_args *)arg;
+
+		if (dt_config == NULL) {
+			CAM_ERR(CAM_TPG, "invalid argument");
+			return -EINVAL;
+		}
+		rc = configure_dt(hw,
+			dt_config->vc_slot,
+			dt_config->dt_slot,
+			dt_config->stream);
+	}
+	break;
+	case TPG_CONFIG_CTRL:
+	{
+		struct global_config_args *global_args =
+			(struct global_config_args *)arg;
+		rc = configure_global_configs(hw,
+				global_args->num_vcs,
+				global_args->globalconfig);
+	}
+	break;
+	default:
+		CAM_ERR(CAM_TPG, "invalid argument");
+		break;
+	}
+	return rc;
+}
+
+int tpg_hw_v_1_2_start(struct tpg_hw *hw, void *data)
+{
+	CAM_DBG(CAM_TPG, "TPG V1.2 HWL start");
+	return 0;
+}
+
+int tpg_hw_v_1_2_stop(struct tpg_hw *hw, void *data)
+{
+	CAM_DBG(CAM_TPG, "TPG V1.2 HWL stop");
+	tpg_hw_v_1_2_reset(hw, data);
+	return 0;
+}
+
+int tpg_hw_v_1_2_dump_status(struct tpg_hw *hw, void *data)
+{
+	struct cam_hw_soc_info *soc_info = NULL;
+	uint32_t val;
+	struct cam_tpg_ver_1_2_reg_offset *tpg_reg = &cam_tpg102_reg;
+
+	if (!hw) {
+		CAM_ERR(CAM_TPG, "invalid params");
+		return -EINVAL;
+	}
+
+	soc_info = hw->soc_info;
+	CAM_DBG(CAM_TPG, "TPG V1.2 HWL status dump");
+	/* Read the version */
+	val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+			tpg_reg->tpg_hw_status);
+	CAM_INFO(CAM_TPG, "TPG[%d] TPG HW status: 0x%x started",
+			hw->hw_idx, val);
+
+	return 0;
+}
+
+int tpg_hw_v_1_2_init(struct tpg_hw *hw, void *data)
+{
+	CAM_DBG(CAM_TPG, "TPG V1.2 HWL init");
+	tpg_hw_v_1_2_reset(hw, data);
+	return 0;
+}

+ 89 - 0
drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_v_1_2/tpg_hw_v_1_2.h

@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef __TPG_HW_V_1_2_H__
+#define __TPG_HW_V_1_2_H__
+
+#include "../tpg_hw.h"
+
+struct cam_tpg_ver_1_2_reg_offset {
+	uint32_t tpg_hw_version;
+	uint32_t tpg_hw_status;
+	uint32_t tpg_module_cfg;
+	uint32_t tpg_cfg0;
+	uint32_t tpg_cfg1;
+	uint32_t tpg_cfg2;
+	uint32_t tpg_cfg3;
+	uint32_t tpg_spare;
+
+	/* configurations */
+	uint32_t major_version;
+	uint32_t minor_version;
+	uint32_t version_incr;
+	uint32_t tpg_en_shift;
+	uint32_t tpg_hbi_shift;
+	uint32_t tpg_dt_shift;
+	uint32_t tpg_rotate_period_shift;
+	uint32_t tpg_split_en_shift;
+	uint32_t top_mux_reg_offset;
+	uint32_t tpg_mux_sel_tpg_0_shift;
+	uint32_t tpg_mux_sel_tpg_1_shift;
+};
+
+
+/**
+ * @brief initialize the tpg hw instance
+ *
+ * @param hw   : tpg hw instance
+ * @param data : argument for initialize
+ *
+ * @return     : 0 on success
+ */
+int tpg_hw_v_1_2_init(struct tpg_hw *hw, void *data);
+
+/**
+ * @brief start tpg hw
+ *
+ * @param hw    : tpg hw instance
+ * @param data  : tpg hw instance data
+ *
+ * @return      : 0 on success
+ */
+int tpg_hw_v_1_2_start(struct tpg_hw *hw, void *data);
+
+/**
+ * @brief stop tpg hw
+ *
+ * @param hw   : tpg hw instance
+ * @param data : argument for tpg hw stop
+ *
+ * @return     : 0 on success
+ */
+int tpg_hw_v_1_2_stop(struct tpg_hw *hw, void *data);
+
+/**
+ * @brief process a command send from hw layer
+ *
+ * @param hw  : tpg hw instance
+ * @param cmd : command to process
+ * @param arg : argument corresponding to command
+ *
+ * @return    : 0 on success
+ */
+int tpg_hw_v_1_2_process_cmd(struct tpg_hw *hw,
+		uint32_t cmd, void *arg);
+
+/**
+ * @brief  dump hw status registers
+ *
+ * @param hw   : tpg hw instance
+ * @param data : argument for status dump
+ *
+ * @return     : 0 on sucdess
+ */
+int tpg_hw_v_1_2_dump_status(struct tpg_hw *hw, void *data);
+
+#endif

+ 28 - 0
drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_v_1_2/tpg_hw_v_1_2_data.h

@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef __TPG_HW_V_1_2_DATA_H__
+#define __TPG_HW_V_1_2_DATA_H__
+
+#include "../tpg_hw.h"
+#include "tpg_hw_v_1_2.h"
+
+struct tpg_hw_ops tpg_hw_v_1_2_ops = {
+	.start = tpg_hw_v_1_2_start,
+	.stop  = tpg_hw_v_1_2_stop,
+	.init = tpg_hw_v_1_2_init,
+	.process_cmd = tpg_hw_v_1_2_process_cmd,
+	.dump_status = tpg_hw_v_1_2_dump_status,
+};
+
+struct tpg_hw_info tpg_v_1_2_hw_info = {
+	.version = TPG_HW_VERSION_1_2,
+	.max_vc_channels = 1,
+	.max_dt_channels_per_vc = 1,
+	.ops = &tpg_hw_v_1_2_ops,
+};
+
+#endif