sec_mmi: initial kernel driver

Kernel driver code for Samsung LSI. Includes MMI specific interfaces

Change-Id: I0b3ae080637f8f103d8d2928240841909ec6c258
Signed-off-by: Konstantin Makariev <hcv867@motorola.com>
Reviewed-on: https://gerrit.mot.com/1351484
SME-Granted: SME Approvals Granted
SLTApproved: Slta Waiver
Tested-by: Jira Key
Reviewed-by: Konstantin Makariev <kmakariev@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
Konstantin Makariev 2019-05-09 08:15:48 -05:00 • committed by Konstantin Makariev
commit af2bdde38f
11 changed files with 8906 additions and 0 deletions

View file

@ -0,0 +1,8 @@
DLKM_DIR := motorola/kernel/modules
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := sec_mmi.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/AndroidKernelModule.mk

View file

@ -0,0 +1,7 @@
# add -Wall to try to catch everything we can.
EXTRA_CFLAGS += -Wall
EXTRA_CFLAGS += -I$(TOP)/motorola/kernel/modules/include \
-I$(TOP)/motorola/kernel/modules/drivers/input/touchscreen/sec_mmi
obj-m := sec_mmi.o
sec_mmi-objs = sec_ts.o sec_ts_fn.o sec_ts_fw.o sec_ts_only_vendor.o sec_ts_mmi.o

View file

@ -0,0 +1,22 @@
#
# Samsung Electronics TOUCH driver configuration
#
config TOUCHSCREEN_SEC_TS
tristate "Samsung Electronics Touchscreen"
depends on I2C
help
Say Y here if you want support for SEC touchscreen controllers.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called sec_ts.
config TOUCHSCREEN_SEC_TS_GLOVEMODE
tristate "Samsung Electronics Touchscreen"
depends on I2C
help
Say Y here if you have a Samsung Electronics Touchscreen and want to enable
support for the built-in touchscreen.
If unsure, say N.

View file

@ -0,0 +1,10 @@
KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
all:
$(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS)
modules_install:
$(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(shell pwd) modules_install
clean:
$(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean

View file

@ -0,0 +1,25 @@
#ifndef _SEC_MMI_H_
#define _SEC_MMI_H_
#include <linux/major.h>
#include <linux/kdev_t.h>
#include <linux/notifier.h>
#include <linux/msm_drm_notify.h>
#define TSDEV_MINOR_BASE 128
#define TSDEV_MINOR_MAX 32
struct sec_mmi_data {
struct i2c_client *i2c_client;
struct device *ts_class_dev;
struct notifier_block panel_nb;
struct work_struct resume_work;
int ctrl_dsi;
char *image_name;
const char *class_entry_name;
const char *bound_display;
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,822 @@
/* drivers/input/touchscreen/sec_ts.h
*
* Copyright (C) 2015 Samsung Electronics Co., Ltd.
* http://www.samsungsemi.com/
*
* Core file for Samsung TSC driver
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __SEC_TS_H__
#define __SEC_TS_H__
#include <asm/unaligned.h>
#include <linux/completion.h>
#include <linux/ctype.h>
#include <linux/delay.h>
#include <linux/firmware.h>
#include <linux/gpio.h>
#include <linux/hrtimer.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/input/sec_cmd.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/uaccess.h>
#include <linux/vmalloc.h>
#include <linux/wakelock.h>
#include <linux/workqueue.h>
#ifdef CONFIG_INPUT_BOOSTER
#include <linux/input/input_booster.h>
#endif
#ifndef input_info
#define input_info(f, d, fmt, args...) dev_info(d, fmt ##args)
#endif
#ifndef input_err
#define input_info(f, d, fmt, args...) dev_info(d, fmt ##args)
#endif
#define SEC_TS_I2C_NAME "sec_ts"
#define SEC_TS_DEVICE_NAME "SEC_TS"
#define USE_OPEN_CLOSE
#undef USE_RESET_DURING_POWER_ON
#undef USE_RESET_EXIT_LPM
#define USE_POR_AFTER_I2C_RETRY
#undef USER_OPEN_DWORK
#define USE_PRESSURE_SENSOR
#define PAT_CONTROL
#if defined(USE_RESET_DURING_POWER_ON) || defined(USE_POR_AFTER_I2C_RETRY) || defined(USE_RESET_EXIT_LPM)
#define USE_POWER_RESET_WORK
#endif
#define TOUCH_RESET_DWORK_TIME 10
#define BRUSH_Z_DATA 63 /* for ArtCanvas */
#define MASK_1_BITS 0x0001
#define MASK_2_BITS 0x0003
#define MASK_3_BITS 0x0007
#define MASK_4_BITS 0x000F
#define MASK_5_BITS 0x001F
#define MASK_6_BITS 0x003F
#define MASK_7_BITS 0x007F
#define MASK_8_BITS 0x00FF
/* support feature */
//#define SEC_TS_SUPPORT_CUSTOMLIB /* support user defined library */
#define TYPE_STATUS_EVENT_CMD_DRIVEN 0
#define TYPE_STATUS_EVENT_ERR 1
#define TYPE_STATUS_EVENT_INFO 2
#define TYPE_STATUS_EVENT_USER_INPUT 3
#define TYPE_STATUS_EVENT_CUSTOMLIB_INFO 6
#define TYPE_STATUS_EVENT_VENDOR_INFO 7
#define TYPE_STATUS_CODE_SAR 0x28
#define BIT_STATUS_EVENT_CMD_DRIVEN(a) (a << TYPE_STATUS_EVENT_CMD_DRIVEN)
#define BIT_STATUS_EVENT_ERR(a) (a << TYPE_STATUS_EVENT_ERR)
#define BIT_STATUS_EVENT_INFO(a) (a << TYPE_STATUS_EVENT_INFO)
#define BIT_STATUS_EVENT_USER_INPUT(a) (a << TYPE_STATUS_EVENT_USER_INPUT)
#define BIT_STATUS_EVENT_VENDOR_INFO(a) (a << TYPE_STATUS_EVENT_VENDOR_INFO)
#define DO_FW_CHECKSUM (1 << 0)
#define DO_PARA_CHECKSUM (1 << 1)
#define MAX_SUPPORT_TOUCH_COUNT 10
#define MAX_SUPPORT_HOVER_COUNT 1
#define SEC_TS_EVENTID_HOVER 10
#define SEC_TS_DEFAULT_FW_NAME "tsp_sec/sec_hero.fw"
#define SEC_TS_DEFAULT_BL_NAME "tsp_sec/s6smc41_blupdate_img_REL.bin"
#define SEC_TS_DEFAULT_PARA_NAME "tsp_sec/s6smc41_para_REL_DGA0_V0106_150114_193317.bin"
#define SEC_TS_DEFAULT_UMS_FW "/sdcard/Firmware/TSP/lsi.bin"
#define SEC_TS_DEFAULT_FFU_FW "ffu_tsp.bin"
#define SEC_TS_MAX_FW_PATH 64
#define SEC_TS_FW_BLK_SIZE_MAX (512)
#define SEC_TS_FW_BLK_SIZE_DEFAULT (512)
#define SEC_TS_SELFTEST_REPORT_SIZE 80
#define I2C_WRITE_BUFFER_SIZE (256 - 1)//10
#define SEC_TS_FW_HEADER_SIGN 0x53494654
#define SEC_TS_FW_CHUNK_SIGN 0x53434654
#define SEC_TS_FW_UPDATE_ON_PROBE
#define AMBIENT_CAL 0
#define OFFSET_CAL_SDC 1
#define OFFSET_CAL_SET 2
#define PRESSURE_CAL 3
#define SEC_TS_SKIPTSP_DUTY 100
#define SEC_TS_NVM_OFFSET_FAC_RESULT 0
#define SEC_TS_NVM_OFFSET_CAL_COUNT 1
#define SEC_TS_NVM_OFFSET_DISASSEMBLE_COUNT 2
#define SEC_TS_NVM_OFFSET_TUNE_VERSION 3
#define SEC_TS_NVM_OFFSET_TUNE_VERSION_LENGTH 2
#define SEC_TS_NVM_OFFSET_LENGTH (SEC_TS_NVM_LAST_BLOCK_OFFSET + SEC_TS_NVM_LAST_BLOCK_SIZE + 1)
/* SEC_TS READ REGISTER ADDRESS */
#define SEC_TS_CMD_SENSE_ON 0x10
#define SEC_TS_CMD_SENSE_OFF 0x11
#define SEC_TS_CMD_SW_RESET 0x12
#define SEC_TS_CMD_CALIBRATION_SEC 0x13 // send it to touch ic, but toucu ic works nothing.
#define SEC_TS_CMD_FACTORY_PANELCALIBRATION 0x14
#define SEC_TS_READ_GPIO_STATUS 0x20 // not support
#define SEC_TS_READ_FIRMWARE_INTEGRITY 0x21
#define SEC_TS_READ_DEVICE_ID 0x22
#define SEC_TS_READ_PANEL_INFO 0x23
#define SEC_TS_READ_CORE_CONFIG_VERSION 0x24
#define SEC_TS_CMD_SET_TOUCHFUNCTION 0x30
#define SEC_TS_CMD_SET_TSC_MODE 0x31
#define SET_TS_CMD_SET_CHARGER_MODE 0x32
#define SET_TS_CMD_SET_NOISE_MODE 0x33
#define SET_TS_CMD_SET_REPORT_RATE 0x34
#define SEC_TS_CMD_TOUCH_MODE_FOR_THRESHOLD 0x35
#define SEC_TS_CMD_TOUCH_THRESHOLD 0x36
#define SET_TS_CMD_KEY_THRESHOLD 0x37
#define SEC_TS_CMD_SET_COVERTYPE 0x38
#define SEC_TS_CMD_WAKEUP_GESTURE_MODE 0x39
#define SEC_TS_WRITE_POSITION_FILTER 0x3A
#define SEC_TS_CMD_WET_MODE 0x3B
#define SEC_TS_CMD_ERASE_FLASH 0x45
#define SEC_TS_READ_ID 0x52
#define SEC_TS_READ_BOOT_STATUS 0x55
#define SEC_TS_CMD_ENTER_FW_MODE 0x57
#define SEC_TS_READ_ONE_EVENT 0x60
#define SEC_TS_READ_ALL_EVENT 0x61
#define SEC_TS_CMD_CLEAR_EVENT_STACK 0x62
#define SEC_TS_CMD_MUTU_RAW_TYPE 0x70
#define SEC_TS_CMD_SELF_RAW_TYPE 0x71
#define SEC_TS_READ_TOUCH_RAWDATA 0x72
#define SEC_TS_READ_TOUCH_SELF_RAWDATA 0x73
#define SEC_TS_READ_SELFTEST_RESULT 0x80
#define SEC_TS_CMD_CALIBRATION_AMBIENT 0x81
#define SEC_TS_CMD_P2P_TEST 0x82
#define SEC_TS_CMD_P2P_MODE 0x83
#define SEC_TS_CMD_NVM 0x85
#define SEC_TS_CMD_STATEMANAGE_ON 0x8E
#define SEC_TS_CMD_CALIBRATION_OFFSET_SDC 0x8F
/* SEC_TS CUSTOMLIB OPCODE COMMAND */
#define SEC_TS_CMD_CUSTOMLIB_GET_INFO 0x90
#define SEC_TS_CMD_CUSTOMLIB_WRITE_PARAM 0x91
#define SEC_TS_CMD_CUSTOMLIB_READ_PARAM 0x92
#define SEC_TS_CMD_CUSTOMLIB_NOTIFY_PACKET 0x93
#define SEC_TS_CMD_STATUS_EVENT_TYPE 0xA0
#define SEC_TS_READ_FW_INFO 0xA2
#define SEC_TS_READ_FW_VERSION 0xA3
#define SEC_TS_READ_PARA_VERSION 0xA4
#define SEC_TS_READ_IMG_VERSION 0xA5
#define SEC_TS_CMD_GET_CHECKSUM 0xA6
#define SEC_TS_CMD_MIS_CAL_CHECK 0xA7
#define SEC_TS_CMD_MIS_CAL_READ 0xA8
#define SEC_TS_CMD_MIS_CAL_SPEC 0xA9
#define SEC_TS_CMD_DEADZONE_RANGE 0xAA
#define SEC_TS_CMD_LONGPRESSZONE_RANGE 0xAB
#define SEC_TS_CMD_LONGPRESS_DROP_AREA 0xAC
#define SEC_TS_CMD_LONGPRESS_DROP_DIFF 0xAD
#define SEC_TS_READ_TS_STATUS 0xAF
#define SEC_TS_CMD_SELFTEST 0xAE
#define SEC_TS_READ_FORCE_RECAL_COUNT 0xB0
#define SEC_TS_READ_FORCE_SIG_MAX_VAL 0xB1
/* SEC_TS FLASH COMMAND */
#define SEC_TS_CMD_FLASH_READ_ADDR 0xD0
#define SEC_TS_CMD_FLASH_READ_SIZE 0xD1
#define SEC_TS_CMD_FLASH_READ_DATA 0xD2
#define SEC_TS_CMD_CHG_SYSMODE 0xD7
#define SEC_TS_CMD_FLASH_ERASE 0xD8
#define SEC_TS_CMD_FLASH_WRITE 0xD9
#define SEC_TS_CMD_FLASH_PADDING 0xDA
#define SEC_TS_READ_BL_UPDATE_STATUS 0xDB
#define SEC_TS_CMD_SET_POWER_MODE 0xE4
#define SEC_TS_CMD_EDGE_DEADZONE 0xE5
#define SEC_TS_CMD_SET_DEX_MODE 0xE7
#define SEC_TS_CMD_CALIBRATION_PRESSURE 0xE9
/* Have to need delay 30msec after writing 0xEA command */
/* Do not write Zero with 0xEA command */
#define SEC_TS_CMD_SET_GET_PRESSURE 0xEA
#define SEC_TS_CMD_SET_USER_PRESSURE 0xEB
#define SEC_TS_CMD_SET_TEMPERATURE_COMP_MODE 0xEC
#define SEC_TS_CMD_SET_TOUCHABLE_AREA 0xED
#define SEC_TS_CMD_SET_BRUSH_MODE 0xEF
#define SEC_TS_READ_CALIBRATION_REPORT 0xF1
#define SEC_TS_CMD_SET_VENDOR_EVENT_LEVEL 0xF2
#define SEC_TS_CMD_SET_SPENMODE 0xF3
#define SEC_TS_CMD_SELECT_PRESSURE_TYPE 0xF5
#define SEC_TS_CMD_READ_PRESSURE_DATA 0xF6
#define SEC_TS_FLASH_SIZE_64 64
#define SEC_TS_FLASH_SIZE_128 128
#define SEC_TS_FLASH_SIZE_256 256
#define SEC_TS_FLASH_SIZE_CMD 1
#define SEC_TS_FLASH_SIZE_ADDR 2
#define SEC_TS_FLASH_SIZE_CHECKSUM 1
#define SEC_TS_STATUS_BOOT_MODE 0x10
#define SEC_TS_STATUS_APP_MODE 0x20
#define SEC_TS_FIRMWARE_PAGE_SIZE_256 256
#define SEC_TS_FIRMWARE_PAGE_SIZE_128 128
/* SEC status event id */
#define SEC_TS_COORDINATE_EVENT 0
#define SEC_TS_STATUS_EVENT 1
#define SEC_TS_GESTURE_EVENT 2
#define SEC_TS_EMPTY_EVENT 3
#define SEC_TS_EVENT_BUFF_SIZE 8
#define SEC_TS_SID_GESTURE 0x14
#define SEC_TS_GESTURE_CODE_SPAY 0x00
#define SEC_TS_GESTURE_CODE_DOUBLE_TAP 0x01
#define SEC_TS_COORDINATE_ACTION_NONE 0
#define SEC_TS_COORDINATE_ACTION_PRESS 1
#define SEC_TS_COORDINATE_ACTION_MOVE 2
#define SEC_TS_COORDINATE_ACTION_RELEASE 3
#define SEC_TS_TOUCHTYPE_NORMAL 0
#define SEC_TS_TOUCHTYPE_HOVER 1
#define SEC_TS_TOUCHTYPE_FLIPCOVER 2
#define SEC_TS_TOUCHTYPE_GLOVE 3
#define SEC_TS_TOUCHTYPE_STYLUS 4
#define SEC_TS_TOUCHTYPE_PALM 5
#define SEC_TS_TOUCHTYPE_WET 6
#define SEC_TS_TOUCHTYPE_PROXIMITY 7
#define SEC_TS_TOUCHTYPE_JIG 8
/* SEC_TS_INFO : Info acknowledge event */
#define SEC_TS_ACK_BOOT_COMPLETE 0x00
#define SEC_TS_ACK_WET_MODE 0x1
/* SEC_TS_VENDOR_INFO : Vendor acknowledge event */
#define SEC_TS_VENDOR_ACK_OFFSET_CAL_DONE 0x40
#define SEC_TS_VENDOR_ACK_SELF_TEST_DONE 0x41
#define SEC_TS_VENDOR_ACK_CMR_TEST_DONE 0x42 /* mutual */
#define SEC_TS_VENDOR_ACK_NOISE_STATUS_NOTI 0x64
/* SEC_TS_STATUS_EVENT_USER_INPUT */
#define SEC_TS_EVENT_FORCE_KEY 0x1
/* SEC_TS_STATUS_EVENT_CUSTOMLIB_INFO */
#define SEC_TS_EVENT_CUSTOMLIB_FORCE_KEY 0x00
/* SEC_TS_ERROR : Error event */
#define SEC_TS_ERR_EVNET_CORE_ERR 0x0
#define SEC_TS_ERR_EVENT_QUEUE_FULL 0x01
#define SEC_TS_ERR_EVENT_ESD 0x2
/* SEC_TS_DEBUG : Print event contents */
#define SEC_TS_DEBUG_PRINT_ALLEVENT 0x01
#define SEC_TS_DEBUG_PRINT_ONEEVENT 0x02
#define SEC_TS_DEBUG_PRINT_I2C_READ_CMD 0x04
#define SEC_TS_DEBUG_PRINT_I2C_WRITE_CMD 0x08
#define SEC_TS_DEBUG_SEND_UEVENT 0x80
#define SEC_TS_BIT_SETFUNC_TOUCH (1 << 0)
#define SEC_TS_BIT_SETFUNC_MUTUAL (1 << 0)
#define SEC_TS_BIT_SETFUNC_HOVER (1 << 1)
#define SEC_TS_BIT_SETFUNC_COVER (1 << 2)
#define SEC_TS_BIT_SETFUNC_GLOVE (1 << 3)
#define SEC_TS_BIT_SETFUNC_STYLUS (1 << 4)
#define SEC_TS_BIT_SETFUNC_PALM (1 << 5)
#define SEC_TS_BIT_SETFUNC_WET (1 << 6)
#define SEC_TS_BIT_SETFUNC_PROXIMITY (1 << 7)
#define SEC_TS_DEFAULT_ENABLE_BIT_SETFUNC (SEC_TS_BIT_SETFUNC_TOUCH | SEC_TS_BIT_SETFUNC_PALM | SEC_TS_BIT_SETFUNC_WET)
#define SEC_TS_BIT_CHARGER_MODE_NO (0x1 << 0)
#define SEC_TS_BIT_CHARGER_MODE_WIRE_CHARGER (0x1 << 1)
#define SEC_TS_BIT_CHARGER_MODE_WIRELESS_CHARGER (0x1 << 2)
#define SEC_TS_BIT_CHARGER_MODE_WIRELESS_BATTERY_PACK (0x1 << 3)
#define STATE_MANAGE_ON 1
#define STATE_MANAGE_OFF 0
#define SEC_TS_STATUS_NOT_CALIBRATION 0x50
#define SEC_TS_STATUS_CALIBRATION_SDC 0xA1
#define SEC_TS_STATUS_CALIBRATION_SEC 0xA2
#define SEC_TS_CMD_EDGE_HANDLER 0xAA
#define SEC_TS_CMD_EDGE_AREA 0xAB
#define SEC_TS_CMD_DEAD_ZONE 0xAC
#define SEC_TS_CMD_LANDSCAPE_MODE 0xAD
enum grip_write_mode {
G_NONE = 0,
G_SET_EDGE_HANDLER = 1,
G_SET_EDGE_ZONE = 2,
G_SET_NORMAL_MODE = 4,
G_SET_LANDSCAPE_MODE = 8,
G_CLR_LANDSCAPE_MODE = 16,
};
enum grip_set_data {
ONLY_EDGE_HANDLER = 0,
GRIP_ALL_DATA = 1,
};
typedef enum {
SEC_TS_STATE_POWER_OFF = 0,
SEC_TS_STATE_LPM,
SEC_TS_STATE_POWER_ON
} TOUCH_POWER_MODE;
typedef enum {
TOUCH_SYSTEM_MODE_BOOT = 0,
TOUCH_SYSTEM_MODE_CALIBRATION = 1,
TOUCH_SYSTEM_MODE_TOUCH = 2,
TOUCH_SYSTEM_MODE_SELFTEST = 3,
TOUCH_SYSTEM_MODE_FLASH = 4,
TOUCH_SYSTEM_MODE_LOWPOWER = 5,
TOUCH_SYSTEM_MODE_LISTEN
} TOUCH_SYSTEM_MODE;
typedef enum {
TOUCH_MODE_STATE_IDLE = 0,
TOUCH_MODE_STATE_HOVER = 1,
TOUCH_MODE_STATE_TOUCH = 2,
TOUCH_MODE_STATE_NOISY = 3,
TOUCH_MODE_STATE_CAL = 4,
TOUCH_MODE_STATE_CAL2 = 5,
TOUCH_MODE_STATE_WAKEUP = 10
} TOUCH_MODE_STATE;
enum switch_system_mode {
TO_TOUCH_MODE = 0,
TO_LOWPOWER_MODE = 1,
TO_SELFTEST_MODE = 2,
TO_FLASH_MODE = 3,
};
enum {
TYPE_RAW_DATA = 0, /* Total - Offset : delta data */
TYPE_SIGNAL_DATA = 1, /* Signal - Filtering & Normalization */
TYPE_AMBIENT_BASELINE = 2, /* Cap Baseline */
TYPE_AMBIENT_DATA = 3, /* Cap Ambient */
TYPE_REMV_BASELINE_DATA = 4,
TYPE_DECODED_DATA = 5, /* Raw */
TYPE_REMV_AMB_DATA = 6, /* TYPE_RAW_DATA - TYPE_AMBIENT_DATA */
TYPE_OFFSET_DATA_SET = 19, /* Cap Offset in SET Manufacturing Line */
TYPE_OFFSET_DATA_SDC = 29, /* Cap Offset in SDC Manufacturing Line */
TYPE_RAW_DATA_P2P_MIN = 30, /* Raw min data for 100 frame */
TYPE_RAW_DATA_P2P_MAX = 31, /* Raw max data for 100 frame */
TYPE_RAWDATA_MAX,
TYPE_INVALID_DATA = 0xFF, /* Invalid data type for release factory mode */
};
typedef enum {
CUSTOMLIB_EVENT_TYPE_SPAY = 0x04,
CUSTOMLIB_EVENT_TYPE_PRESSURE_TOUCHED = 0x05,
CUSTOMLIB_EVENT_TYPE_PRESSURE_RELEASED = 0x06,
CUSTOMLIB_EVENT_TYPE_AOD = 0x08,
CUSTOMLIB_EVENT_TYPE_AOD_PRESS = 0x09,
CUSTOMLIB_EVENT_TYPE_AOD_LONGPRESS = 0x0A,
CUSTOMLIB_EVENT_TYPE_AOD_DOUBLETAB = 0x0B,
CUSTOMLIB_EVENT_TYPE_AOD_HOMEKEY_PRESS = 0x0C,
CUSTOMLIB_EVENT_TYPE_AOD_HOMEKEY_RELEASE = 0x0D,
CUSTOMLIB_EVENT_TYPE_AOD_HOMEKEY_RELEASE_NO_HAPTIC = 0x0E
} CUSTOMLIB_EVENT_TYPE;
#define CMD_RESULT_WORD_LEN 10
#define SEC_TS_I2C_RETRY_CNT 3
#define SEC_TS_WAIT_RETRY_CNT 100
#define SEC_TS_MODE_CUSTOMLIB_SPAY (1 << 1)
#define SEC_TS_MODE_CUSTOMLIB_AOD (1 << 2)
#define SEC_TS_MODE_CUSTOMLIB_FORCE_KEY (1 << 6)
#define SEC_TS_MODE_LOWPOWER_FLAG (SEC_TS_MODE_CUSTOMLIB_SPAY | SEC_TS_MODE_CUSTOMLIB_AOD \
| SEC_TS_MODE_CUSTOMLIB_FORCE_KEY)
#define SEC_TS_CUSTOMLIB_EVENT_PRESSURE_TOUCHED (1 << 6)
#define SEC_TS_CUSTOMLIB_EVENT_PRESSURE_RELEASED (1 << 7)
enum sec_ts_cover_id {
SEC_TS_FLIP_WALLET = 0,
SEC_TS_VIEW_COVER,
SEC_TS_COVER_NOTHING1,
SEC_TS_VIEW_WIRELESS,
SEC_TS_COVER_NOTHING2,
SEC_TS_CHARGER_COVER,
SEC_TS_VIEW_WALLET,
SEC_TS_LED_COVER,
SEC_TS_CLEAR_FLIP_COVER,
SEC_TS_QWERTY_KEYBOARD_EUR,
SEC_TS_QWERTY_KEYBOARD_KOR,
SEC_TS_MONTBLANC_COVER = 100,
};
enum sec_fw_update_status {
SEC_NOT_UPDATE = 0,
SEC_NEED_FW_UPDATE,
SEC_NEED_CALIBRATION_ONLY,
SEC_NEED_FW_UPDATE_N_CALIBRATION,
};
enum tsp_hw_parameter {
TSP_ITO_CHECK = 1,
TSP_RAW_CHECK = 2,
TSP_MULTI_COUNT = 3,
TSP_WET_MODE = 4,
TSP_COMM_ERR_COUNT = 5,
TSP_MODULE_ID = 6,
};
#define TEST_MODE_MIN_MAX false
#define TEST_MODE_ALL_NODE true
#define TEST_MODE_READ_FRAME false
#define TEST_MODE_READ_CHANNEL true
/* factory test mode */
struct sec_ts_test_mode {
u8 type;
short min;
short max;
bool allnode;
bool frame_channel;
};
struct sec_ts_fw_file {
u8 *data;
u32 pos;
size_t size;
};
/*
* write 0xE4 [ 11 | 10 | 01 | 00 ]
* MSB <-------------------> LSB
* read 0xE4
* mapping sequnce : LSB -> MSB
* struct sec_ts_test_result {
* * assy : front + OCTA assay
* * module : only OCTA
* union {
* struct {
* u8 assy_count:2; -> 00
* u8 assy_result:2; -> 01
* u8 module_count:2; -> 10
* u8 module_result:2; -> 11
* } __attribute__ ((packed));
* unsigned char data[1];
* };
*};
*/
struct sec_ts_test_result {
union {
struct {
u8 assy_count:2;
u8 assy_result:2;
u8 module_count:2;
u8 module_result:2;
} __attribute__ ((packed));
unsigned char data[1];
};
};
/* 8 byte */
struct sec_ts_gesture_status {
u8 eid:2;
u8 stype:4;
u8 sf:2;
u8 gesture_id;
u8 gesture_data_1;
u8 gesture_data_2;
u8 gesture_data_3;
u8 gesture_data_4;
u8 reserved_1;
u8 left_event_5_0:6;
u8 reserved_2:2;
} __attribute__ ((packed));
/* 8 byte */
struct sec_ts_event_status {
u8 eid:2;
u8 stype:4;
u8 sf:2;
u8 status_id;
u8 status_data_1;
u8 status_data_2;
u8 status_data_3;
u8 status_data_4;
u8 status_data_5;
u8 left_event_5_0:6;
u8 reserved_2:2;
} __attribute__ ((packed));
/* 8 byte */
struct sec_ts_event_coordinate {
u8 eid:2;
u8 tid:4;
u8 tchsta:2;
u8 x_11_4;
u8 y_11_4;
u8 y_3_0:4;
u8 x_3_0:4;
u8 major;
u8 minor;
u8 z:6;
u8 ttype_3_2:2;
u8 left_event:6;
u8 ttype_1_0:2;
} __attribute__ ((packed));
/* not fixed */
struct sec_ts_coordinate {
u8 id;
u8 ttype;
u8 action;
u16 x;
u16 y;
u8 z;
u8 hover_flag;
u8 glove_flag;
u8 touch_height;
u16 mcount;
u8 major;
u8 minor;
bool palm;
int palm_count;
u8 left_event;
};
struct sec_ts_data {
u32 isr_pin;
u32 crc_addr;
u32 fw_addr;
u32 para_addr;
u32 flash_page_size;
u8 boot_ver[3];
struct device *dev;
struct i2c_client *client;
struct input_dev *input_dev;
struct input_dev *input_dev_pad;
struct input_dev *input_dev_touch;
struct sec_ts_plat_data *plat_data;
struct sec_ts_coordinate coord[MAX_SUPPORT_TOUCH_COUNT + MAX_SUPPORT_HOVER_COUNT];
struct timeval time_pressed[MAX_SUPPORT_TOUCH_COUNT + MAX_SUPPORT_HOVER_COUNT];
struct timeval time_released[MAX_SUPPORT_TOUCH_COUNT + MAX_SUPPORT_HOVER_COUNT];
long time_longest;
u8 lowpower_mode;
u8 lowpower_status;
u8 dex_mode;
char *dex_name;
u8 brush_mode;
u8 touchable_area;
volatile u8 touch_noise_status;
volatile bool input_closed;
int touch_count;
int tx_count;
int rx_count;
int i2c_burstmax;
int ta_status;
volatile int power_status;
int raw_status;
int touchkey_glove_mode_status;
u16 touch_functions;
u8 charger_mode;
struct sec_ts_event_coordinate touchtype;
bool touched[11];
u8 gesture_status[6];
u8 cal_status;
struct mutex lock;
struct mutex device_mutex;
struct mutex i2c_mutex;
struct mutex eventlock;
struct mutex modechange;
struct delayed_work work_read_info;
#ifdef USE_POWER_RESET_WORK
struct delayed_work reset_work;
volatile bool reset_is_on_going;
#endif
struct completion resume_done;
struct wake_lock wakelock;
struct sec_cmd_data sec;
short *pFrame;
bool probe_done;
bool reinit_done;
bool flip_enable;
bool info_work_done;
int cover_type;
u8 cover_cmd;
u16 rect_data[4];
int tspid_val;
int tspicid_val;
bool use_customlib;
unsigned int scrub_id;
unsigned int scrub_x;
unsigned int scrub_y;
u8 grip_edgehandler_direction;
int grip_edgehandler_start_y;
int grip_edgehandler_end_y;
u16 grip_edge_range;
u8 grip_deadzone_up_x;
u8 grip_deadzone_dn_x;
int grip_deadzone_y;
u8 grip_landscape_mode;
int grip_landscape_edge;
u16 grip_landscape_deadzone;
#ifdef CONFIG_TOUCHSCREEN_DUMP_MODE
struct delayed_work ghost_check;
u8 tsp_dump_lock;
#endif
int nv;
int cal_count;
int tune_fix_ver;
bool external_factory;
int wet_mode;
unsigned char ito_test[4]; /* ito panel tx/rx chanel */
unsigned char check_multi;
unsigned int multi_count; /* multi touch count */
unsigned int wet_count; /* wet mode count */
unsigned int noise_count; /* noise mode count */
unsigned int dive_count; /* dive mode count */
unsigned int comm_err_count; /* i2c comm error count */
unsigned int checksum_result; /* checksum result */
unsigned char module_id[4];
unsigned int all_finger_count;
unsigned int all_force_count;
unsigned int all_aod_tap_count;
unsigned int all_spay_count;
unsigned int max_z_value;
unsigned int min_z_value;
unsigned int sum_z_value;
unsigned char pressure_cal_base;
unsigned char pressure_cal_delta;
/* for factory - factory_cmd_result_all() */
short cm_raw_set_p2p_min; //CM_RAW_SET_P2P
short cm_raw_set_p2p_max; //CM_RAW_SET_P2P
short cm_raw_set_p2p_diff; //CM_RAW_SET_P2P_DIFF
#ifdef USE_PRESSURE_SENSOR
short pressure_left;
short pressure_center;
short pressure_right;
u8 pressure_user_level;
#endif
int debug_flag;
int (*sec_ts_i2c_write)(struct sec_ts_data *ts, u8 reg, u8 *data, int len);
int (*sec_ts_i2c_read)(struct sec_ts_data *ts, u8 reg, u8 *data, int len);
int (*sec_ts_i2c_write_burst)(struct sec_ts_data *ts, u8 *data, int len);
int (*sec_ts_i2c_read_bulk)(struct sec_ts_data *ts, u8 *data, int len);
int (*sec_ts_read_customlib)(struct sec_ts_data *ts, u8 *data, int len);
};
struct sec_ts_plat_data {
int max_x;
int max_y;
unsigned irq_gpio;
int irq_type;
int i2c_burstmax;
int always_lpmode;
int bringup;
int mis_cal_check;
const char *firmware_name;
const char *model_name;
const char *project_name;
const char *regulator_dvdd;
const char *regulator_avdd;
u32 panel_revision;
u8 core_version_of_ic[4];
u8 core_version_of_bin[4];
u8 config_version_of_ic[4];
u8 config_version_of_bin[4];
u8 img_version_of_ic[4];
u8 img_version_of_bin[4];
struct pinctrl *pinctrl;
int (*power)(void *data, bool on);
void (*enable_sync)(bool on);
int tsp_icid;
int tsp_id;
int tsp_vsync;
bool regulator_boot_on;
bool support_mt_pressure;
bool support_dex;
bool support_sidegesture;
};
typedef struct {
u32 signature; /* signature */
u32 version; /* version */
u32 totalsize; /* total size */
u32 checksum; /* checksum */
u32 img_ver; /* image file version */
u32 img_date; /* image file date */
u32 img_description; /* image file description */
u32 fw_ver; /* firmware version */
u32 fw_date; /* firmware date */
u32 fw_description; /* firmware description */
u32 para_ver; /* parameter version */
u32 para_date; /* parameter date */
u32 para_description; /* parameter description */
u32 num_chunk; /* number of chunk */
u32 reserved1;
u32 reserved2;
} fw_header;
typedef struct {
u32 signature;
u32 addr;
u32 size;
u32 reserved;
} fw_chunk;
int sec_ts_power(void *data, bool on);
int sec_ts_stop_device(struct sec_ts_data *ts);
int sec_ts_start_device(struct sec_ts_data *ts);
int sec_ts_set_lowpowermode(struct sec_ts_data *ts, u8 mode);
int sec_ts_firmware_update_on_probe(struct sec_ts_data *ts, bool force_update);
int sec_ts_firmware_update_on_hidden_menu(struct sec_ts_data *ts, int update_type);
int sec_ts_glove_mode_enables(struct sec_ts_data *ts, int mode);
int sec_ts_set_cover_type(struct sec_ts_data *ts, bool enable);
int sec_ts_wait_for_ready(struct sec_ts_data *ts, unsigned int ack);
int sec_ts_function(int (*func_init)(void *device_data), void (*func_remove)(void));
int sec_ts_fn_init(struct sec_ts_data *ts);
int sec_ts_read_calibration_report(struct sec_ts_data *ts);
int sec_ts_execute_force_calibration(struct sec_ts_data *ts, int cal_mode);
int sec_ts_fix_tmode(struct sec_ts_data *ts, u8 mode, u8 state);
int sec_ts_release_tmode(struct sec_ts_data *ts);
int get_tsp_nvm_data(struct sec_ts_data *ts, u8 offset);
int get_tsp_nvm_data_by_size(struct sec_ts_data *ts, u8 offset, int length, u8 *data);
void set_tsp_nvm_data_clear(struct sec_ts_data *ts, u8 offset);
#ifdef SEC_TS_SUPPORT_CUSTOMLIB
int sec_ts_set_custom_library(struct sec_ts_data *ts);
int sec_ts_check_custom_library(struct sec_ts_data *ts);
#endif
void sec_ts_unlocked_release_all_finger(struct sec_ts_data *ts);
void sec_ts_locked_release_all_finger(struct sec_ts_data *ts);
void sec_ts_fn_remove(struct sec_ts_data *ts);
void sec_ts_delay(unsigned int ms);
int sec_ts_read_information(struct sec_ts_data *ts);
int execute_selftest(struct sec_ts_data *ts, bool save_result);
void sec_ts_run_rawdata_all(struct sec_ts_data *ts, bool full_read);
void sec_ts_reinit(struct sec_ts_data *ts);
#if (1)//!defined(CONFIG_SAMSUNG_PRODUCT_SHIP)
int sec_ts_raw_device_init(struct sec_ts_data *ts);
#endif
extern bool tsp_init_done;
extern struct sec_ts_data *ts_dup;
#ifdef CONFIG_BATTERY_SAMSUNG
extern unsigned int lpcharge;
#endif
extern void set_grip_data_to_ic(struct sec_ts_data *ts, u8 flag);
extern void sec_ts_set_grip_type(struct sec_ts_data *ts, u8 set_type);
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,419 @@
/*
* Copyright (C) 2018 Motorola Mobility LLC
*
* 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.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/firmware.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/irq.h>
#include <linux/of_gpio.h>
#include <linux/time.h>
#include <linux/vmalloc.h>
#include <linux/uaccess.h>
#include "sec_mmi.h"
/* MMI specific sysfs entries and API */
#define DEV_MMI (&data->i2c_client->dev)
#define DEV_TS (&ts->client->dev)
static inline ssize_t sec_mmi_store_error(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count);
static ssize_t sec_mmi_forcereflash_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size);
static ssize_t sec_mmi_doreflash_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size);
static ssize_t sec_mmi_drv_irq_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size);
static ssize_t sec_mmi_drv_irq_show(struct device *dev,
struct device_attribute *attr, char *buf);
static inline ssize_t sec_mmi_show_error(struct device *dev,
struct device_attribute *attr, char *buf);
static ssize_t sec_mmi_ic_ver_show(struct device *dev,
struct device_attribute *attr, char *buf);
static ssize_t sec_mmi_poweron_show(struct device *dev,
struct device_attribute *attr, char *buf);
static DEVICE_ATTR(forcereflash, (S_IWUSR | S_IWGRP), NULL, sec_mmi_forcereflash_store);
static DEVICE_ATTR(doreflash, (S_IWUSR | S_IWGRP), NULL, sec_mmi_doreflash_store);
static DEVICE_ATTR(drv_irq, (S_IWUSR | S_IWGRP | S_IRUGO), sec_mmi_drv_irq_show, sec_mmi_drv_irq_store);
static DEVICE_ATTR(hw_irqstat, S_IRUGO, sec_mmi_hw_irqstat_show, NULL);
static DEVICE_ATTR(ic_ver, S_IRUGO, sec_mmi_ic_ver_show, NULL);
static DEVICE_ATTR(poweron, S_IRUGO, sec_mmi_poweron_show, NULL);
static struct attribute *mmi_attributes[] = {
&dev_attr_sec_mmi_forcereflash.attr,
&dev_attr_sec_mmi_fdoreflash.attr,
&dev_attr_sec_mmi_drv_irq.attr,
&dev_attr_sec_mmi_hw_irqstat.attr,
&dev_attr_sec_mmi_ic_ver.attr,
&dev_attr_sec_mmi_poweron.attr,
NULL,
};
static struct attribute_group mmi_attr_group = {
.attrs = mmi_attributes,
};
/* Attribute: path (RO) */
static ssize_t path_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct sec_mmi_data *data = dev_get_drvdata(dev);
ssize_t blen;
const char *path;
if (!data) {
dev_err(DEV_MMI "data pointer is NULL\n");
return (ssize_t)0;
}
path = kobject_get_path(&data->i2c_client->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, "samsung");
}
static struct device_attribute class_attributes[] = {
__ATTR_RO(path),
__ATTR_RO(vendor),
__ATTR_NULL
};
static int sec_mmi_touchscreen_class(
struct sec_mmi_data *data, bool create)
{
struct device_attribute *attrs = touchscreen_attributes;
int i, error = 0;
const char *class_fname = "primary";
static struct class *touchscreen_class;
static int minor;
if (create) {
minor = input_get_new_minor(data->i2c_client->addr,
1, false);
if (minor < 0)
minor = input_get_new_minor(TSDEV_MINOR_BASE,
TSDEV_MINOR_MAX, true);
dev_info(DEV_MMI, "assigned minor %d\n", minor);
if (!touchscreen_class) {
touchscreen_class = class_create(THIS_MODULE, "touchscreen");
if (IS_ERR(touchscreen_class)) {
error = PTR_ERR(touchscreen_class);
touchscreen_class = NULL;
return error;
}
}
if (data->class_entry_name)
class_fname = data->class_entry_name;
data->ts_class_dev = device_create(touchscreen_class,
NULL, MKDEV(INPUT_MAJOR, minor), data, class_fname);
if (IS_ERR(data->ts_class_dev)) {
error = PTR_ERR(data->ts_class_dev);
data->ts_class_dev = NULL;
return error;
}
dev_set_drvdata(data->ts_class_dev, data);
for (i = 0; class_attrs[i].attr.name != NULL; ++i) {
error = device_create_file(data->ts_class_dev, &class_attrs[i]);
if (error)
break;
}
if (error)
goto device_destroy;
} else {
if (!touchscreen_class || !data->ts_class_dev)
return -ENODEV;
dev_set_drvdata(rmi4_data->ts_class_dev, NULL);
for (i = 0; class_attrs[i].attr.name != NULL; ++i)
device_remove_file(data->ts_class_dev, &class_attrs[i]);
device_unregister(data->ts_class_dev);
data->ts_class_dev = NULL;
}
return 0;
device_destroy:
for (--i; i >= 0; --i)
device_remove_file(data->ts_class_dev, &class_attrs[i]);
device_destroy(touchscreen_class, MKDEV(INPUT_MAJOR, minor));
data->ts_class_dev = NULL;
class_unregister(touchscreen_class);
dev_err(DEV_MMI, "%s: error creating touchscreen class attrs\n", __func__);
return -ENODEV;
}
static int sec_mmi_panel_cb(struct notifier_block *nb,
unsigned long event, void *evd)
{
struct msm_drm_notifier *evdata = evd;
struct sec_mmi_data *data =
container_of(nb, struct sec_mmi_data, panel_nb);
if (!evdata || (evdata->id != data->ctrl_dsi)) {
dev_dbg(DEV_MMI, "%s: drm notification: id(%d) != ctrl_dsi(%d)\n",
__func__, evdata->id, data->ctrl_dsi);
return 0;
}
if ((event == MSM_DRM_EARLY_EVENT_BLANK || event == MSM_DRM_EVENT_BLANK) &&
evdata && evdata->data && data) {
int *blank = evdata->data;
dev_dbg(DEV_MMI, "%s: drm notification: event = %lu blank = %d\n",
__func__, event, *blank);
/* entering suspend upon early blank event */
/* to ensure shared power supply is still on */
/* for in-cell design touch solutions */
if (event == MSM_DRM_EARLY_EVENT_BLANK) {
if (*blank != MSM_DRM_BLANK_POWERDOWN)
return 0;
synaptics_dsx_display_off(&data->i2c_client->dev);
} else if (*blank == MSM_DRM_BLANK_UNBLANK) {
synaptics_dsx_display_on(&data->i2c_client->dev);
}
}
return 0;
}
static int sec_mmi_register_notifier(
struct sec_mmi_data *data, bool enable)
{
int rc;
if (enable) {
data->panel_nb.notifier_call = sec_mmi_panel_cb;
rc = msm_drm_register_client(&data->panel_nb);
} else
rc = msm_drm_unregister_client(&data->panel_nb);
if (!rc)
dev_dbg(DEV_MMI, "%s: %sregistered drm notifier\n",
__func__, enable ? "" : "un");
else
dev_err(DEV_MMI, "%s: unable to %sregister drm notifier\n",
__func__, enable ? "" : "un");
return rc;
}
static ssize_t sec_mmi_poweron_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct sec_ts_data *ts = dev_get_drvdata(dev);
return scnprintf(buf, PAGE_SIZE, "%d\n",
ts->power_status != SEC_TS_STATE_POWER_OFF);
}
static ssize_t sec_mmi_ic_ver_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct sec_ts_data *ts = dev_get_drvdata(dev);
return scnprintf(buf, PAGE_SIZE, "%s%s\n%s%x\n%s%x\n",
"Product ID: ", rmi->product_id_string,
"Build ID: ", build_id,
"Config ID: ", config_id);
}
static ssize_t sec_mmi_doreflash_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct sec_ts_data *ts = dev_get_drvdata(dev);
const struct firmware *fw_entry;
char fw_path[SEC_TS_MAX_FW_PATH];
int result = -1;
if (size > SEC_TS_MAX_FW_PATH) {
dev_err(&rmi4_data->i2c_client->dev,
"%s: FW filename is too long\n",
__func__);
return -EINVAL;
}
disable_irq(ts->client->irq);
scnprintf(fw_path, SEC_TS_MAX_FW_PATH, "%s", buf);
input_info(true, DEV_TS, "%s: initial bl update %s\n", __func__, fw_path);
/* Loading Firmware------------------------------------------ */
if (request_firmware(&fw_entry, fw_path, &ts->client->dev) != 0) {
input_err(true, DEV_TS, "%s: bt is not available\n", __func__);
goto err_request_fw;
}
input_info(true, DEV_TS, "%s: request bt done! size = %d\n", __func__, (int)fw_entry->size);
result = sec_ts_firmware_update(ts, fw_entry->data, fw_entry->size, 1, false, 0);
err_request_fw:
release_firmware(fw_entry);
enable_irq(ts->client->irq);
return result;
}
static ssize_t sec_ts_regreadsize_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
struct sec_ts_data *ts = dev_get_drvdata(dev);
mutex_lock(&ts->device_mutex);
lv1cmd = buf[0];
lv1_readsize = ((unsigned int)buf[4] << 24) |
((unsigned int)buf[3] << 16) | ((unsigned int) buf[2] << 8) | ((unsigned int)buf[1] << 0);
lv1_readoffset = 0;
lv1_readremain = 0;
mutex_unlock(&ts->device_mutex);
return size;
}
static ssize_t sec_ts_enter_recovery_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
struct sec_ts_data *ts = dev_get_drvdata(dev);
struct sec_ts_plat_data *pdata = ts->plat_data;
int ret;
unsigned long on;
ret = kstrtoul(buf, 10, &on);
if (ret != 0) {
input_err(true, &ts->client->dev, "%s: failed to read:%d\n",
__func__, ret);
return -EINVAL;
}
if (on == 1) {
disable_irq(ts->client->irq);
gpio_free(pdata->irq_gpio);
input_info(true, &ts->client->dev, "%s: gpio free\n", __func__);
if (gpio_is_valid(pdata->irq_gpio)) {
ret = gpio_request_one(pdata->irq_gpio, GPIOF_OUT_INIT_LOW, "sec,tsp_int");
input_info(true, &ts->client->dev, "%s: gpio request one\n", __func__);
if (ret < 0)
input_err(true, &ts->client->dev, "%s: Unable to request tsp_int [%d]: %d\n", __func__, pdata->irq_gpio, ret);
} else {
input_err(true, &ts->client->dev, "%s: Failed to get irq gpio\n", __func__);
return -EINVAL;
}
pdata->power(ts, false);
sec_ts_delay(100);
pdata->power(ts, true);
} else {
gpio_free(pdata->irq_gpio);
if (gpio_is_valid(pdata->irq_gpio)) {
ret = gpio_request_one(pdata->irq_gpio, GPIOF_DIR_IN, "sec,tsp_int");
if (ret) {
input_err(true, &ts->client->dev, "%s: Unable to request tsp_int [%d]\n", __func__, pdata->irq_gpio);
return -EINVAL;
}
} else {
input_err(true, &ts->client->dev, "%s: Failed to get irq gpio\n", __func__);
return -EINVAL;
}
pdata->power(ts, false);
sec_ts_delay(500);
pdata->power(ts, true);
sec_ts_delay(500);
/* AFE Calibration */
ret = ts->sec_ts_i2c_write(ts, SEC_TS_CMD_CALIBRATION_AMBIENT, NULL, 0);
if (ret < 0)
input_err(true, &ts->client->dev, "%s: fail to write AFE_CAL\n", __func__);
sec_ts_delay(1000);
enable_irq(ts->client->irq);
}
sec_ts_read_information(ts);
return size;
}
static inline ssize_t sec_ts_show_error(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct sec_ts_data *ts = dev_get_drvdata(dev);
input_err(true, &ts->client->dev, "%s: read only function, %s\n", __func__, attr->attr.name);
return -EPERM;
}
static inline ssize_t sec_ts_store_error(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct sec_ts_data *ts = dev_get_drvdata(dev);
input_err(true, &ts->client->dev, "%s: write only function, %s\n", __func__, attr->attr.name);
return -EPERM;
}
int sec_ts_raw_device_init(struct sec_ts_data *ts)
{
int ret;
struct class *sec_class = NULL;
sec_class = class_create(THIS_MODULE, "sec");
ret = IS_ERR_OR_NULL(sec_class);
if (ret) {
input_err(true, &ts->client->dev, "%s: fail - class_create\n", __func__);
return;
}
ts->dev = device_create(sec_class, NULL, 0, ts, "sec_ts");
ret = IS_ERR(ts->dev);
if (ret) {
input_err(true, &ts->client->dev, "%s: fail - device_create\n", __func__);
return ret;
}
ret = sysfs_create_group(&ts->dev->kobj, &cmd_attr_group);
if (ret < 0) {
input_err(true, &ts->client->dev, "%s: fail - sysfs_create_group\n", __func__);
goto err_sysfs;
}
return ret;
err_sysfs:
input_err(true, &ts->client->dev, "%s: fail\n", __func__);
return ret;
}

View file

@ -0,0 +1,295 @@
/* drivers/input/touchscreen/sec_ts_fw.c
*
* Copyright (C) 2015 Samsung Electronics Co., Ltd.
* http://www.samsungsemi.com/
*
* Core file for Samsung TSC driver
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/firmware.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/irq.h>
#include <linux/of_gpio.h>
#include <linux/time.h>
#include <linux/vmalloc.h>
#include <linux/uaccess.h>
/*#include <asm/gpio.h>*/
#include "sec_ts.h"
u8 lv1cmd;
u8 *read_lv1_buff;
static int lv1_readsize;
static int lv1_readremain;
static int lv1_readoffset;
static ssize_t sec_ts_reg_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size);
static ssize_t sec_ts_regreadsize_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size);
static inline ssize_t sec_ts_store_error(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count);
static ssize_t sec_ts_enter_recovery_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size);
static ssize_t sec_ts_regread_show(struct device *dev,
struct device_attribute *attr, char *buf);
static ssize_t sec_ts_gesture_status_show(struct device *dev,
struct device_attribute *attr, char *buf);
static inline ssize_t sec_ts_show_error(struct device *dev,
struct device_attribute *attr, char *buf);
static DEVICE_ATTR(sec_ts_reg, (S_IWUSR | S_IWGRP), NULL, sec_ts_reg_store);
static DEVICE_ATTR(sec_ts_regreadsize, (S_IWUSR | S_IWGRP), NULL, sec_ts_regreadsize_store);
static DEVICE_ATTR(sec_ts_enter_recovery, (S_IWUSR | S_IWGRP), NULL, sec_ts_enter_recovery_store);
static DEVICE_ATTR(sec_ts_regread, S_IRUGO, sec_ts_regread_show, NULL);
static DEVICE_ATTR(sec_ts_gesture_status, S_IRUGO, sec_ts_gesture_status_show, NULL);
static struct attribute *cmd_attributes[] = {
&dev_attr_sec_ts_reg.attr,
&dev_attr_sec_ts_regreadsize.attr,
&dev_attr_sec_ts_enter_recovery.attr,
&dev_attr_sec_ts_regread.attr,
&dev_attr_sec_ts_gesture_status.attr,
NULL,
};
static struct attribute_group cmd_attr_group = {
.attrs = cmd_attributes,
};
/* for debugging--------------------------------------------------------------------------------------*/
static ssize_t sec_ts_reg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
struct sec_ts_data *ts = dev_get_drvdata(dev);
if (ts->power_status == SEC_TS_STATE_POWER_OFF) {
input_info(true, &ts->client->dev, "%s: Power off state\n", __func__);
return -EIO;
}
if (size > 0)
ts->sec_ts_i2c_write_burst(ts, (u8 *)buf, size);
input_info(true, &ts->client->dev, "%s: 0x%x, 0x%x, size %d\n", __func__, buf[0], buf[1], (int)size);
return size;
}
static ssize_t sec_ts_regread_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct sec_ts_data *ts = dev_get_drvdata(dev);
int ret;
int length;
int remain;
int offset;
if (ts->power_status == SEC_TS_STATE_POWER_OFF) {
input_err(true, &ts->client->dev, "%s: Power off state\n", __func__);
return -EIO;
}
disable_irq(ts->client->irq);
mutex_lock(&ts->device_mutex);
read_lv1_buff = kzalloc(lv1_readsize, GFP_KERNEL);
if (!read_lv1_buff)
goto malloc_err;
remain = lv1_readsize;
offset = 0;
do {
if (remain >= ts->i2c_burstmax)
length = ts->i2c_burstmax;
else
length = remain;
if (offset == 0)
ret = ts->sec_ts_i2c_read(ts, lv1cmd, &read_lv1_buff[offset], length);
else
ret = ts->sec_ts_i2c_read_bulk (ts, &read_lv1_buff[offset], length);
if (ret < 0) {
input_err(true, &ts->client->dev, "%s: i2c read %x command, remain =%d\n", __func__, lv1cmd, remain);
goto i2c_err;
}
remain -= length;
offset += length;
} while (remain > 0);
input_info(true, &ts->client->dev, "%s: lv1_readsize = %d\n", __func__, lv1_readsize);
memcpy(buf, read_lv1_buff + lv1_readoffset, lv1_readsize);
i2c_err:
kfree(read_lv1_buff);
malloc_err:
mutex_unlock(&ts->device_mutex);
lv1_readremain = 0;
enable_irq(ts->client->irq);
return lv1_readsize;
}
static ssize_t sec_ts_gesture_status_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct sec_ts_data *ts = dev_get_drvdata(dev);
mutex_lock(&ts->device_mutex);
memcpy(buf, ts->gesture_status, sizeof(ts->gesture_status));
input_info(true, &ts->client->dev,
"%s: GESTURE STATUS %x %x %x %x %x %x\n", __func__,
ts->gesture_status[0], ts->gesture_status[1], ts->gesture_status[2],
ts->gesture_status[3], ts->gesture_status[4], ts->gesture_status[5]);
mutex_unlock(&ts->device_mutex);
return sizeof(ts->gesture_status);
}
static ssize_t sec_ts_regreadsize_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
struct sec_ts_data *ts = dev_get_drvdata(dev);
mutex_lock(&ts->device_mutex);
lv1cmd = buf[0];
lv1_readsize = ((unsigned int)buf[4] << 24) |
((unsigned int)buf[3] << 16) | ((unsigned int) buf[2] << 8) | ((unsigned int)buf[1] << 0);
lv1_readoffset = 0;
lv1_readremain = 0;
mutex_unlock(&ts->device_mutex);
return size;
}
static ssize_t sec_ts_enter_recovery_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
struct sec_ts_data *ts = dev_get_drvdata(dev);
struct sec_ts_plat_data *pdata = ts->plat_data;
int ret;
unsigned long on;
ret = kstrtoul(buf, 10, &on);
if (ret != 0) {
input_err(true, &ts->client->dev, "%s: failed to read:%d\n",
__func__, ret);
return -EINVAL;
}
if (on == 1) {
disable_irq(ts->client->irq);
gpio_free(pdata->irq_gpio);
input_info(true, &ts->client->dev, "%s: gpio free\n", __func__);
if (gpio_is_valid(pdata->irq_gpio)) {
ret = gpio_request_one(pdata->irq_gpio, GPIOF_OUT_INIT_LOW, "sec,tsp_int");
input_info(true, &ts->client->dev, "%s: gpio request one\n", __func__);
if (ret < 0)
input_err(true, &ts->client->dev, "%s: Unable to request tsp_int [%d]: %d\n", __func__, pdata->irq_gpio, ret);
} else {
input_err(true, &ts->client->dev, "%s: Failed to get irq gpio\n", __func__);
return -EINVAL;
}
pdata->power(ts, false);
sec_ts_delay(100);
pdata->power(ts, true);
} else {
gpio_free(pdata->irq_gpio);
if (gpio_is_valid(pdata->irq_gpio)) {
ret = gpio_request_one(pdata->irq_gpio, GPIOF_DIR_IN, "sec,tsp_int");
if (ret) {
input_err(true, &ts->client->dev, "%s: Unable to request tsp_int [%d]\n", __func__, pdata->irq_gpio);
return -EINVAL;
}
} else {
input_err(true, &ts->client->dev, "%s: Failed to get irq gpio\n", __func__);
return -EINVAL;
}
pdata->power(ts, false);
sec_ts_delay(500);
pdata->power(ts, true);
sec_ts_delay(500);
/* AFE Calibration */
ret = ts->sec_ts_i2c_write(ts, SEC_TS_CMD_CALIBRATION_AMBIENT, NULL, 0);
if (ret < 0)
input_err(true, &ts->client->dev, "%s: fail to write AFE_CAL\n", __func__);
sec_ts_delay(1000);
enable_irq(ts->client->irq);
}
sec_ts_read_information(ts);
return size;
}
static inline ssize_t sec_ts_show_error(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct sec_ts_data *ts = dev_get_drvdata(dev);
input_err(true, &ts->client->dev, "%s: read only function, %s\n", __func__, attr->attr.name);
return -EPERM;
}
static inline ssize_t sec_ts_store_error(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct sec_ts_data *ts = dev_get_drvdata(dev);
input_err(true, &ts->client->dev, "%s: write only function, %s\n", __func__, attr->attr.name);
return -EPERM;
}
int sec_ts_raw_device_init(struct sec_ts_data *ts)
{
int ret;
struct class *sec_class = NULL;
sec_class = class_create(THIS_MODULE, "sec");
ret = IS_ERR_OR_NULL(sec_class);
if (ret) {
input_err(true, &ts->client->dev, "%s: fail - class_create\n", __func__);
return;
}
ts->dev = device_create(sec_class, NULL, 0, ts, "sec_ts");
ret = IS_ERR(ts->dev);
if (ret) {
input_err(true, &ts->client->dev, "%s: fail - device_create\n", __func__);
return ret;
}
ret = sysfs_create_group(&ts->dev->kobj, &cmd_attr_group);
if (ret < 0) {
input_err(true, &ts->client->dev, "%s: fail - sysfs_create_group\n", __func__);
goto err_sysfs;
}
return ret;
err_sysfs:
input_err(true, &ts->client->dev, "%s: fail\n", __func__);
return ret;
}