mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
Port camera drivers below from /kenrel/nvidia to /kernel/nvidia-oot as OOT modules: - Fusa-capture driver - Tegra V4L2 framework driver - vi/csi driver - tegra camera platform driver Change-Id: I390af27096425bb11e0934201dd1a90f001bb3fa Signed-off-by: Frank Chen <frankc@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2780698 Reviewed-by: FNU Raunak <fraunak@nvidia.com> Reviewed-by: Ankur Pawar <ankurp@nvidia.com> Reviewed-by: Shiva Dubey <sdubey@nvidia.com> GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
150 lines
3.1 KiB
C
150 lines
3.1 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* virtual.c - Camera GPIO driver
|
|
*
|
|
* Copyright (c) 2014-2022, NVIDIA CORPORATION. All rights reserved.
|
|
*/
|
|
|
|
#include <linux/list.h>
|
|
#include <linux/debugfs.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/device.h>
|
|
#include <linux/gpio.h>
|
|
|
|
#include "camera_gpio.h"
|
|
|
|
struct camera_gpio {
|
|
struct list_head list;
|
|
unsigned gpio_num;
|
|
struct mutex mutex;
|
|
atomic_t state_cnt;
|
|
atomic_t use_cnt;
|
|
};
|
|
|
|
static DEFINE_MUTEX(g_mutex);
|
|
static LIST_HEAD(cam_gpio_list);
|
|
|
|
int cam_gpio_register(struct device *dev,
|
|
unsigned pin_num) {
|
|
struct camera_gpio *new_gpio;
|
|
struct camera_gpio *next_gpio;
|
|
|
|
mutex_lock(&g_mutex);
|
|
|
|
|
|
list_for_each_entry(next_gpio, &cam_gpio_list, list) {
|
|
if (next_gpio->gpio_num == pin_num) {
|
|
dev_dbg(dev,
|
|
"%s: gpio pin %u already registered.\n",
|
|
__func__, pin_num);
|
|
|
|
atomic_inc(&next_gpio->use_cnt);
|
|
|
|
mutex_unlock(&g_mutex);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* gpio is not present in the cam_gpio_list, add it */
|
|
new_gpio = kzalloc(sizeof(*new_gpio), GFP_KERNEL);
|
|
if (!new_gpio) {
|
|
dev_err(dev, "%s: memory low!\n", __func__);
|
|
mutex_unlock(&g_mutex);
|
|
return -EFAULT;
|
|
}
|
|
|
|
dev_dbg(dev, "%s: adding cam gpio %u\n",
|
|
__func__, pin_num);
|
|
|
|
new_gpio->gpio_num = pin_num;
|
|
mutex_init(&new_gpio->mutex);
|
|
atomic_inc(&new_gpio->use_cnt);
|
|
|
|
list_add(&new_gpio->list, &cam_gpio_list);
|
|
|
|
mutex_unlock(&g_mutex);
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(cam_gpio_register);
|
|
|
|
void cam_gpio_deregister(struct device *dev,
|
|
unsigned pin_num) {
|
|
struct camera_gpio *next_gpio;
|
|
|
|
mutex_lock(&g_mutex);
|
|
|
|
|
|
list_for_each_entry(next_gpio, &cam_gpio_list, list) {
|
|
if (next_gpio->gpio_num == pin_num) {
|
|
atomic_dec(&next_gpio->use_cnt);
|
|
|
|
if (atomic_read(&next_gpio->use_cnt) == 0) {
|
|
list_del(&next_gpio->list);
|
|
kfree(next_gpio);
|
|
|
|
dev_dbg(dev,
|
|
"%s: removing cam gpio %u\n",
|
|
__func__, pin_num);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
mutex_unlock(&g_mutex);
|
|
return;
|
|
}
|
|
EXPORT_SYMBOL(cam_gpio_deregister);
|
|
|
|
int cam_gpio_ctrl(struct device *dev,
|
|
unsigned pin_num, int val,
|
|
bool active_high) /* val: 0=deassert, 1=assert */
|
|
{
|
|
struct camera_gpio *next_gpio;
|
|
int err = -EINVAL;
|
|
int pin_val;
|
|
bool found = false;
|
|
|
|
list_for_each_entry(next_gpio, &cam_gpio_list, list) {
|
|
mutex_lock(&next_gpio->mutex);
|
|
if (next_gpio->gpio_num == pin_num) {
|
|
found = true;
|
|
|
|
if (!atomic_read(&next_gpio->state_cnt) &&
|
|
!val) {
|
|
dev_err(dev,
|
|
"%s: state cnt can't be < 0\n",
|
|
__func__);
|
|
mutex_unlock(&next_gpio->mutex);
|
|
return err;
|
|
}
|
|
|
|
if (val)
|
|
atomic_inc(&next_gpio->state_cnt);
|
|
else
|
|
atomic_dec(&next_gpio->state_cnt);
|
|
|
|
pin_val = active_high ? val : !val;
|
|
pin_val &= 1;
|
|
err = pin_val;
|
|
|
|
/* subtract val allows a 0 check to be
|
|
* used to indicate that gpio can be written to*/
|
|
if (atomic_read(&next_gpio->state_cnt) - val == 0) {
|
|
gpio_set_value_cansleep(pin_num, pin_val);
|
|
dev_dbg(dev, "%s %u %d\n",
|
|
__func__, pin_num, pin_val);
|
|
}
|
|
}
|
|
mutex_unlock(&next_gpio->mutex);
|
|
}
|
|
|
|
if (!found)
|
|
dev_dbg(dev,
|
|
"WARNING %s: gpio %u not in list\n",
|
|
__func__, pin_num);
|
|
|
|
return err; /* return value written or error */
|
|
}
|
|
EXPORT_SYMBOL(cam_gpio_ctrl);
|