Jelajahi Sumber

msm: camera: sensor: Add tpg hw layer for lanai target

Add tpg hw layer for lanai target.

CRs-Fixed: 3308233
External Impact: No
Change-Id: Id3f5da6bc891840d4d00d0f4ef3db8a4a5a4cd74
Signed-off-by: Rishab Garg <[email protected]>
Rishab Garg 2 tahun lalu
induk
melakukan
b35f65ac17

+ 1 - 0
Kbuild

@@ -228,6 +228,7 @@ camera-$(CONFIG_SPECTRA_SENSOR) += \
 	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_tpg/tpg_hw/tpg_hw_v_1_4/tpg_hw_v_1_4.o \
 	drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.o \
 	drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.o \
 	drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.o \

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

@@ -10,6 +10,7 @@
 #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"
+#include "tpg_hw/tpg_hw_v_1_4/tpg_hw_v_1_4_data.h"
 
 static int cam_tpg_subdev_close(struct v4l2_subdev *sd,
 	struct v4l2_subdev_fh *fh)
@@ -384,6 +385,10 @@ static const struct of_device_id cam_tpg_dt_match[] = {
 		.compatible = "qcom,cam-tpg1031",
 		.data = &tpg_v_1_3_1_hw_info,
 	},
+	{
+		.compatible = "qcom,cam-tpg104",
+		.data = &tpg_v_1_4_hw_info,
+	},
 	{}
 };
 

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

@@ -486,6 +486,7 @@ int tpg_hw_dump_status(struct tpg_hw *hw)
 	switch (hw->hw_info->version) {
 	case TPG_HW_VERSION_1_3:
 	case TPG_HW_VERSION_1_3_1:
+	case TPG_HW_VERSION_1_4:
 		if (hw->hw_info->ops->dump_status)
 			hw->hw_info->ops->dump_status(hw, NULL);
 		break;
@@ -512,6 +513,7 @@ int tpg_hw_start(struct tpg_hw *hw)
 	case TPG_HW_VERSION_1_2:
 	case TPG_HW_VERSION_1_3:
 	case TPG_HW_VERSION_1_3_1:
+	case TPG_HW_VERSION_1_4:
 		if (hw->hw_info->ops->start)
 			hw->hw_info->ops->start(hw, NULL);
 		if (hw->stream_version == 1)
@@ -543,6 +545,7 @@ int tpg_hw_stop(struct tpg_hw *hw)
 	case TPG_HW_VERSION_1_2:
 	case TPG_HW_VERSION_1_3:
 	case TPG_HW_VERSION_1_3_1:
+	case TPG_HW_VERSION_1_4:
 		if (hw->hw_info->ops->stop) {
 			rc = hw->hw_info->ops->stop(hw, NULL);
 			if (rc) {
@@ -584,6 +587,7 @@ int tpg_hw_acquire(struct tpg_hw *hw,
 	case TPG_HW_VERSION_1_2:
 	case TPG_HW_VERSION_1_3:
 	case TPG_HW_VERSION_1_3_1:
+	case TPG_HW_VERSION_1_4:
 		// Start Cpas and enable required clocks
 		break;
 	default:
@@ -609,6 +613,7 @@ int tpg_hw_release(struct tpg_hw *hw)
 	case TPG_HW_VERSION_1_2:
 	case TPG_HW_VERSION_1_3:
 	case TPG_HW_VERSION_1_3_1:
+	case TPG_HW_VERSION_1_4:
 		break;
 	default:
 		CAM_ERR(CAM_TPG, "TPG[%d] Unsupported HW Version",
@@ -671,6 +676,7 @@ static int tpg_hw_configure_init_settings(
 	case TPG_HW_VERSION_1_2:
 	case TPG_HW_VERSION_1_3:
 	case TPG_HW_VERSION_1_3_1:
+	case TPG_HW_VERSION_1_4:
 		clk_level = get_tpg_clk_level(hw);
 		rc = tpg_hw_soc_enable(hw, clk_level);
 		if (rc) {
@@ -712,6 +718,7 @@ static int tpg_hw_configure_init_settings_v3(
 	case TPG_HW_VERSION_1_2:
 	case TPG_HW_VERSION_1_3:
 	case TPG_HW_VERSION_1_3_1:
+	case TPG_HW_VERSION_1_4:
 		rc = tpg_hw_soc_enable(hw, CAM_SVS_VOTE);
 		if (rc) {
 			CAM_ERR(CAM_TPG, "TPG[%d] hw soc enable failed %d",

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

@@ -17,7 +17,7 @@
 #define TPG_HW_VERSION_1_2   0x10000002
 #define TPG_HW_VERSION_1_3   0x10000003
 #define TPG_HW_VERSION_1_3_1 0x10000004
-
+#define TPG_HW_VERSION_1_4   0x10000005
 
 struct tpg_hw;
 

+ 901 - 0
drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_v_1_4/tpg_hw_v_1_4.c

@@ -0,0 +1,901 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include "tpg_hw_v_1_4.h"
+
+enum tpg_hw_v_1_4_encode_fomat_t {
+	RAW_8_BIT = 1,
+	RAW_10_BIT,
+	RAW_12_BIT,
+	RAW_14_BIT,
+	RAW_16_BIT
+};
+
+#define  FRAME_INTERLEAVE  0x0
+#define  LINE_INTERLEAVE   0x1
+#define  SHDR_INTERLEAVE   0x2
+#define  SPARSE_PD_INTERLEAVE 0x3
+#define  CFA_PATTERN_ROW_WIDTH      8
+#define  CFA_PATTERN_BITS_PER_INDEX 2
+#define  Invalid 0x0
+#define  Red     0x0
+#define  Green   0x1
+#define  Blue    0x2
+#define  IR      0x3
+#define  Mono    0x3
+
+static int get_tpg_vc_dt_pattern_id(
+		enum tpg_interleaving_format_t vc_dt_pattern)
+{
+	switch (vc_dt_pattern) {
+	case TPG_INTERLEAVING_FORMAT_INVALID:
+	case TPG_INTERLEAVING_FORMAT_MAX:
+	case TPG_INTERLEAVING_FORMAT_FRAME:
+		return FRAME_INTERLEAVE;
+	case TPG_INTERLEAVING_FORMAT_LINE:
+		return LINE_INTERLEAVE;
+	case TPG_INTERLEAVING_FORMAT_SHDR:
+		return SHDR_INTERLEAVE;
+	case TPG_INTERLEAVING_FORMAT_SPARSE_PD:
+		return SPARSE_PD_INTERLEAVE;
+
+	}
+	return FRAME_INTERLEAVE;
+}
+
+static int get_tpg_encode_format(int sw_encode_format)
+{
+	switch (sw_encode_format) {
+	case PACK_8_BIT:
+		return RAW_8_BIT;
+	case PACK_10_BIT:
+		return RAW_10_BIT;
+	case PACK_12_BIT:
+		return RAW_12_BIT;
+	case PACK_14_BIT:
+		return RAW_14_BIT;
+	case PACK_16_BIT:
+		return RAW_16_BIT;
+	}
+	return RAW_8_BIT;
+}
+
+#define  INCREMENTING       0x0
+#define  ALTERNATING_55_AA  0x1
+#define  RANDOM             0x4
+#define  USER_SPECIFIED     0x5
+#define  COLOR_BARS         0x8
+
+static int get_tpg_payload_mode(enum tpg_pattern_t pattern)
+{
+	switch (pattern) {
+	case TPG_PATTERN_INVALID:
+	case TPG_PATTERN_REAL_IMAGE:
+	case TPG_PATTERN_COLOR_BAR:
+		return COLOR_BARS;
+	case TPG_PATTERN_RANDOM_PIXL:
+	case TPG_PATTERN_RANDOM_INCREMENTING_PIXEL:
+		return RANDOM;
+	case TPG_PATTERN_ALTERNATING_55_AA:
+		return ALTERNATING_55_AA;
+	case TPG_PATTERN_ALTERNATING_USER_DEFINED:
+		return USER_SPECIFIED;
+	default:
+		return COLOR_BARS;
+	}
+	return COLOR_BARS;
+}
+
+#define RGGB_IR_0  0x00770091
+#define RGGB_IR_1  0x00770019
+#define RGGB_2x2   0x05055A5A
+#define RGGB_3x3_0 0x05400540
+#define RGGB_3x3_1 0x0a950540
+#define RGGB_3x3_2 0x0a950a95
+#define RGGB_4x4_0 0x55005500
+#define RGGB_4x4_1 0x55005500
+#define RGGB_4x4_2 0xaa55aa55
+#define RGGB_4x4_3 0xaa55aa55
+#define VC1_GAIN   0x100
+
+static int configure_xcfa_array(struct tpg_hw *hw, int config)
+{
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_tpg_ver_1_4_reg_offset *tpg_reg = NULL;
+
+	if (!hw || !hw->hw_info || !hw->hw_info->hw_data) {
+		CAM_ERR(CAM_TPG, "invalid params");
+		return -EINVAL;
+	}
+	tpg_reg  = hw->hw_info->hw_data;
+
+	soc_info = hw->soc_info;
+
+	switch (config) {
+	case 1:
+		cam_io_w_mb(RGGB_IR_0,
+		soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc0_color_bar_cfa_color0);
+		cam_io_w_mb(RGGB_IR_1,
+		soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc0_color_bar_cfa_color1);
+		break;
+	case 2:
+		cam_io_w_mb(RGGB_2x2,
+		soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc0_color_bar_cfa_color0);
+		break;
+	case 3:
+		cam_io_w_mb(RGGB_3x3_0,
+		soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc0_color_bar_cfa_color0);
+		cam_io_w_mb(RGGB_3x3_1,
+		soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc0_color_bar_cfa_color1);
+		cam_io_w_mb(RGGB_3x3_2,
+		soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc0_color_bar_cfa_color2);
+		break;
+	case 4:
+		cam_io_w_mb(RGGB_4x4_0,
+		soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc0_color_bar_cfa_color0);
+		cam_io_w_mb(RGGB_4x4_1,
+		soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc0_color_bar_cfa_color1);
+		cam_io_w_mb(RGGB_4x4_2,
+		soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc0_color_bar_cfa_color2);
+		cam_io_w_mb(RGGB_4x4_3,
+		soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc0_color_bar_cfa_color3);
+		break;
+	break;
+
+	}
+	return 0;
+}
+
+static int configure_global_configs(
+	struct tpg_hw *hw,
+	int num_vcs,
+	struct tpg_global_config_t *configs)
+{
+	uint32_t val, phy_type = 0;
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_tpg_ver_1_4_reg_offset *tpg_reg = NULL;
+
+	if (!hw || !hw->hw_info || !hw->hw_info->hw_data) {
+		CAM_ERR(CAM_TPG, "invalid params");
+		return -EINVAL;
+	}
+
+	tpg_reg  = hw->hw_info->hw_data;
+	soc_info = hw->soc_info;
+
+	if (configs->phy_type == TPG_PHY_TYPE_CPHY)
+		phy_type = 1;
+
+	if (num_vcs <= 0) {
+		CAM_ERR(CAM_TPG, "invalid vc count");
+		return -EINVAL;
+	}
+
+	/* throttle moved to vc config
+	 * Tpg neable bit is moved to TPG_CMD register
+	 **/
+	val = (num_vcs - 1) <<
+		(tpg_reg->num_active_vc_shift) |
+		(configs->lane_count - 1) << (tpg_reg->num_active_lanes_shift) |
+		(get_tpg_vc_dt_pattern_id(configs->interleaving_format)
+		 << (tpg_reg->vc_dt_pattern_id_shift)) |
+		(phy_type << tpg_reg->phy_sel_shift);
+	cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_ctrl);
+
+	CAM_DBG(CAM_TPG, "tpg[%d] tpg_ctrl=0x%x", hw->hw_idx, val);
+
+	/* Check with hw poc if this needs to be done perframe */
+	val = (1 << tpg_reg->test_en_cmd_shift);
+	cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_ctrl_cmd);
+	CAM_DBG(CAM_TPG, "tpg[%d] tpg_ctrl_cmd=0x%x", hw->hw_idx, val);
+
+	return 0;
+}
+
+static int get_pixel_coordinate(
+	int cfa_pattern_start_index,
+	int cfa_pattern_end_index,
+	uint32_t *val,
+	struct tpg_stream_config_v3_t *configs)
+{
+	uint32_t shift = 0;
+	int idx = 0;
+	int i = 0;
+	int j = 0;
+	*val = 0;
+	for (i = cfa_pattern_start_index; i < cfa_pattern_end_index; i++) {
+		for (j = 0; j < configs->cfa_info.pattern_width; j++) {
+			shift = ((i * CFA_PATTERN_ROW_WIDTH) + j) *
+				CFA_PATTERN_BITS_PER_INDEX;
+			idx = i * configs->cfa_info.pattern_height + j;
+			*val |= (configs->cfa_info.pixel_coordinate[idx].pixel_type) << shift;
+		}
+	}
+	return 0;
+}
+
+static int configure_xcfa_array_v3(
+	struct tpg_hw *hw,
+	struct tpg_stream_config_v3_t *configs)
+{
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_tpg_ver_1_4_reg_offset *tpg_reg = NULL;
+	uint32_t val = 0;
+
+	if (!hw || !hw->hw_info || !hw->hw_info->hw_data) {
+		CAM_ERR(CAM_TPG, "invalid params");
+		return -EINVAL;
+	}
+	tpg_reg  = hw->hw_info->hw_data;
+
+	soc_info = hw->soc_info;
+
+	switch (configs->xcfa_type) {
+	case XCFA_TYPE_RGBIR:
+		get_pixel_coordinate(0, 2, &val, configs);
+		cam_io_w_mb(val,
+		soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc0_color_bar_cfa_color0);
+		get_pixel_coordinate(2, configs->cfa_info.pattern_height, &val, configs);
+		cam_io_w_mb(val,
+		soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc0_color_bar_cfa_color1);
+		break;
+	case XCFA_TYPE_QUADCFA:
+		get_pixel_coordinate(0, 2, &val, configs);
+		CAM_DBG(CAM_TPG, "val = 0x%x", val);
+		cam_io_w_mb(val,
+		soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc0_color_bar_cfa_color0);
+		get_pixel_coordinate(2, configs->cfa_info.pattern_height, &val, configs);
+		CAM_DBG(CAM_TPG, "val = 0x%x", val);
+		cam_io_w_mb(val,
+		soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc0_color_bar_cfa_color1);
+		break;
+	case XCFA_TYPE_THREEXTHREECFA:
+		get_pixel_coordinate(0, 2, &val, configs);
+		cam_io_w_mb(val,
+		soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc0_color_bar_cfa_color0);
+		get_pixel_coordinate(2, 4, &val, configs);
+		cam_io_w_mb(val,
+		soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc0_color_bar_cfa_color1);
+		get_pixel_coordinate(4, configs->cfa_info.pattern_height, &val, configs);
+		cam_io_w_mb(val,
+		soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc0_color_bar_cfa_color2);
+		break;
+	case XCFA_TYPE_FOURXFOURCFA:
+		get_pixel_coordinate(0, 2, &val, configs);
+		cam_io_w_mb(val,
+		soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc0_color_bar_cfa_color0);
+		get_pixel_coordinate(2, 4, &val, configs);
+		cam_io_w_mb(val,
+		soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc0_color_bar_cfa_color1);
+		get_pixel_coordinate(4, 6, &val, configs);
+		cam_io_w_mb(val,
+		soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc0_color_bar_cfa_color2);
+		get_pixel_coordinate(6, configs->cfa_info.pattern_height, &val, configs);
+		cam_io_w_mb(val,
+		soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc0_color_bar_cfa_color3);
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int configure_dt_v3(
+	struct tpg_hw *hw,
+	uint32_t       vc_slot,
+	uint32_t       dt_slot,
+	struct tpg_stream_config_v3_t *stream)
+{
+	uint32_t val = 0;
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_tpg_ver_1_4_reg_offset *tpg_reg = NULL;
+
+	if (!hw || !hw->hw_info || !hw->hw_info->hw_data) {
+		CAM_ERR(CAM_TPG, "invalid params");
+		return -EINVAL;
+	}
+
+	tpg_reg  = hw->hw_info->hw_data;
+
+	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) << tpg_reg->frame_width_shift) |
+			(stream->stream_dimension.height & 0xFFFF << tpg_reg->frame_height_shift));
+	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+			tpg_reg->tpg_vc0_dt_0_cfg_0 +
+			(0x60 * vc_slot) + (dt_slot * 0x0c));
+	CAM_DBG(CAM_TPG, "TPG[%d] vc%d_dt%d_cfg_0=0x%x",
+			hw->hw_idx,
+			vc_slot, dt_slot, val);
+
+	cam_io_w_mb(stream->dt,
+			soc_info->reg_map[0].mem_base +
+			tpg_reg->tpg_vc0_dt_0_cfg_1 +
+			(0x60 * vc_slot) + (dt_slot * 0x0c));
+	CAM_DBG(CAM_TPG, "TPG[%d] vc%d_dt%d_cfg_1=0x%x",
+			hw->hw_idx,
+			vc_slot, dt_slot, stream->dt);
+
+	val = ((get_tpg_encode_format(stream->pixel_depth) & 0xF) <<
+			tpg_reg->encode_format_shift) |
+			(get_tpg_payload_mode(stream->pattern_type) << tpg_reg->pattern_shift);
+	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+			tpg_reg->tpg_vc0_dt_0_cfg_2 +
+			(0x60 * vc_slot) + (dt_slot * 0x0c));
+	CAM_DBG(CAM_TPG, "TPG[%d] vc%d_dt%d_cfg_2=0x%x",
+			hw->hw_idx,
+			vc_slot, dt_slot, 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 = 0;
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_tpg_ver_1_4_reg_offset *tpg_reg = NULL;
+
+	if (!hw || !hw->hw_info || !hw->hw_info->hw_data) {
+		CAM_ERR(CAM_TPG, "invalid params");
+		return -EINVAL;
+	}
+
+	tpg_reg  = hw->hw_info->hw_data;
+
+	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) << tpg_reg->frame_width_shift) |
+			(stream->stream_dimension.height & 0xFFFF) << tpg_reg->frame_height_shift);
+	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+			tpg_reg->tpg_vc0_dt_0_cfg_0 +
+			(0x60 * vc_slot) + (dt_slot * 0x0c));
+	CAM_DBG(CAM_TPG, "TPG[%d] vc%d_dt%d_cfg_0=0x%x",
+			hw->hw_idx,
+			vc_slot, dt_slot, val);
+
+	cam_io_w_mb(stream->dt,
+			soc_info->reg_map[0].mem_base +
+			tpg_reg->tpg_vc0_dt_0_cfg_1 +
+			(0x60 * vc_slot) + (dt_slot * 0x0c));
+	CAM_DBG(CAM_TPG, "TPG[%d] vc%d_dt%d_cfg_1=0x%x",
+			hw->hw_idx,
+			vc_slot, dt_slot, stream->dt);
+
+	val = ((get_tpg_encode_format(stream->pixel_depth) & 0xF) <<
+			tpg_reg->encode_format_shift) |
+		(get_tpg_payload_mode(stream->pattern_type) << tpg_reg->pattern_shift);
+	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+			tpg_reg->tpg_vc0_dt_0_cfg_2 +
+			(0x60 * vc_slot) + (dt_slot * 0x0c));
+	CAM_DBG(CAM_TPG, "TPG[%d] vc%d_dt%d_cfg_2=0x%x",
+			hw->hw_idx,
+			vc_slot, dt_slot, val);
+
+	return 0;
+}
+
+static int configure_vc_v3(
+	struct tpg_hw *hw,
+	uint32_t       vc_slot,
+	int            num_dts,
+	struct tpg_stream_config_v3_t *stream)
+{
+	uint32_t val = 0;
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_tpg_ver_1_4_reg_offset *tpg_reg = NULL;
+
+	if (!hw || !hw->hw_info || !hw->hw_info->hw_data) {
+		CAM_ERR(CAM_TPG, "invalid params");
+		return -EINVAL;
+	}
+	tpg_reg = hw->hw_info->hw_data;
+
+	soc_info = hw->soc_info;
+	/* Use CFA pattern here */
+	if (stream->output_format == TPG_IMAGE_FORMAT_QCFA)
+		val |= (1 << tpg_reg->qcfa_en_shift);
+
+	if (stream->cb_mode == TPG_COLOR_BAR_MODE_SPLIT)
+		val |= (1 << tpg_reg->split_en_shift);
+
+	if (stream->cfa_info_exist != 0) {
+		val |= ((stream->cfa_info.pattern_height - 1) << tpg_reg->size_y_shift);
+		val |= ((stream->cfa_info.pattern_width - 1) << tpg_reg->size_x_shift);
+		val |= (1 << tpg_reg->xcfa_en_shift);
+		configure_xcfa_array_v3(hw, stream);
+	}
+
+	CAM_DBG(CAM_TPG, "TPG[%d] period: %d", hw->hw_idx, stream->rotate_period);
+	val |= ((stream->rotate_period & 0x3F) <<
+			tpg_reg->rotate_period_shift);
+	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+			tpg_reg->tpg_vc0_color_bars_cfg + (0x60 * vc_slot));
+	CAM_DBG(CAM_TPG, "TPG[%d] vc%d_color_bar_cfg=0x%x",
+			hw->hw_idx,
+			vc_slot, val);
+
+	val = stream->hbi;
+	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+			tpg_reg->tpg_vc0_hbi_cfg + (0x60 * vc_slot));
+	CAM_DBG(CAM_TPG, "TPG[%d] vc%d_hbi_cfg=0x%x",
+			hw->hw_idx,
+			vc_slot, val);
+
+	val = stream->vbi;
+	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+			tpg_reg->tpg_vc0_vbi_cfg + (0x60 * vc_slot));
+	CAM_DBG(CAM_TPG, "TPG[%d] vc%d_vbi_cgf=0x%x",
+			hw->hw_idx,
+			vc_slot, val);
+
+	val = stream->skip_pattern;
+	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+		tpg_reg->tpg_vc0_throttle + (0x60 * vc_slot));
+	CAM_DBG(CAM_TPG, "TPG[%d] vc%d_vbi_cgf=0x%x",
+		hw->hw_idx,
+			vc_slot, val);
+
+	cam_io_w_mb(0x12345678,
+		soc_info->reg_map[0].mem_base +
+		tpg_reg->tpg_vc0_lfsr_seed + (0x60 * vc_slot));
+
+	val = ((stream->frame_count << tpg_reg->num_frames_shift) |
+		((num_dts-1) <<	 tpg_reg->num_active_dt_shift) |
+		stream->vc);
+	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+			tpg_reg->tpg_vc0_cfg0 + (0x60 * vc_slot));
+	CAM_DBG(CAM_TPG, "TPG[%d] vc%d_cfg0=0x%x",
+			hw->hw_idx,
+			vc_slot, val);
+	if (hw->hw_info->shdr_overlap == 1) {
+		cam_io_w_mb(hw->hw_info->shdr_overlap << tpg_reg->overlap_shdr_en_shift,
+			soc_info->reg_map[0].mem_base + tpg_reg->tpg_ctrl);
+	}
+	if (hw->hw_info->shdr_offset_num_batch >= 0 && vc_slot > 0)	{
+		val =  (VC1_GAIN << tpg_reg->gain_shift);
+		val |= (hw->hw_info->shdr_offset_num_batch <<
+				tpg_reg->shdr_offset_num_batch_shift);
+		cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+					tpg_reg->tpg_vc1_gain_cfg + (0x60 * (vc_slot-1)));
+		val =  ((stream->shdr_line_offset0 * vc_slot)
+			<< tpg_reg->shdr_line_offset0_shift);
+		val |= ((stream->shdr_line_offset1 * vc_slot)
+			<< tpg_reg->shdr_line_offset1_shift);
+		cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+			tpg_reg->tpg_vc1_shdr_cfg + (0x60 * (vc_slot-1)));
+		CAM_DBG(CAM_TPG, "TPG[%d] vc%d_cfg0=0x%x shdr",
+			hw->hw_idx,
+			vc_slot, 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_4_reg_offset *tpg_reg = NULL;
+
+	if (!hw || !hw->hw_info || !hw->hw_info->hw_data) {
+		CAM_ERR(CAM_TPG, "invalid params");
+		return -EINVAL;
+	}
+	tpg_reg  = hw->hw_info->hw_data;
+
+	soc_info = hw->soc_info;
+
+
+	if (stream->output_format == TPG_IMAGE_FORMAT_QCFA)
+		val |= (1 << tpg_reg->qcfa_en_shift);
+
+	if (stream->cb_mode == TPG_COLOR_BAR_MODE_SPLIT)
+		val |= (1 << tpg_reg->split_en_shift);
+
+	if (stream->xcfa_debug > 0) {
+		if (stream->xcfa_debug == 1) {
+			val |= (3 << tpg_reg->size_y_shift);
+			val |= (3 << tpg_reg->size_x_shift);
+		} else {
+			val |= ((stream->xcfa_debug * 2 - 1) << tpg_reg->size_y_shift);
+			val |= ((stream->xcfa_debug * 2 - 1) << tpg_reg->size_x_shift);
+		}
+		val |= (1 << tpg_reg->xcfa_en_shift);
+		configure_xcfa_array(hw, stream->xcfa_debug);
+		CAM_DBG(CAM_TPG, "xcfa_debug = %d", stream->xcfa_debug);
+	}
+
+	CAM_DBG(CAM_TPG, "TPG[%d] period: %d", hw->hw_idx, stream->rotate_period);
+	val |= ((stream->rotate_period & 0x3F) <<
+			tpg_reg->rotate_period_shift);
+	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+			tpg_reg->tpg_vc0_color_bars_cfg + (0x60 * vc_slot));
+	CAM_DBG(CAM_TPG, "TPG[%d] vc%d_color_bar_cfg=0x%x",
+			hw->hw_idx,
+			vc_slot, val);
+
+	val = stream->hbi;
+	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+			tpg_reg->tpg_vc0_hbi_cfg + (0x60 * vc_slot));
+	CAM_DBG(CAM_TPG, "TPG[%d] vc%d_hbi_cfg=0x%x",
+			hw->hw_idx,
+			vc_slot, val);
+
+	val = stream->vbi;
+	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+			tpg_reg->tpg_vc0_vbi_cfg + (0x60 * vc_slot));
+	CAM_DBG(CAM_TPG, "TPG[%d] vc%d_vbi_cgf=0x%x",
+			hw->hw_idx,
+			vc_slot, val);
+
+	val = stream->skip_pattern;
+	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+		tpg_reg->tpg_vc0_throttle + (0x60 * vc_slot));
+	CAM_DBG(CAM_TPG, "TPG[%d] vc%d_vbi_cgf=0x%x",
+		hw->hw_idx,
+			vc_slot, val);
+
+	cam_io_w_mb(0x12345678,
+		soc_info->reg_map[0].mem_base +
+		tpg_reg->tpg_vc0_lfsr_seed + (0x60 * vc_slot));
+
+	val = ((stream->frame_count << tpg_reg->num_frames_shift) |
+		((num_dts-1) <<	 tpg_reg->num_active_dt_shift) |
+		stream->vc);
+	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+			tpg_reg->tpg_vc0_cfg0 + (0x60 * vc_slot));
+	CAM_DBG(CAM_TPG, "TPG[%d] vc%d_cfg0=0x%x",
+			hw->hw_idx,
+			vc_slot, val);
+	if (hw->hw_info->shdr_overlap == 1) {
+		cam_io_w_mb(hw->hw_info->shdr_overlap << tpg_reg->overlap_shdr_en_shift,
+			soc_info->reg_map[0].mem_base + tpg_reg->tpg_ctrl);
+	}
+	if (hw->hw_info->shdr_offset_num_batch >= 0 && vc_slot > 0)	{
+		val =  (VC1_GAIN << tpg_reg->gain_shift);
+		val |= (hw->hw_info->shdr_offset_num_batch <<
+				tpg_reg->shdr_offset_num_batch_shift);
+		cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+					tpg_reg->tpg_vc1_gain_cfg + (0x60 * (vc_slot-1)));
+		val =  ((stream->shdr_line_offset0 * vc_slot)
+			<< tpg_reg->shdr_line_offset0_shift);
+		val |= ((stream->shdr_line_offset1 * vc_slot)
+			<< tpg_reg->shdr_line_offset1_shift);
+		cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+			tpg_reg->tpg_vc1_shdr_cfg + (0x60 * (vc_slot-1)));
+		CAM_DBG(CAM_TPG, "TPG[%d] vc%d_cfg0=0x%x shdr",
+			hw->hw_idx,
+			vc_slot, val);
+	}
+
+
+	return 0;
+}
+
+static int tpg_hw_v_1_4_reset(
+	struct tpg_hw *hw, void *data)
+{
+	struct cam_hw_soc_info *soc_info = NULL;
+	uint32_t val;
+	struct cam_tpg_ver_1_4_reg_offset *tpg_reg = NULL;
+
+	if (!hw || !hw->hw_info || !hw->hw_info->hw_data) {
+		CAM_ERR(CAM_TPG, "invalid params");
+		return -EINVAL;
+	}
+	tpg_reg  = hw->hw_info->hw_data;
+
+	soc_info = hw->soc_info;
+	/* Clear out tpg_ctrl and irqs before reset */
+	cam_io_w_mb(0, soc_info->reg_map[0].mem_base + tpg_reg->tpg_ctrl);
+
+	cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
+			tpg_reg->top_irq_mask);
+
+	cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
+			tpg_reg->top_irq_clear);
+
+	cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
+			tpg_reg->irq_cmd);
+
+	cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
+			tpg_reg->top_irq_clear);
+
+	/* Read the version */
+	val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+			tpg_reg->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_4_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;
+	}
+	switch (cmd) {
+	case TPG_CONFIG_VC:
+	{
+		if (hw->stream_version == 1) {
+			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);
+		} else if (hw->stream_version == 3) {
+			struct vc_config_args_v3 *vc_config_v3 =
+				(struct vc_config_args_v3 *)arg;
+
+			if (vc_config_v3 == NULL) {
+				CAM_ERR(CAM_TPG, "invalid argument");
+				return -EINVAL;
+			}
+			rc = configure_vc_v3(hw,
+				vc_config_v3->vc_slot,
+				vc_config_v3->num_dts,
+				vc_config_v3->stream);
+		}
+	}
+	break;
+	case TPG_CONFIG_DT:
+	{
+		if (hw->stream_version == 1) {
+			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);
+		} else if (hw->stream_version == 3) {
+			struct dt_config_args_v3 *dt_config_v3 =
+				(struct dt_config_args_v3 *)arg;
+
+			if (dt_config_v3 == NULL) {
+				CAM_ERR(CAM_TPG, "invalid argument");
+				return -EINVAL;
+			}
+			rc = configure_dt_v3(hw,
+				dt_config_v3->vc_slot,
+				dt_config_v3->dt_slot,
+				dt_config_v3->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_4_start(struct tpg_hw *hw, void *data)
+{
+	CAM_DBG(CAM_TPG, "TPG V1.4 HWL start");
+	return 0;
+}
+
+int tpg_hw_v_1_4_stop(struct tpg_hw *hw, void *data)
+{
+	CAM_DBG(CAM_TPG, "TPG V1.4 HWL stop");
+	tpg_hw_v_1_4_reset(hw, data);
+	return 0;
+}
+
+int tpg_hw_v_1_4_dump_status(struct tpg_hw *hw, void *data)
+{
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_tpg_ver_1_4_reg_offset *tpg_reg = NULL;
+
+	if (!hw || !hw->hw_info || !hw->hw_info->hw_data) {
+		CAM_ERR(CAM_TPG, "invalid params");
+		return -EINVAL;
+	}
+
+	tpg_reg  = hw->hw_info->hw_data;
+
+	soc_info = hw->soc_info;
+	CAM_DBG(CAM_TPG, "TPG V1.4 HWL status dump");
+
+	return 0;
+}
+
+int tpg_hw_v_1_4_init(struct tpg_hw *hw, void *data)
+{
+	CAM_DBG(CAM_TPG, "TPG V1.4 HWL init");
+	tpg_hw_v_1_4_reset(hw, data);
+	return 0;
+}
+
+
+
+static int tpg_1_4_get_xcfa_test(void *data, u64 *val)
+{
+	struct tpg_hw *hw = (struct tpg_hw *)data;
+
+	CAM_INFO(CAM_TPG, "get xcfa test %d", hw->hw_info->xcfa_debug);
+	*val = hw->hw_info->xcfa_debug;
+	return 0;
+}
+static int tpg_1_4_get_shdr_overlap_test(void *data, u64 *val)
+{
+	struct tpg_hw *hw = (struct tpg_hw *)data;
+
+	CAM_INFO(CAM_TPG, "get shdr test : %d", hw->hw_info->shdr_overlap);
+	*val = hw->hw_info->shdr_overlap;
+	return 0;
+}
+static int tpg_1_4_get_shdr_offset_num_batch(void *data, u64 *val)
+{
+	struct tpg_hw *hw = (struct tpg_hw *)data;
+
+	CAM_INFO(CAM_TPG, "get shdr_num_batch : %d", hw->hw_info->shdr_offset_num_batch);
+	*val = hw->hw_info->shdr_offset_num_batch;
+	return 0;
+}
+static int tpg_1_4_get_shdr_line_offset0(void *data, u64 *val)
+{
+	struct tpg_hw *hw = (struct tpg_hw *)data;
+
+	CAM_INFO(CAM_TPG, "get shdr_offset0 : %d", hw->hw_info->shdr_line_offset0);
+	*val = hw->hw_info->shdr_line_offset0;
+	return 0;
+}
+static int tpg_1_4_get_shdr_line_offset1(void *data, u64 *val)
+{
+	struct tpg_hw *hw = (struct tpg_hw *)data;
+
+	CAM_INFO(CAM_TPG, "get shdr_offset1 : %d", hw->hw_info->shdr_line_offset1);
+	*val = hw->hw_info->shdr_line_offset1;
+	return 0;
+}
+
+
+static int tpg_1_4_set_xcfa_test(void *data, u64 val)
+{
+	struct tpg_hw *hw = (struct tpg_hw *)data;
+
+	CAM_INFO(CAM_TPG, "set xcfa test prev : %d", hw->hw_info->xcfa_debug);
+	hw->hw_info->xcfa_debug = val;
+	return 0;
+}
+static int tpg_1_4_set_shdr_overlap_test(void *data, u64 val)
+{
+	struct tpg_hw *hw = (struct tpg_hw *)data;
+
+	CAM_INFO(CAM_TPG, "set shdr test prev : %d", hw->hw_info->shdr_overlap);
+	hw->hw_info->shdr_overlap = val;
+	return 0;
+}
+static int tpg_1_4_set_shdr_offset_num_batch(void *data, u64 val)
+{
+	struct tpg_hw *hw = (struct tpg_hw *)data;
+
+	CAM_INFO(CAM_TPG, "set shdr_num_batch : %d", hw->hw_info->shdr_offset_num_batch);
+	hw->hw_info->shdr_offset_num_batch = val;
+	return 0;
+}
+static int tpg_1_4_set_shdr_line_offset0(void *data, u64 val)
+{
+	struct tpg_hw *hw = (struct tpg_hw *)data;
+
+	CAM_INFO(CAM_TPG, "set shdr_offset0 : %d", hw->hw_info->shdr_line_offset0);
+	hw->hw_info->shdr_line_offset0 = val;
+	return 0;
+}
+static int tpg_1_4_set_shdr_line_offset1(void *data, u64 val)
+{
+	struct tpg_hw *hw = (struct tpg_hw *)data;
+
+	CAM_INFO(CAM_TPG, "set shdr_offset1 : %d", hw->hw_info->shdr_line_offset1);
+	hw->hw_info->shdr_line_offset1 = val;
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(tpg_1_4_xcfa_test,
+		&tpg_1_4_get_xcfa_test,
+		&tpg_1_4_set_xcfa_test,
+		"%16d");
+
+DEFINE_SIMPLE_ATTRIBUTE(tpg_1_4_shdr_overlap_test,
+		&tpg_1_4_get_shdr_overlap_test,
+		&tpg_1_4_set_shdr_overlap_test,
+		"%16d");
+DEFINE_SIMPLE_ATTRIBUTE(tpg_1_4_shdr_offset_num_batch,
+		&tpg_1_4_get_shdr_offset_num_batch,
+		&tpg_1_4_set_shdr_offset_num_batch,
+		"%16d");
+DEFINE_SIMPLE_ATTRIBUTE(tpg_1_4_shdr_line_offset0,
+		&tpg_1_4_get_shdr_line_offset0,
+		&tpg_1_4_set_shdr_line_offset0,
+		"%16d");
+DEFINE_SIMPLE_ATTRIBUTE(tpg_1_4_shdr_line_offset1,
+		&tpg_1_4_get_shdr_line_offset1,
+		&tpg_1_4_set_shdr_line_offset1,
+		"%16d");
+
+
+int tpg_1_4_layer_init(struct tpg_hw *hw)
+{
+	int rc = 0;
+	struct dentry *dbgfileptr_parent = NULL;
+	struct dentry *dbgfileptr = NULL;
+	struct dentry *dbgfileptr_shdr = NULL;
+	struct dentry *dfp_shdr_batch = NULL;
+	struct dentry *dfp_shdr_off0 = NULL;
+	struct dentry *dfp_shdr_off1 = NULL;
+	char dir_name[160];
+
+	snprintf(dir_name, sizeof(dir_name), "tpg%d",
+		hw->hw_idx);
+
+	dbgfileptr_parent = debugfs_create_dir(dir_name, NULL);
+	if (!dbgfileptr_parent) {
+		CAM_ERR(CAM_TPG, "Debug fs could not create directory");
+		rc = -ENOENT;
+	}
+
+	dbgfileptr      = debugfs_create_file("tpg_xcfa_test", 0644,
+			dbgfileptr_parent, hw, &tpg_1_4_xcfa_test);
+	dbgfileptr_shdr = debugfs_create_file("tpg_shdr_overlap_test", 0644,
+			dbgfileptr_parent, hw, &tpg_1_4_shdr_overlap_test);
+	dfp_shdr_batch  = debugfs_create_file("tpg_shdr_offset_num_batch", 0644,
+			dbgfileptr_parent, hw, &tpg_1_4_shdr_offset_num_batch);
+	dfp_shdr_off0   = debugfs_create_file("tpg_shdr_line_offset0", 0644,
+			dbgfileptr_parent, hw, &tpg_1_4_shdr_line_offset0);
+	dfp_shdr_off1   = debugfs_create_file("tpg_shdr_line_offset1", 0644,
+			dbgfileptr_parent, hw, &tpg_1_4_shdr_line_offset1);
+	CAM_INFO(CAM_TPG, "Layer init called");
+	return rc;
+}

+ 326 - 0
drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_v_1_4/tpg_hw_v_1_4.h

@@ -0,0 +1,326 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef __TPG_HW_V_1_4_H__
+#define __TPG_HW_V_1_4_H__
+
+#include "../tpg_hw.h"
+
+struct cam_tpg_ver_1_4_reg_offset {
+	/* Register offsets below */
+	int hw_version;
+	int hw_status;
+	int dmi_cfg;
+	int dmi_lut_cfg;
+	int dmi_data;
+	int dmi_data_1;
+	int dmi_data_2;
+	int dmi_data_3;
+	int dmi_data_4;
+	int dmi_data_5;
+	int dmi_data_6;
+	int dmi_data_7;
+	int dmi_data_8;
+	int dmi_data_9;
+	int dmi_data_10;
+	int dmi_data_11;
+	int dmi_data_12;
+	int dmi_data_13;
+	int dmi_data_14;
+	int dmi_data_15;
+	int dmi_cmd;
+	int dmi_status;
+	int dmi_lut_bank_cfg;
+	int module_lut_bank_cfg;
+	int tpg_vc0_gain_cfg;
+	int tpg_ctrl;
+	int tpg_vc0_cfg0;
+	int tpg_vc0_lfsr_seed;
+	int tpg_vc0_hbi_cfg;
+	int tpg_vc0_vbi_cfg;
+	int tpg_vc0_color_bars_cfg;
+	int tpg_vc0_dt_0_cfg_0;
+	int tpg_vc0_dt_0_cfg_1;
+	int tpg_vc0_dt_0_cfg_2;
+	int tpg_vc0_dt_1_cfg_0;
+	int tpg_vc0_dt_1_cfg_1;
+	int tpg_vc0_dt_1_cfg_2;
+	int tpg_vc0_dt_2_cfg_0;
+	int tpg_vc0_dt_2_cfg_1;
+	int tpg_vc0_dt_2_cfg_2;
+	int tpg_vc0_dt_3_cfg_0;
+	int tpg_vc0_dt_3_cfg_1;
+	int tpg_vc0_dt_3_cfg_2;
+	int tpg_vc0_throttle;
+	int tpg_vc0_color_bar_cfa_color0;
+	int tpg_vc0_color_bar_cfa_color1;
+	int tpg_vc0_color_bar_cfa_color2;
+	int tpg_vc0_color_bar_cfa_color3;
+	int tpg_vc1_gain_cfg;
+	int tpg_vc1_shdr_cfg;
+	int tpg_vc1_cfg0;
+	int tpg_vc1_lfsr_seed;
+	int tpg_vc1_hbi_cfg;
+	int tpg_vc1_vbi_cfg;
+	int tpg_vc1_color_bars_cfg;
+	int tpg_vc1_dt_0_cfg_0;
+	int tpg_vc1_dt_0_cfg_1;
+	int tpg_vc1_dt_0_cfg_2;
+	int tpg_vc1_dt_1_cfg_0;
+	int tpg_vc1_dt_1_cfg_1;
+	int tpg_vc1_dt_1_cfg_2;
+	int tpg_vc1_dt_2_cfg_0;
+	int tpg_vc1_dt_2_cfg_1;
+	int tpg_vc1_dt_2_cfg_2;
+	int tpg_vc1_dt_3_cfg_0;
+	int tpg_vc1_dt_3_cfg_1;
+	int tpg_vc1_dt_3_cfg_2;
+	int tpg_vc1_throttle;
+	int tpg_vc1_color_bar_cfa_color0;
+	int tpg_vc1_color_bar_cfa_color1;
+	int tpg_vc1_color_bar_cfa_color2;
+	int tpg_vc1_color_bar_cfa_color3;
+	int tpg_vc2_gain_cfg;
+	int tpg_vc2_shdr_cfg;
+	int tpg_vc2_cfg0;
+	int tpg_vc2_lfsr_seed;
+	int tpg_vc2_hbi_cfg;
+	int tpg_vc2_vbi_cfg;
+	int tpg_vc2_color_bars_cfg;
+	int tpg_vc2_dt_0_cfg_0;
+	int tpg_vc2_dt_0_cfg_1;
+	int tpg_vc2_dt_0_cfg_2;
+	int tpg_vc2_dt_1_cfg_0;
+	int tpg_vc2_dt_1_cfg_1;
+	int tpg_vc2_dt_1_cfg_2;
+	int tpg_vc2_dt_2_cfg_0;
+	int tpg_vc2_dt_2_cfg_1;
+	int tpg_vc2_dt_2_cfg_2;
+	int tpg_vc2_dt_3_cfg_0;
+	int tpg_vc2_dt_3_cfg_1;
+	int tpg_vc2_dt_3_cfg_2;
+	int tpg_vc2_throttle;
+	int tpg_vc2_color_bar_cfa_color0;
+	int tpg_vc2_color_bar_cfa_color1;
+	int tpg_vc2_color_bar_cfa_color2;
+	int tpg_vc2_color_bar_cfa_color3;
+	int tpg_vc3_gain_cfg;
+	int tpg_vc3_shdr_cfg;
+	int tpg_vc3_cfg0;
+	int tpg_vc3_lfsr_seed;
+	int tpg_vc3_hbi_cfg;
+	int tpg_vc3_vbi_cfg;
+	int tpg_vc3_color_bars_cfg;
+	int tpg_vc3_dt_0_cfg_0;
+	int tpg_vc3_dt_0_cfg_1;
+	int tpg_vc3_dt_0_cfg_2;
+	int tpg_vc3_dt_1_cfg_0;
+	int tpg_vc3_dt_1_cfg_1;
+	int tpg_vc3_dt_1_cfg_2;
+	int tpg_vc3_dt_2_cfg_0;
+	int tpg_vc3_dt_2_cfg_1;
+	int tpg_vc3_dt_2_cfg_2;
+	int tpg_vc3_dt_3_cfg_0;
+	int tpg_vc3_dt_3_cfg_1;
+	int tpg_vc3_dt_3_cfg_2;
+	int tpg_vc3_throttle;
+	int tpg_vc3_color_bar_cfa_color0;
+	int tpg_vc3_color_bar_cfa_color1;
+	int tpg_vc3_color_bar_cfa_color2;
+	int tpg_vc3_color_bar_cfa_color3;
+	int top_irq_status;
+	int top_irq_mask;
+	int top_irq_clear;
+	int top_irq_set;
+	int irq_cmd;
+	int tpg_ctrl_cmd;
+	int test_bus_ctrl;
+	int spare;
+	/* Register fields below */
+
+	int gen_shift;
+	int rev_shift;
+	int step_shift;
+	int violation_shift;
+	int auto_load_pattern_shift;
+	int auto_load_en_shift;
+	int addr_shift;
+	int lut_sel_shift;
+	int data_shift;
+	int auto_load_status_clr_shift;
+	int auto_load_cmd_shift;
+	int auto_load_done_shift;
+	int bank_sel_shift;
+	int gain_shift;
+	int num_active_vc_shift;
+	int overlap_shdr_en_shift;
+	int vc_dt_pattern_id_shift;
+	int num_active_lanes_shift;
+	int phy_sel_shift;
+	int num_frames_shift;
+	int num_batch_shift;
+	int num_active_dt_shift;
+	int fe_dis_shift;
+	int fs_dis_shift;
+	int vc_num_shift;
+	int seed_shift;
+	int hbi_clk_cnt_shift;
+	int vbi_line_cnt_shift;
+	int size_y_shift;
+	int size_x_shift;
+	int xcfa_en_shift;
+	int rotate_period_shift;
+	int pix_intl_hdr_mode_shift;
+	int noise_en_shift;
+	int split_en_shift;
+	int qcfa_en_shift;
+	int pix_pattern_shift;
+	int frame_width_shift;
+	int frame_height_shift;
+	int crc_xor_mask_shift;
+	int ecc_xor_mask_shift;
+	int nfi_ssm_mode_en_shift;
+	int data_type_shift;
+	int encode_format_shift;
+	int user_specified_payload_shift;
+	int payload_mode_shift;
+	int pattern_shift;
+	int array15_shift;
+	int array14_shift;
+	int array13_shift;
+	int array12_shift;
+	int array11_shift;
+	int array10_shift;
+	int array9_shift;
+	int array8_shift;
+	int array7_shift;
+	int array6_shift;
+	int array5_shift;
+	int array4_shift;
+	int array3_shift;
+	int array2_shift;
+	int array1_shift;
+	int array0_shift;
+	int array31_shift;
+	int array30_shift;
+	int array29_shift;
+	int array28_shift;
+	int array27_shift;
+	int array26_shift;
+	int array25_shift;
+	int array24_shift;
+	int array23_shift;
+	int array22_shift;
+	int array21_shift;
+	int array20_shift;
+	int array19_shift;
+	int array18_shift;
+	int array17_shift;
+	int array16_shift;
+	int array47_shift;
+	int array46_shift;
+	int array45_shift;
+	int array44_shift;
+	int array43_shift;
+	int array42_shift;
+	int array41_shift;
+	int array40_shift;
+	int array39_shift;
+	int array38_shift;
+	int array37_shift;
+	int array36_shift;
+	int array35_shift;
+	int array34_shift;
+	int array33_shift;
+	int array32_shift;
+	int array63_shift;
+	int array62_shift;
+	int array61_shift;
+	int array60_shift;
+	int array59_shift;
+	int array58_shift;
+	int array57_shift;
+	int array56_shift;
+	int array55_shift;
+	int array54_shift;
+	int array53_shift;
+	int array52_shift;
+	int array51_shift;
+	int array50_shift;
+	int array49_shift;
+	int array48_shift;
+	int shdr_offset_num_batch_shift;
+	int shdr_line_offset1_shift;
+	int shdr_line_offset0_shift;
+	int status_vec_shift;
+	int mask_vec_shift;
+	int clear_vec_shift;
+	int set_vec_shift;
+	int set_shift;
+	int clear_shift;
+	int test_en_cmd_shift;
+	int hw_reset_shift;
+	int test_bus_en_shift;
+	int test_bus_sel_shift;
+	int spare_shift;
+	/* Custome Variables below */
+};
+
+/**
+ * @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_4_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_4_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_4_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_4_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_4_dump_status(struct tpg_hw *hw, void *data);
+
+int tpg_1_4_layer_init(struct tpg_hw *hw);
+
+#endif /* __TPG_HW_V_1_4_H__ */

+ 271 - 0
drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_v_1_4/tpg_hw_v_1_4_0.h

@@ -0,0 +1,271 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef __TPG_HW_V_1_4_0_H__
+#define __TPG_HW_V_1_4_0_H__
+
+
+struct cam_tpg_ver_1_4_reg_offset cam_tpg104_reg = {
+	/* Register offsets below */
+	.hw_version = 0x0,
+	.hw_status = 0x4,
+	.dmi_cfg = 0x8,
+	.dmi_lut_cfg = 0xc,
+	.dmi_data = 0x10,
+	.dmi_data_1 = 0x14,
+	.dmi_data_2 = 0x18,
+	.dmi_data_3 = 0x1c,
+	.dmi_data_4 = 0x20,
+	.dmi_data_5 = 0x24,
+	.dmi_data_6 = 0x28,
+	.dmi_data_7 = 0x2c,
+	.dmi_data_8 = 0x30,
+	.dmi_data_9 = 0x34,
+	.dmi_data_10 = 0x38,
+	.dmi_data_11 = 0x3c,
+	.dmi_data_12 = 0x40,
+	.dmi_data_13 = 0x44,
+	.dmi_data_14 = 0x48,
+	.dmi_data_15 = 0x4c,
+	.dmi_cmd = 0x50,
+	.dmi_status = 0x54,
+	.dmi_lut_bank_cfg = 0x58,
+	.module_lut_bank_cfg = 0x5c,
+	.tpg_vc0_gain_cfg = 0x60,
+	.tpg_ctrl = 0x64,
+	.tpg_vc0_cfg0 = 0x68,
+	.tpg_vc0_lfsr_seed = 0x6c,
+	.tpg_vc0_hbi_cfg = 0x70,
+	.tpg_vc0_vbi_cfg = 0x74,
+	.tpg_vc0_color_bars_cfg = 0x78,
+	.tpg_vc0_dt_0_cfg_0 = 0x7c,
+	.tpg_vc0_dt_0_cfg_1 = 0x80,
+	.tpg_vc0_dt_0_cfg_2 = 0x84,
+	.tpg_vc0_dt_1_cfg_0 = 0x88,
+	.tpg_vc0_dt_1_cfg_1 = 0x8c,
+	.tpg_vc0_dt_1_cfg_2 = 0x90,
+	.tpg_vc0_dt_2_cfg_0 = 0x94,
+	.tpg_vc0_dt_2_cfg_1 = 0x98,
+	.tpg_vc0_dt_2_cfg_2 = 0x9c,
+	.tpg_vc0_dt_3_cfg_0 = 0xa0,
+	.tpg_vc0_dt_3_cfg_1 = 0xa4,
+	.tpg_vc0_dt_3_cfg_2 = 0xa8,
+	.tpg_vc0_throttle = 0xac,
+	.tpg_vc0_color_bar_cfa_color0 = 0xb0,
+	.tpg_vc0_color_bar_cfa_color1 = 0xb4,
+	.tpg_vc0_color_bar_cfa_color2 = 0xb8,
+	.tpg_vc0_color_bar_cfa_color3 = 0xbc,
+	.tpg_vc1_gain_cfg = 0xc0,
+	.tpg_vc1_shdr_cfg = 0xc4,
+	.tpg_vc1_cfg0 = 0xc8,
+	.tpg_vc1_lfsr_seed = 0xcc,
+	.tpg_vc1_hbi_cfg = 0xd0,
+	.tpg_vc1_vbi_cfg = 0xd4,
+	.tpg_vc1_color_bars_cfg = 0xd8,
+	.tpg_vc1_dt_0_cfg_0 = 0xdc,
+	.tpg_vc1_dt_0_cfg_1 = 0xe0,
+	.tpg_vc1_dt_0_cfg_2 = 0xe4,
+	.tpg_vc1_dt_1_cfg_0 = 0xe8,
+	.tpg_vc1_dt_1_cfg_1 = 0xec,
+	.tpg_vc1_dt_1_cfg_2 = 0xf0,
+	.tpg_vc1_dt_2_cfg_0 = 0xf4,
+	.tpg_vc1_dt_2_cfg_1 = 0xf8,
+	.tpg_vc1_dt_2_cfg_2 = 0xfc,
+	.tpg_vc1_dt_3_cfg_0 = 0x100,
+	.tpg_vc1_dt_3_cfg_1 = 0x104,
+	.tpg_vc1_dt_3_cfg_2 = 0x108,
+	.tpg_vc1_throttle = 0x10c,
+	.tpg_vc1_color_bar_cfa_color0 = 0x110,
+	.tpg_vc1_color_bar_cfa_color1 = 0x114,
+	.tpg_vc1_color_bar_cfa_color2 = 0x118,
+	.tpg_vc1_color_bar_cfa_color3 = 0x11c,
+	.tpg_vc2_gain_cfg = 0x120,
+	.tpg_vc2_shdr_cfg = 0x124,
+	.tpg_vc2_cfg0 = 0x128,
+	.tpg_vc2_lfsr_seed = 0x12c,
+	.tpg_vc2_hbi_cfg = 0x130,
+	.tpg_vc2_vbi_cfg = 0x134,
+	.tpg_vc2_color_bars_cfg = 0x138,
+	.tpg_vc2_dt_0_cfg_0 = 0x13c,
+	.tpg_vc2_dt_0_cfg_1 = 0x140,
+	.tpg_vc2_dt_0_cfg_2 = 0x144,
+	.tpg_vc2_dt_1_cfg_0 = 0x148,
+	.tpg_vc2_dt_1_cfg_1 = 0x14c,
+	.tpg_vc2_dt_1_cfg_2 = 0x150,
+	.tpg_vc2_dt_2_cfg_0 = 0x154,
+	.tpg_vc2_dt_2_cfg_1 = 0x158,
+	.tpg_vc2_dt_2_cfg_2 = 0x15c,
+	.tpg_vc2_dt_3_cfg_0 = 0x160,
+	.tpg_vc2_dt_3_cfg_1 = 0x164,
+	.tpg_vc2_dt_3_cfg_2 = 0x168,
+	.tpg_vc2_throttle = 0x16c,
+	.tpg_vc2_color_bar_cfa_color0 = 0x170,
+	.tpg_vc2_color_bar_cfa_color1 = 0x174,
+	.tpg_vc2_color_bar_cfa_color2 = 0x178,
+	.tpg_vc2_color_bar_cfa_color3 = 0x17c,
+	.tpg_vc3_gain_cfg = 0x180,
+	.tpg_vc3_shdr_cfg = 0x184,
+	.tpg_vc3_cfg0 = 0x188,
+	.tpg_vc3_lfsr_seed = 0x18c,
+	.tpg_vc3_hbi_cfg = 0x190,
+	.tpg_vc3_vbi_cfg = 0x194,
+	.tpg_vc3_color_bars_cfg = 0x198,
+	.tpg_vc3_dt_0_cfg_0 = 0x19c,
+	.tpg_vc3_dt_0_cfg_1 = 0x1a0,
+	.tpg_vc3_dt_0_cfg_2 = 0x1a4,
+	.tpg_vc3_dt_1_cfg_0 = 0x1a8,
+	.tpg_vc3_dt_1_cfg_1 = 0x1ac,
+	.tpg_vc3_dt_1_cfg_2 = 0x1b0,
+	.tpg_vc3_dt_2_cfg_0 = 0x1b4,
+	.tpg_vc3_dt_2_cfg_1 = 0x1b8,
+	.tpg_vc3_dt_2_cfg_2 = 0x1bc,
+	.tpg_vc3_dt_3_cfg_0 = 0x1c0,
+	.tpg_vc3_dt_3_cfg_1 = 0x1c4,
+	.tpg_vc3_dt_3_cfg_2 = 0x1c8,
+	.tpg_vc3_throttle = 0x1cc,
+	.tpg_vc3_color_bar_cfa_color0 = 0x1d0,
+	.tpg_vc3_color_bar_cfa_color1 = 0x1d4,
+	.tpg_vc3_color_bar_cfa_color2 = 0x1d8,
+	.tpg_vc3_color_bar_cfa_color3 = 0x1dc,
+	.top_irq_status = 0x1e0,
+	.top_irq_mask = 0x1e4,
+	.top_irq_clear = 0x1e8,
+	.top_irq_set = 0x1ec,
+	.irq_cmd = 0x1f0,
+	.tpg_ctrl_cmd = 0x1f4,
+	.test_bus_ctrl = 0x1f8,
+	.spare = 0x1fc,
+
+	/* Register fields below */
+	.gen_shift = 0x1c,
+	.rev_shift = 0x10,
+	.step_shift = 0x0,
+	.violation_shift = 0x0,
+	.auto_load_pattern_shift = 0x15,
+	.auto_load_en_shift = 0x14,
+	.addr_shift = 0x0,
+	.lut_sel_shift = 0x0,
+	.data_shift = 0x0,
+	.auto_load_status_clr_shift = 0x1,
+	.auto_load_cmd_shift = 0x0,
+	.auto_load_done_shift = 0x0,
+	.bank_sel_shift = 0x0,
+	.gain_shift = 0x0,
+	.num_active_vc_shift = 0x1e,
+	.overlap_shdr_en_shift = 0xa,
+	.vc_dt_pattern_id_shift = 0x6,
+	.num_active_lanes_shift = 0x4,
+	.phy_sel_shift = 0x3,
+	.num_frames_shift = 0x10,
+	.num_batch_shift = 0xc,
+	.num_active_dt_shift = 0x8,
+	.fe_dis_shift = 0x7,
+	.fs_dis_shift = 0x6,
+	.vc_num_shift = 0x0,
+	.seed_shift = 0x0,
+	.hbi_clk_cnt_shift = 0x0,
+	.vbi_line_cnt_shift = 0x0,
+	.size_y_shift = 0x1c,
+	.size_x_shift = 0x18,
+	.xcfa_en_shift = 0x10,
+	.rotate_period_shift = 0x8,
+	.pix_intl_hdr_mode_shift = 0x6,
+	.noise_en_shift = 0x5,
+	.split_en_shift = 0x4,
+	.qcfa_en_shift = 0x3,
+	.pix_pattern_shift = 0x0,
+	.frame_width_shift = 0x10,
+	.frame_height_shift = 0x0,
+	.crc_xor_mask_shift = 0x10,
+	.ecc_xor_mask_shift = 0x8,
+	.nfi_ssm_mode_en_shift = 0x7,
+	.data_type_shift = 0x0,
+	.encode_format_shift = 0x1c,
+	.user_specified_payload_shift = 0x4,
+	.payload_mode_shift = 0x0,
+	.pattern_shift = 0x0,
+	.array15_shift = 0x1e,
+	.array14_shift = 0x1c,
+	.array13_shift = 0x1a,
+	.array12_shift = 0x18,
+	.array11_shift = 0x16,
+	.array10_shift = 0x14,
+	.array9_shift = 0x12,
+	.array8_shift = 0x10,
+	.array7_shift = 0xe,
+	.array6_shift = 0xc,
+	.array5_shift = 0xa,
+	.array4_shift = 0x8,
+	.array3_shift = 0x6,
+	.array2_shift = 0x4,
+	.array1_shift = 0x2,
+	.array0_shift = 0x0,
+	.array31_shift = 0x1e,
+	.array30_shift = 0x1c,
+	.array29_shift = 0x1a,
+	.array28_shift = 0x18,
+	.array27_shift = 0x16,
+	.array26_shift = 0x14,
+	.array25_shift = 0x12,
+	.array24_shift = 0x10,
+	.array23_shift = 0xe,
+	.array22_shift = 0xc,
+	.array21_shift = 0xa,
+	.array20_shift = 0x8,
+	.array19_shift = 0x6,
+	.array18_shift = 0x4,
+	.array17_shift = 0x2,
+	.array16_shift = 0x0,
+	.array47_shift = 0x1e,
+	.array46_shift = 0x1c,
+	.array45_shift = 0x1a,
+	.array44_shift = 0x18,
+	.array43_shift = 0x16,
+	.array42_shift = 0x14,
+	.array41_shift = 0x12,
+	.array40_shift = 0x10,
+	.array39_shift = 0xe,
+	.array38_shift = 0xc,
+	.array37_shift = 0xa,
+	.array36_shift = 0x8,
+	.array35_shift = 0x6,
+	.array34_shift = 0x4,
+	.array33_shift = 0x2,
+	.array32_shift = 0x0,
+	.array63_shift = 0x1e,
+	.array62_shift = 0x1c,
+	.array61_shift = 0x1a,
+	.array60_shift = 0x18,
+	.array59_shift = 0x16,
+	.array58_shift = 0x14,
+	.array57_shift = 0x12,
+	.array56_shift = 0x10,
+	.array55_shift = 0xe,
+	.array54_shift = 0xc,
+	.array53_shift = 0xa,
+	.array52_shift = 0x8,
+	.array51_shift = 0x6,
+	.array50_shift = 0x4,
+	.array49_shift = 0x2,
+	.array48_shift = 0x0,
+	.shdr_offset_num_batch_shift = 0x10,
+	.shdr_line_offset1_shift = 0x10,
+	.shdr_line_offset0_shift = 0x0,
+	.status_vec_shift = 0x0,
+	.mask_vec_shift = 0x0,
+	.clear_vec_shift = 0x0,
+	.set_vec_shift = 0x0,
+	.set_shift = 0x4,
+	.clear_shift = 0x0,
+	.test_en_cmd_shift = 0x4,
+	.hw_reset_shift = 0x0,
+	.test_bus_en_shift = 0x0,
+	.test_bus_sel_shift = 0x4,
+	.spare_shift = 0x0,
+
+	/* Custome Variables below */
+};
+
+#endif /* __TPG_HW_V_1_4_0_H__ */

+ 36 - 0
drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_v_1_4/tpg_hw_v_1_4_data.h

@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef __TPG_HW_V_1_4_DATA_H__
+#define __TPG_HW_V_1_4_DATA_H__
+
+#include "../tpg_hw.h"
+#include "tpg_hw_v_1_4.h"
+#include "tpg_hw_v_1_4_0.h"
+
+struct tpg_hw_ops tpg_hw_v_1_4_ops = {
+	.start = tpg_hw_v_1_4_start,
+	.stop  = tpg_hw_v_1_4_stop,
+	.init  = tpg_hw_v_1_4_init,
+	.process_cmd = tpg_hw_v_1_4_process_cmd,
+	.dump_status = tpg_hw_v_1_4_dump_status,
+};
+
+struct tpg_hw_info tpg_v_1_4_hw_info = {
+	.version = TPG_HW_VERSION_1_4,
+	.max_vc_channels = 4,
+	.max_dt_channels_per_vc = 4,
+	.ops = &tpg_hw_v_1_4_ops,
+	.hw_data = &cam_tpg104_reg,
+	.layer_init = &tpg_1_4_layer_init,
+	.xcfa_debug = 0,
+	.shdr_overlap = 0,
+	.shdr_offset_num_batch = 0,
+	.shdr_line_offset0 = 0x6c,
+	.shdr_line_offset1 = 0x6c,
+};
+
+#endif