mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-09-09 01:28:05 -04:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
48
drivers/input/touchscreen/melfas_mms400/Kconfig
Normal file
48
drivers/input/touchscreen/melfas_mms400/Kconfig
Normal file
|
@ -0,0 +1,48 @@
|
|||
#
|
||||
# Kconfig for MELFAS MMS400 Touchscreen driver
|
||||
#
|
||||
|
||||
if INPUT_TOUCHSCREEN
|
||||
|
||||
config TOUCHSCREEN_MELFAS_MMS438
|
||||
tristate "MELFAS MMS438 Touchscreen"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here if you have a MELFAS MMS438 touchscreen device in your system.
|
||||
|
||||
# If unsure, say N.
|
||||
|
||||
# To compile this driver as a module, choose M here: the module will be called mms_ts.
|
||||
|
||||
config TOUCHSCREEN_MELFAS_MMS449
|
||||
tristate "MELFAS MMS449 Touchscreen"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here if you have a MELFAS MMS449 touchscreen device in your system.
|
||||
|
||||
# If unsure, say N.
|
||||
|
||||
# To compile this driver as a module, choose M here: the module will be called mms_ts.
|
||||
|
||||
config TOUCHSCREEN_MELFAS_MMS458
|
||||
tristate "MELFAS MMS458 Touchscreen"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here if you have a MELFAS MMS458 touchscreen device in your system.
|
||||
|
||||
# If unsure, say N.
|
||||
|
||||
# To compile this driver as a module, choose M here: the module will be called mms_ts.
|
||||
|
||||
config TOUCHSCREEN_MELFAS_MMS492
|
||||
tristate "MELFAS MMS492 Touchscreen"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here if you have a MELFAS MMS492 touchscreen device in your system.
|
||||
|
||||
# If unsure, say N.
|
||||
|
||||
# To compile this driver as a module, choose M here: the module will be called mms_ts.
|
||||
|
||||
endif
|
||||
|
15
drivers/input/touchscreen/melfas_mms400/Makefile
Normal file
15
drivers/input/touchscreen/melfas_mms400/Makefile
Normal file
|
@ -0,0 +1,15 @@
|
|||
#
|
||||
# Makefile for MELFAS MMS400 Touchscreen driver
|
||||
#
|
||||
|
||||
obj-$(CONFIG_TOUCHSCREEN_MELFAS_MMS438) += melfas_mms400.o melfas_mms400_mod.o melfas_mms400_test.o melfas_mms400_cmd.o melfas_mms438_fw_update.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_MELFAS_MMS449) += melfas_mms400.o melfas_mms400_mod.o melfas_mms400_test.o melfas_mms400_cmd.o melfas_mms438_fw_update.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_MELFAS_MMS458) += melfas_mms400.o melfas_mms400_mod.o melfas_mms400_test.o melfas_mms400_cmd.o melfas_mms438_fw_update.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_MELFAS_MMS492) += melfas_mms400.o melfas_mms400_mod.o melfas_mms400_test.o melfas_mms400_cmd.o melfas_mms492_fw_update.o
|
||||
|
||||
#CFLAGS_melfas_mms400.o += -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function -Wno-unused-label
|
||||
#CFLAGS_melfas_mms400_test.o += -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function -Wno-unused-label
|
||||
#CFLAGS_melfas_mms400_cmd.o += -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function -Wno-unused-label
|
||||
#CFLAGS_melfas_mms438_fw_update.o += -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function -Wno-unused-label
|
||||
#CFLAGS_melfas_mms492_fw_update.o += -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function -Wno-unused-label
|
||||
|
1250
drivers/input/touchscreen/melfas_mms400/melfas_mms400.c
Normal file
1250
drivers/input/touchscreen/melfas_mms400/melfas_mms400.c
Normal file
File diff suppressed because it is too large
Load diff
407
drivers/input/touchscreen/melfas_mms400/melfas_mms400.h
Normal file
407
drivers/input/touchscreen/melfas_mms400/melfas_mms400.h
Normal file
|
@ -0,0 +1,407 @@
|
|||
/*
|
||||
* MELFAS MMS400 Touchscreen Driver
|
||||
*
|
||||
* Copyright (C) 2014 MELFAS Inc.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __MELFAS_MMS400_H
|
||||
#define __MELFAS_MMS400_H
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio_event.h>
|
||||
#include <linux/wakelock.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
|
||||
#include "melfas_mms400_reg.h"
|
||||
|
||||
#include <linux/sec_sysfs.h>
|
||||
#ifdef CONFIG_BATTERY_SAMSUNG
|
||||
#include <linux/sec_batt.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_VBUS_NOTIFIER
|
||||
#include <linux/muic/muic.h>
|
||||
#include <linux/muic/muic_notifier.h>
|
||||
#include <linux/vbus_notifier.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SEC_DEBUG_TSP_LOG
|
||||
#include <linux/sec_debug.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SEC_DEBUG_TSP_LOG
|
||||
#define tsp_debug_dbg(mode, dev, fmt, ...) \
|
||||
({ \
|
||||
if (mode) { \
|
||||
dev_dbg(dev, fmt, ## __VA_ARGS__); \
|
||||
sec_debug_tsp_log(fmt, ## __VA_ARGS__); \
|
||||
} \
|
||||
else \
|
||||
dev_dbg(dev, fmt, ## __VA_ARGS__); \
|
||||
})
|
||||
|
||||
#define tsp_debug_info(mode, dev, fmt, ...) \
|
||||
({ \
|
||||
if (mode) { \
|
||||
dev_info(dev, fmt, ## __VA_ARGS__); \
|
||||
sec_debug_tsp_log(fmt, ## __VA_ARGS__); \
|
||||
} \
|
||||
else \
|
||||
dev_info(dev, fmt, ## __VA_ARGS__); \
|
||||
})
|
||||
|
||||
#define tsp_debug_err(mode, dev, fmt, ...) \
|
||||
({ \
|
||||
if (mode) { \
|
||||
dev_err(dev, fmt, ## __VA_ARGS__); \
|
||||
sec_debug_tsp_log(fmt, ## __VA_ARGS__); \
|
||||
} \
|
||||
else \
|
||||
dev_err(dev, fmt, ## __VA_ARGS__); \
|
||||
})
|
||||
#else
|
||||
#define tsp_debug_dbg(mode, dev, fmt, ...) dev_dbg(dev, fmt, ## __VA_ARGS__)
|
||||
#define tsp_debug_info(mode, dev, fmt, ...) dev_info(dev, fmt, ## __VA_ARGS__)
|
||||
#define tsp_debug_err(mode, dev, fmt, ...) dev_err(dev, fmt, ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
#define MMS_USE_DEVICETREE 1
|
||||
#else
|
||||
#define MMS_USE_DEVICETREE 0
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_GLOVE_TOUCH)
|
||||
#define GLOVE_MODE
|
||||
#endif
|
||||
|
||||
#define COVER_MODE
|
||||
|
||||
#define MMS_DEVICE_NAME "mms_ts"
|
||||
#define MMS_CONFIG_DATE {0x00, 0x00, 0x00, 0x00}
|
||||
|
||||
//Chip info
|
||||
#if defined(CONFIG_TOUCHSCREEN_MELFAS_MMS438)
|
||||
#define CHIP_MMS438
|
||||
#define CHIP_NAME "MMS438"
|
||||
#define CHIP_FW_CODE "M4H0"
|
||||
#define FW_UPDATE_TYPE "MMS438"
|
||||
#elif defined(CONFIG_TOUCHSCREEN_MELFAS_MMS449)
|
||||
#define CHIP_MMS449
|
||||
#define CHIP_NAME "MMS449"
|
||||
#define CHIP_FW_CODE "M4HP"
|
||||
#define FW_UPDATE_TYPE "MMS438"
|
||||
#elif defined(CONFIG_TOUCHSCREEN_MELFAS_MMS458)
|
||||
#define CHIP_MMS458
|
||||
#define CHIP_NAME "MMS458"
|
||||
#define CHIP_FW_CODE "M4HN"
|
||||
#define FW_UPDATE_TYPE "MMS438"
|
||||
#elif defined(CONFIG_TOUCHSCREEN_MELFAS_MMS492)
|
||||
#define CHIP_MMS492
|
||||
#define CHIP_NAME "MMS492"
|
||||
#define CHIP_FW_CODE "M4HL"
|
||||
#define FW_UPDATE_TYPE "MMS492"
|
||||
#endif
|
||||
|
||||
//Config driver
|
||||
#define MMS_USE_INPUT_OPEN_CLOSE 1
|
||||
#define I2C_RETRY_COUNT 3
|
||||
#define RESET_ON_EVENT_ERROR 0
|
||||
#define ESD_COUNT_FOR_DISABLE 7
|
||||
#define MMS_USE_TOUCHKEY 0
|
||||
|
||||
//Features
|
||||
#define MMS_USE_NAP_MODE 0
|
||||
#define MMS_USE_TEST_MODE 1
|
||||
#define MMS_USE_CMD_MODE 1
|
||||
#ifdef CONFIG_SAMSUNG_PRODUCT_SHIP
|
||||
#define MMS_USE_DEV_MODE 0
|
||||
#else
|
||||
#define MMS_USE_DEV_MODE 1
|
||||
#endif
|
||||
|
||||
//Input value
|
||||
#define MAX_FINGER_NUM 10
|
||||
#define INPUT_AREA_MIN 0
|
||||
#define INPUT_AREA_MAX 255
|
||||
#define INPUT_PRESSURE_MIN 0
|
||||
#define INPUT_PRESSURE_MAX 255
|
||||
#define INPUT_TOUCH_MAJOR_MIN 0
|
||||
#define INPUT_TOUCH_MAJOR_MAX 255
|
||||
#define INPUT_TOUCH_MINOR_MIN 0
|
||||
#define INPUT_TOUCH_MINOR_MAX 255
|
||||
#define INPUT_ANGLE_MIN 0
|
||||
#define INPUT_ANGLE_MAX 255
|
||||
#define INPUT_HOVER_MIN 0
|
||||
#define INPUT_HOVER_MAX 255
|
||||
#define INPUT_PALM_MIN 0
|
||||
#define INPUT_PALM_MAX 1
|
||||
|
||||
//Firmware update
|
||||
#define INTERNAL_FW_PATH "tsp_melfas/mms449_carmen2.fw"
|
||||
#define EXTERNAL_FW_PATH "/sdcard/melfas.mfsb"
|
||||
#define FFU_FW_PATH "ffu_tsp.bin"
|
||||
#define MMS_USE_AUTO_FW_UPDATE 1
|
||||
#define MMS_FW_MAX_SECT_NUM 4
|
||||
#define MMS_FW_UPDATE_DEBUG 0
|
||||
#define MMS_FW_UPDATE_SECTION 1
|
||||
#define MMS_EXT_FW_FORCE_UPDATE 1
|
||||
|
||||
//Command mode
|
||||
#define CMD_LEN 32
|
||||
#define CMD_RESULT_LEN 512
|
||||
#define CMD_PARAM_NUM 8
|
||||
|
||||
/**
|
||||
* Device info structure
|
||||
*/
|
||||
struct mms_ts_info {
|
||||
struct i2c_client *client;
|
||||
struct input_dev *input_dev;
|
||||
char phys[32];
|
||||
struct mms_devicetree_data *dtdata;
|
||||
struct pinctrl *pinctrl;
|
||||
|
||||
dev_t mms_dev;
|
||||
struct class *class;
|
||||
|
||||
struct mutex lock;
|
||||
struct mutex lock_test;
|
||||
struct mutex lock_cmd;
|
||||
struct mutex lock_dev;
|
||||
|
||||
int irq;
|
||||
bool enabled;
|
||||
bool init;
|
||||
char *fw_name;
|
||||
|
||||
u8 product_name[16];
|
||||
int max_x;
|
||||
int max_y;
|
||||
u8 node_x;
|
||||
u8 node_y;
|
||||
u8 node_key;
|
||||
u8 boot_ver_ic;
|
||||
u8 core_ver_ic;
|
||||
u8 config_ver_ic;
|
||||
u8 event_size;
|
||||
u16 fw_year;
|
||||
u8 fw_month;
|
||||
u8 fw_date;
|
||||
u16 pre_chksum;
|
||||
u16 rt_chksum;
|
||||
unsigned char finger_state[MAX_FINGER_NUM];
|
||||
int touch_count;
|
||||
|
||||
bool tkey_enable;
|
||||
|
||||
u8 nap_mode;
|
||||
u8 glove_mode;
|
||||
u8 charger_mode;
|
||||
u8 cover_mode;
|
||||
|
||||
u8 esd_cnt;
|
||||
bool disable_esd;
|
||||
|
||||
u8 *print_buf;
|
||||
int *image_buf;
|
||||
|
||||
bool test_busy;
|
||||
bool cmd_busy;
|
||||
bool dev_busy;
|
||||
|
||||
#if MMS_USE_CMD_MODE
|
||||
dev_t cmd_dev_t;
|
||||
struct device *cmd_dev;
|
||||
struct class *cmd_class;
|
||||
struct list_head cmd_list_head;
|
||||
u8 cmd_state;
|
||||
char cmd[CMD_LEN];
|
||||
char *cmd_result;
|
||||
int cmd_param[CMD_PARAM_NUM];
|
||||
int cmd_buffer_size;
|
||||
#endif
|
||||
|
||||
#if MMS_USE_DEV_MODE
|
||||
struct cdev cdev;
|
||||
u8 *dev_fs_buf;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_VBUS_NOTIFIER
|
||||
struct notifier_block vbus_nb;
|
||||
bool ta_stsatus;
|
||||
#endif
|
||||
|
||||
#ifdef USE_TSP_TA_CALLBACKS
|
||||
void (*register_cb)(struct tsp_callbacks *);
|
||||
struct tsp_callbacks callbacks;
|
||||
#endif
|
||||
#ifdef CONFIG_SEC_DEBUG_TSP_LOG
|
||||
struct delayed_work ghost_check;
|
||||
u8 tsp_dump_lock;
|
||||
u8 add_log_header;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Platform Data
|
||||
*/
|
||||
struct mms_devicetree_data {
|
||||
unsigned int max_x;
|
||||
unsigned int max_y;
|
||||
int gpio_intr;
|
||||
const char *gpio_vdd_en;
|
||||
const char *gpio_io_en;
|
||||
int gpio_sda;
|
||||
int gpio_scl;
|
||||
int panel;
|
||||
struct regulator *vdd_io;
|
||||
const char *fw_name;
|
||||
};
|
||||
|
||||
/**
|
||||
* Firmware binary header info
|
||||
*/
|
||||
struct mms_bin_hdr {
|
||||
char tag[8];
|
||||
u16 core_version;
|
||||
u16 section_num;
|
||||
u16 contains_full_binary;
|
||||
u16 reserved0;
|
||||
|
||||
u32 binary_offset;
|
||||
u32 binary_length;
|
||||
|
||||
u32 extention_offset;
|
||||
u32 reserved1;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/**
|
||||
* Firmware image info
|
||||
*/
|
||||
struct mms_fw_img {
|
||||
u16 type;
|
||||
u16 version;
|
||||
|
||||
u16 start_page;
|
||||
u16 end_page;
|
||||
|
||||
u32 offset;
|
||||
u32 length;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/**
|
||||
* Firmware update error code
|
||||
*/
|
||||
enum fw_update_errno{
|
||||
fw_err_file_read = -4,
|
||||
fw_err_file_open = -3,
|
||||
fw_err_file_type = -2,
|
||||
fw_err_download = -1,
|
||||
fw_err_none = 0,
|
||||
fw_err_uptodate = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* Declarations
|
||||
*/
|
||||
//main
|
||||
void mms_reboot(struct mms_ts_info *info);
|
||||
int mms_i2c_read(struct mms_ts_info *info, char *write_buf, unsigned int write_len,
|
||||
char *read_buf, unsigned int read_len);
|
||||
int mms_i2c_read_next(struct mms_ts_info *info, char *read_buf, int start_idx,
|
||||
unsigned int read_len);
|
||||
int mms_i2c_write(struct mms_ts_info *info, char *write_buf, unsigned int write_len);
|
||||
int mms_enable(struct mms_ts_info *info);
|
||||
int mms_disable(struct mms_ts_info *info);
|
||||
int mms_get_ready_status(struct mms_ts_info *info);
|
||||
int mms_get_fw_version(struct mms_ts_info *info, u8 *ver_buf);
|
||||
int mms_get_fw_version_u16(struct mms_ts_info *info, u16 *ver_buf_u16);
|
||||
int mms_disable_esd_alert(struct mms_ts_info *info);
|
||||
int mms_fw_update_from_kernel(struct mms_ts_info *info, bool force);
|
||||
int mms_fw_update_from_storage(struct mms_ts_info *info, bool force);
|
||||
int mms_fw_update_from_ffu(struct mms_ts_info *info, bool force);
|
||||
|
||||
int mms_suspend(struct device *dev);
|
||||
int mms_resume(struct device *dev);
|
||||
|
||||
//mod
|
||||
int mms_power_control(struct mms_ts_info *info, int enable);
|
||||
void mms_clear_input(struct mms_ts_info *info);
|
||||
void mms_report_input_event(struct mms_ts_info *info, u8 sz, u8 *buf);
|
||||
void mms_input_event_handler(struct mms_ts_info *info, u8 sz, u8 *buf);
|
||||
#ifdef CONFIG_VBUS_NOTIFIER
|
||||
int mms_charger_attached(struct mms_ts_info *info, bool status);
|
||||
#endif
|
||||
|
||||
#if MMS_USE_DEVICETREE
|
||||
int mms_parse_devicetree(struct device *dev, struct mms_ts_info *info);
|
||||
#endif
|
||||
void mms_config_input(struct mms_ts_info *info);
|
||||
|
||||
//fw_update
|
||||
int mms_flash_fw(struct mms_ts_info *info, const u8 *fw_data, size_t fw_size,
|
||||
bool force, bool section);
|
||||
|
||||
//test
|
||||
#if MMS_USE_DEV_MODE
|
||||
int mms_dev_create(struct mms_ts_info *info);
|
||||
int mms_get_log(struct mms_ts_info *info);
|
||||
#endif
|
||||
int mms_run_test(struct mms_ts_info *info, u8 test_type);
|
||||
int mms_get_image(struct mms_ts_info *info, u8 image_type);
|
||||
#if MMS_USE_TEST_MODE
|
||||
int mms_sysfs_create(struct mms_ts_info *info);
|
||||
void mms_sysfs_remove(struct mms_ts_info *info);
|
||||
static const struct attribute_group mms_test_attr_group;
|
||||
#endif
|
||||
|
||||
//cmd
|
||||
#if MMS_USE_CMD_MODE
|
||||
int mms_sysfs_cmd_create(struct mms_ts_info *info);
|
||||
void mms_sysfs_cmd_remove(struct mms_ts_info *info);
|
||||
static const struct attribute_group mms_cmd_attr_group;
|
||||
extern struct class *sec_class;
|
||||
#endif
|
||||
|
||||
#ifdef USE_TSP_TA_CALLBACKS
|
||||
void mms_charger_status_cb(struct tsp_callbacks *cb, int status);
|
||||
void mms_register_callback(struct tsp_callbacks *cb);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_VBUS_NOTIFIER
|
||||
int mms_vbus_notification(struct notifier_block *nb,
|
||||
unsigned long cmd, void *data);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SAMSUNG_LPM_MODE
|
||||
extern int poweroff_charging;
|
||||
#endif
|
||||
|
||||
#endif /* __MELFAS_MMS400_H */
|
1356
drivers/input/touchscreen/melfas_mms400/melfas_mms400_cmd.c
Normal file
1356
drivers/input/touchscreen/melfas_mms400/melfas_mms400_cmd.c
Normal file
File diff suppressed because it is too large
Load diff
399
drivers/input/touchscreen/melfas_mms400/melfas_mms400_mod.c
Normal file
399
drivers/input/touchscreen/melfas_mms400/melfas_mms400_mod.c
Normal file
|
@ -0,0 +1,399 @@
|
|||
/*
|
||||
* MELFAS MMS400 Touchscreen
|
||||
*
|
||||
* Copyright (C) 2014 MELFAS Inc.
|
||||
*
|
||||
*
|
||||
* Model dependent functions
|
||||
*
|
||||
*/
|
||||
|
||||
#include "melfas_mms400.h"
|
||||
|
||||
#ifdef USE_TSP_TA_CALLBACKS
|
||||
static bool ta_connected = 0;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Control power supply
|
||||
*/
|
||||
int mms_power_control(struct mms_ts_info *info, int enable)
|
||||
{
|
||||
int ret = 0;
|
||||
struct i2c_client *client = info->client;
|
||||
struct regulator *regulator_dvdd;
|
||||
struct regulator *regulator_avdd;
|
||||
struct pinctrl_state *pinctrl_state;
|
||||
static bool on;
|
||||
|
||||
tsp_debug_info(true, &info->client->dev, "%s [START %s] \n",
|
||||
__func__, enable? "on":"off");
|
||||
|
||||
if (on == enable) {
|
||||
tsp_debug_err(true, &client->dev, "%s : TSP power already %s\n",
|
||||
__func__,(on)?"on":"off");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (info->dtdata->gpio_io_en) {
|
||||
regulator_dvdd = regulator_get(NULL, info->dtdata->gpio_io_en);
|
||||
if (IS_ERR(regulator_dvdd)) {
|
||||
tsp_debug_err(true, &client->dev,"%s: Failed to get %s regulator.\n",
|
||||
__func__, info->dtdata->gpio_io_en);
|
||||
ret = PTR_ERR(regulator_dvdd);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
regulator_avdd = regulator_get(NULL, info->dtdata->gpio_vdd_en);
|
||||
if (IS_ERR(regulator_avdd)) {
|
||||
tsp_debug_err(true, &client->dev,"%s: Failed to get %s regulator.\n",
|
||||
__func__, info->dtdata->gpio_vdd_en);
|
||||
ret = PTR_ERR(regulator_avdd);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
ret = regulator_enable(regulator_avdd);
|
||||
if (ret) {
|
||||
tsp_debug_err(true, &client->dev, "%s: Failed to enable avdd: %d\n", __func__, ret);
|
||||
goto out;
|
||||
}
|
||||
if (info->dtdata->gpio_io_en) {
|
||||
ret = regulator_enable(regulator_dvdd);
|
||||
if (ret) {
|
||||
tsp_debug_err(true, &client->dev,"%s: Failed to enable vdd: %d\n", __func__, ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
pinctrl_state = pinctrl_lookup_state(info->pinctrl, "on_state");
|
||||
} else {
|
||||
if (info->dtdata->gpio_io_en) {
|
||||
if (regulator_is_enabled(regulator_dvdd))
|
||||
regulator_disable(regulator_dvdd);
|
||||
}
|
||||
if (regulator_is_enabled(regulator_avdd))
|
||||
regulator_disable(regulator_avdd);
|
||||
|
||||
pinctrl_state = pinctrl_lookup_state(info->pinctrl, "off_state");
|
||||
}
|
||||
|
||||
if (IS_ERR(pinctrl_state)) {
|
||||
tsp_debug_err(true, &client->dev,"%s: Failed to lookup pinctrl.\n", __func__);
|
||||
} else {
|
||||
ret = pinctrl_select_state(info->pinctrl, pinctrl_state);
|
||||
if (ret)
|
||||
tsp_debug_err(true, &client->dev, "%s: Failed to configure pinctrl.\n", __func__);
|
||||
}
|
||||
|
||||
on = enable;
|
||||
out:
|
||||
if (info->dtdata->gpio_io_en) {
|
||||
regulator_put(regulator_dvdd);
|
||||
}
|
||||
regulator_put(regulator_avdd);
|
||||
|
||||
if (!enable)
|
||||
usleep_range(10 * 1000, 11 * 1000);
|
||||
else
|
||||
msleep(50);
|
||||
|
||||
tsp_debug_info(true, &info->client->dev, "%s [DONE %s] \n",
|
||||
__func__, enable? "on":"off");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear touch input events
|
||||
*/
|
||||
void mms_clear_input(struct mms_ts_info *info)
|
||||
{
|
||||
int i;
|
||||
|
||||
input_report_key(info->input_dev, BTN_TOUCH, 0);
|
||||
input_report_key(info->input_dev, BTN_TOOL_FINGER, 0);
|
||||
|
||||
for (i = 0; i< MAX_FINGER_NUM; i++) {
|
||||
info->finger_state[i] = 0;
|
||||
input_mt_slot(info->input_dev, i);
|
||||
input_mt_report_slot_state(info->input_dev, MT_TOOL_FINGER, false);
|
||||
}
|
||||
|
||||
info->touch_count = 0;
|
||||
|
||||
input_sync(info->input_dev);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Input event handler - Report touch input event
|
||||
*/
|
||||
void mms_input_event_handler(struct mms_ts_info *info, u8 sz, u8 *buf)
|
||||
{
|
||||
struct i2c_client *client = info->client;
|
||||
int i;
|
||||
|
||||
tsp_debug_dbg(false, &client->dev, "%s [START]\n", __func__);
|
||||
tsp_debug_dbg(false, &client->dev, "%s - sz[%d] buf[0x%02X]\n", __func__, sz, buf[0]);
|
||||
|
||||
for (i = 1; i < sz; i += info->event_size) {
|
||||
u8 *tmp = &buf[i];
|
||||
|
||||
int id = (tmp[0] & MIP_EVENT_INPUT_ID) - 1;
|
||||
int x = tmp[2] | ((tmp[1] & 0xf) << 8);
|
||||
int y = tmp[3] | (((tmp[1] >> 4) & 0xf) << 8);
|
||||
int pressure = tmp[4];
|
||||
//int size = tmp[5]; // sumsize
|
||||
int touch_major = tmp[6];
|
||||
int touch_minor = tmp[7];
|
||||
|
||||
int palm = (tmp[0] & MIP_EVENT_INPUT_PALM) >> 4;
|
||||
|
||||
// Report input data
|
||||
#if MMS_USE_TOUCHKEY
|
||||
if ((tmp[0] & MIP_EVENT_INPUT_SCREEN) == 0) {
|
||||
//Touchkey Event
|
||||
int key = tmp[0] & 0xf;
|
||||
int key_state = (tmp[0] & MIP_EVENT_INPUT_PRESS) ? 1 : 0;
|
||||
int key_code = 0;
|
||||
|
||||
//Report touchkey event
|
||||
switch (key) {
|
||||
case 1:
|
||||
key_code = KEY_MENU;
|
||||
//tsp_debug_dbg(true, &client->dev, "Key : KEY_MENU\n");
|
||||
break;
|
||||
case 2:
|
||||
key_code = KEY_BACK;
|
||||
//tsp_debug_dbg(true, &client->dev, "Key : KEY_BACK\n");
|
||||
break;
|
||||
default:
|
||||
tsp_debug_err(true, &client->dev,
|
||||
"%s [ERROR] Unknown key code [%d]\n",
|
||||
__func__, key);
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
input_report_key(info->input_dev, key_code, key_state);
|
||||
|
||||
tsp_debug_dbg(true, &client->dev, "%s - Key : ID[%d] Code[%d] State[%d]\n",
|
||||
__func__, key, key_code, key_state);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
//Report touchscreen event
|
||||
if ((tmp[0] & MIP_EVENT_INPUT_PRESS) == 0) {
|
||||
//Release
|
||||
input_mt_slot(info->input_dev, id);
|
||||
#ifdef CONFIG_SEC_FACTORY
|
||||
input_report_abs(info->input_dev, ABS_MT_PRESSURE, 0);
|
||||
#endif
|
||||
input_mt_report_slot_state(info->input_dev,
|
||||
MT_TOOL_FINGER, false);
|
||||
if (info->finger_state[id] != 0){
|
||||
info->touch_count--;
|
||||
if (!info->touch_count) {
|
||||
input_report_key(info->input_dev, BTN_TOUCH, 0);
|
||||
input_report_key(info->input_dev,
|
||||
BTN_TOOL_FINGER, 0);
|
||||
}
|
||||
info->finger_state[id] = 0;
|
||||
tsp_debug_dbg(true, &client->dev,
|
||||
"R[%d] V[%02x%02x%02x] tc:%d\n",
|
||||
id, info->boot_ver_ic, info->core_ver_ic,
|
||||
info->config_ver_ic, info->touch_count);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
//Press or Move
|
||||
input_mt_slot(info->input_dev, id);
|
||||
input_mt_report_slot_state(info->input_dev, MT_TOOL_FINGER, true);
|
||||
input_report_key(info->input_dev, BTN_TOUCH, 1);
|
||||
input_report_key(info->input_dev, BTN_TOOL_FINGER, 1);
|
||||
input_report_abs(info->input_dev, ABS_MT_POSITION_X, x);
|
||||
input_report_abs(info->input_dev, ABS_MT_POSITION_Y, y);
|
||||
#ifdef CONFIG_SEC_FACTORY
|
||||
if (pressure)
|
||||
input_report_abs(info->input_dev, ABS_MT_PRESSURE, pressure);
|
||||
else
|
||||
input_report_abs(info->input_dev, ABS_MT_PRESSURE, 1);
|
||||
#endif
|
||||
input_report_abs(info->input_dev, ABS_MT_TOUCH_MAJOR, touch_major);
|
||||
input_report_abs(info->input_dev, ABS_MT_TOUCH_MINOR, touch_minor);
|
||||
input_report_abs(info->input_dev, ABS_MT_PALM, palm);
|
||||
|
||||
if (info->finger_state[id] == 0){
|
||||
info->finger_state[id] = 1;
|
||||
info->touch_count++;
|
||||
#ifdef CONFIG_SAMSUNG_PRODUCT_SHIP
|
||||
tsp_debug_info(true, &client->dev,
|
||||
"P[%d] z:%d p:%d m:%d,%d tc:%d\n",
|
||||
id, pressure, palm, touch_major, touch_minor, info->touch_count);
|
||||
#else
|
||||
tsp_debug_dbg(true, &client->dev,
|
||||
"P[%d] (%d, %d) z:%d p:%d m:%d,%d tc:%d\n",
|
||||
id, x, y, pressure, palm, touch_major, touch_minor, info->touch_count);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input_sync(info->input_dev);
|
||||
tsp_debug_dbg(false, &client->dev, "%s [DONE]\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
#if MMS_USE_DEVICETREE
|
||||
/**
|
||||
* Parse device tree
|
||||
*/
|
||||
int mms_parse_devicetree(struct device *dev, struct mms_ts_info *info)
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
int ret;
|
||||
|
||||
tsp_debug_info(true, dev, "%s [START]\n", __func__);
|
||||
|
||||
ret = of_property_read_u32(np, "melfas,max_x", &info->dtdata->max_x);
|
||||
if (ret) {
|
||||
tsp_debug_err(true, dev, "%s [ERROR] max_x\n", __func__);
|
||||
info->dtdata->max_x = 720;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(np, "melfas,max_y", &info->dtdata->max_y);
|
||||
if (ret) {
|
||||
tsp_debug_err(true, dev, "%s [ERROR] max_y\n", __func__);
|
||||
info->dtdata->max_y = 1280;
|
||||
}
|
||||
|
||||
info->dtdata->gpio_intr = of_get_named_gpio(np, "melfas,irq-gpio", 0);
|
||||
gpio_request(info->dtdata->gpio_intr, "irq-gpio");
|
||||
gpio_direction_input(info->dtdata->gpio_intr);
|
||||
info->client->irq = gpio_to_irq(info->dtdata->gpio_intr);
|
||||
|
||||
info->dtdata->gpio_scl = of_get_named_gpio(np, "melfas,scl-gpio", 0);
|
||||
gpio_request(info->dtdata->gpio_scl, "melfas_scl_gpio");
|
||||
info->dtdata->gpio_sda = of_get_named_gpio(np, "melfas,sda-gpio", 0);
|
||||
gpio_request(info->dtdata->gpio_sda, "melfas_sda_gpio");
|
||||
|
||||
if (of_property_read_string(np, "melfas,vdd_en", &info->dtdata->gpio_vdd_en)) {
|
||||
tsp_debug_err(true, dev, "Failed to get regulator_dvdd name property\n");
|
||||
}
|
||||
if (of_property_read_string(np, "melfas,io_en", &info->dtdata->gpio_io_en)) {
|
||||
tsp_debug_err(true, dev, "Failed to get regulator_avdd name property\n");
|
||||
info->dtdata->gpio_io_en = NULL;
|
||||
}
|
||||
|
||||
if (of_property_read_string(np, "melfas,fw_name", &info->dtdata->fw_name)) {
|
||||
tsp_debug_err(true, dev, "Failed to get fw_name property\n");
|
||||
info->dtdata->fw_name = INTERNAL_FW_PATH;
|
||||
}
|
||||
|
||||
tsp_debug_info(true, dev, "%s: fw_name %s max_x:%d max_y:%d int:%d irq:%d sda:%d scl:%d \n",
|
||||
__func__, info->dtdata->fw_name, info->dtdata->max_x, info->dtdata->max_y,
|
||||
info->dtdata->gpio_intr, info->client->irq, info->dtdata->gpio_sda,
|
||||
info->dtdata->gpio_scl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Config input interface
|
||||
*/
|
||||
void mms_config_input(struct mms_ts_info *info)
|
||||
{
|
||||
struct input_dev *input_dev = info->input_dev;
|
||||
|
||||
tsp_debug_dbg(true, &info->client->dev, "%s [START]\n", __func__);
|
||||
|
||||
//Screen
|
||||
set_bit(EV_SYN, input_dev->evbit);
|
||||
set_bit(EV_ABS, input_dev->evbit);
|
||||
|
||||
set_bit(BTN_TOUCH, input_dev->keybit);
|
||||
set_bit(BTN_TOOL_FINGER, input_dev->keybit);
|
||||
set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
|
||||
|
||||
input_mt_init_slots(input_dev, MAX_FINGER_NUM, INPUT_MT_DIRECT);
|
||||
|
||||
input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, info->max_x, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, info->max_y, 0, 0);
|
||||
#ifdef CONFIG_SEC_FACTORY
|
||||
input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, INPUT_PRESSURE_MAX, 0, 0);
|
||||
#endif
|
||||
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, INPUT_TOUCH_MAJOR_MAX, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, 0, INPUT_TOUCH_MINOR_MAX, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_MT_PALM, 0, 1, 0, 0);
|
||||
|
||||
//Key
|
||||
set_bit(EV_KEY, input_dev->evbit);
|
||||
#if MMS_USE_TOUCHKEY
|
||||
set_bit(KEY_BACK, input_dev->keybit);
|
||||
set_bit(KEY_MENU, input_dev->keybit);
|
||||
#endif
|
||||
#if MMS_USE_NAP_MODE
|
||||
set_bit(EV_KEY, input_dev->evbit);
|
||||
set_bit(KEY_POWER, input_dev->keybit);
|
||||
#endif
|
||||
tsp_debug_dbg(true, &info->client->dev, "%s [DONE]\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VBUS_NOTIFIER
|
||||
int mms_vbus_notification(struct notifier_block *nb,
|
||||
unsigned long cmd, void *data)
|
||||
{
|
||||
struct mms_ts_info *info = container_of(nb, struct mms_ts_info, vbus_nb);
|
||||
vbus_status_t vbus_type = *(vbus_status_t *)data;
|
||||
|
||||
tsp_debug_info(true, &info->client->dev, "%s cmd=%lu, vbus_type=%d\n", __func__, cmd, vbus_type);
|
||||
|
||||
if (!info->enabled) {
|
||||
tsp_debug_err(true, &info->client->dev, "%s tsp disabled",__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (vbus_type) {
|
||||
case STATUS_VBUS_HIGH:
|
||||
tsp_debug_info(true, &info->client->dev, "%s : attach\n",__func__);
|
||||
info->ta_stsatus = true;
|
||||
break;
|
||||
case STATUS_VBUS_LOW:
|
||||
tsp_debug_info(true, &info->client->dev, "%s : detach\n",__func__);
|
||||
info->ta_stsatus = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mms_charger_attached(info, info->ta_stsatus);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Callback - get charger status
|
||||
*/
|
||||
#ifdef USE_TSP_TA_CALLBACKS
|
||||
void mms_charger_status_cb(struct tsp_callbacks *cb, int status)
|
||||
{
|
||||
pr_info("%s: TA %s\n",
|
||||
__func__, status ? "connected" : "disconnected");
|
||||
|
||||
if (status)
|
||||
ta_connected = true;
|
||||
else
|
||||
ta_connected = false;
|
||||
|
||||
/* not yet defined functions */
|
||||
}
|
||||
|
||||
void mms_register_callback(struct tsp_callbacks *cb)
|
||||
{
|
||||
charger_callbacks = cb;
|
||||
pr_info("%s\n", __func__);
|
||||
}
|
||||
#endif
|
136
drivers/input/touchscreen/melfas_mms400/melfas_mms400_reg.h
Normal file
136
drivers/input/touchscreen/melfas_mms400/melfas_mms400_reg.h
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* MELFAS MMS400 Touchscreen
|
||||
*
|
||||
* Copyright (C) 2014 MELFAS Inc.
|
||||
*
|
||||
*
|
||||
* Protocol information
|
||||
*
|
||||
* Protocol Version : MIP 4.0
|
||||
*
|
||||
*/
|
||||
#ifndef __MELFAS_MMS400_REG_H
|
||||
#define __MELFAS_MMS400_REG_H
|
||||
|
||||
//Address
|
||||
#define MIP_R0_INFO 0x01
|
||||
#define MIP_R1_INFO_PRODUCT_NAME 0x00
|
||||
#define MIP_R1_INFO_RESOLUTION_X 0x10
|
||||
#define MIP_R1_INFO_RESOLUTION_Y 0x12
|
||||
#define MIP_R1_INFO_NODE_NUM_X 0x14
|
||||
#define MIP_R1_INFO_NODE_NUM_Y 0x15
|
||||
#define MIP_R1_INFO_KEY_NUM 0x16
|
||||
#define MIP_R1_INFO_VERSION_BOOT 0x20
|
||||
#define MIP_R1_INFO_VERSION_CORE 0x22
|
||||
#define MIP_R1_INFO_VERSION_CUSTOM 0x24
|
||||
#define MIP_R1_INFO_VERSION_PARAM 0x26
|
||||
#define MIP_R1_INFO_SECT_BOOT_START 0x30
|
||||
#define MIP_R1_INFO_SECT_BOOT_END 0x31
|
||||
#define MIP_R1_INFO_SECT_CORE_START 0x32
|
||||
#define MIP_R1_INFO_SECT_CORE_END 0x33
|
||||
#define MIP_R1_INFO_SECT_CUSTOM_START 0x34
|
||||
#define MIP_R1_INFO_SECT_CUSTOM_END 0x35
|
||||
#define MIP_R1_INFO_SECT_PARAM_START 0x36
|
||||
#define MIP_R1_INFO_SECT_PARAM_END 0x37
|
||||
#define MIP_R1_INFO_BUILD_DATE 0x40
|
||||
#define MIP_R1_INFO_BUILD_TIME 0x44
|
||||
#define MIP_R1_INFO_CHECKSUM_PRECALC 0x48
|
||||
#define MIP_R1_INFO_CHECKSUM_REALTIME 0x4A
|
||||
#define MIP_R1_INFO_CHECKSUM_CALC 0x4C
|
||||
#define MIP_R1_INFO_PROTOCOL_NAME 0x50
|
||||
#define MIP_R1_INFO_PROTOCOL_VERSION 0x58
|
||||
#define MIP_R1_INFO_IC_ID 0x70
|
||||
|
||||
#define MIP_R0_EVENT 0x02
|
||||
#define MIP_R1_EVENT_SUPPORTED_FUNC 0x00
|
||||
#define MIP_R1_EVENT_FORMAT 0x04
|
||||
#define MIP_R1_EVENT_SIZE 0x06
|
||||
#define MIP_R1_EVENT_PACKET_INFO 0x10
|
||||
#define MIP_R1_EVENT_PACKET_DATA 0x11
|
||||
|
||||
#define MIP_R0_CTRL 0x06
|
||||
#define MIP_R1_CTRL_READY_STATUS 0x00
|
||||
#define MIP_R1_CTRL_EVENT_READY 0x01
|
||||
#define MIP_R1_CTRL_MODE 0x10
|
||||
#define MIP_R1_CTRL_EVENT_TRIGGER_TYPE 0x11
|
||||
#define MIP_R1_CTRL_RECALIBRATE 0x12
|
||||
#define MIP_R1_CTRL_POWER_STATE 0x13
|
||||
#define MIP_R1_CTRL_GESTURE_TYPE 0x14
|
||||
#define MIP_R1_CTRL_DISABLE_ESD_ALERT 0x18
|
||||
#define MIP_R1_CTRL_CHARGER_MODE 0x19
|
||||
#define MIP_R1_CTRL_GLOVE_MODE 0x1A
|
||||
#define MIP_R1_CTRL_WINDOW_MODE 0x1B
|
||||
#define MIP_R1_CTRL_PALM_REJECTION 0x1C
|
||||
#define MIP_R1_CTRL_DISABLE_EDGE_EXPAND 0x1D
|
||||
|
||||
#define MIP_R0_PARAM 0x08
|
||||
#define MIP_R1_PARAM_BUFFER_ADDR 0x00
|
||||
#define MIP_R1_PARAM_PROTOCOL 0x04
|
||||
#define MIP_R1_PARAM_MODE 0x10
|
||||
|
||||
#define MIP_R0_TEST 0x0A
|
||||
#define MIP_R1_TEST_BUF_ADDR 0x00
|
||||
#define MIP_R1_TEST_PROTOCOL 0x02
|
||||
#define MIP_R1_TEST_TYPE 0x10
|
||||
#define MIP_R1_TEST_DATA_FORMAT 0x20
|
||||
#define MIP_R1_TEST_ROW_NUM 0x20
|
||||
#define MIP_R1_TEST_COL_NUM 0x21
|
||||
#define MIP_R1_TEST_BUFFER_COL_NUM 0x22
|
||||
#define MIP_R1_TEST_COL_AXIS 0x23
|
||||
#define MIP_R1_TEST_KEY_NUM 0x24
|
||||
#define MIP_R1_TEST_DATA_TYPE 0x25
|
||||
|
||||
#define MIP_R0_IMAGE 0x0C
|
||||
#define MIP_R1_IMAGE_BUF_ADDR 0x00
|
||||
#define MIP_R1_IMAGE_PROTOCOL_ID 0x04
|
||||
#define MIP_R1_IMAGE_TYPE 0x10
|
||||
#define MIP_R1_IMAGE_DATA_FORMAT 0x20
|
||||
#define MIP_R1_IMAGE_ROW_NUM 0x20
|
||||
#define MIP_R1_IMAGE_COL_NUM 0x21
|
||||
#define MIP_R1_IMAGE_BUFFER_COL_NUM 0x22
|
||||
#define MIP_R1_IMAGE_COL_AXIS 0x23
|
||||
#define MIP_R1_IMAGE_KEY_NUM 0x24
|
||||
#define MIP_R1_IMAGE_DATA_TYPE 0x25
|
||||
#define MIP_R1_IMAGE_FINGER_NUM 0x30
|
||||
#define MIP_R1_IMAGE_FINGER_AREA 0x31
|
||||
|
||||
#define MIP_R0_LOG 0x10
|
||||
#define MIP_R1_LOG_TRIGGER 0x14
|
||||
|
||||
//Value
|
||||
#define MIP_EVENT_INPUT_PRESS 0x80
|
||||
#define MIP_EVENT_INPUT_SCREEN 0x40
|
||||
#define MIP_EVENT_INPUT_HOVER 0x20
|
||||
#define MIP_EVENT_INPUT_PALM 0x10
|
||||
#define MIP_EVENT_INPUT_ID 0x0F
|
||||
|
||||
#define MIP_ALERT_ESD 1
|
||||
#define MIP_ALERT_WAKEUP 2
|
||||
|
||||
#define MIP_CTRL_STATUS_NONE 0x05
|
||||
#define MIP_CTRL_STATUS_READY 0xA0
|
||||
#define MIP_CTRL_STATUS_LOG 0x77
|
||||
|
||||
#define MIP_CTRL_MODE_NORMAL 0
|
||||
#define MIP_CTRL_MODE_PARAM 1
|
||||
#define MIP_CTRL_MODE_TEST_CM 2
|
||||
|
||||
#define MIP_TEST_TYPE_NONE 0
|
||||
#define MIP_TEST_TYPE_CM_DELTA 1
|
||||
#define MIP_TEST_TYPE_CM_ABS 2
|
||||
#define MIP_TEST_TYPE_CM_JITTER 3
|
||||
#define MIP_TEST_TYPE_SHORT 4
|
||||
|
||||
#define MIP_IMG_TYPE_NONE 0
|
||||
#define MIP_IMG_TYPE_INTENSITY 1
|
||||
#define MIP_IMG_TYPE_RAWDATA 2
|
||||
#define MIP_IMG_TYPE_WAIT 255
|
||||
|
||||
#define MIP_TRIGGER_TYPE_NONE 0
|
||||
#define MIP_TRIGGER_TYPE_INTR 1
|
||||
#define MIP_TRIGGER_TYPE_REG 2
|
||||
|
||||
#define MIP_LOG_MODE_NONE 0
|
||||
#define MIP_LOG_MODE_TRIG 1
|
||||
|
||||
#endif /* __MELFAS_MMS400_REG_H */
|
1478
drivers/input/touchscreen/melfas_mms400/melfas_mms400_test.c
Normal file
1478
drivers/input/touchscreen/melfas_mms400/melfas_mms400_test.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,497 @@
|
|||
/*
|
||||
* MELFAS MMS438/449/458 Touchscreen
|
||||
*
|
||||
* Copyright (C) 2014 MELFAS Inc.
|
||||
*
|
||||
*
|
||||
* Firmware update functions
|
||||
*
|
||||
*/
|
||||
|
||||
#include "melfas_mms400.h"
|
||||
|
||||
//ISC Info
|
||||
#define ISC_PAGE_SIZE 128
|
||||
|
||||
//ISC Command
|
||||
#define ISC_CMD_ERASE_ALL {0xFB,0x4A,0x00,0x15,0x00,0x00}
|
||||
#define ISC_CMD_ERASE_PAGE {0xFB,0x4A,0x00,0x8F,0x00,0x00}
|
||||
#define ISC_CMD_READ_PAGE {0xFB,0x4A,0x00,0xC2,0x00,0x00}
|
||||
#define ISC_CMD_WRITE_PAGE {0xFB,0x4A,0x00,0xA5,0x00,0x00}
|
||||
#define ISC_CMD_PROGRAM_PAGE {0xFB,0x4A,0x00,0x54,0x00,0x00}
|
||||
#define ISC_CMD_READ_STATUS {0xFB,0x4A,0x36,0xC2,0x00,0x00}
|
||||
#define ISC_CMD_EXIT {0xFB,0x4A,0x00,0x66,0x00,0x00}
|
||||
|
||||
//ISC Status
|
||||
#define ISC_STATUS_BUSY 0x96
|
||||
#define ISC_STATUS_DONE 0xAD
|
||||
|
||||
/**
|
||||
* Read ISC status
|
||||
*/
|
||||
static int mms_isc_read_status(struct mms_ts_info *info)
|
||||
{
|
||||
struct i2c_client *client = info->client;
|
||||
u8 cmd[6] = ISC_CMD_READ_STATUS;
|
||||
u8 result = 0;
|
||||
int cnt = 100;
|
||||
int ret = 0;
|
||||
struct i2c_msg msg[2] = {
|
||||
{
|
||||
.addr = client->addr,
|
||||
.flags = 0,
|
||||
.buf = cmd,
|
||||
.len = 6,
|
||||
}, {
|
||||
.addr = client->addr,
|
||||
.flags = I2C_M_RD,
|
||||
.buf = &result,
|
||||
.len = 1,
|
||||
},
|
||||
};
|
||||
|
||||
tsp_debug_dbg(true, &info->client->dev, "%s [START]\n", __func__);
|
||||
|
||||
do {
|
||||
if (i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg))!=ARRAY_SIZE(msg)) {
|
||||
tsp_debug_err(true, &info->client->dev, "%s [ERROR] i2c_transfer\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (result == ISC_STATUS_DONE) {
|
||||
ret = 0;
|
||||
break;
|
||||
} else if (result == ISC_STATUS_BUSY) {
|
||||
ret = -1;
|
||||
msleep(1);
|
||||
} else {
|
||||
tsp_debug_err(true, &info->client->dev, "%s [ERROR] wrong value [0x%02X]\n",
|
||||
__func__, result);
|
||||
ret = -1;
|
||||
msleep(1);
|
||||
}
|
||||
} while (--cnt);
|
||||
|
||||
if (!cnt) {
|
||||
tsp_debug_err(true, &info->client->dev,
|
||||
"%s [ERROR] count overflow - cnt [%d] status [0x%02X]\n",
|
||||
__func__, cnt, result);
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
tsp_debug_dbg(true, &info->client->dev, "%s [DONE]\n", __func__);
|
||||
|
||||
return ret;
|
||||
|
||||
ERROR:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Command : Erase Page
|
||||
*/
|
||||
static int mms_isc_erase_page(struct mms_ts_info *info, int offset)
|
||||
{
|
||||
u8 write_buf[6] =ISC_CMD_ERASE_PAGE;
|
||||
|
||||
struct i2c_msg msg[1] = {
|
||||
{
|
||||
.addr = info->client->addr,
|
||||
.flags = 0,
|
||||
.buf = write_buf,
|
||||
.len = 6,
|
||||
},
|
||||
};
|
||||
|
||||
tsp_debug_dbg(true, &info->client->dev, "%s [START]\n", __func__);
|
||||
|
||||
write_buf[4] = (u8)(((offset)>>8) & 0xFF);
|
||||
write_buf[5] = (u8)(((offset)>>0) & 0xFF);
|
||||
if (i2c_transfer(info->client->adapter, msg, ARRAY_SIZE(msg)) != ARRAY_SIZE(msg)) {
|
||||
tsp_debug_err(true, &info->client->dev, "%s [ERROR] i2c_transfer\n", __func__);
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
if (mms_isc_read_status(info) != 0) {
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
tsp_debug_dbg(true, &info->client->dev, "%s [DONE] - Offset [0x%04X]\n", __func__, offset);
|
||||
|
||||
return 0;
|
||||
|
||||
ERROR:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Command : Read Page
|
||||
*/
|
||||
static int mms_isc_read_page(struct mms_ts_info *info, int offset, u8 *data)
|
||||
{
|
||||
u8 write_buf[6] =ISC_CMD_READ_PAGE;
|
||||
|
||||
struct i2c_msg msg[2] = {
|
||||
{
|
||||
.addr = info->client->addr,
|
||||
.flags = 0,
|
||||
.buf = write_buf,
|
||||
.len = 6,
|
||||
}, {
|
||||
.addr = info->client->addr,
|
||||
.flags = I2C_M_RD,
|
||||
.buf = data,
|
||||
.len = ISC_PAGE_SIZE,
|
||||
},
|
||||
};
|
||||
|
||||
tsp_debug_dbg(true, &info->client->dev, "%s [START]\n", __func__);
|
||||
|
||||
write_buf[4] = (u8)(((offset)>>8) & 0xFF);
|
||||
write_buf[5] = (u8)(((offset)>>0) & 0xFF);
|
||||
if (i2c_transfer(info->client->adapter, msg, ARRAY_SIZE(msg)) != ARRAY_SIZE(msg)) {
|
||||
tsp_debug_err(true, &info->client->dev, "%s [ERROR] i2c_transfer\n", __func__);
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
tsp_debug_dbg(true, &info->client->dev, "%s [DONE] - Offset [0x%04X]\n", __func__, offset);
|
||||
|
||||
return 0;
|
||||
|
||||
ERROR:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Command : Program Page
|
||||
*/
|
||||
static int mms_isc_program_page(struct mms_ts_info *info, int offset,
|
||||
const u8 *data, int length)
|
||||
{
|
||||
u8 write_buf[134] = ISC_CMD_PROGRAM_PAGE;
|
||||
|
||||
tsp_debug_dbg(true, &info->client->dev, "%s [START]\n", __func__);
|
||||
|
||||
if (length > 128) {
|
||||
tsp_debug_err(true, &info->client->dev, "%s [ERROR] page length overflow\n", __func__);
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
write_buf[4] = (u8)(((offset)>>8) & 0xFF);
|
||||
write_buf[5] = (u8)(((offset)>>0) & 0xFF);
|
||||
|
||||
memcpy(&write_buf[6], data, length);
|
||||
|
||||
if (i2c_master_send(info->client, write_buf, length+6 )!=length+6) {
|
||||
tsp_debug_err(true, &info->client->dev, "%s [ERROR] i2c_master_send\n", __func__);
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
if (mms_isc_read_status(info) != 0) {
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
tsp_debug_dbg(true, &info->client->dev, "%s [DONE] - Offset[0x%04X] Length[%d]\n",
|
||||
__func__, offset, length);
|
||||
|
||||
return 0;
|
||||
|
||||
ERROR:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Command : Exit ISC
|
||||
*/
|
||||
static int mms_isc_exit(struct mms_ts_info *info)
|
||||
{
|
||||
u8 write_buf[6] = ISC_CMD_EXIT;
|
||||
|
||||
tsp_debug_dbg(true, &info->client->dev, "%s [START]\n", __func__);
|
||||
|
||||
if (i2c_master_send(info->client, write_buf, 6) != 6) {
|
||||
tsp_debug_err(true, &info->client->dev, "%s [ERROR] i2c_master_send\n", __func__);
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
tsp_debug_dbg(true, &info->client->dev, "%s [DONE]\n", __func__);
|
||||
|
||||
return 0;
|
||||
|
||||
ERROR:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flash chip firmware (main function)
|
||||
*/
|
||||
int mms_flash_fw(struct mms_ts_info *info, const u8 *fw_data,
|
||||
size_t fw_size, bool force, bool section)
|
||||
{
|
||||
|
||||
struct mms_bin_hdr *fw_hdr;
|
||||
struct mms_fw_img **img;
|
||||
struct i2c_client *client = info->client;
|
||||
int i;
|
||||
int retires = 3;
|
||||
int ret;
|
||||
int nRet;
|
||||
int nStartAddr;
|
||||
int nWriteLength;
|
||||
int nLast;
|
||||
int nOffset;
|
||||
int nTransferLength;
|
||||
int size;
|
||||
u8 *data;
|
||||
u8 *cpydata;
|
||||
|
||||
int offset = sizeof(struct mms_bin_hdr);
|
||||
|
||||
bool update_flag = false;
|
||||
bool update_flags[MMS_FW_MAX_SECT_NUM] = {false, };
|
||||
|
||||
u16 ver_chip[MMS_FW_MAX_SECT_NUM];
|
||||
u16 ver_file[MMS_FW_MAX_SECT_NUM];
|
||||
|
||||
int offsetStart = 0;
|
||||
u8 initData[ISC_PAGE_SIZE];
|
||||
memset(initData, 0xFF, sizeof(initData));
|
||||
|
||||
tsp_debug_dbg(true, &client->dev, "%s [START]\n", __func__);
|
||||
|
||||
//Read firmware file
|
||||
fw_hdr = (struct mms_bin_hdr *)fw_data;
|
||||
img = vzalloc(sizeof(*img) * fw_hdr->section_num);
|
||||
if (!img) {
|
||||
tsp_debug_err(true, &client->dev, "Failed to img allocate memory\n");
|
||||
nRet = -ENOMEM;
|
||||
goto err_alloc_img;
|
||||
}
|
||||
|
||||
|
||||
//Check firmware file
|
||||
if (memcmp(CHIP_FW_CODE, &fw_hdr->tag[4], 4)) {
|
||||
tsp_debug_err(true, &client->dev, "%s [ERROR] F/W file is not for %s\n",
|
||||
__func__, CHIP_NAME);
|
||||
|
||||
nRet = fw_err_file_type;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
//Check chip firmware version
|
||||
while (retires--) {
|
||||
if (!mms_get_fw_version_u16(info, ver_chip))
|
||||
break;
|
||||
else
|
||||
mms_reboot(info);
|
||||
}
|
||||
|
||||
if (retires < 0) {
|
||||
tsp_debug_err(true, &client->dev,
|
||||
"%s [ERROR] cannot read chip firmware version\n",__func__);
|
||||
|
||||
memset(ver_chip, 0xFFFF, sizeof(ver_chip));
|
||||
tsp_debug_dbg(true, &client->dev,
|
||||
"%s - Chip firmware version is set to [0xFFFF]\n", __func__);
|
||||
} else {
|
||||
tsp_debug_info(true, &client->dev,
|
||||
"%s - Chip firmware version [0x%04X 0x%04X 0x%04X 0x%04X]\n",
|
||||
__func__, ver_chip[0], ver_chip[1], ver_chip[2], ver_chip[3]);
|
||||
}
|
||||
|
||||
//Set update flag
|
||||
tsp_debug_info(true, &client->dev,
|
||||
"%s - Firmware file info : Sections[%d] Offset[0x%08X] Length[0x%08X]\n",
|
||||
__func__, fw_hdr->section_num, fw_hdr->binary_offset, fw_hdr->binary_length);
|
||||
|
||||
for (i = 0; i < fw_hdr->section_num; i++, offset += sizeof(struct mms_fw_img)) {
|
||||
img[i] = (struct mms_fw_img *)(fw_data + offset);
|
||||
ver_file[i] = img[i]->version;
|
||||
|
||||
tsp_debug_dbg(true, &client->dev,
|
||||
"%s - Section info : Section[%d] Version[0x%04X] StartPage[%d]"
|
||||
" EndPage[%d] Offset[0x%08X] Length[0x%08X]\n",
|
||||
__func__, i, img[i]->version, img[i]->start_page,
|
||||
img[i]->end_page,img[i]->offset, img[i]->length);
|
||||
|
||||
tsp_debug_err(true, &client->dev,
|
||||
"%s - Section[%d] IC: %04X / BIN: %04X\n",
|
||||
__func__, i, ver_chip[i], ver_file[i]);
|
||||
|
||||
//Compare section version
|
||||
if (ver_chip[i] < ver_file[i] || ver_chip[i] > ver_file[i] + 0x20) {
|
||||
//Set update flag
|
||||
update_flag = true;
|
||||
update_flags[i] = true;
|
||||
|
||||
tsp_debug_info(true, &client->dev,
|
||||
"%s - Section[%d] is need to be updated.", __func__, i);
|
||||
}
|
||||
}
|
||||
|
||||
//Set force update flag
|
||||
if (force == true) {
|
||||
update_flag = true;
|
||||
update_flags[0] = true;
|
||||
update_flags[1] = true;
|
||||
update_flags[2] = true;
|
||||
update_flags[3] = true;
|
||||
|
||||
tsp_debug_info(true, &client->dev, "%s - Force update\n", __func__);
|
||||
}
|
||||
|
||||
//Exit when up-to-date
|
||||
if (update_flag == false) {
|
||||
nRet = fw_err_uptodate;
|
||||
tsp_debug_dbg(true, &client->dev,
|
||||
"%s [DONE] Chip firmware is already up-to-date\n", __func__);
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
//Set start addr offset
|
||||
if (section == true) {
|
||||
if (update_flags[0] == true) {
|
||||
//boot
|
||||
offsetStart = img[0]->start_page;
|
||||
} else if (update_flags[1] == true) {
|
||||
//core
|
||||
offsetStart = img[1]->start_page;
|
||||
} else if (update_flags[2] == true) {
|
||||
//custom
|
||||
offsetStart = img[2]->start_page;
|
||||
} else if (update_flags[3] == true) {
|
||||
//param
|
||||
offsetStart = img[3]->start_page;
|
||||
}
|
||||
} else
|
||||
offsetStart = 0;
|
||||
|
||||
offsetStart = offsetStart * 1024;
|
||||
|
||||
//Load firmware data
|
||||
data = vzalloc(sizeof(u8) * fw_hdr->binary_length);
|
||||
if (!data) {
|
||||
tsp_debug_err(true, &client->dev, "Failed to data allocate memory\n");
|
||||
nRet = -ENOMEM;
|
||||
goto err_alloc_data;
|
||||
}
|
||||
size = fw_hdr->binary_length;
|
||||
cpydata = vzalloc(ISC_PAGE_SIZE);
|
||||
if (!cpydata) {
|
||||
tsp_debug_err(true, &client->dev, "Failed to cpydata allocate memory\n");
|
||||
nRet = -ENOMEM;
|
||||
goto err_alloc_cpydata;
|
||||
}
|
||||
|
||||
//Check firmware size
|
||||
if (size % ISC_PAGE_SIZE !=0) {
|
||||
size += ( ISC_PAGE_SIZE - (size % ISC_PAGE_SIZE) );
|
||||
}
|
||||
|
||||
nStartAddr = 0;
|
||||
nWriteLength = size;
|
||||
nLast = nStartAddr + nWriteLength;
|
||||
|
||||
if ((nLast) % 8 != 0) {
|
||||
nRet = fw_err_file_type;
|
||||
tsp_debug_err(true, &client->dev, "%s [ERROR] Firmware size mismatch\n", __func__);
|
||||
goto ERROR;
|
||||
} else
|
||||
memcpy(data,fw_data+fw_hdr->binary_offset,fw_hdr->binary_length);
|
||||
|
||||
//Set address
|
||||
nOffset = nStartAddr + nWriteLength - ISC_PAGE_SIZE;
|
||||
nTransferLength = ISC_PAGE_SIZE;
|
||||
|
||||
//Erase first page
|
||||
tsp_debug_info(true, &client->dev, "%s - Erase first page : Offset[0x%04X]\n",
|
||||
__func__, offsetStart);
|
||||
nRet = mms_isc_erase_page(info, offsetStart);
|
||||
if (nRet != 0) {
|
||||
tsp_debug_err(true, &client->dev, "%s [ERROR] clear first page failed\n", __func__);
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
//Flash firmware
|
||||
tsp_debug_info(true, &client->dev, "%s - Start Download : Offset Start[0x%04X] End[0x%04X]\n",
|
||||
__func__, nOffset, offsetStart);
|
||||
while( nOffset >= offsetStart )
|
||||
{
|
||||
tsp_debug_dbg(true, &client->dev, "%s - Downloading : Offset[0x%04X]\n", __func__, nOffset);
|
||||
|
||||
//Program (erase and write) a page
|
||||
nRet = mms_isc_program_page(info, nOffset, &data[nOffset], nTransferLength);
|
||||
if (nRet != 0) {
|
||||
tsp_debug_err(true, &client->dev, "%s [ERROR] isc_program_page\n", __func__);
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
//Verify (read and compare)
|
||||
if (mms_isc_read_page(info, nOffset, cpydata)) {
|
||||
tsp_debug_err(true, &client->dev, "%s [ERROR] mms_isc_read_page\n", __func__);
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
if (memcmp(&data[nOffset], cpydata, ISC_PAGE_SIZE)) {
|
||||
#if MMS_FW_UPDATE_DEBUG
|
||||
print_hex_dump(KERN_ERR, "Firmware Page Write : ",
|
||||
DUMP_PREFIX_OFFSET, 16, 1, data, ISC_PAGE_SIZE, false);
|
||||
print_hex_dump(KERN_ERR, "Firmware Page Read : ",
|
||||
DUMP_PREFIX_OFFSET, 16, 1, cpydata, ISC_PAGE_SIZE, false);
|
||||
#endif
|
||||
tsp_debug_err(true, &client->dev, "%s [ERROR] verify page failed\n", __func__);
|
||||
|
||||
ret = -1;
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
nOffset -= nTransferLength;
|
||||
}
|
||||
|
||||
//Exit ISC
|
||||
nRet = mms_isc_exit(info);
|
||||
if (nRet != 0) {
|
||||
tsp_debug_err(true, &client->dev, "%s [ERROR] mms_isc_exit\n", __func__);
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
//Reboot chip
|
||||
mms_reboot(info);
|
||||
|
||||
//Check chip firmware version
|
||||
if (mms_get_fw_version_u16(info, ver_chip)) {
|
||||
tsp_debug_err(true, &client->dev,
|
||||
"%s [ERROR] cannot read chip firmware version after flash\n", __func__);
|
||||
|
||||
nRet = -1;
|
||||
goto ERROR;
|
||||
} else {
|
||||
for (i = 0; i < fw_hdr->section_num; i++) {
|
||||
if (ver_chip[i] != ver_file[i]) {
|
||||
tsp_debug_err(true, &client->dev,
|
||||
"%s [ERROR] version mismatch after flash."
|
||||
" Section[%d] : Chip[0x%04X] != File[0x%04X]\n",
|
||||
__func__, i, ver_chip[i], ver_file[i]);
|
||||
|
||||
nRet = -1;
|
||||
goto ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nRet = 0;
|
||||
tsp_debug_dbg(true, &client->dev, "%s [DONE]\n", __func__);
|
||||
goto DONE;
|
||||
|
||||
ERROR:
|
||||
tsp_debug_err(true, &client->dev, "%s [ERROR]\n", __func__);
|
||||
DONE:
|
||||
vfree(cpydata);
|
||||
err_alloc_cpydata:
|
||||
vfree(data);
|
||||
err_alloc_data:
|
||||
EXIT:
|
||||
vfree(img);
|
||||
err_alloc_img:
|
||||
return nRet;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue