sdk-hwV1.3/lichee/linux-4.9/drivers/input/touchscreen/cst9220/hynitron_proximity.c

544 lines
16 KiB
C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef __HYNITRON_EX_FUN_H__
#define __HYNITRON_EX_FUN_H__
#include "hynitron_core.h"
#define MTK_PS_ENABLE 0
#define SPRD_PS_ENABLE 0
#define HYN_CAP_PROXIMITY_FARAWAY_VALUE 0xC0
#define HYN_CAP_PROXIMITY_NEAR_VALUE 0xE0
#define HYN_MUT_PROXIMITY_FARAWAY_VALUE 0x00
#define HYN_MUT_PROXIMITY_NEAR_VALUE 0x01
#if HYN_PSENSOR_EN
#if MTK_PS_ENABLE
#include <hwmsensor.h>
#include <hwmsen_dev.h>
#include <sensors_io.h>
#endif
#define TP_PS_DEVICE "ltr_558als"
#define TP_PS_INPUT_DEV "alps_pxy"
#define PROXIMITY_DEBUG(fmt,arg...) printk("<<hyn proximity>> "fmt"\n",##arg)
struct hynitron_ps_struct {
u8 proximity_enable ;
u8 proximity_enable_lock;
u8 proximity_detect_value ;
u8 suspend_flag;
/* kernel-4.14 do not wake_lock */
//struct wake_lock proximity_lock;
#if MTK_PS_ENABLE
struct hwmsen_object obj_ps;
#endif
struct class *firmware_class;
struct device *firmware_cmd_dev;
struct input_dev *ps_input_dev;
};
struct hynitron_ps_struct *hyn_proximity_data;
static int hyn_proximity_get_value(void);
/************************************************
MTKƽ̨:
´¥¿ØIC----°ó¶¨hwmsen_attach(ID_PROXIMITY)----Éϱ¨hwm_sensor_data
*************************************************/
#if MTK_PS_ENABLE
#define SENSOR_DELAY 0
#define SENSOR_ENABLE 0
#define SENSOR_GET_DATA 0
#define SENSOR_STATUS_ACCURACY_MEDIUM 0
void hyn_proximity_mtk_report(int proximity_value)
{
int err;
struct hwm_sensor_data sensor_data;
sensor_data.values[0] = proximity_value;
sensor_data.value_divide = 1;
sensor_data.status = SENSOR_STATUS_ACCURACY_MEDIUM;
if ((err = hwmsen_get_interrupt_data(ID_PROXIMITY, &sensor_data)))
{
PROXIMITY_DEBUG(" proxi call hwmsen_get_interrupt_data failed= %d\n", err);
}
}
static int hyn_proximiy_operate(void* self, uint32_t command, void* buff_in, int size_in,
void* buff_out, int size_out, int* actualout)
{
int err = 0;
int value;
PROXIMITY_DEBUG("[proxi]command = 0x%02X\n", command);
switch (command)
{
case SENSOR_DELAY:
if((!buff_in) || (size_in < sizeof(int))){
PROXIMITY_DEBUG("Set delay parameter error!\n");
err = -EINVAL;
}
// Do nothing
break;
case SENSOR_ENABLE:
if((!buff_in) || (size_in < sizeof(int))){
PROXIMITY_DEBUG("Enable sensor parameter error!\n");
err = -EINVAL;
}else{
value = *(int *)buff_in;
if(value){
if((hyn_proximity_enable(1) != 0)){
PROXIMITY_DEBUG("enable ps fail: %d\n", err);
return -1;
}
}else{
if((hyn_proximity_enable(0) != 0)){
PROXIMITY_DEBUG("disable ps fail: %d\n", err);
return -1;
}
}
}
break;
case SENSOR_GET_DATA:
if((!buff_out)){
PROXIMITY_DEBUG("get sensor data parameter error!\n");
err = -EINVAL;
}else{
hyn_proximity_readdata();
}
break;
default:
PROXIMITY_DEBUG("proxmy sensor operate function no this parameter %d!\n", command);
err = -1;
break;
}
return err;
}
void hyn_proximity_mtk_init(void)
{
int ret;
hyn_ts_data->client->obj_ps.polling = 0;//interrupt mode
hyn_ts_data->client->obj_ps.sensor_operate = hyn_proximiy_operate;
if((ret = hwmsen_attach(ID_PROXIMITY, &hyn_ts_data->client->obj_ps))){
PROXIMITY_DEBUG("proxi_hyn attach fail = %d\n", ret);
}else{
PROXIMITY_DEBUG("proxi_hyn attach ok = %d\n", ret);
}
}
#endif
/************************************************
Spreadtrumƽ̨:
´¥¿ØIC----´´½¨½Úµãproximity-----Éϱ¨ÊäÈëÉ豸½Ó½ü»òÕßÔ¶Àë
*************************************************/
#if SPRD_PS_ENABLE
static ssize_t show_proximity_sensor(struct device *dev, struct device_attribute *attr, char *buf)
{
PROXIMITY_DEBUG("show_proximity_sensor get prox state \n");
if(buf)
sprintf(buf, "proximity_enable is:%d, proximity_detect_value:%d.\n",hyn_proximity_data->proximity_enable ,hyn_proximity_data->proximity_detect_value);
return 0;
}
static ssize_t store_proximity_sensor(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
unsigned int on_off = simple_strtoul(buf, NULL, 10);
PROXIMITY_DEBUG("store_proximity_sensor buf=%d,size=%d,on_off=%d\n", *buf, size, on_off);
if((buf) && (size != 0)){
if (0 == on_off)
hyn_proximity_enable(0);
else if (1 == on_off)
hyn_proximity_enable(1);
}
return size;
}
static DEVICE_ATTR(proximity, S_IRUGO | S_IWUSR, show_proximity_sensor, store_proximity_sensor);
void hyn_proximity_sprd_report(int proximity_value)
{
input_report_abs(hyn_proximity_data->ps_input_dev, ABS_DISTANCE, proximity_value);
input_sync(hyn_proximity_data->ps_input_dev);
}
void hyn_proximity_sprd_init(void)
{
// node :/sys/class/sprd-tpd/device/proximity
hyn_ts_data->client->firmware_class = class_create(THIS_MODULE,"sprd-tpd");//client->name
if(IS_ERR(hyn_ts_data->client->firmware_class))
PROXIMITY_DEBUG("Failed to create class(firmware)!\n");
hyn_ts_data->client->firmware_cmd_dev = device_create(hyn_ts_data->client->firmware_class, NULL, 0, NULL, "device");//device
if(IS_ERR(hyn_ts_data->client->firmware_cmd_dev))
PROXIMITY_DEBUG("Failed to create device(firmware_cmd_dev)!\n");
if(device_create_file(hyn_ts_data->client->firmware_cmd_dev, &dev_attr_proximity) < 0){
PROXIMITY_DEBUG("Failed to create device file(%s)!\n", dev_attr_proximity.attr.name);
}
}
#endif
/************************************************************************
* Name: hyn_proximity_mode_show
* Brief: no
* Input: device, device attribute, char buf
* Output: no
* Return:
***********************************************************************/
static ssize_t hyn_proximity_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
{
int count;
u8 val = 0;
//struct i2c_client *client = container_of(dev, struct i2c_client, dev);
HYN_FUNC_ENTER();
mutex_lock(&hyn_ts_data->input_dev->mutex);
count = sprintf(buf, "proximity Mode: %s\n", hyn_proximity_data->proximity_enable ? "On" : "Off");
count += sprintf(buf + count, "Reg(0xD0) = %d\n", val);
mutex_unlock(&hyn_ts_data->input_dev->mutex);
HYN_FUNC_EXIT();
return count;
}
/************************************************************************
* Name: hyn_proximity_mode_store
* Brief: no
* Input: device, device attribute, char buf, char count
* Output: no
* Return:
***********************************************************************/
static ssize_t hyn_proximity_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
HYN_FUNC_ENTER();
mutex_lock(&hyn_ts_data->input_dev->mutex);
if (buf[0]==1)
{
HYN_INFO("[proximity]enable ");
hyn_proximity_data->proximity_enable = ENABLE;
}
else if (buf[0]==0)
{
HYN_INFO("[proximity]disable");
hyn_proximity_data->proximity_enable = DISABLE;
}
mutex_unlock(&hyn_ts_data->input_dev->mutex);
HYN_FUNC_EXIT();
return count;
}
/************************************************************************
* Name: hyn_proximity_buf_show
* Brief: no
* Input: device, device attribute, char buf
* Output: no
* Return:
***********************************************************************/
static ssize_t hyn_proximity_buf_show(struct device *dev, struct device_attribute *attr, char *buf)
{
int count;
HYN_FUNC_ENTER();
mutex_lock(&hyn_ts_data->input_dev->mutex);
count = snprintf(buf, PAGE_SIZE, "proximity: 0x%x\n", hyn_proximity_data->proximity_enable);
count += snprintf(buf + count, PAGE_SIZE, "proximity: %d\n", hyn_proximity_data->proximity_detect_value);
count += snprintf(buf + count, PAGE_SIZE, "proximity Buf:\n");
count += snprintf(buf + count, PAGE_SIZE, "\n");
mutex_unlock(&hyn_ts_data->input_dev->mutex);
HYN_FUNC_EXIT();
return count;
}
/************************************************************************
* Name: hyn_proximity_buf_store
* Brief: no
* Input: device, device attribute, char buf, char count
* Output: no
* Return:
***********************************************************************/
static ssize_t hyn_proximity_buf_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
/* place holder for future use */
return -EPERM;
}
/* sysfs proximity node
* read example: cat hyn_proximity_mode ---read proximity mode
* write example:echo 01 > hyn_proximity_mode ---write proximity mode to 01
*
*/
static DEVICE_ATTR (hyn_proximity_mode, S_IRUGO|S_IWUSR, hyn_proximity_mode_show, hyn_proximity_mode_store);
/*
* read example: cat hyn_proximity_buf ---read proximity buf
*/
static DEVICE_ATTR (hyn_proximity_buf, S_IRUGO|S_IWUSR, hyn_proximity_buf_show, hyn_proximity_buf_store);
static struct attribute *hyn_proximity_mode_attrs[] =
{
&dev_attr_hyn_proximity_mode.attr,
&dev_attr_hyn_proximity_buf.attr,
NULL,
};
static struct attribute_group hyn_proximity_group =
{
.attrs = hyn_proximity_mode_attrs,
};
int hyn_create_proximity_sysfs(struct i2c_client *client)
{
int ret = 0;
HYN_FUNC_ENTER();
if(!hyn_ts_data->k_obj)
return 0;
ret = sysfs_create_group(hyn_ts_data->k_obj, &hyn_proximity_group);
if ( ret != 0)
{
HYN_ERROR( "hyn_create_proximity_sysfs(sysfs) create failed!");
sysfs_remove_group(hyn_ts_data->k_obj, &hyn_proximity_group);
return ret;
}
HYN_FUNC_EXIT();
return 0;
}
int hyn_proximity_readdata(void)
{
int err;
HYN_FUNC_ENTER();
if (hyn_proximity_data->proximity_enable == 1)
{
err=hyn_proximity_get_value();
#if MTK_PS_ENABLE
hyn_proximity_mtk_report(hyn_proximity_data->proximity_detect_value);
#endif
#if SPRD_PS_ENABLE
hyn_proximity_sprd_report(hyn_proximity_data->proximity_detect_value);
#endif
}
HYN_FUNC_EXIT();
return err;
}
static int hyn_proximity_enable_real(int enable)
{
u8 state;
int ret = -1;
HYN_FUNC_ENTER();
if (enable){
state = ENABLE;
hyn_proximity_data->proximity_enable = ENABLE;
/* kernel-4.14 do not wake_lock */
//wake_lock(&hyn_proximity_data->proximity_lock);
PROXIMITY_DEBUG(" proximity function is on.\n");
}else{
if(hyn_proximity_data->suspend_flag) return 0;
state = DISABLE;
/* kernel-4.14 do not wake_lock */
//wake_unlock(&hyn_proximity_data->proximity_lock);
hyn_proximity_data->proximity_enable = DISABLE;
PROXIMITY_DEBUG(" proximity function is off.\n");
}
if(hyn_ts_data->config_chip_product_line==HYN_CHIP_PRODUCT_LINE_MUT_CAP){
u8 buf[3];
buf[0]=HYN_REG_MUT_PROXIMITY_EN>>8;
buf[1]=HYN_REG_MUT_PROXIMITY_EN&0xff;
buf[2]=state<<7;
ret=cst3xx_i2c_write(hyn_ts_data->client, buf, 3);
}else if(hyn_ts_data->config_chip_product_line==HYN_CHIP_PRODUCT_LINE_SEL_CAP){
ret = hyn_i2c_write_byte(hyn_ts_data->client, HYN_REG_CAP_PROXIMITY_EN, state);
}
PROXIMITY_DEBUG("proximity write state is 0x%02X\n", state);
HYN_FUNC_EXIT();
return 0;
}
static int hyn_proximity_get_value(void)
{
u8 proximity_status=0;
HYN_FUNC_ENTER();
if(hyn_ts_data->config_chip_product_line==HYN_CHIP_PRODUCT_LINE_MUT_CAP){
u8 buf[3];
buf[0]=HYN_REG_MUT_PROXIMITY_EN>>8;
buf[1]=HYN_REG_MUT_PROXIMITY_EN&0xff;
cst3xx_i2c_read_register(hyn_ts_data->client, buf, 1);
proximity_status=buf[0]&0x7f;
PROXIMITY_DEBUG("proximity value is 0x%02X\n", proximity_status);
if (proximity_status == HYN_MUT_PROXIMITY_FARAWAY_VALUE){
hyn_proximity_data->proximity_detect_value = 0;
}else if(proximity_status == HYN_MUT_PROXIMITY_NEAR_VALUE){
hyn_proximity_data->proximity_detect_value = 1;
}
}else if(hyn_ts_data->config_chip_product_line==HYN_CHIP_PRODUCT_LINE_SEL_CAP){
hyn_i2c_read_byte(hyn_ts_data->client, HYN_REG_CAP_PROXIMITY_OUTPUT_ADDRESS, &proximity_status);
PROXIMITY_DEBUG("proximity value is 0x%02X\n", proximity_status);
if (proximity_status == HYN_CAP_PROXIMITY_FARAWAY_VALUE){
hyn_proximity_data->proximity_detect_value = 0;
}else if(proximity_status == HYN_CAP_PROXIMITY_NEAR_VALUE){
hyn_proximity_data->proximity_detect_value = 1;
}
}
PROXIMITY_DEBUG("proximity_detect_value = %d\n", hyn_proximity_data->proximity_detect_value);
HYN_FUNC_EXIT();
return hyn_proximity_data->proximity_detect_value;
}
static int hyn_proximity_enable(int enable)
{
HYN_FUNC_ENTER();
PROXIMITY_DEBUG("proximity suspend_flag=0x%02X, enable= 0x%02X.\n",hyn_proximity_data->suspend_flag,enable );
if (hyn_proximity_data->suspend_flag && enable) {
}else{
hyn_proximity_enable_real(enable);
}
HYN_FUNC_EXIT();
return 0;
}
void hyn_proximity_suspend(void)
{
HYN_FUNC_ENTER();
hyn_proximity_data->suspend_flag++;
if (hyn_proximity_data->proximity_enable == 1) hyn_proximity_data->proximity_enable_lock = 1;
PROXIMITY_DEBUG("proximity suspend_flag=0x%02X, enable= 0x%02X,enable_lock = 0x%02X.\n",
hyn_proximity_data->suspend_flag,hyn_proximity_data->proximity_enable,hyn_proximity_data->proximity_enable_lock );
HYN_FUNC_EXIT();
}
void hyn_proximity_resume(void)
{
HYN_FUNC_ENTER();
hyn_proximity_data->suspend_flag = 0;
if (hyn_proximity_data->proximity_enable == 1){
if(hyn_proximity_data->proximity_enable_lock == 1){
hyn_proximity_data->proximity_enable_lock = 0;
PROXIMITY_DEBUG(" proximity_enable_lock. \n");
}
}
PROXIMITY_DEBUG("proximity suspend_flag=0x%02X, enable= 0x%02X,enable_lock = 0x%02X.\n",
hyn_proximity_data->suspend_flag,hyn_proximity_data->proximity_enable,hyn_proximity_data->proximity_enable_lock );
HYN_FUNC_EXIT();
}
void hyn_proximity_init(void)
{
int ret;
HYN_FUNC_ENTER();
/* malloc memory for global struct variable,init 0 */
hyn_proximity_data = kzalloc(sizeof(*hyn_proximity_data), GFP_KERNEL);
if (!hyn_proximity_data) {
PROXIMITY_DEBUG("proximity allocate memory for hyn_proximity_data fail");
return;
}
hyn_proximity_data->ps_input_dev = input_allocate_device();
if (!hyn_proximity_data->ps_input_dev)
{
PROXIMITY_DEBUG(" %s: input allocate device failed\n", __func__);
ret = -ENOMEM;
goto exit_input_dev_allocate_failed;
}
hyn_proximity_data->ps_input_dev->name = TP_PS_INPUT_DEV;
hyn_proximity_data->ps_input_dev->phys = TP_PS_INPUT_DEV;
hyn_proximity_data->ps_input_dev->id.bustype = BUS_I2C;
hyn_proximity_data->ps_input_dev->dev.parent = &hyn_ts_data->client->dev;
__set_bit(EV_ABS, hyn_proximity_data->ps_input_dev->evbit);
input_set_abs_params(hyn_proximity_data->ps_input_dev, ABS_DISTANCE, 0, 1, 0, 0);
//printk("ljl test : %s\n", __func__);
ret= input_register_device(hyn_proximity_data->ps_input_dev);
if (ret < 0)
{
PROXIMITY_DEBUG("%s: input device regist failed\n", __func__);
goto exit_input_register_failed;
}
hyn_create_proximity_sysfs(hyn_ts_data->client);
hyn_proximity_enable(0);
/* kernel-4.14 do not wake_lock */
//wake_lock_init(&hyn_proximity_data->proximity_lock, WAKE_LOCK_SUSPEND, "proximity wakelock");
#if MTK_PS_ENABLE
hyn_proximity_mtk_init();
#endif
#if SPRD_PS_ENABLE
hyn_proximity_sprd_init();
#endif
HYN_FUNC_EXIT();
return;
exit_input_dev_allocate_failed:
input_free_device(hyn_proximity_data->ps_input_dev );
exit_input_register_failed:
input_free_device(hyn_proximity_data->ps_input_dev);
if(!hyn_proximity_data) return;
kfree(hyn_proximity_data);
}
void hyn_proximity_exit(void)
{
HYN_FUNC_ENTER();
if(!hyn_ts_data->k_obj) return;
sysfs_remove_group(hyn_ts_data->k_obj, &hyn_proximity_group);
if(!hyn_proximity_data) return;
kfree(hyn_proximity_data);
//wake_lock_destroy(&hyn_proximity_data->proximity_lock); /* kernel-4.14 do not wake_lock */
HYN_FUNC_EXIT();
}
#endif
#endif