mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-12-30 01:46:30 -05:00
2399 lines
63 KiB
Diff
2399 lines
63 KiB
Diff
From be42c7ff1f0396484882451fd18f47144c8f1b6b Mon Sep 17 00:00:00 2001
|
|
From: Shantanu Jain <shjain@codeaurora.org>
|
|
Date: Thu, 16 Feb 2017 11:39:44 +0530
|
|
Subject: input: touchscreen: remove msg21xx mstar touch driver
|
|
|
|
Remove msg21xx mstar touch driver from the kernel code
|
|
as it has never been used in any of the recent platforms.
|
|
|
|
Change-Id: I0ac1f93d9736c402732b6c4a8d22b1bf3500e4c4
|
|
Signed-off-by: Vevek Venkatesan <vevekv@codeaurora.org>
|
|
Signed-off-by: Shantanu Jain <shjain@codeaurora.org>
|
|
---
|
|
.../bindings/input/touchscreen/msg21xx-ts.txt | 71 -
|
|
drivers/input/touchscreen/Kconfig | 11 -
|
|
drivers/input/touchscreen/Makefile | 1 -
|
|
drivers/input/touchscreen/msg21xx_ts.c | 2260 --------------------
|
|
4 files changed, 2343 deletions(-)
|
|
delete mode 100644 Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt
|
|
delete mode 100644 drivers/input/touchscreen/msg21xx_ts.c
|
|
|
|
diff --git a/Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt
|
|
deleted file mode 100644
|
|
index 7315aef..0000000
|
|
--- a/Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt
|
|
+++ /dev/null
|
|
@@ -1,71 +0,0 @@
|
|
-Mstar touch controller
|
|
-
|
|
-The mstar controller is connected to host processor
|
|
-via i2c. The controller generates interrupts when the
|
|
-user touches the panel. The host controller is expected
|
|
-to read the touch coordinates over i2c and pass the coordinates
|
|
-to the rest of the system.
|
|
-
|
|
-Required properties:
|
|
-
|
|
- - compatible : should be "mstar,msg21xx".
|
|
- - reg : i2c slave address of the device.
|
|
- - interrupt-parent : parent of interrupt.
|
|
- - interrupts : touch sample interrupt to indicate presense or release
|
|
- of fingers on the panel.
|
|
- - vdd-supply : Power supply needed to power up the device.
|
|
- - vcc_i2c-supply : Power source required to power up i2c bus.
|
|
- - mstar,irq-gpio : irq gpio which is to provide interrupts to host,
|
|
- same as "interrupts" node. It will also
|
|
- contain active low or active high information.
|
|
- - mstar,reset-gpio : reset gpio to control the reset of chip.
|
|
- - mstar,display-coords : display coords in pixels. It is a four
|
|
- tuple consisting of min x, min y, max x and
|
|
- max y values.
|
|
- - pinctrl-names : This should be defined if a target uses pinctrl framework.
|
|
- See "pinctrl" in Documentation/devicetree/bindings/pinctrl/msm-pinctrl.txt.
|
|
- Specify the names of the configs that pinctrl can install in driver.
|
|
- Following are the pinctrl configs that can be installed:
|
|
- "pmx_ts_active" : Active configuration of pins, this should specify active
|
|
- config defined in pin groups of interrupt and reset gpio.
|
|
- "pmx_ts_suspend" : Disabled configuration of pins, this should specify sleep
|
|
- config defined in pin groups of interrupt and reset gpio.
|
|
- "pmx_ts_release" : Release configuration of pins, this should specify
|
|
- release config defined in pin groups of interrupt and reset gpio.
|
|
- - mstar,num-max-touches: It defines the maximum number of touch supported by the controller.
|
|
- - mstar,hard-reset-delay-ms : hard reset delay in ms
|
|
- - mstar,post-hard-reset-delay-ms : post hard reset delay in ms
|
|
-
|
|
-Optional properties:
|
|
-
|
|
- - mstar,button-map : button map of key codes. It is a three tuple consisting of key codes.
|
|
- - mstar,panel-coords : panel coords for the chip in pixels.
|
|
- It is a four tuple consisting of min x,
|
|
- min y, max x and max y values.
|
|
- - mstar,ic-type : It defines the ic-type of the controller. Values are as folows:
|
|
- 1 -> msg2133.
|
|
- 2 -> msg21xxA.
|
|
- 3 -> msg26xxM.
|
|
-
|
|
-Example:
|
|
- i2c@78b9000 { /* BLSP1 QUP5 */
|
|
- mstar@26 {
|
|
- compatible = "mstar,msg21xx";
|
|
- reg = <0x26>;
|
|
- interrupt-parent = <&msm_gpio>;
|
|
- interrupts = <13 0x2008>;
|
|
- mstar,irq-gpio = <&msm_gpio 13 0x00000001>;
|
|
- mstar,reset-gpio = <&msm_gpio 12 0x0>;
|
|
- vdd-supply = <&pm8916_l17>;
|
|
- vcc_i2c-supply = <&pm8916_l6>;
|
|
- mstar,display-coords = <0 0 480 854>;
|
|
- pinctrl-names = "pmx_ts_active","pmx_ts_suspend";
|
|
- pinctrl-0 = <&ts_int_active &ts_reset_active>;
|
|
- pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
|
|
- mstar,button-map = <172 139 158>;
|
|
- mstar,ic-type = <2>;
|
|
- mstar,num_max_touches = <2>;
|
|
- mstar,hard-reset-delay-ms = <100>;
|
|
- mstar,post-hard-reset-delay-ms = <100>;
|
|
- };
|
|
- };
|
|
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
|
|
index 49df5e0..9044bb5 100644
|
|
--- a/drivers/input/touchscreen/Kconfig
|
|
+++ b/drivers/input/touchscreen/Kconfig
|
|
@@ -1128,17 +1128,6 @@ config TOUCHSCREEN_FT5X06_GESTURE
|
|
|
|
If unsure, say N.
|
|
|
|
-config TOUCHSCREEN_MSTAR21XX
|
|
- tristate "Mstar touchscreens"
|
|
- depends on I2C
|
|
- help
|
|
- Say Y here if you have a mstar touchscreen.
|
|
-
|
|
- If unsure, say N.
|
|
-
|
|
- To compile this driver as a module, choose M here: the
|
|
- module will be called msg21xx_ts.
|
|
-
|
|
config TOUCHSCREEN_ROHM_BU21023
|
|
tristate "ROHM BU21023/24 Dual touch support resistive touchscreens"
|
|
depends on I2C
|
|
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
|
|
index 06953a6..1b6844b 100644
|
|
--- a/drivers/input/touchscreen/Makefile
|
|
+++ b/drivers/input/touchscreen/Makefile
|
|
@@ -98,5 +98,4 @@ obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
|
|
obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o
|
|
obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o
|
|
obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o
|
|
-obj-$(CONFIG_TOUCHSCREEN_MSTAR21XX) += msg21xx_ts.o
|
|
obj-$(CONFIG_TOUCHSCREEN_GT9XX) += gt9xx/
|
|
diff --git a/drivers/input/touchscreen/msg21xx_ts.c b/drivers/input/touchscreen/msg21xx_ts.c
|
|
deleted file mode 100644
|
|
index fe8c6e164..0000000
|
|
--- a/drivers/input/touchscreen/msg21xx_ts.c
|
|
+++ /dev/null
|
|
@@ -1,2260 +0,0 @@
|
|
-/*
|
|
- * MStar MSG21XX touchscreen driver
|
|
- *
|
|
- * Copyright (c) 2006-2012 MStar Semiconductor, Inc.
|
|
- *
|
|
- * Copyright (C) 2012 Bruce Ding <bruce.ding@mstarsemi.com>
|
|
- *
|
|
- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
|
|
- *
|
|
- * 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.
|
|
- */
|
|
-
|
|
-#include <linux/module.h>
|
|
-#include <linux/kernel.h>
|
|
-#include <linux/input.h>
|
|
-#include <linux/input/mt.h>
|
|
-#include <linux/interrupt.h>
|
|
-#include <linux/i2c.h>
|
|
-#include <linux/gpio.h>
|
|
-#include <linux/of_gpio.h>
|
|
-#include <linux/sysfs.h>
|
|
-#include <linux/init.h>
|
|
-#include <linux/mutex.h>
|
|
-#include <linux/delay.h>
|
|
-#include <linux/firmware.h>
|
|
-#include <linux/debugfs.h>
|
|
-#include <linux/regulator/consumer.h>
|
|
-
|
|
-#if defined(CONFIG_FB)
|
|
-#include <linux/notifier.h>
|
|
-#include <linux/fb.h>
|
|
-#endif
|
|
-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
|
|
-#include <linux/input/vir_ps.h>
|
|
-#endif
|
|
-
|
|
-/* Macro Definition */
|
|
-
|
|
-#define TOUCH_DRIVER_DEBUG 0
|
|
-#if (TOUCH_DRIVER_DEBUG == 1)
|
|
-#define DBG(fmt, arg...) pr_info(fmt, ##arg)
|
|
-#else
|
|
-#define DBG(fmt, arg...)
|
|
-#endif
|
|
-
|
|
-/* Constant Value & Variable Definition */
|
|
-
|
|
-#define MSTAR_VTG_MIN_UV 2800000
|
|
-#define MSTAR_VTG_MAX_UV 3300000
|
|
-#define MSTAR_I2C_VTG_MIN_UV 1800000
|
|
-#define MSTAR_I2C_VTG_MAX_UV 1800000
|
|
-
|
|
-#define MAX_BUTTONS 4
|
|
-#define FT_COORDS_ARR_SIZE 4
|
|
-#define MSTAR_FW_NAME_MAX_LEN 50
|
|
-
|
|
-#define MSTAR_CHIPTOP_REGISTER_BANK 0x1E
|
|
-#define MSTAR_CHIPTOP_REGISTER_ICTYPE 0xCC
|
|
-#define MSTAR_INIT_SW_ID 0x7FF
|
|
-#define MSTAR_DEBUG_DIR_NAME "ts_debug"
|
|
-
|
|
-#define MSG_FW_FILE_MAJOR_VERSION(x) \
|
|
- (((x)->data[0x7f4f] << 8) + ((x)->data[0x7f4e]))
|
|
-
|
|
-#define MSG_FW_FILE_MINOR_VERSION(x) \
|
|
- (((x)->data[0x7f51] << 8) + ((x)->data[0x7f50]))
|
|
-
|
|
-/*
|
|
- * Note.
|
|
- * Please do not change the below setting.
|
|
- */
|
|
-#define TPD_WIDTH (2048)
|
|
-#define TPD_HEIGHT (2048)
|
|
-
|
|
-#ifdef FIRMWARE_AUTOUPDATE
|
|
-enum {
|
|
- SWID_START = 1,
|
|
- SWID_TRULY = SWID_START,
|
|
- SWID_NULL,
|
|
-};
|
|
-
|
|
-static unsigned char MSG_FIRMWARE[1][33*1024] = { {
|
|
- #include "msg21xx_truly_update_bin.h"
|
|
- }
|
|
-};
|
|
-#endif
|
|
-
|
|
-#define CONFIG_TP_HAVE_KEY
|
|
-#define PINCTRL_STATE_ACTIVE "pmx_ts_active"
|
|
-#define PINCTRL_STATE_SUSPEND "pmx_ts_suspend"
|
|
-#define PINCTRL_STATE_RELEASE "pmx_ts_release"
|
|
-
|
|
-#define SLAVE_I2C_ID_DBBUS (0xC4>>1)
|
|
-
|
|
-#define DEMO_MODE_PACKET_LENGTH (8)
|
|
-
|
|
-#define TP_PRINT
|
|
-
|
|
-static char *fw_version; /* customer firmware version */
|
|
-static unsigned short fw_version_major;
|
|
-static unsigned short fw_version_minor;
|
|
-static unsigned char temp[94][1024];
|
|
-static unsigned int crc32_table[256];
|
|
-
|
|
-static unsigned short fw_file_major, fw_file_minor;
|
|
-static unsigned short main_sw_id = MSTAR_INIT_SW_ID;
|
|
-static unsigned short info_sw_id = MSTAR_INIT_SW_ID;
|
|
-static unsigned int bin_conf_crc32;
|
|
-
|
|
-struct msg21xx_ts_platform_data {
|
|
- const char *name;
|
|
- char fw_name[MSTAR_FW_NAME_MAX_LEN];
|
|
- u8 fw_version_major;
|
|
- u8 fw_version_minor;
|
|
- u32 irq_gpio;
|
|
- u32 irq_gpio_flags;
|
|
- u32 reset_gpio;
|
|
- u32 reset_gpio_flags;
|
|
- u32 x_max;
|
|
- u32 y_max;
|
|
- u32 x_min;
|
|
- u32 y_min;
|
|
- u32 panel_minx;
|
|
- u32 panel_miny;
|
|
- u32 panel_maxx;
|
|
- u32 panel_maxy;
|
|
- u32 num_max_touches;
|
|
- bool no_force_update;
|
|
- bool i2c_pull_up;
|
|
- bool ignore_id_check;
|
|
- int (*power_init)(bool);
|
|
- int (*power_on)(bool);
|
|
- int (*power_init)(bool);
|
|
- int (*power_on)(bool);
|
|
- u8 ic_type;
|
|
- u32 button_map[MAX_BUTTONS];
|
|
- u32 num_buttons;
|
|
- u32 hard_reset_delay_ms;
|
|
- u32 post_hard_reset_delay_ms;
|
|
- bool updating_fw;
|
|
-};
|
|
-
|
|
-/* Touch Data Type Definition */
|
|
-struct touchPoint_t {
|
|
- unsigned short x;
|
|
- unsigned short y;
|
|
-};
|
|
-
|
|
-struct touchInfo_t {
|
|
- struct touchPoint_t *point;
|
|
- unsigned char count;
|
|
- unsigned char keycode;
|
|
-};
|
|
-
|
|
-struct msg21xx_ts_data {
|
|
- struct i2c_client *client;
|
|
- struct input_dev *input_dev;
|
|
- struct msg21xx_ts_platform_data *pdata;
|
|
- struct regulator *vdd;
|
|
- struct regulator *vcc_i2c;
|
|
- bool suspended;
|
|
-#if defined(CONFIG_FB)
|
|
- struct notifier_block fb_notif;
|
|
-#endif
|
|
- struct pinctrl *ts_pinctrl;
|
|
- struct pinctrl_state *pinctrl_state_active;
|
|
- struct pinctrl_state *pinctrl_state_suspend;
|
|
- struct pinctrl_state *pinctrl_state_release;
|
|
- struct mutex ts_mutex;
|
|
- struct touchInfo_t info;
|
|
-};
|
|
-
|
|
-#if defined(CONFIG_FB)
|
|
-static int fb_notifier_callback(struct notifier_block *self,
|
|
- unsigned long event, void *data);
|
|
-#endif
|
|
-
|
|
-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
|
|
-static unsigned char bEnableTpProximity;
|
|
-static unsigned char bFaceClosingTp;
|
|
-#endif
|
|
-
|
|
-#ifdef TP_PRINT
|
|
-static int tp_print_proc_read(struct msg21xx_ts_data *ts_data);
|
|
-static void tp_print_create_entry(struct msg21xx_ts_data *ts_data);
|
|
-#endif
|
|
-
|
|
-static void _ReadBinConfig(struct msg21xx_ts_data *ts_data);
|
|
-static unsigned int _CalMainCRC32(struct msg21xx_ts_data *ts_data);
|
|
-
|
|
-static struct mutex msg21xx_mutex;
|
|
-
|
|
-enum EMEM_TYPE_t {
|
|
- EMEM_ALL = 0,
|
|
- EMEM_MAIN,
|
|
- EMEM_INFO,
|
|
-};
|
|
-
|
|
-/* Function Definition */
|
|
-
|
|
-static unsigned int _CRC_doReflect(unsigned int ref, signed char ch)
|
|
-{
|
|
- unsigned int value = 0;
|
|
- unsigned int i = 0;
|
|
-
|
|
- for (i = 1; i < (ch + 1); i++) {
|
|
- if (ref & 1)
|
|
- value |= 1 << (ch - i);
|
|
- ref >>= 1;
|
|
- }
|
|
-
|
|
- return value;
|
|
-}
|
|
-
|
|
-static unsigned int _CRC_getValue(unsigned int text, unsigned int prevCRC)
|
|
-{
|
|
- unsigned int ulCRC = prevCRC;
|
|
-
|
|
- ulCRC = (ulCRC >> 8) ^ crc32_table[(ulCRC & 0xFF) ^ text];
|
|
-
|
|
- return ulCRC;
|
|
-}
|
|
-
|
|
-static void _CRC_initTable(void)
|
|
-{
|
|
- unsigned int magic_number = 0x04c11db7;
|
|
- unsigned int i, j;
|
|
-
|
|
- for (i = 0; i <= 0xFF; i++) {
|
|
- crc32_table[i] = _CRC_doReflect(i, 8) << 24;
|
|
- for (j = 0; j < 8; j++)
|
|
- crc32_table[i] = (crc32_table[i] << 1) ^
|
|
- (crc32_table[i] & (0x80000000L) ?
|
|
- magic_number : 0);
|
|
- crc32_table[i] = _CRC_doReflect(crc32_table[i], 32);
|
|
- }
|
|
-}
|
|
-
|
|
-static void msg21xx_reset_hw(struct msg21xx_ts_platform_data *pdata)
|
|
-{
|
|
- gpio_direction_output(pdata->reset_gpio, 1);
|
|
- gpio_set_value_cansleep(pdata->reset_gpio, 0);
|
|
- /* Note that the RST must be in LOW 10ms at least */
|
|
- usleep(pdata->hard_reset_delay_ms * 1000);
|
|
- gpio_set_value_cansleep(pdata->reset_gpio, 1);
|
|
- /* Enable the interrupt service thread/routine for INT after 50ms */
|
|
- usleep(pdata->post_hard_reset_delay_ms * 1000);
|
|
-}
|
|
-
|
|
-static int read_i2c_seq(struct msg21xx_ts_data *ts_data, unsigned char addr,
|
|
- unsigned char *buf, unsigned short size)
|
|
-{
|
|
- int rc = 0;
|
|
- struct i2c_msg msgs[] = {
|
|
- {
|
|
- .addr = addr,
|
|
- .flags = I2C_M_RD, /* read flag */
|
|
- .len = size,
|
|
- .buf = buf,
|
|
- },
|
|
- };
|
|
-
|
|
- /* If everything went ok (i.e. 1 msg transmitted), return #bytes
|
|
- * transmitted, else error code.
|
|
- */
|
|
- if (ts_data->client != NULL) {
|
|
- rc = i2c_transfer(ts_data->client->adapter, msgs, 1);
|
|
- if (rc < 0)
|
|
- dev_err(&ts_data->client->dev,
|
|
- "%s error %d\n", __func__, rc);
|
|
- } else {
|
|
- dev_err(&ts_data->client->dev, "ts_data->client is NULL\n");
|
|
- }
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int write_i2c_seq(struct msg21xx_ts_data *ts_data, unsigned char addr,
|
|
- unsigned char *buf, unsigned short size)
|
|
-{
|
|
- int rc = 0;
|
|
- struct i2c_msg msgs[] = {
|
|
- {
|
|
- .addr = addr,
|
|
- /*
|
|
- * if read flag is undefined,
|
|
- * then it means write flag.
|
|
- */
|
|
- .flags = 0,
|
|
- .len = size,
|
|
- .buf = buf,
|
|
- },
|
|
- };
|
|
-
|
|
- /*
|
|
- * If everything went ok (i.e. 1 msg transmitted), return #bytes
|
|
- * transmitted, else error code.
|
|
- */
|
|
- if (ts_data->client != NULL) {
|
|
- rc = i2c_transfer(ts_data->client->adapter, msgs, 1);
|
|
- if (rc < 0)
|
|
- dev_err(&ts_data->client->dev,
|
|
- "%s error %d\n", __func__, rc);
|
|
- } else {
|
|
- dev_err(&ts_data->client->dev, "ts_data->client is NULL\n");
|
|
- }
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static unsigned short read_reg(struct msg21xx_ts_data *ts_data,
|
|
- unsigned char bank, unsigned char addr)
|
|
-{
|
|
- unsigned char tx_data[3] = {0x10, bank, addr};
|
|
- unsigned char rx_data[2] = {0};
|
|
-
|
|
- write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, tx_data, sizeof(tx_data));
|
|
- read_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, rx_data, sizeof(rx_data));
|
|
-
|
|
- return rx_data[1] << 8 | rx_data[0];
|
|
-}
|
|
-
|
|
-static void write_reg(struct msg21xx_ts_data *ts_data, unsigned char bank,
|
|
- unsigned char addr,
|
|
- unsigned short data)
|
|
-{
|
|
- unsigned char tx_data[5] = {0x10, bank, addr, data & 0xFF, data >> 8};
|
|
-
|
|
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 5);
|
|
- write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, tx_data, sizeof(tx_data));
|
|
-}
|
|
-
|
|
-static void write_reg_8bit(struct msg21xx_ts_data *ts_data, unsigned char bank,
|
|
- unsigned char addr,
|
|
- unsigned char data)
|
|
-{
|
|
- unsigned char tx_data[4] = {0x10, bank, addr, data};
|
|
-
|
|
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 4);
|
|
- write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, tx_data, sizeof(tx_data));
|
|
-}
|
|
-
|
|
-static void dbbusDWIICEnterSerialDebugMode(struct msg21xx_ts_data *ts_data)
|
|
-{
|
|
- unsigned char data[5];
|
|
-
|
|
- /* Enter the Serial Debug Mode */
|
|
- data[0] = 0x53;
|
|
- data[1] = 0x45;
|
|
- data[2] = 0x52;
|
|
- data[3] = 0x44;
|
|
- data[4] = 0x42;
|
|
-
|
|
- write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, data, sizeof(data));
|
|
-}
|
|
-
|
|
-static void dbbusDWIICStopMCU(struct msg21xx_ts_data *ts_data)
|
|
-{
|
|
- unsigned char data[1];
|
|
-
|
|
- /* Stop the MCU */
|
|
- data[0] = 0x37;
|
|
-
|
|
- write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, data, sizeof(data));
|
|
-}
|
|
-
|
|
-static void dbbusDWIICIICUseBus(struct msg21xx_ts_data *ts_data)
|
|
-{
|
|
- unsigned char data[1];
|
|
-
|
|
- /* IIC Use Bus */
|
|
- data[0] = 0x35;
|
|
-
|
|
- write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, data, sizeof(data));
|
|
-}
|
|
-
|
|
-static void dbbusDWIICIICReshape(struct msg21xx_ts_data *ts_data)
|
|
-{
|
|
- unsigned char data[1];
|
|
-
|
|
- /* IIC Re-shape */
|
|
- data[0] = 0x71;
|
|
-
|
|
- write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, data, sizeof(data));
|
|
-}
|
|
-
|
|
-static unsigned char msg21xx_get_ic_type(struct msg21xx_ts_data *ts_data)
|
|
-{
|
|
- unsigned char ic_type = 0;
|
|
- unsigned char bank;
|
|
- unsigned char addr;
|
|
-
|
|
- msg21xx_reset_hw(ts_data->pdata);
|
|
- dbbusDWIICEnterSerialDebugMode(ts_data);
|
|
- dbbusDWIICStopMCU(ts_data);
|
|
- dbbusDWIICIICUseBus(ts_data);
|
|
- dbbusDWIICIICReshape(ts_data);
|
|
- msleep(300);
|
|
-
|
|
- /* stop mcu */
|
|
- write_reg_8bit(ts_data, 0x0F, 0xE6, 0x01);
|
|
- /* disable watch dog */
|
|
- write_reg(ts_data, 0x3C, 0x60, 0xAA55);
|
|
- /* get ic type */
|
|
- bank = MSTAR_CHIPTOP_REGISTER_BANK;
|
|
- addr = MSTAR_CHIPTOP_REGISTER_ICTYPE;
|
|
- ic_type = (0xff)&(read_reg(ts_data, bank, addr));
|
|
-
|
|
- if (ic_type != ts_data->pdata->ic_type)
|
|
- ic_type = 0;
|
|
-
|
|
- msg21xx_reset_hw(ts_data->pdata);
|
|
-
|
|
- return ic_type;
|
|
-}
|
|
-
|
|
-static int msg21xx_read_firmware_id(struct msg21xx_ts_data *ts_data)
|
|
-{
|
|
- unsigned char command[3] = { 0x53, 0x00, 0x2A};
|
|
- unsigned char response[4] = { 0 };
|
|
-
|
|
- mutex_lock(&msg21xx_mutex);
|
|
- write_i2c_seq(ts_data, ts_data->client->addr, command, sizeof(command));
|
|
- read_i2c_seq(ts_data, ts_data->client->addr, response,
|
|
- sizeof(response));
|
|
- mutex_unlock(&msg21xx_mutex);
|
|
- ts_data->pdata->fw_version_major = (response[1]<<8) + response[0];
|
|
- ts_data->pdata->fw_version_minor = (response[3]<<8) + response[2];
|
|
-
|
|
- dev_info(&ts_data->client->dev, "major num = %d, minor num = %d\n",
|
|
- ts_data->pdata->fw_version_major,
|
|
- ts_data->pdata->fw_version_minor);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int firmware_erase_c33(struct msg21xx_ts_data *ts_data,
|
|
- enum EMEM_TYPE_t emem_type)
|
|
-{
|
|
- /* stop mcu */
|
|
- write_reg(ts_data, 0x0F, 0xE6, 0x0001);
|
|
-
|
|
- /* disable watch dog */
|
|
- write_reg_8bit(ts_data, 0x3C, 0x60, 0x55);
|
|
- write_reg_8bit(ts_data, 0x3C, 0x61, 0xAA);
|
|
-
|
|
- /* set PROGRAM password */
|
|
- write_reg_8bit(ts_data, 0x16, 0x1A, 0xBA);
|
|
- write_reg_8bit(ts_data, 0x16, 0x1B, 0xAB);
|
|
-
|
|
- write_reg_8bit(ts_data, 0x16, 0x18, 0x80);
|
|
-
|
|
- if (emem_type == EMEM_ALL)
|
|
- write_reg_8bit(ts_data, 0x16, 0x08, 0x10);
|
|
-
|
|
- write_reg_8bit(ts_data, 0x16, 0x18, 0x40);
|
|
- msleep(20);
|
|
-
|
|
- /* clear pce */
|
|
- write_reg_8bit(0x16, 0x18, 0x80);
|
|
-
|
|
- /* erase trigger */
|
|
- if (emem_type == EMEM_MAIN)
|
|
- write_reg_8bit(ts_data, 0x16, 0x0E, 0x04); /* erase main */
|
|
- else
|
|
- write_reg_8bit(0x16, 0x0E, 0x08); /* erase all block */
|
|
-
|
|
- return 1;
|
|
-}
|
|
-
|
|
-static void _ReadBinConfig(void);
|
|
-static unsigned int _CalMainCRC32(void);
|
|
-
|
|
-static int check_fw_update(void)
|
|
-{
|
|
- int ret = 0;
|
|
-
|
|
- msg21xx_read_firmware_id();
|
|
- _ReadBinConfig();
|
|
- if (main_sw_id == info_sw_id) {
|
|
- if (_CalMainCRC32() == bin_conf_crc32) {
|
|
- /*check upgrading*/
|
|
- if ((update_bin_major == pdata->fw_version_major) &&
|
|
- (update_bin_minor > pdata->fw_version_minor)) {
|
|
- ret = 1;
|
|
- }
|
|
- }
|
|
- }
|
|
- return ret;
|
|
- write_reg_8bit(ts_data, 0x16, 0x0E, 0x08); /* erase all block */
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static ssize_t firmware_update_c33(struct device *dev,
|
|
- struct device_attribute *attr,
|
|
- const char *buf, size_t size,
|
|
- enum EMEM_TYPE_t emem_type,
|
|
- bool isForce) {
|
|
- unsigned int i, j;
|
|
- unsigned int crc_main, crc_main_tp;
|
|
- unsigned int crc_info, crc_info_tp;
|
|
- unsigned short reg_data = 0;
|
|
- int update_pass = 1;
|
|
- bool fw_upgrade = false;
|
|
- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
|
|
-
|
|
- crc_main = 0xffffffff;
|
|
- crc_info = 0xffffffff;
|
|
-
|
|
- msg21xx_reset_hw(ts_data->pdata);
|
|
-
|
|
- msg21xx_read_firmware_id(ts_data);
|
|
- _ReadBinConfig(ts_data);
|
|
- if ((main_sw_id == info_sw_id) &&
|
|
- (_CalMainCRC32(ts_data) == bin_conf_crc32) &&
|
|
- (fw_file_major == ts_data->pdata->fw_version_major) &&
|
|
- (fw_file_minor > ts_data->pdata->fw_version_minor)) {
|
|
- fw_upgrade = true;
|
|
- }
|
|
-
|
|
- if (!fw_upgrade && !isForce) {
|
|
- dev_dbg(dev, "no need to update\n");
|
|
- msg21xx_reset_hw(ts_data->pdata);
|
|
- return size;
|
|
- }
|
|
- msg21xx_reset_hw(ts_data->pdata);
|
|
- msleep(300);
|
|
-
|
|
- dbbusDWIICEnterSerialDebugMode(ts_data);
|
|
- dbbusDWIICStopMCU(ts_data);
|
|
- dbbusDWIICIICUseBus(ts_data);
|
|
- dbbusDWIICIICReshape(ts_data);
|
|
- msleep(300);
|
|
-
|
|
- /* erase main */
|
|
- firmware_erase_c33(ts_data, EMEM_MAIN);
|
|
- msleep(1000);
|
|
-
|
|
- msg21xx_reset_hw(ts_data->pdata);
|
|
- dbbusDWIICEnterSerialDebugMode(ts_data);
|
|
- dbbusDWIICStopMCU(ts_data);
|
|
- dbbusDWIICIICUseBus(ts_data);
|
|
- dbbusDWIICIICReshape(ts_data);
|
|
- msleep(300);
|
|
- /*
|
|
- * Program
|
|
- */
|
|
- /* polling 0x3CE4 is 0x1C70 */
|
|
- if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
|
|
- do {
|
|
- reg_data = read_reg(ts_data, 0x3C, 0xE4);
|
|
- } while (reg_data != 0x1C70);
|
|
- }
|
|
-
|
|
- switch (emem_type) {
|
|
- case EMEM_ALL:
|
|
- write_reg(ts_data, 0x3C, 0xE4, 0xE38F); /* for all-blocks */
|
|
- break;
|
|
- case EMEM_MAIN:
|
|
- write_reg(ts_data, 0x3C, 0xE4, 0x7731); /* for main block */
|
|
- break;
|
|
- case EMEM_INFO:
|
|
- write_reg(ts_data, 0x3C, 0xE4, 0x7731); /* for info block */
|
|
-
|
|
- write_reg_8bit(ts_data, 0x0F, 0xE6, 0x01);
|
|
-
|
|
- write_reg_8bit(ts_data, 0x3C, 0xE4, 0xC5);
|
|
- write_reg_8bit(ts_data, 0x3C, 0xE5, 0x78);
|
|
-
|
|
- write_reg_8bit(ts_data, MSTAR_CHIPTOP_REGISTER_BANK,
|
|
- 0x04, 0x9F);
|
|
- write_reg_8bit(ts_data, MSTAR_CHIPTOP_REGISTER_BANK,
|
|
- 0x05, 0x82);
|
|
-
|
|
- write_reg_8bit(ts_data, 0x0F, 0xE6, 0x00);
|
|
- msleep(100);
|
|
- break;
|
|
- }
|
|
-
|
|
- /* polling 0x3CE4 is 0x2F43 */
|
|
- do {
|
|
- reg_data = read_reg(ts_data, 0x3C, 0xE4);
|
|
- } while (reg_data != 0x2F43);
|
|
-
|
|
- /* calculate CRC 32 */
|
|
- _CRC_initTable();
|
|
-
|
|
- /* total 32 KB : 2 byte per R/W */
|
|
- for (i = 0; i < 32; i++) {
|
|
- if (i == 31) {
|
|
- fw_bin_data[i][1014] = 0x5A;
|
|
- fw_bin_data[i][1015] = 0xA5;
|
|
-
|
|
- for (j = 0; j < 1016; j++)
|
|
- crc_main = _CRC_getValue(fw_bin_data[i][j],
|
|
- crc_main);
|
|
- } else {
|
|
- for (j = 0; j < 1024; j++)
|
|
- crc_main = _CRC_getValue(fw_bin_data[i][j],
|
|
- crc_main);
|
|
- }
|
|
-
|
|
- for (j = 0; j < 8; j++)
|
|
- write_i2c_seq(ts_data, ts_data->client->addr,
|
|
- &fw_bin_data[i][j * 128], 128);
|
|
- msleep(100);
|
|
-
|
|
- /* polling 0x3CE4 is 0xD0BC */
|
|
- do {
|
|
- reg_data = read_reg(ts_data, 0x3C, 0xE4);
|
|
- } while (reg_data != 0xD0BC);
|
|
-
|
|
- write_reg(ts_data, 0x3C, 0xE4, 0x2F43);
|
|
- }
|
|
-
|
|
- if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
|
|
- /* write file done and check crc */
|
|
- write_reg(ts_data, 0x3C, 0xE4, 0x1380);
|
|
- }
|
|
- msleep(20);
|
|
-
|
|
- if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
|
|
- /* polling 0x3CE4 is 0x9432 */
|
|
- do {
|
|
- reg_data = read_reg(ts_data, 0x3C, 0xE4);
|
|
- } while (reg_data != 0x9432);
|
|
- }
|
|
-
|
|
- crc_main = crc_main ^ 0xffffffff;
|
|
- crc_info = crc_info ^ 0xffffffff;
|
|
-
|
|
- if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
|
|
- /* CRC Main from TP */
|
|
- crc_main_tp = read_reg(ts_data, 0x3C, 0x80);
|
|
- crc_main_tp = (crc_main_tp << 16) |
|
|
- read_reg(ts_data, 0x3C, 0x82);
|
|
-
|
|
- /* CRC Info from TP */
|
|
- crc_info_tp = read_reg(ts_data, 0x3C, 0xA0);
|
|
- crc_info_tp = (crc_info_tp << 16) |
|
|
- read_reg(ts_data, 0x3C, 0xA2);
|
|
- }
|
|
-
|
|
- update_pass = 1;
|
|
- if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
|
|
- if (crc_main_tp != crc_main)
|
|
- update_pass = 0;
|
|
- }
|
|
-
|
|
- if (!update_pass) {
|
|
- dev_err(dev, "update_C33 failed\n");
|
|
- msg21xx_reset_hw(ts_data->pdata);
|
|
- return 0;
|
|
- }
|
|
-
|
|
- dev_dbg(dev, "update_C33 OK\n");
|
|
- msg21xx_reset_hw(ts_data->pdata);
|
|
- return size;
|
|
-}
|
|
-
|
|
-static unsigned int _CalMainCRC32(struct msg21xx_ts_data *ts_data)
|
|
-{
|
|
- unsigned int ret = 0;
|
|
- unsigned short reg_data = 0;
|
|
-
|
|
- msg21xx_reset_hw(ts_data->pdata);
|
|
-
|
|
- dbbusDWIICEnterSerialDebugMode(ts_data);
|
|
- dbbusDWIICStopMCU(ts_data);
|
|
- dbbusDWIICIICUseBus(ts_data);
|
|
- dbbusDWIICIICReshape(ts_data);
|
|
- msleep(100);
|
|
-
|
|
- /* Stop MCU */
|
|
- write_reg(ts_data, 0x0F, 0xE6, 0x0001);
|
|
-
|
|
- /* Stop Watchdog */
|
|
- write_reg_8bit(ts_data, 0x3C, 0x60, 0x55);
|
|
- write_reg_8bit(ts_data, 0x3C, 0x61, 0xAA);
|
|
-
|
|
- /* cmd */
|
|
- write_reg(ts_data, 0x3C, 0xE4, 0xDF4C);
|
|
- write_reg(ts_data, MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x7d60);
|
|
- /* TP SW reset */
|
|
- write_reg(ts_data, MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x829F);
|
|
-
|
|
- /* MCU run */
|
|
- write_reg(ts_data, 0x0F, 0xE6, 0x0000);
|
|
-
|
|
- /* polling 0x3CE4 */
|
|
- do {
|
|
- reg_data = read_reg(ts_data, 0x3C, 0xE4);
|
|
- } while (reg_data != 0x9432);
|
|
-
|
|
- /* Cal CRC Main from TP */
|
|
- ret = read_reg(ts_data, 0x3C, 0x80);
|
|
- ret = (ret << 16) | read_reg(ts_data, 0x3C, 0x82);
|
|
-
|
|
- dev_dbg(&ts_data->client->dev,
|
|
- "[21xxA]:Current main crc32=0x%x\n", ret);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-static void _ReadBinConfig(struct msg21xx_ts_data *ts_data)
|
|
-{
|
|
- unsigned char dbbus_tx_data[5] = {0};
|
|
- unsigned char dbbus_rx_data[4] = {0};
|
|
- unsigned short reg_data = 0;
|
|
-
|
|
- msg21xx_reset_hw(ts_data->pdata);
|
|
-
|
|
- dbbusDWIICEnterSerialDebugMode(ts_data);
|
|
- dbbusDWIICStopMCU(ts_data);
|
|
- dbbusDWIICIICUseBus(ts_data);
|
|
- dbbusDWIICIICReshape(ts_data);
|
|
- msleep(100);
|
|
-
|
|
- /* Stop MCU */
|
|
- write_reg(ts_data, 0x0F, 0xE6, 0x0001);
|
|
-
|
|
- /* Stop Watchdog */
|
|
- write_reg_8bit(ts_data, 0x3C, 0x60, 0x55);
|
|
- write_reg_8bit(ts_data, 0x3C, 0x61, 0xAA);
|
|
-
|
|
- /* cmd */
|
|
- write_reg(ts_data, 0x3C, 0xE4, 0xA4AB);
|
|
- write_reg(ts_data, MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x7d60);
|
|
-
|
|
- /* TP SW reset */
|
|
- write_reg(ts_data, MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x829F);
|
|
-
|
|
- /* MCU run */
|
|
- write_reg(ts_data, 0x0F, 0xE6, 0x0000);
|
|
-
|
|
- /* polling 0x3CE4 */
|
|
- do {
|
|
- reg_data = read_reg(ts_data, 0x3C, 0xE4);
|
|
- } while (reg_data != 0x5B58);
|
|
-
|
|
- dbbus_tx_data[0] = 0x72;
|
|
- dbbus_tx_data[1] = 0x7F;
|
|
- dbbus_tx_data[2] = 0x55;
|
|
- dbbus_tx_data[3] = 0x00;
|
|
- dbbus_tx_data[4] = 0x04;
|
|
- write_i2c_seq(ts_data, ts_data->client->addr, &dbbus_tx_data[0], 5);
|
|
- read_i2c_seq(ts_data, ts_data->client->addr, &dbbus_rx_data[0], 4);
|
|
- if ((dbbus_rx_data[0] >= 0x30 && dbbus_rx_data[0] <= 0x39)
|
|
- && (dbbus_rx_data[1] >= 0x30 && dbbus_rx_data[1] <= 0x39)
|
|
- && (dbbus_rx_data[2] >= 0x31 && dbbus_rx_data[2] <= 0x39)) {
|
|
- main_sw_id = (dbbus_rx_data[0] - 0x30) * 100 +
|
|
- (dbbus_rx_data[1] - 0x30) * 10 +
|
|
- (dbbus_rx_data[2] - 0x30);
|
|
- }
|
|
-
|
|
- dbbus_tx_data[0] = 0x72;
|
|
- dbbus_tx_data[1] = 0x7F;
|
|
- dbbus_tx_data[2] = 0xFC;
|
|
- dbbus_tx_data[3] = 0x00;
|
|
- dbbus_tx_data[4] = 0x04;
|
|
- write_i2c_seq(ts_data, ts_data->client->addr, &dbbus_tx_data[0], 5);
|
|
- read_i2c_seq(ts_data, ts_data->client->addr, &dbbus_rx_data[0], 4);
|
|
- bin_conf_crc32 = (dbbus_rx_data[0] << 24) |
|
|
- (dbbus_rx_data[1] << 16) |
|
|
- (dbbus_rx_data[2] << 8) |
|
|
- (dbbus_rx_data[3]);
|
|
-
|
|
- dbbus_tx_data[0] = 0x72;
|
|
- dbbus_tx_data[1] = 0x83;
|
|
- dbbus_tx_data[2] = 0x00;
|
|
- dbbus_tx_data[3] = 0x00;
|
|
- dbbus_tx_data[4] = 0x04;
|
|
- write_i2c_seq(ts_data, ts_data->client->addr, &dbbus_tx_data[0], 5);
|
|
- read_i2c_seq(ts_data, ts_data->client->addr, &dbbus_rx_data[0], 4);
|
|
- if ((dbbus_rx_data[0] >= 0x30 && dbbus_rx_data[0] <= 0x39)
|
|
- && (dbbus_rx_data[1] >= 0x30 && dbbus_rx_data[1] <= 0x39)
|
|
- && (dbbus_rx_data[2] >= 0x31 && dbbus_rx_data[2] <= 0x39)) {
|
|
- info_sw_id = (dbbus_rx_data[0] - 0x30) * 100 +
|
|
- (dbbus_rx_data[1] - 0x30) * 10 +
|
|
- (dbbus_rx_data[2] - 0x30);
|
|
- }
|
|
-
|
|
- dev_dbg(&ts_data->client->dev,
|
|
- "[21xxA]:main_sw_id = %d, info_sw_id = %d, bin_conf_crc32 = 0x%x\n",
|
|
- main_sw_id, info_sw_id, bin_conf_crc32);
|
|
-}
|
|
-
|
|
-static ssize_t firmware_update_show(struct device *dev,
|
|
- struct device_attribute *attr,
|
|
- char *buf)
|
|
-{
|
|
- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
|
|
-
|
|
- return snprintf(buf, 3, "%d\n", ts_data->pdata->updating_fw);
|
|
-}
|
|
-
|
|
-static ssize_t firmware_update_store(struct device *dev,
|
|
- struct device_attribute *attr,
|
|
- const char *buf,
|
|
- size_t size)
|
|
-{
|
|
- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
|
|
-
|
|
- ts_data->pdata->updating_fw = true;
|
|
- disable_irq(ts_data->client->irq);
|
|
-
|
|
- size = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN, false);
|
|
-
|
|
- enable_irq(ts_data->client->irq);
|
|
- ts_data->pdata->updating_fw = false;
|
|
-
|
|
- return size;
|
|
-}
|
|
-
|
|
-static DEVICE_ATTR(update, (S_IRUGO | S_IWUSR),
|
|
- firmware_update_show,
|
|
- firmware_update_store);
|
|
-
|
|
-static int prepare_fw_data(struct device *dev)
|
|
-{
|
|
- int count;
|
|
- int i;
|
|
- int ret;
|
|
- const struct firmware *fw = NULL;
|
|
- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
|
|
-
|
|
- ret = request_firmware(&fw, ts_data->pdata->fw_name, dev);
|
|
- if (ret < 0) {
|
|
- dev_err(dev, "Request firmware failed - %s (%d)\n",
|
|
- ts_data->pdata->fw_name, ret);
|
|
- return ret;
|
|
- }
|
|
-
|
|
- count = fw->size / 1024;
|
|
-
|
|
- for (i = 0; i < count; i++)
|
|
- memcpy(fw_bin_data[i], fw->data + (i * 1024), 1024);
|
|
-
|
|
- fw_file_major = MSG_FW_FILE_MAJOR_VERSION(fw);
|
|
- fw_file_minor = MSG_FW_FILE_MINOR_VERSION(fw);
|
|
- dev_dbg(dev, "New firmware: %d.%d",
|
|
- fw_file_major, fw_file_minor);
|
|
-
|
|
- return fw->size;
|
|
-}
|
|
-
|
|
-static ssize_t firmware_update_smart_store(struct device *dev,
|
|
- struct device_attribute *attr,
|
|
- const char *buf,
|
|
- size_t size)
|
|
-{
|
|
- int ret;
|
|
- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
|
|
-
|
|
- ret = prepare_fw_data(dev);
|
|
- if (ret < 0) {
|
|
- dev_err(dev, "Request firmware failed -(%d)\n", ret);
|
|
- return ret;
|
|
- }
|
|
- ts_data->pdata->updating_fw = true;
|
|
- disable_irq(ts_data->client->irq);
|
|
-
|
|
- ret = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN, false);
|
|
- if (ret == 0)
|
|
- dev_err(dev, "firmware_update_c33 ret = %d\n", ret);
|
|
-
|
|
- enable_irq(ts_data->client->irq);
|
|
- ts_data->pdata->updating_fw = false;
|
|
-
|
|
- return ret;
|
|
-}
|
|
-
|
|
-static ssize_t firmware_force_update_smart_store(struct device *dev,
|
|
- struct device_attribute *attr,
|
|
- const char *buf,
|
|
- size_t size)
|
|
-{
|
|
- int ret;
|
|
- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
|
|
-
|
|
- ret = prepare_fw_data(dev);
|
|
- if (ret < 0) {
|
|
- dev_err(dev, "Request firmware failed -(%d)\n", ret);
|
|
- return ret;
|
|
- }
|
|
- ts_data->pdata->updating_fw = true;
|
|
- disable_irq(ts_data->client->irq);
|
|
-
|
|
- ret = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN, true);
|
|
- if (ret == 0)
|
|
- dev_err(dev, "firmware_update_c33 et = %d\n", ret);
|
|
-
|
|
- enable_irq(ts_data->client->irq);
|
|
- ts_data->pdata->updating_fw = false;
|
|
-
|
|
- return ret;
|
|
-}
|
|
-
|
|
-static DEVICE_ATTR(update_fw, (S_IRUGO | S_IWUSR),
|
|
- firmware_update_show,
|
|
- firmware_update_smart_store);
|
|
-
|
|
-static DEVICE_ATTR(force_update_fw, (S_IRUGO | S_IWUSR),
|
|
- firmware_update_show,
|
|
- firmware_force_update_smart_store);
|
|
-
|
|
-static ssize_t firmware_version_show(struct device *dev,
|
|
- struct device_attribute *attr,
|
|
- char *buf)
|
|
-{
|
|
- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
|
|
-
|
|
- msg21xx_read_firmware_id(ts_data);
|
|
- return snprintf(buf, sizeof(char) * 8, "%03d%03d\n",
|
|
- ts_data->pdata->fw_version_major,
|
|
- ts_data->pdata->fw_version_minor);
|
|
-}
|
|
-
|
|
-static DEVICE_ATTR(version, S_IRUGO,
|
|
- firmware_version_show,
|
|
- NULL);
|
|
-
|
|
-
|
|
-static ssize_t msg21xx_fw_name_show(struct device *dev,
|
|
- struct device_attribute *attr, char *buf)
|
|
-{
|
|
- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
|
|
-
|
|
- return snprintf(buf, MSTAR_FW_NAME_MAX_LEN - 1,
|
|
- "%s\n", ts_data->pdata->fw_name);
|
|
-}
|
|
-
|
|
-static ssize_t msg21xx_fw_name_store(struct device *dev,
|
|
- struct device_attribute *attr,
|
|
- const char *buf, size_t size)
|
|
-{
|
|
- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
|
|
-
|
|
- if (size > MSTAR_FW_NAME_MAX_LEN - 1)
|
|
- return -EINVAL;
|
|
-
|
|
- strlcpy(ts_data->pdata->fw_name, buf, size);
|
|
- if (ts_data->pdata->fw_name[size - 1] == '\n')
|
|
- ts_data->pdata->fw_name[size - 1] = 0;
|
|
-
|
|
- return size;
|
|
-}
|
|
-
|
|
-static DEVICE_ATTR(fw_name, (S_IRUGO | S_IWUSR),
|
|
- msg21xx_fw_name_show, msg21xx_fw_name_store);
|
|
-
|
|
-static ssize_t firmware_data_store(struct device *dev,
|
|
- struct device_attribute *attr,
|
|
- const char *buf,
|
|
- size_t size)
|
|
-{
|
|
- int count = size / 1024;
|
|
- int i;
|
|
-
|
|
- for (i = 0; i < count; i++)
|
|
- memcpy(fw_bin_data[i], buf + (i * 1024), 1024);
|
|
-
|
|
- if (buf != NULL)
|
|
- dev_dbg(dev, "buf[0] = %c\n", buf[0]);
|
|
-
|
|
- return size;
|
|
-}
|
|
-
|
|
-static DEVICE_ATTR(data, S_IWUSR, NULL, firmware_data_store);
|
|
-
|
|
-static ssize_t tp_print_show(struct device *dev,
|
|
- struct device_attribute *attr,
|
|
- char *buf)
|
|
-{
|
|
- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
|
|
-
|
|
- tp_print_proc_read(ts_data);
|
|
-
|
|
- return snprintf(buf, 3, "%d\n", ts_data->suspended);
|
|
-}
|
|
-
|
|
-static ssize_t tp_print_store(struct device *dev,
|
|
- struct device_attribute *attr,
|
|
- const char *buf,
|
|
- size_t size)
|
|
-{
|
|
- return size;
|
|
-}
|
|
-
|
|
-static DEVICE_ATTR(tpp, (S_IRUGO | S_IWUSR),
|
|
- tp_print_show, tp_print_store);
|
|
-
|
|
-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
|
|
-static void _msg_enable_proximity(void)
|
|
-{
|
|
- unsigned char tx_data[4] = {0};
|
|
-
|
|
- tx_data[0] = 0x52;
|
|
- tx_data[1] = 0x00;
|
|
- tx_data[2] = 0x47;
|
|
- tx_data[3] = 0xa0;
|
|
- mutex_lock(&msg21xx_mutex);
|
|
- write_i2c_seq(ts_data->client->addr, &tx_data[0], 4);
|
|
- mutex_unlock(&msg21xx_mutex);
|
|
-
|
|
- bEnableTpProximity = 1;
|
|
-}
|
|
-
|
|
-static void _msg_disable_proximity(void)
|
|
-{
|
|
- unsigned char tx_data[4] = {0};
|
|
-
|
|
- tx_data[0] = 0x52;
|
|
- tx_data[1] = 0x00;
|
|
- tx_data[2] = 0x47;
|
|
- tx_data[3] = 0xa1;
|
|
- mutex_lock(&msg21xx_mutex);
|
|
- write_i2c_seq(ts_data->client->addr, &tx_data[0], 4);
|
|
- mutex_unlock(&msg21xx_mutex);
|
|
-
|
|
- bEnableTpProximity = 0;
|
|
- bFaceClosingTp = 0;
|
|
-}
|
|
-
|
|
-static void tsps_msg21xx_enable(int en)
|
|
-{
|
|
- if (en)
|
|
- _msg_enable_proximity();
|
|
- else
|
|
- _msg_disable_proximity();
|
|
-}
|
|
-
|
|
-static int tsps_msg21xx_data(void)
|
|
-{
|
|
- return bFaceClosingTp;
|
|
-}
|
|
-#endif
|
|
-
|
|
-static int msg21xx_pinctrl_init(struct msg21xx_ts_data *ts_data)
|
|
-{
|
|
- int retval;
|
|
-
|
|
- /* Get pinctrl if target uses pinctrl */
|
|
- ts_data->ts_pinctrl = devm_pinctrl_get(&(ts_data->client->dev));
|
|
- if (IS_ERR_OR_NULL(ts_data->ts_pinctrl)) {
|
|
- retval = PTR_ERR(ts_data->ts_pinctrl);
|
|
- dev_dbg(&ts_data->client->dev,
|
|
- "Target does not use pinctrl %d\n", retval);
|
|
- goto err_pinctrl_get;
|
|
- }
|
|
-
|
|
- ts_data->pinctrl_state_active = pinctrl_lookup_state(
|
|
- ts_data->ts_pinctrl, PINCTRL_STATE_ACTIVE);
|
|
- if (IS_ERR_OR_NULL(ts_data->pinctrl_state_active)) {
|
|
- retval = PTR_ERR(ts_data->pinctrl_state_active);
|
|
- dev_dbg(&ts_data->client->dev,
|
|
- "Can't lookup %s pinstate %d\n",
|
|
- PINCTRL_STATE_ACTIVE, retval);
|
|
- goto err_pinctrl_lookup;
|
|
- }
|
|
-
|
|
- ts_data->pinctrl_state_suspend = pinctrl_lookup_state(
|
|
- ts_data->ts_pinctrl, PINCTRL_STATE_SUSPEND);
|
|
- if (IS_ERR_OR_NULL(ts_data->pinctrl_state_suspend)) {
|
|
- retval = PTR_ERR(ts_data->pinctrl_state_suspend);
|
|
- dev_dbg(&ts_data->client->dev,
|
|
- "Can't lookup %s pinstate %d\n",
|
|
- PINCTRL_STATE_SUSPEND, retval);
|
|
- goto err_pinctrl_lookup;
|
|
- }
|
|
-
|
|
- ts_data->pinctrl_state_release = pinctrl_lookup_state(
|
|
- ts_data->ts_pinctrl, PINCTRL_STATE_RELEASE);
|
|
- if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) {
|
|
- retval = PTR_ERR(ts_data->pinctrl_state_release);
|
|
- dev_dbg(&ts_data->client->dev,
|
|
- "Can't lookup %s pinstate %d\n",
|
|
- PINCTRL_STATE_RELEASE, retval);
|
|
- }
|
|
-
|
|
- return 0;
|
|
-
|
|
-err_pinctrl_lookup:
|
|
- devm_pinctrl_put(ts_data->ts_pinctrl);
|
|
-err_pinctrl_get:
|
|
- ts_data->ts_pinctrl = NULL;
|
|
- return retval;
|
|
-}
|
|
-
|
|
-static unsigned char calculate_checksum(unsigned char *msg, int length)
|
|
-{
|
|
- int checksum = 0, i;
|
|
-
|
|
- for (i = 0; i < length; i++)
|
|
- checksum += msg[i];
|
|
-
|
|
- return (unsigned char)((-checksum) & 0xFF);
|
|
-}
|
|
-
|
|
-static int parse_info(struct msg21xx_ts_data *ts_data)
|
|
-{
|
|
- unsigned char data[DEMO_MODE_PACKET_LENGTH] = {0};
|
|
- unsigned char checksum = 0;
|
|
- unsigned int x = 0, y = 0;
|
|
- unsigned int x2 = 0, y2 = 0;
|
|
- unsigned int delta_x = 0, delta_y = 0;
|
|
-
|
|
- mutex_lock(&msg21xx_mutex);
|
|
- read_i2c_seq(ts_data, ts_data->client->addr, &data[0],
|
|
- DEMO_MODE_PACKET_LENGTH);
|
|
- mutex_unlock(&msg21xx_mutex);
|
|
- checksum = calculate_checksum(&data[0], (DEMO_MODE_PACKET_LENGTH-1));
|
|
- dev_dbg(&ts_data->client->dev, "check sum: [%x] == [%x]?\n",
|
|
- data[DEMO_MODE_PACKET_LENGTH-1], checksum);
|
|
-
|
|
- if (data[DEMO_MODE_PACKET_LENGTH-1] != checksum) {
|
|
- dev_err(&ts_data->client->dev, "WRONG CHECKSUM\n");
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- if (data[0] != 0x52) {
|
|
- dev_err(&ts_data->client->dev, "WRONG HEADER\n");
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- ts_data->info.keycode = 0xFF;
|
|
- if ((data[1] == 0xFF) && (data[2] == 0xFF) &&
|
|
- (data[3] == 0xFF) && (data[4] == 0xFF) &&
|
|
- (data[6] == 0xFF)) {
|
|
- if ((data[5] == 0xFF) || (data[5] == 0)) {
|
|
- ts_data->info.keycode = 0xFF;
|
|
- } else if ((data[5] == 1) || (data[5] == 2) ||
|
|
- (data[5] == 4) || (data[5] == 8)) {
|
|
- ts_data->info.keycode = data[5] >> 1;
|
|
-
|
|
- dev_dbg(&ts_data->client->dev,
|
|
- "ts_data->info.keycode index %d\n",
|
|
- ts_data->info.keycode);
|
|
- }
|
|
- #ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
|
|
- else if (bEnableTpProximity && ((data[5] == 0x80) ||
|
|
- (data[5] == 0x40))) {
|
|
- if (data[5] == 0x80)
|
|
- bFaceClosingTp = 1;
|
|
- else if (data[5] == 0x40)
|
|
- bFaceClosingTp = 0;
|
|
-
|
|
- return -EINVAL;
|
|
- }
|
|
- #endif
|
|
- else {
|
|
- dev_err(&ts_data->client->dev, "WRONG KEY\n");
|
|
- return -EINVAL;
|
|
- }
|
|
- } else {
|
|
- x = (((data[1] & 0xF0) << 4) | data[2]);
|
|
- y = (((data[1] & 0x0F) << 8) | data[3]);
|
|
- delta_x = (((data[4] & 0xF0) << 4) | data[5]);
|
|
- delta_y = (((data[4] & 0x0F) << 8) | data[6]);
|
|
-
|
|
- if ((delta_x == 0) && (delta_y == 0)) {
|
|
- ts_data->info.point[0].x =
|
|
- x * ts_data->pdata->x_max / TPD_WIDTH;
|
|
- ts_data->info.point[0].y =
|
|
- y * ts_data->pdata->y_max / TPD_HEIGHT;
|
|
- ts_data->info.count = 1;
|
|
- } else {
|
|
- if (delta_x > 2048)
|
|
- delta_x -= 4096;
|
|
-
|
|
- if (delta_y > 2048)
|
|
- delta_y -= 4096;
|
|
-
|
|
- x2 = (unsigned int)((signed short)x +
|
|
- (signed short)delta_x);
|
|
- y2 = (unsigned int)((signed short)y +
|
|
- (signed short)delta_y);
|
|
- ts_data->info.point[0].x =
|
|
- x * ts_data->pdata->x_max / TPD_WIDTH;
|
|
- ts_data->info.point[0].y =
|
|
- y * ts_data->pdata->y_max / TPD_HEIGHT;
|
|
- ts_data->info.point[1].x =
|
|
- x2 * ts_data->pdata->x_max / TPD_WIDTH;
|
|
- ts_data->info.point[1].y =
|
|
- y2 * ts_data->pdata->y_max / TPD_HEIGHT;
|
|
- ts_data->info.count = ts_data->pdata->num_max_touches;
|
|
- }
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static void touch_driver_touch_released(struct msg21xx_ts_data *ts_data)
|
|
-{
|
|
- int i;
|
|
-
|
|
- for (i = 0; i < ts_data->pdata->num_max_touches; i++) {
|
|
- input_mt_slot(ts_data->input_dev, i);
|
|
- input_mt_report_slot_state(ts_data->input_dev,
|
|
- MT_TOOL_FINGER, 0);
|
|
- }
|
|
-
|
|
- input_report_key(ts_data->input_dev, BTN_TOUCH, 0);
|
|
- input_report_key(ts_data->input_dev, BTN_TOOL_FINGER, 0);
|
|
- input_sync(ts_data->input_dev);
|
|
-}
|
|
-
|
|
-/* read data through I2C then report data to input
|
|
- *sub-system when interrupt occurred
|
|
- */
|
|
-static irqreturn_t msg21xx_ts_interrupt(int irq, void *dev_id)
|
|
-{
|
|
- int i = 0;
|
|
- static int last_keycode = 0xFF;
|
|
- static int last_count;
|
|
- struct msg21xx_ts_data *ts_data = dev_id;
|
|
-
|
|
- ts_data->info.count = 0;
|
|
- if (parse_info(ts_data) == 0) {
|
|
- if (ts_data->info.keycode != 0xFF) { /* key touch pressed */
|
|
- if (ts_data->info.keycode <
|
|
- ts_data->pdata->num_buttons) {
|
|
- if (ts_data->info.keycode != last_keycode) {
|
|
- dev_dbg(&ts_data->client->dev,
|
|
- "key touch pressed");
|
|
-
|
|
- input_report_key(ts_data->input_dev,
|
|
- BTN_TOUCH, 1);
|
|
- input_report_key(ts_data->input_dev,
|
|
- ts_data->pdata->button_map[
|
|
- ts_data->info.keycode], 1);
|
|
-
|
|
- last_keycode = ts_data->info.keycode;
|
|
- } else {
|
|
- /* pass duplicate key-pressing */
|
|
- dev_dbg(&ts_data->client->dev,
|
|
- "REPEATED KEY\n");
|
|
- }
|
|
- } else {
|
|
- dev_dbg(&ts_data->client->dev, "WRONG KEY\n");
|
|
- }
|
|
- } else { /* key touch released */
|
|
- if (last_keycode != 0xFF) {
|
|
- dev_dbg(&ts_data->client->dev, "key touch released");
|
|
-
|
|
- input_report_key(ts_data->input_dev,
|
|
- BTN_TOUCH, 0);
|
|
- input_report_key(ts_data->input_dev,
|
|
- ts_data->pdata->button_map[last_keycode],
|
|
- 0);
|
|
-
|
|
- last_keycode = 0xFF;
|
|
- }
|
|
- }
|
|
-
|
|
- if (ts_data->info.count > 0) { /* point touch pressed */
|
|
- for (i = 0; i < ts_data->info.count; i++) {
|
|
- input_mt_slot(ts_data->input_dev, i);
|
|
- input_mt_report_slot_state(ts_data->input_dev,
|
|
- MT_TOOL_FINGER, 1);
|
|
- input_report_abs(ts_data->input_dev,
|
|
- ABS_MT_TOUCH_MAJOR, 1);
|
|
- input_report_abs(ts_data->input_dev,
|
|
- ABS_MT_POSITION_X,
|
|
- ts_data->info.point[i].x);
|
|
- input_report_abs(ts_data->input_dev,
|
|
- ABS_MT_POSITION_Y,
|
|
- ts_data->info.point[i].y);
|
|
- }
|
|
- }
|
|
-
|
|
- if (last_count > info.count) {
|
|
- for (i = info.count; i < MAX_TOUCH_NUM; i++) {
|
|
- input_mt_slot(input_dev, i);
|
|
- input_mt_report_slot_state(input_dev,
|
|
- }
|
|
-
|
|
- if (last_count > ts_data->info.count) {
|
|
- for (i = ts_data->info.count;
|
|
- i < ts_data->pdata->num_max_touches;
|
|
- i++) {
|
|
- input_mt_slot(ts_data->input_dev, i);
|
|
- input_mt_report_slot_state(ts_data->input_dev,
|
|
- MT_TOOL_FINGER, 0);
|
|
- }
|
|
- }
|
|
- last_count = ts_data->info.count;
|
|
-
|
|
- input_report_key(ts_data->input_dev, BTN_TOUCH,
|
|
- ts_data->info.count > 0);
|
|
- input_report_key(ts_data->input_dev, BTN_TOOL_FINGER,
|
|
- ts_data->info.count > 0);
|
|
-
|
|
- input_sync(ts_data->input_dev);
|
|
- }
|
|
-
|
|
- return IRQ_HANDLED;
|
|
-}
|
|
-
|
|
-static int msg21xx_ts_power_init(struct msg21xx_ts_data *ts_data, bool init)
|
|
-{
|
|
- int rc;
|
|
-
|
|
- if (init) {
|
|
- ts_data->vdd = regulator_get(&ts_data->client->dev,
|
|
- "vdd");
|
|
- if (IS_ERR(ts_data->vdd)) {
|
|
- rc = PTR_ERR(ts_data->vdd);
|
|
- dev_err(&ts_data->client->dev,
|
|
- "Regulator get failed vdd rc=%d\n", rc);
|
|
- return rc;
|
|
- }
|
|
-
|
|
- if (regulator_count_voltages(ts_data->vdd) > 0) {
|
|
- rc = regulator_set_voltage(ts_data->vdd,
|
|
- MSTAR_VTG_MIN_UV,
|
|
- MSTAR_VTG_MAX_UV);
|
|
- if (rc) {
|
|
- dev_err(&ts_data->client->dev,
|
|
- "Regulator set_vtg failed vdd rc=%d\n",
|
|
- rc);
|
|
- goto reg_vdd_put;
|
|
- }
|
|
- }
|
|
-
|
|
- ts_data->vcc_i2c = regulator_get(&ts_data->client->dev,
|
|
- "vcc_i2c");
|
|
- if (IS_ERR(ts_data->vcc_i2c)) {
|
|
- rc = PTR_ERR(ts_data->vcc_i2c);
|
|
- dev_err(&ts_data->client->dev,
|
|
- "Regulator get failed vcc_i2c rc=%d\n", rc);
|
|
- goto reg_vdd_set_vtg;
|
|
- }
|
|
-
|
|
- if (regulator_count_voltages(ts_data->vcc_i2c) > 0) {
|
|
- rc = regulator_set_voltage(ts_data->vcc_i2c,
|
|
- MSTAR_I2C_VTG_MIN_UV,
|
|
- MSTAR_I2C_VTG_MAX_UV);
|
|
- if (rc) {
|
|
- dev_err(&ts_data->client->dev,
|
|
- "Regulator set_vtg failed vcc_i2c rc=%d\n", rc);
|
|
- goto reg_vcc_i2c_put;
|
|
- }
|
|
- }
|
|
- } else {
|
|
- if (regulator_count_voltages(ts_data->vdd) > 0)
|
|
- regulator_set_voltage(ts_data->vdd, 0,
|
|
- MSTAR_VTG_MAX_UV);
|
|
-
|
|
- regulator_put(ts_data->vdd);
|
|
-
|
|
- if (regulator_count_voltages(ts_data->vcc_i2c) > 0)
|
|
- regulator_set_voltage(ts_data->vcc_i2c, 0,
|
|
- MSTAR_I2C_VTG_MAX_UV);
|
|
-
|
|
- regulator_put(ts_data->vcc_i2c);
|
|
- }
|
|
-
|
|
- return 0;
|
|
-
|
|
-reg_vcc_i2c_put:
|
|
- regulator_put(ts_data->vcc_i2c);
|
|
-reg_vdd_set_vtg:
|
|
- if (regulator_count_voltages(ts_data->vdd) > 0)
|
|
- regulator_set_voltage(ts_data->vdd, 0, MSTAR_VTG_MAX_UV);
|
|
-reg_vdd_put:
|
|
- regulator_put(ts_data->vdd);
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int msg21xx_ts_power_on(struct msg21xx_ts_data *ts_data, bool on)
|
|
-{
|
|
- int rc;
|
|
-
|
|
- if (!on)
|
|
- goto power_off;
|
|
-
|
|
- rc = regulator_enable(ts_data->vdd);
|
|
- if (rc) {
|
|
- dev_err(&ts_data->client->dev,
|
|
- "Regulator vdd enable failed rc=%d\n", rc);
|
|
- return rc;
|
|
- }
|
|
-
|
|
- rc = regulator_enable(ts_data->vcc_i2c);
|
|
- if (rc) {
|
|
- dev_err(&ts_data->client->dev,
|
|
- "Regulator vcc_i2c enable failed rc=%d\n", rc);
|
|
- regulator_disable(ts_data->vdd);
|
|
- }
|
|
-
|
|
- return rc;
|
|
-
|
|
- DBG("*** %s ***\n", __func__);
|
|
- rc = regulator_disable(vdd);
|
|
-power_off:
|
|
- rc = regulator_disable(ts_data->vdd);
|
|
- if (rc) {
|
|
- dev_err(&ts_data->client->dev,
|
|
- "Regulator vdd disable failed rc=%d\n", rc);
|
|
- return rc;
|
|
- }
|
|
-
|
|
- rc = regulator_disable(ts_data->vcc_i2c);
|
|
- if (rc) {
|
|
- dev_err(&ts_data->client->dev,
|
|
- "Regulator vcc_i2c disable failed rc=%d\n", rc);
|
|
- rc = regulator_enable(ts_data->vdd);
|
|
- }
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int msg21xx_ts_gpio_configure(struct msg21xx_ts_data *ts_data, bool on)
|
|
-{
|
|
- int ret = 0;
|
|
-
|
|
- if (!on)
|
|
- goto pwr_deinit;
|
|
-
|
|
- if (gpio_is_valid(ts_data->pdata->irq_gpio)) {
|
|
- ret = gpio_request(ts_data->pdata->irq_gpio,
|
|
- "msg21xx_irq_gpio");
|
|
- if (ret) {
|
|
- dev_err(&ts_data->client->dev,
|
|
- "Failed to request GPIO[%d], %d\n",
|
|
- ts_data->pdata->irq_gpio, ret);
|
|
- goto err_irq_gpio_req;
|
|
- }
|
|
- ret = gpio_direction_input(ts_data->pdata->irq_gpio);
|
|
- if (ret) {
|
|
- dev_err(&ts_data->client->dev,
|
|
- "Failed to set direction for gpio[%d], %d\n",
|
|
- ts_data->pdata->irq_gpio, ret);
|
|
- goto err_irq_gpio_dir;
|
|
- }
|
|
- gpio_set_value_cansleep(ts_data->pdata->irq_gpio, 1);
|
|
- } else {
|
|
- dev_err(&ts_data->client->dev, "irq gpio not provided\n");
|
|
- goto err_irq_gpio_req;
|
|
- }
|
|
-
|
|
- if (gpio_is_valid(ts_data->pdata->reset_gpio)) {
|
|
- ret = gpio_request(ts_data->pdata->reset_gpio,
|
|
- "msg21xx_reset_gpio");
|
|
- if (ret) {
|
|
- dev_err(&ts_data->client->dev,
|
|
- "Failed to request GPIO[%d], %d\n",
|
|
- ts_data->pdata->reset_gpio, ret);
|
|
- goto err_reset_gpio_req;
|
|
- }
|
|
-
|
|
- } else {
|
|
- if (gpio_is_valid(pdata->irq_gpio))
|
|
- gpio_free(pdata->irq_gpio);
|
|
- if (gpio_is_valid(pdata->reset_gpio)) {
|
|
- gpio_set_value_cansleep(pdata->reset_gpio, 0);
|
|
- ret = gpio_direction_input(pdata->reset_gpio);
|
|
- if (ret)
|
|
- dev_err(&i2c_client->dev,
|
|
- "Unable to set direction for gpio [%d]\n",
|
|
- pdata->reset_gpio);
|
|
- gpio_free(pdata->reset_gpio);
|
|
- }
|
|
- }
|
|
- return 0;
|
|
- /* power on TP */
|
|
- ret = gpio_direction_output(
|
|
- ts_data->pdata->reset_gpio, 1);
|
|
- if (ret) {
|
|
- dev_err(&ts_data->client->dev,
|
|
- "Failed to set direction for GPIO[%d], %d\n",
|
|
- ts_data->pdata->reset_gpio, ret);
|
|
- goto err_reset_gpio_dir;
|
|
- }
|
|
- msleep(100);
|
|
- gpio_set_value_cansleep(ts_data->pdata->reset_gpio, 0);
|
|
- msleep(20);
|
|
- gpio_set_value_cansleep(ts_data->pdata->reset_gpio, 1);
|
|
- msleep(200);
|
|
- } else {
|
|
- dev_err(&ts_data->client->dev, "reset gpio not provided\n");
|
|
- goto err_reset_gpio_req;
|
|
- }
|
|
-
|
|
- return 0;
|
|
-
|
|
-err_reset_gpio_dir:
|
|
- if (gpio_is_valid(ts_data->pdata->reset_gpio))
|
|
- gpio_free(ts_data->pdata->irq_gpio);
|
|
-err_reset_gpio_req:
|
|
-err_irq_gpio_dir:
|
|
- if (gpio_is_valid(ts_data->pdata->irq_gpio))
|
|
- gpio_free(ts_data->pdata->irq_gpio);
|
|
-err_irq_gpio_req:
|
|
- return ret;
|
|
-
|
|
-pwr_deinit:
|
|
- if (gpio_is_valid(ts_data->pdata->irq_gpio))
|
|
- gpio_free(ts_data->pdata->irq_gpio);
|
|
- if (gpio_is_valid(ts_data->pdata->reset_gpio)) {
|
|
- gpio_set_value_cansleep(ts_data->pdata->reset_gpio, 0);
|
|
- ret = gpio_direction_input(ts_data->pdata->reset_gpio);
|
|
- if (ret)
|
|
- dev_err(&ts_data->client->dev,
|
|
- "Unable to set direction for gpio [%d]\n",
|
|
- ts_data->pdata->reset_gpio);
|
|
- gpio_free(ts_data->pdata->reset_gpio);
|
|
- }
|
|
- return 0;
|
|
-}
|
|
-
|
|
-#ifdef CONFIG_PM
|
|
-static int msg21xx_ts_resume(struct device *dev)
|
|
-{
|
|
- int retval;
|
|
- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
|
|
-
|
|
- if (!ts_data->suspended) {
|
|
- dev_info(dev, "msg21xx_ts already in resume\n");
|
|
- return 0;
|
|
- }
|
|
-
|
|
- mutex_lock(&ts_data->ts_mutex);
|
|
-
|
|
- retval = msg21xx_ts_power_on(ts_data, true);
|
|
- if (retval) {
|
|
- dev_err(dev, "msg21xx_ts power on failed");
|
|
- mutex_unlock(&ts_data->ts_mutex);
|
|
- return retval;
|
|
- }
|
|
-
|
|
- if (ts_data->ts_pinctrl) {
|
|
- retval = pinctrl_select_state(ts_data->ts_pinctrl,
|
|
- ts_data->pinctrl_state_active);
|
|
- if (retval < 0) {
|
|
- dev_err(dev, "Cannot get active pinctrl state\n");
|
|
- mutex_unlock(&ts_data->ts_mutex);
|
|
- return retval;
|
|
- }
|
|
- }
|
|
-
|
|
- retval = msg21xx_ts_gpio_configure(ts_data, true);
|
|
- if (retval) {
|
|
- dev_err(dev, "Failed to put gpios in active state %d",
|
|
- retval);
|
|
- mutex_unlock(&ts_data->ts_mutex);
|
|
- return retval;
|
|
- }
|
|
-
|
|
- enable_irq(ts_data->client->irq);
|
|
- ts_data->suspended = false;
|
|
-
|
|
- mutex_unlock(&ts_data->ts_mutex);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int msg21xx_ts_suspend(struct device *dev)
|
|
-{
|
|
- int retval;
|
|
- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
|
|
-
|
|
- if (ts_data->pdata->updating_fw) {
|
|
- dev_info(dev, "Firmware loading in progress\n");
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if (ts_data->suspended) {
|
|
- dev_info(dev, "msg21xx_ts already in suspend\n");
|
|
- return 0;
|
|
- }
|
|
-
|
|
-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
|
|
- if (bEnableTpProximity) {
|
|
- dev_dbg(dev, "suspend bEnableTpProximity=%d\n",
|
|
- bEnableTpProximity);
|
|
- return 0;
|
|
- }
|
|
-#endif
|
|
-
|
|
- mutex_lock(&ts_data->ts_mutex);
|
|
-
|
|
- disable_irq(ts_data->client->irq);
|
|
-
|
|
- touch_driver_touch_released(ts_data);
|
|
-
|
|
- if (ts_data->ts_pinctrl) {
|
|
- retval = pinctrl_select_state(ts_data->ts_pinctrl,
|
|
- ts_data->pinctrl_state_suspend);
|
|
- if (retval < 0) {
|
|
- dev_err(dev, "Cannot get idle pinctrl state %d\n",
|
|
- retval);
|
|
- mutex_unlock(&ts_data->ts_mutex);
|
|
- return retval;
|
|
- }
|
|
- }
|
|
-
|
|
- retval = msg21xx_ts_gpio_configure(ts_data, false);
|
|
- if (retval) {
|
|
- dev_err(dev, "Failed to put gpios in idle state %d",
|
|
- retval);
|
|
- mutex_unlock(&ts_data->ts_mutex);
|
|
- return retval;
|
|
- }
|
|
-
|
|
- retval = msg21xx_ts_power_on(ts_data, false);
|
|
- if (retval) {
|
|
- dev_err(dev, "msg21xx_ts power off failed");
|
|
- mutex_unlock(&ts_data->ts_mutex);
|
|
- return retval;
|
|
- }
|
|
-
|
|
- ts_data->suspended = true;
|
|
-
|
|
- mutex_unlock(&ts_data->ts_mutex);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-#else
|
|
-static int msg21xx_ts_resume(struct device *dev)
|
|
-{
|
|
- return 0;
|
|
-}
|
|
-static int msg21xx_ts_suspend(struct device *dev)
|
|
-{
|
|
- return 0;
|
|
-}
|
|
-#endif
|
|
-
|
|
-static int msg21xx_debug_suspend_set(void *_data, u64 val)
|
|
-{
|
|
- struct msg21xx_ts_data *data = _data;
|
|
-
|
|
- mutex_lock(&data->input_dev->mutex);
|
|
-
|
|
- if (val)
|
|
- msg21xx_ts_suspend(&data->client->dev);
|
|
- else
|
|
- msg21xx_ts_resume(&data->client->dev);
|
|
-
|
|
- mutex_unlock(&data->input_dev->mutex);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int msg21xx_debug_suspend_get(void *_data, u64 *val)
|
|
-{
|
|
- struct msg21xx_ts_data *data = _data;
|
|
-
|
|
- mutex_lock(&data->input_dev->mutex);
|
|
- *val = data->suspended;
|
|
- mutex_unlock(&data->input_dev->mutex);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, msg21xx_debug_suspend_get,
|
|
- msg21xx_debug_suspend_set, "%lld\n");
|
|
-
|
|
-
|
|
-#if defined(CONFIG_FB)
|
|
-static int fb_notifier_callback(struct notifier_block *self,
|
|
- unsigned long event, void *data)
|
|
-{
|
|
- struct fb_event *evdata = data;
|
|
- int *blank;
|
|
- struct msg21xx_ts_data *ts_data =
|
|
- container_of(self, struct msg21xx_ts_data, fb_notif);
|
|
-
|
|
- if (evdata && evdata->data && event == FB_EVENT_BLANK) {
|
|
- blank = evdata->data;
|
|
- if (*blank == FB_BLANK_UNBLANK)
|
|
- msg21xx_ts_resume(&ts_data->client->dev);
|
|
- else if (*blank == FB_BLANK_POWERDOWN)
|
|
- msg21xx_ts_suspend(&ts_data->client->dev);
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-#endif
|
|
-
|
|
-static int msg21xx_get_dt_coords(struct device *dev, char *name,
|
|
- struct msg21xx_ts_platform_data *pdata)
|
|
-{
|
|
- u32 coords[FT_COORDS_ARR_SIZE];
|
|
- struct property *prop;
|
|
- struct device_node *np = dev->of_node;
|
|
- int coords_size, rc;
|
|
-
|
|
- prop = of_find_property(np, name, NULL);
|
|
- if (!prop)
|
|
- return -EINVAL;
|
|
- if (!prop->value)
|
|
- return -ENODATA;
|
|
-
|
|
- coords_size = prop->length / sizeof(u32);
|
|
- if (coords_size != FT_COORDS_ARR_SIZE) {
|
|
- dev_err(dev, "invalid %s\n", name);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- rc = of_property_read_u32_array(np, name, coords, coords_size);
|
|
- if (rc && (rc != -EINVAL)) {
|
|
- dev_err(dev, "Unable to read %s\n", name);
|
|
- return rc;
|
|
- }
|
|
-
|
|
- if (!strcmp(name, "mstar,panel-coords")) {
|
|
- pdata->panel_minx = coords[0];
|
|
- pdata->panel_miny = coords[1];
|
|
- pdata->panel_maxx = coords[2];
|
|
- pdata->panel_maxy = coords[3];
|
|
- } else if (!strcmp(name, "mstar,display-coords")) {
|
|
- pdata->x_min = coords[0];
|
|
- pdata->y_min = coords[1];
|
|
- pdata->x_max = coords[2];
|
|
- pdata->y_max = coords[3];
|
|
- } else {
|
|
- dev_err(dev, "unsupported property %s\n", name);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int msg21xx_parse_dt(struct device *dev,
|
|
- struct msg21xx_ts_platform_data *pdata)
|
|
-{
|
|
- int rc;
|
|
- struct device_node *np = dev->of_node;
|
|
- struct property *prop;
|
|
- u32 temp_val;
|
|
-
|
|
- rc = msg21xx_get_dt_coords(dev, "mstar,panel-coords", pdata);
|
|
- if (rc && (rc != -EINVAL))
|
|
- return rc;
|
|
-
|
|
- rc = msg21xx_get_dt_coords(dev, "mstar,display-coords", pdata);
|
|
- if (rc)
|
|
- return rc;
|
|
-
|
|
- rc = of_property_read_u32(np, "mstar,hard-reset-delay-ms",
|
|
- &temp_val);
|
|
- if (!rc)
|
|
- pdata->hard_reset_delay_ms = temp_val;
|
|
- else
|
|
- return rc;
|
|
-
|
|
- rc = of_property_read_u32(np, "mstar,post-hard-reset-delay-ms",
|
|
- &temp_val);
|
|
- if (!rc)
|
|
- pdata->post_hard_reset_delay_ms = temp_val;
|
|
- else
|
|
- return rc;
|
|
-
|
|
- /* reset, irq gpio info */
|
|
- pdata->reset_gpio = of_get_named_gpio_flags(np, "mstar,reset-gpio",
|
|
- 0, &pdata->reset_gpio_flags);
|
|
- if (pdata->reset_gpio < 0)
|
|
- return pdata->reset_gpio;
|
|
-
|
|
- pdata->irq_gpio = of_get_named_gpio_flags(np, "mstar,irq-gpio",
|
|
- 0, &pdata->irq_gpio_flags);
|
|
- if (pdata->irq_gpio < 0)
|
|
- return pdata->irq_gpio;
|
|
-
|
|
- rc = of_property_read_u32(np, "mstar,ic-type", &temp_val);
|
|
- if (rc && (rc != -EINVAL))
|
|
- return rc;
|
|
-
|
|
- pdata->ic_type = temp_val;
|
|
-
|
|
- rc = of_property_read_u32(np, "mstar,num-max-touches", &temp_val);
|
|
- if (!rc)
|
|
- pdata->num_max_touches = temp_val;
|
|
- else
|
|
- return rc;
|
|
-
|
|
- prop = of_find_property(np, "mstar,button-map", NULL);
|
|
- if (prop) {
|
|
- pdata->num_buttons = prop->length / sizeof(temp_val);
|
|
- if (pdata->num_buttons > MAX_BUTTONS)
|
|
- return -EINVAL;
|
|
-
|
|
- rc = of_property_read_u32_array(np,
|
|
- "mstar,button-map", pdata->button_map,
|
|
- pdata->num_buttons);
|
|
- if (rc) {
|
|
- dev_err(dev, "Unable to read key codes\n");
|
|
- return rc;
|
|
- }
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/* probe function is used for matching and initializing input device */
|
|
-static int msg21xx_ts_probe(struct i2c_client *client,
|
|
- const struct i2c_device_id *id) {
|
|
-
|
|
- int ret = 0, i;
|
|
- struct dentry *temp, *dir;
|
|
- struct input_dev *input_dev;
|
|
- struct msg21xx_ts_data *ts_data;
|
|
- struct msg21xx_ts_platform_data *pdata;
|
|
-
|
|
- if (client->dev.of_node) {
|
|
- pdata = devm_kzalloc(&client->dev,
|
|
- sizeof(struct msg21xx_ts_platform_data), GFP_KERNEL);
|
|
- if (!pdata)
|
|
- return -ENOMEM;
|
|
-
|
|
- ret = msg21xx_parse_dt(&client->dev, pdata);
|
|
- if (ret) {
|
|
- dev_err(&client->dev, "DT parsing failed\n");
|
|
- return ret;
|
|
- }
|
|
- } else
|
|
- pdata = client->dev.platform_data;
|
|
-
|
|
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
|
|
- dev_err(&client->dev, "I2C not supported\n");
|
|
- return -ENODEV;
|
|
- }
|
|
-
|
|
- ts_data = devm_kzalloc(&client->dev,
|
|
- sizeof(struct msg21xx_ts_data), GFP_KERNEL);
|
|
- if (!ts_data)
|
|
- return -ENOMEM;
|
|
-
|
|
- ts_data->client = client;
|
|
- ts_data->info.point = devm_kzalloc(&client->dev,
|
|
- sizeof(struct touchPoint_t) * pdata->num_max_touches,
|
|
- GFP_KERNEL);
|
|
- if (!ts_data->info.point) {
|
|
- dev_err(&client->dev, "Not enough memory\n");
|
|
- return -ENOMEM;
|
|
- }
|
|
-
|
|
- /* allocate an input device */
|
|
- input_dev = input_allocate_device();
|
|
- if (!input_dev) {
|
|
- ret = -ENOMEM;
|
|
- dev_err(&client->dev, "input device allocation failed\n");
|
|
- goto err_input_allocate_dev;
|
|
- }
|
|
-
|
|
- input_dev->name = client->name;
|
|
- input_dev->phys = "I2C";
|
|
- input_dev->dev.parent = &client->dev;
|
|
- input_dev->id.bustype = BUS_I2C;
|
|
-
|
|
- ts_data->input_dev = input_dev;
|
|
- ts_data->client = client;
|
|
- ts_data->pdata = pdata;
|
|
-
|
|
- input_set_drvdata(input_dev, ts_data);
|
|
- i2c_set_clientdata(client, ts_data);
|
|
-
|
|
- ret = msg21xx_ts_power_init(ts_data, true);
|
|
- if (ret) {
|
|
- dev_err(&client->dev, "Mstar power init failed\n");
|
|
- return ret;
|
|
- }
|
|
-
|
|
- ret = msg21xx_ts_power_on(ts_data, true);
|
|
- if (ret) {
|
|
- dev_err(&client->dev, "Mstar power on failed\n");
|
|
- goto exit_deinit_power;
|
|
- }
|
|
-
|
|
- ret = msg21xx_pinctrl_init(ts_data);
|
|
- if (!ret && ts_data->ts_pinctrl) {
|
|
- /*
|
|
- * Pinctrl handle is optional. If pinctrl handle is found
|
|
- * let pins to be configured in active state. If not
|
|
- * found continue further without error.
|
|
- */
|
|
- ret = pinctrl_select_state(ts_data->ts_pinctrl,
|
|
- ts_data->pinctrl_state_active);
|
|
- if (ret < 0)
|
|
- dev_err(&client->dev,
|
|
- "Failed to select %s pinatate %d\n",
|
|
- PINCTRL_STATE_ACTIVE, ret);
|
|
- }
|
|
-
|
|
- ret = msg21xx_ts_gpio_configure(ts_data, true);
|
|
- if (ret) {
|
|
- dev_err(&client->dev, "Failed to configure gpio %d\n", ret);
|
|
- goto exit_gpio_config;
|
|
- }
|
|
-
|
|
- if (msg21xx_get_ic_type(ts_data) == 0) {
|
|
- dev_err(&client->dev, "The current IC is not Mstar\n");
|
|
- ret = -1;
|
|
- goto err_wrong_ic_type;
|
|
- }
|
|
-
|
|
- mutex_init(&msg21xx_mutex);
|
|
- mutex_init(&ts_data->ts_mutex);
|
|
-
|
|
- /* set the supported event type for input device */
|
|
- set_bit(EV_ABS, input_dev->evbit);
|
|
- set_bit(EV_SYN, input_dev->evbit);
|
|
- set_bit(EV_KEY, 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);
|
|
-
|
|
- for (i = 0; i < pdata->num_buttons; i++)
|
|
- input_set_capability(input_dev, EV_KEY, pdata->button_map[i]);
|
|
-
|
|
- input_set_drvdata(input_dev, ts_data);
|
|
- i2c_set_clientdata(client, ts_data);
|
|
-
|
|
-#ifdef CONFIG_TP_HAVE_KEY
|
|
- {
|
|
- int i;
|
|
-
|
|
- for (i = 0; i < num_buttons; i++)
|
|
- input_set_capability(input_dev, EV_KEY, button_map[i]);
|
|
- }
|
|
-#endif
|
|
-
|
|
- input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
|
|
- 0, 2, 0, 0);
|
|
- input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 2, 0, 0);
|
|
- input_set_abs_params(input_dev, ABS_MT_POSITION_X,
|
|
- 0, pdata->x_max, 0, 0);
|
|
- input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
|
|
- 0, pdata->y_max, 0, 0);
|
|
- ret = input_mt_init_slots(input_dev, pdata->num_max_touches, 0);
|
|
- if (ret) {
|
|
- dev_err(&client->dev,
|
|
- "Error %d initialising slots\n", ret);
|
|
- goto err_free_mem;
|
|
- }
|
|
-
|
|
- /* register the input device to input sub-system */
|
|
- ret = input_register_device(input_dev);
|
|
- if (ret < 0) {
|
|
- dev_err(&client->dev,
|
|
- "Unable to register ms-touchscreen input device\n");
|
|
- goto err_input_reg_dev;
|
|
- }
|
|
-
|
|
- /* version */
|
|
- if (device_create_file(&client->dev, &dev_attr_version) < 0) {
|
|
- dev_err(&client->dev,
|
|
- "Failed to create device file(%s)!\n",
|
|
- dev_attr_version.attr.name);
|
|
- goto err_create_fw_ver_file;
|
|
- }
|
|
- /* update */
|
|
- if (device_create_file(&client->dev, &dev_attr_update) < 0) {
|
|
- dev_err(&client->dev,
|
|
- "Failed to create device file(%s)!\n",
|
|
- dev_attr_update.attr.name);
|
|
- goto err_create_fw_update_file;
|
|
- }
|
|
- /* data */
|
|
- if (device_create_file(&client->dev, &dev_attr_data) < 0) {
|
|
- dev_err(&client->dev,
|
|
- "Failed to create device file(%s)!\n",
|
|
- dev_attr_data.attr.name);
|
|
- goto err_create_fw_data_file;
|
|
- }
|
|
- /* fw name */
|
|
- if (device_create_file(&client->dev, &dev_attr_fw_name) < 0) {
|
|
- dev_err(&client->dev,
|
|
- "Failed to create device file(%s)!\n",
|
|
- dev_attr_fw_name.attr.name);
|
|
- goto err_create_fw_name_file;
|
|
- }
|
|
- /* smart fw update */
|
|
- if (device_create_file(&client->dev, &dev_attr_update_fw) < 0) {
|
|
- dev_err(&client->dev,
|
|
- "Failed to create device file(%s)!\n",
|
|
- dev_attr_update_fw.attr.name);
|
|
- goto err_create_update_fw_file;
|
|
- }
|
|
- /* smart fw force update */
|
|
- if (device_create_file(&client->dev,
|
|
- &dev_attr_force_update_fw) < 0) {
|
|
- dev_err(&client->dev,
|
|
- "Failed to create device file(%s)!\n",
|
|
- dev_attr_force_update_fw.attr.name);
|
|
- goto err_create_force_update_fw_file;
|
|
- }
|
|
- dir = debugfs_create_dir(MSTAR_DEBUG_DIR_NAME, NULL);
|
|
- temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, dir,
|
|
- ts_data, &debug_suspend_fops);
|
|
- if (temp == NULL || IS_ERR(temp)) {
|
|
- dev_err(&client->dev,
|
|
- "debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
|
|
- goto free_debug_dir;
|
|
- }
|
|
-
|
|
-#ifdef TP_PRINT
|
|
- tp_print_create_entry(ts_data);
|
|
-#endif
|
|
-
|
|
- ret = request_threaded_irq(client->irq, NULL,
|
|
- msg21xx_ts_interrupt,
|
|
- pdata->irq_gpio_flags | IRQF_ONESHOT,
|
|
- "msg21xx", ts_data);
|
|
- if (ret)
|
|
- goto err_req_irq;
|
|
-
|
|
- disable_irq(client->irq);
|
|
-
|
|
-#if defined(CONFIG_FB)
|
|
- ts_data->fb_notif.notifier_call = fb_notifier_callback;
|
|
- ret = fb_register_client(&ts_data->fb_notif);
|
|
-#endif
|
|
-
|
|
-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
|
|
- tsps_assist_register_callback("msg21xx", &tsps_msg21xx_enable,
|
|
- &tsps_msg21xx_data);
|
|
-#endif
|
|
-
|
|
- dev_dbg(&client->dev, "mstar touch screen registered\n");
|
|
- enable_irq(client->irq);
|
|
- return 0;
|
|
-
|
|
-err_req_irq:
|
|
- free_irq(client->irq, ts_data);
|
|
- device_remove_file(&client->dev, &dev_attr_data);
|
|
-free_debug_dir:
|
|
- debugfs_remove_recursive(dir);
|
|
-err_create_fw_data_file:
|
|
- device_remove_file(&client->dev, &dev_attr_update);
|
|
-err_create_fw_update_file:
|
|
- device_remove_file(&client->dev, &dev_attr_version);
|
|
-err_create_fw_name_file:
|
|
- device_remove_file(&client->dev, &dev_attr_fw_name);
|
|
-err_create_update_fw_file:
|
|
- device_remove_file(&client->dev, &dev_attr_update_fw);
|
|
-err_create_force_update_fw_file:
|
|
- device_remove_file(&client->dev, &dev_attr_force_update_fw);
|
|
-err_create_fw_ver_file:
|
|
- input_unregister_device(input_dev);
|
|
-
|
|
-err_input_reg_dev:
|
|
- input_free_device(input_dev);
|
|
- input_dev = NULL;
|
|
-err_input_allocate_dev:
|
|
- mutex_destroy(&msg21xx_mutex);
|
|
- mutex_destroy(&ts_data->ts_mutex);
|
|
-
|
|
-err_wrong_ic_type:
|
|
- msg21xx_ts_gpio_configure(ts_data, false);
|
|
-exit_gpio_config:
|
|
- if (ts_data->ts_pinctrl) {
|
|
- if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) {
|
|
- devm_pinctrl_put(ts_data->ts_pinctrl);
|
|
- ts_data->ts_pinctrl = NULL;
|
|
- } else {
|
|
- ret = pinctrl_select_state(ts_data->ts_pinctrl,
|
|
- ts_data->pinctrl_state_release);
|
|
- if (ret < 0)
|
|
- dev_err(&ts_data->client->dev,
|
|
- "Cannot get release pinctrl state\n");
|
|
- }
|
|
- }
|
|
- msg21xx_ts_power_on(ts_data, false);
|
|
-exit_deinit_power:
|
|
- msg21xx_ts_power_init(ts_data, false);
|
|
-err_free_mem:
|
|
- input_free_device(input_dev);
|
|
-
|
|
- return ret;
|
|
-}
|
|
-
|
|
-/* remove function is triggered when the input device is removed
|
|
- *from input sub-system
|
|
- */
|
|
-static int touch_driver_remove(struct i2c_client *client)
|
|
-{
|
|
- int retval = 0;
|
|
- struct msg21xx_ts_data *ts_data = i2c_get_clientdata(client);
|
|
-
|
|
- free_irq(ts_data->client->irq, ts_data);
|
|
- gpio_free(ts_data->pdata->irq_gpio);
|
|
- gpio_free(ts_data->pdata->reset_gpio);
|
|
-
|
|
- if (ts_data->ts_pinctrl) {
|
|
- if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) {
|
|
- devm_pinctrl_put(ts_data->ts_pinctrl);
|
|
- ts_data->ts_pinctrl = NULL;
|
|
- } else {
|
|
- retval = pinctrl_select_state(ts_data->ts_pinctrl,
|
|
- ts_data->pinctrl_state_release);
|
|
- if (retval < 0)
|
|
- dev_err(&ts_data->client->dev,
|
|
- "Cannot get release pinctrl state\n");
|
|
- }
|
|
- }
|
|
-
|
|
- input_unregister_device(ts_data->input_dev);
|
|
- mutex_destroy(&msg21xx_mutex);
|
|
- mutex_destroy(&ts_data->ts_mutex);
|
|
-
|
|
- return retval;
|
|
-}
|
|
-
|
|
-/* The I2C device list is used for matching I2C device
|
|
- *and I2C device driver.
|
|
- */
|
|
-static const struct i2c_device_id touch_device_id[] = {
|
|
- {"msg21xx", 0},
|
|
- {}, /* should not omitted */
|
|
-};
|
|
-
|
|
-static const struct of_device_id msg21xx_match_table[] = {
|
|
- { .compatible = "mstar,msg21xx", },
|
|
- { },
|
|
-};
|
|
-
|
|
-MODULE_DEVICE_TABLE(i2c, touch_device_id);
|
|
-
|
|
-static struct i2c_driver touch_device_driver = {
|
|
- .driver = {
|
|
- .name = "ms-msg21xx",
|
|
- .owner = THIS_MODULE,
|
|
- .of_match_table = msg21xx_match_table,
|
|
- },
|
|
- .probe = msg21xx_ts_probe,
|
|
- .remove = touch_driver_remove,
|
|
- .id_table = touch_device_id,
|
|
-};
|
|
-
|
|
-module_i2c_driver(touch_device_driver);
|
|
-
|
|
-#ifdef TP_PRINT
|
|
-#include <linux/proc_fs.h>
|
|
-
|
|
-static unsigned short InfoAddr = 0x0F, PoolAddr = 0x10, TransLen = 256;
|
|
-static unsigned char row, units, cnt;
|
|
-
|
|
-static int tp_print_proc_read(struct msg21xx_ts_data *ts_data)
|
|
-{
|
|
- unsigned short i, j;
|
|
- unsigned short left, offset = 0;
|
|
- unsigned char dbbus_tx_data[3] = {0};
|
|
- unsigned char u8Data;
|
|
- signed short s16Data;
|
|
- int s32Data;
|
|
- char *buf = NULL;
|
|
-
|
|
- left = cnt*row*units;
|
|
- if ((ts_data->suspended == 0) &&
|
|
- (InfoAddr != 0x0F) &&
|
|
- (PoolAddr != 0x10) &&
|
|
- (left > 0)) {
|
|
- buf = kmalloc(left, GFP_KERNEL);
|
|
- if (buf != NULL) {
|
|
-
|
|
- while (left > 0) {
|
|
- dbbus_tx_data[0] = 0x53;
|
|
- dbbus_tx_data[1] = ((PoolAddr + offset) >> 8)
|
|
- & 0xFF;
|
|
- dbbus_tx_data[2] = (PoolAddr + offset) & 0xFF;
|
|
- mutex_lock(&msg21xx_mutex);
|
|
- write_i2c_seq(ts_data, ts_data->client->addr,
|
|
- &dbbus_tx_data[0], 3);
|
|
- read_i2c_seq(ts_data, ts_data->client->addr,
|
|
- &buf[offset],
|
|
- left > TransLen ? TransLen : left);
|
|
- mutex_unlock(&msg21xx_mutex);
|
|
-
|
|
- if (left > TransLen) {
|
|
- left -= TransLen;
|
|
- offset += TransLen;
|
|
- } else {
|
|
- left = 0;
|
|
- }
|
|
- }
|
|
-
|
|
- for (i = 0; i < cnt; i++) {
|
|
- for (j = 0; j < row; j++) {
|
|
- if (units == 1) {
|
|
- u8Data = buf[i * row * units +
|
|
- j * units];
|
|
- } else if (units == 2) {
|
|
- s16Data = buf[i * row * units +
|
|
- j * units] +
|
|
- (buf[i * row * units +
|
|
- j * units + 1] << 8);
|
|
- } else if (units == 4) {
|
|
- s32Data = buf[i * row * units +
|
|
- j * units] +
|
|
- (buf[i * row * units +
|
|
- j * units + 1] << 8) +
|
|
- (buf[i * row * units +
|
|
- j * units + 2] << 16) +
|
|
- (buf[i * row * units +
|
|
- j * units + 3] << 24);
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- kfree(buf);
|
|
- }
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static void tp_print_create_entry(struct msg21xx_ts_data *ts_data)
|
|
-{
|
|
- unsigned char dbbus_tx_data[3] = {0};
|
|
- unsigned char dbbus_rx_data[8] = {0};
|
|
-
|
|
- dbbus_tx_data[0] = 0x53;
|
|
- dbbus_tx_data[1] = 0x00;
|
|
- dbbus_tx_data[2] = 0x58;
|
|
- mutex_lock(&msg21xx_mutex);
|
|
- write_i2c_seq(ts_data, ts_data->client->addr, &dbbus_tx_data[0], 3);
|
|
- read_i2c_seq(ts_data, ts_data->client->addr, &dbbus_rx_data[0], 4);
|
|
- mutex_unlock(&msg21xx_mutex);
|
|
- InfoAddr = (dbbus_rx_data[1]<<8) + dbbus_rx_data[0];
|
|
- PoolAddr = (dbbus_rx_data[3]<<8) + dbbus_rx_data[2];
|
|
-
|
|
- if ((InfoAddr != 0x0F) && (PoolAddr != 0x10)) {
|
|
- msleep(20);
|
|
- dbbus_tx_data[0] = 0x53;
|
|
- dbbus_tx_data[1] = (InfoAddr >> 8) & 0xFF;
|
|
- dbbus_tx_data[2] = InfoAddr & 0xFF;
|
|
- mutex_lock(&msg21xx_mutex);
|
|
- write_i2c_seq(ts_data, ts_data->client->addr,
|
|
- &dbbus_tx_data[0], 3);
|
|
- read_i2c_seq(ts_data, ts_data->client->addr,
|
|
- &dbbus_rx_data[0], 8);
|
|
- mutex_unlock(&msg21xx_mutex);
|
|
-
|
|
- units = dbbus_rx_data[0];
|
|
- row = dbbus_rx_data[1];
|
|
- cnt = dbbus_rx_data[2];
|
|
- TransLen = (dbbus_rx_data[7]<<8) + dbbus_rx_data[6];
|
|
-
|
|
- if (device_create_file(&ts_data->client->dev,
|
|
- &dev_attr_tpp) < 0)
|
|
- dev_err(&ts_data->client->dev, "Failed to create device file(%s)!\n",
|
|
- dev_attr_tpp.attr.name);
|
|
- }
|
|
-}
|
|
-#endif
|
|
-
|
|
-MODULE_AUTHOR("MStar Semiconductor, Inc.");
|
|
-MODULE_LICENSE("GPL v2");
|
|
--
|
|
cgit v1.1
|
|
|