input: add touch sensor driver.
authorjinrong.liao <jinrong.liao@amlogic.com>
Wed, 29 Aug 2018 04:21:49 +0000 (12:21 +0800)
committerjinrong.liao <jinrong.liao@amlogic.com>
Thu, 30 Aug 2018 12:40:01 +0000 (20:40 +0800)
PD#172287: this commit changes mainly for GVA

1) add sensor cy8c4014 driver.

Change-Id: Ic1ed6cf2a42e2286e4860946d89091a3dd524ef8
Signed-off-by: jinrong.liao <jinrong.liao@amlogic.com>
Documentation/devicetree/bindings/amlogic/input/cy8c4014_i2c.txt [new file with mode: 0644]
MAINTAINERS
arch/arm64/boot/dts/amlogic/axg_s400_v03gva.dts
arch/arm64/boot/dts/amlogic/axg_s420_v03gva.dts
arch/arm64/configs/meson64_smarthome_defconfig
drivers/amlogic/input/Kconfig
drivers/amlogic/input/Makefile
drivers/amlogic/input/sensor/Kconfig [new file with mode: 0644]
drivers/amlogic/input/sensor/Makefile [new file with mode: 0644]
drivers/amlogic/input/sensor/cy8c4014.c [new file with mode: 0644]
drivers/amlogic/ledring/aml-pca9557.c

diff --git a/Documentation/devicetree/bindings/amlogic/input/cy8c4014_i2c.txt b/Documentation/devicetree/bindings/amlogic/input/cy8c4014_i2c.txt
new file mode 100644 (file)
index 0000000..20c5222
--- /dev/null
@@ -0,0 +1,6 @@
+cy8c4014_08: cy8c4014_08@08 {
+       compatible = "cy8c4014";
+       #sound-dai-cells = <0>;
+       reg = <0x8>;
+       status = "okay";
+};
index 37cb69b..e5bf092 100644 (file)
@@ -14618,3 +14618,5 @@ AMLOGIC SYSTEM AS ROOT
 M:     Renjun Xu  <renjun.xu@amlogic.com>
 F:      arch/arm64/boot/dts/amlogic/axg_s400_v03gva.dts
 F:      arch/arm64/boot/dts/amlogic/axg_s420_v03gva.dts
+F:     Documentation/devicetree/bindings/input/cy8c4014_i2c.txt
+F:     drivers/amlogic/input/sensor/cy8c4014.c
index 7d76763..c9311bf 100644 (file)
              reg = <0x13>;
              status = "disable";
        };
+       cy8c4014_08: cy8c4014_08@08 {
+            compatible = "cy8c4014";
+            #sound-dai-cells = <0>;
+            reg = <0x8>;
+            status = "okay";
+       };
        is31fl3236a: is31f3236a@0x78 {
                compatible = "issi,is31fl3236";
                reg = <0x3c>;
index 9ec2416..f55e35e 100644 (file)
              reg = <0x13>;
              status = "disable";
        };
+       cy8c4014_08: cy8c4014_08@08 {
+            compatible = "cy8c4014";
+            #sound-dai-cells = <0>;
+            reg = <0x8>;
+            status = "okay";
+       };
        is31fl3236a: is31f3236a@0x78 {
                compatible = "issi,is31fl3236";
                reg = <0x3c>;
index 51760ad..46fe2d4 100644 (file)
@@ -311,6 +311,8 @@ CONFIG_AMLOGIC_IIO=y
 CONFIG_AMLOGIC_SARADC=y
 CONFIG_AMLOGIC_DDR_WINDOW_TOOL=m
 CONFIG_AMLOGIC_LEDRING=y
+CONFIG_AMLOGIC_SENSOR=y
+CONFIG_AMLOGIC_SENSOR_CY8C4014=y
 CONFIG_AMLOGIC_GPIO_IRQ=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
index 5e0685b..47317b0 100644 (file)
@@ -17,5 +17,8 @@ source "drivers/amlogic/input/keyboard/Kconfig"
 source "drivers/amlogic/input/remote/Kconfig"
 
 source "drivers/amlogic/input/touchscreen/Kconfig"
+
+source "drivers/amlogic/input/sensor/Kconfig"
+
 endif
 
index ae6f8ab..3ea361c 100644 (file)
@@ -11,3 +11,5 @@ obj-$(CONFIG_AMLOGIC_INPUT_KEYBOARD) += keyboard/
 obj-$(CONFIG_AMLOGIC_REMOTE) += remote/
 
 obj-$(CONFIG_AMLOGIC_TOUCHSCREEN) += touchscreen/
+
+obj-$(CONFIG_AMLOGIC_SENSOR) += sensor/
diff --git a/drivers/amlogic/input/sensor/Kconfig b/drivers/amlogic/input/sensor/Kconfig
new file mode 100644 (file)
index 0000000..f0f4214
--- /dev/null
@@ -0,0 +1,21 @@
+menuconfig AMLOGIC_SENSOR
+       bool "Sensor devices"
+       ---help---
+         Say Y here to get to see options for sensor device drivers from
+         all categories. This option alone does not add any kernel code.
+
+         If you say N,all options in this submenu will be skipped and disabled.
+
+if AMLOGIC_SENSOR
+
+config AMLOGIC_SENSOR_CY8C4014
+       tristate "cy8c4014 sensor driver"
+       depends on I2C
+       default n
+       help
+         Say yes here to support Cypress cy8c4014 sensor and proximity
+         sensor
+         Say yes here to support Cypress cy8c4014 sensor and proximity
+         sensor
+
+endif # SENSOR_DEVICES
diff --git a/drivers/amlogic/input/sensor/Makefile b/drivers/amlogic/input/sensor/Makefile
new file mode 100644 (file)
index 0000000..51c18f9
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the sensor drivers.
+#
+obj-$(CONFIG_AMLOGIC_SENSOR_CY8C4014)  += cy8c4014.o
+
diff --git a/drivers/amlogic/input/sensor/cy8c4014.c b/drivers/amlogic/input/sensor/cy8c4014.c
new file mode 100644 (file)
index 0000000..d1600b4
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * drivers/amlogic/input/sensor/cy8c4014.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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.
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+
+
+#define DRV_VERSION            "1.0.0.0"
+#define CY8C4014_DEV_NAME      "cy8c4014"
+#define CY8C4014_SCHE_DELAY    200
+#define CY8C4014_ADDR  0x8
+
+struct cy8c4014_data {
+       struct delayed_work work;
+       struct input_dev *input_dev;
+       struct i2c_client *i2c_client;
+       int  delay;
+       int  enable;
+       struct mutex mutex;
+};
+struct cy8c4014_data *cy8c4014_data;
+static struct i2c_driver cy8c4014_driver;
+
+static int cy8c4014_reset(struct i2c_client *client)
+{
+       return 0;
+}
+
+int cy8c4014_read(struct i2c_client *dev, int add, uint8_t *val)
+{
+       int ret;
+       uint8_t buf[2] = {};
+       struct i2c_msg msg[] = {
+               {
+                       .addr  = CY8C4014_ADDR,
+                       .flags = 0,
+                       .len   = sizeof(buf),
+                       .buf   = buf,
+               },
+               {
+                       .addr  = CY8C4014_ADDR,
+                       .flags = I2C_M_RD,
+                       .len   = 1,
+                       .buf   = val,
+               }
+       };
+
+
+       buf[0] = add & 0xff;
+       buf[1] = (add >> 8) & 0x0f;
+       ret = i2c_transfer(dev->adapter, msg, 2);
+       if (ret < 0) {
+               pr_info("%s: i2c transfer failed, ret:%d\n", __func__, ret);
+               return ret;
+       }
+       return 0;
+}
+
+static void cy8c4014_schedwork(struct work_struct *work)
+{
+       unsigned long delay = msecs_to_jiffies(cy8c4014_data->delay);
+       struct input_dev *input_dev = cy8c4014_data->input_dev;
+       uint8_t x = 0;
+       /*uint8_t y = 0;*/
+
+       cy8c4014_read(cy8c4014_data->i2c_client, 0x00, &x);
+       /*cy8c4014_read(cy8c4014_data->i2c_client,0x01,&y);*/
+       if (x != 0xFF)
+               input_report_abs(input_dev, ABS_X, x);
+       /*if(y != 0xFF)*/
+               /*input_report_abs(input_dev, ABS_Y, y);*/
+       input_sync(input_dev);
+       schedule_delayed_work(&cy8c4014_data->work, delay);
+}
+
+static ssize_t cy8c4014_enable_show(struct device *dev,
+                                 struct device_attribute *attr, char *buf)
+{
+       int ret = 0;
+
+       ret = sprintf(buf, "cy8c4014 sensor Auto Enable = %d\n",
+                       cy8c4014_data->enable);
+
+       return ret;
+}
+
+static int cy8c4014_sensor_enable(void)
+{
+       int ret = 0;
+
+       unsigned long delay = msecs_to_jiffies(cy8c4014_data->delay);
+
+       if (cy8c4014_data->enable == 1)
+               return ret;
+
+       mutex_lock(&cy8c4014_data->mutex);
+
+       schedule_delayed_work(&cy8c4014_data->work, delay);
+       cy8c4014_data->enable = 1;
+
+       mutex_unlock(&cy8c4014_data->mutex);
+
+       return ret;
+}
+
+static int cy8c4014_sensor_disable(void)
+{
+       int ret = 0;
+
+       if (cy8c4014_data->enable == 0)
+               return ret;
+
+       mutex_lock(&cy8c4014_data->mutex);
+
+       cancel_delayed_work(&cy8c4014_data->work);
+       cy8c4014_data->enable = 0;
+
+       mutex_unlock(&cy8c4014_data->mutex);
+
+       return ret;
+}
+static ssize_t cy8c4014_enable_store(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t count)
+{
+       int ls_auto, ret;
+
+       ls_auto = -1;
+       ret = kstrtoint(buf, 10, &ls_auto);
+       if (ret == -1)
+               return -EINVAL;
+       if (ls_auto != 0 && ls_auto != 1)
+               return -EINVAL;
+
+       if (ls_auto)
+               cy8c4014_sensor_enable();
+       else
+               cy8c4014_sensor_disable();
+
+
+       return count;
+}
+
+static ssize_t cy8c4014_poll_delay_show(struct device *dev,
+                                 struct device_attribute *attr, char *buf)
+{
+       int ret = 0;
+
+       ret = sprintf(buf, "cy8c4014 sensor Poll Delay = %d ms\n",
+                       cy8c4014_data->delay);
+
+       return ret;
+}
+
+static ssize_t cy8c4014_poll_delay_store(struct device *dev,
+               struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       int new_delay, ret;
+
+       ret = kstrtoint(buf, 10, &new_delay);
+       if (ret == -1)
+               return -EINVAL;
+       pr_info("new delay = %d ms, old delay = %d ms\n",  new_delay,
+                       cy8c4014_data->delay);
+
+       cy8c4014_data->delay = new_delay;
+
+       if (cy8c4014_data->enable) {
+               cy8c4014_sensor_disable();
+               cy8c4014_sensor_enable();
+       }
+
+       return count;
+}
+
+static struct device_attribute dev_attr_cy8c4014_enable =
+__ATTR(enable, 0664, cy8c4014_enable_show,
+       cy8c4014_enable_store);
+
+static struct device_attribute dev_attr_cy8c4014_delay =
+__ATTR(delay, 0664, cy8c4014_poll_delay_show,
+       cy8c4014_poll_delay_store);
+
+static struct attribute *sensor_sysfs_attrs[] = {
+&dev_attr_cy8c4014_enable.attr,
+&dev_attr_cy8c4014_delay.attr,
+NULL
+};
+
+static struct attribute_group cy8c4014_attribute_group = {
+.attrs = sensor_sysfs_attrs,
+};
+
+static int cy8c4014_probe(struct i2c_client *client,
+               const struct i2c_device_id *id)
+{
+       int ret = 0;
+       struct input_dev *idev;
+       struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+
+       pr_info(" start cy8c4014 probe !!\n");
+
+       if (!i2c_check_functionality(adapter,
+               I2C_FUNC_SMBUS_WRITE_BYTE | I2C_FUNC_SMBUS_READ_BYTE_DATA)){
+               ret = -EIO;
+               return ret;
+       }
+
+       /* data memory allocation */
+       cy8c4014_data = kzalloc(sizeof(struct cy8c4014_data), GFP_KERNEL);
+       if (cy8c4014_data == NULL) {
+               ret = -ENOMEM;
+               return ret;
+       }
+       cy8c4014_data->i2c_client = client;
+
+       i2c_set_clientdata(client, cy8c4014_data);
+
+       cy8c4014_reset(cy8c4014_data->i2c_client);
+
+       INIT_DELAYED_WORK(&cy8c4014_data->work, cy8c4014_schedwork);
+       cy8c4014_data->delay = CY8C4014_SCHE_DELAY;
+
+       idev = input_allocate_device();
+       if (!idev) {
+               pr_alert("%s: cy8c4014 allocate input device failed.\n",
+                               __func__);
+               goto kfree_exit;
+       }
+
+       idev->name = CY8C4014_DEV_NAME;
+       idev->id.bustype = BUS_I2C;
+       input_set_capability(idev, EV_ABS, ABS_X);
+       input_set_capability(idev, EV_ABS, ABS_Y);
+       input_set_abs_params(idev, ABS_X, 0, 255, 0, 0);
+       input_set_abs_params(idev, ABS_Y, 0, 255, 0, 0);
+       cy8c4014_data->input_dev = idev;
+       input_set_drvdata(idev, cy8c4014_data);
+
+       ret = input_register_device(idev);
+       if (ret < 0) {
+               input_free_device(idev);
+               goto kfree_exit;
+       }
+
+       mutex_init(&cy8c4014_data->mutex);
+       /* register the attributes */
+       ret = sysfs_create_group(&idev->dev.kobj, &cy8c4014_attribute_group);
+       if (ret)
+               goto unregister_exit;
+
+       schedule_delayed_work(&cy8c4014_data->work, CY8C4014_SCHE_DELAY);
+       cy8c4014_data->enable = 1;
+       return ret;
+
+unregister_exit:
+       input_unregister_device(idev);
+       input_free_device(idev);
+
+kfree_exit:
+       kfree(cy8c4014_data);
+       return ret;
+}
+
+static int cy8c4014_remove(struct i2c_client *client)
+{
+       i2c_unregister_device(cy8c4014_data->i2c_client);
+       cancel_delayed_work(&cy8c4014_data->work);
+       kfree(cy8c4014_data);
+       return 0;
+}
+static const struct i2c_device_id cy8c4014_id[] = {
+       { CY8C4014_DEV_NAME, 0 },
+       { }
+};
+
+static struct i2c_driver cy8c4014_driver = {
+       .driver = {
+               .name   = CY8C4014_DEV_NAME,
+               .owner  = THIS_MODULE,
+       },
+       .probe = cy8c4014_probe,
+       .remove = cy8c4014_remove,
+       .id_table = cy8c4014_id,
+};
+
+static int __init cy8c4014_init(void)
+{
+       i2c_add_driver(&cy8c4014_driver);
+       return 0;
+}
+
+static void __exit cy8c4014_exit(void)
+{
+       i2c_del_driver(&cy8c4014_driver);
+}
+
+module_init(cy8c4014_init);
+module_exit(cy8c4014_exit);
+
+MODULE_AUTHOR("Amlogic");
+MODULE_DESCRIPTION("CYPRESS CY8C4014 driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
index 59cc6d0..53efaf1 100644 (file)
@@ -74,7 +74,7 @@ static struct _key_led {
        int mode;
 } *key_led_des;
 
-struct _key_des {
+static struct _key_des {
        char name[MAX_NAME_LEN];
        unsigned int key_val;
        int pin;