273 lines
6.8 KiB
C
273 lines
6.8 KiB
C
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||
|
/*
|
||
|
* Copyright (C) 2016 MediaTek Inc.
|
||
|
*/
|
||
|
|
||
|
#include "focaltech_core.h"
|
||
|
|
||
|
/*****************************************************************************
|
||
|
* 2.Private constant and macro definitions using #define
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/*****************************************************************************
|
||
|
* 3.Private enumerations, structures and unions using typedef
|
||
|
*****************************************************************************/
|
||
|
enum _ex_mode {
|
||
|
MODE_GLOVE = 0,
|
||
|
MODE_COVER,
|
||
|
MODE_CHARGER,
|
||
|
};
|
||
|
|
||
|
/*****************************************************************************
|
||
|
* 4.Static variables
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/*****************************************************************************
|
||
|
* 5.Global variable or extern global variabls/functions
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/*****************************************************************************
|
||
|
* 6.Static function prototypes
|
||
|
*************************************************************************/
|
||
|
static int fts_ex_mode_switch(enum _ex_mode mode, u8 value)
|
||
|
{
|
||
|
int ret = 0;
|
||
|
u8 m_val = 0;
|
||
|
|
||
|
if (value)
|
||
|
m_val = 0x01;
|
||
|
else
|
||
|
m_val = 0x00;
|
||
|
|
||
|
switch (mode) {
|
||
|
case MODE_GLOVE:
|
||
|
ret = fts_write_reg(FTS_REG_GLOVE_MODE_EN, m_val);
|
||
|
if (ret < 0)
|
||
|
FTS_ERROR("MODE_GLOVE switch to %d fail", m_val);
|
||
|
|
||
|
break;
|
||
|
case MODE_COVER:
|
||
|
ret = fts_write_reg(FTS_REG_COVER_MODE_EN, m_val);
|
||
|
if (ret < 0)
|
||
|
FTS_ERROR("MODE_COVER switch to %d fail", m_val);
|
||
|
|
||
|
break;
|
||
|
case MODE_CHARGER:
|
||
|
ret = fts_write_reg(FTS_REG_CHARGER_MODE_EN, m_val);
|
||
|
if (ret < 0)
|
||
|
FTS_ERROR("MODE_CHARGER switch to %d fail", m_val);
|
||
|
|
||
|
break;
|
||
|
default:
|
||
|
FTS_ERROR("mode(%d) unsupport", mode);
|
||
|
ret = -EINVAL;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static ssize_t fts_glove_mode_show(struct device *dev,
|
||
|
struct device_attribute *attr, char *buf)
|
||
|
{
|
||
|
int count = 0;
|
||
|
u8 val = 0;
|
||
|
struct fts_ts_data *ts_data = fts_data;
|
||
|
struct input_dev *input_dev = ts_data->input_dev;
|
||
|
|
||
|
mutex_lock(&input_dev->mutex);
|
||
|
fts_read_reg(FTS_REG_GLOVE_MODE_EN, &val);
|
||
|
count = snprintf(buf + count, PAGE_SIZE, "Glove Mode:%s\n",
|
||
|
ts_data->glove_mode ? "On" : "Off");
|
||
|
count += snprintf(buf + count, PAGE_SIZE, "Glove Reg(0xC0):%d\n", val);
|
||
|
mutex_unlock(&input_dev->mutex);
|
||
|
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
static ssize_t fts_glove_mode_store(struct device *dev,
|
||
|
struct device_attribute *attr,
|
||
|
const char *buf, size_t count)
|
||
|
{
|
||
|
int ret = 0;
|
||
|
struct fts_ts_data *ts_data = fts_data;
|
||
|
|
||
|
if (FTS_SYSFS_ECHO_ON(buf)) {
|
||
|
if (!ts_data->glove_mode) {
|
||
|
FTS_DEBUG("enter glove mode");
|
||
|
ret = fts_ex_mode_switch(MODE_GLOVE, ENABLE);
|
||
|
if (ret >= 0)
|
||
|
ts_data->glove_mode = ENABLE;
|
||
|
|
||
|
}
|
||
|
} else if (FTS_SYSFS_ECHO_OFF(buf)) {
|
||
|
if (ts_data->glove_mode) {
|
||
|
FTS_DEBUG("exit glove mode");
|
||
|
ret = fts_ex_mode_switch(MODE_GLOVE, DISABLE);
|
||
|
if (ret >= 0)
|
||
|
ts_data->glove_mode = DISABLE;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FTS_DEBUG("glove mode:%d", ts_data->glove_mode);
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
static ssize_t fts_cover_mode_show(struct device *dev,
|
||
|
struct device_attribute *attr, char *buf)
|
||
|
{
|
||
|
int count = 0;
|
||
|
u8 val = 0;
|
||
|
struct fts_ts_data *ts_data = fts_data;
|
||
|
struct input_dev *input_dev = ts_data->input_dev;
|
||
|
|
||
|
mutex_lock(&input_dev->mutex);
|
||
|
fts_read_reg(FTS_REG_COVER_MODE_EN, &val);
|
||
|
count = snprintf(buf + count, PAGE_SIZE, "Cover Mode:%s\n",
|
||
|
ts_data->cover_mode ? "On" : "Off");
|
||
|
count += snprintf(buf + count, PAGE_SIZE, "Cover Reg(0xC1):%d\n", val);
|
||
|
mutex_unlock(&input_dev->mutex);
|
||
|
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
static ssize_t fts_cover_mode_store(struct device *dev,
|
||
|
struct device_attribute *attr,
|
||
|
const char *buf, size_t count)
|
||
|
{
|
||
|
int ret = 0;
|
||
|
struct fts_ts_data *ts_data = fts_data;
|
||
|
|
||
|
if (FTS_SYSFS_ECHO_ON(buf)) {
|
||
|
if (!ts_data->cover_mode) {
|
||
|
FTS_DEBUG("enter cover mode");
|
||
|
ret = fts_ex_mode_switch(MODE_COVER, ENABLE);
|
||
|
if (ret >= 0)
|
||
|
ts_data->cover_mode = ENABLE;
|
||
|
|
||
|
}
|
||
|
} else if (FTS_SYSFS_ECHO_OFF(buf)) {
|
||
|
if (ts_data->cover_mode) {
|
||
|
FTS_DEBUG("exit cover mode");
|
||
|
ret = fts_ex_mode_switch(MODE_COVER, DISABLE);
|
||
|
if (ret >= 0)
|
||
|
ts_data->cover_mode = DISABLE;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FTS_DEBUG("cover mode:%d", ts_data->cover_mode);
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
static ssize_t fts_charger_mode_show(struct device *dev,
|
||
|
struct device_attribute *attr, char *buf)
|
||
|
{
|
||
|
int count = 0;
|
||
|
u8 val = 0;
|
||
|
struct fts_ts_data *ts_data = fts_data;
|
||
|
struct input_dev *input_dev = ts_data->input_dev;
|
||
|
|
||
|
mutex_lock(&input_dev->mutex);
|
||
|
fts_read_reg(FTS_REG_CHARGER_MODE_EN, &val);
|
||
|
count = snprintf(buf + count, PAGE_SIZE, "Charger Mode:%s\n",
|
||
|
ts_data->charger_mode ? "On" : "Off");
|
||
|
count +=
|
||
|
snprintf(buf + count, PAGE_SIZE, "Charger Reg(0x8B):%d\n", val);
|
||
|
mutex_unlock(&input_dev->mutex);
|
||
|
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
static ssize_t fts_charger_mode_store(struct device *dev,
|
||
|
struct device_attribute *attr,
|
||
|
const char *buf, size_t count)
|
||
|
{
|
||
|
int ret = 0;
|
||
|
struct fts_ts_data *ts_data = fts_data;
|
||
|
|
||
|
if (FTS_SYSFS_ECHO_ON(buf)) {
|
||
|
if (!ts_data->charger_mode) {
|
||
|
FTS_DEBUG("enter charger mode");
|
||
|
ret = fts_ex_mode_switch(MODE_CHARGER, ENABLE);
|
||
|
if (ret >= 0)
|
||
|
ts_data->charger_mode = ENABLE;
|
||
|
|
||
|
}
|
||
|
} else if (FTS_SYSFS_ECHO_OFF(buf)) {
|
||
|
if (ts_data->charger_mode) {
|
||
|
FTS_DEBUG("exit charger mode");
|
||
|
ret = fts_ex_mode_switch(MODE_CHARGER, DISABLE);
|
||
|
if (ret >= 0)
|
||
|
ts_data->charger_mode = DISABLE;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FTS_DEBUG("charger mode:%d", ts_data->glove_mode);
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
/* read and write charger mode
|
||
|
* read example: cat fts_glove_mode ---read glove mode
|
||
|
* write example:echo 1 > fts_glove_mode ---write glove mode to 01
|
||
|
*/
|
||
|
static DEVICE_ATTR_RW(fts_glove_mode);
|
||
|
|
||
|
static DEVICE_ATTR_RW(fts_cover_mode);
|
||
|
|
||
|
static DEVICE_ATTR_RW(fts_charger_mode);
|
||
|
|
||
|
static struct attribute *fts_touch_mode_attrs[] = {
|
||
|
&dev_attr_fts_glove_mode.attr, &dev_attr_fts_cover_mode.attr,
|
||
|
&dev_attr_fts_charger_mode.attr, NULL,
|
||
|
};
|
||
|
|
||
|
static struct attribute_group fts_touch_mode_group = {
|
||
|
.attrs = fts_touch_mode_attrs,
|
||
|
};
|
||
|
|
||
|
int fts_ex_mode_recovery(struct fts_ts_data *ts_data)
|
||
|
{
|
||
|
if (ts_data->glove_mode)
|
||
|
fts_ex_mode_switch(MODE_GLOVE, ENABLE);
|
||
|
|
||
|
|
||
|
if (ts_data->cover_mode)
|
||
|
fts_ex_mode_switch(MODE_COVER, ENABLE);
|
||
|
|
||
|
|
||
|
if (ts_data->charger_mode)
|
||
|
fts_ex_mode_switch(MODE_CHARGER, ENABLE);
|
||
|
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int fts_ex_mode_init(struct fts_ts_data *ts_data)
|
||
|
{
|
||
|
int ret = 0;
|
||
|
|
||
|
ts_data->glove_mode = DISABLE;
|
||
|
ts_data->cover_mode = DISABLE;
|
||
|
ts_data->charger_mode = DISABLE;
|
||
|
|
||
|
ret = sysfs_create_group(&ts_data->dev->kobj, &fts_touch_mode_group);
|
||
|
if (ret < 0) {
|
||
|
FTS_ERROR("create sysfs(ex_mode) fail");
|
||
|
sysfs_remove_group(&ts_data->dev->kobj, &fts_touch_mode_group);
|
||
|
return ret;
|
||
|
}
|
||
|
FTS_DEBUG("create sysfs(ex_mode) succeedfully");
|
||
|
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int fts_ex_mode_exit(struct fts_ts_data *ts_data)
|
||
|
{
|
||
|
sysfs_remove_group(&ts_data->dev->kobj, &fts_touch_mode_group);
|
||
|
return 0;
|
||
|
}
|