Files
linux-nv-oot/drivers/media/i2c/max96712.c
Ankur Pawar c9858e1282 media: add ar0234 sensor driver
Add ar0234 camera sensor driver code,
max96712 GMSL serializer code, mode tables
and makefile changes. These drivers are copied
from K5.10 camera driver repo. Changes include
svcacv warning fix and eeprom read status is
ignored due to bug 4064490.

Bug 3583587
Bug 4064490

Change-Id: I7ea0ecf959caccafd283c8db5fb7c3be912cf8bb
Signed-off-by: Ankur Pawar <ankurp@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2868422
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
2023-04-14 15:45:38 -07:00

275 lines
6.1 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* max96712.c - max96712 IO Expander driver
*
* Copyright (c) 2016-2023, NVIDIA CORPORATION & AFFILIATES. All Rights Reserved.
*/
/* #define DEBUG */
#include <linux/seq_file.h>
#include <linux/debugfs.h>
#include <media/camera_common.h>
#include <linux/module.h>
struct max96712 {
struct i2c_client *i2c_client;
struct regmap *regmap;
const char *channel;
};
static struct max96712 *global_priv[4];
int max96712_write_reg_Dser(int slaveAddr, int channel, u16 addr, u8 val);
int max96712_read_reg_Dser(int slaveAddr, int channel, u16 addr, unsigned int *val);
int max96712_write_reg_Dser(int slaveAddr, int channel,
u16 addr, u8 val)
{
struct i2c_client *i2c_client = NULL;
int bak = 0;
int err;
/* unsigned int ival = 0; */
if (channel > 3 || channel < 0 || global_priv[channel] == NULL)
return -1;
i2c_client = global_priv[channel]->i2c_client;
bak = i2c_client->addr;
i2c_client->addr = slaveAddr / 2;
err = regmap_write(global_priv[channel]->regmap, addr, val);
i2c_client->addr = bak;
if (err) {
dev_err(&i2c_client->dev, "%s: addr = 0x%x, val = 0x%x\n",
__func__, addr, val);
return -1;
}
return 0;
}
EXPORT_SYMBOL(max96712_write_reg_Dser);
int max96712_read_reg_Dser(int slaveAddr, int channel,
u16 addr, unsigned int *val)
{
struct i2c_client *i2c_client = NULL;
int bak = 0;
int err;
if (channel > 3 || channel < 0 || global_priv[channel] == NULL)
return -1;
i2c_client = global_priv[channel]->i2c_client;
bak = i2c_client->addr;
i2c_client->addr = slaveAddr / 2;
err = regmap_read(global_priv[channel]->regmap, addr, val);
i2c_client->addr = bak;
if (err) {
dev_err(&i2c_client->dev, "%s: addr = 0x%x, val = 0x%x\n",
__func__, addr, *val);
return -1;
}
return 0;
}
EXPORT_SYMBOL(max96712_read_reg_Dser);
static int max96712_read_reg(struct max96712 *priv,
u16 addr, unsigned int *val)
{
struct i2c_client *i2c_client = priv->i2c_client;
int err;
err = regmap_read(priv->regmap, addr, val);
if (err)
dev_err(&i2c_client->dev, "%s:i2c read failed, 0x%x = %x\n",
__func__, addr, *val);
return err;
}
static int max96712_stats_show(struct seq_file *s, void *data)
{
return 0;
}
static int max96712_debugfs_open(struct inode *inode, struct file *file)
{
return single_open(file, max96712_stats_show, inode->i_private);
}
static ssize_t max96712_debugfs_write(struct file *s,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct max96712 *priv =
((struct seq_file *)s->private_data)->private;
struct i2c_client *i2c_client = priv->i2c_client;
char buf[255];
int buf_size;
int val = 0;
if (!user_buf || count <= 1)
return -EFAULT;
memset(buf, 0, sizeof(buf));
buf_size = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, buf_size))
return -EFAULT;
if (buf[0] == 'd') {
dev_info(&i2c_client->dev, "%s, set daymode\n", __func__);
max96712_read_reg(priv, 0x0010, &val);
return count;
}
if (buf[0] == 'n') {
dev_info(&i2c_client->dev, "%s, set nightmode\n", __func__);
return count;
}
return count;
}
static const struct file_operations max96712_debugfs_fops = {
.open = max96712_debugfs_open,
.read = seq_read,
.write = max96712_debugfs_write,
.llseek = seq_lseek,
.release = single_release,
};
static int max96712_debugfs_init(const char *dir_name,
struct dentry **d_entry,
struct dentry **f_entry,
struct max96712 *priv)
{
struct dentry *dp, *fp;
char dev_name[20];
struct i2c_client *i2c_client = priv->i2c_client;
struct device_node *np = i2c_client->dev.of_node;
int err = 0;
int index = 0;
if (np) {
err = of_property_read_string(np, "channel", &priv->channel);
if (err)
dev_err(&i2c_client->dev, "channel not found\n");
err = snprintf(dev_name, sizeof(dev_name), "max96712_%s", priv->channel);
if (err < 0)
return -EINVAL;
}
index = priv->channel[0] - 'a';
if (index < 0)
return -EINVAL;
global_priv[index] = priv;
dev_dbg(&i2c_client->dev, "%s: index %d\n", __func__, index);
dp = debugfs_create_dir(dev_name, NULL);
if (dp == NULL) {
dev_err(&i2c_client->dev, "%s: debugfs create dir failed\n",
__func__);
return -ENOMEM;
}
fp = debugfs_create_file("max96712", 0644, dp, priv,
&max96712_debugfs_fops);
if (!fp) {
dev_err(&i2c_client->dev, "%s: debugfs create file failed\n",
__func__);
debugfs_remove_recursive(dp);
return -ENOMEM;
}
if (d_entry)
*d_entry = dp;
if (f_entry)
*f_entry = fp;
return 0;
}
static struct regmap_config max96712_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
.cache_type = REGCACHE_RBTREE,
};
static int max96712_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct max96712 *priv;
int err = 0;
dev_info(&client->dev, "%s: enter\n", __func__);
priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
priv->i2c_client = client;
priv->regmap = devm_regmap_init_i2c(priv->i2c_client,
&max96712_regmap_config);
if (IS_ERR(priv->regmap)) {
dev_err(&client->dev,
"regmap init failed: %ld\n", PTR_ERR(priv->regmap));
return -ENODEV;
}
err = max96712_debugfs_init(NULL, NULL, NULL, priv);
if (err)
return err;
/*set daymode by fault*/
dev_info(&client->dev, "%s: success\n", __func__);
return err;
}
#if (KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE)
static int max96712_remove(struct i2c_client *client)
#else
static void max96712_remove(struct i2c_client *client)
#endif
{
if (client != NULL) {
i2c_unregister_device(client);
client = NULL;
}
#if (KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE)
return 0;
#endif
}
static const struct i2c_device_id max96712_id[] = {
{ "max96712", 0 },
{ },
};
static const struct of_device_id max96712_of_match[] = {
{ .compatible = "nvidia,max96712", },
{ },
};
MODULE_DEVICE_TABLE(i2c, max96712_id);
static struct i2c_driver max96712_i2c_driver = {
.driver = {
.name = "max96712",
.owner = THIS_MODULE,
},
.probe = max96712_probe,
.remove = max96712_remove,
.id_table = max96712_id,
};
module_i2c_driver(max96712_i2c_driver);
MODULE_DESCRIPTION("IO Expander driver max96712");
MODULE_AUTHOR("NVIDIA Corporation");
MODULE_LICENSE("GPL v2");