mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-10 06:09:23 -04:00
Ocean: DLKM: Bringup ili9881h touch driver
Bringup ili9881h touch driver for ocean Change-Id: I4371a5db7ce5a95baeb67dc6f23346fbd05695cc Signed-off-by: wengjun1 <wengjun1@motorola.com> Reviewed-on: https://gerrit.mot.com/1213203 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao <liaohs@motorola.com> Submit-Approved: Jira Key
This commit is contained in:
parent
c8818aa97a
commit
b09895661b
29 changed files with 19619 additions and 0 deletions
8
drivers/input/touchscreen/ilitek_mmi/Android.mk
Normal file
8
drivers/input/touchscreen/ilitek_mmi/Android.mk
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
DLKM_DIR := motorola/kernel/modules
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := ilitek_mmi.ko
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||
include $(DLKM_DIR)/AndroidKernelModule.mk
|
||||
20
drivers/input/touchscreen/ilitek_mmi/Kbuild
Normal file
20
drivers/input/touchscreen/ilitek_mmi/Kbuild
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# 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/ilitek_mmi
|
||||
|
||||
ifeq ($(filter m y, $(CONFIG_TOUCHSCREEN_ILITEK_CHIPSET)),)
|
||||
obj-m += ilitek_mmi.o
|
||||
endif
|
||||
|
||||
ilitek_mmi-objs += platform.o userspace.o
|
||||
ilitek_mmi-objs += core/config.o \
|
||||
core/finger_report.o \
|
||||
core/firmware.o \
|
||||
core/flash.o \
|
||||
core/i2c.o \
|
||||
core/spi.o \
|
||||
core/mp_test.o \
|
||||
core/protocol.o \
|
||||
core/parser.o \
|
||||
core/gesture.o
|
||||
10
drivers/input/touchscreen/ilitek_mmi/Makefile
Normal file
10
drivers/input/touchscreen/ilitek_mmi/Makefile
Normal 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
|
||||
259
drivers/input/touchscreen/ilitek_mmi/common.h
Normal file
259
drivers/input/touchscreen/ilitek_mmi/common.h
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
* ILITEK Touch IC driver
|
||||
*
|
||||
* Copyright (C) 2011 ILI Technology Corporation.
|
||||
*
|
||||
* Author: Dicky Chiang <dicky_chiang@ilitek.com>
|
||||
* Based on TDD v7.0 implemented by Mstar & ILITEK
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __COMMON_H
|
||||
#define __COMMON_H
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/ctype.h>
|
||||
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/socket.h>
|
||||
#include <net/sock.h>
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/time.h>
|
||||
|
||||
#include <linux/namei.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FB
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/fb.h>
|
||||
#else
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Relative Driver with Touch IC
|
||||
*/
|
||||
|
||||
/* An Touch IC currently supported by driver */
|
||||
#define CHIP_TYPE_ILI7807 0x7807
|
||||
#define CHIP_TYPE_ILI9881 0x9881
|
||||
|
||||
#define CHIP_ID_ERR (-100)
|
||||
|
||||
/* A interface currently supported by driver */
|
||||
#define I2C_INTERFACE 1
|
||||
#define SPI_INTERFACE 2
|
||||
#define INTERFACE I2C_INTERFACE
|
||||
|
||||
/* Driver version */
|
||||
#define DRIVER_VERSION "1.0.3.5"
|
||||
|
||||
/* Driver core type */
|
||||
#define CORE_TYPE_B 0x00
|
||||
#define CORE_TYPE_E 0x03
|
||||
|
||||
/* Protocol version */
|
||||
#define PROTOCOL_MAJOR 0x5
|
||||
#define PROTOCOL_MID 0x4
|
||||
#define PROTOCOL_MINOR 0x0
|
||||
|
||||
/* Debug messages */
|
||||
#ifdef BIT
|
||||
#undef BIT
|
||||
#endif
|
||||
#define BIT(x) (1 << (x))
|
||||
|
||||
enum {
|
||||
DEBUG_NONE = 0,
|
||||
DEBUG_IRQ = BIT(0),
|
||||
DEBUG_FINGER_REPORT = BIT(1),
|
||||
DEBUG_FIRMWARE = BIT(2),
|
||||
DEBUG_CONFIG = BIT(3),
|
||||
DEBUG_I2C = BIT(4),
|
||||
DEBUG_BATTERY = BIT(5),
|
||||
DEBUG_MP_TEST = BIT(6),
|
||||
DEBUG_IOCTL = BIT(7),
|
||||
DEBUG_NETLINK = BIT(8),
|
||||
DEBUG_PARSER = BIT(9),
|
||||
DEBUG_GESTURE = BIT(10),
|
||||
DEBUG_ALL = ~0,
|
||||
};
|
||||
|
||||
#define ipio_info(fmt, arg...) \
|
||||
pr_info("ILITEK: (%s, %d): " fmt, __func__, __LINE__, ##arg)
|
||||
|
||||
#define ipio_err(fmt, arg...) \
|
||||
pr_err("ILITEK: (%s, %d): " fmt, __func__, __LINE__, ##arg)
|
||||
|
||||
#define ipio_debug(level, fmt, arg...) \
|
||||
do { \
|
||||
if (level & ipio_debug_level) \
|
||||
pr_info("ILITEK: (%s, %d): " fmt, __func__, \
|
||||
__LINE__, ##arg); \
|
||||
} while (0)
|
||||
|
||||
/* Distributed to all core functions */
|
||||
extern uint32_t ipio_debug_level;
|
||||
extern uint32_t ipio_chip_list[2];
|
||||
|
||||
/* Macros */
|
||||
#define CHECK_EQUAL(X, Y) ((X == Y) ? 0 : -1)
|
||||
#define ERR_ALLOC_MEM(X) ((IS_ERR(X) || X == NULL) ? 1 : 0)
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#define USEC 1
|
||||
#define MSEC (USEC * 1000)
|
||||
|
||||
/* The size of firmware upgrade */
|
||||
#define MAX_HEX_FILE_SIZE (160*1024)
|
||||
#define MAX_FLASH_FIRMWARE_SIZE (256*1024)
|
||||
#define MAX_IRAM_FIRMWARE_SIZE (60*1024)
|
||||
#define ILI_FILE_HEADER 64
|
||||
#define MAX_AP_FIRMWARE_SIZE (64*1024)
|
||||
#define MAX_DLM_FIRMWARE_SIZE (8*1024)
|
||||
#define MAX_MP_FIRMWARE_SIZE (64*1024)
|
||||
#define MAX_GESTURE_FIRMWARE_SIZE (8*1024)
|
||||
#define DLM_START_ADDRESS 0x20610
|
||||
#define DLM_HEX_ADDRESS 0x10000
|
||||
#define MP_HEX_ADDRESS 0x13000
|
||||
#define SPI_UPGRADE_LEN 2048
|
||||
#define UPDATE_RETRY_COUNT 3
|
||||
|
||||
/* ILI7807 Series */
|
||||
enum ili7881_types {
|
||||
ILI7807_TYPE_F_AA = 0x0000,
|
||||
ILI7807_TYPE_F_AB = 0x0001,
|
||||
ILI7807_TYPE_H = 0x1100
|
||||
};
|
||||
|
||||
#define ILI7807_SLAVE_ADDR 0x41
|
||||
#define ILI7807_ICE_MODE_ADDR 0x181062
|
||||
#define ILI7807_PID_ADDR 0x4009C
|
||||
#define ILI7808_WDT_ADDR 0x5100C
|
||||
|
||||
/* ILI9881 Series */
|
||||
enum ili9881_types {
|
||||
ILI9881_TYPE_F = 0x0F,
|
||||
ILI9881_TYPE_H = 0x11
|
||||
};
|
||||
/*Error code*/
|
||||
#define SUCCESS 0
|
||||
#define ERROR (-1)
|
||||
#define UPDATE_FAIL (-1)
|
||||
#define CHECK_RECOVER -2
|
||||
|
||||
#define ILI9881_SLAVE_ADDR 0x41
|
||||
#define ILI9881_ICE_MODE_ADDR 0x181062
|
||||
#define ILI9881_PID_ADDR 0x4009C
|
||||
#define ILI9881_WDT_ADDR 0x5100C
|
||||
|
||||
/*
|
||||
* Other settings
|
||||
*/
|
||||
#define CSV_PATH "/sdcard"
|
||||
#define INI_NAME_PATH "/sdcard/mp.ini"
|
||||
#define UPDATE_FW_PATH "/mnt/sdcard/ILITEK_FW"
|
||||
#define ILITEK_FW_FILENAME "ILITEK_FW.bin"
|
||||
#define POWER_STATUS_PATH "/sys/class/power_supply/battery/status"
|
||||
#define CHECK_BATTERY_TIME 2000
|
||||
#define VDD_VOLTAGE 1800000
|
||||
#define VDD_I2C_VOLTAGE 1800000
|
||||
|
||||
|
||||
/* It's only for spi interface used to download data to iram */
|
||||
#if (INTERFACE == SPI_INTERFACE)
|
||||
#define HOST_DOWNLOAD
|
||||
#endif
|
||||
|
||||
/* Linux multiple touch protocol, either B type or A type. */
|
||||
//#define MT_B_TYPE
|
||||
|
||||
/* Enable the support of regulator power. */
|
||||
/* #define REGULATOR_POWER_ON */
|
||||
|
||||
/* Either an interrupt event handled by kthread or work queue. */
|
||||
#define USE_KTHREAD
|
||||
|
||||
/* Enable DMA with I2C. */
|
||||
/* #define I2C_DMA */
|
||||
|
||||
/* Split the length written to or read from IC via I2C. */
|
||||
/* #define I2C_SEGMENT */
|
||||
|
||||
/* Be able to upgrade fw at boot stage */
|
||||
/* #define BOOT_FW_UPGRADE */
|
||||
|
||||
/* Check battery's status in order to avoid some effects from charge. */
|
||||
/* #define BATTERY_CHECK */
|
||||
|
||||
/*suspend TP power off*/
|
||||
#define SUSPEND_TP_POWER_OFF
|
||||
|
||||
static inline void ipio_kfree(void **mem)
|
||||
{
|
||||
if (*mem != NULL) {
|
||||
kfree(*mem);
|
||||
*mem = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
extern int katoi(char *string);
|
||||
extern int str2hex(char *str);
|
||||
|
||||
#endif /* __COMMON_H */
|
||||
7170
drivers/input/touchscreen/ilitek_mmi/core/FW_TDDI_9881H.ili
Normal file
7170
drivers/input/touchscreen/ilitek_mmi/core/FW_TDDI_9881H.ili
Normal file
File diff suppressed because it is too large
Load diff
1104
drivers/input/touchscreen/ilitek_mmi/core/config.c
Normal file
1104
drivers/input/touchscreen/ilitek_mmi/core/config.c
Normal file
File diff suppressed because it is too large
Load diff
134
drivers/input/touchscreen/ilitek_mmi/core/config.h
Normal file
134
drivers/input/touchscreen/ilitek_mmi/core/config.h
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* ILITEK Touch IC driver
|
||||
*
|
||||
* Copyright (C) 2011 ILI Technology Corporation.
|
||||
*
|
||||
* Author: Dicky Chiang <dicky_chiang@ilitek.com>
|
||||
* Based on TDD v7.0 implemented by Mstar & ILITEK
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __CONFIG_H
|
||||
#define __CONFIG_H
|
||||
|
||||
typedef struct {
|
||||
int nId;
|
||||
int nX;
|
||||
int nY;
|
||||
int nStatus;
|
||||
int nFlag;
|
||||
} VIRTUAL_KEYS;
|
||||
|
||||
typedef struct {
|
||||
uint16_t nMaxX;
|
||||
uint16_t nMaxY;
|
||||
uint16_t nMinX;
|
||||
uint16_t nMinY;
|
||||
|
||||
uint8_t nMaxTouchNum;
|
||||
uint8_t nMaxKeyButtonNum;
|
||||
|
||||
uint8_t nXChannelNum;
|
||||
uint8_t nYChannelNum;
|
||||
uint8_t nHandleKeyFlag;
|
||||
uint8_t nKeyCount;
|
||||
|
||||
uint16_t nKeyAreaXLength;
|
||||
uint16_t nKeyAreaYLength;
|
||||
|
||||
VIRTUAL_KEYS virtual_key[10];
|
||||
|
||||
/* added for protocol v5 */
|
||||
uint8_t self_tx_channel_num;
|
||||
uint8_t self_rx_channel_num;
|
||||
uint8_t side_touch_type;
|
||||
|
||||
} TP_INFO;
|
||||
|
||||
struct core_config_data {
|
||||
uint32_t chip_id;
|
||||
uint32_t chip_type;
|
||||
uint32_t chip_pid;
|
||||
|
||||
uint8_t core_type;
|
||||
|
||||
uint32_t slave_i2c_addr;
|
||||
uint32_t ice_mode_addr;
|
||||
uint32_t pid_addr;
|
||||
uint32_t wdt_addr;
|
||||
uint32_t ic_reset_addr;
|
||||
|
||||
uint8_t protocol_ver[4];
|
||||
uint8_t firmware_ver[9];
|
||||
uint8_t core_ver[5];
|
||||
|
||||
bool do_ic_reset;
|
||||
bool isEnableGesture;
|
||||
bool icemodeenable;
|
||||
bool spi_pro_9881h11;
|
||||
TP_INFO *tp_info;
|
||||
};
|
||||
|
||||
extern struct core_config_data *core_config;
|
||||
|
||||
extern int fw_cmd_len;
|
||||
extern int protocol_cmd_len;
|
||||
extern int tp_info_len;
|
||||
extern int key_info_len;
|
||||
extern int core_cmd_len;
|
||||
|
||||
/* R/W with Touch ICs */
|
||||
extern uint32_t core_config_ice_mode_read(uint32_t addr);
|
||||
extern int core_config_ice_mode_write(uint32_t addr, uint32_t data, uint32_t size);
|
||||
extern uint32_t core_config_read_write_onebyte(uint32_t addr);
|
||||
extern int core_config_ice_mode_disable(void);
|
||||
extern int core_config_ice_mode_enable(void);
|
||||
|
||||
/* Touch IC status */
|
||||
extern int core_config_set_watch_dog(bool enable);
|
||||
extern int core_config_check_cdc_busy(int count, int delay);
|
||||
extern int core_config_check_int_status(bool high);
|
||||
extern void core_config_ic_suspend(void);
|
||||
extern void core_config_ic_resume(void);
|
||||
extern void core_config_ic_reset(void);
|
||||
|
||||
/* control features of Touch IC */
|
||||
extern void core_config_sense_ctrl(bool start);
|
||||
extern void core_config_sleep_ctrl(bool out);
|
||||
extern void core_config_glove_ctrl(bool enable, bool seamless);
|
||||
extern void core_config_stylus_ctrl(bool enable, bool seamless);
|
||||
extern void core_config_tp_scan_mode(bool mode);
|
||||
extern void core_config_lpwg_ctrl(bool enable);
|
||||
extern void core_config_gesture_ctrl(uint8_t func);
|
||||
extern void core_config_phone_cover_ctrl(bool enable);
|
||||
extern void core_config_finger_sense_ctrl(bool enable);
|
||||
extern void core_config_proximity_ctrl(bool enable);
|
||||
extern void core_config_plug_ctrl(bool out);
|
||||
extern void core_config_set_phone_cover(uint8_t *pattern);
|
||||
|
||||
/* Touch IC information */
|
||||
extern int core_config_get_core_ver(void);
|
||||
extern int core_config_get_key_info(void);
|
||||
extern int core_config_get_tp_info(void);
|
||||
extern int core_config_get_protocol_ver(void);
|
||||
extern int core_config_get_fw_ver(void);
|
||||
extern int core_config_get_chip_id(void);
|
||||
|
||||
extern int core_config_init(void);
|
||||
extern void core_config_remove(void);
|
||||
|
||||
#endif /* __CONFIG_H */
|
||||
822
drivers/input/touchscreen/ilitek_mmi/core/finger_report.c
Normal file
822
drivers/input/touchscreen/ilitek_mmi/core/finger_report.c
Normal file
|
|
@ -0,0 +1,822 @@
|
|||
/*
|
||||
* ILITEK Touch IC driver
|
||||
*
|
||||
* Copyright (C) 2011 ILI Technology Corporation.
|
||||
*
|
||||
* Author: Dicky Chiang <dicky_chiang@ilitek.com>
|
||||
* Based on TDD v7.0 implemented by Mstar & ILITEK
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#include <linux/errno.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
#include "../common.h"
|
||||
#include "../platform.h"
|
||||
#include "config.h"
|
||||
#include "i2c.h"
|
||||
#include "finger_report.h"
|
||||
#include "gesture.h"
|
||||
#include "mp_test.h"
|
||||
#include "protocol.h"
|
||||
|
||||
/* An id with position in each fingers */
|
||||
struct mutual_touch_point {
|
||||
uint16_t id;
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
uint16_t pressure;
|
||||
};
|
||||
|
||||
/* Keys and code with each fingers */
|
||||
struct mutual_touch_info {
|
||||
uint8_t touch_num;
|
||||
uint8_t key_code;
|
||||
struct mutual_touch_point mtp[10];
|
||||
};
|
||||
|
||||
/* Store the packet of finger report */
|
||||
struct fr_data_node {
|
||||
uint8_t *data;
|
||||
uint16_t len;
|
||||
};
|
||||
|
||||
/* record the status of touch being pressed or released currently and previosuly */
|
||||
uint8_t g_current_touch[10];
|
||||
uint8_t g_previous_touch[10];
|
||||
|
||||
/* the total length of finger report packet */
|
||||
uint16_t g_total_len;
|
||||
|
||||
struct mutual_touch_info g_mutual_data;
|
||||
struct fr_data_node *g_fr_node = NULL, *g_fr_uart = NULL;
|
||||
struct core_fr_data *core_fr;
|
||||
|
||||
/**
|
||||
* Calculate the check sum of each packet reported by firmware
|
||||
*
|
||||
* @pMsg: packet come from firmware
|
||||
* @nLength : the length of its packet
|
||||
*/
|
||||
uint8_t core_fr_calc_checksum(uint8_t *pMsg, uint32_t nLength)
|
||||
{
|
||||
int i;
|
||||
int32_t nCheckSum = 0;
|
||||
|
||||
for (i = 0 ; i < nLength; i++) {
|
||||
nCheckSum += pMsg[i];
|
||||
}
|
||||
|
||||
return (uint8_t) ((-nCheckSum) & 0xFF);
|
||||
}
|
||||
EXPORT_SYMBOL(core_fr_calc_checksum);
|
||||
|
||||
/**
|
||||
* Receive data when fw mode stays at i2cuart mode.
|
||||
*
|
||||
* the first is to receive N bytes depending on the mode that firmware stays
|
||||
* before going in this function, and it would check with i2c buffer if it
|
||||
* remains the rest of data.
|
||||
*/
|
||||
static void i2cuart_recv_packet(void)
|
||||
{
|
||||
int res = 0, need_read_len = 0, one_data_bytes = 0;
|
||||
int type = g_fr_node->data[3] & 0x0F;
|
||||
int actual_len = g_fr_node->len - 5;
|
||||
|
||||
ipio_debug(DEBUG_FINGER_REPORT, "pid = %x, data[3] = %x, type = %x, actual_len = %d\n",
|
||||
g_fr_node->data[0], g_fr_node->data[3], type, actual_len);
|
||||
|
||||
need_read_len = g_fr_node->data[1] * g_fr_node->data[2];
|
||||
|
||||
if (type == 0 || type == 1 || type == 6) {
|
||||
one_data_bytes = 1;
|
||||
} else if (type == 2 || type == 3) {
|
||||
one_data_bytes = 2;
|
||||
} else if (type == 4 || type == 5) {
|
||||
one_data_bytes = 4;
|
||||
}
|
||||
|
||||
ipio_debug(DEBUG_FINGER_REPORT, "need_read_len = %d one_data_bytes = %d\n", need_read_len, one_data_bytes);
|
||||
|
||||
need_read_len = need_read_len * one_data_bytes + 1;
|
||||
|
||||
if (need_read_len > actual_len) {
|
||||
g_fr_uart = kmalloc(sizeof(*g_fr_uart), GFP_ATOMIC);
|
||||
if (ERR_ALLOC_MEM(g_fr_uart)) {
|
||||
ipio_err("Failed to allocate g_fr_uart memory %ld\n", PTR_ERR(g_fr_uart));
|
||||
return;
|
||||
}
|
||||
|
||||
g_fr_uart->len = need_read_len - actual_len;
|
||||
g_fr_uart->data = kzalloc(g_fr_uart->len, GFP_ATOMIC);
|
||||
if (ERR_ALLOC_MEM(g_fr_uart->data)) {
|
||||
ipio_err("Failed to allocate g_fr_uart memory %ld\n", PTR_ERR(g_fr_uart->data));
|
||||
return;
|
||||
}
|
||||
|
||||
g_total_len += g_fr_uart->len;
|
||||
res = core_read(core_config->slave_i2c_addr, g_fr_uart->data, g_fr_uart->len);
|
||||
if (res < 0)
|
||||
ipio_err("Failed to read finger report packet\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* It'd be called when a finger's touching down a screen. It'll notify the event
|
||||
* to the uplayer from input device.
|
||||
*
|
||||
* @x: the axis of X
|
||||
* @y: the axis of Y
|
||||
* @pressure: the value of pressue on a screen
|
||||
* @id: an id represents a finger pressing on a screen
|
||||
*/
|
||||
void core_fr_touch_press(int32_t x, int32_t y, uint32_t pressure, int32_t id)
|
||||
{
|
||||
ipio_debug(DEBUG_FINGER_REPORT, "DOWN: id = %d, x = %d, y = %d\n", id, x, y);
|
||||
|
||||
if (ipd->x_flip)
|
||||
x = ipd->x_max - x;
|
||||
if (ipd->y_flip)
|
||||
y = ipd->y_max - y;
|
||||
ipio_debug(DEBUG_FINGER_REPORT, "Flip:: DOWN: id = %d, x = %d, y = %d\n", id, x, y);
|
||||
|
||||
if (ipd->MT_B_TYPE) {
|
||||
input_mt_slot(core_fr->input_device, id);
|
||||
input_mt_report_slot_state(core_fr->input_device, MT_TOOL_FINGER, true);
|
||||
input_report_abs(core_fr->input_device, ABS_MT_POSITION_X, x);
|
||||
input_report_abs(core_fr->input_device, ABS_MT_POSITION_Y, y);
|
||||
if (core_fr->isEnablePressure)
|
||||
input_report_abs(core_fr->input_device, ABS_MT_PRESSURE, pressure);
|
||||
} else{
|
||||
input_report_key(core_fr->input_device, BTN_TOUCH, 1);
|
||||
input_report_abs(core_fr->input_device, ABS_MT_TRACKING_ID, id);
|
||||
input_report_abs(core_fr->input_device, ABS_MT_TOUCH_MAJOR, 1);
|
||||
input_report_abs(core_fr->input_device, ABS_MT_WIDTH_MAJOR, 1);
|
||||
input_report_abs(core_fr->input_device, ABS_MT_POSITION_X, x);
|
||||
input_report_abs(core_fr->input_device, ABS_MT_POSITION_Y, y);
|
||||
if (core_fr->isEnablePressure)
|
||||
input_report_abs(core_fr->input_device, ABS_MT_PRESSURE, pressure);
|
||||
|
||||
input_mt_sync(core_fr->input_device);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(core_fr_touch_press);
|
||||
|
||||
/*
|
||||
* It'd be called when a finger's touched up from a screen. It'll notify
|
||||
* the event to the uplayer from input device.
|
||||
*
|
||||
* @x: the axis of X
|
||||
* @y: the axis of Y
|
||||
* @id: an id represents a finger leaving from a screen.
|
||||
*/
|
||||
void core_fr_touch_release(int32_t x, int32_t y, int32_t id)
|
||||
{
|
||||
ipio_debug(DEBUG_FINGER_REPORT, "UP: id = %d, x = %d, y = %d\n", id, x, y);
|
||||
|
||||
if (ipd->MT_B_TYPE) {
|
||||
input_mt_slot(core_fr->input_device, id);
|
||||
input_mt_report_slot_state(core_fr->input_device, MT_TOOL_FINGER, false);
|
||||
} else{
|
||||
input_report_key(core_fr->input_device, BTN_TOUCH, 0);
|
||||
input_mt_sync(core_fr->input_device);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(core_fr_touch_release);
|
||||
|
||||
static int parse_touch_package_v3_2(void)
|
||||
{
|
||||
ipio_info("Not implemented yet\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int finger_report_ver_3_2(void)
|
||||
{
|
||||
ipio_info("Not implemented yet\n");
|
||||
parse_touch_package_v3_2();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* It mainly parses the packet assembled by protocol v5.0
|
||||
*/
|
||||
static int parse_touch_package_v5_0(uint8_t pid)
|
||||
{
|
||||
int i, res = 0;
|
||||
uint8_t check_sum = 0;
|
||||
uint32_t nX = 0, nY = 0;
|
||||
|
||||
for (i = 0 ; i < 9; i++)
|
||||
ipio_debug(DEBUG_FINGER_REPORT, "data[%d] = %x\n", i, g_fr_node->data[i]);
|
||||
|
||||
check_sum = core_fr_calc_checksum(&g_fr_node->data[0], (g_fr_node->len - 1));
|
||||
ipio_debug(DEBUG_FINGER_REPORT, "data = %x ; check_sum : %x\n", g_fr_node->data[g_fr_node->len - 1], check_sum);
|
||||
|
||||
if (g_fr_node->data[g_fr_node->len - 1] != check_sum) {
|
||||
ipio_err("Wrong checksum\n");
|
||||
res = ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* start to parsing the packet of finger report */
|
||||
if (pid == protocol->demo_pid) {
|
||||
ipio_debug(DEBUG_FINGER_REPORT, " **** Parsing DEMO packets : 0x%x ****\n", pid);
|
||||
|
||||
for (i = 0 ; i < ipd->MAX_TOUCH_NUM; i++) {
|
||||
if ((g_fr_node->data[(4 * i) + 1] == 0xFF) && (g_fr_node->data[(4 * i) + 2] && 0xFF)
|
||||
&& (g_fr_node->data[(4 * i) + 3] == 0xFF)) {
|
||||
if (ipd->MT_B_TYPE)
|
||||
g_current_touch[i] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
nX = (((g_fr_node->data[(4 * i) + 1] & 0xF0) << 4) | (g_fr_node->data[(4 * i) + 2]));
|
||||
nY = (((g_fr_node->data[(4 * i) + 1] & 0x0F) << 8) | (g_fr_node->data[(4 * i) + 3]));
|
||||
|
||||
if (!core_fr->isSetResolution) {
|
||||
g_mutual_data.mtp[g_mutual_data.touch_num].x = nX * (ipd->x_max) / (ipd->TPD_WIDTH);
|
||||
g_mutual_data.mtp[g_mutual_data.touch_num].y = nY * (ipd->y_max) / (ipd->TPD_HEIGHT);
|
||||
g_mutual_data.mtp[g_mutual_data.touch_num].id = i;
|
||||
} else {
|
||||
g_mutual_data.mtp[g_mutual_data.touch_num].x = nX;
|
||||
g_mutual_data.mtp[g_mutual_data.touch_num].y = nY;
|
||||
g_mutual_data.mtp[g_mutual_data.touch_num].id = i;
|
||||
}
|
||||
|
||||
if (core_fr->isEnablePressure)
|
||||
g_mutual_data.mtp[g_mutual_data.touch_num].pressure = g_fr_node->data[(4 * i) + 4];
|
||||
else
|
||||
g_mutual_data.mtp[g_mutual_data.touch_num].pressure = 1;
|
||||
|
||||
ipio_debug(DEBUG_FINGER_REPORT, "[x,y]=[%d,%d]\n", nX, nY);
|
||||
ipio_debug(DEBUG_FINGER_REPORT, "point[%d] : (%d,%d) = %d\n",
|
||||
g_mutual_data.mtp[g_mutual_data.touch_num].id,
|
||||
g_mutual_data.mtp[g_mutual_data.touch_num].x,
|
||||
g_mutual_data.mtp[g_mutual_data.touch_num].y, g_mutual_data.mtp[g_mutual_data.touch_num].pressure);
|
||||
|
||||
g_mutual_data.touch_num++;
|
||||
|
||||
if (ipd->MT_B_TYPE)
|
||||
g_current_touch[i] = 1;
|
||||
}
|
||||
} else if (pid == protocol->debug_pid) {
|
||||
ipio_debug(DEBUG_FINGER_REPORT, " **** Parsing DEBUG packets : 0x%x ****\n", pid);
|
||||
ipio_debug(DEBUG_FINGER_REPORT, "Length = %d\n", (g_fr_node->data[1] << 8 | g_fr_node->data[2]));
|
||||
|
||||
for (i = 0 ; i < ipd->MAX_TOUCH_NUM; i++) {
|
||||
if ((g_fr_node->data[(3 * i) + 5] == 0xFF) && (g_fr_node->data[(3 * i) + 6] && 0xFF)
|
||||
&& (g_fr_node->data[(3 * i) + 7] == 0xFF)) {
|
||||
if (ipd->MT_B_TYPE)
|
||||
g_current_touch[i] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
nX = (((g_fr_node->data[(3 * i) + 5] & 0xF0) << 4) | (g_fr_node->data[(3 * i) + 6]));
|
||||
nY = (((g_fr_node->data[(3 * i) + 5] & 0x0F) << 8) | (g_fr_node->data[(3 * i) + 7]));
|
||||
|
||||
if (!core_fr->isSetResolution) {
|
||||
g_mutual_data.mtp[g_mutual_data.touch_num].x = nX * (ipd->x_max) / (ipd->TPD_WIDTH);
|
||||
g_mutual_data.mtp[g_mutual_data.touch_num].y = nY * (ipd->y_max) / (ipd->TPD_HEIGHT);
|
||||
g_mutual_data.mtp[g_mutual_data.touch_num].id = i;
|
||||
} else {
|
||||
g_mutual_data.mtp[g_mutual_data.touch_num].x = nX;
|
||||
g_mutual_data.mtp[g_mutual_data.touch_num].y = nY;
|
||||
g_mutual_data.mtp[g_mutual_data.touch_num].id = i;
|
||||
}
|
||||
|
||||
if (core_fr->isEnablePressure)
|
||||
g_mutual_data.mtp[g_mutual_data.touch_num].pressure = g_fr_node->data[(4 * i) + 4];
|
||||
else
|
||||
g_mutual_data.mtp[g_mutual_data.touch_num].pressure = 1;
|
||||
|
||||
ipio_debug(DEBUG_FINGER_REPORT, "[x,y]=[%d,%d]\n", nX, nY);
|
||||
ipio_debug(DEBUG_FINGER_REPORT, "point[%d] : (%d,%d) = %d\n",
|
||||
g_mutual_data.mtp[g_mutual_data.touch_num].id,
|
||||
g_mutual_data.mtp[g_mutual_data.touch_num].x,
|
||||
g_mutual_data.mtp[g_mutual_data.touch_num].y, g_mutual_data.mtp[g_mutual_data.touch_num].pressure);
|
||||
|
||||
g_mutual_data.touch_num++;
|
||||
|
||||
if (ipd->MT_B_TYPE)
|
||||
g_current_touch[i] = 1;
|
||||
}
|
||||
} else {
|
||||
if (pid != 0) {
|
||||
/* ignore the pid with 0x0 after enable irq at once */
|
||||
ipio_err(" **** Unknown PID : 0x%x ****\n", pid);
|
||||
res = ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* The function is called by an interrupt and used to handle packet of finger
|
||||
* touch from firmware. A differnece in the process of the data is acorrding to the protocol
|
||||
*/
|
||||
static int finger_report_ver_5_0(void)
|
||||
{
|
||||
int i, gesture, res = 0;
|
||||
static int last_touch;
|
||||
uint8_t pid = 0x0;
|
||||
|
||||
memset(&g_mutual_data, 0x0, sizeof(struct mutual_touch_info));
|
||||
|
||||
#ifdef I2C_SEGMENT
|
||||
res = core_i2c_segmental_read(core_config->slave_i2c_addr, g_fr_node->data, g_fr_node->len);
|
||||
#else
|
||||
res = core_read(core_config->slave_i2c_addr, g_fr_node->data, g_fr_node->len);
|
||||
#endif
|
||||
|
||||
if (res < 0) {
|
||||
ipio_err("Failed to read finger report packet\n");
|
||||
if (res == CHECK_RECOVER) {
|
||||
ipio_err("==================Recover=================\n");
|
||||
/*ilitek_platform_tp_hw_reset(true);*/
|
||||
/* Soft reset */
|
||||
core_config_ice_mode_enable();
|
||||
core_config_set_watch_dog(false);
|
||||
mdelay(10);
|
||||
core_config_ic_reset();
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
pid = g_fr_node->data[0];
|
||||
ipio_debug(DEBUG_FINGER_REPORT, "PID = 0x%x\n", pid);
|
||||
|
||||
if (pid == 0)
|
||||
goto out;
|
||||
|
||||
|
||||
if (pid == protocol->i2cuart_pid) {
|
||||
ipio_debug(DEBUG_FINGER_REPORT, "I2CUART(0x%x): prepare to receive rest of data\n", pid);
|
||||
i2cuart_recv_packet();
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (pid == protocol->ges_pid && core_config->isEnableGesture) {
|
||||
ipio_debug(DEBUG_FINGER_REPORT, "pid = 0x%x, code = %x\n", pid, g_fr_node->data[1]);
|
||||
gesture = core_gesture_match_key(g_fr_node->data[1]);
|
||||
if (gesture != -1) {
|
||||
input_report_key(core_fr->input_device, gesture, 1);
|
||||
input_sync(core_fr->input_device);
|
||||
input_report_key(core_fr->input_device, gesture, 0);
|
||||
input_sync(core_fr->input_device);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
res = parse_touch_package_v5_0(pid);
|
||||
if (res < 0) {
|
||||
ipio_err("Failed to parse packet of finger touch\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ipio_debug(DEBUG_FINGER_REPORT, "Touch Num = %d, LastTouch = %d\n", g_mutual_data.touch_num, last_touch);
|
||||
|
||||
/* interpret parsed packat and send input events to system */
|
||||
if (g_mutual_data.touch_num > 0) {
|
||||
if (ipd->MT_B_TYPE) {
|
||||
for (i = 0 ; i < g_mutual_data.touch_num; i++) {
|
||||
input_report_key(core_fr->input_device, BTN_TOUCH, 1);
|
||||
core_fr_touch_press(g_mutual_data.mtp[i].x, g_mutual_data.mtp[i].y, g_mutual_data.mtp[i].pressure, g_mutual_data.mtp[i].id);
|
||||
|
||||
input_report_key(core_fr->input_device, BTN_TOOL_FINGER, 1);
|
||||
}
|
||||
|
||||
for (i = 0 ; i < ipd->MAX_TOUCH_NUM; i++) {
|
||||
ipio_debug(DEBUG_FINGER_REPORT, "g_previous_touch[%d]=%d, g_current_touch[%d]=%d\n", i,
|
||||
g_previous_touch[i], i, g_current_touch[i]);
|
||||
|
||||
if (g_current_touch[i] == 0 && g_previous_touch[i] == 1) {
|
||||
core_fr_touch_release(0, 0, i);
|
||||
}
|
||||
|
||||
g_previous_touch[i] = g_current_touch[i];
|
||||
}
|
||||
} else{
|
||||
for (i = 0 ; i < g_mutual_data.touch_num; i++) {
|
||||
core_fr_touch_press(g_mutual_data.mtp[i].x, g_mutual_data.mtp[i].y, g_mutual_data.mtp[i].pressure, g_mutual_data.mtp[i].id);
|
||||
}
|
||||
}
|
||||
input_sync(core_fr->input_device);
|
||||
|
||||
last_touch = g_mutual_data.touch_num;
|
||||
} else {
|
||||
if (last_touch > 0) {
|
||||
if (ipd->MT_B_TYPE) {
|
||||
for (i = 0 ; i < ipd->MAX_TOUCH_NUM; i++) {
|
||||
ipio_debug(DEBUG_FINGER_REPORT, "g_previous_touch[%d]=%d, g_current_touch[%d]=%d\n", i,
|
||||
g_previous_touch[i], i, g_current_touch[i]);
|
||||
|
||||
if (g_current_touch[i] == 0 && g_previous_touch[i] == 1) {
|
||||
core_fr_touch_release(0, 0, i);
|
||||
}
|
||||
g_previous_touch[i] = g_current_touch[i];
|
||||
}
|
||||
input_report_key(core_fr->input_device, BTN_TOUCH, 0);
|
||||
input_report_key(core_fr->input_device, BTN_TOOL_FINGER, 0);
|
||||
} else{
|
||||
core_fr_touch_release(0, 0, 0);
|
||||
}
|
||||
|
||||
input_sync(core_fr->input_device);
|
||||
|
||||
last_touch = 0;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
|
||||
void core_fr_mode_control(uint8_t *from_user)
|
||||
{
|
||||
int i, mode;
|
||||
int checksum = 0, codeLength = 8;
|
||||
uint8_t mp_code[8] = { 0 };
|
||||
uint8_t cmd[4] = { 0 };
|
||||
|
||||
ilitek_platform_disable_irq();
|
||||
|
||||
if (from_user == NULL) {
|
||||
ipio_err("Arguments from user space are invaild\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ipio_debug(DEBUG_FINGER_REPORT, "mode = %x, b1 = %x, b2 = %x, b3 = %x\n",
|
||||
from_user[0], from_user[1], from_user[2], from_user[3]);
|
||||
|
||||
mode = from_user[0];
|
||||
|
||||
if (protocol->major == 0x5) {
|
||||
if (mode == protocol->i2cuart_mode) {
|
||||
cmd[0] = protocol->cmd_i2cuart;
|
||||
cmd[1] = *(from_user + 1);
|
||||
cmd[2] = *(from_user + 2);
|
||||
|
||||
ipio_info("Switch to I2CUART mode, cmd = %x, b1 = %x, b2 = %x\n", cmd[0], cmd[1], cmd[2]);
|
||||
|
||||
if ((core_write(core_config->slave_i2c_addr, cmd, 3)) < 0) {
|
||||
ipio_err("Failed to switch I2CUART mode\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
} else if (mode == protocol->demo_mode || mode == protocol->debug_mode) {
|
||||
cmd[0] = protocol->cmd_mode_ctrl;
|
||||
cmd[1] = mode;
|
||||
|
||||
ipio_info("Switch to Demo/Debug mode, cmd = 0x%x, b1 = 0x%x\n", cmd[0], cmd[1]);
|
||||
|
||||
if ((core_write(core_config->slave_i2c_addr, cmd, 2)) < 0) {
|
||||
ipio_err("Failed to switch Demo/Debug mode\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
core_fr->actual_fw_mode = mode;
|
||||
|
||||
} else if (mode == protocol->test_mode) {
|
||||
cmd[0] = protocol->cmd_mode_ctrl;
|
||||
cmd[1] = mode;
|
||||
|
||||
ipio_info("Switch to Test mode, cmd = 0x%x, b1 = 0x%x\n", cmd[0], cmd[1]);
|
||||
|
||||
if ((core_write(core_config->slave_i2c_addr, cmd, 2)) < 0) {
|
||||
ipio_err("Failed to switch Test mode\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd[0] = 0xFE;
|
||||
|
||||
/* Read MP Test information to ensure if fw supports test mode. */
|
||||
core_write(core_config->slave_i2c_addr, cmd, 1);
|
||||
mdelay(10);
|
||||
core_read(core_config->slave_i2c_addr, mp_code, codeLength);
|
||||
|
||||
for (i = 0 ; i < codeLength - 1; i++)
|
||||
checksum += mp_code[i];
|
||||
|
||||
if ((-checksum & 0xFF) != mp_code[codeLength - 1]) {
|
||||
ipio_info("checksume error (0x%x), FW doesn't support test mode.\n",
|
||||
(-checksum & 0XFF));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* FW enter to Test Mode */
|
||||
#if (INTERFACE == SPI_INTERFACE)
|
||||
core_fr->actual_fw_mode = mode;
|
||||
#endif
|
||||
if (core_mp_move_code() == 0)
|
||||
core_fr->actual_fw_mode = mode;
|
||||
|
||||
} else {
|
||||
ipio_err("Unknown firmware mode: %x\n", mode);
|
||||
}
|
||||
} else {
|
||||
ipio_err("Wrong the major version of protocol, 0x%x\n", protocol->major);
|
||||
}
|
||||
|
||||
out:
|
||||
ilitek_platform_enable_irq();
|
||||
}
|
||||
EXPORT_SYMBOL(core_fr_mode_control);
|
||||
|
||||
/**
|
||||
* Calculate the length with different modes according to the format of protocol 5.0
|
||||
*
|
||||
* We compute the length before receiving its packet. If the length is differnet between
|
||||
* firmware and the number we calculated, in this case I just print an error to inform users
|
||||
* and still send up to users.
|
||||
*/
|
||||
static uint16_t calc_packet_length(void)
|
||||
{
|
||||
uint16_t xch = 0, ych = 0, stx = 0, srx = 0;
|
||||
/* FIXME: self_key not defined by firmware yet */
|
||||
uint16_t self_key = 2;
|
||||
uint16_t rlen = 0;
|
||||
|
||||
if (protocol->major == 0x5) {
|
||||
if (!ERR_ALLOC_MEM(core_config->tp_info)) {
|
||||
xch = core_config->tp_info->nXChannelNum;
|
||||
ych = core_config->tp_info->nYChannelNum;
|
||||
stx = core_config->tp_info->self_tx_channel_num;
|
||||
srx = core_config->tp_info->self_rx_channel_num;
|
||||
}
|
||||
|
||||
ipio_debug(DEBUG_FINGER_REPORT, "firmware mode : 0x%x\n", core_fr->actual_fw_mode);
|
||||
|
||||
if (protocol->demo_mode == core_fr->actual_fw_mode) {
|
||||
rlen = protocol->demo_len;
|
||||
} else if (protocol->test_mode == core_fr->actual_fw_mode) {
|
||||
if (ERR_ALLOC_MEM(core_config->tp_info)) {
|
||||
rlen = protocol->test_len;
|
||||
} else {
|
||||
rlen = (2 * xch * ych) + (stx * 2) + (srx * 2) + 2 * self_key + 1;
|
||||
rlen += 1;
|
||||
}
|
||||
} else if (protocol->debug_mode == core_fr->actual_fw_mode) {
|
||||
if (ERR_ALLOC_MEM(core_config->tp_info)) {
|
||||
rlen = protocol->debug_len;
|
||||
} else {
|
||||
rlen = (2 * xch * ych) + (stx * 2) + (srx * 2) + 2 * self_key + (8 * 2) + 1;
|
||||
rlen += 35;
|
||||
}
|
||||
} else if (protocol->gesture_mode == core_fr->actual_fw_mode) {
|
||||
if (core_gesture->mode == GESTURE_NORMAL_MODE)
|
||||
rlen = GESTURE_MORMAL_LENGTH;
|
||||
else
|
||||
rlen = GESTURE_INFO_LENGTH;
|
||||
ipio_debug(DEBUG_FINGER_REPORT, "rlen = %d\n", rlen);
|
||||
} else {
|
||||
ipio_err("Unknown firmware mode : %d\n", core_fr->actual_fw_mode);
|
||||
rlen = 0;
|
||||
}
|
||||
} else {
|
||||
ipio_err("Wrong the major version of protocol, 0x%x\n", protocol->major);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ipio_debug(DEBUG_FINGER_REPORT, "rlen = %d\n", rlen);
|
||||
return rlen;
|
||||
}
|
||||
|
||||
/**
|
||||
* The table is used to handle calling functions that deal with packets of finger report.
|
||||
* The callback function might be different of what a protocol is used on a chip.
|
||||
*
|
||||
* It's possible to have the different protocol according to customer's requirement on the same
|
||||
* touch ic with customised firmware, so I don't have to identify which of the ic has been used; instead,
|
||||
* the version of protocol should match its parsing pattern.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t protocol_marjor_ver;
|
||||
uint8_t protocol_minor_ver;
|
||||
int (*finger_report)(void);
|
||||
} fr_hashtable;
|
||||
|
||||
fr_hashtable fr_t[] = {
|
||||
{0x3, 0x2, finger_report_ver_3_2},
|
||||
{0x5, 0x0, finger_report_ver_5_0},
|
||||
{0x5, 0x1, finger_report_ver_5_0},
|
||||
};
|
||||
|
||||
/**
|
||||
* The function is an entry for the work queue registered by ISR activates.
|
||||
*
|
||||
* Here will allocate the size of packet depending on what the current protocol
|
||||
* is used on its firmware.
|
||||
*/
|
||||
void core_fr_handler(void)
|
||||
{
|
||||
int i = 0;
|
||||
uint8_t *tdata = NULL;
|
||||
|
||||
if (core_fr->isEnableFR) {
|
||||
g_total_len = calc_packet_length();
|
||||
if (g_total_len) {
|
||||
g_fr_node = kmalloc(sizeof(*g_fr_node), GFP_ATOMIC);
|
||||
if (ERR_ALLOC_MEM(g_fr_node)) {
|
||||
ipio_err("Failed to allocate g_fr_node memory %ld\n", PTR_ERR(g_fr_node));
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_fr_node->data = kcalloc(g_total_len, sizeof(uint8_t), GFP_ATOMIC);
|
||||
if (ERR_ALLOC_MEM(g_fr_node->data)) {
|
||||
ipio_err("Failed to allocate g_fr_node memory %ld\n", PTR_ERR(g_fr_node->data));
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_fr_node->len = g_total_len;
|
||||
memset(g_fr_node->data, 0xFF, (uint8_t) sizeof(uint8_t) * g_total_len);
|
||||
|
||||
while (i < ARRAY_SIZE(fr_t)) {
|
||||
if (protocol->major == fr_t[i].protocol_marjor_ver) {
|
||||
mutex_lock(&ipd->plat_mutex);
|
||||
fr_t[i].finger_report();
|
||||
mutex_unlock(&ipd->plat_mutex);
|
||||
|
||||
/* 2048 is referred to the defination by user */
|
||||
if (g_total_len < 2048) {
|
||||
tdata = kmalloc(g_total_len, GFP_ATOMIC);
|
||||
if (ERR_ALLOC_MEM(tdata)) {
|
||||
ipio_err("Failed to allocate g_fr_node memory %ld\n",
|
||||
PTR_ERR(tdata));
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(tdata, g_fr_node->data, g_fr_node->len);
|
||||
/* merge uart data if it's at i2cuart mode */
|
||||
if (g_fr_uart != NULL)
|
||||
memcpy(tdata + g_fr_node->len, g_fr_uart->data, g_fr_uart->len);
|
||||
} else {
|
||||
ipio_err("total length (%d) is too long than user can handle\n",
|
||||
g_total_len);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (core_fr->isEnableNetlink)
|
||||
netlink_reply_msg(tdata, g_total_len);
|
||||
|
||||
if (ipd->debug_node_open) {
|
||||
mutex_lock(&ipd->ilitek_debug_mutex);
|
||||
memset(ipd->debug_buf[ipd->debug_data_frame], 0x00,
|
||||
(uint8_t) sizeof(uint8_t) * 2048);
|
||||
memcpy(ipd->debug_buf[ipd->debug_data_frame], tdata, g_total_len);
|
||||
ipd->debug_data_frame++;
|
||||
if (ipd->debug_data_frame > 1) {
|
||||
ipio_info("ipd->debug_data_frame = %d\n", ipd->debug_data_frame);
|
||||
}
|
||||
if (ipd->debug_data_frame > 1023) {
|
||||
ipio_err("ipd->debug_data_frame = %d > 1024\n",
|
||||
ipd->debug_data_frame);
|
||||
ipd->debug_data_frame = 1023;
|
||||
}
|
||||
mutex_unlock(&ipd->ilitek_debug_mutex);
|
||||
wake_up(&(ipd->inq));
|
||||
}
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i >= ARRAY_SIZE(fr_t))
|
||||
ipio_err("Can't find any callback functions to handle INT event\n");
|
||||
} else {
|
||||
ipio_err("Wrong the length of packet\n");
|
||||
}
|
||||
} else {
|
||||
ipio_err("The figner report was disabled\n");
|
||||
return;
|
||||
}
|
||||
ilitek_platform_enable_irq();
|
||||
|
||||
out:
|
||||
ipio_kfree((void **)&tdata);
|
||||
|
||||
if (g_fr_node != NULL) {
|
||||
ipio_kfree((void **)&g_fr_node->data);
|
||||
ipio_kfree((void **)&g_fr_node);
|
||||
}
|
||||
|
||||
if (g_fr_uart != NULL) {
|
||||
ipio_kfree((void **)&g_fr_uart->data);
|
||||
ipio_kfree((void **)&g_fr_uart);
|
||||
}
|
||||
|
||||
g_total_len = 0;
|
||||
ipio_debug(DEBUG_IRQ, "handle INT done\n\n");
|
||||
}
|
||||
EXPORT_SYMBOL(core_fr_handler);
|
||||
|
||||
void core_fr_input_set_param(struct input_dev *input_device)
|
||||
{
|
||||
int max_x = 0, max_y = 0, min_x = 0, min_y = 0;
|
||||
int max_tp = 0;
|
||||
|
||||
core_fr->input_device = input_device;
|
||||
|
||||
/* set the supported event type for input device */
|
||||
set_bit(EV_ABS, core_fr->input_device->evbit);
|
||||
set_bit(EV_SYN, core_fr->input_device->evbit);
|
||||
set_bit(EV_KEY, core_fr->input_device->evbit);
|
||||
set_bit(BTN_TOUCH, core_fr->input_device->keybit);
|
||||
set_bit(BTN_TOOL_FINGER, core_fr->input_device->keybit);
|
||||
set_bit(INPUT_PROP_DIRECT, core_fr->input_device->propbit);
|
||||
|
||||
if (core_fr->isSetResolution) {
|
||||
max_x = core_config->tp_info->nMaxX;
|
||||
max_y = core_config->tp_info->nMaxY;
|
||||
min_x = core_config->tp_info->nMinX;
|
||||
min_y = core_config->tp_info->nMinY;
|
||||
max_tp = core_config->tp_info->nMaxTouchNum;
|
||||
} else {
|
||||
max_x = ipd->x_max;
|
||||
max_y = ipd->y_max;
|
||||
min_x = ipd->x_min;
|
||||
min_y = ipd->y_min;
|
||||
max_tp = ipd->MAX_TOUCH_NUM;
|
||||
}
|
||||
|
||||
ipio_info("input resolution : max_x = %d, max_y = %d, min_x = %d, min_y = %d\n", max_x, max_y, min_x, min_y);
|
||||
ipio_info("input touch number: max_tp = %d\n", max_tp);
|
||||
|
||||
input_set_abs_params(core_fr->input_device, ABS_MT_POSITION_X, min_x, max_x - 1, 0, 0);
|
||||
input_set_abs_params(core_fr->input_device, ABS_MT_POSITION_Y, min_y, max_y - 1, 0, 0);
|
||||
|
||||
input_set_abs_params(core_fr->input_device, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
|
||||
input_set_abs_params(core_fr->input_device, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
|
||||
|
||||
if (core_fr->isEnablePressure)
|
||||
input_set_abs_params(core_fr->input_device, ABS_MT_PRESSURE, 0, 255, 0, 0);
|
||||
|
||||
if (ipd->MT_B_TYPE) {
|
||||
#if KERNEL_VERSION(3, 7, 0) <= LINUX_VERSION_CODE
|
||||
input_mt_init_slots(core_fr->input_device, max_tp, INPUT_MT_DIRECT);
|
||||
#else
|
||||
input_mt_init_slots(core_fr->input_device, max_tp);
|
||||
#endif /* LINUX_VERSION_CODE */
|
||||
} else{
|
||||
input_set_abs_params(core_fr->input_device, ABS_MT_TRACKING_ID, 0, max_tp, 0, 0);
|
||||
} /* MT_B_TYPE */
|
||||
|
||||
/* Set up virtual key with gesture code */
|
||||
core_gesture_set_key(core_fr);
|
||||
}
|
||||
EXPORT_SYMBOL(core_fr_input_set_param);
|
||||
|
||||
int core_fr_init(void)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
core_fr = kzalloc(sizeof(*core_fr), GFP_KERNEL);
|
||||
if (ERR_ALLOC_MEM(core_fr)) {
|
||||
ipio_err("Failed to allocate core_fr mem, %ld\n", PTR_ERR(core_fr));
|
||||
core_fr_remove();
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (i = 0 ; i < ARRAY_SIZE(ipio_chip_list); i++) {
|
||||
if (ipio_chip_list[i] == ipd->chip_id) {
|
||||
core_fr->isEnableFR = true;
|
||||
core_fr->isEnableNetlink = false;
|
||||
core_fr->isEnablePressure = false;
|
||||
core_fr->isSetResolution = false;
|
||||
core_fr->actual_fw_mode = protocol->demo_mode;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ipio_err("Can't find this chip in support list\n");
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(core_fr_init);
|
||||
|
||||
void core_fr_remove(void)
|
||||
{
|
||||
ipio_info("Remove core-FingerReport members\n");
|
||||
ipio_kfree((void **)&core_fr);
|
||||
}
|
||||
EXPORT_SYMBOL(core_fr_remove);
|
||||
67
drivers/input/touchscreen/ilitek_mmi/core/finger_report.h
Normal file
67
drivers/input/touchscreen/ilitek_mmi/core/finger_report.h
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* ILITEK Touch IC driver
|
||||
*
|
||||
* Copyright (C) 2011 ILI Technology Corporation.
|
||||
*
|
||||
* Author: Dicky Chiang <dicky_chiang@ilitek.com>
|
||||
* Based on TDD v7.0 implemented by Mstar & ILITEK
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __FINGER_REPORT_H
|
||||
#define __FINGER_REPORT_H
|
||||
|
||||
struct core_fr_data {
|
||||
struct input_dev *input_device;
|
||||
|
||||
/* the default of finger report is enabled */
|
||||
bool isEnableFR;
|
||||
/* used to send finger report packet to user psace */
|
||||
bool isEnableNetlink;
|
||||
/* allow input dev to report the value of physical touch */
|
||||
bool isEnablePressure;
|
||||
/* get screen resloution from fw if it's true */
|
||||
bool isSetResolution;
|
||||
/* used to change I2C Uart Mode when fw mode is in this mode */
|
||||
uint8_t i2cuart_mode;
|
||||
|
||||
/* current firmware mode in driver */
|
||||
uint16_t actual_fw_mode;
|
||||
|
||||
/* mutual firmware info */
|
||||
uint16_t log_packet_length;
|
||||
uint8_t log_packet_header;
|
||||
uint8_t type;
|
||||
uint8_t Mx;
|
||||
uint8_t My;
|
||||
uint8_t Sd;
|
||||
uint8_t Ss;
|
||||
};
|
||||
|
||||
extern struct core_fr_data *core_fr;
|
||||
|
||||
extern uint8_t core_fr_calc_checksum(uint8_t *pMsg, uint32_t nLength);
|
||||
extern void core_fr_touch_press(int32_t x, int32_t y, uint32_t pressure
|
||||
, int32_t id);
|
||||
extern void core_fr_touch_release(int32_t x, int32_t y, int32_t id);
|
||||
extern void core_fr_mode_control(uint8_t *from_user);
|
||||
extern void core_fr_handler(void);
|
||||
extern void core_fr_input_set_param(struct input_dev *input_device);
|
||||
extern int core_fr_init(void);
|
||||
extern void core_fr_remove(void);
|
||||
|
||||
#endif /* __FINGER_REPORT_H */
|
||||
1635
drivers/input/touchscreen/ilitek_mmi/core/firmware.c
Normal file
1635
drivers/input/touchscreen/ilitek_mmi/core/firmware.c
Normal file
File diff suppressed because it is too large
Load diff
64
drivers/input/touchscreen/ilitek_mmi/core/firmware.h
Normal file
64
drivers/input/touchscreen/ilitek_mmi/core/firmware.h
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* ILITEK Touch IC driver
|
||||
*
|
||||
* Copyright (C) 2011 ILI Technology Corporation.
|
||||
*
|
||||
* Author: Dicky Chiang <dicky_chiang@ilitek.com>
|
||||
* Based on TDD v7.0 implemented by Mstar & ILITEK
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __FIRMWARE_H
|
||||
#define __FIRMWARE_H
|
||||
|
||||
struct core_firmware_data {
|
||||
uint8_t new_fw_ver[4];
|
||||
uint8_t old_fw_ver[4];
|
||||
|
||||
uint32_t start_addr;
|
||||
uint32_t end_addr;
|
||||
uint32_t checksum;
|
||||
uint32_t crc32;
|
||||
uint32_t update_status;
|
||||
uint32_t max_count;
|
||||
|
||||
int delay_after_upgrade;
|
||||
|
||||
bool isUpgrading;
|
||||
bool force_upgrad;
|
||||
bool isCRC;
|
||||
bool isboot;
|
||||
bool hasBlockInfo;
|
||||
|
||||
int (*upgrade_func)(bool isIRAM);
|
||||
};
|
||||
|
||||
extern struct core_firmware_data *core_firmware;
|
||||
|
||||
#ifdef HOST_DOWNLOAD
|
||||
extern int core_firmware_boot_host_download(void);
|
||||
extern int tddi_host_download(bool isIRAM);
|
||||
#endif
|
||||
#ifdef BOOT_FW_UPGRADE
|
||||
extern int core_firmware_boot_upgrade(void);
|
||||
#endif
|
||||
/* extern int core_firmware_iram_upgrade(const char* fpath); */
|
||||
extern int core_firmware_upgrade(const char *pFilePath, bool isIRAM);
|
||||
extern int core_firmware_init(void);
|
||||
extern void core_firmware_remove(void);
|
||||
|
||||
#endif /* __FIRMWARE_H */
|
||||
187
drivers/input/touchscreen/ilitek_mmi/core/flash.c
Normal file
187
drivers/input/touchscreen/ilitek_mmi/core/flash.c
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* ILITEK Touch IC driver
|
||||
*
|
||||
* Copyright (C) 2011 ILI Technology Corporation.
|
||||
*
|
||||
* Author: Dicky Chiang <dicky_chiang@ilitek.com>
|
||||
* Based on TDD v7.0 implemented by Mstar & ILITEK
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../common.h"
|
||||
#include "config.h"
|
||||
#include "flash.h"
|
||||
|
||||
#define K (1024)
|
||||
#define M (K * K)
|
||||
|
||||
/*
|
||||
* The table contains fundamental data used to program our flash, which
|
||||
* would be different according to the vendors.
|
||||
*/
|
||||
struct flash_table ft[] = {
|
||||
{0xEF, 0x6011, (128 * K), 256, (4 * K), (64 * K)}, /* W25Q10EW */
|
||||
{0xEF, 0x6012, (256 * K), 256, (4 * K), (64 * K)}, /* W25Q20EW */
|
||||
{0xC8, 0x6012, (256 * K), 256, (4 * K), (64 * K)}, /* GD25LQ20B */
|
||||
{0xC8, 0x6013, (512 * K), 256, (4 * K), (64 * K)}, /* GD25LQ40 */
|
||||
{0x85, 0x6013, (4 * M), 256, (4 * K), (64 * K)},
|
||||
{0xC2, 0x2812, (256 * K), 256, (4 * K), (64 * K)},
|
||||
{0x1C, 0x3812, (256 * K), 256, (4 * K), (64 * K)},
|
||||
};
|
||||
|
||||
struct flash_table *flashtab;
|
||||
|
||||
int core_flash_poll_busy(void)
|
||||
{
|
||||
int timer = 500, res = 0;
|
||||
|
||||
core_config_ice_mode_write(0x041000, 0x0, 1); /* CS low */
|
||||
core_config_ice_mode_write(0x041004, 0x66aa55, 3); /* Key */
|
||||
|
||||
core_config_ice_mode_write(0x041008, 0x5, 1);
|
||||
while (timer > 0) {
|
||||
core_config_ice_mode_write(0x041008, 0xFF, 1);
|
||||
|
||||
mdelay(1);
|
||||
|
||||
if ((core_config_read_write_onebyte(0x041010) & 0x03) == 0x00)
|
||||
goto out;
|
||||
timer--;
|
||||
}
|
||||
|
||||
ipio_err("Polling busy Time out !\n");
|
||||
res = ERROR;
|
||||
out:
|
||||
core_config_ice_mode_write(0x041000, 0x1, 1); /* CS high */
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(core_flash_poll_busy);
|
||||
|
||||
int core_flash_write_enable(void)
|
||||
{
|
||||
if (core_config_ice_mode_write(0x041000, 0x0, 1) < 0)
|
||||
goto out;
|
||||
if (core_config_ice_mode_write(0x041004, 0x66aa55, 3) < 0)
|
||||
goto out;
|
||||
if (core_config_ice_mode_write(0x041008, 0x6, 1) < 0)
|
||||
goto out;
|
||||
if (core_config_ice_mode_write(0x041000, 0x1, 1) < 0)
|
||||
goto out;
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
ipio_err("Write enable failed !\n");
|
||||
return -EIO;
|
||||
}
|
||||
EXPORT_SYMBOL(core_flash_write_enable);
|
||||
|
||||
void core_flash_enable_protect(bool enable)
|
||||
{
|
||||
ipio_info("Set flash protect as (%d)\n", enable);
|
||||
|
||||
if (core_flash_write_enable() < 0) {
|
||||
ipio_err("Failed to config flash's write enable\n");
|
||||
return;
|
||||
}
|
||||
|
||||
core_config_ice_mode_write(0x041000, 0x0, 1); /* CS low */
|
||||
core_config_ice_mode_write(0x041004, 0x66aa55, 3); /* Key */
|
||||
|
||||
switch (flashtab->mid) {
|
||||
case 0xEF:
|
||||
if (flashtab->dev_id == 0x6012 || flashtab->dev_id == 0x6011) {
|
||||
core_config_ice_mode_write(0x041008, 0x1, 1);
|
||||
core_config_ice_mode_write(0x041008, 0x00, 1);
|
||||
|
||||
if (enable)
|
||||
core_config_ice_mode_write(0x041008, 0x7E, 1);
|
||||
else
|
||||
core_config_ice_mode_write(0x041008, 0x00, 1);
|
||||
}
|
||||
break;
|
||||
case 0xC8:
|
||||
if (flashtab->dev_id == 0x6012 || flashtab->dev_id == 0x6013) {
|
||||
core_config_ice_mode_write(0x041008, 0x1, 1);
|
||||
core_config_ice_mode_write(0x041008, 0x00, 1);
|
||||
|
||||
if (enable)
|
||||
core_config_ice_mode_write(0x041008, 0x7A, 1);
|
||||
else
|
||||
core_config_ice_mode_write(0x041008, 0x00, 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ipio_err("Can't find flash id, ignore protection\n");
|
||||
break;
|
||||
}
|
||||
|
||||
core_config_ice_mode_write(0x041000, 0x1, 1); /* CS high */
|
||||
mdelay(5);
|
||||
}
|
||||
EXPORT_SYMBOL(core_flash_enable_protect);
|
||||
|
||||
void core_flash_init(uint16_t mid, uint16_t did)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
ipio_info("M_ID = %x, DEV_ID = %x", mid, did);
|
||||
|
||||
flashtab = kzalloc(sizeof(ft), GFP_KERNEL);
|
||||
if (ERR_ALLOC_MEM(flashtab)) {
|
||||
ipio_err("Failed to allocate flashtab memory, %ld\n", PTR_ERR(flashtab));
|
||||
return;
|
||||
}
|
||||
|
||||
for (; i < ARRAY_SIZE(ft); i++) {
|
||||
if (mid == ft[i].mid && did == ft[i].dev_id) {
|
||||
ipio_info("Find them in flash table\n");
|
||||
|
||||
flashtab->mid = mid;
|
||||
flashtab->dev_id = did;
|
||||
flashtab->mem_size = ft[i].mem_size;
|
||||
flashtab->program_page = ft[i].program_page;
|
||||
flashtab->sector = ft[i].sector;
|
||||
flashtab->block = ft[i].block;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= ARRAY_SIZE(ft)) {
|
||||
ipio_err("Can't find them in flash table, apply default flash config\n");
|
||||
flashtab->mid = mid;
|
||||
flashtab->dev_id = did;
|
||||
flashtab->mem_size = (256 * K);
|
||||
flashtab->program_page = 256;
|
||||
flashtab->sector = (4 * K);
|
||||
flashtab->block = (64 * K);
|
||||
}
|
||||
|
||||
ipio_info("Max Memory size = %d\n", flashtab->mem_size);
|
||||
ipio_info("Per program page = %d\n", flashtab->program_page);
|
||||
ipio_info("Sector size = %d\n", flashtab->sector);
|
||||
ipio_info("Block size = %d\n", flashtab->block);
|
||||
}
|
||||
EXPORT_SYMBOL(core_flash_init);
|
||||
|
||||
void core_flash_remove(void)
|
||||
{
|
||||
ipio_info("Remove core-flash memebers\n");
|
||||
|
||||
ipio_kfree((void **)&flashtab);
|
||||
}
|
||||
EXPORT_SYMBOL(core_flash_remove);
|
||||
45
drivers/input/touchscreen/ilitek_mmi/core/flash.h
Normal file
45
drivers/input/touchscreen/ilitek_mmi/core/flash.h
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* ILITEK Touch IC driver
|
||||
*
|
||||
* Copyright (C) 2011 ILI Technology Corporation.
|
||||
*
|
||||
* Author: Dicky Chiang <dicky_chiang@ilitek.com>
|
||||
* Based on TDD v7.0 implemented by Mstar & ILITEK
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __FLASH_H
|
||||
#define __FLASH_H
|
||||
|
||||
struct flash_table {
|
||||
uint16_t mid;
|
||||
uint16_t dev_id;
|
||||
int mem_size;
|
||||
int program_page;
|
||||
int sector;
|
||||
int block;
|
||||
};
|
||||
|
||||
extern struct flash_table *flashtab;
|
||||
|
||||
extern int core_flash_poll_busy(void);
|
||||
extern int core_flash_write_enable(void);
|
||||
extern void core_flash_enable_protect(bool status);
|
||||
extern void core_flash_init(uint16_t mid, uint16_t did);
|
||||
extern void core_flash_remove(void);
|
||||
|
||||
#endif /* __FLASH_H */
|
||||
289
drivers/input/touchscreen/ilitek_mmi/core/gesture.c
Normal file
289
drivers/input/touchscreen/ilitek_mmi/core/gesture.c
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
/*
|
||||
* ILITEK Touch IC driver
|
||||
*
|
||||
* Copyright (C) 2011 ILI Technology Corporation.
|
||||
*
|
||||
* Author: Dicky Chiang <dicky_chiang@ilitek.com>
|
||||
* Based on TDD v7.0 implemented by Mstar & ILITEK
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../common.h"
|
||||
#include "finger_report.h"
|
||||
#include "firmware.h"
|
||||
#include "gesture.h"
|
||||
#include "protocol.h"
|
||||
#include "config.h"
|
||||
|
||||
struct core_gesture_data *core_gesture;
|
||||
|
||||
#ifdef HOST_DOWNLOAD
|
||||
int core_gesture_load_code(void)
|
||||
{
|
||||
int i = 0, ret = 0;
|
||||
uint8_t temp[64] = {0};
|
||||
|
||||
core_gesture->entry = true;
|
||||
|
||||
/* Already read during parsing hex file */
|
||||
ipio_info("gesture_start_addr = 0x%x, length = 0x%x\n",
|
||||
core_gesture->start_addr, core_gesture->length);
|
||||
ipio_info("area = %d, ap_start_addr = 0x%x, ap_length = 0x%x\n",
|
||||
core_gesture->area_section, core_gesture->ap_start_addr,
|
||||
core_gesture->ap_length);
|
||||
|
||||
/* write load gesture flag */
|
||||
ipio_info("write load gesture flag\n");
|
||||
temp[0] = 0x01;
|
||||
temp[1] = 0x0A;
|
||||
temp[2] = 0x03;
|
||||
if ((core_write(core_config->slave_i2c_addr, temp, 3)) < 0)
|
||||
ipio_err("write gesture flag error\n");
|
||||
|
||||
ipio_info("enter gesture cmd lpwg start\n");
|
||||
/* enter gesture cmd lpwg start */
|
||||
temp[0] = 0x01;
|
||||
temp[1] = 0x0A;
|
||||
temp[2] = core_gesture->mode + 1;
|
||||
if ((core_write(core_config->slave_i2c_addr, temp, 3)) < 0)
|
||||
ipio_err("write lpwg start error\n");
|
||||
|
||||
for (i = 0 ; i < 20 ; i++) {
|
||||
temp[0] = 0xF6;
|
||||
temp[1] = 0x0A;
|
||||
temp[2] = 0x05;
|
||||
if ((core_write(core_config->slave_i2c_addr, temp, 2)) < 0)
|
||||
ipio_err("write 0xF6,0xA,0x05 command error\n");
|
||||
|
||||
mdelay(i * 50);
|
||||
|
||||
temp[0] = 0x01;
|
||||
temp[1] = 0x0A;
|
||||
temp[2] = 0x05;
|
||||
if ((core_write(core_config->slave_i2c_addr, temp, 3)) < 0)
|
||||
ipio_err("write command error\n");
|
||||
|
||||
if ((core_read(core_config->slave_i2c_addr, temp, 1)) < 0)
|
||||
ipio_err("Read command error\n");
|
||||
|
||||
if (temp[0] == 0x91) {
|
||||
ipio_info("check fw ready\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (temp[0] != 0x91)
|
||||
ipio_err("FW is busy, error\n");
|
||||
ipio_info("load gesture code\n");
|
||||
/* load gesture code */
|
||||
if (core_config_ice_mode_enable() < 0)
|
||||
ipio_err("Failed to enter ICE mode\n");
|
||||
|
||||
tddi_host_download(true);
|
||||
|
||||
temp[0] = 0x01;
|
||||
temp[1] = 0x0A;
|
||||
temp[2] = 0x06;
|
||||
if ((core_write(core_config->slave_i2c_addr, temp, 3)) < 0)
|
||||
ipio_err("write command error\n");
|
||||
|
||||
core_gesture->entry = false;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(core_gesture_load_code);
|
||||
|
||||
int core_gesture_load_ap_code(void)
|
||||
{
|
||||
int i = 0, ret = 0;
|
||||
uint8_t temp[64] = {0};
|
||||
|
||||
core_gesture->entry = true;
|
||||
|
||||
/* Write Load AP Flag */
|
||||
temp[0] = 0x01;
|
||||
temp[1] = 0x01;
|
||||
temp[2] = 0x00;
|
||||
if ((core_write(core_config->slave_i2c_addr, temp, 3)) < 0)
|
||||
ipio_err("write command AP Flag error\n");
|
||||
|
||||
if ((core_read(core_config->slave_i2c_addr, temp, 20)) < 0)
|
||||
ipio_err("Read AP Flag error\n");
|
||||
|
||||
/* Leave Gesture Cmd LPWG Stop */
|
||||
temp[0] = 0x01;
|
||||
temp[1] = 0x0A;
|
||||
temp[2] = 0x00;
|
||||
if ((core_write(core_config->slave_i2c_addr, temp, 3)) < 0)
|
||||
ipio_err("write command LPWG Stop error\n");
|
||||
|
||||
for (i = 0 ; i < 20 ; i++) {
|
||||
|
||||
mdelay(i * 100 + 100);
|
||||
|
||||
temp[0] = 0x01;
|
||||
temp[1] = 0x0A;
|
||||
temp[2] = 0x05;
|
||||
if ((core_write(core_config->slave_i2c_addr, temp, 3)) < 0)
|
||||
ipio_err("write command error\n");
|
||||
if ((core_read(core_config->slave_i2c_addr, temp, 1)) < 0)
|
||||
ipio_err("Read command error\n");
|
||||
if (temp[0] == 0x91) {
|
||||
ipio_info("check fw ready\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 3 && temp[0] != 0x01)
|
||||
ipio_err("FW is busy, error\n");
|
||||
|
||||
/* load AP code */
|
||||
if (core_config_ice_mode_enable() < 0)
|
||||
ipio_err("Failed to enter ICE mode\n");
|
||||
|
||||
tddi_host_download(false);
|
||||
|
||||
temp[0] = 0x01;
|
||||
temp[1] = 0x0A;
|
||||
temp[2] = 0x06;
|
||||
if ((core_write(core_config->slave_i2c_addr, temp, 3)) < 0)
|
||||
ipio_err("write command error\n");
|
||||
|
||||
core_gesture->entry = false;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(core_gesture_load_ap_code);
|
||||
#endif
|
||||
|
||||
int core_gesture_match_key(uint8_t gdata)
|
||||
{
|
||||
int gcode;
|
||||
|
||||
switch (gdata) {
|
||||
case GESTURE_LEFT:
|
||||
gcode = KEY_GESTURE_LEFT;
|
||||
break;
|
||||
case GESTURE_RIGHT:
|
||||
gcode = KEY_GESTURE_RIGHT;
|
||||
break;
|
||||
case GESTURE_UP:
|
||||
gcode = KEY_GESTURE_UP;
|
||||
break;
|
||||
case GESTURE_DOWN:
|
||||
gcode = KEY_GESTURE_DOWN;
|
||||
break;
|
||||
case GESTURE_DOUBLECLICK:
|
||||
gcode = KEY_GESTURE_D;
|
||||
break;
|
||||
case GESTURE_O:
|
||||
gcode = KEY_GESTURE_O;
|
||||
break;
|
||||
case GESTURE_W:
|
||||
gcode = KEY_GESTURE_W;
|
||||
break;
|
||||
case GESTURE_M:
|
||||
gcode = KEY_GESTURE_M;
|
||||
break;
|
||||
case GESTURE_E:
|
||||
gcode = KEY_GESTURE_E;
|
||||
break;
|
||||
case GESTURE_S:
|
||||
gcode = KEY_GESTURE_S;
|
||||
break;
|
||||
case GESTURE_V:
|
||||
gcode = KEY_GESTURE_V;
|
||||
break;
|
||||
case GESTURE_Z:
|
||||
gcode = KEY_GESTURE_Z;
|
||||
break;
|
||||
case GESTURE_C:
|
||||
gcode = KEY_GESTURE_C;
|
||||
break;
|
||||
default:
|
||||
gcode = ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
ipio_debug(DEBUG_GESTURE, "gcode = %d\n", gcode);
|
||||
return gcode;
|
||||
}
|
||||
EXPORT_SYMBOL(core_gesture_match_key);
|
||||
|
||||
void core_gesture_set_key(struct core_fr_data *fr_data)
|
||||
{
|
||||
struct input_dev *input_dev = fr_data->input_device;
|
||||
|
||||
if (input_dev != NULL) {
|
||||
input_set_capability(input_dev, EV_KEY, KEY_POWER);
|
||||
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_UP);
|
||||
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_DOWN);
|
||||
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_LEFT);
|
||||
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_RIGHT);
|
||||
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_O);
|
||||
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_E);
|
||||
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_M);
|
||||
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_W);
|
||||
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_S);
|
||||
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_V);
|
||||
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_Z);
|
||||
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_C);
|
||||
|
||||
__set_bit(KEY_POWER, input_dev->keybit);
|
||||
__set_bit(KEY_GESTURE_UP, input_dev->keybit);
|
||||
__set_bit(KEY_GESTURE_DOWN, input_dev->keybit);
|
||||
__set_bit(KEY_GESTURE_LEFT, input_dev->keybit);
|
||||
__set_bit(KEY_GESTURE_RIGHT, input_dev->keybit);
|
||||
__set_bit(KEY_GESTURE_O, input_dev->keybit);
|
||||
__set_bit(KEY_GESTURE_E, input_dev->keybit);
|
||||
__set_bit(KEY_GESTURE_M, input_dev->keybit);
|
||||
__set_bit(KEY_GESTURE_W, input_dev->keybit);
|
||||
__set_bit(KEY_GESTURE_S, input_dev->keybit);
|
||||
__set_bit(KEY_GESTURE_V, input_dev->keybit);
|
||||
__set_bit(KEY_GESTURE_Z, input_dev->keybit);
|
||||
__set_bit(KEY_GESTURE_C, input_dev->keybit);
|
||||
return;
|
||||
}
|
||||
|
||||
ipio_err("GESTURE: input dev is NULL\n");
|
||||
}
|
||||
EXPORT_SYMBOL(core_gesture_set_key);
|
||||
|
||||
int core_gesture_init(void)
|
||||
{
|
||||
if (core_gesture == NULL) {
|
||||
core_gesture = kzalloc(sizeof(*core_gesture), GFP_KERNEL);
|
||||
if (ERR_ALLOC_MEM(core_gesture)) {
|
||||
ipio_err("Failed to allocate core_gesture mem, %ld\n",
|
||||
PTR_ERR(core_gesture));
|
||||
core_gesture_remove();
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
core_gesture->entry = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(core_gesture_init);
|
||||
|
||||
void core_gesture_remove(void)
|
||||
{
|
||||
ipio_info("Remove core-gesture members\n");
|
||||
ipio_kfree((void **)&core_gesture);
|
||||
}
|
||||
EXPORT_SYMBOL(core_gesture_remove);
|
||||
|
||||
|
||||
88
drivers/input/touchscreen/ilitek_mmi/core/gesture.h
Normal file
88
drivers/input/touchscreen/ilitek_mmi/core/gesture.h
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* ILITEK Touch IC driver
|
||||
*
|
||||
* Copyright (C) 2011 ILI Technology Corporation.
|
||||
*
|
||||
* Author: Dicky Chiang <dicky_chiang@ilitek.com>
|
||||
* Based on TDD v7.0 implemented by Mstar & ILITEK
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __GESTURE_H
|
||||
#define __GESTURE_H
|
||||
#define GESTURE_NORMAL_MODE 0
|
||||
#define GESTURE_INFO_MPDE 1
|
||||
#define GESTURE_INFO_LENGTH 170
|
||||
#define GESTURE_MORMAL_LENGTH 8
|
||||
|
||||
/* The example for the gesture virtual keys */
|
||||
#define GESTURE_DOUBLECLICK 0x58
|
||||
#define GESTURE_UP 0x60
|
||||
#define GESTURE_DOWN 0x61
|
||||
#define GESTURE_LEFT 0x62
|
||||
#define GESTURE_RIGHT 0x63
|
||||
#define GESTURE_M 0x64
|
||||
#define GESTURE_W 0x65
|
||||
#define GESTURE_C 0x66
|
||||
#define GESTURE_E 0x67
|
||||
#define GESTURE_V 0x68
|
||||
#define GESTURE_O 0x69
|
||||
#define GESTURE_S 0x6A
|
||||
#define GESTURE_Z 0x6B
|
||||
|
||||
/* oppo gesture define */
|
||||
#define GESTURE_CODE_V_DOWN 0x6C
|
||||
#define GESTURE_CODE_V_LEFT 0x6D
|
||||
#define GESTURE_CODE_V_RIGHT 0x6E
|
||||
#define GESTURE_CODE_TWO_LINE_2_BOTTOM 0x6F
|
||||
|
||||
#define KEY_GESTURE_D KEY_D
|
||||
#define KEY_GESTURE_UP KEY_UP
|
||||
#define KEY_GESTURE_DOWN KEY_DOWN
|
||||
#define KEY_GESTURE_LEFT KEY_LEFT
|
||||
#define KEY_GESTURE_RIGHT KEY_RIGHT
|
||||
#define KEY_GESTURE_O KEY_O
|
||||
#define KEY_GESTURE_E KEY_E
|
||||
#define KEY_GESTURE_M KEY_M
|
||||
#define KEY_GESTURE_W KEY_W
|
||||
#define KEY_GESTURE_S KEY_S
|
||||
#define KEY_GESTURE_V KEY_V
|
||||
#define KEY_GESTURE_C KEY_C
|
||||
#define KEY_GESTURE_Z KEY_Z
|
||||
|
||||
struct core_gesture_data {
|
||||
uint32_t start_addr;
|
||||
uint32_t length;
|
||||
bool entry;
|
||||
uint8_t mode; /* normal:0 info:1 */
|
||||
uint32_t ap_start_addr;
|
||||
uint32_t ap_length;
|
||||
uint32_t area_section;
|
||||
bool suspend;
|
||||
};
|
||||
|
||||
extern struct core_gesture_data *core_gesture;
|
||||
extern uint8_t ap_fw[MAX_AP_FIRMWARE_SIZE];
|
||||
#ifdef HOST_DOWNLOAD
|
||||
extern int core_gesture_load_code(void);
|
||||
extern int core_gesture_load_ap_code(void);
|
||||
#endif
|
||||
extern int core_gesture_match_key(uint8_t gid);
|
||||
extern void core_gesture_set_key(struct core_fr_data *fr_data);
|
||||
extern int core_gesture_init(void);
|
||||
extern void core_gesture_remove(void);
|
||||
#endif
|
||||
278
drivers/input/touchscreen/ilitek_mmi/core/i2c.c
Normal file
278
drivers/input/touchscreen/ilitek_mmi/core/i2c.c
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
/*
|
||||
* ILITEK Touch IC driver
|
||||
*
|
||||
* Copyright (C) 2011 ILI Technology Corporation.
|
||||
*
|
||||
* Author: Dicky Chiang <dicky_chiang@ilitek.com>
|
||||
* Based on TDD v7.0 implemented by Mstar & ILITEK
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../common.h"
|
||||
#include "config.h"
|
||||
#include "i2c.h"
|
||||
#include "mp_test.h"
|
||||
#include "finger_report.h"
|
||||
#include "protocol.h"
|
||||
#include "../platform.h"
|
||||
|
||||
|
||||
struct core_i2c_data *core_i2c;
|
||||
|
||||
#ifdef I2C_DMA
|
||||
static unsigned char *ilitek_dma_va;
|
||||
static dma_addr_t ilitek_dma_pa;
|
||||
|
||||
#define DMA_VA_BUFFER 4096
|
||||
|
||||
static int dma_alloc(struct core_i2c_data *i2c)
|
||||
{
|
||||
if (i2c->client != NULL) {
|
||||
i2c->client->dev.coherent_dma_mask = DMA_BIT_MASK(32);
|
||||
ilitek_dma_va = (u8 *) dma_alloc_coherent(&i2c->client->dev
|
||||
, DMA_VA_BUFFER, &ilitek_dma_pa, GFP_KERNEL);
|
||||
if (ERR_ALLOC_MEM(ilitek_dma_va)) {
|
||||
ipio_err("Allocate DMA I2C Buffer failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(ilitek_dma_va, 0, DMA_VA_BUFFER);
|
||||
i2c->client->ext_flag |= I2C_DMA_FLAG;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ipio_err("i2c->client is NULL, return fail\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static void dma_free(void)
|
||||
{
|
||||
if (ilitek_dma_va != NULL) {
|
||||
dma_free_coherent(&core_i2c->client->dev, DMA_VA_BUFFER
|
||||
, ilitek_dma_va, ilitek_dma_pa);
|
||||
|
||||
ilitek_dma_va = NULL;
|
||||
ilitek_dma_pa = 0;
|
||||
|
||||
ipio_info("Succeed to free DMA buffer\n");
|
||||
}
|
||||
}
|
||||
#endif /* I2C_DMA */
|
||||
|
||||
int core_i2c_write(uint8_t nSlaveId, uint8_t *pBuf, uint16_t nSize)
|
||||
{
|
||||
int res = 0;
|
||||
uint8_t check_sum = 0;
|
||||
uint8_t *txbuf = NULL;
|
||||
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = nSlaveId,
|
||||
.flags = 0, /* write flag. */
|
||||
.len = nSize,
|
||||
.buf = pBuf,
|
||||
},
|
||||
};
|
||||
|
||||
#ifdef I2C_DMA
|
||||
ipio_debug(DEBUG_I2C, "DMA: size = %d\n", nSize);
|
||||
if (nSize > 8) {
|
||||
msgs[0].addr = (core_i2c->client->addr & I2C_MASK_FLAG);
|
||||
msgs[0].ext_flag =
|
||||
(core_i2c->client->ext_flag | I2C_ENEXT_FLAG | I2C_DMA_FLAG);
|
||||
memcpy(ilitek_dma_va, pBuf, nSize);
|
||||
msgs[0].buf = (uint8_t *) ilitek_dma_pa;
|
||||
}
|
||||
#endif /* I2C_DMA */
|
||||
|
||||
/*
|
||||
* NOTE: If TP driver is doing MP test and commanding 0xF1 to FW,
|
||||
* we add a checksum to the last index and plus 1 with size.
|
||||
*/
|
||||
if (protocol->major >= 5 && protocol->mid >= 4) {
|
||||
if (!core_config->icemodeenable && pBuf[0] == 0xF1 &&
|
||||
core_mp->run) {
|
||||
check_sum = core_fr_calc_checksum(pBuf, nSize);
|
||||
txbuf =
|
||||
kcalloc(nSize + 1, sizeof(uint8_t), GFP_KERNEL);
|
||||
if (ERR_ALLOC_MEM(txbuf)) {
|
||||
ipio_err("Failed to allocate txbuf mem\n");
|
||||
res = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
memcpy(txbuf, pBuf, nSize);
|
||||
txbuf[nSize] = check_sum;
|
||||
msgs[0].buf = txbuf;
|
||||
msgs[0].len = nSize + 1;
|
||||
dump_data(txbuf, 8, nSize + 1, nSize + 1, "summer_i2c_dump");
|
||||
}
|
||||
}
|
||||
|
||||
if (i2c_transfer(core_i2c->client->adapter, msgs, 1) < 0) {
|
||||
if (core_config->do_ic_reset) {
|
||||
/* ignore i2c error if doing ic reset */
|
||||
res = 0;
|
||||
} else {
|
||||
res = -EIO;
|
||||
ipio_err("I2C Write Error, res = %d\n", res);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
ipio_kfree((void **)&txbuf);
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(core_i2c_write);
|
||||
|
||||
int core_i2c_read(uint8_t nSlaveId, uint8_t *pBuf, uint16_t nSize)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = nSlaveId,
|
||||
.flags = I2C_M_RD, /* read flag */
|
||||
.len = nSize,
|
||||
.buf = pBuf,
|
||||
},
|
||||
};
|
||||
|
||||
#ifdef I2C_DMA
|
||||
ipio_debug(DEBUG_I2C, "DMA: size = %d\n", nSize);
|
||||
if (nSize > 8) {
|
||||
msgs[0].addr = (core_i2c->client->addr & I2C_MASK_FLAG);
|
||||
msgs[0].ext_flag =
|
||||
(core_i2c->client->ext_flag | I2C_ENEXT_FLAG | I2C_DMA_FLAG);
|
||||
msgs[0].buf = (uint8_t *) ilitek_dma_pa;
|
||||
} else {
|
||||
msgs[0].buf = pBuf;
|
||||
}
|
||||
#endif /* I2C_DMA */
|
||||
|
||||
if (i2c_transfer(core_i2c->client->adapter, msgs, 1) < 0) {
|
||||
res = -EIO;
|
||||
ipio_err("I2C Read Error, res = %d\n", res);
|
||||
goto out;
|
||||
}
|
||||
#ifdef I2C_DMA
|
||||
if (nSize > 8)
|
||||
memcpy(pBuf, ilitek_dma_va, nSize);
|
||||
|
||||
#endif /* I2C_DMA */
|
||||
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(core_i2c_read);
|
||||
|
||||
int core_i2c_segmental_read(uint8_t nSlaveId, uint8_t *pBuf, uint16_t nSize)
|
||||
{
|
||||
int res = 0;
|
||||
int offset = 0;
|
||||
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = nSlaveId,
|
||||
.flags = I2C_M_RD,
|
||||
.len = nSize,
|
||||
/* .buf = pBuf, */
|
||||
},
|
||||
};
|
||||
|
||||
while (nSize > 0) {
|
||||
msgs[0].buf = &pBuf[offset];
|
||||
|
||||
if (nSize > core_i2c->seg_len) {
|
||||
msgs[0].len = core_i2c->seg_len;
|
||||
nSize -= core_i2c->seg_len;
|
||||
offset += msgs[0].len;
|
||||
} else {
|
||||
msgs[0].len = nSize;
|
||||
nSize = 0;
|
||||
}
|
||||
|
||||
ipio_debug(DEBUG_I2C, "Length = %d\n", msgs[0].len);
|
||||
|
||||
if (i2c_transfer(core_i2c->client->adapter, msgs, 1) < 0) {
|
||||
res = -EIO;
|
||||
ipio_err("I2C Read Error, res = %d\n", res);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(core_i2c_segmental_read);
|
||||
|
||||
int core_i2c_init(struct i2c_client *client)
|
||||
{
|
||||
int i;
|
||||
|
||||
core_i2c = kmalloc(sizeof(*core_i2c), GFP_KERNEL);
|
||||
if (ERR_ALLOC_MEM(core_i2c)) {
|
||||
ipio_err("Failed to alllocate core_i2c mem %ld\n",
|
||||
PTR_ERR(core_i2c));
|
||||
core_i2c_remove();
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
core_i2c->client = client;
|
||||
core_i2c->seg_len = 256; /* length of segment */
|
||||
|
||||
#ifdef I2C_DMA
|
||||
if (dma_alloc(core_i2c->client) < 0) {
|
||||
ipio_err("Failed to alllocate DMA mem %ld\n",
|
||||
PTR_ERR(core_i2c));
|
||||
return -ENOMEM;
|
||||
}
|
||||
#endif /* I2C_DMA */
|
||||
|
||||
for (i = 0 ; i < ARRAY_SIZE(ipio_chip_list); i++) {
|
||||
if (ipio_chip_list[i] == ipd->chip_id) {
|
||||
if (ipio_chip_list[i] == CHIP_TYPE_ILI7807) {
|
||||
if (core_config->chip_type == ILI7807_TYPE_F_AA
|
||||
&& core_config->chip_type == ILI7807_TYPE_F_AB)
|
||||
core_i2c->clk = 100000;
|
||||
else
|
||||
core_i2c->clk = 400000;
|
||||
|
||||
} else if (ipio_chip_list[i] == CHIP_TYPE_ILI9881) {
|
||||
core_i2c->clk = 400000;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ipio_err("Can't find this chip in support list\n");
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(core_i2c_init);
|
||||
|
||||
void core_i2c_remove(void)
|
||||
{
|
||||
ipio_info("Remove core-i2c members\n");
|
||||
|
||||
#ifdef I2C_DMA
|
||||
dma_free();
|
||||
#endif /* I2C_DMA */
|
||||
|
||||
ipio_kfree((void **)&core_i2c);
|
||||
}
|
||||
EXPORT_SYMBOL(core_i2c_remove);
|
||||
45
drivers/input/touchscreen/ilitek_mmi/core/i2c.h
Normal file
45
drivers/input/touchscreen/ilitek_mmi/core/i2c.h
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* ILITEK Touch IC driver
|
||||
*
|
||||
* Copyright (C) 2011 ILI Technology Corporation.
|
||||
*
|
||||
* Author: Dicky Chiang <dicky_chiang@ilitek.com>
|
||||
* Based on TDD v7.0 implemented by Mstar & ILITEK
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __I2C_H
|
||||
#define __I2C_H
|
||||
|
||||
struct core_i2c_data {
|
||||
struct i2c_client *client;
|
||||
int clk;
|
||||
int seg_len;
|
||||
};
|
||||
|
||||
extern struct core_i2c_data *core_i2c;
|
||||
|
||||
extern int core_i2c_write(uint8_t nSlaveId, uint8_t *pBuf, uint16_t nSize);
|
||||
extern int core_i2c_read(uint8_t nSlaveId, uint8_t *pBuf, uint16_t nSize);
|
||||
|
||||
extern int core_i2c_segmental_read(uint8_t nSlaveId, uint8_t *pBuf
|
||||
, uint16_t nSize);
|
||||
|
||||
extern int core_i2c_init(struct i2c_client *client);
|
||||
extern void core_i2c_remove(void);
|
||||
|
||||
#endif
|
||||
3
drivers/input/touchscreen/ilitek_mmi/core/ilitek_fw.h
Normal file
3
drivers/input/touchscreen/ilitek_mmi/core/ilitek_fw.h
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
static unsigned char CTPM_FW[] = {
|
||||
#include "FW_TDDI_9881H.ili"
|
||||
};
|
||||
2446
drivers/input/touchscreen/ilitek_mmi/core/mp_test.c
Normal file
2446
drivers/input/touchscreen/ilitek_mmi/core/mp_test.c
Normal file
File diff suppressed because it is too large
Load diff
172
drivers/input/touchscreen/ilitek_mmi/core/mp_test.h
Normal file
172
drivers/input/touchscreen/ilitek_mmi/core/mp_test.h
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* ILITEK Touch IC driver
|
||||
*
|
||||
* Copyright (C) 2011 ILI Technology Corporation.
|
||||
*
|
||||
* Author: Dicky Chiang <dicky_chiang@ilitek.com>
|
||||
* Based on TDD v7.0 implemented by Mstar & ILITEK
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __MP_TEST_H
|
||||
#define __MP_TEST_H
|
||||
|
||||
#define MP_PASS 1
|
||||
#define MP_FAIL -1
|
||||
#define BENCHMARK 1
|
||||
#define NODETYPE 1
|
||||
#define RAWDATA_NO_BK_DATA_SHIFT_9881H 8192
|
||||
#define RAWDATA_NO_BK_DATA_SHIFT_9881F 4096
|
||||
#define TYPE_BENCHMARK 0
|
||||
#define TYPE_NO_JUGE 1
|
||||
#define TYPE_JUGE 2
|
||||
|
||||
struct mp_test_P540_open {
|
||||
int32_t *cbk_700;
|
||||
int32_t *cbk_250;
|
||||
int32_t *cbk_200;
|
||||
int32_t *charg_rate;
|
||||
int32_t *full_Open;
|
||||
int32_t *dac;
|
||||
int32_t *cdc;
|
||||
};
|
||||
|
||||
struct mp_test_items {
|
||||
char *name;
|
||||
/* The description must be the same as ini's section name */
|
||||
char *desp;
|
||||
char *result;
|
||||
int catalog;
|
||||
uint8_t cmd;
|
||||
uint8_t spec_option;
|
||||
uint8_t type_option;
|
||||
bool run;
|
||||
int max;
|
||||
int max_res;
|
||||
int item_result;
|
||||
int test_count;
|
||||
int min;
|
||||
int min_res;
|
||||
int frame_count;
|
||||
int trimmed_mean;
|
||||
int lowest_percentage;
|
||||
int highest_percentage;
|
||||
int32_t *result_buf;
|
||||
int32_t *buf;
|
||||
int32_t *max_buf;
|
||||
int32_t *min_buf;
|
||||
int32_t *bench_mark_max;
|
||||
int32_t *bench_mark_min;
|
||||
int32_t *node_type;
|
||||
int (*do_test)(int index);
|
||||
};
|
||||
|
||||
struct mp_nodp_calc {
|
||||
bool is60HZ;
|
||||
bool isLongV;
|
||||
|
||||
/* Input */
|
||||
uint16_t tshd;
|
||||
uint8_t multi_term_num_120;
|
||||
uint8_t multi_term_num_60;
|
||||
uint16_t tsvd_to_tshd;
|
||||
uint16_t qsh_tdf;
|
||||
|
||||
/* Settings */
|
||||
uint8_t auto_trim;
|
||||
uint16_t tp_tshd_wait_120;
|
||||
uint16_t ddi_width_120;
|
||||
uint16_t tp_tshd_wait_60;
|
||||
uint16_t ddi_width_60;
|
||||
uint16_t dp_to_tp;
|
||||
uint16_t tx_wait_const;
|
||||
uint16_t tx_wait_const_multi;
|
||||
uint16_t tp_to_dp;
|
||||
uint8_t phase_adc;
|
||||
uint8_t r2d_pw;
|
||||
uint8_t rst_pw;
|
||||
uint8_t rst_pw_back;
|
||||
uint8_t dac_td;
|
||||
uint8_t qsh_pw;
|
||||
uint8_t qsh_td;
|
||||
uint8_t drop_nodp;
|
||||
|
||||
/* Output */
|
||||
uint32_t first_tp_width;
|
||||
uint32_t tp_width;
|
||||
uint32_t txpw;
|
||||
uint32_t long_tsdh_wait;
|
||||
uint32_t nodp;
|
||||
};
|
||||
|
||||
struct core_mp_test_data {
|
||||
struct mp_nodp_calc nodp;
|
||||
/* A flag shows a test run in particular */
|
||||
bool run;
|
||||
bool oppo_run;
|
||||
bool oppo_lcm;
|
||||
bool m_signal;
|
||||
bool m_dac;
|
||||
bool s_signal;
|
||||
bool s_dac;
|
||||
bool key_dac;
|
||||
bool st_dac;
|
||||
bool p_no_bk;
|
||||
bool p_has_bk;
|
||||
bool open_integ;
|
||||
bool open_cap;
|
||||
|
||||
int xch_len;
|
||||
int ych_len;
|
||||
int stx_len;
|
||||
int srx_len;
|
||||
int key_len;
|
||||
int st_len;
|
||||
int frame_len;
|
||||
int mp_items;
|
||||
int final_result;
|
||||
|
||||
/* Tx/Rx threshold & buffer */
|
||||
int TxDeltaMax;
|
||||
int TxDeltaMin;
|
||||
int RxDeltaMax;
|
||||
int RxDeltaMin;
|
||||
int32_t *tx_delta_buf;
|
||||
int32_t *rx_delta_buf;
|
||||
int32_t *tx_max_buf;
|
||||
int32_t *tx_min_buf;
|
||||
int32_t *rx_max_buf;
|
||||
int32_t *rx_min_buf;
|
||||
|
||||
int tdf;
|
||||
bool retry;
|
||||
bool busy_cdc;
|
||||
bool ctrl_lcm;
|
||||
};
|
||||
|
||||
extern struct core_mp_test_data *core_mp;
|
||||
extern struct mp_test_items tItems[];
|
||||
|
||||
extern void dump_data(void *data, int type, int len, int row_len, const char *name);
|
||||
extern int core_mp_calc_timing_nodp(void);
|
||||
extern int core_mp_ctrl_lcm_status(bool on);
|
||||
extern void core_mp_test_free(void);
|
||||
extern void core_mp_show_result(void);
|
||||
extern void core_mp_run_test(char *item, bool ini);
|
||||
extern int core_mp_move_code(void);
|
||||
extern int core_mp_init(void);
|
||||
#endif
|
||||
500
drivers/input/touchscreen/ilitek_mmi/core/parser.c
Normal file
500
drivers/input/touchscreen/ilitek_mmi/core/parser.c
Normal file
|
|
@ -0,0 +1,500 @@
|
|||
/*
|
||||
* ILITEK Touch IC driver
|
||||
*
|
||||
* Copyright (C) 2011 ILI Technology Corporation.
|
||||
*
|
||||
* Author: Dicky Chiang <dicky_chiang@ilitek.com>
|
||||
* Based on TDD v7.0 implemented by Mstar & ILITEK
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../common.h"
|
||||
#include "parser.h"
|
||||
#include "config.h"
|
||||
|
||||
#define PARSER_MAX_CFG_BUF (512 * 3)
|
||||
#define PARSER_MAX_KEY_NUM (600 * 3)
|
||||
#define PARSER_MAX_KEY_NAME_LEN 100
|
||||
#define PARSER_MAX_KEY_VALUE_LEN 2000
|
||||
|
||||
#define INI_ERR_OUT_OF_LINE -1
|
||||
|
||||
struct ini_file_data {
|
||||
char pSectionName[PARSER_MAX_KEY_NAME_LEN];
|
||||
char pKeyName[PARSER_MAX_KEY_NAME_LEN];
|
||||
char pKeyValue[PARSER_MAX_KEY_VALUE_LEN];
|
||||
int iSectionNameLen;
|
||||
int iKeyNameLen;
|
||||
int iKeyValueLen;
|
||||
} ilitek_ini_file_data[PARSER_MAX_KEY_NUM];
|
||||
|
||||
int g_ini_items;
|
||||
|
||||
static int isspace_t(int x)
|
||||
{
|
||||
if (x == ' ' || x == '\t' || x == '\n' || x == '\f' || x == '\b' || x == '\r')
|
||||
return ERROR;
|
||||
else
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static char *ini_str_trim_r(char *buf)
|
||||
{
|
||||
int len, i;
|
||||
char tmp[512] = { 0 };
|
||||
|
||||
len = strlen(buf)+1;
|
||||
for (i = 0 ; i < len ; i++) {
|
||||
if (buf[i] != ' ')
|
||||
break;
|
||||
}
|
||||
if (i < len)
|
||||
strlcpy(tmp, (buf + i), (len - i));
|
||||
|
||||
strlcpy(buf, tmp, len);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Count the number of each line and assign the content to tmp buffer */
|
||||
static int get_ini_phy_line(char *data, char *buffer, int maxlen)
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int iRetNum = -1;
|
||||
char ch1 = '\0';
|
||||
|
||||
for (i = 0, j = 0 ; i < maxlen ; j++) {
|
||||
ch1 = data[j];
|
||||
iRetNum = j + 1;
|
||||
if (ch1 == '\n' || ch1 == '\r') { /* line end */
|
||||
ch1 = data[j + 1];
|
||||
if (ch1 == '\n' || ch1 == '\r') {
|
||||
iRetNum++;
|
||||
}
|
||||
|
||||
break;
|
||||
} else if (ch1 == 0x00) {
|
||||
//iRetNum = -1;
|
||||
break; /* file end */
|
||||
}
|
||||
|
||||
buffer[i++] = ch1;
|
||||
}
|
||||
|
||||
buffer[i] = '\0';
|
||||
return iRetNum;
|
||||
}
|
||||
|
||||
static int get_ini_phy_data(char *data, int fsize)
|
||||
{
|
||||
int i, n = 0, res = 0, banchmark_flag = 0, empty_section, nodetype_flag = 0;
|
||||
int offset = 0, isEqualSign = 0;
|
||||
char *ini_buf = NULL, *tmpSectionName = NULL, *temp;
|
||||
char M_CFG_SSL = '[';
|
||||
char M_CFG_SSR = ']';
|
||||
/* char M_CFG_NIS = ':'; */
|
||||
char M_CFG_NTS = '#';
|
||||
char M_CFG_EQS = '=';
|
||||
|
||||
if (data == NULL) {
|
||||
ipio_err("INI data is NULL\n");
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ini_buf = kzalloc((PARSER_MAX_CFG_BUF + 1) * sizeof(char), GFP_KERNEL);
|
||||
if (ERR_ALLOC_MEM(ini_buf)) {
|
||||
ipio_err("Failed to allocate ini_buf memory, %ld\n", PTR_ERR(ini_buf));
|
||||
res = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
tmpSectionName = kzalloc((PARSER_MAX_CFG_BUF + 1) * sizeof(char), GFP_KERNEL);
|
||||
if (ERR_ALLOC_MEM(tmpSectionName)) {
|
||||
ipio_err("Failed to allocate tmpSectionName memory, %ld\n", PTR_ERR(tmpSectionName));
|
||||
res = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
temp = strnstr(data, TYPE_MARK, fsize);
|
||||
if (temp != NULL) {
|
||||
ipio_debug(DEBUG_PARSER, "Find Type mark, locat = %ld", temp-data);
|
||||
if (core_config->core_type == CORE_TYPE_B)
|
||||
offset = temp-data;
|
||||
else
|
||||
fsize = temp-data;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
banchmark_flag = 0;
|
||||
empty_section = 0;
|
||||
nodetype_flag = 0;
|
||||
if (g_ini_items > PARSER_MAX_KEY_NUM) {
|
||||
ipio_err("MAX_KEY_NUM: Out of length\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (offset >= fsize)
|
||||
goto out;/*over size*/
|
||||
n = get_ini_phy_line(data + offset, ini_buf, PARSER_MAX_CFG_BUF);
|
||||
|
||||
if (n < 0) {
|
||||
ipio_err("End of Line\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
offset += n;
|
||||
|
||||
n = strlen(ini_str_trim_r(ini_buf));
|
||||
|
||||
if (n == 0 || ini_buf[0] == M_CFG_NTS)
|
||||
continue;
|
||||
|
||||
/* Get section names */
|
||||
if (n > 2 && ((ini_buf[0] == M_CFG_SSL && ini_buf[n - 1] != M_CFG_SSR))) {
|
||||
ipio_err("Bad Section: %s\n", ini_buf);
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
} else {
|
||||
if (ini_buf[0] == M_CFG_SSL) {
|
||||
ilitek_ini_file_data[g_ini_items].iSectionNameLen = n - 2;
|
||||
if (ilitek_ini_file_data[g_ini_items].iSectionNameLen > PARSER_MAX_KEY_NAME_LEN) {
|
||||
ipio_err("MAX_KEY_NAME_LEN: Out Of Length\n");
|
||||
res = INI_ERR_OUT_OF_LINE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ini_buf[n - 1] = 0x00;
|
||||
strlcpy((char *)tmpSectionName, ini_buf + 1, ((PARSER_MAX_CFG_BUF + 1) * sizeof(char)));
|
||||
banchmark_flag = 0;
|
||||
nodetype_flag = 0;
|
||||
ipio_debug(DEBUG_PARSER, "Section Name: %s, Len: %d, offset = %d\n", tmpSectionName, n - 2, offset);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* copy section's name without square brackets to its real buffer */
|
||||
strlcpy(ilitek_ini_file_data[g_ini_items].pSectionName, tmpSectionName, strlen(tmpSectionName)+1);
|
||||
ilitek_ini_file_data[g_ini_items].iSectionNameLen = strlen(tmpSectionName);
|
||||
|
||||
isEqualSign = 0;
|
||||
for (i = 0 ; i < n ; i++) {
|
||||
if (ini_buf[i] == M_CFG_EQS) {
|
||||
isEqualSign = i;
|
||||
break;
|
||||
}
|
||||
if (ini_buf[i] == M_CFG_SSL || ini_buf[i] == M_CFG_SSR) {
|
||||
empty_section = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isEqualSign == 0) {
|
||||
if (empty_section)
|
||||
continue;
|
||||
|
||||
if (strnstr(ilitek_ini_file_data[g_ini_items].pSectionName, "Benchmark_Data", strlen(ilitek_ini_file_data[g_ini_items].pSectionName)) > 0) {
|
||||
banchmark_flag = 1;
|
||||
isEqualSign = -1;
|
||||
} else if (strnstr(ilitek_ini_file_data[g_ini_items].pSectionName, "Node Type", strlen(ilitek_ini_file_data[g_ini_items].pSectionName)) > 0) {
|
||||
nodetype_flag = 1;
|
||||
isEqualSign = -1;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (banchmark_flag) {
|
||||
/* Get Key names */
|
||||
ilitek_ini_file_data[g_ini_items].iKeyNameLen = strlen(BENCHMARK_KEY_NAME);
|
||||
strlcpy(ilitek_ini_file_data[g_ini_items].pKeyName, BENCHMARK_KEY_NAME, strlen(BENCHMARK_KEY_NAME)+1);
|
||||
ilitek_ini_file_data[g_ini_items].iKeyValueLen = n;
|
||||
} else if (nodetype_flag) {
|
||||
/* Get Key names */
|
||||
ilitek_ini_file_data[g_ini_items].iKeyNameLen = strlen(NODE_TYPE_KEY_NAME);
|
||||
strlcpy(ilitek_ini_file_data[g_ini_items].pKeyName, NODE_TYPE_KEY_NAME, strlen(NODE_TYPE_KEY_NAME)+1);
|
||||
ilitek_ini_file_data[g_ini_items].iKeyValueLen = n;
|
||||
} else {
|
||||
/* Get Key names */
|
||||
ilitek_ini_file_data[g_ini_items].iKeyNameLen = isEqualSign;
|
||||
if (ilitek_ini_file_data[g_ini_items].iKeyNameLen > PARSER_MAX_KEY_NAME_LEN) {
|
||||
/* ret = CFG_ERR_OUT_OF_LEN; */
|
||||
ipio_err("MAX_KEY_NAME_LEN: Out Of Length\n");
|
||||
res = INI_ERR_OUT_OF_LINE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(ilitek_ini_file_data[g_ini_items].pKeyName,
|
||||
ini_buf, ilitek_ini_file_data[g_ini_items].iKeyNameLen);
|
||||
ilitek_ini_file_data[g_ini_items].iKeyValueLen = n - isEqualSign - 1;
|
||||
}
|
||||
|
||||
/* Get a value assigned to a key */
|
||||
|
||||
if (ilitek_ini_file_data[g_ini_items].iKeyValueLen > PARSER_MAX_KEY_VALUE_LEN) {
|
||||
ipio_err("MAX_KEY_VALUE_LEN: Out Of Length\n");
|
||||
res = INI_ERR_OUT_OF_LINE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(ilitek_ini_file_data[g_ini_items].pKeyValue,
|
||||
ini_buf + isEqualSign + 1, ilitek_ini_file_data[g_ini_items].iKeyValueLen);
|
||||
|
||||
ipio_debug(DEBUG_PARSER, "%s = %s\n", ilitek_ini_file_data[g_ini_items].pKeyName,
|
||||
ilitek_ini_file_data[g_ini_items].pKeyValue);
|
||||
|
||||
g_ini_items++;
|
||||
}
|
||||
|
||||
out:
|
||||
ipio_kfree((void **)&ini_buf);
|
||||
ipio_kfree((void **)&tmpSectionName);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void init_ilitek_ini_data(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
g_ini_items = 0;
|
||||
|
||||
/* Initialise ini strcture */
|
||||
for (i = 0 ; i < PARSER_MAX_KEY_NUM; i++) {
|
||||
memset(ilitek_ini_file_data[i].pSectionName, 0, PARSER_MAX_KEY_NAME_LEN);
|
||||
memset(ilitek_ini_file_data[i].pKeyName, 0, PARSER_MAX_KEY_NAME_LEN);
|
||||
memset(ilitek_ini_file_data[i].pKeyValue, 0, PARSER_MAX_KEY_VALUE_LEN);
|
||||
ilitek_ini_file_data[i].iSectionNameLen = 0;
|
||||
ilitek_ini_file_data[i].iKeyNameLen = 0;
|
||||
ilitek_ini_file_data[i].iKeyValueLen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* get_ini_key_value - get ini's key and value based on its section from its array
|
||||
*
|
||||
* A function is digging into the key and value by its section from the ini array.
|
||||
* The comparsion is not only a string's name, but its length.
|
||||
*/
|
||||
static int get_ini_key_value(char *section, char *key, char *value)
|
||||
{
|
||||
int i = 0;
|
||||
int ret = ERROR;
|
||||
int len = 0;
|
||||
|
||||
len = strlen(key);
|
||||
|
||||
for (i = 0 ; i < g_ini_items; i++) {
|
||||
|
||||
if (strcmp(section, ilitek_ini_file_data[i].pSectionName) != 0)
|
||||
continue;
|
||||
if (strcmp(key, ilitek_ini_file_data[i].pKeyName) == 0) {
|
||||
memcpy(value, ilitek_ini_file_data[i].pKeyValue, ilitek_ini_file_data[i].iKeyValueLen);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void core_parser_nodetype(int32_t *type_ptr, char *desp)
|
||||
{
|
||||
|
||||
int i = 0, j = 0, index1 = 0, temp, count = 0;
|
||||
char str[512] = { 0 }, record = ',';
|
||||
|
||||
for (i = 0 ; i < g_ini_items; i++) {
|
||||
|
||||
if ((strnstr(ilitek_ini_file_data[i].pSectionName, desp, strlen(ilitek_ini_file_data[i].pSectionName)) <= 0) ||
|
||||
strcmp(ilitek_ini_file_data[i].pKeyName, NODE_TYPE_KEY_NAME) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
record = ',';
|
||||
for (j = 0, index1 = 0 ; j <= ilitek_ini_file_data[i].iKeyValueLen ; j++) {
|
||||
|
||||
if (ilitek_ini_file_data[i].pKeyValue[j] == ';' || j == ilitek_ini_file_data[i].iKeyValueLen) {
|
||||
|
||||
if (record != '.') {
|
||||
memset(str, 0, sizeof(str));
|
||||
memcpy(str, &ilitek_ini_file_data[i].pKeyValue[index1], (j - index1));
|
||||
temp = katoi(str);
|
||||
type_ptr[count] = temp;
|
||||
printk("%04d, ", temp);
|
||||
count++;
|
||||
}
|
||||
record = ilitek_ini_file_data[i].pKeyValue[j];
|
||||
index1 = j+1;
|
||||
|
||||
}
|
||||
}
|
||||
printk("\n");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void core_parser_benchmark(int32_t *max_ptr, int32_t *min_ptr, int8_t type, char *desp)
|
||||
{
|
||||
int i = 0, j = 0, index1 = 0, temp, count = 0;
|
||||
char str[512] = { 0 }, record = ',';
|
||||
int32_t data[4];
|
||||
|
||||
for (i = 0 ; i < g_ini_items; i++) {
|
||||
if ((strnstr(ilitek_ini_file_data[i].pSectionName, desp, strlen(ilitek_ini_file_data[i].pSectionName)) <= 0) ||
|
||||
strcmp(ilitek_ini_file_data[i].pKeyName, BENCHMARK_KEY_NAME) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
record = ',';
|
||||
for (j = 0, index1 = 0 ; j <= ilitek_ini_file_data[i].iKeyValueLen ; j++) {
|
||||
if (ilitek_ini_file_data[i].pKeyValue[j] == ',' || ilitek_ini_file_data[i].pKeyValue[j] == ';' ||
|
||||
ilitek_ini_file_data[i].pKeyValue[j] == '.' || j == ilitek_ini_file_data[i].iKeyValueLen) {
|
||||
|
||||
if (record != '.') {
|
||||
memset(str, 0, sizeof(str));
|
||||
memcpy(str, &ilitek_ini_file_data[i].pKeyValue[index1], (j - index1));
|
||||
temp = katoi(str);
|
||||
data[(count % 4)] = temp;
|
||||
if ((count % 4) == 3) {
|
||||
if (data[0] == 1) {
|
||||
if (type == VALUE) {
|
||||
max_ptr[count/4] = data[1] + data[2];
|
||||
min_ptr[count/4] = data[1] + data[3];
|
||||
} else {
|
||||
max_ptr[count/4] = data[1] + (data[1] * data[2]) / 100;
|
||||
min_ptr[count/4] = data[1] - (data[1] * data[3]) / 100;
|
||||
}
|
||||
} else {
|
||||
max_ptr[count/4] = INT_MAX;
|
||||
min_ptr[count/4] = INT_MIN;
|
||||
}
|
||||
}
|
||||
count++;
|
||||
}
|
||||
record = ilitek_ini_file_data[i].pKeyValue[j];
|
||||
index1 = j + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(core_parser_benchmark);
|
||||
|
||||
int core_parser_get_u8_array(char *key, uint8_t *buf)
|
||||
{
|
||||
char *s = key;
|
||||
char *pToken;
|
||||
int res, conut = 0;
|
||||
long s_to_long = 0;
|
||||
|
||||
if (isspace_t((int)(unsigned char)*s) == SUCCESS) {
|
||||
while ((pToken = strsep(&s, ",")) != NULL) {
|
||||
res = kstrtol(pToken, 0, &s_to_long);
|
||||
if (res == 0)
|
||||
buf[conut] = s_to_long;
|
||||
else
|
||||
ipio_info("convert string too long, res = %d\n", res);
|
||||
conut++;
|
||||
}
|
||||
}
|
||||
|
||||
return conut;
|
||||
}
|
||||
EXPORT_SYMBOL(core_parser_get_u8_array);
|
||||
|
||||
int core_parser_get_int_data(char *section, char *keyname, char *rv)
|
||||
{
|
||||
int len = 0;
|
||||
char value[512] = { 0 };
|
||||
|
||||
if (rv == NULL || section == NULL || keyname == NULL) {
|
||||
ipio_err("Parameters are invalid\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* return a white-space string if get nothing */
|
||||
if (get_ini_key_value(section, keyname, value) < 0) {
|
||||
snprintf(rv, sizeof(value), "%s", value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = snprintf(rv, sizeof(value), "%s", value);
|
||||
printk("section =%s,keyname =%s,value = %s,rv =%s\n", section, keyname, value, rv);//summer
|
||||
return len;
|
||||
}
|
||||
EXPORT_SYMBOL(core_parser_get_int_data);
|
||||
|
||||
|
||||
int core_parser_path(char *path)
|
||||
{
|
||||
int res = 0, fsize = 0;
|
||||
char *tmp = NULL;
|
||||
struct file *f = NULL;
|
||||
struct inode *inode;
|
||||
mm_segment_t old_fs;
|
||||
loff_t pos = 0;
|
||||
|
||||
ipio_info("path = %s\n", path);
|
||||
f = filp_open(path, O_RDONLY, 0);
|
||||
if (ERR_ALLOC_MEM(f)) {
|
||||
ipio_err("Failed to open the file at %ld.\n", PTR_ERR(f));
|
||||
res = -ENOENT;
|
||||
return res;
|
||||
}
|
||||
|
||||
#if KERNEL_VERSION(3, 18, 0) >= LINUX_VERSION_CODE
|
||||
inode = f->f_dentry->d_inode;
|
||||
#else
|
||||
inode = f->f_path.dentry->d_inode;
|
||||
#endif
|
||||
|
||||
fsize = inode->i_size;
|
||||
ipio_info("fsize = %d\n", fsize);
|
||||
if (fsize <= 0) {
|
||||
ipio_err("The size of file is invaild\n");
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
tmp = kmalloc(fsize+1, GFP_KERNEL);
|
||||
if (ERR_ALLOC_MEM(tmp)) {
|
||||
ipio_err("Failed to allocate tmp memory, %ld\n", PTR_ERR(tmp));
|
||||
res = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* ready to map user's memory to obtain data by reading files */
|
||||
old_fs = get_fs();
|
||||
set_fs(get_ds());
|
||||
vfs_read(f, tmp, fsize, &pos);
|
||||
set_fs(old_fs);
|
||||
tmp[fsize] = 0x00;
|
||||
|
||||
init_ilitek_ini_data();
|
||||
|
||||
res = get_ini_phy_data(tmp, fsize);
|
||||
if (res < 0) {
|
||||
ipio_err("Failed to get physical ini data, res = %d\n", res);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ipio_info("Parsing INI file doen\n");
|
||||
|
||||
out:
|
||||
ipio_kfree((void **)&tmp);
|
||||
filp_close(f, NULL);
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(core_parser_path);
|
||||
40
drivers/input/touchscreen/ilitek_mmi/core/parser.h
Normal file
40
drivers/input/touchscreen/ilitek_mmi/core/parser.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* ILITEK Touch IC driver
|
||||
*
|
||||
* Copyright (C) 2011 ILI Technology Corporation.
|
||||
*
|
||||
* Author: Dicky Chiang <dicky_chiang@ilitek.com>
|
||||
* Based on TDD v7.0 implemented by Mstar & ILITEK
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PARSER_H
|
||||
#define __PARSER_H
|
||||
#include "config.h"
|
||||
|
||||
#define BENCHMARK_KEY_NAME "Benchmark_Data"
|
||||
#define NODE_TYPE_KEY_NAME "node_type_Data"
|
||||
#define TYPE_MARK "[Driver Type Mark]"
|
||||
#define VALUE 0
|
||||
|
||||
extern void core_parser_nodetype(int32_t *type_ptr, char *desp);
|
||||
extern void core_parser_benchmark(int32_t *max_ptr, int32_t *min_ptr, int8_t type, char *desp);
|
||||
extern int core_parser_get_u8_array(char *key, uint8_t *buf);
|
||||
extern int core_parser_get_int_data(char *section, char *keyname, char *rv);
|
||||
extern int core_parser_path(char *path);
|
||||
|
||||
#endif
|
||||
414
drivers/input/touchscreen/ilitek_mmi/core/protocol.c
Normal file
414
drivers/input/touchscreen/ilitek_mmi/core/protocol.c
Normal file
|
|
@ -0,0 +1,414 @@
|
|||
/*
|
||||
* ILITEK Touch IC driver
|
||||
*
|
||||
* Copyright (C) 2011 ILI Technology Corporation.
|
||||
*
|
||||
* Author: Dicky Chiang <dicky_chiang@ilitek.com>
|
||||
* Based on TDD v7.0 implemented by Mstar & ILITEK
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#include "../common.h"
|
||||
#include "config.h"
|
||||
#include "i2c.h"
|
||||
#include "spi.h"
|
||||
#include "protocol.h"
|
||||
|
||||
#define FUNC_NUM 20
|
||||
|
||||
struct protocol_sup_list {
|
||||
uint8_t major;
|
||||
uint8_t mid;
|
||||
uint8_t minor;
|
||||
};
|
||||
|
||||
struct DataItem {
|
||||
int key;
|
||||
char *name;
|
||||
int len;
|
||||
uint8_t *cmd;
|
||||
};
|
||||
|
||||
struct DataItem *hashArray[FUNC_NUM];
|
||||
struct protocol_cmd_list *protocol;
|
||||
|
||||
int core_write(uint8_t nSlaveId, uint8_t *pBuf, uint16_t nSize)
|
||||
{
|
||||
#if (INTERFACE == I2C_INTERFACE)
|
||||
return core_i2c_write(nSlaveId, pBuf, nSize);
|
||||
#else
|
||||
return core_spi_write(pBuf, nSize);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(core_write);
|
||||
|
||||
int core_read(uint8_t nSlaveId, uint8_t *pBuf, uint16_t nSize)
|
||||
{
|
||||
#if (INTERFACE == I2C_INTERFACE)
|
||||
return core_i2c_read(nSlaveId, pBuf, nSize);
|
||||
#else
|
||||
return core_spi_read(pBuf, nSize);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(core_read);
|
||||
|
||||
static int hashCode(int key)
|
||||
{
|
||||
return key % FUNC_NUM;
|
||||
}
|
||||
|
||||
static struct DataItem *search_func(int key)
|
||||
{
|
||||
int hashIndex = hashCode(key);
|
||||
|
||||
while (hashArray[hashIndex] != NULL) {
|
||||
if (hashArray[hashIndex]->key == key)
|
||||
return hashArray[hashIndex];
|
||||
|
||||
hashIndex++;
|
||||
hashIndex %= FUNC_NUM;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void insert_func(int key, int len, uint8_t *cmd, char *name)
|
||||
{
|
||||
int i, hashIndex;
|
||||
struct DataItem *tmp = NULL;
|
||||
|
||||
tmp = kmalloc(sizeof(struct DataItem), GFP_KERNEL);
|
||||
if (ERR_ALLOC_MEM(tmp)) {
|
||||
ipio_err("Failed to allocate memory\n");
|
||||
return;
|
||||
}
|
||||
|
||||
tmp->key = key;
|
||||
tmp->name = name;
|
||||
tmp->len = len;
|
||||
|
||||
tmp->cmd = kcalloc(len, sizeof(uint8_t), GFP_KERNEL);
|
||||
for (i = 0 ; i < len ; i++)
|
||||
tmp->cmd[i] = cmd[i];
|
||||
|
||||
hashIndex = hashCode(key);
|
||||
|
||||
while (hashArray[hashIndex] != NULL) {
|
||||
hashIndex++;
|
||||
hashIndex %= FUNC_NUM;
|
||||
}
|
||||
|
||||
hashArray[hashIndex] = tmp;
|
||||
}
|
||||
|
||||
static void free_func_hash(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < FUNC_NUM; i++)
|
||||
ipio_kfree((void **)&hashArray[i]);
|
||||
}
|
||||
|
||||
static void create_func_hash(void)
|
||||
{
|
||||
/* if protocol is updated, we free its allocated mem at all before create new ones. */
|
||||
free_func_hash();
|
||||
|
||||
insert_func(0, protocol->func_ctrl_len, protocol->sense_ctrl, "sense_ctrl");
|
||||
insert_func(1, protocol->func_ctrl_len, protocol->sleep_ctrl, "sleep_ctrl");
|
||||
insert_func(2, protocol->func_ctrl_len, protocol->glove_ctrl, "glove_ctrl");
|
||||
insert_func(3, protocol->func_ctrl_len, protocol->stylus_ctrl, "stylus_ctrl");
|
||||
insert_func(4, protocol->func_ctrl_len, protocol->tp_scan_mode, "tp_scan_mode");
|
||||
insert_func(5, protocol->func_ctrl_len, protocol->lpwg_ctrl, "lpwg_ctrl");
|
||||
insert_func(6, protocol->func_ctrl_len, protocol->gesture_ctrl, "gesture_ctrl");
|
||||
insert_func(7, protocol->func_ctrl_len, protocol->phone_cover_ctrl, "phone_cover_ctrl");
|
||||
insert_func(8, protocol->func_ctrl_len, protocol->finger_sense_ctrl, "finger_sense_ctrl");
|
||||
insert_func(9, protocol->window_len, protocol->phone_cover_window, "phone_cover_window");
|
||||
insert_func(10, protocol->func_ctrl_len, protocol->finger_sense_ctrl, "finger_sense_ctrl");
|
||||
insert_func(11, protocol->func_ctrl_len, protocol->proximity_ctrl, "proximity_ctrl");
|
||||
insert_func(12, protocol->func_ctrl_len, protocol->plug_ctrl, "plug_ctrl");
|
||||
}
|
||||
|
||||
static void config_protocol_v5_cmd(void)
|
||||
{
|
||||
if (protocol->mid == 0x0) {
|
||||
protocol->func_ctrl_len = 2;
|
||||
|
||||
protocol->sense_ctrl[0] = 0x1;
|
||||
protocol->sense_ctrl[1] = 0x0;
|
||||
|
||||
protocol->sleep_ctrl[0] = 0x2;
|
||||
protocol->sleep_ctrl[1] = 0x0;
|
||||
|
||||
protocol->glove_ctrl[0] = 0x6;
|
||||
protocol->glove_ctrl[1] = 0x0;
|
||||
|
||||
protocol->stylus_ctrl[0] = 0x7;
|
||||
protocol->stylus_ctrl[1] = 0x0;
|
||||
|
||||
protocol->tp_scan_mode[0] = 0x8;
|
||||
protocol->tp_scan_mode[1] = 0x0;
|
||||
|
||||
protocol->lpwg_ctrl[0] = 0xA;
|
||||
protocol->lpwg_ctrl[1] = 0x0;
|
||||
|
||||
protocol->gesture_ctrl[0] = 0xB;
|
||||
protocol->gesture_ctrl[1] = 0x3F;
|
||||
|
||||
protocol->phone_cover_ctrl[0] = 0xC;
|
||||
protocol->phone_cover_ctrl[1] = 0x0;
|
||||
|
||||
protocol->finger_sense_ctrl[0] = 0xF;
|
||||
protocol->finger_sense_ctrl[1] = 0x0;
|
||||
|
||||
protocol->phone_cover_window[0] = 0xD;
|
||||
|
||||
/* Non support on v5.0 */
|
||||
/* protocol->proximity_ctrl[0] = 0x10; */
|
||||
/* protocol->proximity_ctrl[1] = 0x0; */
|
||||
|
||||
/* protocol->plug_ctrl[0] = 0x11; */
|
||||
/* protocol->plug_ctrl[1] = 0x0; */
|
||||
} else {
|
||||
protocol->func_ctrl_len = 3;
|
||||
|
||||
protocol->sense_ctrl[0] = 0x1;
|
||||
protocol->sense_ctrl[1] = 0x1;
|
||||
protocol->sense_ctrl[2] = 0x0;
|
||||
|
||||
protocol->sleep_ctrl[0] = 0x1;
|
||||
protocol->sleep_ctrl[1] = 0x2;
|
||||
protocol->sleep_ctrl[2] = 0x0;
|
||||
|
||||
protocol->glove_ctrl[0] = 0x1;
|
||||
protocol->glove_ctrl[1] = 0x6;
|
||||
protocol->glove_ctrl[2] = 0x0;
|
||||
|
||||
protocol->stylus_ctrl[0] = 0x1;
|
||||
protocol->stylus_ctrl[1] = 0x7;
|
||||
protocol->stylus_ctrl[2] = 0x0;
|
||||
|
||||
protocol->tp_scan_mode[0] = 0x1;
|
||||
protocol->tp_scan_mode[1] = 0x8;
|
||||
protocol->tp_scan_mode[2] = 0x0;
|
||||
|
||||
protocol->lpwg_ctrl[0] = 0x1;
|
||||
protocol->lpwg_ctrl[1] = 0xA;
|
||||
protocol->lpwg_ctrl[2] = 0x0;
|
||||
|
||||
protocol->gesture_ctrl[0] = 0x1;
|
||||
protocol->gesture_ctrl[1] = 0xB;
|
||||
protocol->gesture_ctrl[2] = 0x3F;
|
||||
|
||||
protocol->phone_cover_ctrl[0] = 0x1;
|
||||
protocol->phone_cover_ctrl[1] = 0xC;
|
||||
protocol->phone_cover_ctrl[2] = 0x0;
|
||||
|
||||
protocol->finger_sense_ctrl[0] = 0x1;
|
||||
protocol->finger_sense_ctrl[1] = 0xF;
|
||||
protocol->finger_sense_ctrl[2] = 0x0;
|
||||
|
||||
protocol->proximity_ctrl[0] = 0x1;
|
||||
protocol->proximity_ctrl[1] = 0x10;
|
||||
protocol->proximity_ctrl[2] = 0x0;
|
||||
|
||||
protocol->plug_ctrl[0] = 0x1;
|
||||
protocol->plug_ctrl[1] = 0x11;
|
||||
protocol->plug_ctrl[2] = 0x0;
|
||||
|
||||
protocol->phone_cover_window[0] = 0xE;
|
||||
}
|
||||
if (protocol->mid >= 0x3)
|
||||
protocol->fw_ver_len = 9;
|
||||
else
|
||||
protocol->fw_ver_len = 4;
|
||||
|
||||
if (protocol->mid == 0x1) {
|
||||
protocol->pro_ver_len = 3;
|
||||
} else {
|
||||
protocol->pro_ver_len = 4;
|
||||
}
|
||||
|
||||
protocol->tp_info_len = 14;
|
||||
protocol->key_info_len = 30;
|
||||
protocol->core_ver_len = 5;
|
||||
protocol->window_len = 8;
|
||||
|
||||
/* The commadns about panel information */
|
||||
protocol->cmd_read_ctrl = P5_0_READ_DATA_CTRL;
|
||||
protocol->cmd_get_tp_info = P5_0_GET_TP_INFORMATION;
|
||||
protocol->cmd_get_key_info = P5_0_GET_KEY_INFORMATION;
|
||||
protocol->cmd_get_fw_ver = P5_0_GET_FIRMWARE_VERSION;
|
||||
protocol->cmd_get_pro_ver = P5_0_GET_PROTOCOL_VERSION;
|
||||
protocol->cmd_get_core_ver = P5_0_GET_CORE_VERSION;
|
||||
protocol->cmd_mode_ctrl = P5_0_MODE_CONTROL;
|
||||
protocol->cmd_cdc_busy = P5_0_CDC_BUSY_STATE;
|
||||
protocol->cmd_i2cuart = P5_0_I2C_UART;
|
||||
|
||||
/* The commands about the packets of finger report from FW */
|
||||
protocol->unknown_mode = P5_0_FIRMWARE_UNKNOWN_MODE;
|
||||
protocol->demo_mode = P5_0_FIRMWARE_DEMO_MODE;
|
||||
protocol->debug_mode = P5_0_FIRMWARE_DEBUG_MODE;
|
||||
protocol->test_mode = P5_0_FIRMWARE_TEST_MODE;
|
||||
protocol->i2cuart_mode = P5_0_FIRMWARE_I2CUART_MODE;
|
||||
protocol->gesture_mode = P5_0_FIRMWARE_GESTURE_MODE;
|
||||
|
||||
protocol->demo_pid = P5_0_DEMO_PACKET_ID;
|
||||
protocol->debug_pid = P5_0_DEBUG_PACKET_ID;
|
||||
protocol->test_pid = P5_0_TEST_PACKET_ID;
|
||||
protocol->i2cuart_pid = P5_0_I2CUART_PACKET_ID;
|
||||
protocol->ges_pid = P5_0_GESTURE_PACKET_ID;
|
||||
|
||||
protocol->demo_len = P5_0_DEMO_MODE_PACKET_LENGTH;
|
||||
protocol->debug_len = P5_0_DEBUG_MODE_PACKET_LENGTH;
|
||||
protocol->test_len = P5_0_TEST_MODE_PACKET_LENGTH;
|
||||
|
||||
/* The commands about MP test */
|
||||
protocol->cmd_cdc = P5_0_SET_CDC_INIT;
|
||||
protocol->cmd_get_cdc = P5_0_GET_CDC_DATA;
|
||||
|
||||
if (protocol->mid < 4) {
|
||||
protocol->cdc_len = 3;
|
||||
} else {
|
||||
protocol->cdc_len = 15;
|
||||
}
|
||||
|
||||
protocol->mutual_dac = 0x1;
|
||||
protocol->mutual_bg = 0x2;
|
||||
protocol->mutual_signal = 0x3;
|
||||
protocol->mutual_no_bk = 0x5;
|
||||
protocol->mutual_has_bk = 0x8;
|
||||
protocol->mutual_bk_dac = 0x10;
|
||||
|
||||
protocol->self_dac = 0xC;
|
||||
protocol->self_bg = 0xF;
|
||||
protocol->self_signal = 0xD;
|
||||
protocol->self_no_bk = 0xE;
|
||||
protocol->self_has_bk = 0xB;
|
||||
protocol->self_bk_dac = 0x11;
|
||||
|
||||
protocol->key_dac = 0x14;
|
||||
protocol->key_bg = 0x16;
|
||||
protocol->key_no_bk = 0x7;
|
||||
protocol->key_has_bk = 0x15;
|
||||
protocol->key_open = 0x12;
|
||||
protocol->key_short = 0x13;
|
||||
|
||||
protocol->st_dac = 0x1A;
|
||||
protocol->st_bg = 0x1C;
|
||||
protocol->st_no_bk = 0x17;
|
||||
protocol->st_has_bk = 0x1B;
|
||||
protocol->st_open = 0x18;
|
||||
|
||||
protocol->tx_short = 0x19;
|
||||
|
||||
protocol->rx_short = 0x4;
|
||||
protocol->rx_open = 0x6;
|
||||
|
||||
protocol->tx_rx_delta = 0x1E;
|
||||
|
||||
protocol->cm_data = 0x9;
|
||||
protocol->cs_data = 0xA;
|
||||
|
||||
protocol->trcrq_pin = 0x20;
|
||||
protocol->resx2_pin = 0x21;
|
||||
protocol->mutual_integra_time = 0x22;
|
||||
protocol->self_integra_time = 0x23;
|
||||
protocol->key_integra_time = 0x24;
|
||||
protocol->st_integra_time = 0x25;
|
||||
protocol->peak_to_peak = 0x1D;
|
||||
|
||||
protocol->get_timing = 0x30;
|
||||
protocol->doze_p2p = 0x32;
|
||||
protocol->doze_raw = 0x33;
|
||||
}
|
||||
|
||||
void core_protocol_func_control(int key, int ctrl)
|
||||
{
|
||||
struct DataItem *tmp = search_func(key);
|
||||
|
||||
if (tmp != NULL) {
|
||||
ipio_info("Found func's name: %s, key = %d\n", tmp->name, key);
|
||||
|
||||
/* last element is used to control this func */
|
||||
if (tmp->key != 9)
|
||||
tmp->cmd[tmp->len - 1] = ctrl;
|
||||
|
||||
core_write(core_config->slave_i2c_addr, tmp->cmd, tmp->len);
|
||||
return;
|
||||
}
|
||||
|
||||
ipio_info("Can't find any main functions\n");
|
||||
}
|
||||
EXPORT_SYMBOL(core_protocol_func_control);
|
||||
|
||||
int core_protocol_update_ver(uint8_t major, uint8_t mid, uint8_t minor)
|
||||
{
|
||||
int i = 0;
|
||||
struct protocol_sup_list pver[] = {
|
||||
{0x5, 0x0, 0x0},
|
||||
{0x5, 0x1, 0x0},
|
||||
{0x5, 0x2, 0x0},
|
||||
{0x5, 0x3, 0x0},
|
||||
{0x5, 0x4, 0x0},
|
||||
};
|
||||
|
||||
for (i = 0 ; i < ARRAY_SIZE(pver); i++) {
|
||||
if (pver[i].major == major && pver[i].mid == mid && pver[i].minor == minor) {
|
||||
protocol->major = major;
|
||||
protocol->mid = mid;
|
||||
protocol->minor = minor;
|
||||
ipio_info("protocol: major = %d, mid = %d, minor = %d\n",
|
||||
protocol->major, protocol->mid, protocol->minor);
|
||||
|
||||
if (protocol->major == 0x5)
|
||||
config_protocol_v5_cmd();
|
||||
|
||||
/* We need to recreate function controls because of the commands updated. */
|
||||
create_func_hash();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ipio_err("Doesn't support this version of protocol\n");
|
||||
return ERROR;
|
||||
}
|
||||
EXPORT_SYMBOL(core_protocol_update_ver);
|
||||
|
||||
int core_protocol_init(void)
|
||||
{
|
||||
if (protocol == NULL) {
|
||||
protocol = kzalloc(sizeof(*protocol), GFP_KERNEL);
|
||||
if (ERR_ALLOC_MEM(protocol)) {
|
||||
ipio_err("Failed to allocate protocol mem, %ld\n", PTR_ERR(protocol));
|
||||
core_protocol_remove();
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
/* The default version must only once be set up at this initial time. */
|
||||
core_protocol_update_ver(PROTOCOL_MAJOR, PROTOCOL_MID, PROTOCOL_MINOR);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(core_protocol_init);
|
||||
|
||||
void core_protocol_remove(void)
|
||||
{
|
||||
ipio_info("Remove core-protocol memebers\n");
|
||||
ipio_kfree((void **)&protocol);
|
||||
free_func_hash();
|
||||
}
|
||||
EXPORT_SYMBOL(core_protocol_remove);
|
||||
189
drivers/input/touchscreen/ilitek_mmi/core/protocol.h
Normal file
189
drivers/input/touchscreen/ilitek_mmi/core/protocol.h
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* ILITEK Touch IC driver
|
||||
*
|
||||
* Copyright (C) 2011 ILI Technology Corporation.
|
||||
*
|
||||
* Author: Dicky Chiang <dicky_chiang@ilitek.com>
|
||||
* Based on TDD v7.0 implemented by Mstar & ILITEK
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#ifndef __PROTOCOL_H
|
||||
#define __PROTOCOL_H
|
||||
|
||||
/* V3.2 */
|
||||
#define P3_2_GET_TP_INFORMATION 0x20
|
||||
#define P3_2_GET_KEY_INFORMATION 0x22
|
||||
#define P3_2_GET_FIRMWARE_VERSION 0x40
|
||||
#define P3_2_GET_PROTOCOL_VERSION 0x42
|
||||
|
||||
/* V5.X */
|
||||
#define P5_0_READ_DATA_CTRL 0xF6
|
||||
#define P5_0_GET_TP_INFORMATION 0x20
|
||||
#define P5_0_GET_KEY_INFORMATION 0x27
|
||||
#define P5_0_GET_FIRMWARE_VERSION 0x21
|
||||
#define P5_0_GET_PROTOCOL_VERSION 0x22
|
||||
#define P5_0_GET_CORE_VERSION 0x23
|
||||
#define P5_0_MODE_CONTROL 0xF0
|
||||
#define P5_0_SET_CDC_INIT 0xF1
|
||||
#define P5_0_GET_CDC_DATA 0xF2
|
||||
#define P5_0_CDC_BUSY_STATE 0xF3
|
||||
#define P5_0_I2C_UART 0x40
|
||||
|
||||
#define P5_0_FIRMWARE_UNKNOWN_MODE 0xFF
|
||||
#define P5_0_FIRMWARE_DEMO_MODE 0x00
|
||||
#define P5_0_FIRMWARE_TEST_MODE 0x01
|
||||
#define P5_0_FIRMWARE_DEBUG_MODE 0x02
|
||||
#define P5_0_FIRMWARE_I2CUART_MODE 0x03
|
||||
#define P5_0_FIRMWARE_GESTURE_MODE 0x04
|
||||
|
||||
#define P5_0_DEMO_PACKET_ID 0x5A
|
||||
#define P5_0_DEBUG_PACKET_ID 0xA7
|
||||
#define P5_0_TEST_PACKET_ID 0xF2
|
||||
#define P5_0_GESTURE_PACKET_ID 0xAA
|
||||
#define P5_0_I2CUART_PACKET_ID 0x7A
|
||||
|
||||
#define P5_0_DEMO_MODE_PACKET_LENGTH 43
|
||||
#define P5_0_DEBUG_MODE_PACKET_LENGTH 1280
|
||||
#define P5_0_TEST_MODE_PACKET_LENGTH 1180
|
||||
|
||||
struct protocol_cmd_list {
|
||||
/* version of protocol */
|
||||
uint8_t major;
|
||||
uint8_t mid;
|
||||
uint8_t minor;
|
||||
|
||||
/* Length of command */
|
||||
int fw_ver_len;
|
||||
int pro_ver_len;
|
||||
int tp_info_len;
|
||||
int key_info_len;
|
||||
int core_ver_len;
|
||||
int func_ctrl_len;
|
||||
int window_len;
|
||||
int cdc_len;
|
||||
int cdc_raw_len;
|
||||
|
||||
/* TP information */
|
||||
uint8_t cmd_read_ctrl;
|
||||
uint8_t cmd_get_tp_info;
|
||||
uint8_t cmd_get_key_info;
|
||||
uint8_t cmd_get_fw_ver;
|
||||
uint8_t cmd_get_pro_ver;
|
||||
uint8_t cmd_get_core_ver;
|
||||
uint8_t cmd_mode_ctrl;
|
||||
uint8_t cmd_i2cuart;
|
||||
uint8_t cmd_cdc_busy;
|
||||
|
||||
/* Function control */
|
||||
uint8_t sense_ctrl[3];
|
||||
uint8_t sleep_ctrl[3];
|
||||
uint8_t glove_ctrl[3];
|
||||
uint8_t stylus_ctrl[3];
|
||||
uint8_t tp_scan_mode[3];
|
||||
uint8_t lpwg_ctrl[3];
|
||||
uint8_t gesture_ctrl[3];
|
||||
uint8_t phone_cover_ctrl[3];
|
||||
uint8_t finger_sense_ctrl[3];
|
||||
uint8_t proximity_ctrl[3];
|
||||
uint8_t plug_ctrl[3];
|
||||
uint8_t phone_cover_window[9];
|
||||
|
||||
/* firmware mode */
|
||||
uint8_t unknown_mode;
|
||||
uint8_t demo_mode;
|
||||
uint8_t debug_mode;
|
||||
uint8_t test_mode;
|
||||
uint8_t i2cuart_mode;
|
||||
uint8_t gesture_mode;
|
||||
|
||||
/* Pakcet ID reported by FW */
|
||||
uint8_t demo_pid;
|
||||
uint8_t debug_pid;
|
||||
uint8_t i2cuart_pid;
|
||||
uint8_t test_pid;
|
||||
uint8_t ges_pid;
|
||||
|
||||
/* Length of finger report */
|
||||
int demo_len;
|
||||
int debug_len;
|
||||
int test_len;
|
||||
int gesture_len;
|
||||
|
||||
/* MP Test with cdc commands */
|
||||
uint8_t cmd_cdc;
|
||||
uint8_t cmd_get_cdc;
|
||||
|
||||
uint8_t cm_data;
|
||||
uint8_t cs_data;
|
||||
|
||||
uint8_t rx_short;
|
||||
uint8_t rx_open;
|
||||
uint8_t tx_short;
|
||||
|
||||
uint8_t mutual_dac;
|
||||
uint8_t mutual_bg;
|
||||
uint8_t mutual_signal;
|
||||
uint8_t mutual_no_bk;
|
||||
uint8_t mutual_bk_dac;
|
||||
uint8_t mutual_has_bk;
|
||||
uint16_t mutual_has_bk_16;
|
||||
|
||||
uint8_t self_dac;
|
||||
uint8_t self_bk_dac;
|
||||
uint8_t self_has_bk;
|
||||
uint8_t self_no_bk;
|
||||
uint8_t self_signal;
|
||||
uint8_t self_bg;
|
||||
|
||||
uint8_t key_dac;
|
||||
uint8_t key_has_bk;
|
||||
uint8_t key_bg;
|
||||
uint8_t key_no_bk;
|
||||
uint8_t key_open;
|
||||
uint8_t key_short;
|
||||
|
||||
uint8_t st_no_bk;
|
||||
uint8_t st_open;
|
||||
uint8_t st_dac;
|
||||
uint8_t st_has_bk;
|
||||
uint8_t st_bg;
|
||||
|
||||
uint8_t tx_rx_delta;
|
||||
|
||||
uint8_t trcrq_pin;
|
||||
uint8_t resx2_pin;
|
||||
uint8_t mutual_integra_time;
|
||||
uint8_t self_integra_time;
|
||||
uint8_t key_integra_time;
|
||||
uint8_t st_integra_time;
|
||||
uint8_t peak_to_peak;
|
||||
|
||||
uint8_t get_timing;
|
||||
uint8_t doze_p2p;
|
||||
uint8_t doze_raw;
|
||||
};
|
||||
|
||||
extern struct protocol_cmd_list *protocol;
|
||||
|
||||
extern void core_protocol_func_control(int key, int ctrl);
|
||||
extern int core_protocol_update_ver(uint8_t major, uint8_t mid, uint8_t minor);
|
||||
extern int core_protocol_init(void);
|
||||
extern void core_protocol_remove(void);
|
||||
extern int core_write(uint8_t, uint8_t *, uint16_t);
|
||||
extern int core_read(uint8_t, uint8_t *, uint16_t);
|
||||
|
||||
#endif
|
||||
412
drivers/input/touchscreen/ilitek_mmi/core/spi.c
Normal file
412
drivers/input/touchscreen/ilitek_mmi/core/spi.c
Normal file
|
|
@ -0,0 +1,412 @@
|
|||
/*
|
||||
* ILITEK Touch IC driver
|
||||
*
|
||||
* Copyright (C) 2011 ILI Technology Corporation.
|
||||
*
|
||||
* Author: Dicky Chiang <dicky_chiang@ilitek.com>
|
||||
* Based on TDD v7.0 implemented by Mstar & ILITEK
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../common.h"
|
||||
#include "config.h"
|
||||
#include "spi.h"
|
||||
#include "finger_report.h"
|
||||
|
||||
struct core_spi_data *core_spi;
|
||||
|
||||
int core_Rx_check(uint16_t check)
|
||||
{
|
||||
int size = 0, i, count = 100;
|
||||
uint8_t txbuf[5] = { 0 }, rxbuf[4] = {0};
|
||||
uint16_t status = 0;
|
||||
|
||||
txbuf[0] = SPI_WRITE;
|
||||
txbuf[1] = 0x25;
|
||||
txbuf[2] = 0x94;
|
||||
txbuf[3] = 0x0;
|
||||
txbuf[4] = 0x2;
|
||||
|
||||
for (i = 0 ; i < count; i++) {
|
||||
|
||||
txbuf[0] = SPI_WRITE;
|
||||
if (spi_write_then_read(core_spi->spi, txbuf, 5, txbuf, 0) < 0) {
|
||||
size = -EIO;
|
||||
ipio_err("spi Write Error, res = %d\n", size);
|
||||
}
|
||||
|
||||
txbuf[0] = SPI_READ;
|
||||
if (spi_write_then_read(core_spi->spi, txbuf, 1, rxbuf, 4) < 0) {
|
||||
size = -EIO;
|
||||
ipio_err("spi Read Error, res = %d\n", size);
|
||||
}
|
||||
|
||||
status = (rxbuf[2] << 8) + rxbuf[3];
|
||||
size = (rxbuf[0] << 8) + rxbuf[1];
|
||||
|
||||
if (status == check)
|
||||
return size;
|
||||
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
size = -EIO;
|
||||
ipio_err("Check lock error\n");
|
||||
return size;
|
||||
}
|
||||
|
||||
int core_Tx_unlock_check(void)
|
||||
{
|
||||
int res = 0, i, count = 100;
|
||||
uint8_t txbuf[5] = { 0 }, rxbuf[4] = {0};
|
||||
uint16_t unlock = 0;
|
||||
|
||||
txbuf[0] = SPI_WRITE;
|
||||
txbuf[1] = 0x25;
|
||||
txbuf[2] = 0x0;
|
||||
txbuf[3] = 0x0;
|
||||
txbuf[4] = 0x2;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
txbuf[0] = SPI_WRITE;
|
||||
if (spi_write_then_read(core_spi->spi, txbuf, 5, txbuf, 0) < 0) {
|
||||
res = -EIO;
|
||||
ipio_err("spi Write Error, res = %d\n", res);
|
||||
}
|
||||
|
||||
txbuf[0] = SPI_READ;
|
||||
if (spi_write_then_read(core_spi->spi, txbuf, 1, rxbuf, 4) < 0) {
|
||||
res = -EIO;
|
||||
ipio_err("spi Read Error, res = %d\n", res);
|
||||
}
|
||||
|
||||
unlock = (rxbuf[2] << 8) + rxbuf[3];
|
||||
|
||||
if (unlock == 0x9881)
|
||||
return res;
|
||||
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
ipio_err("Check unlock error\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
int core_ice_mode_read_9881H11(uint8_t *data, uint32_t size)
|
||||
{
|
||||
int res = 0;
|
||||
uint8_t txbuf[64] = { 0 };
|
||||
|
||||
/* set read address */
|
||||
txbuf[0] = SPI_WRITE;
|
||||
txbuf[1] = 0x25;
|
||||
txbuf[2] = 0x98;
|
||||
txbuf[3] = 0x0;
|
||||
txbuf[4] = 0x2;
|
||||
if (spi_write_then_read(core_spi->spi, txbuf, 5, txbuf, 0) < 0) {
|
||||
res = -EIO;
|
||||
return res;
|
||||
}
|
||||
|
||||
/* read data */
|
||||
txbuf[0] = SPI_READ;
|
||||
if (spi_write_then_read(core_spi->spi, txbuf, 1, data, size) < 0) {
|
||||
res = -EIO;
|
||||
return res;
|
||||
}
|
||||
|
||||
/* write data unlock */
|
||||
txbuf[0] = SPI_WRITE;
|
||||
txbuf[1] = 0x25;
|
||||
txbuf[2] = 0x94;
|
||||
txbuf[3] = 0x0;
|
||||
txbuf[4] = 0x2;
|
||||
txbuf[5] = (size & 0xFF00) >> 8;
|
||||
txbuf[6] = size & 0xFF;
|
||||
txbuf[7] = (char)0x98;
|
||||
txbuf[8] = (char)0x81;
|
||||
if (spi_write_then_read(core_spi->spi, txbuf, 9, txbuf, 0) < 0) {
|
||||
res = -EIO;
|
||||
ipio_err("spi Write data unlock error, res = %d\n", res);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int core_ice_mode_write_9881H11(uint8_t *data, uint32_t size)
|
||||
{
|
||||
int res = 0;
|
||||
uint8_t check_sum = 0, wsize = 0;
|
||||
uint8_t *txbuf = NULL;
|
||||
|
||||
txbuf = kcalloc(size + 9, sizeof(uint8_t), GFP_KERNEL);
|
||||
if (ERR_ALLOC_MEM(txbuf)) {
|
||||
ipio_err("Failed to allocate txbuf\n");
|
||||
res = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Write data */
|
||||
txbuf[0] = SPI_WRITE;
|
||||
txbuf[1] = 0x25;
|
||||
txbuf[2] = 0x4;
|
||||
txbuf[3] = 0x0;
|
||||
txbuf[4] = 0x2;
|
||||
|
||||
/* Calcuate checsum and fill it in the last byte */
|
||||
check_sum = core_fr_calc_checksum(data, size);
|
||||
memcpy(txbuf + 5, data, size);
|
||||
txbuf[5 + size] = check_sum;
|
||||
size++;
|
||||
wsize = size;
|
||||
if (wsize % 4 != 0)
|
||||
wsize += 4 - (wsize % 4);
|
||||
|
||||
if (spi_write_then_read(core_spi->spi, txbuf, wsize + 5, txbuf, 0) < 0) {
|
||||
res = -EIO;
|
||||
ipio_err("spi Write Error, res = %d\n", res);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* write data lock */
|
||||
txbuf[0] = SPI_WRITE;
|
||||
txbuf[1] = 0x25;
|
||||
txbuf[2] = 0x0;
|
||||
txbuf[3] = 0x0;
|
||||
txbuf[4] = 0x2;
|
||||
txbuf[5] = (size & 0xFF00) >> 8;
|
||||
txbuf[6] = size & 0xFF;
|
||||
txbuf[7] = (char)0x5A;
|
||||
txbuf[8] = (char)0xA5;
|
||||
if (spi_write_then_read(core_spi->spi, txbuf, 9, txbuf, 0) < 0) {
|
||||
res = -EIO;
|
||||
ipio_err("spi Write data lock Error, res = %d\n", res);
|
||||
}
|
||||
|
||||
out:
|
||||
ipio_kfree((void **)&txbuf);
|
||||
return res;
|
||||
}
|
||||
|
||||
int core_ice_mode_disable_9881H11(void)
|
||||
{
|
||||
int res = 0;
|
||||
uint8_t txbuf[5] = {0};
|
||||
|
||||
txbuf[0] = 0x82;
|
||||
txbuf[1] = 0x1B;
|
||||
txbuf[2] = 0x62;
|
||||
txbuf[3] = 0x10;
|
||||
txbuf[4] = 0x18;
|
||||
|
||||
if (spi_write_then_read(core_spi->spi, txbuf, 5, txbuf, 0) < 0) {
|
||||
res = -EIO;
|
||||
ipio_err("spi_write_then_read Error, res = %d\n", res);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int core_ice_mode_enable_9881H11(void)
|
||||
{
|
||||
int res = 0;
|
||||
uint8_t txbuf[5] = {0}, rxbuf[2] = {0};
|
||||
|
||||
txbuf[0] = 0x82;
|
||||
txbuf[1] = 0x1F;
|
||||
txbuf[2] = 0x62;
|
||||
txbuf[3] = 0x10;
|
||||
txbuf[4] = 0x18;
|
||||
|
||||
if (spi_write_then_read(core_spi->spi, txbuf, 1, rxbuf, 1) < 0) {
|
||||
res = -EIO;
|
||||
ipio_err("spi Write Error, res = %d\n", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* check recover data */
|
||||
if (rxbuf[0] == 0x82) {
|
||||
ipio_info("rxbuf:0x%x\n", rxbuf[0]);
|
||||
return CHECK_RECOVER;
|
||||
}
|
||||
|
||||
if (spi_write_then_read(core_spi->spi, txbuf, 5, rxbuf, 0) < 0) {
|
||||
res = -EIO;
|
||||
ipio_err("spi Write Error, res = %d\n", res);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int core_spi_read_9881H11(uint8_t *pBuf, uint16_t nSize)
|
||||
{
|
||||
int res = 0, size = 0;
|
||||
|
||||
res = core_ice_mode_enable_9881H11();
|
||||
if (res < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
size = core_Rx_check(0x5AA5);
|
||||
if (size < 0) {
|
||||
res = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (core_ice_mode_read_9881H11(pBuf, size) < 0) {
|
||||
res = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (core_ice_mode_disable_9881H11() < 0) {
|
||||
res = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
|
||||
int core_spi_write_9881H11(uint8_t *pBuf, uint16_t nSize)
|
||||
{
|
||||
int res = 0;
|
||||
uint8_t *txbuf = NULL;
|
||||
|
||||
txbuf = kcalloc(nSize + 5, sizeof(uint8_t), GFP_KERNEL);
|
||||
if (ERR_ALLOC_MEM(txbuf)) {
|
||||
ipio_err("Failed to allocate txbuf\n");
|
||||
return -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
res = core_ice_mode_enable_9881H11();
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
if (core_ice_mode_write_9881H11(pBuf, nSize) < 0) {
|
||||
res = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (core_Tx_unlock_check() < 0) {
|
||||
res = -ETXTBSY;
|
||||
}
|
||||
|
||||
out:
|
||||
ipio_kfree((void **)&txbuf);
|
||||
return res;
|
||||
}
|
||||
|
||||
int core_spi_write(uint8_t *pBuf, uint16_t nSize)
|
||||
{
|
||||
int res = 0;
|
||||
uint8_t *txbuf = NULL;
|
||||
|
||||
txbuf = kcalloc(nSize + 1, sizeof(uint8_t), GFP_KERNEL);
|
||||
if (ERR_ALLOC_MEM(txbuf)) {
|
||||
ipio_err("Failed to allocate txbuf\n");
|
||||
return -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (core_config->icemodeenable == false) {
|
||||
res = core_spi_write_9881H11(pBuf, nSize);
|
||||
core_ice_mode_disable_9881H11();
|
||||
ipio_kfree((void **)&txbuf);
|
||||
return res;
|
||||
}
|
||||
|
||||
txbuf[0] = SPI_WRITE;
|
||||
memcpy(txbuf+1, pBuf, nSize);
|
||||
|
||||
if (spi_write_then_read(core_spi->spi, txbuf, nSize+1, txbuf, 0) < 0) {
|
||||
if (core_config->do_ic_reset) {
|
||||
/* ignore spi error if doing ic reset */
|
||||
res = 0;
|
||||
} else {
|
||||
res = -EIO;
|
||||
ipio_err("spi Write Error, res = %d\n", res);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
ipio_kfree((void **)&txbuf);
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(core_spi_write);
|
||||
|
||||
int core_spi_read(uint8_t *pBuf, uint16_t nSize)
|
||||
{
|
||||
int res = 0;
|
||||
uint8_t txbuf[1] = {0};
|
||||
|
||||
txbuf[0] = SPI_READ;
|
||||
|
||||
if (core_config->icemodeenable == false)
|
||||
return core_spi_read_9881H11(pBuf, nSize);
|
||||
|
||||
if (spi_write_then_read(core_spi->spi, txbuf, 1, pBuf, nSize) < 0) {
|
||||
if (core_config->do_ic_reset) {
|
||||
/* ignore spi error if doing ic reset */
|
||||
res = 0;
|
||||
} else {
|
||||
res = -EIO;
|
||||
ipio_err("spi Read Error, res = %d\n", res);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(core_spi_read);
|
||||
|
||||
int core_spi_init(struct spi_device *spi)
|
||||
{
|
||||
int ret;
|
||||
|
||||
core_spi = kmalloc(sizeof(*core_spi), GFP_KERNEL);
|
||||
if (ERR_ALLOC_MEM(core_spi)) {
|
||||
ipio_err("Failed to alllocate core_i2c mem %ld\n", PTR_ERR(core_spi));
|
||||
core_spi_remove();
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
core_spi->spi = spi;
|
||||
spi->mode = SPI_MODE_0;
|
||||
spi->bits_per_word = 8;
|
||||
|
||||
ret = spi_setup(spi);
|
||||
if (ret < 0) {
|
||||
ipio_err("ERR: fail to setup spi\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ipio_info("name = %s, bus_num = %d,cs = %d, mode = %d, speed = %d\n", spi->modalias,
|
||||
spi->master->bus_num, spi->chip_select, spi->mode, spi->max_speed_hz);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(core_spi_init);
|
||||
|
||||
void core_spi_remove(void)
|
||||
{
|
||||
ipio_info("Remove core-spi members\n");
|
||||
ipio_kfree((void **)&core_spi);
|
||||
}
|
||||
EXPORT_SYMBOL(core_spi_remove);
|
||||
42
drivers/input/touchscreen/ilitek_mmi/core/spi.h
Normal file
42
drivers/input/touchscreen/ilitek_mmi/core/spi.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* ILITEK Touch IC driver
|
||||
*
|
||||
* Copyright (C) 2011 ILI Technology Corporation.
|
||||
*
|
||||
* Author: Dicky Chiang <dicky_chiang@ilitek.com>
|
||||
* Based on TDD v7.0 implemented by Mstar & ILITEK
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SPI_H
|
||||
#define __SPI_H
|
||||
|
||||
#define SPI_WRITE 0X82
|
||||
#define SPI_READ 0X83
|
||||
|
||||
struct core_spi_data {
|
||||
struct spi_device *spi;
|
||||
};
|
||||
|
||||
extern struct core_spi_data *core_spi;
|
||||
|
||||
extern int core_spi_write(uint8_t *pBuf, uint16_t nSize);
|
||||
extern int core_spi_read(uint8_t *pBuf, uint16_t nSize);
|
||||
extern int core_spi_init(struct spi_device *spi);
|
||||
extern void core_spi_remove(void);
|
||||
|
||||
#endif
|
||||
1120
drivers/input/touchscreen/ilitek_mmi/platform.c
Normal file
1120
drivers/input/touchscreen/ilitek_mmi/platform.c
Normal file
File diff suppressed because it is too large
Load diff
128
drivers/input/touchscreen/ilitek_mmi/platform.h
Normal file
128
drivers/input/touchscreen/ilitek_mmi/platform.h
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* ILITEK Touch IC driver
|
||||
*
|
||||
* Copyright (C) 2011 ILI Technology Corporation.
|
||||
*
|
||||
* Author: Dicky Chiang <dicky_chiang@ilitek.com>
|
||||
* Based on TDD v7.0 implemented by Mstar & ILITEK
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PLATFORM_H
|
||||
#define __PLATFORM_H
|
||||
|
||||
struct ilitek_platform_data {
|
||||
|
||||
struct i2c_client *client;
|
||||
|
||||
struct input_dev *input_device;
|
||||
|
||||
const struct i2c_device_id *i2c_id;
|
||||
|
||||
struct regulator *vdd;
|
||||
struct regulator *vdd_i2c;
|
||||
|
||||
struct mutex plat_mutex;
|
||||
spinlock_t plat_spinlock;
|
||||
|
||||
uint32_t chip_id;
|
||||
|
||||
int int_gpio;
|
||||
int reset_gpio;
|
||||
int isr_gpio;
|
||||
|
||||
int delay_time_high;
|
||||
int delay_time_low;
|
||||
int edge_delay;
|
||||
|
||||
bool isEnableIRQ;
|
||||
bool isEnablePollCheckPower;
|
||||
|
||||
#ifdef USE_KTHREAD
|
||||
struct task_struct *irq_thread;
|
||||
bool irq_trigger;
|
||||
bool free_irq_thread;
|
||||
#else
|
||||
struct work_struct report_work_queue;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FB
|
||||
struct notifier_block notifier_fb;
|
||||
#else
|
||||
struct early_suspend early_suspend;
|
||||
#endif
|
||||
|
||||
#ifdef BOOT_FW_UPGRADE
|
||||
struct task_struct *update_thread;
|
||||
#endif
|
||||
|
||||
/* obtain msg when battery status has changed */
|
||||
struct delayed_work check_power_status_work;
|
||||
struct workqueue_struct *check_power_status_queue;
|
||||
unsigned long work_delay;
|
||||
bool vpower_reg_nb;
|
||||
|
||||
/* Sending report data to users for the debug */
|
||||
bool debug_node_open;
|
||||
int debug_data_frame;
|
||||
wait_queue_head_t inq;
|
||||
unsigned char debug_buf[1024][2048];
|
||||
struct mutex ilitek_debug_mutex;
|
||||
struct mutex ilitek_debug_read_mutex;
|
||||
|
||||
struct spi_device *spi;
|
||||
bool suspended;
|
||||
|
||||
const char *TP_IC_TYPE;
|
||||
bool MT_B_TYPE;
|
||||
bool REGULATOR_POWER_ON;
|
||||
bool BATTERY_CHECK;
|
||||
bool ENABLE_BATTERY_CHECK;
|
||||
|
||||
u32 x_max;
|
||||
u32 y_max;
|
||||
u32 x_min;
|
||||
u32 y_min;
|
||||
|
||||
bool x_flip;
|
||||
bool y_flip;
|
||||
|
||||
int TPD_WIDTH;
|
||||
int TPD_HEIGHT;
|
||||
int MAX_TOUCH_NUM;
|
||||
|
||||
};
|
||||
|
||||
extern struct ilitek_platform_data *ipd;
|
||||
extern struct tpd_device *tpd;
|
||||
/* exported from platform.c */
|
||||
extern void ilitek_platform_disable_irq(void);
|
||||
extern void ilitek_platform_enable_irq(void);
|
||||
extern int ilitek_platform_read_tp_info(void);
|
||||
extern void ilitek_platform_tp_hw_reset(bool isEnable);
|
||||
#ifdef ENABLE_REGULATOR_POWER_ON
|
||||
extern void ilitek_regulator_power_on(bool status);
|
||||
#endif
|
||||
|
||||
/* exported from userspsace.c */
|
||||
extern void netlink_reply_msg(void *raw, int size);
|
||||
extern int ilitek_proc_init(void);
|
||||
extern void ilitek_proc_remove(void);
|
||||
extern int ilitek_sys_init(void);
|
||||
extern void ilitek_sys_remove(void);
|
||||
|
||||
#endif /* __PLATFORM_H */
|
||||
1928
drivers/input/touchscreen/ilitek_mmi/userspace.c
Normal file
1928
drivers/input/touchscreen/ilitek_mmi/userspace.c
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue