input: add touch sensor driver.

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>
This commit is contained in:
jinrong.liao
2018-08-29 12:21:49 +08:00
parent 5c89dd620f
commit a4625c4ac3
11 changed files with 384 additions and 1 deletions

View File

@@ -0,0 +1,6 @@
cy8c4014_08: cy8c4014_08@08 {
compatible = "cy8c4014";
#sound-dai-cells = <0>;
reg = <0x8>;
status = "okay";
};

View 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

View File

@@ -983,6 +983,12 @@
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>;

View File

@@ -803,6 +803,12 @@
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>;

View 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

View 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

View 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/

View File

@@ -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

View File

@@ -0,0 +1,5 @@
#
# Makefile for the sensor drivers.
#
obj-$(CONFIG_AMLOGIC_SENSOR_CY8C4014) += cy8c4014.o

View File

@@ -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);

View 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;