diff --git a/Kbuild b/Kbuild index e88f995a87..a143c8f331 100644 --- a/Kbuild +++ b/Kbuild @@ -230,6 +230,7 @@ camera-$(CONFIG_SPECTRA_SENSOR) += \ drivers/cam_sensor_module/cam_tpg/cam_tpg_dev.o \ 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_common.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 \ diff --git a/drivers/cam_sensor_module/cam_tpg/cam_tpg_core.c b/drivers/cam_sensor_module/cam_tpg/cam_tpg_core.c index f8a8f45837..9f03b38b2b 100644 --- a/drivers/cam_sensor_module/cam_tpg/cam_tpg_core.c +++ b/drivers/cam_sensor_module/cam_tpg/cam_tpg_core.c @@ -426,6 +426,19 @@ static int cam_tpg_validate_cmd_descriptor( *cmd_type = TPG_CMD_TYPE_ILLUMINATION_CONFIG; break; } + case TPG_CMD_TYPE_SETTINGS_CONFIG: { + if (cmd_header->size != sizeof(struct tpg_settings_config_t)) { + CAM_ERR(CAM_TPG, "Got invalid settings config command recv: %d exp: %d", + cmd_header->size, + sizeof(struct tpg_settings_config_t)); + rc = -EINVAL; + goto end; + } + CAM_INFO(CAM_TPG, "Got settings config command"); + *cmd_type = TPG_CMD_TYPE_SETTINGS_CONFIG; + break; + } + default: rc = -EINVAL; CAM_ERR(CAM_TPG, "invalid config command"); @@ -486,6 +499,13 @@ static int cam_tpg_cmd_buf_parse( } break; } + case TPG_CMD_TYPE_SETTINGS_CONFIG: { + CAM_DBG(CAM_TPG, "TPG[%d] Got TPG Settings Config", + tpg_dev->soc_info.index); + rc = tpg_hw_copy_settings_config(&tpg_dev->tpg_hw, + (struct tpg_settings_config_t *)cmd_addr); + break; + } case TPG_CMD_TYPE_ILLUMINATION_CONFIG: CAM_ERR(CAM_TPG, "TPG[%d] ILLUMINATION CONFIG not supported now ", tpg_dev->soc_info.index); diff --git a/drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw.c b/drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw.c index 847e0cb46d..d734cf8920 100644 --- a/drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw.c +++ b/drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw.c @@ -501,9 +501,17 @@ int tpg_hw_dump_status(struct tpg_hw *hw) int tpg_hw_start(struct tpg_hw *hw) { int rc = 0; + struct tpg_reg_settings *reg_settings = NULL; + struct tpg_settings_config_t *config = NULL; + uint32_t settings_count = 0; if (!hw || !hw->hw_info || !hw->hw_info->ops) return -EINVAL; + + reg_settings = hw->register_settings; + config = &hw->settings_config; + settings_count = config->active_count; + mutex_lock(&hw->mutex); switch (hw->hw_info->version) { case TPG_HW_VERSION_1_0: @@ -517,10 +525,15 @@ int tpg_hw_start(struct tpg_hw *hw) case TPG_HW_VERSION_1_4: if (hw->hw_info->ops->start) hw->hw_info->ops->start(hw, NULL); - if (hw->stream_version == 1) - tpg_hw_start_default_new(hw); - else if (hw->stream_version == 3) - tpg_hw_start_default_new_v3(hw); + if (settings_count != 0) { + hw->hw_info->ops->write_settings(hw, config, + reg_settings); + } else { + if (hw->stream_version == 1) + tpg_hw_start_default_new(hw); + else if (hw->stream_version == 3) + tpg_hw_start_default_new_v3(hw); + } cam_tpg_mem_dmp(hw->soc_info); break; default: @@ -833,6 +846,41 @@ int tpg_hw_copy_global_config( return 0; } +int tpg_hw_copy_settings_config( + struct tpg_hw *hw, + struct tpg_settings_config_t *settings) +{ + struct tpg_reg_settings *reg_settings; + + if (!hw || !settings) { + CAM_ERR(CAM_TPG, "invalid parameter"); + return -EINVAL; + } + + hw->register_settings = + kzalloc(sizeof(struct tpg_reg_settings) * + settings->settings_array_size, GFP_KERNEL); + + if (hw->register_settings == NULL) { + CAM_ERR(CAM_TPG, "unable to allocate memory"); + return -EINVAL; + } + + reg_settings = (struct tpg_reg_settings *) + ((uint8_t *)settings + settings->settings_array_offset); + + mutex_lock(&hw->mutex); + memcpy(&hw->settings_config, + settings, + sizeof(struct tpg_settings_config_t)); + memcpy(hw->register_settings, + reg_settings, + sizeof(struct tpg_reg_settings) * settings->settings_array_size); + mutex_unlock(&hw->mutex); + + return 0; +} + static int assign_vc_slot( struct tpg_hw *hw, int vc, diff --git a/drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw.h b/drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw.h index 4166dcb30c..5e3aaf6c0a 100644 --- a/drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw.h +++ b/drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw.h @@ -32,6 +32,7 @@ struct tpg_hw; * @write : tpg hw write register * @process_cmd : tpg hw process command * @dump_status : dump any status registers + * @write_settings : write register settings */ struct tpg_hw_ops { int (*init)(struct tpg_hw *hw, void *data); @@ -42,6 +43,8 @@ struct tpg_hw_ops { int (*write)(struct tpg_hw *hw, uint32_t *addr, uint32_t *val); int (*process_cmd)(struct tpg_hw *hw, uint32_t cmd, void *arg); int (*dump_status)(struct tpg_hw *hw, void *data); + int (*write_settings)(struct tpg_hw *hw, + struct tpg_settings_config_t *config, struct tpg_reg_settings *settings); }; /** @@ -146,6 +149,8 @@ struct tpg_hw { struct mutex mutex; struct tpg_vc_slot_info *vc_slots; struct tpg_global_config_t global_config; + struct tpg_settings_config_t settings_config; + struct tpg_reg_settings *register_settings; }; /** @@ -416,4 +421,14 @@ int tpg_hw_add_stream_v3(struct tpg_hw *hw, struct tpg_stream_config_v3_t *cmd); */ int tpg_hw_copy_global_config(struct tpg_hw *hw, struct tpg_global_config_t *global); +/** + * @brief : copy settings config command + * + * @param hw: tpg hw instance + * @param settings: settings config command + * + * @return : 0 on success + */ +int tpg_hw_copy_settings_config(struct tpg_hw *hw, struct tpg_settings_config_t *settings); + #endif diff --git a/drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_common.c b/drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_common.c new file mode 100644 index 0000000000..f04fa2f48e --- /dev/null +++ b/drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_common.c @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include "tpg_hw_common.h" + +int tpg_hw_write_settings(struct tpg_hw *hw, + struct tpg_settings_config_t *config, struct tpg_reg_settings *settings) +{ + struct cam_hw_soc_info *soc_info = NULL; + int setting_index; + + if (!hw || !config || !settings) { + CAM_ERR(CAM_TPG, "invalid params"); + return -EINVAL; + } + + soc_info = hw->soc_info; + for (setting_index = 0; setting_index < config->active_count; setting_index++) { + cam_io_w_mb(settings->reg_value, soc_info->reg_map[0].mem_base + + settings->reg_offset); + settings++; + } + + return 0; +} diff --git a/drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_common.h b/drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_common.h new file mode 100644 index 0000000000..52313d79b4 --- /dev/null +++ b/drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_common.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __TPG_HW_COMMON_H__ +#define __TPG_HW_COMMON_H__ + +#include +#include "cam_debug_util.h" +#include "cam_soc_util.h" +#include +#include +#include "tpg_hw.h" + +/** + * @brief write register settings + * + * @param hw : tpg hw instance + * @param config : argument for settings config + * @param settings : argument for register settings + * + * @return : 0 on sucdess + */ +int tpg_hw_write_settings(struct tpg_hw *hw, + struct tpg_settings_config_t *config, struct tpg_reg_settings *settings); + +#endif diff --git a/drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_v_1_3/tpg_hw_v_1_3_data.h b/drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_v_1_3/tpg_hw_v_1_3_data.h index ea72def2cc..19cf7dd83a 100644 --- a/drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_v_1_3/tpg_hw_v_1_3_data.h +++ b/drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_v_1_3/tpg_hw_v_1_3_data.h @@ -8,6 +8,7 @@ #define __TPG_HW_V_1_3_DATA_H__ #include "../tpg_hw.h" +#include "../tpg_hw_common.h" #include "tpg_hw_v_1_3.h" #include "tpg_hw_v_1_3_0.h" #include "tpg_hw_v_1_3_1.h" @@ -18,6 +19,7 @@ struct tpg_hw_ops tpg_hw_v_1_3_ops = { .init = tpg_hw_v_1_3_init, .process_cmd = tpg_hw_v_1_3_process_cmd, .dump_status = tpg_hw_v_1_3_dump_status, + .write_settings = tpg_hw_write_settings, }; struct tpg_hw_info tpg_v_1_3_hw_info = { diff --git a/drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_v_1_4/tpg_hw_v_1_4_data.h b/drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_v_1_4/tpg_hw_v_1_4_data.h index 869d9fe333..057b4806a9 100644 --- a/drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_v_1_4/tpg_hw_v_1_4_data.h +++ b/drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_v_1_4/tpg_hw_v_1_4_data.h @@ -8,6 +8,7 @@ #define __TPG_HW_V_1_4_DATA_H__ #include "../tpg_hw.h" +#include "../tpg_hw_common.h" #include "tpg_hw_v_1_4.h" #include "tpg_hw_v_1_4_0.h" @@ -17,6 +18,7 @@ struct tpg_hw_ops tpg_hw_v_1_4_ops = { .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, + .write_settings = tpg_hw_write_settings, }; struct tpg_hw_info tpg_v_1_4_hw_info = { diff --git a/include/uapi/camera/media/cam_sensor.h b/include/uapi/camera/media/cam_sensor.h index ed3b9465c5..100f0ac16a 100644 --- a/include/uapi/camera/media/cam_sensor.h +++ b/include/uapi/camera/media/cam_sensor.h @@ -135,6 +135,7 @@ enum tpg_command_type_t { TPG_CMD_TYPE_GLOBAL_CONFIG, TPG_CMD_TYPE_STREAM_CONFIG, TPG_CMD_TYPE_ILLUMINATION_CONFIG, + TPG_CMD_TYPE_SETTINGS_CONFIG, TPG_CMD_TYPE_MAX, }; @@ -879,6 +880,41 @@ struct tpg_cfa_information_t { struct tpg_pixel_coordinate_t pixel_coordinate[64]; } __attribute__((packed)); +/** + * tpg_reg_settings : TPG register settings + * + * @reg_offset : register offset + * @reg_value : register value + * @operation : operation + * @delay_us : delay in micro second + */ +struct tpg_reg_settings { + uint32_t reg_offset; + uint32_t reg_value; + uint32_t operation; + uint32_t delay_us; + uint32_t reserved[4]; +} __attribute__((packed)); + +/** + * tpg_settings_config_t : settings configuration command structure + * + * @header : common header + * @settings_array_offset : settings array offset + * @settings_array_size : settings array size + * @active_count : active count + * @param_mask : Mask to indicate fields in params + * @params : Additional Params + */ +struct tpg_settings_config_t { + struct tpg_command_header_t header; + uint32_t settings_array_offset; + uint32_t settings_array_size; + uint32_t active_count; + uint32_t param_mask; + uint32_t params[4]; +} __attribute__((packed)); + /** * tpg_global_config_t : global configuration command structure *