blob: c86c92d3e07e13b7d397191992261b7ca58ce14f [file] [log] [blame]
/*
*
* FocalTech TouchScreen driver.
*
* Copyright (c) 2012-2020, Focaltech Ltd. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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.
*
*/
/*****************************************************************************
*
* File Name: focaltech_core.h
* Author: Focaltech Driver Team
*
* Created: 2016-08-08
*
* Abstract:
*
* Reference:
*
*****************************************************************************/
#ifndef __LINUX_FOCALTECH_CORE_H__
#define __LINUX_FOCALTECH_CORE_H__
/*****************************************************************************
* Included header files
*****************************************************************************/
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/uaccess.h>
#include <linux/firmware.h>
#include <linux/debugfs.h>
#include <linux/mutex.h>
#include <linux/workqueue.h>
#include <linux/wait.h>
#include <linux/time.h>
#include <linux/jiffies.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/dma-mapping.h>
#include <linux/pm_qos.h>
#include "focaltech_common.h"
#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD)
#include <touch_offload.h>
#endif
#if IS_ENABLED(CONFIG_TOUCHSCREEN_HEATMAP)
#include <heatmap.h>
#endif
/*****************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
#define FTS_MAX_POINTS_SUPPORT 10 /* constant value, can't be changed */
#define FTS_MAX_KEYS 4
#define FTS_KEY_DIM 10
#define FTS_ONE_TCH_LEN 6
#define FTS_TOUCH_DATA_LEN (FTS_MAX_POINTS_SUPPORT * FTS_ONE_TCH_LEN + 3)
#define FTS_GESTURE_POINTS_MAX 1
#define FTS_GESTURE_DATA_LEN 14
#define FTS_GESTURE_TOTAL_DATA_SIZE (FTS_GESTURE_POINTS_MAX * FTS_GESTURE_DATA_LEN)
#define FTS_MAX_ID 0x0A
#define FTS_TOUCH_X_H_POS 3
#define FTS_TOUCH_X_L_POS 4
#define FTS_TOUCH_Y_H_POS 5
#define FTS_TOUCH_Y_L_POS 6
#define FTS_TOUCH_PRE_POS 7
#define FTS_TOUCH_AREA_POS 8
#define FTS_TOUCH_POINT_NUM 2
#define FTS_TOUCH_EVENT_POS 3
#define FTS_TOUCH_ID_POS 5
#define FTS_COORDS_ARR_SIZE 4
#define FTS_X_MIN_DISPLAY_DEFAULT 0
#define FTS_Y_MIN_DISPLAY_DEFAULT 0
#define FTS_X_MAX_DISPLAY_DEFAULT 720
#define FTS_Y_MAX_DISPLAY_DEFAULT 1280
#define FTS_TOUCH_DOWN 0
#define FTS_TOUCH_UP 1
#define FTS_TOUCH_CONTACT 2
#define EVENT_DOWN(flag) ((FTS_TOUCH_DOWN == flag) || (FTS_TOUCH_CONTACT == flag))
#define EVENT_UP(flag) (FTS_TOUCH_UP == flag)
#define EVENT_NO_DOWN(data) (!data->point_num)
#define FTS_MAX_COMPATIBLE_TYPE 4
#define FTS_MAX_COMMMAND_LENGTH 16
/*****************************************************************************
* Alternative mode (When something goes wrong, the modules may be able to solve the problem.)
*****************************************************************************/
/*
* For commnication error in PM(deep sleep) state
*/
#define FTS_PATCH_COMERR_PM 0
#define FTS_TIMEOUT_COMERR_PM 700
#define FTS_HIGH_REPORT 0
#define FTS_SIZE_DEFAULT 15
/*****************************************************************************
* Private enumerations, structures and unions using typedef
*****************************************************************************/
struct ftxxxx_proc {
struct proc_dir_entry *proc_entry;
u8 opmode;
u8 cmd_len;
u8 cmd[FTS_MAX_COMMMAND_LENGTH];
};
struct fts_ts_platform_data {
u32 irq_gpio;
u32 irq_gpio_flags;
u32 reset_gpio;
u32 reset_gpio_flags;
struct drm_panel *panel;
u32 initial_panel_index;
bool have_key;
u32 key_number;
u32 keys[FTS_MAX_KEYS];
u32 key_y_coords[FTS_MAX_KEYS];
u32 key_x_coords[FTS_MAX_KEYS];
u32 x_max;
u32 y_max;
u32 x_min;
u32 y_min;
u32 max_touch_number;
#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD)
u32 offload_id;
#endif
u32 tx_ch_num;
u32 rx_ch_num;
/* convert mm to pixel for major and minor */
u8 mm2px;
};
struct ts_event {
int x; /*x coordinate */
int y; /*y coordinate */
int p; /* pressure */
int flag; /* touch event flag: 0 -- down; 1-- up; 2 -- contact */
int id; /*touch ID */
int area;
int major;
int minor;
};
struct pen_event {
int inrange;
int tip;
int x; /*x coordinate */
int y; /*y coordinate */
int p; /* pressure */
int flag; /* touch event flag: 0 -- down; 1-- up; 2 -- contact */
int id; /*touch ID */
int tilt_x;
int tilt_y;
int tool_type;
};
/* Motion filter finite state machine (FSM) states
* MF_FILTERED - default coordinate filtering
* MF_UNFILTERED - unfiltered single-touch coordinates
* MF_FILTERED_LOCKED - filtered coordinates. Locked until touch is lifted.
*/
typedef enum {
MF_FILTERED,
MF_UNFILTERED,
MF_FILTERED_LOCKED,
} motion_filter_state_t;
/* Motion filter mode.
* MF_OFF : 0 = Always unfilter.
* MF_DYNAMIC: 1 = Dynamic change motion filter.
* MF_ON : 2 = Always filter by touch FW.
*/
enum MF_MODE {
MF_OFF,
MF_DYNAMIC,
MF_ON,
};
/*
* gesture_id - mean which gesture is recognised
* point_num - points number of this gesture
* coordinate_x - All gesture point x coordinate
* coordinate_y - All gesture point y coordinate
* major - All gesture major value
* minor - All gesture minor value
* orientation - All gesture orientation value
*/
struct fts_gesture_st {
u8 gesture_id;
u8 point_num;
int coordinate_x[FTS_GESTURE_POINTS_MAX];
int coordinate_y[FTS_GESTURE_POINTS_MAX];
int major[FTS_GESTURE_POINTS_MAX];
int minor[FTS_GESTURE_POINTS_MAX];
int orientation[FTS_GESTURE_POINTS_MAX];
};
enum SS_TYPE {
SS_NORMAL,
SS_WATER,
};
struct fts_ts_data {
struct i2c_client *client;
struct spi_device *spi;
struct device *dev;
struct input_dev *input_dev;
struct input_dev *pen_dev;
struct fts_ts_platform_data *pdata;
struct ts_ic_info ic_info;
struct workqueue_struct *ts_workqueue;
struct work_struct fwupg_work;
struct delayed_work esdcheck_work;
struct delayed_work prc_work;
struct work_struct resume_work;
struct work_struct suspend_work;
struct pm_qos_request pm_qos_req;
struct ftxxxx_proc proc;
spinlock_t irq_lock;
struct mutex report_mutex;
struct mutex bus_lock;
struct mutex reg_lock;
struct mutex device_mutex;
struct completion bus_resumed;
struct fts_gesture_st fts_gesture_data;
unsigned long intr_jiffies;
int irq;
int log_level;
int fw_is_running; /* confirm fw is running when using spi:default 0 */
int dummy_byte;
#if defined(CONFIG_PM) && FTS_PATCH_COMERR_PM
struct completion pm_completion;
bool pm_suspend;
#endif
bool suspended;
bool fw_loading;
bool irq_disabled;
bool power_disabled;
bool glove_mode;
bool cover_mode;
bool charger_mode;
bool gesture_mode; /* gesture enable or disable, default: disable */
bool prc_mode;
bool driver_probed;
struct pen_event pevent;
/* multi-touch */
struct ts_event *events;
u8 *bus_tx_buf;
u8 *bus_rx_buf;
int bus_type;
u8 *point_buf;
int pnt_buf_size;
int touchs;
int key_state;
int touch_point;
int point_num;
#if GOOGLE_REPORT_MODE
u8 current_host_status[FTS_CUSTOMER_STATUS_LEN];
#endif
/* Motion filter mode.
* MF_OFF : 0 = Always unfilter.
* MF_DYNAMIC: 1 = Dynamic change motion filter.
* MF_ON : 2 = Always filter by touch FW.
*/
u8 mf_mode;
/* Payload for continuously report. */
u8 set_continuously_report;
/* Motion filter finite state machine (FSM) state */
motion_filter_state_t mf_state;
/* Time of initial single-finger touch down. This timestamp is used to
* compute the duration a single finger is touched before it is lifted.
*/
ktime_t mf_downtime;
ktime_t bugreport_ktime_start;
u8 work_mode;
#if IS_ENABLED(CONFIG_TOUCHSCREEN_HEATMAP)
u8 fw_heatmap_mode;
u8 fw_default_heatmap_mode;
int compress_heatmap_wlen;
#endif
u8 enable_fw_grip;
u8 enable_fw_palm;
ktime_t isr_timestamp; /* Time that the event was first received from the
* touch IC, acquired during hard interrupt, in
* CLOCK_MONOTONIC */
ktime_t coords_timestamp;
bool is_deepsleep;
#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD) || \
IS_ENABLED(CONFIG_TOUCHSCREEN_HEATMAP)
u8 *heatmap_raw;
u16 heatmap_raw_size;
u8 *trans_raw;
u16 trans_raw_size;
u16 *heatmap_buff;
u16 heatmap_buff_size;
u8 self_sensing_type;
#endif
#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD)
struct touch_offload_context offload;
struct touch_offload_frame *reserved_frame;
u8 touch_offload_active_coords;
#endif
#if IS_ENABLED(CONFIG_TOUCHSCREEN_HEATMAP)
struct v4l2_heatmap v4l2;
#endif
struct proc_dir_entry *proc_touch_entry;
struct regulator *avdd;
struct regulator *dvdd;
#if FTS_PINCTRL_EN
struct pinctrl *pinctrl;
struct pinctrl_state *pins_active;
struct pinctrl_state *pins_suspend;
#endif
#if defined(CONFIG_FB) || defined(CONFIG_DRM)
struct notifier_block fb_notif;
#elif defined(CONFIG_HAS_EARLYSUSPEND)
struct early_suspend early_suspend;
#endif
#if IS_ENABLED(CONFIG_TOUCHSCREEN_PANEL_BRIDGE)
volatile int power_status;
u16 bus_refmask;
struct mutex bus_mutex;
struct drm_bridge panel_bridge;
struct drm_connector *connector;
bool is_panel_lp_mode;
int display_refresh_rate;
#endif
#if IS_ENABLED(CONFIG_TOUCHSCREEN_TBN)
u32 tbn_register_mask;
u8 tbn_owner;
#endif
};
enum FTS_BUS_TYPE {
FTS_BUS_TYPE_NONE,
FTS_BUS_TYPE_I2C,
FTS_BUS_TYPE_SPI,
FTS_BUS_TYPE_SPI_V2,
};
#if GOOGLE_REPORT_MODE
enum FTS_CUSTOMER_STATUS {
STATUS_BASELINE_REFRESH_B0,
STATUS_BASELINE_REFRESH_B1,
STATUS_PALM,
STATUS_WATER,
STATUS_GRIP,
STATUS_GLOVE,
STATUS_EDGE_PALM,
STATUS_RESET,
STATUS_CNT_END,
};
enum FTS_FW_MODE_SETTING{
FW_GLOVE = 0,
FW_GRIP,
FW_PALM,
FW_HEATMAP,
FW_CONTINUOUS,
FW_CNT_END,
};
#endif
enum FTS_SCAN_MODE {
MODE_AUTO,
MODE_NORMAL_ACTIVE,
MODE_NORMAL_IDLE,
MODE_LOW_POWER_ACTIVE,
MODE_LOW_POWER_IDLE,
MODE_CNT,
};
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
extern struct fts_ts_data *fts_data;
/* communication interface */
int fts_read(u8 *cmd, u32 cmdlen, u8 *data, u32 datalen);
int fts_read_reg(u8 addr, u8 *value);
int fts_write(u8 *writebuf, u32 writelen);
int fts_write_reg(u8 addr, u8 value);
void fts_hid2std(void);
int fts_bus_init(struct fts_ts_data *ts_data);
int fts_bus_exit(struct fts_ts_data *ts_data);
int fts_spi_transfer_direct(u8 *writebuf, u32 writelen, u8 *readbuf, u32 readlen);
/* Gesture functions */
int fts_gesture_init(struct fts_ts_data *ts_data);
int fts_gesture_exit(struct fts_ts_data *ts_data);
void fts_gesture_recovery(struct fts_ts_data *ts_data);
int fts_gesture_readdata(struct fts_ts_data *ts_data, bool is_report);
int fts_gesture_suspend(struct fts_ts_data *ts_data);
int fts_gesture_resume(struct fts_ts_data *ts_data);
/* Heatmap and Offload*/
#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD) || \
IS_ENABLED(CONFIG_TOUCHSCREEN_HEATMAP)
int fts_get_default_heatmap_mode(struct fts_ts_data *ts_data);
int fts_set_heatmap_mode(struct fts_ts_data *ts_data, u8 heatmap_mode);
#endif
int fts_set_grip_mode(struct fts_ts_data *ts_datam, u8 grip_mode);
int fts_set_palm_mode(struct fts_ts_data *ts_data, u8 palm_mode);
int fts_set_continuous_mode(struct fts_ts_data *ts_data, bool en);
int fts_set_glove_mode(struct fts_ts_data *ts_data, bool en);
/* Apk and functions */
int fts_create_apk_debug_channel(struct fts_ts_data *);
void fts_release_apk_debug_channel(struct fts_ts_data *);
/* ADB functions */
int fts_create_sysfs(struct fts_ts_data *ts_data);
int fts_remove_sysfs(struct fts_ts_data *ts_data);
/* ESD */
#if FTS_ESDCHECK_EN
int fts_esdcheck_init(struct fts_ts_data *ts_data);
int fts_esdcheck_exit(struct fts_ts_data *ts_data);
int fts_esdcheck_switch(bool enable);
int fts_esdcheck_proc_busy(bool proc_debug);
int fts_esdcheck_set_intr(bool intr);
int fts_esdcheck_suspend(void);
int fts_esdcheck_resume(void);
#endif
/* Production test */
#if FTS_TEST_EN
int fts_test_init(struct fts_ts_data *ts_data);
int fts_test_exit(struct fts_ts_data *ts_data);
#endif
/* Point Report Check*/
#if FTS_POINT_REPORT_CHECK_EN
int fts_point_report_check_init(struct fts_ts_data *ts_data);
int fts_point_report_check_exit(struct fts_ts_data *ts_data);
void fts_prc_queue_work(struct fts_ts_data *ts_data);
#endif
/* FW upgrade */
int fts_fwupg_init(struct fts_ts_data *ts_data);
int fts_fwupg_exit(struct fts_ts_data *ts_data);
int fts_upgrade_bin(char *fw_name, bool force);
int fts_enter_test_environment(bool test_state);
/* Other */
int fts_reset_proc(int hdelayms);
int fts_check_cid(struct fts_ts_data *ts_data, u8 id_h);
int fts_wait_tp_to_valid(void);
void fts_release_all_finger(void);
void fts_tp_state_recovery(struct fts_ts_data *ts_data);
int fts_ex_mode_init(struct fts_ts_data *ts_data);
int fts_ex_mode_exit(struct fts_ts_data *ts_data);
int fts_ex_mode_recovery(struct fts_ts_data *ts_data);
void fts_update_feature_setting(struct fts_ts_data *ts_data);
void fts_irq_disable(void);
void fts_irq_enable(void);
#if IS_ENABLED(CONFIG_TOUCHSCREEN_PANEL_BRIDGE)
/* Bus reference tracking */
int fts_ts_set_bus_ref(struct fts_ts_data *ts, u16 ref, bool enable);
#endif
#endif /* __LINUX_FOCALTECH_CORE_H__ */