kernel: cdi: Update fsync logic

CIM version 3 for Ferrix is added in DT which can be used to select
GPIO port number of IO expander to control the multiplexer for
each deserializer

Bug 5163582

Change-Id: I3ce608be9f5c18af005e1bc6fea9c73daeef7995
Signed-off-by: Junghyun Kim <juskim@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3342728
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Mohit Ingale <mohiti@nvidia.com>
Reviewed-by: Frank Chen <frankc@nvidia.com>
Reviewed-by: Chinmay Mahajan <cmahajan@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
Junghyun Kim
2025-04-17 08:34:14 +00:00
committed by Jon Hunter
parent efd43d9c76
commit 7b863e3e09
3 changed files with 80 additions and 37 deletions

View File

@@ -27,7 +27,6 @@ struct tca9539_priv {
u32 dat_len;
u8 init_val[12];
u32 power_port;
u32 fsync_ctrl_port;
bool enable;
};

View File

@@ -436,7 +436,6 @@ static int cdi_dev_set_fsync_mux(
void __user *arg)
{
u8 val, shift;
u8 cam_grp;
struct cdi_dev_fsync_mux fsync_mux;
if (copy_from_user(&fsync_mux, arg, sizeof(fsync_mux))) {
@@ -451,14 +450,9 @@ static int cdi_dev_set_fsync_mux(
* P05:P04 for the camera group D. cam_grp 3.
*/
if ((fsync_mux.cam_grp > 0U) && (fsync_mux.cam_grp < 4U)) {
if (info->tca9539.fsync_ctrl_port != -1)
cam_grp = info->tca9539.fsync_ctrl_port;
else
cam_grp = fsync_mux.cam_grp;
if (tca9539_rd(info, 0x02, &val) != 0)
return -EFAULT;
switch (cam_grp) {
switch (fsync_mux.cam_grp) {
case 1U:
shift = 0U;
break;
@@ -473,6 +467,34 @@ static int cdi_dev_set_fsync_mux(
break;
}
val &= ~(0x3 << shift);
val |= (fsync_mux.mux_sel << shift);
if (tca9539_wr(info, 0x02, val) != 0)
return -EFAULT;
}
} else if (info->cim_ver == 3U) {
/* P01:P00 for the camera group A. cam_grp 1.
* P03:P02 for the camera group B. cam_grp 3.
* P05:P04 for the camera group D. cam_grp 2.
*/
if ((fsync_mux.cam_grp > 0U) && (fsync_mux.cam_grp < 4U)) {
if (tca9539_rd(info, 0x02, &val) != 0)
return -EFAULT;
switch (fsync_mux.cam_grp) {
case 1U:
shift = 0U;
break;
case 2U:
shift = 4U;
break;
case 3U:
shift = 2U;
break;
default:
shift = 0U;
break;
}
val &= ~(0x3 << shift);
val |= (fsync_mux.mux_sel << shift);
if (tca9539_wr(info, 0x02, val) != 0)
@@ -567,10 +589,16 @@ static void cdi_dev_get_cim_ver(struct device_node *np, struct cdi_dev_info *inf
dev_info(info->dev,
"CIM A01\n");
info->cim_ver = 1U;
} else {
} else if (!strncmp(cim_ver,
"cim_ver_a02",
sizeof("cim_ver_a02"))) {
dev_info(info->dev,
"CIM A02\n");
info->cim_ver = 2U;
} else {
dev_info(info->dev,
"CIM A03\n");
info->cim_ver = 3U;
}
}
}
@@ -592,7 +620,6 @@ static int cdi_dev_probe(struct i2c_client *client,
int err;
int numLinks = 0;
int i;
u32 fsync_ctrl_port;
dev_dbg(&client->dev, "%s: initializing link @%x-%04x\n",
__func__, client->adapter->nr, client->addr);
@@ -690,7 +717,7 @@ static int cdi_dev_probe(struct i2c_client *client,
}
}
if (info->cim_ver == 2U) {
if ((info->cim_ver == 2U) || (info->cim_ver == 3U)) {
/* get the I/O expander information */
child_tca9539 = of_get_child_by_name(child, "tca9539");
if (child_tca9539 != NULL) {
@@ -739,17 +766,6 @@ static int cdi_dev_probe(struct i2c_client *client,
info->tca9539.power_port);
return -ENODEV;
}
info->tca9539.fsync_ctrl_port = -1;
err = of_property_read_u32(child_tca9539,
"fsync_ctrl_port",
&fsync_ctrl_port);
if (err == 0) {
if ((fsync_ctrl_port >= 0) &&
(fsync_ctrl_port <= 3)) {
info->tca9539.fsync_ctrl_port =
fsync_ctrl_port;
}
}
info->tca9539.reg_len /= 8;
info->tca9539.dat_len /= 8;
info->tca9539.enable = 1;

View File

@@ -1732,9 +1732,17 @@ static void cdi_mgr_get_cim_ver(struct device *dev, struct cdi_mgr_priv *cdi_mgr
"CIM A01\n");
cdi_mgr->cim_ver = 1U;
} else {
dev_info(dev,
"CIM A02\n");
cdi_mgr->cim_ver = 2U;
if (!strncmp(cim_ver,
"cim_ver_a02",
sizeof("cim_ver_a02"))) {
dev_info(dev,
"CIM A02\n");
cdi_mgr->cim_ver = 2U;
} else {
dev_info(dev,
"CIM A03\n");
cdi_mgr->cim_ver = 3U;
}
if (of_property_read_u32_array(cim,
"cim_frsync_src",
cdi_mgr->cim_frsync,
@@ -1760,7 +1768,6 @@ static int cdi_mgr_probe(struct platform_device *pdev)
struct device_node *child_tca9539 = NULL;
struct device_node *root_node = NULL;
const char *model;
u32 fsync_ctrl_port;
dev_info(&pdev->dev, "%sing...\n", __func__);
@@ -1993,17 +2000,6 @@ static int cdi_mgr_probe(struct platform_device *pdev)
cdi_mgr->tca9539.power_port);
goto err_probe;
}
cdi_mgr->tca9539.fsync_ctrl_port = -1;
err = of_property_read_u32(child_tca9539,
"fsync_ctrl_port",
&fsync_ctrl_port);
if (err == 0) {
if ((fsync_ctrl_port >= 0) &&
(fsync_ctrl_port <= 3)) {
cdi_mgr->tca9539.fsync_ctrl_port =
fsync_ctrl_port;
}
}
cdi_mgr->tca9539.reg_len /= 8;
cdi_mgr->tca9539.dat_len /= 8;
@@ -2085,6 +2081,38 @@ static int cdi_mgr_probe(struct platform_device *pdev)
__func__, err);
goto err_probe;
}
} else if (cdi_mgr->cim_ver == 3U) { /* P3966 */
err = tca9539_wr(cdi_mgr, 0x6, 0xC0);
if (err != 0) {
dev_err(&pdev->dev,
"%s: ERR %d: TCA9539: Failed to select FS selection signal source\n",
__func__, err);
goto err_probe;
}
err = tca9539_wr(cdi_mgr, 0x7, 0x70);
if (err != 0) {
dev_err(&pdev->dev,
"%s: ERR %d: TCA9539: Failed to select PWDN signal source\n",
__func__, err);
goto err_probe;
}
/* Configure FRSYNC logic */
dev_info(&pdev->dev,
"FRSYNC source: %d %d %d\n",
cdi_mgr->cim_frsync[0],
cdi_mgr->cim_frsync[1],
cdi_mgr->cim_frsync[2]);
err = tca9539_wr(cdi_mgr, 0x2,
(cdi_mgr->cim_frsync[2] << 4) |
(cdi_mgr->cim_frsync[1] << 2) |
(cdi_mgr->cim_frsync[0]));
if (err < 0) {
dev_err(&pdev->dev,
"%s: ERR %d: TCA9539: Failed to set FRSYNC control logic\n",
__func__, err);
goto err_probe;
}
}
}
}