544 lines
16 KiB
C
Executable File
544 lines
16 KiB
C
Executable File
#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
|
||
|