focaltech_0flash_v2_mmi: add touch sys nodes, enable FW download

focaltech_0flash_v2_mmi: ft8726 support
-add touch sys nodes;
-enable FW download;
-add configs for gesture, point report, etc.
-check drm logic before fb for build fix for drm panel

Change-Id: Idaa91550a4ee29d8ba0784a253051d6b2390d0f7
Reviewed-on: https://gerrit.mot.com/2245683
SME-Granted: SME Approvals Granted
SLTApproved: Slta Waiver
Tested-by: Jira Key
Reviewed-by: Wei Deng <dengwei1@motorola.com>
Reviewed-by: Xiangpo Zhao <zhaoxp3@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
hujing3 2022-04-19 10:06:42 +08:00 • committed by Jing Hu
commit 746007756c
10 changed files with 399 additions and 69 deletions

View file

@ -1,6 +1,15 @@
DLKM_DIR := motorola/kernel/modules
LOCAL_PATH := $(call my-dir)
ifneq ($(FOCALTECH_TOUCH_IC_NAME),)
KERNEL_CFLAGS += CONFIG_INPUT_FOCALTECH_0FLASH_MMI_IC_NAME=$(FOCALTECH_TOUCH_IC_NAME)
else
KERNEL_CFLAGS += CONFIG_INPUT_FOCALTECH_0FLASH_MMI_IC_NAME=ft8726
endif
ifneq ($(BOARD_USES_PANEL_NOTIFICATIONS),)
KERNEL_CFLAGS += CONFIG_INPUT_FOCALTECH_PANEL_NOTIFICATIONS=y
endif
include $(CLEAR_VARS)
LOCAL_MODULE := focaltech_0flash_v2_mmi.ko

View file

@ -14,3 +14,6 @@ focaltech_0flash_v2_mmi-objs += focaltech_gesture.o
focaltech_0flash_v2_mmi-objs += focaltech_point_report_check.o
focaltech_0flash_v2_mmi-objs += focaltech_spi.o
ifneq ($(filter m y,$(CONFIG_INPUT_FOCALTECH_PANEL_NOTIFICATIONS)),)
EXTRA_CFLAGS += -DFOCALTECH_CONFIG_PANEL_NOTIFICATIONS
endif

View file

@ -56,9 +56,13 @@
#define FTS_MAX_CHIP_IDS 8
#if defined(CONFIG_INPUT_FOCALTECH_0FLASH_MMI_IC_NAME_FT8726)
#define FTS_CHIP_TYPE_MAPPING {{0x1C, 0x87, 0x20, 0x87, 0x20, 0x87, 0xA0, 0x00, 0x00}}
#define FTS_CHIP_ID_MAPPING {{0x1C, {0x8726, 0x872A, 0x872B}}}
#else
#define FTS_CHIP_TYPE_MAPPING {{0x1C, 0x87, 0x20, 0x87, 0x20, 0x87, 0xA0, 0x00, 0x00}}
#define FTS_CHIP_ID_MAPPING {{0x1C, {0x8726, 0x872A, 0x872B}}}
#endif
#define FILE_NAME_LENGTH 128
#define ENABLE 1
@ -163,9 +167,17 @@ struct ts_ic_info {
printk("[FTS_TS]%s: Exit(%d)\n", __func__, __LINE__); \
} while (0)
#else /* #if FTS_DEBUG_EN*/
#define FTS_DEBUG(fmt, args...)
#define FTS_FUNC_ENTER()
#define FTS_FUNC_EXIT()
#define FTS_DEBUG(fmt, args...) do { \
pr_debug("[FTS_TS]%s:"fmt"\n", __func__, ##args); \
} while (0)
#define FTS_FUNC_ENTER() do { \
pr_debug("[FTS_TS]%s: Enter\n", __func__); \
} while (0)
#define FTS_FUNC_EXIT() do { \
pr_debug("[FTS_TS]%s: Exit(%d)\n", __func__, __LINE__); \
} while (0)
#endif
#define FTS_INFO(fmt, args...) do { \

View file

@ -182,7 +182,13 @@
/*
* choose your ic chip type of focaltech
*/
#if defined(CONFIG_INPUT_FOCALTECH_0FLASH_MMI_IC_NAME_FT8726)
#define FTS_CHIP_TYPE _FT8726
#define FTS_CHIP_NAME "ft8726"
#else
#define FTS_CHIP_TYPE _FT8726
#define FTS_CHIP_NAME "ft8726"
#endif
/******************* Enables *********************/
/*********** 1 to enable, 0 to disable ***********/
@ -215,13 +221,21 @@
* Gesture function enable
* default: disable
*/
#ifdef FOCALTECH_SENSOR_EN
#define FTS_GESTURE_EN 1
#else
#define FTS_GESTURE_EN 0
#endif
/*
* ESD check & protection
* default: disable
*/
#ifdef FOCALTECH_ESD_EN
#define FTS_ESDCHECK_EN 1
#else
#define FTS_ESDCHECK_EN 0
#endif
/*
@ -243,7 +257,7 @@
/*
* auto upgrade
*/
#define FTS_AUTO_UPGRADE_EN 0
#define FTS_AUTO_UPGRADE_EN 1
/*
* auto upgrade for lcd cfg
@ -282,6 +296,7 @@
* FW.i file for auto upgrade, you must replace it with your own
* define your own fw_file, the sample one to be replaced is invalid
* NOTE: if FTS_GET_MODULE_NUM > 1, it's the fw corresponding with FTS_VENDOR_ID
* NOTE: git may ignore xxx.i file
*/
#define FTS_UPGRADE_FW_FILE "include/firmware/fw_sample.h"

View file

@ -37,21 +37,30 @@
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#if defined(CONFIG_FB)
#include <linux/notifier.h>
#include <linux/fb.h>
#elif defined(CONFIG_DRM)
#if defined(CONFIG_DRM)
#if defined(CONFIG_DRM_PANEL)
#include <drm/drm_panel.h>
#else
#include <linux/msm_drm_notify.h>
#endif
#elif defined(CONFIG_FB)
#include <linux/notifier.h>
#include <linux/fb.h>
#elif defined(CONFIG_HAS_EARLYSUSPEND)
#include <linux/earlysuspend.h>
#define FTS_SUSPEND_LEVEL 1 /* Early-suspend level */
#endif
#include "focaltech_core.h"
#ifdef FOCALTECH_CONFIG_PANEL_NOTIFICATIONS
#define register_panel_notifier panel_register_notifier
#define unregister_panel_notifier panel_unregister_notifier
enum touch_state {
TOUCH_DEEP_SLEEP_STATE = 0,
TOUCH_LOW_POWER_STATE,
};
#endif
/*****************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
@ -144,7 +153,9 @@ void fts_tp_state_recovery(struct fts_ts_data *ts_data)
/* recover TP cover state 0xC1 */
fts_ex_mode_recovery(ts_data);
/* recover TP gesture state 0xD0 */
#if FTS_GESTURE_EN
fts_gesture_recovery(ts_data);
#endif
FTS_FUNC_EXIT();
}
@ -697,7 +708,9 @@ static int fts_read_touchdata(struct fts_ts_data *ts_data, u8 *buf)
static int fts_read_parse_touchdata(struct fts_ts_data *ts_data, u8 *touch_buf)
{
int ret = 0;
#if FTS_GESTURE_EN
u8 gesture_en = 0xFF;
#endif
memset(touch_buf, 0xFF, FTS_MAX_TOUCH_BUF);
ts_data->ta_size = ts_data->touch_size;
@ -715,6 +728,7 @@ static int fts_read_parse_touchdata(struct fts_ts_data *ts_data, u8 *touch_buf)
if (ret)
return TOUCH_IGNORE;
#if FTS_GESTURE_EN
/*gesture*/
if (ts_data->suspended && ts_data->gesture_support) {
ret = fts_read_reg(FTS_REG_GESTURE_EN, &gesture_en);
@ -723,6 +737,7 @@ static int fts_read_parse_touchdata(struct fts_ts_data *ts_data, u8 *touch_buf)
else
FTS_DEBUG("gesture not enable in fw, don't process gesture");
}
#endif
if ((touch_buf[1] == 0xFF) && (touch_buf[2] == 0xFF)
&& (touch_buf[3] == 0xFF) && (touch_buf[4] == 0xFF)) {
@ -886,11 +901,13 @@ static int fts_irq_read_report(struct fts_ts_data *ts_data)
mutex_unlock(&ts_data->report_mutex);
break;
#if FTS_GESTURE_EN
case TOUCH_GESTURE:
if (0 == fts_gesture_readdata(ts_data, touch_buf)) {
FTS_INFO("succuss to get gesture data in irq handler");
}
break;
#endif
case TOUCH_FW_INIT:
fts_release_all_finger();
@ -927,7 +944,9 @@ static irqreturn_t fts_irq_handler(int irq, void *data)
#endif
ts_data->intr_jiffies = jiffies;
#if FTS_POINT_REPORT_CHECK_EN
fts_prc_queue_work(ts_data);
#endif
fts_irq_read_report(ts_data);
if (ts_data->touch_analysis_support && ts_data->ta_flag) {
ts_data->ta_flag = 0;
@ -1518,6 +1537,14 @@ static int fts_parse_dt(struct device *dev, struct fts_ts_platform_data *pdata)
FTS_INFO("max touch number:%d, irq gpio:%d, reset gpio:%d",
pdata->max_touch_number, pdata->irq_gpio, pdata->reset_gpio);
ret = of_property_read_string(np, "focaltech,panel-supplier",
&fts_data->panel_supplier);
if (ret < 0) {
fts_data->panel_supplier = NULL;
FTS_ERROR("Unable to read panel supplier\n");
} else {
FTS_INFO("panel supplier is %s", (char *)fts_data->panel_supplier);
}
FTS_FUNC_EXIT();
return 0;
}
@ -1530,51 +1557,7 @@ static void fts_resume_work(struct work_struct *work)
fts_ts_resume(ts_data->dev);
}
#if defined(CONFIG_FB)
static int fb_notifier_callback(struct notifier_block *self,
unsigned long event, void *data)
{
struct fb_event *evdata = data;
int *blank = NULL;
struct fts_ts_data *ts_data = container_of(self, struct fts_ts_data,
fb_notif);
if (!evdata) {
FTS_ERROR("evdata is null");
return 0;
}
if (!(event == FB_EARLY_EVENT_BLANK || event == FB_EVENT_BLANK)) {
FTS_INFO("event(%lu) do not need process\n", event);
return 0;
}
blank = evdata->data;
FTS_INFO("FB event:%lu,blank:%d", event, *blank);
switch (*blank) {
case FB_BLANK_UNBLANK:
if (FB_EARLY_EVENT_BLANK == event) {
FTS_INFO("resume: event = %lu, not care\n", event);
} else if (FB_EVENT_BLANK == event) {
queue_work(fts_data->ts_workqueue, &fts_data->resume_work);
}
break;
case FB_BLANK_POWERDOWN:
if (FB_EARLY_EVENT_BLANK == event) {
cancel_work_sync(&fts_data->resume_work);
fts_ts_suspend(ts_data->dev);
} else if (FB_EVENT_BLANK == event) {
FTS_INFO("suspend: event = %lu, not care\n", event);
}
break;
default:
FTS_INFO("FB BLANK(%d) do not need process\n", *blank);
break;
}
return 0;
}
#elif defined(CONFIG_DRM)
#if defined(CONFIG_DRM)
#if defined(CONFIG_DRM_PANEL)
static struct drm_panel *active_panel;
@ -1609,7 +1592,7 @@ static int drm_check_dt(struct device_node *np)
static int drm_notifier_callback(struct notifier_block *self,
unsigned long event, void *data)
{
struct msm_drm_notifier *evdata = data;
struct drm_panel_notifier *evdata = data;
int *blank = NULL;
struct fts_ts_data *ts_data = container_of(self, struct fts_ts_data,
fb_notif);
@ -1651,6 +1634,7 @@ static int drm_notifier_callback(struct notifier_block *self,
return 0;
}
#else
#ifndef FOCALTECH_CONFIG_PANEL_NOTIFICATIONS
static int drm_notifier_callback(struct notifier_block *self,
unsigned long event, void *data)
{
@ -1695,7 +1679,91 @@ static int drm_notifier_callback(struct notifier_block *self,
return 0;
}
#else
int drm_notifier_callback(struct notifier_block *self,
unsigned long event, void *data)
{
struct msm_drm_notifier *evdata = data;
struct fts_ts_data *ts_data =
container_of(self, struct fts_ts_data, fb_notif);
if (!evdata || (evdata->id != 0)) {
return 0;
}
FTS_INFO("DRM event:%lu", event);
switch (event) {
case PANEL_EVENT_DISPLAY_ON:
queue_work(fts_data->ts_workqueue, &fts_data->resume_work);
break;
case PANEL_EVENT_PRE_DISPLAY_OFF:
cancel_work_sync(&fts_data->resume_work);
fts_ts_suspend(ts_data->dev);
#ifdef FOCALTECH_SENSOR_EN
if (fts_data->should_enable_gesture) {
FTS_INFO("double tap gesture suspend\n");
touch_set_state(TOUCH_LOW_POWER_STATE, TOUCH_PANEL_IDX_PRIMARY);
fts_gesture_suspend(ts_data);
} else {
#endif
touch_set_state(TOUCH_DEEP_SLEEP_STATE, TOUCH_PANEL_IDX_PRIMARY);
fts_ts_suspend(ts_data->dev);
#ifdef FOCALTECH_SENSOR_EN
}
#endif
break;
default:
break;
}
return 0;
}
#endif
#endif
#elif defined(CONFIG_FB)
static int fb_notifier_callback(struct notifier_block *self,
unsigned long event, void *data)
{
struct fb_event *evdata = data;
int *blank = NULL;
struct fts_ts_data *ts_data = container_of(self, struct fts_ts_data,
fb_notif);
if (!evdata) {
FTS_ERROR("evdata is null");
return 0;
}
if (!(event == FB_EARLY_EVENT_BLANK || event == FB_EVENT_BLANK)) {
FTS_INFO("event(%lu) do not need process\n", event);
return 0;
}
blank = evdata->data;
FTS_INFO("FB event:%lu,blank:%d", event, *blank);
switch (*blank) {
case FB_BLANK_UNBLANK:
if (FB_EARLY_EVENT_BLANK == event) {
FTS_INFO("resume: event = %lu, not care\n", event);
} else if (FB_EVENT_BLANK == event) {
queue_work(fts_data->ts_workqueue, &fts_data->resume_work);
}
break;
case FB_BLANK_POWERDOWN:
if (FB_EARLY_EVENT_BLANK == event) {
cancel_work_sync(&fts_data->resume_work);
fts_ts_suspend(ts_data->dev);
} else if (FB_EVENT_BLANK == event) {
FTS_INFO("suspend: event = %lu, not care\n", event);
}
break;
default:
FTS_INFO("FB BLANK(%d) do not need process\n", *blank);
break;
}
return 0;
}
#elif defined(CONFIG_HAS_EARLYSUSPEND)
static void fts_ts_early_suspend(struct early_suspend *handler)
{
@ -1738,6 +1806,7 @@ static int fts_ts_probe_entry(struct fts_ts_data *ts_data)
ret = drm_check_dt(ts_data->dev->of_node);
if (ret) {
FTS_ERROR("parse drm-panel fail");
return -ENODEV;
}
#endif
#endif
@ -1813,20 +1882,24 @@ static int fts_ts_probe_entry(struct fts_ts_data *ts_data)
FTS_ERROR("create sysfs node fail");
}
#if FTS_POINT_REPORT_CHECK_EN
ret = fts_point_report_check_init(ts_data);
if (ret) {
FTS_ERROR("init point report check fail");
}
#endif
ret = fts_ex_mode_init(ts_data);
if (ret) {
FTS_ERROR("init glove/cover/charger fail");
}
#if FTS_GESTURE_EN
ret = fts_gesture_init(ts_data);
if (ret) {
FTS_ERROR("init gesture fail");
}
#endif
ret = fts_esdcheck_init(ts_data);
@ -1854,13 +1927,7 @@ static int fts_ts_probe_entry(struct fts_ts_data *ts_data)
ts_data->pm_suspend = false;
#endif
#if defined(CONFIG_FB)
ts_data->fb_notif.notifier_call = fb_notifier_callback;
ret = fb_register_client(&ts_data->fb_notif);
if (ret) {
FTS_ERROR("[FB]Unable to register fb_notifier: %d", ret);
}
#elif defined(CONFIG_DRM)
#if defined(CONFIG_DRM)
ts_data->fb_notif.notifier_call = drm_notifier_callback;
#if defined(CONFIG_DRM_PANEL)
if (active_panel) {
@ -1869,11 +1936,24 @@ static int fts_ts_probe_entry(struct fts_ts_data *ts_data)
FTS_ERROR("[DRM]drm_panel_notifier_register fail: %d\n", ret);
}
#else
#ifndef FOCALTECH_CONFIG_PANEL_NOTIFICATIONS
ret = msm_drm_register_client(&ts_data->fb_notif);
if (ret) {
FTS_ERROR("[DRM]Unable to register fb_notifier: %d\n", ret);
}
#else
ret = register_panel_notifier(&ts_data->fb_notif);
if(ret) {
FTS_ERROR("register panel_notifier failed. ret=%d\n", ret);
}
#endif
#endif
#elif defined(CONFIG_FB)
ts_data->fb_notif.notifier_call = fb_notifier_callback;
ret = fb_register_client(&ts_data->fb_notif);
if (ret) {
FTS_ERROR("[FB]Unable to register fb_notifier: %d", ret);
}
#elif defined(CONFIG_HAS_EARLYSUSPEND)
ts_data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + FTS_SUSPEND_LEVEL;
ts_data->early_suspend.suspend = fts_ts_early_suspend;
@ -1917,7 +1997,10 @@ static int fts_ts_remove_entry(struct fts_ts_data *ts_data)
FTS_FUNC_ENTER();
cancel_work_sync(&fts_data->resume_work);
#if FTS_POINT_REPORT_CHECK_EN
fts_point_report_check_exit(ts_data);
#endif
fts_release_apk_debug_channel(ts_data);
fts_remove_sysfs(ts_data);
fts_ex_mode_exit(ts_data);
@ -1927,7 +2010,9 @@ static int fts_ts_remove_entry(struct fts_ts_data *ts_data)
fts_esdcheck_exit(ts_data);
#if FTS_GESTURE_EN
fts_gesture_exit(ts_data);
#endif
free_irq(ts_data->irq, ts_data);
@ -1941,10 +2026,7 @@ static int fts_ts_remove_entry(struct fts_ts_data *ts_data)
if (ts_data->ts_workqueue)
destroy_workqueue(ts_data->ts_workqueue);
#if defined(CONFIG_FB)
if (fb_unregister_client(&ts_data->fb_notif))
FTS_ERROR("[FB]Error occurred while unregistering fb_notifier.");
#elif defined(CONFIG_DRM)
#if defined(CONFIG_DRM)
#if defined(CONFIG_DRM_PANEL)
if (active_panel)
drm_panel_notifier_unregister(active_panel, &ts_data->fb_notif);
@ -1952,6 +2034,9 @@ static int fts_ts_remove_entry(struct fts_ts_data *ts_data)
if (msm_drm_unregister_client(&ts_data->fb_notif))
FTS_ERROR("[DRM]Error occurred while unregistering fb_notifier.\n");
#endif
#elif defined(CONFIG_FB)
if (fb_unregister_client(&ts_data->fb_notif))
FTS_ERROR("[FB]Error occurred while unregistering fb_notifier.");
#elif defined(CONFIG_HAS_EARLYSUSPEND)
unregister_early_suspend(&ts_data->early_suspend);
#endif
@ -1993,10 +2078,13 @@ static int fts_ts_suspend(struct device *dev)
fts_esdcheck_suspend(ts_data);
#if FTS_GESTURE_EN
if (ts_data->gesture_support) {
fts_gesture_suspend(ts_data);
} else {
} else
#endif
{
FTS_INFO("make TP enter into sleep mode");
ret = fts_write_reg(FTS_REG_POWER_MODE, FTS_REG_POWER_MODE_SLEEP);
if (ret < 0)
@ -2043,9 +2131,11 @@ static int fts_ts_resume(struct device *dev)
fts_esdcheck_resume(ts_data);
#if FTS_GESTURE_EN
if (ts_data->gesture_support) {
fts_gesture_resume(ts_data);
}
#endif
FTS_FUNC_EXIT();
return 0;

View file

@ -224,6 +224,7 @@ struct fts_ts_data {
u8 *bus_tx_buf;
u8 *bus_rx_buf;
int bus_type;
const char *panel_supplier;
struct regulator *vdd;
struct regulator *vcc_i2c;
#if FTS_PINCTRL_EN

View file

@ -800,6 +800,39 @@ static ssize_t fts_bootmode_show(
return count;
}
static ssize_t fts_productinfo_show(struct device *dev, struct device_attribute *attr, char *buf)
{
return scnprintf(buf, PAGE_SIZE, "%s\n", FTS_CHIP_NAME);
}
static ssize_t fts_ic_ver_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int count = 0;
u8 val = 0;
struct input_dev *input_dev = fts_data->input_dev;
mutex_lock(&input_dev->mutex);
#if FTS_ESDCHECK_EN
fts_esdcheck_proc_busy(1);
#endif
fts_read_reg(FTS_REG_VENDOR_ID, &val);
count += snprintf(buf + count, PAGE_SIZE, "Product ID: 0x%02x\n", val);
fts_read_reg(FTS_REG_FW_VER, &val);
count += snprintf(buf + count, PAGE_SIZE, "Build ID: 0000-%02x\n", val);
count += scnprintf(buf + count, PAGE_SIZE, "IC: %s\n", FTS_CHIP_NAME);
#if FTS_ESDCHECK_EN
fts_esdcheck_proc_busy(0);
#endif
mutex_unlock(&input_dev->mutex);
return count;
}
static ssize_t fts_name_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return scnprintf(buf, PAGE_SIZE, "focaltech");
}
/* fts_tpfwver interface */
static ssize_t fts_tpfwver_show(
struct device *dev, struct device_attribute *attr, char *buf)
@ -829,6 +862,32 @@ static ssize_t fts_tpfwver_store(
return -EPERM;
}
static ssize_t buildid_show(
struct device *dev, struct device_attribute *attr, char *buf)
{
struct fts_ts_data *ts_data = fts_data;
struct input_dev *input_dev = ts_data->input_dev;
ssize_t num_read_chars = 0;
u8 fwver = 0;
mutex_lock(&input_dev->mutex);
#if FTS_ESDCHECK_EN
fts_esdcheck_proc_busy(1);
#endif
fts_read_reg(FTS_REG_FW_VER, &fwver);
#if FTS_ESDCHECK_EN
fts_esdcheck_proc_busy(0);
#endif
if ((fwver == 0xFF) || (fwver == 0x00))
num_read_chars = snprintf(buf, PAGE_SIZE, "get tp fw version fail!\n");
else
num_read_chars = snprintf(buf, PAGE_SIZE, "0000-%02x\n", fwver);
mutex_unlock(&input_dev->mutex);
return num_read_chars;
}
/* fts_rw_reg */
static ssize_t fts_tprwreg_show(
struct device *dev, struct device_attribute *attr, char *buf)
@ -1392,6 +1451,18 @@ static ssize_t fts_tamode_store(
return count;
}
static ssize_t fts_panel_supplier_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct fts_ts_data *data = dev_get_drvdata(dev);
if (data->panel_supplier)
return scnprintf(buf, PAGE_SIZE, "%s\n",
data->panel_supplier);
return 0;
}
static DEVICE_ATTR(panel_supplier, 0444, fts_panel_supplier_show, NULL);
/* get the fw version example:cat fw_version */
static DEVICE_ATTR(fts_fw_version, S_IRUGO | S_IWUSR, fts_tpfwver_show, fts_tpfwver_store);
@ -1422,6 +1493,10 @@ static DEVICE_ATTR(fts_log_level, S_IRUGO | S_IWUSR, fts_log_level_show, fts_log
static DEVICE_ATTR(fts_pen, S_IRUGO | S_IWUSR, fts_pen_show, fts_pen_store);
static DEVICE_ATTR(fts_touch_size, S_IRUGO | S_IWUSR, fts_touchsize_show, fts_touchsize_store);
static DEVICE_ATTR(fts_ta_mode, S_IRUGO | S_IWUSR, fts_tamode_show, fts_tamode_store);
static DEVICE_ATTR(buildid, S_IRUGO, buildid_show, NULL);
static DEVICE_ATTR(productinfo, S_IRUGO, fts_productinfo_show, NULL);
static DEVICE_ATTR(ic_ver, S_IRUGO, fts_ic_ver_show, NULL);
static DEVICE_ATTR(name, S_IRUGO, fts_name_show, NULL);
/* add your attr in here*/
static struct attribute *fts_attributes[] = {
@ -1439,6 +1514,11 @@ static struct attribute *fts_attributes[] = {
&dev_attr_fts_pen.attr,
&dev_attr_fts_touch_size.attr,
&dev_attr_fts_ta_mode.attr,
&dev_attr_buildid.attr,
&dev_attr_productinfo.attr,
&dev_attr_ic_ver.attr,
&dev_attr_name.attr,
&dev_attr_panel_supplier.attr,
NULL
};
@ -1446,6 +1526,108 @@ static struct attribute_group fts_attribute_group = {
.attrs = fts_attributes
};
#include <linux/major.h>
#include <linux/kdev_t.h>
/* Attribute: path (RO) */
static ssize_t path_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct fts_ts_data *data = dev_get_drvdata(dev);
ssize_t blen;
const char *path;
if (!data) {
pr_err("cannot get fts_ts_data pointer\n");
return (ssize_t)0;
}
path = kobject_get_path(&data->spi->dev.kobj, GFP_KERNEL);
blen = scnprintf(buf, PAGE_SIZE, "%s", path ? path : "na");
kfree(path);
return blen;
}
/* Attribute: vendor (RO) */
static ssize_t vendor_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return scnprintf(buf, PAGE_SIZE, "focaltech");
}
static struct device_attribute touchscreen_attributes[] = {
__ATTR_RO(path),
__ATTR_RO(vendor),
__ATTR_NULL
};
#define TSDEV_MINOR_BASE 128
#define TSDEV_MINOR_MAX 32
static int fts_sysfs_class(void *_data, bool create)
{
struct fts_ts_data *data = _data;
struct device_attribute *attrs = touchscreen_attributes;
int i, error = 0;
static struct class *touchscreen_class;
static struct device *ts_class_dev;
static int minor;
if (create) {
minor = input_get_new_minor(data->spi->chip_select,
1, false);
if (minor < 0)
minor = input_get_new_minor(TSDEV_MINOR_BASE,
TSDEV_MINOR_MAX, true);
pr_info("assigned minor %d\n", minor);
touchscreen_class = class_create(THIS_MODULE, "touchscreen");
if (IS_ERR(touchscreen_class)) {
error = PTR_ERR(touchscreen_class);
touchscreen_class = NULL;
return error;
}
ts_class_dev = device_create(touchscreen_class, NULL,
MKDEV(INPUT_MAJOR, minor),
data, FTS_CHIP_NAME);
if (IS_ERR(ts_class_dev)) {
error = PTR_ERR(ts_class_dev);
ts_class_dev = NULL;
return error;
}
for (i = 0; attrs[i].attr.name != NULL; ++i) {
error = device_create_file(ts_class_dev, &attrs[i]);
if (error)
break;
}
if (error)
goto device_destroy;
} else {
if (!touchscreen_class || !ts_class_dev)
return -ENODEV;
for (i = 0; attrs[i].attr.name != NULL; ++i)
device_remove_file(ts_class_dev, &attrs[i]);
device_unregister(ts_class_dev);
class_unregister(touchscreen_class);
}
return 0;
device_destroy:
for (--i; i >= 0; --i)
device_remove_file(ts_class_dev, &attrs[i]);
device_destroy(touchscreen_class, MKDEV(INPUT_MAJOR, minor));
ts_class_dev = NULL;
class_unregister(touchscreen_class);
pr_err("error creating touchscreen class\n");
return -ENODEV;
}
int fts_create_sysfs(struct fts_ts_data *ts_data)
{
int ret = 0;
@ -1459,6 +1641,13 @@ int fts_create_sysfs(struct fts_ts_data *ts_data)
FTS_INFO("[EX]: sysfs_create_group() succeeded!!");
}
ret = fts_sysfs_class(ts_data, true);
if (ret) {
FTS_ERROR("[EX]: fts_sysfs_class() failed!!");
sysfs_remove_group(&ts_data->dev->kobj, &fts_attribute_group);
return -ENOMEM;
}
return ret;
}

View file

@ -38,7 +38,7 @@
/*****************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
#define FTS_FW_REQUEST_SUPPORT 0
#define FTS_FW_REQUEST_SUPPORT 1
/* Example: focaltech_ts_fw_tianma.bin */
#define FTS_FW_NAME_PREX_WITH_REQUEST "focaltech_ts_fw_"
#define FTS_READ_BOOT_ID_TIMEOUT 3
@ -1063,7 +1063,14 @@ static int fts_get_fw_file_via_request_firmware(struct fts_upgrade *upg)
u8 *tmpbuf = NULL;
char fwname[FILE_NAME_LENGTH] = { 0 };
snprintf(fwname, FILE_NAME_LENGTH, "%s%s.bin", \
if (fts_data->panel_supplier) {
FTS_INFO("fts_data->panel_supplier=%s\n", fts_data->panel_supplier);
snprintf(fwname, FILE_NAME_LENGTH, "%s%s.bin", \
FTS_FW_NAME_PREX_WITH_REQUEST, \
fts_data->panel_supplier);
}
else
snprintf(fwname, FILE_NAME_LENGTH, "%s%s.bin", \
FTS_FW_NAME_PREX_WITH_REQUEST, \
upg->module_info->vendor_name);

View file

@ -34,6 +34,7 @@
*****************************************************************************/
#include "focaltech_core.h"
#if FTS_GESTURE_EN
/******************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
@ -502,3 +503,4 @@ int fts_gesture_exit(struct fts_ts_data *ts_data)
FTS_FUNC_EXIT();
return 0;
}
#endif

View file

@ -36,6 +36,7 @@
*****************************************************************************/
#include "focaltech_core.h"
#if FTS_POINT_REPORT_CHECK_EN
/*****************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
@ -183,3 +184,4 @@ int fts_point_report_check_exit(struct fts_ts_data *ts_data)
FTS_FUNC_EXIT();
return 0;
}
#endif /* FTS_POINT_REPORT_CHECK_EN */