mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-23 17:55:05 +03:00
drivers: media: CDI: Add IO Expander support
Add IO Expander support in CDI Dev to control the FRSYNC multiplexer with the speicific platform Bug 3582660 Change-Id: I3ee376e7a0bccabcfa16efb228879d4df0d65748 Signed-off-by: Junghyun Kim <juskim@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2727256 Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2824551 Reviewed-by: Frank Chen <frankc@nvidia.com> Reviewed-by: Shiva Dubey <sdubey@nvidia.com> GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
eb1d8b3b58
commit
9269dac3ec
@@ -5,6 +5,7 @@
|
||||
#define __CDI_DEV_PRIV_H__
|
||||
|
||||
#include <linux/cdev.h>
|
||||
#include "cdi-tca-priv.h"
|
||||
|
||||
#define MAX_POWER_LINKS_PER_BLOCK (4U)
|
||||
|
||||
@@ -32,6 +33,8 @@ struct cdi_dev_info {
|
||||
u8 cam_pwr_method;
|
||||
u8 cam_pwr_i2c_addr;
|
||||
struct max20087_priv max20087;
|
||||
struct tca9539_priv tca9539;
|
||||
u8 cim_ver; /* 1 - P3714 A01, 2 - P3714 A02/A03 */
|
||||
};
|
||||
|
||||
int cdi_dev_raw_rd(struct cdi_dev_info *info, unsigned int offset,
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <linux/cdev.h>
|
||||
#include <media/cdi-mgr.h>
|
||||
#include "cdi-tca-priv.h"
|
||||
|
||||
#define CDI_MGR_STOP_GPIO_INTR_EVENT_WAIT (~(0u))
|
||||
#define CDI_MGR_TCA9539_REGISTER_COUNT (8)
|
||||
@@ -24,17 +25,6 @@ struct cam_gpio_config {
|
||||
int gpio_intr_irq;
|
||||
};
|
||||
|
||||
struct tca9539_priv {
|
||||
struct i2c_adapter *adap;
|
||||
int bus;
|
||||
u32 addr;
|
||||
u32 reg_len;
|
||||
u32 dat_len;
|
||||
u8 init_val[12];
|
||||
u32 power_port;
|
||||
bool enable;
|
||||
};
|
||||
|
||||
struct cdi_mgr_priv {
|
||||
struct device *pdev; /* parent device */
|
||||
struct device *dev; /* this device */
|
||||
@@ -65,7 +55,7 @@ struct cdi_mgr_priv {
|
||||
uint32_t gpio_count;
|
||||
uint32_t err_irq_recvd_status_mask;
|
||||
bool stop_err_irq_wait;
|
||||
u8 cim_ver; /* 1 - P3714 A01, 2 - P3714 A02 */
|
||||
u8 cim_ver; /* 1 - P3714 A01, 2 - P3714 A02/A03 */
|
||||
u32 cim_frsync[3]; /* FRSYNC source selection for each muxer */
|
||||
u8 pre_suspend_tca9539_regvals[CDI_MGR_TCA9539_REGISTER_COUNT];
|
||||
};
|
||||
|
||||
122
drivers/media/platform/tegra/cdi/cdi-tca-priv.h
Normal file
122
drivers/media/platform/tegra/cdi/cdi-tca-priv.h
Normal file
@@ -0,0 +1,122 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
|
||||
#ifndef __CDI_TCA9539_PRIV_H__
|
||||
#define __CDI_TCA9539_PRIV_H__
|
||||
|
||||
/* i2c payload size is only 12 bit */
|
||||
#define MAX_MSG_SIZE (0xFFF - 1)
|
||||
|
||||
struct tca9539_priv {
|
||||
struct i2c_adapter *adap;
|
||||
int bus;
|
||||
u32 addr;
|
||||
u32 reg_len;
|
||||
u32 dat_len;
|
||||
u8 init_val[12];
|
||||
u32 power_port;
|
||||
bool enable;
|
||||
};
|
||||
|
||||
static int tca9539_raw_wr(
|
||||
struct device *dev, struct tca9539_priv *tca9539, unsigned int offset, u8 val)
|
||||
{
|
||||
int ret = -ENODEV;
|
||||
u8 *buf_start = NULL;
|
||||
struct i2c_msg *i2cmsg;
|
||||
unsigned int num_msgs = 0, total_size, i;
|
||||
u8 data[3];
|
||||
size_t size = 1;
|
||||
|
||||
dev_dbg(dev, "%s\n", __func__);
|
||||
|
||||
if (tca9539->reg_len == 2) {
|
||||
data[0] = (u8)((offset >> 8) & 0xff);
|
||||
data[1] = (u8)(offset & 0xff);
|
||||
data[2] = val;
|
||||
size += 2;
|
||||
} else if (tca9539->reg_len == 1) {
|
||||
data[0] = (u8)(offset & 0xff);
|
||||
data[1] = val;
|
||||
size += 1;
|
||||
} else if ((tca9539->reg_len == 0) ||
|
||||
(tca9539->reg_len > 3)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
num_msgs = size / MAX_MSG_SIZE;
|
||||
num_msgs += (size % MAX_MSG_SIZE) ? 1 : 0;
|
||||
|
||||
i2cmsg = kzalloc((sizeof(struct i2c_msg)*num_msgs), GFP_KERNEL);
|
||||
if (!i2cmsg) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
buf_start = data;
|
||||
total_size = size;
|
||||
|
||||
dev_dbg(dev, "%s: num_msgs: %d\n", __func__, num_msgs);
|
||||
for (i = 0; i < num_msgs; i++) {
|
||||
i2cmsg[i].addr = tca9539->addr;
|
||||
i2cmsg[i].buf = (__u8 *)buf_start;
|
||||
|
||||
if (i > 0)
|
||||
i2cmsg[i].flags = I2C_M_NOSTART;
|
||||
else
|
||||
i2cmsg[i].flags = 0;
|
||||
|
||||
if (total_size > MAX_MSG_SIZE) {
|
||||
i2cmsg[i].len = MAX_MSG_SIZE;
|
||||
buf_start += MAX_MSG_SIZE;
|
||||
total_size -= MAX_MSG_SIZE;
|
||||
} else {
|
||||
i2cmsg[i].len = total_size;
|
||||
}
|
||||
dev_dbg(dev, "%s: addr:%x buf:%p, flags:%u len:%u\n",
|
||||
__func__, i2cmsg[i].addr, (void *)i2cmsg[i].buf,
|
||||
i2cmsg[i].flags, i2cmsg[i].len);
|
||||
}
|
||||
|
||||
ret = i2c_transfer(tca9539->adap, i2cmsg, num_msgs);
|
||||
if (ret > 0)
|
||||
ret = 0;
|
||||
|
||||
kfree(i2cmsg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tca9539_raw_rd(
|
||||
struct device *dev, struct tca9539_priv *tca9539, unsigned int offset, u8 *val)
|
||||
{
|
||||
int ret = -ENODEV;
|
||||
u8 data[2];
|
||||
size_t size = 1;
|
||||
struct i2c_msg i2cmsg[2];
|
||||
|
||||
dev_dbg(dev, "%s\n", __func__);
|
||||
|
||||
if (tca9539->reg_len == 2) {
|
||||
data[0] = (u8)((offset >> 8) & 0xff);
|
||||
data[1] = (u8)(offset & 0xff);
|
||||
} else if (tca9539->reg_len == 1)
|
||||
data[0] = (u8)(offset & 0xff);
|
||||
|
||||
i2cmsg[0].addr = tca9539->addr;
|
||||
i2cmsg[0].len = tca9539->reg_len;
|
||||
i2cmsg[0].buf = (__u8 *)data;
|
||||
i2cmsg[0].flags = I2C_M_NOSTART;
|
||||
|
||||
i2cmsg[1].addr = tca9539->addr;
|
||||
i2cmsg[1].flags = I2C_M_RD;
|
||||
i2cmsg[1].len = size;
|
||||
i2cmsg[1].buf = (__u8 *)val;
|
||||
|
||||
ret = i2c_transfer(tca9539->adap, i2cmsg, 2);
|
||||
if (ret > 0)
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* __CDI_TCA9539_PRIV_H__ */
|
||||
|
||||
@@ -394,6 +394,81 @@ static int cdi_dev_get_pwr_info(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tca9539_wr(
|
||||
struct cdi_dev_info *info, unsigned int offset, u8 val)
|
||||
{
|
||||
int ret = -ENODEV;
|
||||
|
||||
dev_dbg(info->dev, "%s\n", __func__);
|
||||
mutex_lock(&info->mutex);
|
||||
|
||||
ret = tca9539_raw_wr(info->dev, &info->tca9539, offset, val);
|
||||
|
||||
mutex_unlock(&info->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tca9539_rd(
|
||||
struct cdi_dev_info *info, unsigned int offset, u8 *val)
|
||||
{
|
||||
int ret = -ENODEV;
|
||||
|
||||
dev_dbg(info->dev, "%s\n", __func__);
|
||||
mutex_lock(&info->mutex);
|
||||
|
||||
ret = tca9539_raw_rd(info->dev, &info->tca9539, offset, val);
|
||||
|
||||
mutex_unlock(&info->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cdi_dev_set_fsync_mux(
|
||||
struct cdi_dev_info *info,
|
||||
void __user *arg)
|
||||
{
|
||||
u8 val, shift;
|
||||
struct cdi_dev_fsync_mux fsync_mux;
|
||||
|
||||
if (copy_from_user(&fsync_mux, arg, sizeof(fsync_mux))) {
|
||||
dev_err(info->dev,
|
||||
"%s: failed to copy from user\n", __func__);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (info->cim_ver == 2U) {
|
||||
/* P01:P00 for the camera group B. cam_grp 1.
|
||||
* P03:P02 for the camera group C. cam_grp 2.
|
||||
* P05:P04 for the camera group D. cam_grp 3.
|
||||
*/
|
||||
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 = 2U;
|
||||
break;
|
||||
case 3U:
|
||||
shift = 4U;
|
||||
break;
|
||||
default:
|
||||
shift = 0U;
|
||||
break;
|
||||
}
|
||||
|
||||
val &= ~(0x3 << shift);
|
||||
val |= (fsync_mux.mux_sel << shift);
|
||||
if (tca9539_wr(info, 0x02, val) != 0)
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long cdi_dev_ioctl(struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
@@ -411,6 +486,9 @@ static long cdi_dev_ioctl(struct file *file,
|
||||
case CDI_DEV_IOCTL_GET_PWR_INFO:
|
||||
err = cdi_dev_get_pwr_info(info, (void __user *)arg);
|
||||
break;
|
||||
case CDI_DEV_IOCTL_FRSYNC_MUX:
|
||||
err = cdi_dev_set_fsync_mux(info, (void __user *)arg);
|
||||
break;
|
||||
default:
|
||||
dev_dbg(info->dev, "%s: invalid cmd %x\n", __func__, cmd);
|
||||
return -EINVAL;
|
||||
@@ -453,6 +531,38 @@ static const struct file_operations cdi_dev_fileops = {
|
||||
.release = cdi_dev_release,
|
||||
};
|
||||
|
||||
static void cdi_dev_get_cim_ver(struct device_node *np, struct cdi_dev_info *info)
|
||||
{
|
||||
int err = 0;
|
||||
struct device_node *child = NULL;
|
||||
struct device_node *cim = NULL;
|
||||
const char *cim_ver;
|
||||
|
||||
child = of_get_parent(np);
|
||||
if (child != NULL) {
|
||||
cim = of_get_compatible_child(child,
|
||||
"nvidia,cim_ver");
|
||||
if (cim != NULL) {
|
||||
err = of_property_read_string(cim,
|
||||
"cim_ver",
|
||||
&cim_ver);
|
||||
if (!err) {
|
||||
if (!strncmp(cim_ver,
|
||||
"cim_ver_a01",
|
||||
sizeof("cim_ver_a01"))) {
|
||||
dev_info(info->dev,
|
||||
"CIM A01\n");
|
||||
info->cim_ver = 1U;
|
||||
} else {
|
||||
dev_info(info->dev,
|
||||
"CIM A02\n");
|
||||
info->cim_ver = 2U;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int cdi_dev_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
@@ -460,6 +570,7 @@ static int cdi_dev_probe(struct i2c_client *client,
|
||||
struct cdi_mgr_priv *cdi_mgr = NULL;
|
||||
struct device *pdev;
|
||||
struct device_node *child = NULL, *child_max20087 = NULL;
|
||||
struct device_node *child_tca9539 = NULL;
|
||||
int err;
|
||||
int numLinks = 0;
|
||||
int i;
|
||||
@@ -483,7 +594,10 @@ static int cdi_dev_probe(struct i2c_client *client,
|
||||
dev_notice(&client->dev, "%s NO platform data\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (info->pdata->np != NULL) {
|
||||
cdi_dev_get_cim_ver(info->pdata->np, info);
|
||||
|
||||
child = of_get_child_by_name(info->pdata->np,
|
||||
"pwr_ctrl");
|
||||
if (child != NULL) {
|
||||
@@ -553,6 +667,68 @@ static int cdi_dev_probe(struct i2c_client *client,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (info->cim_ver == 2U) {
|
||||
/* get the I/O expander information */
|
||||
child_tca9539 = of_get_child_by_name(child, "tca9539");
|
||||
if (child_tca9539 != NULL) {
|
||||
err = of_property_read_u32(child_tca9539, "i2c-bus",
|
||||
&info->tca9539.bus);
|
||||
if (err) {
|
||||
dev_err(info->dev,
|
||||
"%s: Failed to get I2C bus number, ERROR %d\n",
|
||||
__func__, err);
|
||||
return -ENODEV;
|
||||
}
|
||||
err = of_property_read_u32(child_tca9539, "addr",
|
||||
&info->tca9539.addr);
|
||||
if (err || !info->tca9539.addr) {
|
||||
dev_err(info->dev,
|
||||
"%s: ERROR %d addr = %d\n",
|
||||
__func__, err,
|
||||
info->tca9539.addr);
|
||||
return -ENODEV;
|
||||
}
|
||||
err = of_property_read_u32(child_tca9539, "reg_len",
|
||||
&info->tca9539.reg_len);
|
||||
if (err || !info->tca9539.reg_len) {
|
||||
dev_err(info->dev,
|
||||
"%s: ERROR %d reg_len = %d\n",
|
||||
__func__, err,
|
||||
info->tca9539.reg_len);
|
||||
return -ENODEV;
|
||||
}
|
||||
err = of_property_read_u32(child_tca9539, "dat_len",
|
||||
&info->tca9539.dat_len);
|
||||
if (err || !info->tca9539.dat_len) {
|
||||
dev_err(info->dev,
|
||||
"%s: ERROR %d dat_len = %d\n",
|
||||
__func__, err,
|
||||
info->tca9539.dat_len);
|
||||
return -ENODEV;
|
||||
}
|
||||
err = of_property_read_u32(child_tca9539->parent,
|
||||
"power_port",
|
||||
&info->tca9539.power_port);
|
||||
if (err) {
|
||||
dev_err(info->dev,
|
||||
"%s: ERROR %d power_port = %d\n",
|
||||
__func__, err,
|
||||
info->tca9539.power_port);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
info->tca9539.reg_len /= 8;
|
||||
info->tca9539.dat_len /= 8;
|
||||
info->tca9539.enable = 1;
|
||||
info->tca9539.adap = i2c_get_adapter(info->tca9539.bus);
|
||||
if (!info->tca9539.adap) {
|
||||
dev_err(info->dev, "%s no such i2c bus %d\n",
|
||||
__func__, info->tca9539.bus);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (info->pdata->reg_bits)
|
||||
|
||||
@@ -146,107 +146,30 @@ static int pwr_off_set(void *data, u64 val)
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(pwr_off_fops, pwr_off_get, pwr_off_set, "0x%02llx\n");
|
||||
|
||||
static int tca9539_raw_wr(
|
||||
static int tca9539_wr(
|
||||
struct cdi_mgr_priv *info, unsigned int offset, u8 val)
|
||||
{
|
||||
int ret = -ENODEV;
|
||||
u8 *buf_start = NULL;
|
||||
struct i2c_msg *i2cmsg;
|
||||
unsigned int num_msgs = 0, total_size, i;
|
||||
u8 data[3];
|
||||
size_t size = 1;
|
||||
|
||||
dev_dbg(info->dev, "%s\n", __func__);
|
||||
mutex_lock(&info->mutex);
|
||||
|
||||
if (info->tca9539.reg_len == 2) {
|
||||
data[0] = (u8)((offset >> 8) & 0xff);
|
||||
data[1] = (u8)(offset & 0xff);
|
||||
data[2] = val;
|
||||
size += 2;
|
||||
} else if (info->tca9539.reg_len == 1) {
|
||||
data[0] = (u8)(offset & 0xff);
|
||||
data[1] = val;
|
||||
size += 1;
|
||||
} else if ((info->tca9539.reg_len == 0) ||
|
||||
(info->tca9539.reg_len > 3)) {
|
||||
mutex_unlock(&info->mutex);
|
||||
return 0;
|
||||
}
|
||||
ret = tca9539_raw_wr(info->dev, &info->tca9539, offset, val);
|
||||
|
||||
num_msgs = size / MAX_MSG_SIZE;
|
||||
num_msgs += (size % MAX_MSG_SIZE) ? 1 : 0;
|
||||
|
||||
i2cmsg = kzalloc((sizeof(struct i2c_msg)*num_msgs), GFP_KERNEL);
|
||||
if (!i2cmsg) {
|
||||
mutex_unlock(&info->mutex);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
buf_start = data;
|
||||
total_size = size;
|
||||
|
||||
dev_dbg(info->dev, "%s: num_msgs: %d\n", __func__, num_msgs);
|
||||
for (i = 0; i < num_msgs; i++) {
|
||||
i2cmsg[i].addr = info->tca9539.addr;
|
||||
i2cmsg[i].buf = (__u8 *)buf_start;
|
||||
|
||||
if (i > 0)
|
||||
i2cmsg[i].flags = I2C_M_NOSTART;
|
||||
else
|
||||
i2cmsg[i].flags = 0;
|
||||
|
||||
if (total_size > MAX_MSG_SIZE) {
|
||||
i2cmsg[i].len = MAX_MSG_SIZE;
|
||||
buf_start += MAX_MSG_SIZE;
|
||||
total_size -= MAX_MSG_SIZE;
|
||||
} else {
|
||||
i2cmsg[i].len = total_size;
|
||||
}
|
||||
dev_dbg(info->dev, "%s: addr:%x buf:%p, flags:%u len:%u\n",
|
||||
__func__, i2cmsg[i].addr, (void *)i2cmsg[i].buf,
|
||||
i2cmsg[i].flags, i2cmsg[i].len);
|
||||
}
|
||||
|
||||
ret = i2c_transfer(info->tca9539.adap, i2cmsg, num_msgs);
|
||||
if (ret > 0)
|
||||
ret = 0;
|
||||
|
||||
kfree(i2cmsg);
|
||||
mutex_unlock(&info->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tca9539_raw_rd(
|
||||
static int tca9539_rd(
|
||||
struct cdi_mgr_priv *info, unsigned int offset, u8 *val)
|
||||
{
|
||||
int ret = -ENODEV;
|
||||
u8 data[2];
|
||||
size_t size = 1;
|
||||
struct i2c_msg i2cmsg[2];
|
||||
|
||||
dev_dbg(info->dev, "%s\n", __func__);
|
||||
mutex_lock(&info->mutex);
|
||||
|
||||
if (info->tca9539.reg_len == 2) {
|
||||
data[0] = (u8)((offset >> 8) & 0xff);
|
||||
data[1] = (u8)(offset & 0xff);
|
||||
} else if (info->tca9539.reg_len == 1)
|
||||
data[0] = (u8)(offset & 0xff);
|
||||
ret = tca9539_raw_rd(info->dev, &info->tca9539, offset, val);
|
||||
|
||||
i2cmsg[0].addr = info->tca9539.addr;
|
||||
i2cmsg[0].len = info->tca9539.reg_len;
|
||||
i2cmsg[0].buf = (__u8 *)data;
|
||||
i2cmsg[0].flags = I2C_M_NOSTART;
|
||||
|
||||
i2cmsg[1].addr = info->tca9539.addr;
|
||||
i2cmsg[1].flags = I2C_M_RD;
|
||||
i2cmsg[1].len = size;
|
||||
i2cmsg[1].buf = (__u8 *)val;
|
||||
|
||||
ret = i2c_transfer(info->tca9539.adap, i2cmsg, 2);
|
||||
if (ret > 0)
|
||||
ret = 0;
|
||||
mutex_unlock(&info->mutex);
|
||||
|
||||
return ret;
|
||||
@@ -901,16 +824,16 @@ static int cdi_mgr_open(struct inode *inode, struct file *file)
|
||||
"%s: failed to wait for the semaphore\n",
|
||||
__func__);
|
||||
if (cdi_mgr->cim_ver == 1U) { /* P3714 A01 */
|
||||
if (tca9539_raw_rd(cdi_mgr, 0x02, &val) != 0)
|
||||
if (tca9539_rd(cdi_mgr, 0x02, &val) != 0)
|
||||
return -EFAULT;
|
||||
val |= (0x10 << cdi_mgr->tca9539.power_port);
|
||||
if (tca9539_raw_wr(cdi_mgr, 0x02, val) != 0)
|
||||
if (tca9539_wr(cdi_mgr, 0x02, val) != 0)
|
||||
return -EFAULT;
|
||||
} else if (cdi_mgr->cim_ver == 2U) { /* P3714 A02 */
|
||||
if (tca9539_raw_rd(cdi_mgr, 0x03, &val) != 0)
|
||||
if (tca9539_rd(cdi_mgr, 0x03, &val) != 0)
|
||||
return -EFAULT;
|
||||
val |= (0x1 << cdi_mgr->tca9539.power_port);
|
||||
if (tca9539_raw_wr(cdi_mgr, 0x03, val) != 0)
|
||||
if (tca9539_wr(cdi_mgr, 0x03, val) != 0)
|
||||
return -EFAULT;
|
||||
}
|
||||
up(&tca9539_sem);
|
||||
@@ -933,16 +856,16 @@ static int cdi_mgr_release(struct inode *inode, struct file *file)
|
||||
"%s: failed to wait for the semaphore\n",
|
||||
__func__);
|
||||
if (cdi_mgr->cim_ver == 1U) { /* P3714 A01 */
|
||||
if (tca9539_raw_rd(cdi_mgr, 0x02, &val) != 0)
|
||||
if (tca9539_rd(cdi_mgr, 0x02, &val) != 0)
|
||||
return -EFAULT;
|
||||
val &= ~(0x10 << cdi_mgr->tca9539.power_port);
|
||||
if (tca9539_raw_wr(cdi_mgr, 0x02, val) != 0)
|
||||
if (tca9539_wr(cdi_mgr, 0x02, val) != 0)
|
||||
return -EFAULT;
|
||||
} else if (cdi_mgr->cim_ver == 2U) { /* P3714 A02 */
|
||||
if (tca9539_raw_rd(cdi_mgr, 0x03, &val) != 0)
|
||||
if (tca9539_rd(cdi_mgr, 0x03, &val) != 0)
|
||||
return -EFAULT;
|
||||
val &= ~(0x1 << cdi_mgr->tca9539.power_port);
|
||||
if (tca9539_raw_wr(cdi_mgr, 0x03, val) != 0)
|
||||
if (tca9539_wr(cdi_mgr, 0x03, val) != 0)
|
||||
return -EFAULT;
|
||||
}
|
||||
up(&tca9539_sem);
|
||||
@@ -1242,7 +1165,7 @@ static int cdi_mgr_suspend(struct device *dev)
|
||||
if (cdi_mgr->tca9539.enable) {
|
||||
reg_addr = CDI_MGR_TCA9539_BASE_REG_ADDR;
|
||||
while (reg_addr < CDI_MGR_TCA9539_REGISTER_COUNT) {
|
||||
rc = tca9539_raw_rd(cdi_mgr, reg_addr,
|
||||
rc = tca9539_rd(cdi_mgr, reg_addr,
|
||||
&cdi_mgr->pre_suspend_tca9539_regvals[reg_addr]);
|
||||
if (rc != 0) {
|
||||
dev_err(dev, "%s: tca9539_raw_rd failed reading reg[0x%x]\n",
|
||||
@@ -1276,7 +1199,7 @@ static int cdi_mgr_resume(struct device *dev)
|
||||
if (cdi_mgr->tca9539.enable) {
|
||||
reg_addr = CDI_MGR_TCA9539_BASE_REG_ADDR;
|
||||
while (reg_addr < CDI_MGR_TCA9539_REGISTER_COUNT) {
|
||||
rc = tca9539_raw_wr(cdi_mgr, reg_addr,
|
||||
rc = tca9539_wr(cdi_mgr, reg_addr,
|
||||
cdi_mgr->pre_suspend_tca9539_regvals[reg_addr]);
|
||||
if (rc != 0) {
|
||||
dev_err(dev, "%s: tca9539_raw_wr failed setting reg[0x%x] = 0x%x\n",
|
||||
@@ -1689,27 +1612,27 @@ static int cdi_mgr_probe(struct platform_device *pdev)
|
||||
/* the registers in TCA9539 */
|
||||
/* Use the IO expander to control PWDN signals */
|
||||
if (cdi_mgr->cim_ver == 1U) { /* P3714 A01 */
|
||||
if (tca9539_raw_wr(cdi_mgr, 0x6, 0x0E) != 0) {
|
||||
if (tca9539_wr(cdi_mgr, 0x6, 0x0E) != 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"%s: ERR %d: TCA9539: Failed to select PWDN signal source\n",
|
||||
__func__, err);
|
||||
goto err_probe;
|
||||
}
|
||||
/* Output low for AGGA/B/C/D_PWRDN */
|
||||
if (tca9539_raw_wr(cdi_mgr, 0x2, 0x0E) != 0) {
|
||||
if (tca9539_wr(cdi_mgr, 0x2, 0x0E) != 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"%s: ERR %d: TCA9539: Failed to set the output level\n",
|
||||
__func__, err);
|
||||
goto err_probe;
|
||||
}
|
||||
} else if (cdi_mgr->cim_ver == 2U) { /* P3714 A02 */
|
||||
if (tca9539_raw_wr(cdi_mgr, 0x6, 0xC0) != 0) {
|
||||
if (tca9539_wr(cdi_mgr, 0x6, 0xC0) != 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"%s: ERR %d: TCA9539: Failed to select FS selection signal source\n",
|
||||
__func__, err);
|
||||
goto err_probe;
|
||||
}
|
||||
if (tca9539_raw_wr(cdi_mgr, 0x7, 0x70) != 0) {
|
||||
if (tca9539_wr(cdi_mgr, 0x7, 0x70) != 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"%s: ERR %d: TCA9539: Failed to select PWDN signal source\n",
|
||||
__func__, err);
|
||||
@@ -1722,7 +1645,7 @@ static int cdi_mgr_probe(struct platform_device *pdev)
|
||||
cdi_mgr->cim_frsync[0],
|
||||
cdi_mgr->cim_frsync[1],
|
||||
cdi_mgr->cim_frsync[2]);
|
||||
if (tca9539_raw_wr(cdi_mgr, 0x2,
|
||||
if (tca9539_wr(cdi_mgr, 0x2,
|
||||
(cdi_mgr->cim_frsync[2] << 4) |
|
||||
(cdi_mgr->cim_frsync[1] << 2) |
|
||||
(cdi_mgr->cim_frsync[0])) < 0) {
|
||||
@@ -1732,7 +1655,7 @@ static int cdi_mgr_probe(struct platform_device *pdev)
|
||||
goto err_probe;
|
||||
}
|
||||
/* Output low for AGGA/B/C/D_PWRDN */
|
||||
if (tca9539_raw_wr(cdi_mgr, 0x3, 0x00) != 0) {
|
||||
if (tca9539_wr(cdi_mgr, 0x3, 0x00) != 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"%s: ERR %d: TCA9539: Failed to set the output level\n",
|
||||
__func__, err);
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#define CDI_DEV_IOCTL_RW _IOW('o', 1, struct cdi_dev_package)
|
||||
#define CDI_DEV_IOCTL_GET_PWR_INFO _IOW('o', 2, struct cdi_dev_pwr_ctrl_info)
|
||||
#define CDI_DEV_IOCTL_FRSYNC_MUX _IOW('o', 3, struct cdi_dev_fsync_mux)
|
||||
|
||||
#define DES_PWR_NVCCP 0U
|
||||
#define DES_PWR_GPIO 1U
|
||||
@@ -27,6 +28,11 @@ struct __attribute__ ((__packed__)) cdi_dev_pwr_ctrl_info {
|
||||
__u8 cam_pwr_links[MAX_POWER_LINKS_PER_BLOCK];
|
||||
};
|
||||
|
||||
struct cdi_dev_fsync_mux {
|
||||
__s8 mux_sel;
|
||||
__s8 cam_grp;
|
||||
};
|
||||
|
||||
struct __attribute__ ((__packed__)) cdi_dev_package {
|
||||
__u16 offset;
|
||||
__u16 offset_len;
|
||||
|
||||
Reference in New Issue
Block a user