diff --git a/Kbuild b/Kbuild index 5e78ceffe7..848ed7ea98 100644 --- a/Kbuild +++ b/Kbuild @@ -231,6 +231,7 @@ camera-$(CONFIG_SPECTRA_SENSOR) += \ drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.o \ drivers/cam_sensor_module/cam_sensor_io/cam_sensor_cci_i2c.o \ drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.o \ + drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i3c.o \ drivers/cam_sensor_module/cam_sensor_io/cam_sensor_spi.o \ drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.o \ drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.o \ diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h index dffbc14cec..444fcb017e 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ @@ -86,6 +87,7 @@ struct actuator_intf_params { * @cci_i2c_master: I2C structure * @io_master_info: Information about the communication master * @actuator_mutex: Actuator mutex + * @is_i3c_device : A Flag to indicate whether this actuator is I3C device * @act_apply_state: Actuator settings aRegulator config * @id: Cell Index * @res_apply_state: Actuator settings apply state @@ -106,6 +108,7 @@ struct cam_actuator_ctrl_t { struct camera_io_master io_master_info; struct cam_hw_soc_info soc_info; struct mutex actuator_mutex; + bool is_i3c_device; uint32_t id; enum cam_actuator_apply_state_t setting_apply_state; enum cam_actuator_state cam_act_state; diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c index 08872a2267..8104f597d3 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -34,6 +35,14 @@ int32_t cam_actuator_parse_dt(struct cam_actuator_ctrl_t *a_ctrl, of_node = soc_info->dev->of_node; + rc = of_property_read_bool(of_node, "i3c-target"); + if (rc) { + a_ctrl->is_i3c_device = true; + a_ctrl->io_master_info.master_type = I3C_MASTER; + } + + CAM_DBG(CAM_SENSOR, "I3C Target: %s", CAM_BOOL_TO_YESNO(a_ctrl->is_i3c_device)); + if (a_ctrl->io_master_info.master_type == CCI_MASTER) { rc = of_property_read_u32(of_node, "cci-master", &(a_ctrl->cci_i2c_master)); diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h index 005b9c0325..a64b52df6d 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _CAM_EEPROM_DEV_H_ #define _CAM_EEPROM_DEV_H_ @@ -164,6 +165,7 @@ struct eebin_info { * @gpio_num_info : gpio info * @cci_i2c_master : I2C structure * @v4l2_dev_str : V4L2 device structure + * @is_i3c_device : A flag to indicate whether this eeprom is I3C device * @bridge_intf : bridge interface params * @cam_eeprom_state : eeprom_device_state * @userspace_probe : flag indicates userspace or kernel probe @@ -184,6 +186,7 @@ struct cam_eeprom_ctrl_t { enum cci_i2c_master_t cci_i2c_master; enum cci_device_num cci_num; struct cam_subdev v4l2_dev_str; + bool is_i3c_device; struct cam_eeprom_intf_params bridge_intf; enum msm_camera_device_type_t eeprom_device_type; enum cam_eeprom_state cam_eeprom_state; diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_soc.c b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_soc.c index 016a4d8b08..fcad1eb261 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_soc.c +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_soc.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -304,6 +305,14 @@ int cam_eeprom_parse_dt(struct cam_eeprom_ctrl_t *e_ctrl) of_node = soc_info->dev->of_node; + rc = of_property_read_bool(of_node, "i3c-target"); + if (rc) { + e_ctrl->is_i3c_device = true; + e_ctrl->io_master_info.master_type = I3C_MASTER; + } + + CAM_DBG(CAM_SENSOR, "I3C Target: %s", CAM_BOOL_TO_YESNO(e_ctrl->is_i3c_device)); + if (of_property_read_bool(of_node, "multimodule-support")) { CAM_DBG(CAM_UTIL, "Multi Module is Supported"); e_ctrl->is_multimodule_mode = true; diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h index c9dfc09931..90b81f954f 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _CAM_OIS_DEV_H_ #define _CAM_OIS_DEV_H_ @@ -93,6 +94,7 @@ struct cam_ois_intf_params { * @io_master_info : Information about the communication master * @cci_i2c_master : I2C structure * @v4l2_dev_str : V4L2 device structure + * @is_i3c_device : A Flag to indicate whether this OIS is I3C Device or not. * @bridge_intf : bridge interface params * @i2c_fwinit_data : ois i2c firmware init settings * @i2c_init_data : ois i2c init settings @@ -116,6 +118,7 @@ struct cam_ois_ctrl_t { enum cci_i2c_master_t cci_i2c_master; enum cci_device_num cci_num; struct cam_subdev v4l2_dev_str; + bool is_i3c_device; struct cam_ois_intf_params bridge_intf; struct i2c_settings_array i2c_fwinit_data; struct i2c_settings_array i2c_init_data; diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_soc.c b/drivers/cam_sensor_module/cam_ois/cam_ois_soc.c index 9560c08e40..0a37283d3b 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_soc.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_soc.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -41,6 +42,14 @@ static int cam_ois_get_dt_data(struct cam_ois_ctrl_t *o_ctrl) return rc; } + rc = of_property_read_bool(of_node, "i3c-target"); + if (rc) { + o_ctrl->is_i3c_device = true; + o_ctrl->io_master_info.master_type = I3C_MASTER; + } + + CAM_DBG(CAM_SENSOR, "I3C Target: %s", CAM_BOOL_TO_YESNO(o_ctrl->is_i3c_device)); + /* Initialize regulators to default parameters */ for (i = 0; i < soc_info->num_rgltr; i++) { soc_info->rgltr[i] = devm_regulator_get(soc_info->dev, @@ -126,7 +135,6 @@ int cam_ois_driver_soc_init(struct cam_ois_ctrl_t *o_ctrl) o_ctrl->io_master_info.cci_client->cci_device = o_ctrl->cci_num; CAM_DBG(CAM_OIS, "cci-device %d", o_ctrl->cci_num, rc); - } rc = cam_ois_get_dt_data(o_ctrl); diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index e7f49a7fe9..6776c42366 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -13,6 +13,7 @@ #include "cam_common_util.h" #include "cam_packet_util.h" +extern struct completion *cam_sensor_get_i3c_completion(uint32_t index); static int cam_sensor_update_req_mgr( struct cam_sensor_ctrl_t *s_ctrl, @@ -790,7 +791,9 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, struct cam_sensor_power_ctrl_t *power_info = &s_ctrl->sensordata->power_info; struct timespec64 ts; + struct completion *i3c_probe_completion; uint64_t ms, sec, min, hrs; + long time_left; if (!s_ctrl || !arg) { CAM_ERR(CAM_SENSOR, "s_ctrl is NULL"); @@ -879,6 +882,21 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, goto free_power_settings; } } + + if (s_ctrl->io_master_info.master_type == I3C_MASTER) { + i3c_probe_completion = + cam_sensor_get_i3c_completion(s_ctrl->soc_info.index); + + time_left = cam_common_wait_for_completion_timeout( + i3c_probe_completion, + msecs_to_jiffies(CAM_SENSOR_I3C_PROBE_TIMEOUT_MS)); + if (!time_left) { + CAM_ERR(CAM_SENSOR, "Wait for I3C probe timedout for %s", + s_ctrl->sensor_name); + return -ETIMEDOUT; + } + } + /* Match sensor ID */ rc = cam_sensor_match_id(s_ctrl); if (rc < 0) { diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c index 8e1946f01c..1e8bd6edab 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c @@ -9,6 +9,17 @@ #include "cam_sensor_soc.h" #include "cam_sensor_core.h" #include "camera_main.h" +#include "cam_compat.h" + +static struct cam_sensor_i3c_sensor_data { + struct cam_sensor_ctrl_t *s_ctrl; + struct completion probe_complete; +} g_i3c_sensor_data[MAX_CAMERAS]; + +struct completion *cam_sensor_get_i3c_completion(uint32_t index) +{ + return &g_i3c_sensor_data[index].probe_complete; +} static int cam_sensor_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) @@ -136,21 +147,14 @@ static int cam_sensor_init_subdev_params(struct cam_sensor_ctrl_t *s_ctrl) { int rc = 0; - s_ctrl->v4l2_dev_str.internal_ops = - &cam_sensor_internal_ops; - s_ctrl->v4l2_dev_str.ops = - &cam_sensor_subdev_ops; - strlcpy(s_ctrl->device_name, CAMX_SENSOR_DEV_NAME, - sizeof(s_ctrl->device_name)); - s_ctrl->v4l2_dev_str.name = - s_ctrl->device_name; - s_ctrl->v4l2_dev_str.sd_flags = - (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS); - s_ctrl->v4l2_dev_str.ent_function = - CAM_SENSOR_DEVICE_TYPE; + s_ctrl->v4l2_dev_str.internal_ops = &cam_sensor_internal_ops; + s_ctrl->v4l2_dev_str.ops = &cam_sensor_subdev_ops; + strscpy(s_ctrl->device_name, CAMX_SENSOR_DEV_NAME, CAM_CTX_DEV_NAME_MAX_LENGTH); + s_ctrl->v4l2_dev_str.name = s_ctrl->device_name; + s_ctrl->v4l2_dev_str.sd_flags = (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS); + s_ctrl->v4l2_dev_str.ent_function = CAM_SENSOR_DEVICE_TYPE; s_ctrl->v4l2_dev_str.token = s_ctrl; - s_ctrl->v4l2_dev_str.close_seq_prior = - CAM_SD_CLOSE_MEDIUM_LOW_PRIORITY; + s_ctrl->v4l2_dev_str.close_seq_prior = CAM_SD_CLOSE_MEDIUM_LOW_PRIORITY; rc = cam_register_subdev(&(s_ctrl->v4l2_dev_str)); if (rc) @@ -159,6 +163,45 @@ static int cam_sensor_init_subdev_params(struct cam_sensor_ctrl_t *s_ctrl) return rc; } +static int cam_sensor_i3c_driver_probe(struct i3c_device *client) +{ + int32_t rc = 0; + struct cam_sensor_ctrl_t *s_ctrl = NULL; + uint32_t index; + struct device *dev; + + dev = i3cdev_to_dev(client); + + CAM_DBG(CAM_SENSOR, "Probe for I3C Slave %s", dev_name(dev)); + + rc = of_property_read_u32(dev->of_node, "cell-index", &index); + if (rc) { + CAM_ERR(CAM_UTIL, "device %s failed to read cell-index", dev_name(dev)); + return rc; + } + + if (index >= MAX_CAMERAS) { + CAM_ERR(CAM_SENSOR, "Invalid Cell-Index: %u for %s", index, dev_name(dev)); + return -EINVAL; + } + + s_ctrl = g_i3c_sensor_data[index].s_ctrl; + if (!s_ctrl) { + CAM_ERR(CAM_SENSOR, "S_ctrl is null. I3C Probe before platfom driver probe for %s", + dev_name(dev)); + return -EINVAL; + } + + i3cdev_set_drvdata(client, s_ctrl); + + s_ctrl->io_master_info.i3c_client = client; + + complete_all(&g_i3c_sensor_data[index].probe_complete); + + CAM_DBG(CAM_SENSOR, "I3C Probe Finished for %s", dev_name(dev)); + return rc; +} + static int cam_sensor_i2c_component_bind(struct device *dev, struct device *master_dev, void *data) { @@ -358,6 +401,8 @@ static int cam_sensor_component_bind(struct device *dev, goto free_s_ctrl; } + CAM_DBG(CAM_SENSOR, "Master Type: %u", s_ctrl->io_master_info.master_type); + /* Fill platform device id*/ pdev->id = soc_info->index; @@ -406,7 +451,10 @@ static int cam_sensor_component_bind(struct device *dev, s_ctrl->sensordata->power_info.dev = &pdev->dev; platform_set_drvdata(pdev, s_ctrl); s_ctrl->sensor_state = CAM_SENSOR_INIT; - CAM_DBG(CAM_SENSOR, "Component bound successfully"); + CAM_DBG(CAM_SENSOR, "Component bound successfully for %s", pdev->name); + + g_i3c_sensor_data[soc_info->index].s_ctrl = s_ctrl; + init_completion(&g_i3c_sensor_data[soc_info->index].probe_complete); return rc; @@ -464,13 +512,14 @@ static const struct of_device_id cam_sensor_driver_dt_match[] = { {.compatible = "qcom,cam-sensor"}, {} }; +MODULE_DEVICE_TABLE(of, cam_sensor_driver_dt_match); static int32_t cam_sensor_driver_platform_probe( struct platform_device *pdev) { int rc = 0; - CAM_DBG(CAM_SENSOR, "Adding Sensor component"); + CAM_DBG(CAM_SENSOR, "Adding Sensor component for %s", pdev->name); rc = component_add(&pdev->dev, &cam_sensor_component_ops); if (rc) CAM_ERR(CAM_SENSOR, "failed to add component rc: %d", rc); @@ -478,8 +527,6 @@ static int32_t cam_sensor_driver_platform_probe( return rc; } -MODULE_DEVICE_TABLE(of, cam_sensor_driver_dt_match); - struct platform_driver cam_sensor_platform_driver = { .probe = cam_sensor_driver_platform_probe, .driver = { @@ -495,7 +542,6 @@ static const struct of_device_id cam_sensor_i2c_driver_dt_match[] = { {.compatible = "qcom,cam-i2c-sensor"}, {} }; - MODULE_DEVICE_TABLE(of, cam_sensor_i2c_driver_dt_match); static const struct i2c_device_id i2c_id[] = { @@ -515,20 +561,110 @@ struct i2c_driver cam_sensor_i2c_driver = { }, }; +static struct i3c_device_id sensor_i3c_id[MAX_I3C_DEVICE_ID_ENTRIES + 1]; + +static struct i3c_driver cam_sensor_i3c_driver = { + .id_table = sensor_i3c_id, + .probe = cam_sensor_i3c_driver_probe, + .remove = cam_sensor_i3c_driver_remove, + .driver = { + .owner = THIS_MODULE, + .name = SENSOR_DRIVER_I3C, + .of_match_table = cam_sensor_driver_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int cam_sensor_fill_i3c_device_id(void) +{ + struct device_node *dev; + int num_entries; + int i = 0; + uint8_t ent_num = 0; + uint32_t mid; + uint32_t pid; + int rc; + + dev = of_find_node_by_path(I3C_SENSOR_DEV_ID_DT_PATH); + if (!dev) { + CAM_WARN(CAM_SENSOR, "Couldnt Find the i3c-id-table dev node"); + return 0; + } + + num_entries = of_property_count_u32_elems(dev, "i3c-sensor-id-table"); + if (num_entries <= 0) { + CAM_WARN(CAM_SENSOR, "Failed while reading the property. num_entries:%d", + num_entries); + return 0; + } + + while (i < num_entries) { + if (ent_num >= MAX_I3C_DEVICE_ID_ENTRIES) { + CAM_WARN(CAM_SENSOR, "Num_entries are more than MAX_I3C_DEVICE_ID_ENTRIES"); + return -ENOMEM; + } + + rc = of_property_read_u32_index(dev, "i3c-sensor-id-table", i, &mid); + if (rc) { + CAM_ERR(CAM_SENSOR, "Failed in reading the MID. rc: %d", rc); + return rc; + } + i++; + + rc = of_property_read_u32_index(dev, "i3c-sensor-id-table", i, &pid); + if (rc) { + CAM_ERR(CAM_SENSOR, "Failed in reading the PID. rc: %d", rc); + return rc; + } + i++; + + CAM_DBG(CAM_SENSOR, "PID: 0x%x, MID: 0x%x", pid, mid); + + sensor_i3c_id[ent_num].manuf_id = mid; + sensor_i3c_id[ent_num].match_flags = I3C_MATCH_MANUF_AND_PART; + sensor_i3c_id[ent_num].part_id = pid; + sensor_i3c_id[ent_num].data = 0; + + ent_num++; + } + + return 0; +} + int cam_sensor_driver_init(void) { - int32_t rc = 0; + int rc; rc = platform_driver_register(&cam_sensor_platform_driver); if (rc < 0) { - CAM_ERR(CAM_SENSOR, "platform_driver_register Failed: rc = %d", - rc); + CAM_ERR(CAM_SENSOR, "platform_driver_register Failed: rc = %d", rc); return rc; } rc = i2c_add_driver(&cam_sensor_i2c_driver); - if (rc) + if (rc) { CAM_ERR(CAM_SENSOR, "i2c_add_driver failed rc = %d", rc); + goto i2c_register_err; + } + + memset(sensor_i3c_id, 0, sizeof(struct i3c_device_id) * (MAX_I3C_DEVICE_ID_ENTRIES + 1)); + + rc = cam_sensor_fill_i3c_device_id(); + if (rc) + goto i3c_register_err; + + rc = i3c_driver_register_with_owner(&cam_sensor_i3c_driver, THIS_MODULE); + if (rc) { + CAM_ERR(CAM_SENSOR, "i3c_driver registration failed, rc: %d", rc); + goto i3c_register_err; + } + + return 0; + +i3c_register_err: + i2c_del_driver(&cam_sensor_i2c_driver); +i2c_register_err: + platform_driver_unregister(&cam_sensor_platform_driver); return rc; } @@ -537,6 +673,7 @@ void cam_sensor_driver_exit(void) { platform_driver_unregister(&cam_sensor_platform_driver); i2c_del_driver(&cam_sensor_i2c_driver); + i3c_driver_unregister(&cam_sensor_i3c_driver); } MODULE_DESCRIPTION("cam_sensor_driver"); diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h index 5473f53872..98f2893d5c 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h @@ -28,16 +28,9 @@ #define NUM_MASTERS 2 #define NUM_QUEUES 2 - -#undef CDBG -#ifdef CAM_SENSOR_DEBUG -#define CDBG(fmt, args...) pr_err(fmt, ##args) -#else -#define CDBG(fmt, args...) pr_debug(fmt, ##args) -#endif - -#define SENSOR_DRIVER_I2C "cam-i2c-sensor" -#define CAMX_SENSOR_DEV_NAME "cam-sensor-driver" +#define SENSOR_DRIVER_I2C "cam-i2c-sensor" +#define CAMX_SENSOR_DEV_NAME "cam-sensor-driver" +#define SENSOR_DRIVER_I3C "i3c_camera_sensor" enum cam_sensor_state_t { CAM_SENSOR_INIT, @@ -73,6 +66,7 @@ struct sensor_intf_params { * @sensor_state: Sensor states * @is_probe_succeed: Probe succeeded or not * @id: Cell Index + * @is_i3c_device: A Flag to indicate whether this sensor is an I3C Device. * @of_node: Of node ptr * @v4l2_dev_str: V4L2 device structure * @sensor_probe_addr_type: Sensor probe address type @@ -90,8 +84,7 @@ struct sensor_intf_params { * @aon_camera_id: AON Camera ID associated with this sensor */ struct cam_sensor_ctrl_t { - char device_name[ - CAM_CTX_DEV_NAME_MAX_LENGTH]; + char device_name[CAM_CTX_DEV_NAME_MAX_LENGTH]; struct platform_device *pdev; struct cam_hw_soc_info soc_info; struct mutex cam_sensor_mutex; @@ -102,6 +95,7 @@ struct cam_sensor_ctrl_t { enum cam_sensor_state_t sensor_state; uint8_t is_probe_succeed; uint32_t id; + bool is_i3c_device; struct device_node *of_node; struct cam_subdev v4l2_dev_str; uint8_t sensor_probe_addr_type; diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_soc.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_soc.c index 73e574f4e8..05ca0c6015 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_soc.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_soc.c @@ -110,14 +110,19 @@ static int32_t cam_sensor_init_bus_params(struct cam_sensor_ctrl_t *s_ctrl) if (s_ctrl->io_master_info.master_type == CCI_MASTER) { s_ctrl->io_master_info.cci_client = kzalloc(sizeof( struct cam_sensor_cci_client), GFP_KERNEL); - if (!(s_ctrl->io_master_info.cci_client)) + if (!(s_ctrl->io_master_info.cci_client)) { + CAM_ERR(CAM_SENSOR, "Memory allocation failed"); return -ENOMEM; + } } else if (s_ctrl->io_master_info.master_type == I2C_MASTER) { if (!(s_ctrl->io_master_info.client)) return -EINVAL; + } else if (s_ctrl->io_master_info.master_type == I3C_MASTER) { + CAM_DBG(CAM_SENSOR, "I3C Master Type"); } else { CAM_ERR(CAM_SENSOR, - "Invalid master / Master type Not supported"); + "Invalid master / Master type Not supported : %d", + s_ctrl->io_master_info.master_type); return -EINVAL; } @@ -161,6 +166,13 @@ static int32_t cam_sensor_driver_get_dt_data(struct cam_sensor_ctrl_t *s_ctrl) goto FREE_SENSOR_DATA; } + rc = of_property_read_bool(of_node, "i3c-target"); + if (rc) { + CAM_INFO(CAM_SENSOR, "I3C Target"); + s_ctrl->is_i3c_device = true; + s_ctrl->io_master_info.master_type = I3C_MASTER; + } + /* Store the index of BoB regulator if it is available */ for (i = 0; i < soc_info->num_rgltr; i++) { if (!strcmp(soc_info->rgltr_name[i], diff --git a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i3c.h b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i3c.h new file mode 100644 index 0000000000..16b063bc8a --- /dev/null +++ b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i3c.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef _CAM_SENSOR_I3C_H_ +#define _CAM_SENSOR_I3C_H_ + +#include +#include +#include +#include "cam_sensor_io.h" + +/** + * cam_qup_i3c_read : This API handles QUP I3C read operations + * @client : QUP IeC client structure + * @data : I3C data + * @addr_type : I3C address type + * @data_type : I3C data type + */ + +int cam_qup_i3c_read(struct i3c_device *client, + uint32_t addr, uint32_t *data, + enum camera_sensor_i2c_type addr_type, + enum camera_sensor_i2c_type data_type); + +/** + * cam_qup_i3c_read_seq : This API handles QUP I3C Sequential read operations + * @client : QUP I3C client structure + * @data : I3C data + * @addr_type : I3C address type + * @num_bytes : Number of bytes to read + */ + +int cam_qup_i3c_read_seq(struct i3c_device *client, + uint32_t addr, uint8_t *data, + enum camera_sensor_i2c_type addr_type, + uint32_t num_byte); + +/** + * cam_qup_i3c_poll : This API handles QUP based I3C poll operation + * @client : QUP I3C client structure + * @addr : I3C address + * @data : I3C data + * @data_mask : I3C data mask + * @data_type : I3C data type + * @addr_type : I3C addr type + * @delay_ms : Delay in milli seconds + */ + +int cam_qup_i3c_poll(struct i3c_device *client, + uint32_t addr, uint16_t data, uint16_t data_mask, + enum camera_sensor_i2c_type addr_type, + enum camera_sensor_i2c_type data_type, + uint32_t delay_ms); + +/** + * cam_qup_i3c_write_table : This API Handles QUP based I3C write random operations + * @client : QUP I3C client structure + * @write_setting : I3C register settings + */ + +int cam_qup_i3c_write_table( + struct camera_io_master *client, + struct cam_sensor_i2c_reg_setting *write_setting); + +/** + * cam_qup_i3c_write_continuous_write: This API Handles QUP based I3C write continuous(Burst/Seq) + * @client: QUP I3C client structure + * @write_setting: I3C register setting + * @cam_sensor_i3c_write_flag: burst or seq write + */ +int cam_qup_i3c_write_continuous_table( + struct camera_io_master *client, + struct cam_sensor_i2c_reg_setting *write_setting, + uint8_t cam_sensor_i3c_write_flag); + +#endif /*_CAM_SENSOR_I3C_H_*/ diff --git a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.c b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.c index 8e03dd3007..9aba7dc3e6 100644 --- a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.c +++ b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.c @@ -6,6 +6,7 @@ #include "cam_sensor_io.h" #include "cam_sensor_i2c.h" +#include "cam_sensor_i3c.h" int32_t camera_io_dev_poll(struct camera_io_master *io_master_info, uint32_t addr, uint16_t data, uint32_t data_mask, @@ -20,48 +21,49 @@ int32_t camera_io_dev_poll(struct camera_io_master *io_master_info, return -EINVAL; } - if (io_master_info->master_type == CCI_MASTER) { + switch (io_master_info->master_type) { + case CCI_MASTER: return cam_cci_i2c_poll(io_master_info->cci_client, addr, data, mask, data_type, addr_type, delay_ms); - } else if (io_master_info->master_type == I2C_MASTER) { + case I2C_MASTER: return cam_qup_i2c_poll(io_master_info->client, - addr, data, data_mask, addr_type, data_type, - delay_ms); - } else { - CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d", - io_master_info->master_type); - return -EINVAL; + addr, data, data_mask, addr_type, data_type, delay_ms); + case I3C_MASTER: + return cam_qup_i3c_poll(io_master_info->i3c_client, + addr, data, data_mask, addr_type, data_type, delay_ms); + default: + CAM_ERR(CAM_SENSOR, "Invalid Master Type: %d", io_master_info->master_type); } + + return -EINVAL; } int32_t camera_io_dev_erase(struct camera_io_master *io_master_info, uint32_t addr, uint32_t size) { - int rc = 0; - if (!io_master_info) { CAM_ERR(CAM_SENSOR, "Invalid Args"); return -EINVAL; } if (size == 0) - return rc; + return 0; - if (io_master_info->master_type == SPI_MASTER) { + switch (io_master_info->master_type) { + case SPI_MASTER: CAM_DBG(CAM_SENSOR, "Calling SPI Erase"); - return cam_spi_erase(io_master_info, addr, - CAMERA_SENSOR_I2C_TYPE_WORD, size); - } else if (io_master_info->master_type == I2C_MASTER || - io_master_info->master_type == CCI_MASTER) { - CAM_ERR(CAM_SENSOR, "Erase not supported on master :%d", + return cam_spi_erase(io_master_info, addr, CAMERA_SENSOR_I2C_TYPE_WORD, size); + case I2C_MASTER: + case CCI_MASTER: + case I3C_MASTER: + CAM_ERR(CAM_SENSOR, "Erase not supported on Master Type: %d", io_master_info->master_type); - rc = -EINVAL; - } else { - CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d", - io_master_info->master_type); - rc = -EINVAL; + return -EINVAL; + default: + CAM_ERR(CAM_SENSOR, "Invalid Master Type: %d", io_master_info->master_type); } - return rc; + + return -EINVAL; } int32_t camera_io_dev_read(struct camera_io_master *io_master_info, @@ -75,21 +77,23 @@ int32_t camera_io_dev_read(struct camera_io_master *io_master_info, return -EINVAL; } - if (io_master_info->master_type == CCI_MASTER) { - return cam_cci_i2c_read(io_master_info->cci_client, - addr, data, addr_type, data_type, is_probing); - } else if (io_master_info->master_type == I2C_MASTER) { + switch (io_master_info->master_type) { + case SPI_MASTER: + return cam_spi_read(io_master_info, addr, data, addr_type, data_type); + case I2C_MASTER: return cam_qup_i2c_read(io_master_info->client, addr, data, addr_type, data_type); - } else if (io_master_info->master_type == SPI_MASTER) { - return cam_spi_read(io_master_info, + case CCI_MASTER: + return cam_cci_i2c_read(io_master_info->cci_client, + addr, data, addr_type, data_type, is_probing); + case I3C_MASTER: + return cam_qup_i3c_read(io_master_info->i3c_client, addr, data, addr_type, data_type); - } else { - CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d", - io_master_info->master_type); - return -EINVAL; + default: + CAM_ERR(CAM_SENSOR, "Invalid Master Type: %d", io_master_info->master_type); } - return 0; + + return -EINVAL; } int32_t camera_io_dev_read_seq(struct camera_io_master *io_master_info, @@ -97,24 +101,23 @@ int32_t camera_io_dev_read_seq(struct camera_io_master *io_master_info, enum camera_sensor_i2c_type addr_type, enum camera_sensor_i2c_type data_type, int32_t num_bytes) { - if (io_master_info->master_type == CCI_MASTER) { + switch (io_master_info->master_type) { + case CCI_MASTER: return cam_camera_cci_i2c_read_seq(io_master_info->cci_client, addr, data, addr_type, data_type, num_bytes); - } else if (io_master_info->master_type == I2C_MASTER) { + case I2C_MASTER: return cam_qup_i2c_read_seq(io_master_info->client, addr, data, addr_type, num_bytes); - } else if (io_master_info->master_type == SPI_MASTER) { - return cam_spi_read_seq(io_master_info, + case SPI_MASTER: + return cam_spi_read_seq(io_master_info, addr, data, addr_type, num_bytes); + case I3C_MASTER: + return cam_qup_i3c_read_seq(io_master_info->i3c_client, addr, data, addr_type, num_bytes); - } else if (io_master_info->master_type == SPI_MASTER) { - return cam_spi_write_seq(io_master_info, - addr, data, addr_type, num_bytes); - } else { - CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d", - io_master_info->master_type); - return -EINVAL; + default: + CAM_ERR(CAM_SENSOR, "Invalid Master Type: %d", io_master_info->master_type); } - return 0; + + return -EINVAL; } int32_t camera_io_dev_write(struct camera_io_master *io_master_info, @@ -132,20 +135,20 @@ int32_t camera_io_dev_write(struct camera_io_master *io_master_info, return -EINVAL; } - if (io_master_info->master_type == CCI_MASTER) { - return cam_cci_i2c_write_table(io_master_info, - write_setting); - } else if (io_master_info->master_type == I2C_MASTER) { - return cam_qup_i2c_write_table(io_master_info, - write_setting); - } else if (io_master_info->master_type == SPI_MASTER) { - return cam_spi_write_table(io_master_info, - write_setting); - } else { - CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d", - io_master_info->master_type); - return -EINVAL; + switch (io_master_info->master_type) { + case CCI_MASTER: + return cam_cci_i2c_write_table(io_master_info, write_setting); + case I2C_MASTER: + return cam_qup_i2c_write_table(io_master_info, write_setting); + case SPI_MASTER: + return cam_spi_write_table(io_master_info, write_setting); + case I3C_MASTER: + return cam_qup_i3c_write_table(io_master_info, write_setting); + default: + CAM_ERR(CAM_SENSOR, "Invalid Master Type:%d", io_master_info->master_type); } + + return -EINVAL; } int32_t camera_io_dev_write_continuous(struct camera_io_master *io_master_info, @@ -164,20 +167,23 @@ int32_t camera_io_dev_write_continuous(struct camera_io_master *io_master_info, return -EINVAL; } - if (io_master_info->master_type == CCI_MASTER) { + switch (io_master_info->master_type) { + case CCI_MASTER: return cam_cci_i2c_write_continuous_table(io_master_info, write_setting, cam_sensor_i2c_write_flag); - } else if (io_master_info->master_type == I2C_MASTER) { + case I2C_MASTER: return cam_qup_i2c_write_continuous_table(io_master_info, write_setting, cam_sensor_i2c_write_flag); - } else if (io_master_info->master_type == SPI_MASTER) { - return cam_spi_write_table(io_master_info, - write_setting); - } else { - CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d", - io_master_info->master_type); - return -EINVAL; + case SPI_MASTER: + return cam_spi_write_table(io_master_info, write_setting); + case I3C_MASTER: + return cam_qup_i3c_write_continuous_table(io_master_info, + write_setting, cam_sensor_i2c_write_flag); + default: + CAM_ERR(CAM_SENSOR, "Invalid Master Type:%d", io_master_info->master_type); } + + return -EINVAL; } int32_t camera_io_init(struct camera_io_master *io_master_info) @@ -187,14 +193,16 @@ int32_t camera_io_init(struct camera_io_master *io_master_info) return -EINVAL; } - if (io_master_info->master_type == CCI_MASTER) { - io_master_info->cci_client->cci_subdev = - cam_cci_get_subdev(io_master_info->cci_client->cci_device); - return cam_sensor_cci_i2c_util(io_master_info->cci_client, - MSM_CCI_INIT); - } else if ((io_master_info->master_type == I2C_MASTER) || - (io_master_info->master_type == SPI_MASTER)) { - return 0; + switch (io_master_info->master_type) { + case CCI_MASTER: + io_master_info->cci_client->cci_subdev = cam_cci_get_subdev( + io_master_info->cci_client->cci_device); + return cam_sensor_cci_i2c_util(io_master_info->cci_client, MSM_CCI_INIT); + case I2C_MASTER: + case SPI_MASTER: + case I3C_MASTER: return 0; + default: + CAM_ERR(CAM_SENSOR, "Invalid Master Type:%d", io_master_info->master_type); } return -EINVAL; @@ -207,12 +215,14 @@ int32_t camera_io_release(struct camera_io_master *io_master_info) return -EINVAL; } - if (io_master_info->master_type == CCI_MASTER) { - return cam_sensor_cci_i2c_util(io_master_info->cci_client, - MSM_CCI_RELEASE); - } else if ((io_master_info->master_type == I2C_MASTER) || - (io_master_info->master_type == SPI_MASTER)) { - return 0; + switch (io_master_info->master_type) { + case CCI_MASTER: + return cam_sensor_cci_i2c_util(io_master_info->cci_client, MSM_CCI_RELEASE); + case I2C_MASTER: + case SPI_MASTER: + case I3C_MASTER: return 0; + default: + CAM_ERR(CAM_SENSOR, "Invalid Master Type:%d", io_master_info->master_type); } return -EINVAL; diff --git a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.h b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.h index 13467b8f2c..ab7b6159ec 100644 --- a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.h +++ b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.h @@ -8,22 +8,25 @@ #define _CAM_SENSOR_IO_H_ #include - #include "cam_sensor_cmn_header.h" -#define CCI_MASTER 1 -#define I2C_MASTER 2 -#define SPI_MASTER 3 +/* Master Types */ +#define CCI_MASTER 1 +#define I2C_MASTER 2 +#define SPI_MASTER 3 +#define I3C_MASTER 4 /** * @master_type: CCI master type - * @client: I2C client information structure + * @i2c_client: I2C client information structure + * @i3c_client: I3C client information structure * @cci_client: CCI client information structure * @spi_client: SPI client information structure */ struct camera_io_master { int master_type; struct i2c_client *client; + struct i3c_device *i3c_client; struct cam_sensor_cci_client *cci_client; struct cam_sensor_spi_client *spi_client; }; @@ -116,4 +119,6 @@ int32_t camera_io_dev_poll(struct camera_io_master *io_master_info, #include "cam_sensor_i2c.h" #include "cam_sensor_spi.h" +#include "cam_sensor_i3c.h" + #endif /* _CAM_SENSOR_IO_H_ */ diff --git a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i3c.c b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i3c.c new file mode 100644 index 0000000000..6c31fdc106 --- /dev/null +++ b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i3c.c @@ -0,0 +1,517 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include "cam_sensor_i3c.h" +#include "cam_sensor_io.h" + +#define I3C_REG_MAX_BUF_SIZE 8 + +static int cam_qup_i3c_rxdata(struct i3c_device *dev_client, unsigned char *rxdata, + enum camera_sensor_i2c_type addr_type, int data_length) +{ + int rc; + struct i3c_priv_xfer read_buf[2] = { + { + .rnw = 0, + .len = addr_type, + .data.out = rxdata, + }, + { + .rnw = 1, + .len = data_length, + .data.in = rxdata, + }, + }; + + rc = i3c_device_do_priv_xfers(dev_client, read_buf, ARRAY_SIZE(read_buf)); + if (rc) + CAM_ERR(CAM_SENSOR, "Failed with i3c_read: rc = %d", rc); + + return rc; +} + + +static int cam_qup_i3c_txdata(struct camera_io_master *dev_client, unsigned char *txdata, + int length) +{ + int rc; + struct i3c_priv_xfer write_buf = { + .rnw = 0, + .len = length, + .data.out = txdata, + }; + + rc = i3c_device_do_priv_xfers(dev_client->i3c_client, &write_buf, 1); + if (rc) + CAM_ERR(CAM_SENSOR, "Failed with i3c_write: rc = %d", rc); + + return rc; +} + +int cam_qup_i3c_read(struct i3c_device *client, uint32_t addr, uint32_t *data, + enum camera_sensor_i2c_type addr_type, + enum camera_sensor_i2c_type data_type) +{ + int rc; + unsigned char *buf; + + if ((addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID) + || (addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) + || (data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID) + || (data_type >= CAMERA_SENSOR_I2C_TYPE_MAX)) { + CAM_ERR(CAM_SENSOR, "Failed with addr/data_type verfication"); + return -EINVAL; + } + + buf = kzalloc(addr_type + data_type, GFP_DMA | GFP_KERNEL); + if (!buf) + return -ENOMEM; + + if (addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE) { + buf[0] = addr; + } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_WORD) { + buf[0] = addr >> 8; + buf[1] = addr; + } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_3B) { + buf[0] = addr >> 16; + buf[1] = addr >> 8; + buf[2] = addr; + } else { + buf[0] = addr >> 24; + buf[1] = addr >> 16; + buf[2] = addr >> 8; + buf[3] = addr; + } + + rc = cam_qup_i3c_rxdata(client, buf, addr_type, data_type); + if (rc) { + CAM_ERR(CAM_SENSOR, "failed rc: %d", rc); + goto read_fail; + } + + if (data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) + *data = buf[0]; + else if (data_type == CAMERA_SENSOR_I2C_TYPE_WORD) + *data = (buf[0] << 8) | buf[1]; + else if (data_type == CAMERA_SENSOR_I2C_TYPE_3B) + *data = (buf[0] << 16) | (buf[1] << 8) | buf[2]; + else + *data = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; + + CAM_DBG(CAM_SENSOR, "addr = 0x%x data: 0x%x", addr, *data); +read_fail: + kfree(buf); + return rc; +} + +int cam_qup_i3c_read_seq(struct i3c_device *client, + uint32_t addr, uint8_t *data, + enum camera_sensor_i2c_type addr_type, + uint32_t num_byte) +{ + int rc; + unsigned char *buf; + int i; + + if (addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID + || addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) { + CAM_ERR(CAM_SENSOR, "Failed with addr_type verification"); + return -EFAULT; + } + + if ((num_byte == 0) || (num_byte > I2C_REG_DATA_MAX)) { + CAM_ERR(CAM_SENSOR, "num_byte:0x%x max supported:0x%x", + num_byte, I2C_REG_DATA_MAX); + return -EFAULT; + } + + buf = kzalloc(addr_type + num_byte, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + if (addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE) { + buf[0] = addr; + } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_WORD) { + buf[0] = addr >> BITS_PER_BYTE; + buf[1] = addr; + } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_3B) { + buf[0] = addr >> 16; + buf[1] = addr >> 8; + buf[2] = addr; + } else { + buf[0] = addr >> 24; + buf[1] = addr >> 16; + buf[2] = addr >> 8; + buf[3] = addr; + } + + rc = cam_qup_i3c_rxdata(client, buf, addr_type, num_byte); + if (rc) { + CAM_ERR(CAM_SENSOR, "failed rc: %d", rc); + goto read_seq_fail; + } + + for (i = 0; i < num_byte; i++) + data[i] = buf[i]; + +read_seq_fail: + kfree(buf); + return rc; +} + +static int cam_qup_i3c_compare(struct i3c_device *client, + uint32_t addr, uint32_t data, uint16_t data_mask, + enum camera_sensor_i2c_type data_type, + enum camera_sensor_i2c_type addr_type) +{ + int rc; + uint32_t reg_data; + + rc = cam_qup_i3c_read(client, addr, ®_data, + addr_type, data_type); + if (rc < 0) + return rc; + + reg_data = reg_data & 0xFFFF; + if (data != (reg_data & ~data_mask)) + return I2C_COMPARE_MISMATCH; + + return I2C_COMPARE_MATCH; +} + +int cam_qup_i3c_poll(struct i3c_device *client, + uint32_t addr, uint16_t data, uint16_t data_mask, + enum camera_sensor_i2c_type addr_type, + enum camera_sensor_i2c_type data_type, + uint32_t delay_ms) +{ + int rc; + int i; + + if ((delay_ms > MAX_POLL_DELAY_MS) || (delay_ms == 0)) { + CAM_ERR(CAM_SENSOR, "invalid delay = %d max_delay = %d", + delay_ms, MAX_POLL_DELAY_MS); + return -EINVAL; + } + + if ((addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID + || addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX + || data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID + || data_type >= CAMERA_SENSOR_I2C_TYPE_MAX)) + return -EINVAL; + + for (i = 0; i < delay_ms; i++) { + rc = cam_qup_i3c_compare(client, + addr, data, data_mask, data_type, addr_type); + if (rc == I2C_COMPARE_MATCH) + return rc; + + usleep_range(1000, 1010); + } + /* If rc is MISMATCH then read is successful but poll is failure */ + if (rc == I2C_COMPARE_MISMATCH) + CAM_ERR(CAM_SENSOR, "poll failed rc=%d(non-fatal)", rc); + if (rc < 0) + CAM_ERR(CAM_SENSOR, "poll failed rc=%d", rc); + + return rc; +} + +static int cam_qup_i3c_write(struct camera_io_master *client, + struct cam_sensor_i2c_reg_array *reg_setting, + enum camera_sensor_i2c_type addr_type, + enum camera_sensor_i2c_type data_type) +{ + int rc; + unsigned char *buf = NULL; + uint8_t len = 0; + + buf = kzalloc(I3C_REG_MAX_BUF_SIZE, GFP_KERNEL | GFP_DMA); + if (!buf) { + CAM_ERR(CAM_SENSOR, "Buffer memory allocation failed"); + return -ENOMEM; + } + + CAM_DBG(CAM_SENSOR, "reg addr = 0x%x data type: %d", + reg_setting->reg_addr, data_type); + if (addr_type == CAMERA_SENSOR_I2C_TYPE_INVALID) { + buf[0] = reg_setting->reg_addr; + CAM_DBG(CAM_SENSOR, "byte %d: 0x%x", len, buf[len]); + len = 1; + } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_WORD) { + buf[0] = reg_setting->reg_addr >> 8; + buf[1] = reg_setting->reg_addr; + CAM_DBG(CAM_SENSOR, "byte %d: 0x%x", len, buf[len]); + CAM_DBG(CAM_SENSOR, "byte %d: 0x%x", len+1, buf[len+1]); + len = 2; + } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_3B) { + buf[0] = reg_setting->reg_addr >> 16; + buf[1] = reg_setting->reg_addr >> 8; + buf[2] = reg_setting->reg_addr; + len = 3; + } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_DWORD) { + buf[0] = reg_setting->reg_addr >> 24; + buf[1] = reg_setting->reg_addr >> 16; + buf[2] = reg_setting->reg_addr >> 8; + buf[3] = reg_setting->reg_addr; + len = 4; + } else { + CAM_ERR(CAM_SENSOR, "Invalid I2C addr type"); + rc = -EINVAL; + goto deallocate_buffer; + } + + CAM_DBG(CAM_SENSOR, "Data: 0x%x", reg_setting->reg_data); + if (data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) { + buf[len] = reg_setting->reg_data; + CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len, buf[len]); + len += 1; + } else if (data_type == CAMERA_SENSOR_I2C_TYPE_WORD) { + buf[len] = reg_setting->reg_data >> 8; + buf[len+1] = reg_setting->reg_data; + CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len, buf[len]); + CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len+1, buf[len+1]); + len += 2; + } else if (data_type == CAMERA_SENSOR_I2C_TYPE_3B) { + buf[len] = reg_setting->reg_data >> 16; + buf[len + 1] = reg_setting->reg_data >> 8; + buf[len + 2] = reg_setting->reg_data; + CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len, buf[len]); + CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len+1, buf[len+1]); + CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len+2, buf[len+2]); + len += 3; + } else if (data_type == CAMERA_SENSOR_I2C_TYPE_DWORD) { + buf[len] = reg_setting->reg_data >> 24; + buf[len + 1] = reg_setting->reg_data >> 16; + buf[len + 2] = reg_setting->reg_data >> 8; + buf[len + 3] = reg_setting->reg_data; + CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len, buf[len]); + CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len+1, buf[len+1]); + CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len+2, buf[len+2]); + CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len+3, buf[len+3]); + len += 4; + } else { + CAM_ERR(CAM_SENSOR, "Invalid Data Type"); + rc = -EINVAL; + goto deallocate_buffer; + } + + rc = cam_qup_i3c_txdata(client, buf, len); + if (rc) + CAM_ERR(CAM_SENSOR, "failed rc: %d", rc); + +deallocate_buffer: + kfree(buf); + return rc; +} + +int cam_qup_i3c_write_table(struct camera_io_master *client, + struct cam_sensor_i2c_reg_setting *write_setting) +{ + int i; + int rc = -EINVAL; + struct cam_sensor_i2c_reg_array *reg_setting; + + if (!client || !write_setting) + return -EINVAL; + + if ((write_setting->addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID + || write_setting->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX + || (write_setting->data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID + || write_setting->data_type >= CAMERA_SENSOR_I2C_TYPE_MAX))) + return -EINVAL; + + reg_setting = write_setting->reg_setting; + + for (i = 0; i < write_setting->size; i++) { + CAM_DBG(CAM_SENSOR, "addr 0x%x data 0x%x", + reg_setting->reg_addr, reg_setting->reg_data); + + rc = cam_qup_i3c_write(client, reg_setting, + write_setting->addr_type, write_setting->data_type); + if (rc < 0) + break; + reg_setting++; + } + + if (write_setting->delay > 20) + msleep(write_setting->delay); + else if (write_setting->delay) + usleep_range(write_setting->delay * 1000, (write_setting->delay + * 1000) + 1000); + + return rc; +} + +static int cam_qup_i3c_write_seq(struct camera_io_master *client, + struct cam_sensor_i2c_reg_setting *write_setting) +{ + int i; + int rc = 0; + struct cam_sensor_i2c_reg_array *reg_setting; + + reg_setting = write_setting->reg_setting; + + for (i = 0; i < write_setting->size; i++) { + reg_setting->reg_addr += i; + rc = cam_qup_i3c_write(client, reg_setting, + write_setting->addr_type, write_setting->data_type); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Sequential i2c write failed: rc: %d", rc); + break; + } + reg_setting++; + } + + if (write_setting->delay > 20) + msleep(write_setting->delay); + else if (write_setting->delay) + usleep_range(write_setting->delay * 1000, (write_setting->delay + * 1000) + 1000); + + return rc; +} + +static int cam_qup_i3c_write_burst(struct camera_io_master *client, + struct cam_sensor_i2c_reg_setting *write_setting) +{ + int i; + int rc; + uint32_t len = 0; + unsigned char *buf; + struct cam_sensor_i2c_reg_array *reg_setting; + enum camera_sensor_i2c_type addr_type; + enum camera_sensor_i2c_type data_type; + + buf = kzalloc((write_setting->addr_type + + (write_setting->size * write_setting->data_type)), + GFP_DMA | GFP_KERNEL); + + if (!buf) { + CAM_ERR(CAM_SENSOR, "BUF is NULL"); + return -ENOMEM; + } + + reg_setting = write_setting->reg_setting; + addr_type = write_setting->addr_type; + data_type = write_setting->data_type; + + CAM_DBG(CAM_SENSOR, "reg addr = 0x%x data type: %d", + reg_setting->reg_addr, data_type); + if (addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE) { + buf[0] = reg_setting->reg_addr; + CAM_DBG(CAM_SENSOR, "byte %d: 0x%x", len, buf[len]); + len = 1; + } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_WORD) { + buf[0] = reg_setting->reg_addr >> 8; + buf[1] = reg_setting->reg_addr; + CAM_DBG(CAM_SENSOR, "byte %d: 0x%x", len, buf[len]); + CAM_DBG(CAM_SENSOR, "byte %d: 0x%x", len+1, buf[len+1]); + len = 2; + } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_3B) { + buf[0] = reg_setting->reg_addr >> 16; + buf[1] = reg_setting->reg_addr >> 8; + buf[2] = reg_setting->reg_addr; + len = 3; + } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_DWORD) { + buf[0] = reg_setting->reg_addr >> 24; + buf[1] = reg_setting->reg_addr >> 16; + buf[2] = reg_setting->reg_addr >> 8; + buf[3] = reg_setting->reg_addr; + len = 4; + } else { + CAM_ERR(CAM_SENSOR, "Invalid I2C addr type"); + rc = -EINVAL; + goto free_res; + } + + for (i = 0; i < write_setting->size; i++) { + if (data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) { + buf[len] = reg_setting->reg_data; + CAM_DBG(CAM_SENSOR, + "Byte %d: 0x%x", len, buf[len]); + len += 1; + } else if (data_type == CAMERA_SENSOR_I2C_TYPE_WORD) { + buf[len] = reg_setting->reg_data >> 8; + buf[len+1] = reg_setting->reg_data; + CAM_DBG(CAM_SENSOR, + "Byte %d: 0x%x", len, buf[len]); + CAM_DBG(CAM_SENSOR, + "Byte %d: 0x%x", len+1, buf[len+1]); + len += 2; + } else if (data_type == CAMERA_SENSOR_I2C_TYPE_3B) { + buf[len] = reg_setting->reg_data >> 16; + buf[len + 1] = reg_setting->reg_data >> 8; + buf[len + 2] = reg_setting->reg_data; + CAM_DBG(CAM_SENSOR, + "Byte %d: 0x%x", len, buf[len]); + CAM_DBG(CAM_SENSOR, + "Byte %d: 0x%x", len+1, buf[len+1]); + CAM_DBG(CAM_SENSOR, + "Byte %d: 0x%x", len+2, buf[len+2]); + len += 3; + } else if (data_type == CAMERA_SENSOR_I2C_TYPE_DWORD) { + buf[len] = reg_setting->reg_data >> 24; + buf[len + 1] = reg_setting->reg_data >> 16; + buf[len + 2] = reg_setting->reg_data >> 8; + buf[len + 3] = reg_setting->reg_data; + CAM_DBG(CAM_SENSOR, + "Byte %d: 0x%x", len, buf[len]); + CAM_DBG(CAM_SENSOR, + "Byte %d: 0x%x", len+1, buf[len+1]); + CAM_DBG(CAM_SENSOR, + "Byte %d: 0x%x", len+2, buf[len+2]); + CAM_DBG(CAM_SENSOR, + "Byte %d: 0x%x", len+3, buf[len+3]); + len += 4; + } else { + CAM_ERR(CAM_SENSOR, "Invalid Data Type"); + rc = -EINVAL; + goto free_res; + } + reg_setting++; + } + + if (len > (write_setting->addr_type + + (write_setting->size * write_setting->data_type))) { + CAM_ERR(CAM_SENSOR, "Invalid Length: %u | Expected length: %u", + len, (write_setting->addr_type + + (write_setting->size * write_setting->data_type))); + rc = -EINVAL; + goto free_res; + } + + rc = cam_qup_i3c_txdata(client, buf, len); + if (rc < 0) + CAM_ERR(CAM_SENSOR, "failed rc: %d", rc); + +free_res: + kfree(buf); + return rc; +} + +int cam_qup_i3c_write_continuous_table(struct camera_io_master *client, + struct cam_sensor_i2c_reg_setting *write_settings, + uint8_t cam_sensor_i2c_write_flag) +{ + int rc = 0; + + if (!client || !write_settings) + return -EINVAL; + + if ((write_settings->addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID + || write_settings->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX + || (write_settings->data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID + || write_settings->data_type >= CAMERA_SENSOR_I2C_TYPE_MAX))) + return -EINVAL; + + if (cam_sensor_i2c_write_flag == CAM_SENSOR_I2C_WRITE_BURST) + rc = cam_qup_i3c_write_burst(client, write_settings); + else if (cam_sensor_i2c_write_flag == CAM_SENSOR_I2C_WRITE_SEQ) + rc = cam_qup_i3c_write_seq(client, write_settings); + + return rc; +} diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h index 9e4759d22e..9e4b8125e4 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h @@ -8,6 +8,7 @@ #define _CAM_SENSOR_CMN_HEADER_ #include +#include #include #include #include @@ -19,10 +20,12 @@ #include #include -#define MAX_POWER_CONFIG 12 - -#define MAX_PER_FRAME_ARRAY 32 -#define BATCH_SIZE_MAX 16 +#define MAX_POWER_CONFIG 12 +#define MAX_PER_FRAME_ARRAY 32 +#define BATCH_SIZE_MAX 16 +#define CAM_SENSOR_I3C_PROBE_TIMEOUT_MS 10 +#define I3C_SENSOR_DEV_ID_DT_PATH "/soc/qcom,cam-i3c-id-table" +#define MAX_I3C_DEVICE_ID_ENTRIES MAX_CAMERAS #define CAM_SENSOR_NAME "cam-sensor" #define CAM_ACTUATOR_NAME "cam-actuator" diff --git a/drivers/cam_utils/cam_compat.c b/drivers/cam_utils/cam_compat.c index 0a00baf016..f0d383c060 100644 --- a/drivers/cam_utils/cam_compat.c +++ b/drivers/cam_utils/cam_compat.c @@ -364,6 +364,12 @@ void cam_compat_util_put_dmabuf_va(struct dma_buf *dmabuf, void *vaddr) dma_buf_vunmap(dmabuf, &mapping); } + +void cam_sensor_i3c_driver_remove(struct i3c_device *client) +{ + CAM_DBG(CAM_SENSOR, "I3C remove invoked for %s", dev_name(i3cdev_to_dev(client))); +} + #else void cam_smmu_util_iommu_custom(struct device *dev, dma_addr_t discard_start, size_t discard_length) @@ -402,4 +408,10 @@ void cam_compat_util_put_dmabuf_va(struct dma_buf *dmabuf, void *vaddr) { dma_buf_vunmap(dmabuf, vaddr); } + +int cam_sensor_i3c_driver_remove(struct i3c_device *client) +{ + CAM_DBG(CAM_SENSOR, "I3C remove invoked for %s", dev_name(i3cdev_to_dev(client))); + return 0; +} #endif diff --git a/drivers/cam_utils/cam_compat.h b/drivers/cam_utils/cam_compat.h index c07f935531..9285cbf55d 100644 --- a/drivers/cam_utils/cam_compat.h +++ b/drivers/cam_utils/cam_compat.h @@ -58,9 +58,11 @@ void cam_smmu_util_iommu_custom(struct device *dev, #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) int cam_req_mgr_ordered_list_cmp(void *priv, const struct list_head *head_1, const struct list_head *head_2); +void cam_sensor_i3c_driver_remove(struct i3c_device *client); #else int cam_req_mgr_ordered_list_cmp(void *priv, struct list_head *head_1, struct list_head *head_2); +int cam_sensor_i3c_driver_remove(struct i3c_device *client); #endif #endif /* _CAM_COMPAT_H_ */