]> rtime.felk.cvut.cz Git - hercules2020/nv-tegra/linux-4.4.git/commitdiff
media:platform:tegra: Port camera_gpio to k4.4
authorWenjia Zhou <wenjiaz@nvidia.com>
Wed, 15 Jun 2016 23:32:31 +0000 (16:32 -0700)
committerWenjia Zhou <wenjiaz@nvidia.com>
Mon, 27 Jun 2016 20:36:46 +0000 (13:36 -0700)
Bug 1778427

Change-Id: I2de873892cb64363a313cf7b71574f1d58cbf60e
Signed-off-by: Wenjia Zhou <wenjiaz@nvidia.com>
drivers/media/platform/tegra/camera/Makefile
drivers/media/platform/tegra/camera/camera_gpio.c [new file with mode: 0644]
drivers/media/platform/tegra/camera/camera_gpio.h [new file with mode: 0644]

index cd2981b5e8d9318661a2d4e1cf3010881bdf83d5..5e2ab04b7897529280b13754d5df35d89e057b1d 100644 (file)
@@ -3,4 +3,4 @@ ccflags-y += -I../nvhost/drivers/video/tegra/host
 ccflags-y += -Idrivers/video/tegra/camera
 ccflags-y += -Werror
 
-obj-y += camera_common.o mc_common.o core.o channel.o graph.o
+obj-y += camera_common.o mc_common.o core.o channel.o graph.o camera_gpio.o
diff --git a/drivers/media/platform/tegra/camera/camera_gpio.c b/drivers/media/platform/tegra/camera/camera_gpio.c
new file mode 100644 (file)
index 0000000..fcd53e3
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * virtual.c - Camera GPIO driver
+ *
+ * Copyright (c) 2014-2015, NVIDIA CORPORATION.  All rights reserved.
+
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/list.h>
+#include <linux/debugfs.h>
+#include <linux/i2c.h>
+#include <linux/slab.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 i2c_client *client,
+                       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(&client->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(&client->dev, "%s: memory low!\n", __func__);
+               mutex_unlock(&g_mutex);
+               return -EFAULT;
+       }
+
+       dev_dbg(&client->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 i2c_client *client,
+                       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(&client->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 i2c_client *client,
+                       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(&client->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(&client->dev, "%s %u %d\n",
+                                        __func__, pin_num, pin_val);
+                       }
+               }
+               mutex_unlock(&next_gpio->mutex);
+       }
+
+       if (!found)
+               dev_dbg(&client->dev,
+                        "WARNING %s: gpio %u not in list\n",
+                        __func__, pin_num);
+
+       return err; /* return value written or error */
+}
+EXPORT_SYMBOL(cam_gpio_ctrl);
diff --git a/drivers/media/platform/tegra/camera/camera_gpio.h b/drivers/media/platform/tegra/camera/camera_gpio.h
new file mode 100644 (file)
index 0000000..b388e17
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
+
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __CAMERA_GPIO_H__
+#define __CAMERA_GPIO_H__
+
+int cam_gpio_register(struct i2c_client *client,
+                       unsigned pin_num);
+
+void cam_gpio_deregister(struct i2c_client *client,
+                       unsigned pin_num);
+
+int cam_gpio_ctrl(struct i2c_client *client,
+                       unsigned pin_num, int ref_inc, bool active_high);
+
+#endif
+/* __CAMERA_GPIO_H__ */