msm: camera: common: Add I3C Driver support

Add I3C driver Support for eeprom, actuator
and OIS modules.

CRs-Fixed: 3204977
Change-Id: Ic96d1edc787efcf3069935fc53fc799e786a95a7
Signed-off-by: Jigar Agrawal <quic_jigar@quicinc.com>
This commit is contained in:
Jigar Agrawal
2022-05-12 15:32:55 -07:00
committed by Camera Software Integration
parent 8f297a31ea
commit 57c67da8f3
21 changed files with 552 additions and 79 deletions

View File

@@ -54,10 +54,10 @@ free_power_settings:
static int32_t cam_actuator_power_up(struct cam_actuator_ctrl_t *a_ctrl)
{
int rc = 0;
struct cam_hw_soc_info *soc_info =
&a_ctrl->soc_info;
struct cam_hw_soc_info *soc_info = &a_ctrl->soc_info;
struct cam_actuator_soc_private *soc_private;
struct cam_sensor_power_ctrl_t *power_info;
struct completion *i3c_probe_completion = NULL;
soc_private =
(struct cam_actuator_soc_private *)a_ctrl->soc_info.soc_private;
@@ -99,7 +99,10 @@ static int32_t cam_actuator_power_up(struct cam_actuator_ctrl_t *a_ctrl)
power_info->dev = soc_info->dev;
rc = cam_sensor_core_power_up(power_info, soc_info);
if (a_ctrl->io_master_info.master_type == I3C_MASTER)
i3c_probe_completion = cam_actuator_get_i3c_completion(a_ctrl->soc_info.index);
rc = cam_sensor_core_power_up(power_info, soc_info, i3c_probe_completion);
if (rc) {
CAM_ERR(CAM_ACTUATOR,
"failed in actuator power up rc %d", rc);

View File

@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef _CAM_ACTUATOR_CORE_H_
@@ -63,4 +64,6 @@ int32_t cam_actuator_driver_cmd(struct cam_actuator_ctrl_t *a_ctrl, void *arg);
*/
void cam_actuator_shutdown(struct cam_actuator_ctrl_t *a_ctrl);
struct completion *cam_actuator_get_i3c_completion(uint32_t index);
#endif /* _CAM_ACTUATOR_CORE_H_ */

View File

@@ -10,6 +10,17 @@
#include "cam_actuator_core.h"
#include "cam_trace.h"
#include "camera_main.h"
#include "cam_compat.h"
static struct cam_i3c_actuator_data {
struct cam_actuator_ctrl_t *a_ctrl;
struct completion probe_complete;
} g_i3c_actuator_data[MAX_CAMERAS];
struct completion *cam_actuator_get_i3c_completion(uint32_t index)
{
return &g_i3c_actuator_data[index].probe_complete;
}
static int cam_actuator_subdev_close_internal(struct v4l2_subdev *sd,
struct v4l2_subdev_fh *fh)
@@ -411,6 +422,9 @@ static int cam_actuator_platform_component_bind(struct device *dev,
CAM_DBG(CAM_ACTUATOR, "Component bound successfully %d",
a_ctrl->soc_info.index);
g_i3c_actuator_data[a_ctrl->soc_info.index].a_ctrl = a_ctrl;
init_completion(&g_i3c_actuator_data[a_ctrl->soc_info.index].probe_complete);
return rc;
free_mem:
@@ -525,6 +539,120 @@ struct i2c_driver cam_actuator_i2c_driver = {
},
};
static struct i3c_device_id actuator_i3c_id[MAX_I3C_DEVICE_ID_ENTRIES + 1];
static int cam_actuator_i3c_driver_probe(struct i3c_device *client)
{
int32_t rc = 0;
struct cam_actuator_ctrl_t *a_ctrl = NULL;
uint32_t index;
struct device *dev;
if (!client) {
CAM_INFO(CAM_ACTUATOR, "Null Client pointer");
return -EINVAL;
}
dev = &client->dev;
CAM_DBG(CAM_ACTUATOR, "Probe for I3C Slave %s", dev_name(dev));
rc = of_property_read_u32(dev->of_node, "cell-index", &index);
if (rc) {
CAM_ERR(CAM_ACTUATOR, "device %s failed to read cell-index", dev_name(dev));
return rc;
}
if (index >= MAX_CAMERAS) {
CAM_ERR(CAM_ACTUATOR, "Invalid Cell-Index: %u for %s", index, dev_name(dev));
return -EINVAL;
}
a_ctrl = g_i3c_actuator_data[index].a_ctrl;
if (!a_ctrl) {
CAM_ERR(CAM_ACTUATOR,
"a_ctrl is null. I3C Probe before platfom driver probe for %s",
dev_name(dev));
return -EINVAL;
}
a_ctrl->io_master_info.i3c_client = client;
complete_all(&g_i3c_actuator_data[index].probe_complete);
CAM_DBG(CAM_ACTUATOR, "I3C Probe Finished for %s", dev_name(dev));
return rc;
}
static struct i3c_driver cam_actuator_i3c_driver = {
.id_table = actuator_i3c_id,
.probe = cam_actuator_i3c_driver_probe,
.remove = cam_i3c_driver_remove,
.driver = {
.owner = THIS_MODULE,
.name = ACTUATOR_DRIVER_I3C,
.of_match_table = cam_actuator_driver_dt_match,
.suppress_bind_attrs = true,
},
};
static int cam_actuator_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_ACTUATOR, "Couldnt Find the i3c-id-table dev node");
return 0;
}
num_entries = of_property_count_u32_elems(dev, "i3c-actuator-id-table");
if (num_entries <= 0) {
CAM_WARN(CAM_ACTUATOR, "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_ACTUATOR,
"Num_entries are more than MAX_I3C_DEVICE_ID_ENTRIES");
return -ENOMEM;
}
rc = of_property_read_u32_index(dev, "i3c-actuator-id-table", i, &mid);
if (rc) {
CAM_ERR(CAM_ACTUATOR, "Failed in reading the MID. rc: %d", rc);
return rc;
}
i++;
rc = of_property_read_u32_index(dev, "i3c-actuator-id-table", i, &pid);
if (rc) {
CAM_ERR(CAM_ACTUATOR, "Failed in reading the PID. rc: %d", rc);
return rc;
}
i++;
CAM_DBG(CAM_ACTUATOR, "PID: 0x%x, MID: 0x%x", pid, mid);
actuator_i3c_id[ent_num].manuf_id = mid;
actuator_i3c_id[ent_num].match_flags = I3C_MATCH_MANUF_AND_PART;
actuator_i3c_id[ent_num].part_id = pid;
actuator_i3c_id[ent_num].data = 0;
ent_num++;
}
return 0;
}
int cam_actuator_driver_init(void)
{
int32_t rc = 0;
@@ -535,9 +663,30 @@ int cam_actuator_driver_init(void)
"platform_driver_register failed rc = %d", rc);
return rc;
}
rc = i2c_add_driver(&cam_actuator_i2c_driver);
if (rc)
if (rc) {
CAM_ERR(CAM_ACTUATOR, "i2c_add_driver failed rc = %d", rc);
goto i2c_register_err;
}
memset(actuator_i3c_id, 0, sizeof(struct i3c_device_id) * (MAX_I3C_DEVICE_ID_ENTRIES + 1));
rc = cam_actuator_fill_i3c_device_id();
if (rc)
goto i3c_register_err;
rc = i3c_driver_register_with_owner(&cam_actuator_i3c_driver, THIS_MODULE);
if (rc) {
CAM_ERR(CAM_ACTUATOR, "i3c_driver registration failed, rc: %d", rc);
goto i3c_register_err;
}
return 0;
i3c_register_err:
i2c_del_driver(&cam_actuator_i2c_driver);
i2c_register_err:
platform_driver_unregister(&cam_actuator_platform_driver);
return rc;
}
@@ -546,6 +695,7 @@ void cam_actuator_driver_exit(void)
{
platform_driver_unregister(&cam_actuator_platform_driver);
i2c_del_driver(&cam_actuator_i2c_driver);
i3c_driver_unregister(&cam_actuator_i3c_driver);
}
MODULE_DESCRIPTION("cam_actuator_driver");

View File

@@ -33,6 +33,8 @@
#define ACTUATOR_DRIVER_I2C "cam-i2c-actuator"
#define CAMX_ACTUATOR_DEV_NAME "cam-actuator-driver"
#define ACTUATOR_DRIVER_I3C "i3c_camera_actuator"
#define MSM_ACTUATOR_MAX_VREGS (10)
#define ACTUATOR_MAX_POLL_COUNT 10

View File

@@ -149,8 +149,8 @@ static int cam_eeprom_power_up(struct cam_eeprom_ctrl_t *e_ctrl,
struct cam_sensor_power_ctrl_t *power_info)
{
int32_t rc = 0;
struct cam_hw_soc_info *soc_info =
&e_ctrl->soc_info;
struct cam_hw_soc_info *soc_info = &e_ctrl->soc_info;
struct completion *i3c_probe_completion = NULL;
/* Parse and fill vreg params for power up settings */
rc = msm_camera_fill_vreg_params(
@@ -176,7 +176,10 @@ static int cam_eeprom_power_up(struct cam_eeprom_ctrl_t *e_ctrl,
power_info->dev = soc_info->dev;
rc = cam_sensor_core_power_up(power_info, soc_info);
if (e_ctrl->io_master_info.master_type == I3C_MASTER)
i3c_probe_completion = cam_eeprom_get_i3c_completion(e_ctrl->soc_info.index);
rc = cam_sensor_core_power_up(power_info, soc_info, i3c_probe_completion);
if (rc) {
CAM_ERR(CAM_EEPROM, "failed in eeprom power up rc %d", rc);
return rc;
@@ -189,6 +192,7 @@ static int cam_eeprom_power_up(struct cam_eeprom_ctrl_t *e_ctrl,
goto cci_failure;
}
}
return rc;
cci_failure:
if (cam_sensor_util_power_down(power_info, soc_info))

View File

@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef _CAM_EEPROM_CORE_H_
#define _CAM_EEPROM_CORE_H_
@@ -17,5 +18,7 @@ int32_t cam_eeprom_parse_read_memory_map(struct device_node *of_node,
*/
void cam_eeprom_shutdown(struct cam_eeprom_ctrl_t *e_ctrl);
struct completion *cam_eeprom_get_i3c_completion(uint32_t index);
#endif
/* _CAM_EEPROM_CORE_H_ */

View File

@@ -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 "cam_eeprom_dev.h"
@@ -9,6 +10,17 @@
#include "cam_eeprom_core.h"
#include "cam_debug_util.h"
#include "camera_main.h"
#include "cam_compat.h"
static struct cam_i3c_eeprom_data {
struct cam_eeprom_ctrl_t *e_ctrl;
struct completion probe_complete;
} g_i3c_eeprom_data[MAX_CAMERAS];
struct completion *cam_eeprom_get_i3c_completion(uint32_t index)
{
return &g_i3c_eeprom_data[index].probe_complete;
}
static int cam_eeprom_subdev_close_internal(struct v4l2_subdev *sd,
struct v4l2_subdev_fh *fh)
@@ -546,6 +558,9 @@ static int cam_eeprom_component_bind(struct device *dev,
e_ctrl->cam_eeprom_state = CAM_EEPROM_INIT;
CAM_DBG(CAM_EEPROM, "Component bound successfully");
g_i3c_eeprom_data[e_ctrl->soc_info.index].e_ctrl = e_ctrl;
init_completion(&g_i3c_eeprom_data[e_ctrl->soc_info.index].probe_complete);
return rc;
free_soc:
kfree(soc_private);
@@ -665,6 +680,119 @@ static struct spi_driver cam_eeprom_spi_driver = {
.probe = cam_eeprom_spi_driver_probe,
.remove = cam_eeprom_spi_driver_remove,
};
static struct i3c_device_id eeprom_i3c_id[MAX_I3C_DEVICE_ID_ENTRIES + 1];
static int cam_eeprom_i3c_driver_probe(struct i3c_device *client)
{
int32_t rc = 0;
struct cam_eeprom_ctrl_t *e_ctrl = NULL;
uint32_t index;
struct device *dev;
if (!client) {
CAM_INFO(CAM_EEPROM, "Null Client pointer");
return -EINVAL;
}
dev = &client->dev;
CAM_DBG(CAM_EEPROM, "Probe for I3C Slave %s", dev_name(dev));
rc = of_property_read_u32(dev->of_node, "cell-index", &index);
if (rc) {
CAM_ERR(CAM_EEPROM, "device %s failed to read cell-index", dev_name(dev));
return rc;
}
if (index >= MAX_CAMERAS) {
CAM_ERR(CAM_EEPROM, "Invalid Cell-Index: %u for %s", index, dev_name(dev));
return -EINVAL;
}
e_ctrl = g_i3c_eeprom_data[index].e_ctrl;
if (!e_ctrl) {
CAM_ERR(CAM_EEPROM, "e_ctrl is null. I3C Probe before platfom driver probe for %s",
dev_name(dev));
return -EINVAL;
}
e_ctrl->io_master_info.i3c_client = client;
complete_all(&g_i3c_eeprom_data[index].probe_complete);
CAM_DBG(CAM_EEPROM, "I3C Probe Finished for %s", dev_name(dev));
return rc;
}
static struct i3c_driver cam_eeprom_i3c_driver = {
.id_table = eeprom_i3c_id,
.probe = cam_eeprom_i3c_driver_probe,
.remove = cam_i3c_driver_remove,
.driver = {
.owner = THIS_MODULE,
.name = EEPROM_DRIVER_I3C,
.of_match_table = cam_eeprom_dt_match,
.suppress_bind_attrs = true,
},
};
static int cam_eeprom_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_EEPROM, "Couldnt Find the i3c-id-table dev node");
return 0;
}
num_entries = of_property_count_u32_elems(dev, "i3c-eeprom-id-table");
if (num_entries <= 0) {
CAM_WARN(CAM_EEPROM, "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_EEPROM, "Num_entries are more than MAX_I3C_DEVICE_ID_ENTRIES");
return -ENOMEM;
}
rc = of_property_read_u32_index(dev, "i3c-eeprom-id-table", i, &mid);
if (rc) {
CAM_ERR(CAM_EEPROM, "Failed in reading the MID. rc: %d", rc);
return rc;
}
i++;
rc = of_property_read_u32_index(dev, "i3c-eeprom-id-table", i, &pid);
if (rc) {
CAM_ERR(CAM_EEPROM, "Failed in reading the PID. rc: %d", rc);
return rc;
}
i++;
CAM_DBG(CAM_EEPROM, "PID: 0x%x, MID: 0x%x", pid, mid);
eeprom_i3c_id[ent_num].manuf_id = mid;
eeprom_i3c_id[ent_num].match_flags = I3C_MATCH_MANUF_AND_PART;
eeprom_i3c_id[ent_num].part_id = pid;
eeprom_i3c_id[ent_num].data = 0;
ent_num++;
}
return 0;
}
int cam_eeprom_driver_init(void)
{
int rc = 0;
@@ -679,15 +807,35 @@ int cam_eeprom_driver_init(void)
rc = spi_register_driver(&cam_eeprom_spi_driver);
if (rc < 0) {
CAM_ERR(CAM_EEPROM, "spi_register_driver failed rc = %d", rc);
return rc;
goto spi_register_err;
}
rc = i2c_add_driver(&cam_eeprom_i2c_driver);
if (rc < 0) {
CAM_ERR(CAM_EEPROM, "i2c_add_driver failed rc = %d", rc);
return rc;
goto i2c_register_err;
}
memset(eeprom_i3c_id, 0, sizeof(struct i3c_device_id) * (MAX_I3C_DEVICE_ID_ENTRIES + 1));
rc = cam_eeprom_fill_i3c_device_id();
if (rc)
goto i3c_register_err;
rc = i3c_driver_register_with_owner(&cam_eeprom_i3c_driver, THIS_MODULE);
if (rc) {
CAM_ERR(CAM_EEPROM, "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:
spi_unregister_driver(&cam_eeprom_spi_driver);
spi_register_err:
platform_driver_unregister(&cam_sensor_platform_driver);
return rc;
}
@@ -696,6 +844,7 @@ void cam_eeprom_driver_exit(void)
platform_driver_unregister(&cam_eeprom_platform_driver);
spi_unregister_driver(&cam_eeprom_spi_driver);
i2c_del_driver(&cam_eeprom_i2c_driver);
i3c_driver_unregister(&cam_eeprom_i3c_driver);
}
MODULE_DESCRIPTION("CAM EEPROM driver");

View File

@@ -35,6 +35,8 @@
#define MSM_EEPROM_MEM_MAP_PROPERTIES_CNT 8
#define EEPROM_DRIVER_I2C "cam-i2c-eeprom"
#define EEPROM_DRIVER_I3C "i3c_camera_eeprom"
enum cam_eeprom_state {
CAM_EEPROM_INIT,

View File

@@ -169,7 +169,7 @@ int cam_flash_i2c_power_ops(struct cam_flash_ctrl *fctrl,
}
}
rc = cam_sensor_core_power_up(power_info, soc_info);
rc = cam_sensor_core_power_up(power_info, soc_info, NULL);
if (rc) {
CAM_ERR(CAM_FLASH, "power up the core is failed:%d",
rc);

View File

@@ -7,7 +7,7 @@
#include <linux/module.h>
#include <linux/firmware.h>
#include <cam_sensor_cmn_header.h>
#include "cam_sensor_cmn_header.h"
#include "cam_ois_core.h"
#include "cam_ois_soc.h"
#include "cam_sensor_util.h"
@@ -106,13 +106,12 @@ static int cam_ois_get_dev_handle(struct cam_ois_ctrl_t *o_ctrl,
static int cam_ois_power_up(struct cam_ois_ctrl_t *o_ctrl)
{
int rc = 0;
struct cam_hw_soc_info *soc_info =
&o_ctrl->soc_info;
struct cam_hw_soc_info *soc_info = &o_ctrl->soc_info;
struct cam_ois_soc_private *soc_private;
struct cam_sensor_power_ctrl_t *power_info;
struct completion *i3c_probe_completion = NULL;
soc_private =
(struct cam_ois_soc_private *)o_ctrl->soc_info.soc_private;
soc_private = (struct cam_ois_soc_private *)o_ctrl->soc_info.soc_private;
power_info = &soc_private->power_info;
if ((power_info->power_setting == NULL) &&
@@ -151,7 +150,10 @@ static int cam_ois_power_up(struct cam_ois_ctrl_t *o_ctrl)
power_info->dev = soc_info->dev;
rc = cam_sensor_core_power_up(power_info, soc_info);
if (o_ctrl->io_master_info.master_type == I3C_MASTER)
i3c_probe_completion = cam_ois_get_i3c_completion(o_ctrl->soc_info.index);
rc = cam_sensor_core_power_up(power_info, soc_info, i3c_probe_completion);
if (rc) {
CAM_ERR(CAM_OIS, "failed in ois power up rc %d", rc);
return rc;

View File

@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef _CAM_OIS_CORE_H_
#define _CAM_OIS_CORE_H_
@@ -30,5 +31,7 @@ int cam_ois_driver_cmd(struct cam_ois_ctrl_t *e_ctrl, void *arg);
*/
void cam_ois_shutdown(struct cam_ois_ctrl_t *o_ctrl);
struct completion *cam_ois_get_i3c_completion(uint32_t index);
#endif
/* _CAM_OIS_CORE_H_ */

View File

@@ -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 "cam_ois_dev.h"
@@ -9,6 +10,17 @@
#include "cam_ois_core.h"
#include "cam_debug_util.h"
#include "camera_main.h"
#include "cam_compat.h"
static struct cam_i3c_ois_data {
struct cam_ois_ctrl_t *o_ctrl;
struct completion probe_complete;
} g_i3c_ois_data[MAX_CAMERAS];
struct completion *cam_ois_get_i3c_completion(uint32_t index)
{
return &g_i3c_ois_data[index].probe_complete;
}
static int cam_ois_subdev_close_internal(struct v4l2_subdev *sd,
struct v4l2_subdev_fh *fh)
@@ -372,6 +384,10 @@ static int cam_ois_component_bind(struct device *dev,
platform_set_drvdata(pdev, o_ctrl);
o_ctrl->cam_ois_state = CAM_OIS_INIT;
g_i3c_ois_data[o_ctrl->soc_info.index].o_ctrl = o_ctrl;
init_completion(&g_i3c_ois_data[o_ctrl->soc_info.index].probe_complete);
CAM_DBG(CAM_OIS, "Component bound successfully");
return rc;
unreg_subdev:
@@ -485,8 +501,117 @@ struct i2c_driver cam_ois_i2c_driver = {
},
};
static struct cam_ois_registered_driver_t registered_driver = {
0, 0};
static struct i3c_device_id ois_i3c_id[MAX_I3C_DEVICE_ID_ENTRIES + 1];
static int cam_ois_i3c_driver_probe(struct i3c_device *client)
{
int32_t rc = 0;
struct cam_ois_ctrl_t *o_ctrl = NULL;
uint32_t index;
struct device *dev;
if (!client) {
CAM_INFO(CAM_OIS, "Null Client pointer");
return -EINVAL;
}
dev = &client->dev;
CAM_DBG(CAM_OIS, "Probe for I3C Slave %s", dev_name(dev));
rc = of_property_read_u32(dev->of_node, "cell-index", &index);
if (rc) {
CAM_ERR(CAM_OIS, "device %s failed to read cell-index", dev_name(dev));
return rc;
}
if (index >= MAX_CAMERAS) {
CAM_ERR(CAM_OIS, "Invalid Cell-Index: %u for %s", index, dev_name(dev));
return -EINVAL;
}
o_ctrl = g_i3c_ois_data[index].o_ctrl;
if (!o_ctrl) {
CAM_ERR(CAM_OIS, "o_ctrl is null. I3C Probe before platfom driver probe for %s",
dev_name(dev));
return -EINVAL;
}
o_ctrl->io_master_info.i3c_client = client;
complete_all(&g_i3c_ois_data[index].probe_complete);
CAM_DBG(CAM_OIS, "I3C Probe Finished for %s", dev_name(dev));
return rc;
}
static struct i3c_driver cam_ois_i3c_driver = {
.id_table = ois_i3c_id,
.probe = cam_ois_i3c_driver_probe,
.remove = cam_i3c_driver_remove,
.driver = {
.owner = THIS_MODULE,
.name = OIS_DRIVER_I3C,
.of_match_table = cam_ois_dt_match,
.suppress_bind_attrs = true,
},
};
static int cam_ois_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_OIS, "Couldnt Find the i3c-id-table dev node");
return 0;
}
num_entries = of_property_count_u32_elems(dev, "i3c-ois-id-table");
if (num_entries <= 0) {
CAM_WARN(CAM_OIS, "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_OIS, "Num_entries are more than MAX_I3C_DEVICE_ID_ENTRIES");
return -ENOMEM;
}
rc = of_property_read_u32_index(dev, "i3c-ois-id-table", i, &mid);
if (rc) {
CAM_ERR(CAM_OIS, "Failed in reading the MID. rc: %d", rc);
return rc;
}
i++;
rc = of_property_read_u32_index(dev, "i3c-ois-id-table", i, &pid);
if (rc) {
CAM_ERR(CAM_OIS, "Failed in reading the PID. rc: %d", rc);
return rc;
}
i++;
CAM_DBG(CAM_OIS, "PID: 0x%x, MID: 0x%x", pid, mid);
ois_i3c_id[ent_num].manuf_id = mid;
ois_i3c_id[ent_num].match_flags = I3C_MATCH_MANUF_AND_PART;
ois_i3c_id[ent_num].part_id = pid;
ois_i3c_id[ent_num].data = 0;
ent_num++;
}
return 0;
}
int cam_ois_driver_init(void)
{
@@ -494,30 +619,42 @@ int cam_ois_driver_init(void)
rc = platform_driver_register(&cam_ois_platform_driver);
if (rc) {
CAM_ERR(CAM_OIS, "platform_driver_register failed rc = %d",
rc);
CAM_ERR(CAM_OIS, "platform_driver_register failed rc = %d", rc);
return rc;
}
registered_driver.platform_driver = 1;
rc = i2c_add_driver(&cam_ois_i2c_driver);
if (rc) {
CAM_ERR(CAM_OIS, "i2c_add_driver failed rc = %d", rc);
return rc;
goto i2c_register_err;
}
registered_driver.i2c_driver = 1;
memset(ois_i3c_id, 0, sizeof(struct i3c_device_id) * (MAX_I3C_DEVICE_ID_ENTRIES + 1));
rc = cam_ois_fill_i3c_device_id();
if (rc)
goto i3c_register_err;
rc = i3c_driver_register_with_owner(&cam_ois_i3c_driver, THIS_MODULE);
if (rc) {
CAM_ERR(CAM_OIS, "i3c_driver registration failed, rc: %d", rc);
goto i3c_register_err;
}
return 0;
i3c_register_err:
i2c_del_driver(&cam_ois_i2c_driver);
i2c_register_err:
platform_driver_unregister(&cam_ois_platform_driver);
return rc;
}
void cam_ois_driver_exit(void)
{
if (registered_driver.platform_driver)
platform_driver_unregister(&cam_ois_platform_driver);
if (registered_driver.i2c_driver)
i2c_del_driver(&cam_ois_i2c_driver);
i3c_driver_unregister(&cam_ois_i3c_driver);
}
MODULE_DESCRIPTION("CAM OIS driver");

View File

@@ -27,6 +27,7 @@
static struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)
#define OIS_DRIVER_I2C "cam-i2c-ois"
#define OIS_DRIVER_I3C "i3c_camera_ois"
enum cam_ois_state {
CAM_OIS_INIT,
@@ -35,17 +36,6 @@ enum cam_ois_state {
CAM_OIS_START,
};
/**
* struct cam_ois_registered_driver_t - registered driver info
* @platform_driver : flag indicates if platform driver is registered
* @i2c_driver : flag indicates if i2c driver is registered
*
*/
struct cam_ois_registered_driver_t {
bool platform_driver;
bool i2c_driver;
};
/**
* struct cam_ois_i2c_info_t - I2C info
* @slave_addr : slave address

View File

@@ -866,9 +866,7 @@ 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");
@@ -943,6 +941,7 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl,
);
goto free_power_settings;
}
if (s_ctrl->i2c_data.reg_bank_unlock_settings.is_settings_valid) {
rc = cam_sensor_apply_settings(s_ctrl, 0,
CAM_SENSOR_PACKET_OPCODE_SENSOR_REG_BANK_UNLOCK);
@@ -958,20 +957,6 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl,
}
}
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) {
@@ -1429,8 +1414,8 @@ int cam_sensor_power_up(struct cam_sensor_ctrl_t *s_ctrl)
int rc;
struct cam_sensor_power_ctrl_t *power_info;
struct cam_camera_slave_info *slave_info;
struct cam_hw_soc_info *soc_info =
&s_ctrl->soc_info;
struct cam_hw_soc_info *soc_info = &s_ctrl->soc_info;
struct completion *i3c_probe_completion = NULL;
if (!s_ctrl) {
CAM_ERR(CAM_SENSOR, "failed: %pK", s_ctrl);
@@ -1469,7 +1454,10 @@ int cam_sensor_power_up(struct cam_sensor_ctrl_t *s_ctrl)
}
}
rc = cam_sensor_core_power_up(power_info, soc_info);
if (s_ctrl->io_master_info.master_type == I3C_MASTER)
i3c_probe_completion = cam_sensor_get_i3c_completion(s_ctrl->soc_info.index);
rc = cam_sensor_core_power_up(power_info, soc_info, i3c_probe_completion);
if (rc < 0) {
CAM_ERR(CAM_SENSOR, "core power up failed:%d", rc);
return rc;

View File

@@ -572,7 +572,7 @@ 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,
.remove = cam_i3c_driver_remove,
.driver = {
.owner = THIS_MODULE,
.name = SENSOR_DRIVER_I3C,

View File

@@ -12,6 +12,7 @@ static int cam_qup_i3c_rxdata(struct i3c_device *dev_client, unsigned char *rxda
enum camera_sensor_i2c_type addr_type, int data_length)
{
int rc;
uint32_t us = 0;
struct i3c_priv_xfer read_buf[2] = {
{
.rnw = 0,
@@ -26,7 +27,18 @@ static int cam_qup_i3c_rxdata(struct i3c_device *dev_client, unsigned char *rxda
};
rc = i3c_device_do_priv_xfers(dev_client, read_buf, ARRAY_SIZE(read_buf));
if (rc == -ENOTCONN) {
while (us < CAM_I3C_DEV_PROBE_TIMEOUT_US) {
usleep_range(1000, 1005);
rc = i3c_device_do_priv_xfers(dev_client, read_buf, ARRAY_SIZE(read_buf));
if (rc != -ENOTCONN)
break;
us += 1000;
}
if (rc)
CAM_ERR(CAM_SENSOR, "Retry Failed i3c_read: rc = %d, us = %d", rc, us);
} else if (rc)
CAM_ERR(CAM_SENSOR, "Failed with i3c_read: rc = %d", rc);
return rc;
@@ -37,6 +49,7 @@ static int cam_qup_i3c_txdata(struct camera_io_master *dev_client, unsigned char
int length)
{
int rc;
uint32_t us = 0;
struct i3c_priv_xfer write_buf = {
.rnw = 0,
.len = length,
@@ -44,7 +57,18 @@ static int cam_qup_i3c_txdata(struct camera_io_master *dev_client, unsigned char
};
rc = i3c_device_do_priv_xfers(dev_client->i3c_client, &write_buf, 1);
if (rc == -ENOTCONN) {
while (us < CAM_I3C_DEV_PROBE_TIMEOUT_US) {
usleep_range(1000, 1005);
rc = i3c_device_do_priv_xfers(dev_client->i3c_client, &write_buf, 1);
if (rc != -ENOTCONN)
break;
us += 1000;
}
if (rc)
CAM_ERR(CAM_SENSOR, "Retry Failed i3c_write: rc = %d, us = %d", rc, us);
} else if (rc)
CAM_ERR(CAM_SENSOR, "Failed with i3c_write: rc = %d", rc);
return rc;

View File

@@ -23,7 +23,8 @@
#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 CAM_I3C_DEV_PROBE_TIMEOUT_MS 10
#define CAM_I3C_DEV_PROBE_TIMEOUT_US (CAM_I3C_DEV_PROBE_TIMEOUT_MS * 1000)
#define I3C_SENSOR_DEV_ID_DT_PATH "/soc/qcom,cam-i3c-id-table"
#define MAX_I3C_DEVICE_ID_ENTRIES MAX_CAMERAS

View File

@@ -1977,12 +1977,13 @@ static int cam_config_mclk_reg(struct cam_sensor_power_ctrl_t *ctrl,
}
int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl,
struct cam_hw_soc_info *soc_info)
struct cam_hw_soc_info *soc_info, struct completion *i3c_probe_status)
{
int rc = 0, index = 0, no_gpio = 0, ret = 0, num_vreg, j = 0, i = 0;
int32_t vreg_idx = -1;
struct cam_sensor_power_setting *power_setting = NULL;
struct msm_camera_gpio_num_info *gpio_num_info = NULL;
long time_left;
CAM_DBG(CAM_SENSOR, "Enter");
if (!ctrl) {
@@ -2195,6 +2196,17 @@ int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl,
(power_setting->delay * 1000) + 1000);
}
if (i3c_probe_status) {
time_left = cam_common_wait_for_completion_timeout(
i3c_probe_status,
msecs_to_jiffies(CAM_I3C_DEV_PROBE_TIMEOUT_MS));
if (!time_left) {
CAM_ERR(CAM_SENSOR, "Wait for I3C probe timedout");
rc = -ETIMEDOUT;
goto power_up_failed;
}
}
return 0;
power_up_failed:
CAM_ERR(CAM_SENSOR, "failed. rc:%d", rc);

View File

@@ -66,7 +66,7 @@ int cam_sensor_util_init_gpio_pin_tbl(
struct cam_hw_soc_info *soc_info,
struct msm_camera_gpio_num_info **pgpio_num_info);
int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl,
struct cam_hw_soc_info *soc_info);
struct cam_hw_soc_info *soc_info, struct completion *i3c_probe_status);
int cam_sensor_util_power_down(struct cam_sensor_power_ctrl_t *ctrl,
struct cam_hw_soc_info *soc_info);

View File

@@ -366,7 +366,7 @@ 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)
void cam_i3c_driver_remove(struct i3c_device *client)
{
CAM_DBG(CAM_SENSOR, "I3C remove invoked for %s",
(client ? dev_name(&client->dev) : "none"));
@@ -411,7 +411,7 @@ 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)
int cam_i3c_driver_remove(struct i3c_device *client)
{
CAM_DBG(CAM_SENSOR, "I3C remove invoked for %s",
(client ? dev_name(&client->dev) : "none"));

View File

@@ -58,11 +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);
void cam_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);
int cam_i3c_driver_remove(struct i3c_device *client);
#endif
long cam_dma_buf_set_name(struct dma_buf *dmabuf, const char *name);