Skip to content

Instantly share code, notes, and snippets.

@luk1337
Created April 28, 2017 22:57
Show Gist options
  • Save luk1337/00ce7067ff26ed736ce2f018fcdac3ce to your computer and use it in GitHub Desktop.
Save luk1337/00ce7067ff26ed736ce2f018fcdac3ce to your computer and use it in GitHub Desktop.
diff --git a/Kconfig b/Kconfig
index 1cb30a9..cfa0dde 100644
--- a/Kconfig
+++ b/Kconfig
@@ -1,7 +1,7 @@
#
# Synaptics DSX touchscreen driver configuration
#
-menuconfig TOUCHSCREEN_SYNAPTICS_DSX
+menuconfig TOUCHSCREEN_SYNAPTICS_DSX_FORCE
bool "Synaptics DSX touchscreen"
default y
help
@@ -10,23 +10,23 @@ menuconfig TOUCHSCREEN_SYNAPTICS_DSX
If unsure, say N.
-if TOUCHSCREEN_SYNAPTICS_DSX
+if TOUCHSCREEN_SYNAPTICS_DSX_FORCE
choice
- default TOUCHSCREEN_SYNAPTICS_DSX_I2C
+ default TOUCHSCREEN_SYNAPTICS_DSX_I2C_FORCE
prompt "Synaptics DSX bus interface"
-config TOUCHSCREEN_SYNAPTICS_DSX_I2C
+config TOUCHSCREEN_SYNAPTICS_DSX_I2C_FORCE
bool "RMI over I2C"
depends on I2C
-config TOUCHSCREEN_SYNAPTICS_DSX_SPI
+config TOUCHSCREEN_SYNAPTICS_DSX_SPI_FORCE
bool "RMI over SPI"
depends on SPI_MASTER
-config TOUCHSCREEN_SYNAPTICS_DSX_RMI_HID_I2C
+config TOUCHSCREEN_SYNAPTICS_DSX_RMI_HID_I2C_FORCE
bool "HID over I2C"
depends on I2C
endchoice
-config TOUCHSCREEN_SYNAPTICS_DSX_CORE
+config TOUCHSCREEN_SYNAPTICS_DSX_CORE_FORCE
tristate "Synaptics DSX core driver module"
depends on I2C || SPI_MASTER
help
@@ -37,9 +37,9 @@ config TOUCHSCREEN_SYNAPTICS_DSX_CORE
To compile this driver as a module, choose M here: the
module will be called synaptics_dsx_core.
-config TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV
+config TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_FORCE
tristate "Synaptics DSX RMI device module"
- depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE
+ depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE_FORCE
help
Say Y here to enable support for direct RMI register access.
@@ -48,9 +48,9 @@ config TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV
To compile this driver as a module, choose M here: the
module will be called synaptics_dsx_rmi_dev.
-config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE
+config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_FORCE
tristate "Synaptics DSX firmware update module"
- depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE
+ depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE_FORCE
help
Say Y here to enable support for doing firmware update.
@@ -59,9 +59,9 @@ config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE
To compile this driver as a module, choose M here: the
module will be called synaptics_dsx_fw_update.
-config TOUCHSCREEN_SYNAPTICS_DSX_TEST_REPORTING
+config TOUCHSCREEN_SYNAPTICS_DSX_TEST_REPORTING_FORCE
tristate "Synaptics DSX test reporting module"
- depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE
+ depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE_FORCE
help
Say Y here to enable support for retrieving production test reports.
@@ -70,9 +70,9 @@ config TOUCHSCREEN_SYNAPTICS_DSX_TEST_REPORTING
To compile this driver as a module, choose M here: the
module will be called synaptics_dsx_test_reporting.
-config TOUCHSCREEN_SYNAPTICS_DSX_PROXIMITY
+config TOUCHSCREEN_SYNAPTICS_DSX_PROXIMITY_FORCE
tristate "Synaptics DSX proximity module"
- depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE
+ depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE_FORCE
help
Say Y here to enable support for proximity functionality.
@@ -81,9 +81,9 @@ config TOUCHSCREEN_SYNAPTICS_DSX_PROXIMITY
To compile this driver as a module, choose M here: the
module will be called synaptics_dsx_proximity.
-config TOUCHSCREEN_SYNAPTICS_DSX_ACTIVE_PEN
+config TOUCHSCREEN_SYNAPTICS_DSX_ACTIVE_PEN_FORCE
tristate "Synaptics DSX active pen module"
- depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE
+ depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE_FORCE
help
Say Y here to enable support for active pen functionality.
@@ -92,9 +92,9 @@ config TOUCHSCREEN_SYNAPTICS_DSX_ACTIVE_PEN
To compile this driver as a module, choose M here: the
module will be called synaptics_dsx_active_pen.
-config TOUCHSCREEN_SYNAPTICS_DSX_GESTURE
+config TOUCHSCREEN_SYNAPTICS_DSX_GESTURE_FORCE
tristate "Synaptics DSX user defined gesture module"
- depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE
+ depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE_FORCE
help
Say Y here to enable support for user defined gesture functionality.
@@ -103,9 +103,9 @@ config TOUCHSCREEN_SYNAPTICS_DSX_GESTURE
To compile this driver as a module, choose M here: the
module will be called synaptics_dsx_gesture.
-config TOUCHSCREEN_SYNAPTICS_DSX_VIDEO
+config TOUCHSCREEN_SYNAPTICS_DSX_VIDEO_FORCE
tristate "Synaptics DSX video module"
- depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE
+ depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE_FORCE
help
Say Y here to enable support for video communication functionality.
@@ -114,4 +114,18 @@ config TOUCHSCREEN_SYNAPTICS_DSX_VIDEO
To compile this driver as a module, choose M here: the
module will be called synaptics_dsx_video.
+config TOUCHSCREEN_SYNAPTICS_DSX_2D_PRESSURE_FORCE
+ bool "Synaptics DSX 2D pressure support"
+ default n
+ depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE_FORCE
+ help
+ Say Y here to enable support for 2D pressure.
+
+config TOUCH_DEBUG_FS
+ bool "touch debugfs suport"
+ default n
+ depends on DEBUG_FS
+ help
+ Say Y here to enable support for touch debugfs.
+
endif
diff --git a/Makefile b/Makefile
index 515bc17..f613ea9 100644
--- a/Makefile
+++ b/Makefile
@@ -4,14 +4,14 @@
# Each configuration option enables a list of files.
-obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_I2C) += synaptics_dsx_i2c.o
-obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_SPI) += synaptics_dsx_spi.o
-obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_HID_I2C) += synaptics_dsx_rmi_hid_i2c.o
-obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE) += synaptics_dsx_core.o
-obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV) += synaptics_dsx_rmi_dev.o
-obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE) += synaptics_dsx_fw_update.o
-obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_TEST_REPORTING) += synaptics_dsx_test_reporting.o
-obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_PROXIMITY) += synaptics_dsx_proximity.o
-obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_ACTIVE_PEN) += synaptics_dsx_active_pen.o
-obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_GESTURE) += synaptics_dsx_gesture.o
-obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_VIDEO) += synaptics_dsx_video.o
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_I2C_FORCE) += synaptics_dsx_i2c.o
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_SPI_FORCE) += synaptics_dsx_spi.o
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_HID_I2C_FORCE) += synaptics_dsx_rmi_hid_i2c.o
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_FORCE) += synaptics_dsx_core.o
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_FORCE) += synaptics_dsx_rmi_dev.o
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_FORCE) += synaptics_dsx_fw_update.o
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_TEST_REPORTING_FORCE) += synaptics_dsx_test_reporting.o
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_PROXIMITY_FORCE) += synaptics_dsx_proximity.o
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_ACTIVE_PEN_FORCE) += synaptics_dsx_active_pen.o
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_GESTURE_FORCE) += synaptics_dsx_gesture.o
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_VIDEO_FORCE) += synaptics_dsx_video.o
diff --git a/synaptics_dsx_active_pen.c b/synaptics_dsx_active_pen.c
index 910ab16..1ff7a6d 100644
--- a/synaptics_dsx_active_pen.c
+++ b/synaptics_dsx_active_pen.c
@@ -609,14 +609,14 @@ static struct synaptics_rmi4_exp_fn active_pen_module = {
static int __init rmi4_active_pen_module_init(void)
{
- synaptics_rmi4_new_function(&active_pen_module, true);
+ synaptics_rmi4_new_function_force(&active_pen_module, true);
return 0;
}
static void __exit rmi4_active_pen_module_exit(void)
{
- synaptics_rmi4_new_function(&active_pen_module, false);
+ synaptics_rmi4_new_function_force(&active_pen_module, false);
wait_for_completion(&apen_remove_complete);
diff --git a/synaptics_dsx_core.c b/synaptics_dsx_core.c
index b72ed74..c76a1b1 100644
--- a/synaptics_dsx_core.c
+++ b/synaptics_dsx_core.c
@@ -16,6 +16,20 @@
* 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.
+ *
+ * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS
+ * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
+ * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS.
+ * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED
+ * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES
+ * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS'
+ * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S.
+ * DOLLARS.
*/
#include <linux/kernel.h>
@@ -32,6 +46,7 @@
#ifdef KERNEL_ABOVE_2_6_38
#include <linux/input/mt.h>
#endif
+
#if defined(CONFIG_SECURE_TOUCH)
#include <linux/pm_runtime.h>
#include <linux/errno.h>
@@ -39,6 +54,14 @@
#include <linux/power_supply.h>
+#ifdef CONFIG_TOUCH_DEBUG_FS
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+#endif
+
+#include <linux/mdss_io_util.h>
+
#define INPUT_PHYS_NAME "synaptics_dsx/touch_input"
#define STYLUS_PHYS_NAME "synaptics_dsx/stylus"
@@ -54,6 +77,10 @@
#define REPORT_2D_Z
#define REPORT_2D_W
+#ifdef TOUCHSCREEN_SYNAPTICS_DSX_2D_PRESSURE_FORCE
+#define REPORT_2D_PRESSURE
+#endif
+
#define F12_DATA_15_WORKAROUND
#define IGNORE_FN_INIT_FAILURE
@@ -99,6 +126,10 @@
#define F12_CONTINUOUS_MODE 0x00
#define F12_WAKEUP_GESTURE_MODE 0x02
#define F12_UDG_DETECT 0x0f
+#define F12_HOMEKEY_DETECT 0x0c
+
+#define DOUBLE_TAP 0x01
+#define HOMEKEY_WAKEUP 0x80
#define INPUT_EVENT_START 0
#define INPUT_EVENT_SENSITIVE_MODE_OFF 0
@@ -109,16 +140,16 @@
#define INPUT_EVENT_WAKUP_MODE_ON 5
#define INPUT_EVENT_COVER_MODE_OFF 6
#define INPUT_EVENT_COVER_MODE_ON 7
-#define INPUT_EVENT_END 7
+#define INPUT_EVENT_CAPTOUCH_MODE_OFF 8
+#define INPUT_EVENT_CAPTOUCH_MODE_ON 9
+#define INPUT_EVENT_END 9
+
+#define BUTTON_WG_EN 1
-#define COMMAND_TIMEOUT_100MS 20
+void (*captouch_key_report_ptr)(int key_status) = NULL;
+bool (*captouch_get_status_ptr)(void) = NULL;
-#define BTN_DOZE_WAKEUP_TH 0x0013
-#define BTN_FAST_RELAX_RATE 0x011f
-#define BTN_SLOW_RELAX_RATE 0x011e
-#define BTN_RELEASE_TH 0x0317
-#define BTN_TOUCH_TH1 0x0313
-#define BTN_TOUCH_TH2 0x0314
+static bool check_captouch_support(struct synaptics_rmi4_data *rmi4_data);
static int synaptics_rmi4_check_status(struct synaptics_rmi4_data *rmi4_data,
bool *was_in_bl_mode);
@@ -153,9 +184,12 @@ static int synaptics_rmi4_fb_notifier_cb_lgd(struct notifier_block *self,
unsigned long event, void *data);
#endif
-static void mdss_regulator_ctrl(struct synaptics_rmi4_data *rmi4_data, bool enable);
+#define DISP_REG_VDD (1<<0)
+#define DISP_REG_LAB (1<<1)
+#define DISP_REG_IBB (1<<2)
+#define DISP_REG_ALL (DISP_REG_VDD | DISP_REG_LAB | DISP_REG_IBB)
-static void synaptics_rmi4_protection_film(struct synaptics_rmi4_data *rmi4_data);
+static void mdss_regulator_ctrl(struct synaptics_rmi4_data *rmi4_data, unsigned int flag, bool enable);
#ifdef CONFIG_HAS_EARLYSUSPEND
#ifndef CONFIG_FB
@@ -200,9 +234,21 @@ static ssize_t synaptics_rmi4_wake_gesture_show(struct device *dev,
static ssize_t synaptics_rmi4_wake_gesture_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t synaptics_rmi4_irq_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t synaptics_rmi4_irq_enable_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t synaptics_rmi4_captouch_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+
static ssize_t synaptics_rmi4_panel_color_show(struct device *dev,
struct device_attribute *attr, char *buf);
+static ssize_t synaptics_rmi4_panel_vendor_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
static ssize_t synaptics_rmi4_virtual_key_map_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf);
@@ -408,8 +454,48 @@ struct synaptics_rmi4_f12_query_5 {
unsigned char ctrl30_is_present:1;
unsigned char ctrl31_is_present:1;
} __packed;
+ struct {
+ unsigned char ctrl32_is_present:1;
+ unsigned char ctrl33_is_present:1;
+ unsigned char ctrl34_is_present:1;
+ unsigned char ctrl35_is_present:1;
+ unsigned char ctrl36_is_present:1;
+ unsigned char ctrl37_is_present:1;
+ unsigned char ctrl38_is_present:1;
+ unsigned char ctrl39_is_present:1;
+ } __packed;
+ struct {
+ unsigned char ctrl40_is_present:1;
+ unsigned char ctrl41_is_present:1;
+ unsigned char ctrl42_is_present:1;
+ unsigned char ctrl43_is_present:1;
+ unsigned char ctrl44_is_present:1;
+ unsigned char ctrl45_is_present:1;
+ unsigned char ctrl46_is_present:1;
+ unsigned char ctrl47_is_present:1;
+ } __packed;
+ struct {
+ unsigned char ctrl48_is_present:1;
+ unsigned char ctrl49_is_present:1;
+ unsigned char ctrl50_is_present:1;
+ unsigned char ctrl51_is_present:1;
+ unsigned char ctrl52_is_present:1;
+ unsigned char ctrl53_is_present:1;
+ unsigned char ctrl54_is_present:1;
+ unsigned char ctrl55_is_present:1;
+ } __packed;
+ struct {
+ unsigned char ctrl56_is_present:1;
+ unsigned char ctrl57_is_present:1;
+ unsigned char ctrl58_is_present:1;
+ unsigned char ctrl59_is_present:1;
+ unsigned char ctrl60_is_present:1;
+ unsigned char ctrl61_is_present:1;
+ unsigned char ctrl62_is_present:1;
+ unsigned char ctrl63_is_present:1;
+ } __packed;
};
- unsigned char data[5];
+ unsigned char data[9];
};
};
@@ -447,8 +533,18 @@ struct synaptics_rmi4_f12_query_8 {
unsigned char data22_is_present:1;
unsigned char data23_is_present:1;
} __packed;
+ struct {
+ unsigned char data24_is_present:1;
+ unsigned char data25_is_present:1;
+ unsigned char data26_is_present:1;
+ unsigned char data27_is_present:1;
+ unsigned char data28_is_present:1;
+ unsigned char data29_is_present:1;
+ unsigned char data30_is_present:1;
+ unsigned char data31_is_present:1;
+ } __packed;
};
- unsigned char data[4];
+ unsigned char data[5];
};
};
@@ -528,6 +624,28 @@ struct synaptics_rmi4_f12_ctrl_31 {
};
};
+struct synaptics_rmi4_f12_ctrl_58 {
+ union {
+ struct {
+ unsigned char reporting_format;
+ unsigned char f12_ctr58_00_reserved;
+ unsigned char min_force_lsb;
+ unsigned char min_force_msb;
+ unsigned char max_force_lsb;
+ unsigned char max_force_msb;
+ unsigned char light_press_threshold_lsb;
+ unsigned char light_press_threshold_msb;
+ unsigned char light_press_hysteresis_lsb;
+ unsigned char light_press_hysteresis_msb;
+ unsigned char hard_press_threshold_lsb;
+ unsigned char hard_press_threshold_msb;
+ unsigned char hard_press_hysteresis_lsb;
+ unsigned char hard_press_hysteresis_msb;
+ };
+ unsigned char data[14];
+ };
+};
+
struct synaptics_rmi4_f12_finger_data {
unsigned char object_type_and_status;
unsigned char x_lsb;
@@ -547,7 +665,10 @@ struct synaptics_rmi4_f1a_query {
union {
struct {
unsigned char max_button_count:3;
- unsigned char reserved:5;
+ unsigned char f1a_query0_b3__4:2;
+ unsigned char has_query4:1;
+ unsigned char has_query3:1;
+ unsigned char has_query2:1;
unsigned char has_general_control:1;
unsigned char has_interrupt_enable:1;
unsigned char has_multibutton_select:1;
@@ -561,6 +682,18 @@ struct synaptics_rmi4_f1a_query {
};
};
+struct synaptics_rmi4_f1a_query_4 {
+ union {
+ struct {
+ unsigned char has_ctrl19:1;
+ unsigned char f1a_query4_b1__4:4;
+ unsigned char has_ctrl24:1;
+ unsigned char f1a_query4_b6__7:2;
+ } __packed;
+ unsigned char data[1];
+ };
+};
+
struct synaptics_rmi4_f1a_control_0 {
union {
struct {
@@ -636,6 +769,9 @@ static struct device_attribute attrs[] = {
__ATTR(wake_gesture, (S_IRUGO | S_IWUSR),
synaptics_rmi4_wake_gesture_show,
synaptics_rmi4_wake_gesture_store),
+ __ATTR(irq_enable, (S_IRUGO | S_IWUSR),
+ synaptics_rmi4_irq_enable_show,
+ synaptics_rmi4_irq_enable_store),
};
#if defined(CONFIG_SECURE_TOUCH)
@@ -866,6 +1002,8 @@ static ssize_t synaptics_secure_touch_show(struct device *dev,
#endif
static DEVICE_ATTR(panel_color, S_IRUSR, synaptics_rmi4_panel_color_show, NULL);
+static DEVICE_ATTR(captouch, S_IWUSR, NULL, synaptics_rmi4_captouch_store);
+static DEVICE_ATTR(panel_vendor, S_IRUSR, synaptics_rmi4_panel_vendor_show, NULL);
static struct kobj_attribute virtual_key_map_attr = {
.attr = {
@@ -1058,6 +1196,55 @@ static ssize_t synaptics_rmi4_wake_gesture_store(struct device *dev,
return count;
}
+static ssize_t synaptics_rmi4_irq_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ rmi4_data->irq_enabled);
+}
+
+static ssize_t synaptics_rmi4_irq_enable_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned int input;
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+ if (sscanf(buf, "%u", &input) != 1)
+ return -EINVAL;
+ if (input)
+ enable_irq(rmi4_data->irq);
+ else
+ disable_irq(rmi4_data->irq);
+
+ return count;
+}
+static ssize_t synaptics_rmi4_captouch_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned int input;
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+ const struct synaptics_dsx_board_data *bdata =
+ rmi4_data->hw_if->board_data;
+
+ if (sscanf(buf, "%u", &input) != 1)
+ return -EINVAL;
+
+ if (bdata->cut_off_power) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Unable to switch wakeup gesture mode\n", __func__);
+ return count;
+ }
+
+ input = input > 0 ? 1 : 0;
+
+ if (bdata->captouch_use)
+ rmi4_data->homekey_wakeup = input;
+
+ return count;
+}
+
static ssize_t synaptics_rmi4_panel_color_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -1067,6 +1254,15 @@ static ssize_t synaptics_rmi4_panel_color_show(struct device *dev,
rmi4_data->lockdown_info[2]);
}
+static ssize_t synaptics_rmi4_panel_vendor_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%c\n",
+ rmi4_data->lockdown_info[0]);
+}
+
static ssize_t synaptics_rmi4_virtual_key_map_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
@@ -1269,9 +1465,18 @@ static int synaptics_rmi4_f12_abs_report(struct synaptics_rmi4_data *rmi4_data,
int wx;
int wy;
int temp;
-#ifdef REPORT_2D_PRESSURE
+#if defined(REPORT_2D_PRESSURE) || defined(F51_DISCRETE_FORCE)
int pressure;
#endif
+#ifdef REPORT_2D_PRESSURE
+ unsigned char f_fingers;
+ unsigned char f_lsb;
+ unsigned char f_msb;
+ unsigned char *f_data;
+#endif
+#ifdef F51_DISCRETE_FORCE
+ unsigned char force_level;
+#endif
struct synaptics_rmi4_f12_extra_data *extra_data;
struct synaptics_rmi4_f12_finger_data *data;
struct synaptics_rmi4_f12_finger_data *finger_data;
@@ -1292,7 +1497,7 @@ static int synaptics_rmi4_f12_abs_report(struct synaptics_rmi4_data *rmi4_data,
extra_data = (struct synaptics_rmi4_f12_extra_data *)fhandler->extra;
size_of_2d_data = sizeof(struct synaptics_rmi4_f12_finger_data);
- if (rmi4_data->suspend && rmi4_data->enable_wakeup_gesture) {
+ if (rmi4_data->suspend && (rmi4_data->enable_wakeup_gesture || rmi4_data->homekey_wakeup)) {
retval = synaptics_rmi4_reg_read(rmi4_data,
data_addr + extra_data->data4_offset,
rmi4_data->gesture_detection,
@@ -1301,7 +1506,6 @@ static int synaptics_rmi4_f12_abs_report(struct synaptics_rmi4_data *rmi4_data,
return 0;
gesture_type = rmi4_data->gesture_detection[0];
-
if (gesture_type && gesture_type != F12_UDG_DETECT) {
input_report_key(rmi4_data->input_dev, KEY_WAKEUP, 1);
input_sync(rmi4_data->input_dev);
@@ -1309,6 +1513,14 @@ static int synaptics_rmi4_f12_abs_report(struct synaptics_rmi4_data *rmi4_data,
input_sync(rmi4_data->input_dev);
}
+ if (gesture_type == F12_HOMEKEY_DETECT) {
+ if (captouch_key_report_ptr != NULL) {
+ dev_info(rmi4_data->pdev->dev.parent,
+ "(captouch) fake report captouch keydown~!!\n");
+ captouch_key_report_ptr(1);
+ }
+ }
+
return 0;
}
@@ -1366,9 +1578,9 @@ static int synaptics_rmi4_f12_abs_report(struct synaptics_rmi4_data *rmi4_data,
#ifdef REPORT_2D_PRESSURE
if (rmi4_data->report_pressure) {
retval = synaptics_rmi4_reg_read(rmi4_data,
- data_addr + extra_data->data23_offset,
- extra_data->data23_data,
- fingers_to_process);
+ data_addr + extra_data->data29_offset,
+ extra_data->data29_data,
+ extra_data->data29_size);
if (retval < 0)
return 0;
}
@@ -1384,26 +1596,26 @@ static int synaptics_rmi4_f12_abs_report(struct synaptics_rmi4_data *rmi4_data,
objects_already_present = finger + 1;
#endif
- x = (finger_data->x_msb << 8) | (finger_data->x_lsb);
- y = (finger_data->y_msb << 8) | (finger_data->y_lsb);
+ x = (finger_data->x_msb << 8) | (finger_data->x_lsb);
+ y = (finger_data->y_msb << 8) | (finger_data->y_lsb);
#ifdef REPORT_2D_W
- wx = finger_data->wx;
- wy = finger_data->wy;
+ wx = finger_data->wx;
+ wy = finger_data->wy;
#endif
- if (rmi4_data->hw_if->board_data->swap_axes) {
- temp = x;
- x = y;
- y = temp;
- temp = wx;
- wx = wy;
- wy = temp;
- }
+ if (rmi4_data->hw_if->board_data->swap_axes) {
+ temp = x;
+ x = y;
+ y = temp;
+ temp = wx;
+ wx = wy;
+ wy = temp;
+ }
- if (rmi4_data->hw_if->board_data->x_flip)
- x = rmi4_data->sensor_max_x - x;
- if (rmi4_data->hw_if->board_data->y_flip)
- y = rmi4_data->sensor_max_y - y;
+ if (rmi4_data->hw_if->board_data->x_flip)
+ x = rmi4_data->sensor_max_x - x;
+ if (rmi4_data->hw_if->board_data->y_flip)
+ y = rmi4_data->sensor_max_y - y;
switch (finger_status) {
case F12_FINGER_STATUS:
@@ -1441,14 +1653,41 @@ static int synaptics_rmi4_f12_abs_report(struct synaptics_rmi4_data *rmi4_data,
#endif
#ifdef REPORT_2D_PRESSURE
if (rmi4_data->report_pressure) {
- pressure = extra_data->data23_data[finger];
+ f_fingers = extra_data->data29_size / 2;
+ f_data = extra_data->data29_data;
+ if (finger + 1 > f_fingers) {
+ pressure = 1;
+ } else {
+ f_lsb = finger * 2;
+ f_msb = finger * 2 + 1;
+ pressure = (int)f_data[f_lsb] << 0 |
+ (int)f_data[f_msb] << 8;
+ }
+ pressure = pressure > 0 ? pressure : 1;
+ if (pressure > rmi4_data->force_max)
+ pressure = rmi4_data->force_max;
input_report_abs(rmi4_data->input_dev,
ABS_MT_PRESSURE, pressure);
}
+#elif defined(F51_DISCRETE_FORCE)
+ if (finger == 0) {
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ FORCE_LEVEL_ADDR,
+ &force_level,
+ sizeof(force_level));
+ if (retval < 0)
+ return 0;
+ pressure = force_level > 0 ? force_level : 1;
+ } else {
+ pressure = 1;
+ }
+ input_report_abs(rmi4_data->input_dev,
+ ABS_MT_PRESSURE, pressure);
#endif
#ifndef TYPE_B_PROTOCOL
input_mt_sync(rmi4_data->input_dev);
#endif
+ input_sync(rmi4_data->input_dev);
dev_dbg(rmi4_data->pdev->dev.parent,
"%s: Finger %d: "
@@ -1476,36 +1715,33 @@ static int synaptics_rmi4_f12_abs_report(struct synaptics_rmi4_data *rmi4_data,
break;
case F12_STYLUS_STATUS:
case F12_ERASER_STATUS:
- if (rmi4_data->stylus_enable && rmi4_data->stylus_dev != NULL) {
- if (finger_presence) { /* Stylus has priority over fingers */
- mutex_unlock(&(rmi4_data->rmi4_report_mutex));
- synaptics_rmi4_free_fingers(rmi4_data);
- mutex_lock(&(rmi4_data->rmi4_report_mutex));
- finger_presence = 0;
- }
- if (stylus_presence) {/* Allow one stylus at a timee */
- if (finger + 1 != stylus_presence)
- break;
- }
+ if (finger_presence) { /* Stylus has priority over fingers */
+ mutex_unlock(&(rmi4_data->rmi4_report_mutex));
+ synaptics_rmi4_free_fingers(rmi4_data);
+ mutex_lock(&(rmi4_data->rmi4_report_mutex));
+ finger_presence = 0;
+ }
+ if (stylus_presence) {/* Allow one stylus at a timee */
+ if (finger + 1 != stylus_presence)
+ break;
+ }
+ input_report_key(rmi4_data->stylus_dev,
+ BTN_TOUCH, 1);
+ if (finger_status == F12_STYLUS_STATUS) {
input_report_key(rmi4_data->stylus_dev,
- BTN_TOUCH, 1);
- if (finger_status == F12_STYLUS_STATUS) {
- input_report_key(rmi4_data->stylus_dev,
- BTN_TOOL_PEN, 1);
- } else {
- input_report_key(rmi4_data->stylus_dev,
- BTN_TOOL_RUBBER, 1);
- }
- input_report_abs(rmi4_data->stylus_dev,
- ABS_X, x);
- input_report_abs(rmi4_data->stylus_dev,
- ABS_Y, y);
- input_sync(rmi4_data->stylus_dev);
-
- stylus_presence = finger + 1;
- touch_count++;
+ BTN_TOOL_PEN, 1);
+ } else {
+ input_report_key(rmi4_data->stylus_dev,
+ BTN_TOOL_RUBBER, 1);
}
+ input_report_abs(rmi4_data->stylus_dev,
+ ABS_X, x);
+ input_report_abs(rmi4_data->stylus_dev,
+ ABS_Y, y);
+ input_sync(rmi4_data->stylus_dev);
+ stylus_presence = finger + 1;
+ touch_count++;
break;
default:
#ifdef TYPE_B_PROTOCOL
@@ -1531,7 +1767,7 @@ static int synaptics_rmi4_f12_abs_report(struct synaptics_rmi4_data *rmi4_data,
#endif
input_sync(rmi4_data->input_dev);
- if (rmi4_data->stylus_enable && rmi4_data->stylus_dev != NULL) {
+ if (rmi4_data->stylus_enable) {
stylus_presence = 0;
input_report_key(rmi4_data->stylus_dev,
BTN_TOUCH, 0);
@@ -1545,8 +1781,6 @@ static int synaptics_rmi4_f12_abs_report(struct synaptics_rmi4_data *rmi4_data,
}
}
- input_sync(rmi4_data->input_dev);
-
mutex_unlock(&(rmi4_data->rmi4_report_mutex));
return touch_count;
@@ -1600,9 +1834,10 @@ static void synaptics_rmi4_f1a_report(struct synaptics_rmi4_data *rmi4_data,
shift = button % 8;
status = ((data[index] >> shift) & MASK_1BIT);
- if (current_status[button] == status)
- continue;
- else
+ if (current_status[button] == status) {
+ if (!rmi4_data->suspend)
+ continue;
+ } else
current_status[button] = status;
dev_dbg(rmi4_data->pdev->dev.parent,
@@ -1622,6 +1857,17 @@ static void synaptics_rmi4_f1a_report(struct synaptics_rmi4_data *rmi4_data,
before_2d_status[button] = 0;
}
}
+
+ if (f1a->button_map[button] == KEY_HOME) {
+ if (captouch_key_report_ptr != NULL) {
+ captouch_key_report_ptr(status);
+ } else {
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: captouch is enabled but captouch_key_report_ptr is NULL\n", __func__);
+ }
+ if (check_captouch_support(rmi4_data))
+ continue;
+ }
touch_count++;
input_report_key(rmi4_data->input_dev,
f1a->button_map[button],
@@ -1694,8 +1940,6 @@ static void synaptics_rmi4_report_touch(struct synaptics_rmi4_data *rmi4_data,
return;
}
-extern void mdss_fb_prim_panel_recover(void);
-
static void synaptics_rmi4_sensor_report(struct synaptics_rmi4_data *rmi4_data,
bool report)
{
@@ -1725,9 +1969,6 @@ static void synaptics_rmi4_sensor_report(struct synaptics_rmi4_data *rmi4_data,
return;
}
- if (rmi4_data->chip_id == CHIP_ID_4322 && (status.status_code == 0x09 && status.unconfigured))
- mdss_fb_prim_panel_recover();
-
status.data[0] = data[0];
if (status.status_code == STATUS_CRC_IN_PROGRESS) {
retval = synaptics_rmi4_check_status(rmi4_data,
@@ -1948,26 +2189,39 @@ static int synaptics_rmi4_query_product_id(struct synaptics_rmi4_data *rmi4_data
static int synaptics_rmi4_query_chip_id(struct synaptics_rmi4_data *rmi4_data)
{
int retval;
- unsigned short lockdown_addr;
+ unsigned short chipdata_addr;
unsigned char query_data[8] = {0};
- lockdown_addr = rmi4_data->f01_query_base_addr + F01_PROD_ID_OFFSET;
+ chipdata_addr = rmi4_data->f01_query_base_addr + F01_PROD_ID_OFFSET;
retval = synaptics_rmi4_reg_read(rmi4_data,
- lockdown_addr,
+ chipdata_addr,
query_data,
8);
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
"Failed reading reg %d\n",
- lockdown_addr);
+ chipdata_addr);
return retval;
}
- if (query_data[0] == 0x53)
- rmi4_data->chip_id = CHIP_ID_3330;
- else {
- rmi4_data->chip_id = CHIP_ID_4322;
+ dev_info(rmi4_data->pdev->dev.parent,
+ "chip info: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X",
+ query_data[0], query_data[1],
+ query_data[2], query_data[3],
+ query_data[4], query_data[5],
+ query_data[6], query_data[7]);
+
+
+ if (query_data[0] == 0x53 && query_data[4] == 0x30)
+ rmi4_data->chip_id = rmi4_data->hw_if->board_data->chip_3330;
+ else if (query_data[0] == 0x53 && query_data[4] == 0x31)
+ rmi4_data->chip_id = rmi4_data->hw_if->board_data->chip_3331;
+ else if (query_data[0] == 0x54 && query_data[3] == 0x33) {
+ rmi4_data->chip_id = rmi4_data->hw_if->board_data->chip_4322;
+ rmi4_data->hw_if->board_data->reset_gpio = -1;
+ } else if (query_data[0] == 0x54 && query_data[3] == 0x37) {
+ rmi4_data->chip_id = rmi4_data->hw_if->board_data->chip_4722;
rmi4_data->hw_if->board_data->reset_gpio = -1;
}
@@ -2255,93 +2509,94 @@ static int synaptics_rmi4_f12_set_enables(struct synaptics_rmi4_data *rmi4_data,
return retval;
}
-static int synaptics_rmi4_f12_ctrl_sub(struct synaptics_rmi4_data *rmi4_data,
+static int synaptics_rmi4_f12_find_sub(struct synaptics_rmi4_data *rmi4_data,
struct synaptics_rmi4_fn *fhandler,
- struct synaptics_rmi4_f12_query_5 *query_5,
- unsigned char ctrlreg, unsigned char subpacket)
+ unsigned char *presence, unsigned char presence_size,
+ unsigned char structure_offset, unsigned char reg,
+ unsigned char sub)
{
int retval;
unsigned char cnt;
unsigned char regnum;
unsigned char bitnum;
- unsigned char q5_index;
- unsigned char q6_index;
+ unsigned char p_index;
+ unsigned char s_index;
unsigned char offset;
- unsigned char max_ctrlreg;
- unsigned char *query_6;
+ unsigned char max_reg;
+ unsigned char *structure;
- max_ctrlreg = (sizeof(query_5->data) - 1) * 8 - 1;
+ max_reg = (presence_size - 1) * 8 - 1;
- if (ctrlreg > max_ctrlreg) {
+ if (reg > max_reg) {
dev_err(rmi4_data->pdev->dev.parent,
- "%s: Control register number (%d) over limit\n",
- __func__, ctrlreg);
+ "%s: Register number (%d) over limit\n",
+ __func__, reg);
return -EINVAL;
}
- q5_index = ctrlreg / 8 + 1;
- bitnum = ctrlreg % 8;
- if ((query_5->data[q5_index] & (1 << bitnum)) == 0x00) {
+ p_index = reg / 8 + 1;
+ bitnum = reg % 8;
+ if ((presence[p_index] & (1 << bitnum)) == 0x00) {
dev_err(rmi4_data->pdev->dev.parent,
- "%s: Control %d is not present\n",
- __func__, ctrlreg);
+ "%s: Register %d is not present\n",
+ __func__, reg);
return -EINVAL;
}
- query_6 = kmalloc(query_5->size_of_query6, GFP_KERNEL);
- if (!query_6) {
+ structure = kmalloc(presence[0], GFP_KERNEL);
+ if (!structure) {
dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to alloc mem for query 6\n",
+ "%s: Failed to alloc mem for structure register\n",
__func__);
return -ENOMEM;
}
retval = synaptics_rmi4_reg_read(rmi4_data,
- fhandler->full_addr.query_base + 6,
- query_6,
- query_5->size_of_query6);
+ fhandler->full_addr.query_base + structure_offset,
+ structure,
+ presence[0]);
if (retval < 0)
goto exit;
- q6_index = 0;
+ s_index = 0;
- for (regnum = 0; regnum < ctrlreg; regnum++) {
- q5_index = regnum / 8 + 1;
+ for (regnum = 0; regnum < reg; regnum++) {
+ p_index = regnum / 8 + 1;
bitnum = regnum % 8;
- if ((query_5->data[q5_index] & (1 << bitnum)) == 0x00)
+ if ((presence[p_index] & (1 << bitnum)) == 0x00)
continue;
- if (query_6[q6_index] == 0x00)
- q6_index += 3;
+ if (structure[s_index] == 0x00)
+ s_index += 3;
else
- q6_index++;
+ s_index++;
- while (query_6[q6_index] & ~MASK_7BIT)
- q6_index++;
+ while (structure[s_index] & ~MASK_7BIT)
+ s_index++;
- q6_index++;
+ s_index++;
}
cnt = 0;
- q6_index++;
- offset = subpacket / 7;
- bitnum = subpacket % 7;
+ s_index++;
+ offset = sub / 7;
+ bitnum = sub % 7;
do {
if (cnt == offset) {
- if (query_6[q6_index + cnt] & (1 << bitnum))
+ if (structure[s_index + cnt] & (1 << bitnum))
retval = 1;
else
retval = 0;
goto exit;
}
cnt++;
- } while (query_6[q6_index + cnt - 1] & ~MASK_7BIT);
+ } while (structure[s_index + cnt - 1] & ~MASK_7BIT);
retval = 0;
exit:
- kfree(query_6);
+ kfree(structure);
return retval;
}
@@ -2356,13 +2611,17 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
unsigned char subpacket;
unsigned char ctrl_23_size;
unsigned char size_of_2d_data;
+ unsigned char size_of_query5;
unsigned char size_of_query8;
unsigned char ctrl_8_offset;
unsigned char ctrl_20_offset;
unsigned char ctrl_23_offset;
unsigned char ctrl_26_offset;
+ unsigned char ctrl_27_offset;
unsigned char ctrl_28_offset;
unsigned char ctrl_31_offset;
+ unsigned char ctrl_47_offset;
+ unsigned char ctrl_58_offset;
unsigned char num_of_fingers;
struct synaptics_rmi4_f12_extra_data *extra_data;
struct synaptics_rmi4_f12_query_5 *query_5 = NULL;
@@ -2370,6 +2629,7 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
struct synaptics_rmi4_f12_ctrl_8 *ctrl_8 = NULL;
struct synaptics_rmi4_f12_ctrl_23 *ctrl_23 = NULL;
struct synaptics_rmi4_f12_ctrl_31 *ctrl_31 = NULL;
+ struct synaptics_rmi4_f12_ctrl_58 *ctrl_58 = NULL;
const struct synaptics_dsx_board_data *bdata =
rmi4_data->hw_if->board_data;
@@ -2385,7 +2645,7 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
extra_data = (struct synaptics_rmi4_f12_extra_data *)fhandler->extra;
size_of_2d_data = sizeof(struct synaptics_rmi4_f12_finger_data);
- query_5 = kmalloc(sizeof(*query_5), GFP_KERNEL);
+ query_5 = kzalloc(sizeof(*query_5), GFP_KERNEL);
if (!query_5) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to alloc mem for query_5\n",
@@ -2394,7 +2654,7 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
goto exit;
}
- query_8 = kmalloc(sizeof(*query_8), GFP_KERNEL);
+ query_8 = kzalloc(sizeof(*query_8), GFP_KERNEL);
if (!query_8) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to alloc mem for query_8\n",
@@ -2403,7 +2663,7 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
goto exit;
}
- ctrl_8 = kmalloc(sizeof(*ctrl_8), GFP_KERNEL);
+ ctrl_8 = kzalloc(sizeof(*ctrl_8), GFP_KERNEL);
if (!ctrl_8) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to alloc mem for ctrl_8\n",
@@ -2412,7 +2672,7 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
goto exit;
}
- ctrl_23 = kmalloc(sizeof(*ctrl_23), GFP_KERNEL);
+ ctrl_23 = kzalloc(sizeof(*ctrl_23), GFP_KERNEL);
if (!ctrl_23) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to alloc mem for ctrl_23\n",
@@ -2421,7 +2681,7 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
goto exit;
}
- ctrl_31 = kmalloc(sizeof(*ctrl_31), GFP_KERNEL);
+ ctrl_31 = kzalloc(sizeof(*ctrl_31), GFP_KERNEL);
if (!ctrl_31) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to alloc mem for ctrl_31\n",
@@ -2430,10 +2690,36 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
goto exit;
}
+ ctrl_58 = kzalloc(sizeof(*ctrl_58), GFP_KERNEL);
+ if (!ctrl_58) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to alloc mem for ctrl_58\n",
+ __func__);
+ retval = -ENOMEM;
+ goto exit;
+ }
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ fhandler->full_addr.query_base + 4,
+ &size_of_query5,
+ sizeof(size_of_query5));
+ if (retval < 0)
+ goto exit;
+
+ pr_err("%s %d: fhandler->full_addr.query_base = 0x%04x\n", __func__, __LINE__, fhandler->full_addr.query_base);
+ pr_err("%s %d: fhandler->full_addr.ctrl_base = 0x%04x\n", __func__, __LINE__, fhandler->full_addr.ctrl_base);
+ pr_err("%s %d: size_of_query5 = %d\n", __func__, __LINE__, size_of_query5);
+
+ if (size_of_query5 > sizeof(query_5->data))
+ size_of_query5 = sizeof(query_5->data);
+ memset(query_5->data, 0x00, sizeof(query_5->data));
+
+ pr_err("%s %d: size_of_query5 = %d\n", __func__, __LINE__, size_of_query5);
+
retval = synaptics_rmi4_reg_read(rmi4_data,
fhandler->full_addr.query_base + 5,
query_5->data,
- sizeof(query_5->data));
+ size_of_query5);
if (retval < 0)
goto exit;
@@ -2471,8 +2757,10 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
query_5->ctrl24_is_present +
query_5->ctrl25_is_present;
- ctrl_28_offset = ctrl_26_offset +
- query_5->ctrl26_is_present +
+ ctrl_27_offset = ctrl_26_offset +
+ query_5->ctrl26_is_present;
+
+ ctrl_28_offset = ctrl_27_offset +
query_5->ctrl27_is_present;
ctrl_31_offset = ctrl_28_offset +
@@ -2480,10 +2768,41 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
query_5->ctrl29_is_present +
query_5->ctrl30_is_present;
+ ctrl_47_offset = ctrl_31_offset +
+ query_5->ctrl31_is_present +
+ query_5->ctrl32_is_present +
+ query_5->ctrl33_is_present +
+ query_5->ctrl34_is_present +
+ query_5->ctrl35_is_present +
+ query_5->ctrl36_is_present +
+ query_5->ctrl37_is_present +
+ query_5->ctrl38_is_present +
+ query_5->ctrl39_is_present +
+ query_5->ctrl40_is_present +
+ query_5->ctrl41_is_present +
+ query_5->ctrl42_is_present +
+ query_5->ctrl43_is_present +
+ query_5->ctrl44_is_present +
+ query_5->ctrl45_is_present +
+ query_5->ctrl46_is_present;
+ ctrl_58_offset = ctrl_47_offset +
+ query_5->ctrl47_is_present +
+ query_5->ctrl48_is_present +
+ query_5->ctrl49_is_present +
+ query_5->ctrl50_is_present +
+ query_5->ctrl51_is_present +
+ query_5->ctrl52_is_present +
+ query_5->ctrl53_is_present +
+ query_5->ctrl54_is_present +
+ query_5->ctrl55_is_present +
+ query_5->ctrl56_is_present +
+ query_5->ctrl57_is_present;
+
ctrl_23_size = 2;
for (subpacket = 2; subpacket <= 4; subpacket++) {
- retval = synaptics_rmi4_f12_ctrl_sub(rmi4_data,
- fhandler, query_5, 23, subpacket);
+ retval = synaptics_rmi4_f12_find_sub(rmi4_data,
+ fhandler, query_5->data, sizeof(query_5->data),
+ 6, 23, subpacket);
if (retval == 1)
ctrl_23_size++;
else if (retval < 0)
@@ -2498,7 +2817,8 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
goto exit;
/* Maximum number of fingers supported */
- fhandler->num_of_data_points = min(ctrl_23->max_reported_objects,
+ fhandler->num_of_data_points = min_t(unsigned char,
+ ctrl_23->max_reported_objects,
(unsigned char)F12_FINGERS_TO_SUPPORT);
num_of_fingers = fhandler->num_of_data_points;
@@ -2514,6 +2834,10 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
if (retval < 0)
goto exit;
+ if (size_of_query8 > sizeof(query_8->data))
+ size_of_query8 = sizeof(query_8->data);
+ memset(query_8->data, 0x00, sizeof(query_8->data));
+
retval = synaptics_rmi4_reg_read(rmi4_data,
fhandler->full_addr.query_base + 8,
query_8->data,
@@ -2546,8 +2870,8 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
}
#ifdef REPORT_2D_PRESSURE
- if ((size_of_query8 >= 4) && (query_8->data23_is_present)) {
- extra_data->data23_offset = query_8->data0_is_present +
+ if ((size_of_query8 >= 5) && (query_8->data29_is_present)) {
+ extra_data->data29_offset = query_8->data0_is_present +
query_8->data1_is_present +
query_8->data2_is_present +
query_8->data3_is_present +
@@ -2569,11 +2893,48 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
query_8->data19_is_present +
query_8->data20_is_present +
query_8->data21_is_present +
- query_8->data22_is_present;
- extra_data->data23_size = num_of_fingers;
+ query_8->data22_is_present +
+ query_8->data23_is_present +
+ query_8->data24_is_present +
+ query_8->data25_is_present +
+ query_8->data26_is_present +
+ query_8->data27_is_present +
+ query_8->data28_is_present;
+ extra_data->data29_size = 0;
+ for (subpacket = 0; subpacket <= num_of_fingers; subpacket++) {
+ retval = synaptics_rmi4_f12_find_sub(rmi4_data,
+ fhandler, query_8->data,
+ sizeof(query_8->data),
+ 9, 29, subpacket);
+ if (retval == 1)
+ extra_data->data29_size += 2;
+ else if (retval < 0)
+ goto exit;
+ }
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ fhandler->full_addr.ctrl_base + ctrl_58_offset,
+ ctrl_58->data,
+ sizeof(ctrl_58->data));
+ if (retval < 0)
+ goto exit;
+
+ pr_err("%s %d: extra_data->data29_offset = %d\n", __func__, __LINE__, extra_data->data29_offset);
+ pr_err("%s %d: extra_data->data29_size = %d\n", __func__, __LINE__, extra_data->data29_size);
+ pr_err("%s %d: ctrl_58_offset = %d\n", __func__, __LINE__, ctrl_58_offset);
+
+ rmi4_data->force_min =
+ (int)(ctrl_58->min_force_lsb << 0) |
+ (int)(ctrl_58->min_force_msb << 8);
+ rmi4_data->force_max =
+ (int)(ctrl_58->max_force_lsb << 0) |
+ (int)(ctrl_58->max_force_msb << 8);
+
+ pr_err("%s %d: rmi4_data->force_min = %d\n", __func__, __LINE__, rmi4_data->force_min);
+ pr_err("%s %d: rmi4_data->force_max = %d\n", __func__, __LINE__, rmi4_data->force_max);
+
rmi4_data->report_pressure = true;
} else {
- extra_data->data23_size = 0;
+ extra_data->data29_size = 0;
rmi4_data->report_pressure = false;
}
#endif
@@ -2655,6 +3016,7 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
extra_data->ctrl26_offset = ctrl_26_offset;
+ extra_data->ctrl27_offset = ctrl_27_offset;
/* Allocate memory for finger data storage space */
fhandler->data_size = num_of_fingers * size_of_2d_data;
@@ -2673,6 +3035,7 @@ exit:
kfree(ctrl_8);
kfree(ctrl_23);
kfree(ctrl_31);
+ kfree(ctrl_58);
return retval;
}
@@ -2743,18 +3106,19 @@ static int synaptics_rmi4_f1a_button_map(struct synaptics_rmi4_data *rmi4_data,
{
int retval;
unsigned char ii;
- unsigned char mapping_offset = 0;
+ unsigned char offset = 0;
+ struct synaptics_rmi4_f1a_query_4 query_4;
struct synaptics_rmi4_f1a_handle *f1a = fhandler->data;
const struct synaptics_dsx_board_data *bdata =
rmi4_data->hw_if->board_data;
- mapping_offset = f1a->button_query.has_general_control +
+ offset = f1a->button_query.has_general_control +
f1a->button_query.has_interrupt_enable +
f1a->button_query.has_multibutton_select;
if (f1a->button_query.has_tx_rx_map) {
retval = synaptics_rmi4_reg_read(rmi4_data,
- fhandler->full_addr.ctrl_base + mapping_offset,
+ fhandler->full_addr.ctrl_base + offset,
f1a->button_control.txrx_map,
f1a->max_count * 2);
if (retval < 0) {
@@ -2767,6 +3131,27 @@ static int synaptics_rmi4_f1a_button_map(struct synaptics_rmi4_data *rmi4_data,
rmi4_data->button_txrx_mapping = f1a->button_control.txrx_map;
}
+ if (f1a->button_query.has_query4) {
+ offset = 2 + f1a->button_query.has_query2 +
+ f1a->button_query.has_query3;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ fhandler->full_addr.query_base + offset,
+ query_4.data,
+ sizeof(query_4.data));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read button features 4\n",
+ __func__);
+ return retval;
+ }
+
+ if (query_4.has_ctrl24)
+ rmi4_data->external_afe_buttons = true;
+ else
+ rmi4_data->external_afe_buttons = false;
+ }
+
if (!bdata->cap_button_map) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: cap_button_map is NULL in board file\n",
@@ -2945,7 +3330,7 @@ static void synaptics_rmi4_set_configured(struct synaptics_rmi4_data *rmi4_data)
static int synaptics_rmi4_alloc_fh(struct synaptics_rmi4_fn **fhandler,
struct synaptics_rmi4_fn_desc *rmi_fd, int page_number)
{
- *fhandler = kmalloc(sizeof(**fhandler), GFP_KERNEL);
+ *fhandler = kzalloc(sizeof(**fhandler), GFP_KERNEL);
if (!(*fhandler))
return -ENOMEM;
@@ -3124,11 +3509,29 @@ rescan_pdt:
case SYNAPTICS_RMI4_F35:
f35found = true;
break;
- case SYNAPTICS_RMI4_F54:
- rmi4_data->f54_cmd_base_addr =
- rmi_fd.cmd_base_addr |
+
+ case SYNAPTICS_RMI4_F51:
+ if (rmi4_data->hw_if->board_data->captouch_use) {
+ retval = synaptics_rmi4_alloc_fh(&fhandler,
+ &rmi_fd, page_number);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to alloc for F%d\n",
+ __func__,
+ rmi_fd.fn_number);
+ return retval;
+ }
+
+ fhandler->fn_number = SYNAPTICS_RMI4_F51;
+ fhandler->data = NULL;
+ fhandler->extra = NULL;
+ }
+#ifdef F51_DISCRETE_FORCE
+ rmi4_data->f51_query_base_addr =
+ rmi_fd.query_base_addr |
(page_number << 8);
break;
+#endif
}
/* Accumulate the interrupt count */
@@ -3328,9 +3731,13 @@ static void synaptics_rmi4_set_params(struct synaptics_rmi4_data *rmi4_data)
#ifdef REPORT_2D_PRESSURE
if (rmi4_data->report_pressure) {
input_set_abs_params(rmi4_data->input_dev,
- ABS_MT_PRESSURE, 0,
- MAX_F12_TOUCH_PRESSURE, 0, 0);
+ ABS_MT_PRESSURE, rmi4_data->force_min,
+ rmi4_data->force_max, 0, 0);
}
+#elif defined(F51_DISCRETE_FORCE)
+ input_set_abs_params(rmi4_data->input_dev,
+ ABS_MT_PRESSURE, 0,
+ FORCE_LEVEL_MAX, 0, 0);
#endif
#ifdef TYPE_B_PROTOCOL
@@ -3385,13 +3792,19 @@ static void synaptics_rmi4_wakeup_reconfigure(struct synaptics_rmi4_data *rmi4_d
synaptics_rmi4_sleep_enable(rmi4_data, !enable);
- if (enable)
- mdss_regulator_ctrl(rmi4_data, true);
+ if (enable) {
+ mdss_regulator_ctrl(rmi4_data, DISP_REG_ALL, true);
+ if (rmi4_data->hw_if->board_data->mdss_reset != 0)
+ gpio_set_value(rmi4_data->hw_if->board_data->mdss_reset, rmi4_data->hw_if->board_data->mdss_reset_state);
+ }
synaptics_rmi4_wakeup_gesture(rmi4_data, enable);
- if (!enable)
- mdss_regulator_ctrl(rmi4_data, false);
+ if (!enable) {
+ mdss_regulator_ctrl(rmi4_data, DISP_REG_ALL, false);
+ if (rmi4_data->hw_if->board_data->mdss_reset != 0)
+ gpio_set_value(rmi4_data->hw_if->board_data->mdss_reset, !rmi4_data->hw_if->board_data->mdss_reset_state);
+ }
synaptics_rmi4_irq_enable(rmi4_data, enable, false);
@@ -3451,52 +3864,6 @@ static void synaptics_key_ctrl(struct synaptics_rmi4_data *rmi4_data, bool enabl
return ;
}
-static void do_force_update(struct synaptics_rmi4_data *rmi4_data)
-{
- int retval;
- unsigned char command = 0x04;
- unsigned char timeout_count;
-
- retval = synaptics_rmi4_reg_write(rmi4_data,
- rmi4_data->f54_cmd_base_addr,
- &command,
- sizeof(command));
- if (retval < 0) {
- dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to write command\n",
- __func__);
- return;
- }
-
- timeout_count = 0;
- do {
- retval = synaptics_rmi4_reg_read(rmi4_data,
- rmi4_data->f54_cmd_base_addr,
- &command,
- sizeof(command));
- if (retval < 0) {
- dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to read command register\n",
- __func__);
- return;
- }
-
- if ((command & 0x04) == 0x00)
- break;
-
- msleep(100);
- timeout_count++;
- } while (timeout_count < COMMAND_TIMEOUT_100MS);
-
- if (timeout_count == COMMAND_TIMEOUT_100MS) {
- dev_err(rmi4_data->pdev->dev.parent,
- "%s: Timed out waiting for command completion\n",
- __func__);
- }
-
- return;
-}
-
static void cover_mode_set(struct synaptics_rmi4_data *rmi4_data, int enable)
{
struct synaptics_rmi4_f12_extra_data *extra_data;
@@ -3548,9 +3915,6 @@ static void cover_mode_set(struct synaptics_rmi4_data *rmi4_data, int enable)
}
synaptics_key_ctrl(rmi4_data, true);
-
- if (rmi4_data->chip_id == CHIP_ID_4322)
- do_force_update(rmi4_data);
} else {
retval = synaptics_rmi4_reg_read(rmi4_data,
fhandler->full_addr.ctrl_base + extra_data->ctrl26_offset,
@@ -3582,9 +3946,6 @@ static void cover_mode_set(struct synaptics_rmi4_data *rmi4_data, int enable)
}
synaptics_key_ctrl(rmi4_data, false);
-
- if (rmi4_data->chip_id == CHIP_ID_4322)
- do_force_update(rmi4_data);
}
mutex_unlock(&rmi4_data->rmi4_cover_mutex);
@@ -3606,12 +3967,15 @@ static void synaptics_rmi4_switch_mode_work(struct work_struct *work)
rmi4_data->enable_wakeup_gesture = value - INPUT_EVENT_WAKUP_MODE_OFF;
- if (rmi4_data->suspend && rmi4_data->chip_id != CHIP_ID_4322)
+ if (rmi4_data->suspend && rmi4_data->chip_id != bdata->chip_4322 && rmi4_data->chip_id != bdata->chip_4722)
synaptics_rmi4_wakeup_reconfigure(rmi4_data,
(bool)rmi4_data->enable_wakeup_gesture);
} else if (value >= INPUT_EVENT_COVER_MODE_OFF && value <= INPUT_EVENT_COVER_MODE_ON) {
rmi4_data->enable_cover_mode = value - INPUT_EVENT_COVER_MODE_OFF;
cover_mode_set(rmi4_data, rmi4_data->enable_cover_mode);
+ } else if (value >= INPUT_EVENT_CAPTOUCH_MODE_OFF && value <= INPUT_EVENT_CAPTOUCH_MODE_ON) {
+ if (bdata->captouch_use)
+ rmi4_data->homekey_wakeup = value - INPUT_EVENT_CAPTOUCH_MODE_OFF;
} else {
dev_err(rmi4_data->pdev->dev.parent,
"Does not support touch mode %d\n", value);
@@ -3986,12 +4350,6 @@ static int synaptics_rmi4_free_fingers(struct synaptics_rmi4_data *rmi4_data)
{
unsigned char ii;
- if (rmi4_data->input_dev == NULL) {
- dev_err(rmi4_data->pdev->dev.parent, "input_dev is NULL, do not report data\n");
-
- return 0;
- }
-
mutex_lock(&(rmi4_data->rmi4_report_mutex));
#ifdef TYPE_B_PROTOCOL
@@ -4010,7 +4368,7 @@ static int synaptics_rmi4_free_fingers(struct synaptics_rmi4_data *rmi4_data)
#endif
input_sync(rmi4_data->input_dev);
- if (rmi4_data->stylus_enable && rmi4_data->stylus_dev != NULL) {
+ if (rmi4_data->stylus_enable) {
input_report_key(rmi4_data->stylus_dev,
BTN_TOUCH, 0);
input_report_key(rmi4_data->stylus_dev,
@@ -4049,9 +4407,6 @@ static int synaptics_rmi4_sw_reset(struct synaptics_rmi4_data *rmi4_data)
return retval;
}
- if (rmi4_data->chip_id != CHIP_ID_3330)
- synaptics_rmi4_protection_film(rmi4_data);
-
return 0;
}
@@ -4345,7 +4700,7 @@ static void synaptics_rmi4_exp_fn_work(struct work_struct *work)
return;
}
-void synaptics_rmi4_new_function(struct synaptics_rmi4_exp_fn *exp_fn,
+void synaptics_rmi4_new_function_force(struct synaptics_rmi4_exp_fn *exp_fn,
bool insert)
{
struct synaptics_rmi4_exp_fhandler *exp_fhandler;
@@ -4389,7 +4744,6 @@ exit:
return;
}
-EXPORT_SYMBOL(synaptics_rmi4_new_function);
static void charger_reg_set(struct synaptics_rmi4_data *rmi4_data, bool enable)
{
@@ -4403,6 +4757,8 @@ static void charger_reg_set(struct synaptics_rmi4_data *rmi4_data, bool enable)
&val,
1);
if (retval < 0) {
+ pr_err("%s: Failed to read reg of charger noise\n", __func__);
+
mutex_unlock(&rmi4_data->rmi4_charger_mutex);
return ;
@@ -4418,6 +4774,9 @@ static void charger_reg_set(struct synaptics_rmi4_data *rmi4_data, bool enable)
&val,
1);
+ if (retval < 0)
+ pr_err("%s: Failed to write reg of charger noise\n", __func__);
+
mutex_unlock(&rmi4_data->rmi4_charger_mutex);
}
@@ -4452,31 +4811,167 @@ static int synaptics_power_supply_event(struct notifier_block *nb, unsigned long
return 0;
}
-static void synaptics_rmi4_protection_film(struct synaptics_rmi4_data *rmi4_data)
+#ifdef CONFIG_TOUCH_DEBUG_FS
+static int synaptics_tpdbg_suspend(struct synaptics_rmi4_data *rmi4_data)
{
- unsigned char value;
+ struct synaptics_rmi4_exp_fhandler *exp_fhandler;
+
+ synaptics_rmi4_irq_enable(rmi4_data, false, false);
+ if (!rmi4_data->enable_wakeup_gesture && !rmi4_data->homekey_wakeup)
+ synaptics_rmi4_sleep_enable(rmi4_data, true);
- value = 0x1e;
- synaptics_rmi4_reg_write(rmi4_data, BTN_DOZE_WAKEUP_TH, &value, sizeof(value));
+ if (rmi4_data->enable_wakeup_gesture || rmi4_data->homekey_wakeup) {
+ msleep(300);
+ synaptics_rmi4_wakeup_gesture(rmi4_data, true);
+ synaptics_rmi4_irq_enable(rmi4_data, true, false);
+ goto exit;
+ }
- value = 0x80;
- synaptics_rmi4_reg_write(rmi4_data, BTN_FAST_RELAX_RATE, &value, sizeof(value));
+ mutex_lock(&exp_data.mutex);
+ if (!list_empty(&exp_data.list)) {
+ list_for_each_entry(exp_fhandler, &exp_data.list, link)
+ if (exp_fhandler->exp_fn->suspend != NULL)
+ exp_fhandler->exp_fn->suspend(rmi4_data);
+ }
+ mutex_unlock(&exp_data.mutex);
- value = 0x0a;
- synaptics_rmi4_reg_write(rmi4_data, BTN_SLOW_RELAX_RATE, &value, sizeof(value));
+exit:
+ return 0;
+}
- value = 0x80;
- synaptics_rmi4_reg_write(rmi4_data, BTN_RELEASE_TH, &value, sizeof(value));
+static int synaptics_tpdbg_resume(struct synaptics_rmi4_data *rmi4_data)
+{
+ struct synaptics_rmi4_exp_fhandler *exp_fhandler;
+ const struct synaptics_dsx_board_data *bdata =
+ rmi4_data->hw_if->board_data;
- value = 0x54;
- synaptics_rmi4_reg_write(rmi4_data, BTN_TOUCH_TH1, &value, sizeof(value));
+ if (rmi4_data->enable_wakeup_gesture || rmi4_data->homekey_wakeup) {
+ synaptics_rmi4_wakeup_gesture(rmi4_data, false);
+ if (bdata->reset_gpio >= 0) {
+ gpio_set_value(bdata->reset_gpio, bdata->reset_on_state);
+ msleep(bdata->reset_active_ms);
+ gpio_set_value(bdata->reset_gpio, !bdata->reset_on_state);
+ msleep(bdata->reset_delay_ms);
+ }
+ } else {
+ rmi4_data->current_page = MASK_8BIT;
+ if (bdata->reset_gpio >= 0) {
+ gpio_set_value(bdata->reset_gpio, bdata->reset_on_state);
+ msleep(bdata->reset_active_ms);
+ gpio_set_value(bdata->reset_gpio, !bdata->reset_on_state);
+ msleep(bdata->reset_delay_ms);
+ }
- value = 0x54;
- synaptics_rmi4_reg_write(rmi4_data, BTN_TOUCH_TH2, &value, sizeof(value));
+ synaptics_rmi4_sleep_enable(rmi4_data, false);
+ synaptics_rmi4_irq_enable(rmi4_data, true, false);
- do_force_update(rmi4_data);
+ mutex_lock(&exp_data.mutex);
+ if (!list_empty(&exp_data.list)) {
+ list_for_each_entry(exp_fhandler, &exp_data.list, link)
+ if (exp_fhandler->exp_fn->resume != NULL)
+ exp_fhandler->exp_fn->resume(rmi4_data);
+ }
+ mutex_unlock(&exp_data.mutex);
+ }
+
+ return 0;
+}
+
+static void tpdbg_shutdown(struct synaptics_rmi4_data *rmi4_data, bool sleep)
+{
+ synaptics_rmi4_sleep_enable(rmi4_data, sleep);
+}
+
+static void tpdbg_suspend(struct synaptics_rmi4_data *rmi4_data, bool enable)
+{
+ if (enable)
+ synaptics_tpdbg_suspend(rmi4_data);
+ else
+ synaptics_tpdbg_resume(rmi4_data);
+}
+
+static int tpdbg_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+
+ return 0;
+}
+
+ssize_t tpdbg_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
+{
+ const char *str = "cmd support as below:\n \
+ \necho \"irq-disable\" or \"irq-enable\" to ctrl irq\n \
+ \necho \"shutdown-en\" of \"shutdown-off\" to ctrl panel in or off sleep mode\n \
+ \necho \"suspend-en\" or \"suspend-off\" to ctrl panel in or off suspend status\n";
+
+ loff_t pos = *ppos;
+ int len = strlen(str);
+
+ if (pos < 0)
+ return -EINVAL;
+ if (pos >= len)
+ return 0;
+
+ if (copy_to_user(buf, str, len))
+ return -EFAULT;
+
+ *ppos = pos + len;
+
+ return len;
}
+ssize_t tpdbg_write(struct file *file, const char __user *buf, size_t size, loff_t *ppos)
+{
+ struct synaptics_rmi4_data *rmi4_data = file->private_data;
+ char *cmd = kzalloc(size + 1, GFP_KERNEL);
+ int ret = size;
+
+ if (!cmd)
+ return -ENOMEM;
+
+ if (copy_from_user(cmd, buf, size)) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ cmd[size] = '\0';
+
+ if (!strncmp(cmd, "irq-disable", 11))
+ disable_irq(rmi4_data->irq);
+ else if (!strncmp(cmd, "irq-enable", 10))
+ enable_irq(rmi4_data->irq);
+ else if (!strncmp(cmd, "shutdown-en", 11))
+ tpdbg_shutdown(rmi4_data, true);
+ else if (!strncmp(cmd, "shutdown-off", 12))
+ tpdbg_shutdown(rmi4_data, false);
+ else if (!strncmp(cmd, "suspend-en", 10))
+ tpdbg_suspend(rmi4_data, true);
+ else if (!strncmp(cmd, "suspend-off", 11))
+ tpdbg_suspend(rmi4_data, false);
+out:
+ kfree(cmd);
+
+ return ret;
+}
+
+int tpdbg_release (struct inode *inode, struct file *file)
+{
+ file->private_data = NULL;
+
+ return 0;
+}
+
+static const struct file_operations tpdbg_operations = {
+ .owner = THIS_MODULE,
+ .open = tpdbg_open,
+ .read = tpdbg_read,
+ .write = tpdbg_write,
+ .release = tpdbg_release,
+};
+#endif
+
+extern unsigned int get_hw_version_major(void);
+
static int synaptics_rmi4_probe(struct platform_device *pdev)
{
int retval;
@@ -4486,15 +4981,20 @@ static int synaptics_rmi4_probe(struct platform_device *pdev)
const struct synaptics_dsx_board_data *bdata;
hw_if = pdev->dev.platform_data;
+ if (!hw_if) {
+ dev_err(&pdev->dev,
+ "%s: No hardware interface found\n",
+ __func__);
+ return -EINVAL;
+ }
bdata = hw_if->board_data;
if (!bdata) {
dev_err(&pdev->dev,
- "%s: No board data found\n",
- __func__);
+ "%s: No board data found\n",
+ __func__);
return -EINVAL;
}
-
rmi4_data = kzalloc(sizeof(*rmi4_data), GFP_KERNEL);
if (!rmi4_data) {
dev_err(&pdev->dev,
@@ -4510,15 +5010,18 @@ static int synaptics_rmi4_probe(struct platform_device *pdev)
rmi4_data->irq_enabled = false;
rmi4_data->fingers_on_2d = false;
rmi4_data->wakeup_en = false;
+ rmi4_data->homekey_wakeup = false;
rmi4_data->reset_device = synaptics_rmi4_reset_device;
rmi4_data->irq_enable = synaptics_rmi4_irq_enable;
rmi4_data->sleep_enable = synaptics_rmi4_sleep_enable;
+ rmi4_data->hw_version = get_hw_version_major();
mutex_init(&(rmi4_data->rmi4_reset_mutex));
mutex_init(&(rmi4_data->rmi4_report_mutex));
mutex_init(&(rmi4_data->rmi4_io_ctrl_mutex));
mutex_init(&(rmi4_data->rmi4_exp_init_mutex));
+ mutex_init(&(rmi4_data->rmi4_irq_enable_mutex));
mutex_init(&(rmi4_data->rmi4_cover_mutex));
mutex_init(&(rmi4_data->rmi4_charger_mutex));
@@ -4567,6 +5070,7 @@ static int synaptics_rmi4_probe(struct platform_device *pdev)
goto err_pinctrl_init;
}
+
retval = synaptics_rmi4_set_input_dev(rmi4_data);
if (retval < 0) {
dev_err(&pdev->dev,
@@ -4578,7 +5082,7 @@ static int synaptics_rmi4_probe(struct platform_device *pdev)
synaptics_rmi4_query_chip_id(rmi4_data);
#ifdef CONFIG_FB
- if (rmi4_data->chip_id == CHIP_ID_3330)
+ if (rmi4_data->chip_id != bdata->chip_4322 && rmi4_data->chip_id != bdata->chip_4722)
rmi4_data->fb_notifier.notifier_call = synaptics_rmi4_fb_notifier_cb_jdi;
else
rmi4_data->fb_notifier.notifier_call = synaptics_rmi4_fb_notifier_cb_lgd;
@@ -4645,13 +5149,24 @@ static int synaptics_rmi4_probe(struct platform_device *pdev)
}
+ if (bdata->captouch_use) {
+ retval = sysfs_create_file(&rmi4_data->pdev->dev.parent->kobj, &dev_attr_captouch.attr);
+
+ if (retval < 0) {
+ dev_err(&pdev->dev,
+ "%s: Failed to create sysfs attributes\n",
+ __func__);
+ goto err_sysfs;
+ }
+ }
+
retval = sysfs_create_file(&rmi4_data->pdev->dev.parent->kobj, &dev_attr_panel_color.attr);
if (retval < 0) {
dev_err(&pdev->dev,
"%s: Failed to create sysfs attributes\n",
__func__);
- goto err_sysfs;
+ goto err_sysfs_captouch;
}
#if defined(CONFIG_SECURE_TOUCH)
@@ -4674,6 +5189,22 @@ static int synaptics_rmi4_probe(struct platform_device *pdev)
}
#endif
+ retval = sysfs_create_file(&rmi4_data->pdev->dev.parent->kobj, &dev_attr_panel_vendor.attr);
+
+ if (retval < 0) {
+ dev_err(&pdev->dev,
+ "%s: Failed to create sysfs attributes\n",
+ __func__);
+ goto err_sysfs_panel_vendor;
+ }
+
+#ifdef CONFIG_TOUCH_DEBUG_FS
+ rmi4_data->debugfs = debugfs_create_dir("tp_debug", NULL);
+ if (rmi4_data->debugfs) {
+ debugfs_create_file("switch_state", 0660, rmi4_data->debugfs, rmi4_data, &tpdbg_operations);
+ }
+#endif
+
dev_set_drvdata(rmi4_data->pdev->dev.parent, rmi4_data);
rmi4_data->rb_workqueue =
@@ -4700,7 +5231,8 @@ static int synaptics_rmi4_probe(struct platform_device *pdev)
synaptics_secure_touch_init(rmi4_data);
synaptics_secure_touch_stop(rmi4_data, 1);
- if (rmi4_data->chip_id != CHIP_ID_3330) {
+
+ if (rmi4_data->chip_id == bdata->chip_4322 || rmi4_data->chip_id == bdata->chip_4722) {
rmi4_data->power_supply_notif.notifier_call = synaptics_power_supply_event;
INIT_WORK(&rmi4_data->noise_work, synaptics_noise_work);
power_supply_reg_notifier(&rmi4_data->power_supply_notif);
@@ -4709,12 +5241,17 @@ static int synaptics_rmi4_probe(struct platform_device *pdev)
return retval;
+err_sysfs_panel_vendor:
#if defined(CONFIG_SECURE_TOUCH)
+ sysfs_remove_file(&rmi4_data->pdev->dev.parent->kobj, &dev_attr_secure_touch_enable.attr);
err_sysfs_secure_enable:
sysfs_remove_file(&rmi4_data->pdev->dev.parent->kobj, &dev_attr_secure_touch.attr);
err_sysfs_secure:
sysfs_remove_file(&rmi4_data->pdev->dev.parent->kobj, &dev_attr_panel_color.attr);
#endif
+err_sysfs_captouch:
+ if (bdata->captouch_use)
+ sysfs_remove_file(&rmi4_data->pdev->dev.parent->kobj, &dev_attr_captouch.attr);
err_sysfs:
for (attr_count--; attr_count >= 0; attr_count--) {
sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
@@ -4780,9 +5317,6 @@ static int synaptics_rmi4_remove(struct platform_device *pdev)
struct synaptics_rmi4_data *rmi4_data = platform_get_drvdata(pdev);
const struct synaptics_dsx_board_data *bdata =
rmi4_data->hw_if->board_data;
-
- if (rmi4_data->chip_id != CHIP_ID_3330)
- power_supply_unreg_notifier(&rmi4_data->power_supply_notif);
#ifdef FB_READY_RESET
cancel_work_sync(&rmi4_data->reset_work);
flush_workqueue(rmi4_data->reset_workqueue);
@@ -4797,10 +5331,19 @@ static int synaptics_rmi4_remove(struct platform_device *pdev)
flush_workqueue(rmi4_data->rb_workqueue);
destroy_workqueue(rmi4_data->rb_workqueue);
+#ifdef CONFIG_TOUCH_DEBUG_FS
+ debugfs_remove_recursive(rmi4_data->debugfs);
+#endif
+
+ sysfs_remove_file(&rmi4_data->pdev->dev.parent->kobj, &dev_attr_panel_vendor.attr);
#if defined(CONFIG_SECURE_TOUCH)
sysfs_remove_file(&rmi4_data->pdev->dev.parent->kobj, &dev_attr_secure_touch_enable.attr);
sysfs_remove_file(&rmi4_data->pdev->dev.parent->kobj, &dev_attr_secure_touch.attr);
#endif
+
+ if (bdata->captouch_use)
+ sysfs_remove_file(&rmi4_data->pdev->dev.parent->kobj, &dev_attr_captouch.attr);
+
sysfs_remove_file(&rmi4_data->pdev->dev.parent->kobj, &dev_attr_panel_color.attr);
for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
@@ -4894,15 +5437,16 @@ static void synaptics_rmi4_f11_wg(struct synaptics_rmi4_data *rmi4_data,
return;
}
-static void mdss_regulator_ctrl(struct synaptics_rmi4_data *rmi4_data, bool enable)
+static void mdss_regulator_ctrl(struct synaptics_rmi4_data *rmi4_data, unsigned int flag, bool enable)
{
int retval = 0;
+ static unsigned int status;
if (rmi4_data == NULL)
return;
if (enable) {
- if (rmi4_data->disp_reg) {
+ if (rmi4_data->disp_reg && (flag & DISP_REG_VDD) && !(status & DISP_REG_VDD)) {
retval = regulator_enable(rmi4_data->disp_reg);
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
@@ -4910,9 +5454,11 @@ static void mdss_regulator_ctrl(struct synaptics_rmi4_data *rmi4_data, bool enab
__func__);
return;
}
+
+ status |= DISP_REG_VDD;
}
- if (rmi4_data->lab_reg) {
+ if (rmi4_data->lab_reg && (flag & DISP_REG_LAB) && !(status & DISP_REG_LAB)) {
retval = regulator_enable(rmi4_data->lab_reg);
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
@@ -4920,9 +5466,11 @@ static void mdss_regulator_ctrl(struct synaptics_rmi4_data *rmi4_data, bool enab
__func__);
return;
}
+
+ status |= DISP_REG_LAB;
}
- if (rmi4_data->ibb_reg) {
+ if (rmi4_data->ibb_reg && (flag & DISP_REG_IBB) && !(status & DISP_REG_IBB)) {
retval = regulator_enable(rmi4_data->ibb_reg);
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
@@ -4930,9 +5478,11 @@ static void mdss_regulator_ctrl(struct synaptics_rmi4_data *rmi4_data, bool enab
__func__);
return;
}
+
+ status |= DISP_REG_IBB;
}
} else {
- if (rmi4_data->ibb_reg) {
+ if (rmi4_data->ibb_reg && (flag & DISP_REG_IBB) && (status & DISP_REG_IBB)) {
retval = regulator_disable(rmi4_data->ibb_reg);
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
@@ -4940,9 +5490,11 @@ static void mdss_regulator_ctrl(struct synaptics_rmi4_data *rmi4_data, bool enab
__func__);
return;
}
+
+ status &= ~DISP_REG_IBB;
}
- if (rmi4_data->lab_reg) {
+ if (rmi4_data->lab_reg && (flag & DISP_REG_LAB) && (status & DISP_REG_LAB)) {
retval = regulator_disable(rmi4_data->lab_reg);
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
@@ -4950,9 +5502,11 @@ static void mdss_regulator_ctrl(struct synaptics_rmi4_data *rmi4_data, bool enab
__func__);
return;
}
+
+ status &= ~DISP_REG_LAB;
}
- if (rmi4_data->disp_reg) {
+ if (rmi4_data->disp_reg && (flag & DISP_REG_VDD) && (status & DISP_REG_VDD)) {
retval = regulator_disable(rmi4_data->disp_reg);
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
@@ -4960,6 +5514,8 @@ static void mdss_regulator_ctrl(struct synaptics_rmi4_data *rmi4_data, bool enab
__func__);
return;
}
+
+ status &= ~DISP_REG_VDD;
}
}
}
@@ -5004,6 +5560,7 @@ static void synaptics_rmi4_f12_wg(struct synaptics_rmi4_data *rmi4_data,
fhandler->full_addr.ctrl_base + offset,
reporting_control,
sizeof(reporting_control));
+
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to change reporting mode\n",
@@ -5014,6 +5571,51 @@ static void synaptics_rmi4_f12_wg(struct synaptics_rmi4_data *rmi4_data,
return;
}
+static void synaptics_rmi4_gesture_ctrl(struct synaptics_rmi4_data *rmi4_data, unsigned char value)
+{
+ struct synaptics_rmi4_f12_extra_data *extra_data;
+ struct synaptics_rmi4_fn *fhandler;
+ struct synaptics_rmi4_device_info *rmi;
+ int retval;
+
+ rmi = &(rmi4_data->rmi4_mod_info);
+
+ list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
+ if (fhandler->fn_number == SYNAPTICS_RMI4_F12)
+ break;
+ }
+
+ extra_data = (struct synaptics_rmi4_f12_extra_data *)fhandler->extra;
+
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ fhandler->full_addr.ctrl_base + extra_data->ctrl27_offset,
+ &value,
+ 1);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to switch double click mode\n",
+ __func__);
+ }
+}
+
+static bool check_captouch_support(struct synaptics_rmi4_data *rmi4_data)
+{
+ struct synaptics_dsx_board_data *bdata = NULL;
+
+ if (rmi4_data == NULL)
+ return false;
+
+ bdata = rmi4_data->hw_if->board_data;
+
+ if (bdata == NULL)
+ return false;
+
+ if (bdata->captouch_use && (captouch_get_status_ptr != NULL) && !captouch_get_status_ptr())
+ return true;
+ else
+ return false;
+}
+
static void synaptics_rmi4_wakeup_gesture(struct synaptics_rmi4_data *rmi4_data,
bool enable)
{
@@ -5022,7 +5624,14 @@ static void synaptics_rmi4_wakeup_gesture(struct synaptics_rmi4_data *rmi4_data,
else if (rmi4_data->f12_wakeup_gesture)
synaptics_rmi4_f12_wg(rmi4_data, enable);
- return;
+ if (rmi4_data->hw_if->board_data->captouch_use) {
+ if (rmi4_data->enable_wakeup_gesture && rmi4_data->homekey_wakeup)
+ synaptics_rmi4_gesture_ctrl(rmi4_data, DOUBLE_TAP | HOMEKEY_WAKEUP);
+ else if (rmi4_data->enable_wakeup_gesture && !rmi4_data->homekey_wakeup)
+ synaptics_rmi4_gesture_ctrl(rmi4_data, DOUBLE_TAP);
+ else if (!rmi4_data->enable_wakeup_gesture && rmi4_data->homekey_wakeup)
+ synaptics_rmi4_gesture_ctrl(rmi4_data, HOMEKEY_WAKEUP);
+ }
}
#ifdef CONFIG_FB
@@ -5036,6 +5645,7 @@ static int synaptics_rmi4_fb_notifier_cb_jdi(struct notifier_block *self,
struct synaptics_rmi4_data *rmi4_data =
container_of(self, struct synaptics_rmi4_data,
fb_notifier);
+
const struct synaptics_dsx_board_data *bdata = NULL;
if (rmi4_data->hw_if->board_data)
@@ -5053,17 +5663,26 @@ static int synaptics_rmi4_fb_notifier_cb_jdi(struct notifier_block *self,
} else if ((*transition == FB_BLANK_UNBLANK) || (*transition == FB_BLANK_NORMAL)) {
synaptics_rmi4_resume(&rmi4_data->pdev->dev);
rmi4_data->fb_ready = true;
- if (rmi4_data->enable_wakeup_gesture) {
+ if (rmi4_data->wakeup_en) {
mdss_panel_reset_skip_enable(false);
- mdss_regulator_ctrl(rmi4_data, false);
+ if (rmi4_data->enable_wakeup_gesture) {
+ mdss_regulator_ctrl(rmi4_data, DISP_REG_ALL, false);
+ } else if (rmi4_data->homekey_wakeup) {
+ mdss_regulator_ctrl(rmi4_data, DISP_REG_VDD, false);
+ }
+ rmi4_data->wakeup_en = false;
}
}
} else if (event == FB_EARLY_EVENT_BLANK) {
transition = evdata->data;
if ((*transition == FB_BLANK_POWERDOWN) || (*transition == FB_BLANK_NORMAL)) {
if (rmi4_data->enable_wakeup_gesture) {
- mdss_regulator_ctrl(rmi4_data, true);
+ rmi4_data->wakeup_en = true;
+ mdss_regulator_ctrl(rmi4_data, DISP_REG_ALL, true);
mdss_panel_reset_skip_enable(true);
+ } else if (rmi4_data->homekey_wakeup) {
+ rmi4_data->wakeup_en = true;
+ mdss_regulator_ctrl(rmi4_data, DISP_REG_VDD, true);
}
} else if ((*transition == FB_BLANK_UNBLANK) || (*transition == FB_BLANK_NORMAL)) {
if (bdata->reset_gpio >= 0 && rmi4_data->suspend) {
@@ -5071,7 +5690,7 @@ static int synaptics_rmi4_fb_notifier_cb_jdi(struct notifier_block *self,
msleep(bdata->reset_active_ms);
gpio_set_value(bdata->reset_gpio, !bdata->reset_on_state);
}
- if (rmi4_data->enable_wakeup_gesture) {
+ if (rmi4_data->wakeup_en && rmi4_data->enable_wakeup_gesture) {
if (bdata->mdss_reset != 0) {
gpio_set_value(bdata->mdss_reset, !bdata->mdss_reset_state);
msleep(10);
@@ -5095,38 +5714,48 @@ static int synaptics_rmi4_fb_notifier_cb_lgd(struct notifier_block *self,
container_of(self, struct synaptics_rmi4_data,
fb_notifier);
+ if (mdss_prim_panel_is_dead())
+ return 0;
+
/* Receive notifications from primary panel only */
if (evdata && evdata->data && rmi4_data && mdss_panel_is_prim(evdata->info)) {
if (event == FB_EVENT_BLANK) {
transition = evdata->data;
if ((*transition == FB_BLANK_UNBLANK) || (*transition == FB_BLANK_NORMAL)) {
- synaptics_rmi4_resume(&rmi4_data->pdev->dev);
- rmi4_data->fb_ready = true;
- if (rmi4_data->wakeup_en && rmi4_data->enable_wakeup_gesture) {
- mdss_panel_reset_skip_enable(false);
- mdss_regulator_ctrl(rmi4_data, false);
+ mdss_regulator_ctrl(rmi4_data, DISP_REG_ALL, false);
+ mdss_panel_reset_skip_enable(false);
+ if (rmi4_data->wakeup_en)
rmi4_data->wakeup_en = false;
+ } else if ((*transition == FB_BLANK_POWERDOWN) || (*transition == FB_BLANK_NORMAL)) {
+ msleep(160);
+ synaptics_rmi4_suspend(&rmi4_data->pdev->dev);
+ rmi4_data->fb_ready = false;
+
+ if (!rmi4_data->wakeup_en) {
+ msleep(10);
+ mdss_regulator_ctrl(rmi4_data, DISP_REG_IBB, false);
+ msleep(10);
+ mdss_regulator_ctrl(rmi4_data, DISP_REG_LAB, false);
}
}
} else if (event == FB_EARLY_EVENT_BLANK) {
transition = evdata->data;
if (*transition == FB_BLANK_UNBLANK) {
- if (rmi4_data->wakeup_en && rmi4_data->enable_wakeup_gesture) {
- if (rmi4_data->hw_if->board_data->mdss_reset != 0) {
- gpio_set_value(rmi4_data->hw_if->board_data->mdss_reset, !rmi4_data->hw_if->board_data->mdss_reset_state);
- msleep(10);
- gpio_set_value(rmi4_data->hw_if->board_data->mdss_reset, rmi4_data->hw_if->board_data->mdss_reset_state);
- msleep(100);
- }
+ if (!rmi4_data->wakeup_en) {
+ mdss_regulator_ctrl(rmi4_data, DISP_REG_LAB, true);
+ msleep(10);
+ mdss_regulator_ctrl(rmi4_data, DISP_REG_IBB, true);
+ msleep(10);
}
+
+ synaptics_rmi4_resume(&rmi4_data->pdev->dev);
+ rmi4_data->fb_ready = true;
+ msleep(10);
} else if ((*transition == FB_BLANK_POWERDOWN) || (*transition == FB_BLANK_NORMAL)) {
- if (rmi4_data->enable_wakeup_gesture) {
+ mdss_panel_reset_skip_enable(true);
+ mdss_regulator_ctrl(rmi4_data, DISP_REG_ALL, true);
+ if (rmi4_data->enable_wakeup_gesture || rmi4_data->homekey_wakeup)
rmi4_data->wakeup_en = true;
- mdss_panel_reset_skip_enable(true);
- mdss_regulator_ctrl(rmi4_data, true);
- }
- synaptics_rmi4_suspend(&rmi4_data->pdev->dev);
- rmi4_data->fb_ready = false;
}
}
}
@@ -5231,12 +5860,11 @@ static int synaptics_rmi4_suspend(struct device *dev)
if (rmi4_data->stay_awake || rmi4_data->suspend)
return 0;
- if (bdata->cut_off_power || (rmi4_data->chip_id == CHIP_ID_4322 && !rmi4_data->wakeup_en)) {
+ if (bdata->cut_off_power) {
if (rmi4_data->fw_updating)
return 0;
synaptics_rmi4_irq_enable(rmi4_data, false, false);
- synaptics_rmi4_free_fingers(rmi4_data);
if (bdata->power_gpio >= 0)
gpio_set_value(bdata->power_gpio,
@@ -5248,20 +5876,25 @@ static int synaptics_rmi4_suspend(struct device *dev)
mdelay(bdata->reset_active_ms);
}
- synaptics_rmi4_enable_reg(rmi4_data, false);
+ if (!bdata->power_ctrl || (bdata->power_ctrl && rmi4_data->hw_version > 2))
+ synaptics_rmi4_enable_reg(rmi4_data, false);
} else {
synaptics_secure_touch_stop(rmi4_data, 1);
- synaptics_rmi4_free_fingers(rmi4_data);
-
if (!rmi4_data->suspend) {
synaptics_rmi4_irq_enable(rmi4_data, false, false);
- if (!rmi4_data->enable_wakeup_gesture)
+ if (!rmi4_data->wakeup_en) {
+ if (rmi4_data->chip_id == bdata->chip_4322 || rmi4_data->chip_id == bdata->chip_4722) {
+ synaptics_rmi4_wakeup_gesture(rmi4_data, true);
+ msleep(10);
+ }
synaptics_rmi4_sleep_enable(rmi4_data, true);
+ }
}
- if (rmi4_data->enable_wakeup_gesture) {
- msleep(300);
+ if (rmi4_data->wakeup_en) {
+ if (rmi4_data->chip_id != bdata->chip_4322 && rmi4_data->chip_id != bdata->chip_4722)
+ msleep(300);
synaptics_rmi4_wakeup_gesture(rmi4_data, true);
synaptics_rmi4_irq_enable(rmi4_data, true, false);
goto exit;
@@ -5277,6 +5910,8 @@ static int synaptics_rmi4_suspend(struct device *dev)
}
exit:
+ synaptics_rmi4_free_fingers(rmi4_data);
+
rmi4_data->suspend = true;
return 0;
@@ -5304,8 +5939,9 @@ static int synaptics_rmi4_resume(struct device *dev)
if (rmi4_data->stay_awake || !rmi4_data->suspend)
return 0;
- if (bdata->cut_off_power || (rmi4_data->chip_id == CHIP_ID_4322 && !rmi4_data->wakeup_en)) {
- synaptics_rmi4_enable_reg(rmi4_data, true);
+ if (bdata->cut_off_power) {
+ if (!bdata->power_ctrl || (bdata->power_ctrl && rmi4_data->hw_version > 2))
+ synaptics_rmi4_enable_reg(rmi4_data, true);
if (bdata->power_gpio >= 0) {
gpio_set_value(bdata->power_gpio,
@@ -5320,17 +5956,19 @@ static int synaptics_rmi4_resume(struct device *dev)
}
synaptics_rmi4_irq_enable(rmi4_data, true, false);
-
- if (rmi4_data->enable_cover_mode)
- cover_mode_set(rmi4_data, rmi4_data->enable_cover_mode);
} else {
synaptics_secure_touch_stop(rmi4_data, 0);
- if (rmi4_data->enable_wakeup_gesture) {
+ if (rmi4_data->wakeup_en) {
synaptics_rmi4_wakeup_gesture(rmi4_data, false);
} else {
rmi4_data->current_page = MASK_8BIT;
- synaptics_rmi4_sleep_enable(rmi4_data, false);
+
+ if (rmi4_data->chip_id == bdata->chip_4322 || rmi4_data->chip_id == bdata->chip_4722) {
+ synaptics_rmi4_wakeup_gesture(rmi4_data, false);
+ rmi4_data->sensor_sleep = false;
+ } else
+ synaptics_rmi4_sleep_enable(rmi4_data, false);
synaptics_rmi4_irq_enable(rmi4_data, true, false);
#ifdef FB_READY_RESET
@@ -5354,11 +5992,6 @@ static int synaptics_rmi4_resume(struct device *dev)
cover_mode_set(rmi4_data, rmi4_data->enable_cover_mode);
}
- if (rmi4_data->chip_id != CHIP_ID_3330 && rmi4_data->is_usb_plug_in)
- charger_reg_set(rmi4_data, true);
-
- if (rmi4_data->chip_id != CHIP_ID_3330)
- synaptics_rmi4_protection_film(rmi4_data);
rmi4_data->suspend = false;
return 0;
@@ -5372,7 +6005,7 @@ static int synaptics_rmi4_pm_suspend(struct device *dev)
rmi4_data->hw_if->board_data;
if (device_may_wakeup(dev) &&
- rmi4_data->enable_wakeup_gesture &&
+ rmi4_data->wakeup_en &&
!bdata->cut_off_power) {
dev_info(rmi4_data->pdev->dev.parent,
"Enable touch irq wake\n");
@@ -5391,7 +6024,7 @@ static int synaptics_rmi4_pm_resume(struct device *dev)
rmi4_data->hw_if->board_data;
if (device_may_wakeup(dev) &&
- rmi4_data->enable_wakeup_gesture &&
+ rmi4_data->wakeup_en &&
!bdata->cut_off_power) {
dev_info(rmi4_data->pdev->dev.parent,
"Disable touch irq wake\n");
@@ -5410,7 +6043,7 @@ static const struct dev_pm_ops synaptics_rmi4_dev_pm_ops = {
static struct platform_driver synaptics_rmi4_driver = {
.driver = {
- .name = PLATFORM_DRIVER_NAME,
+ .name = PLATFORM_DRIVER_FORCE,
.owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &synaptics_rmi4_dev_pm_ops,
@@ -5424,7 +6057,7 @@ static int __init synaptics_rmi4_init(void)
{
int retval;
- retval = synaptics_rmi4_bus_init();
+ retval = synaptics_rmi4_bus_init_force();
if (retval)
return retval;
@@ -5435,7 +6068,7 @@ static void __exit synaptics_rmi4_exit(void)
{
platform_driver_unregister(&synaptics_rmi4_driver);
- synaptics_rmi4_bus_exit();
+ synaptics_rmi4_bus_exit_force();
return;
}
diff --git a/synaptics_dsx_core.h b/synaptics_dsx_core.h
index 588915c..5a96473 100644
--- a/synaptics_dsx_core.h
+++ b/synaptics_dsx_core.h
@@ -16,6 +16,20 @@
* 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.
+ *
+ * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS
+ * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
+ * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS.
+ * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED
+ * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES
+ * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS'
+ * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S.
+ * DOLLARS.
*/
#ifndef _SYNAPTICS_DSX_RMI4_H_
@@ -24,10 +38,7 @@
#define SYNAPTICS_DS4 (1 << 0)
#define SYNAPTICS_DS5 (1 << 1)
#define SYNAPTICS_DSX_DRIVER_PRODUCT (SYNAPTICS_DS4 | SYNAPTICS_DS5)
-#define SYNAPTICS_DSX_DRIVER_VERSION 0x2050
-
-#define CHIP_ID_3330 1
-#define CHIP_ID_4322 2
+#define SYNAPTICS_DSX_DRIVER_VERSION 0x2065
#include <linux/version.h>
#ifdef CONFIG_FB
@@ -37,6 +48,7 @@
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
#endif
+
#if defined(CONFIG_SECURE_TOUCH)
#include <linux/completion.h>
#include <linux/atomic.h>
@@ -63,7 +75,7 @@
#define PDT_ENTRY_SIZE (0x0006)
#define PAGES_TO_SERVICE (10)
#define PAGE_SELECT_LEN (2)
-#define ADDRESS_WORD_LEN (2)
+#define ADDRESS_LEN (2)
#define SYNAPTICS_RMI4_F01 (0x01)
#define SYNAPTICS_RMI4_F11 (0x11)
@@ -182,9 +194,9 @@ struct synaptics_rmi4_f11_extra_data {
* @data15_offset: offset to F12_2D_DATA15 register
* @data15_size: size of F12_2D_DATA15 register
* @data15_data: buffer for reading F12_2D_DATA15 register
- * @data23_offset: offset to F12_2D_DATA23 register
- * @data23_size: size of F12_2D_DATA23 register
- * @data23_data: buffer for reading F12_2D_DATA23 register
+ * @data29_offset: offset to F12_2D_DATA29 register
+ * @data29_size: size of F12_2D_DATA29 register
+ * @data29_data: buffer for reading F12_2D_DATA29 register
* @ctrl20_offset: offset to F12_2D_CTRL20 register
*/
struct synaptics_rmi4_f12_extra_data {
@@ -193,11 +205,12 @@ struct synaptics_rmi4_f12_extra_data {
unsigned char data15_offset;
unsigned char data15_size;
unsigned char data15_data[(F12_FINGERS_TO_SUPPORT + 7) / 8];
- unsigned char data23_offset;
- unsigned char data23_size;
- unsigned char data23_data[F12_FINGERS_TO_SUPPORT];
+ unsigned char data29_offset;
+ unsigned char data29_size;
+ unsigned char data29_data[F12_FINGERS_TO_SUPPORT * 2];
unsigned char ctrl20_offset;
unsigned char ctrl26_offset;
+ unsigned char ctrl27_offset;
};
/*
@@ -265,6 +278,7 @@ struct synaptics_rmi4_device_info {
* @rmi4_report_mutex: mutex for input event reporting
* @rmi4_io_ctrl_mutex: mutex for communication interface I/O
* @rmi4_exp_init_mutex: mutex for expansion function module initialization
+ * @rmi4_irq_enable_mutex: mutex for enabling/disabling interrupt
* @rb_work: work for rebuilding input device
* @rb_workqueue: workqueue for rebuilding input device
* @fb_notifier: framebuffer notifier client
@@ -305,9 +319,11 @@ struct synaptics_rmi4_device_info {
* @report_pressure: flag to indicate reporting of pressure data
* @stylus_enable: flag to indicate reporting of stylus data
* @eraser_enable: flag to indicate reporting of eraser data
+ * @external_afe_buttons: flag to indicate presence of external AFE buttons
* @reset_device: pointer to device reset function
* @irq_enable: pointer to interrupt enable function
* @sleep_enable: pointer to sleep enable function
+ * @report_touch: pointer to touch reporting function
*/
struct synaptics_rmi4_data {
struct platform_device *pdev;
@@ -327,6 +343,7 @@ struct synaptics_rmi4_data {
struct mutex rmi4_exp_init_mutex;
struct mutex rmi4_cover_mutex;
struct mutex rmi4_charger_mutex;
+ struct mutex rmi4_irq_enable_mutex;
struct delayed_work rb_work;
struct workqueue_struct *rb_workqueue;
#ifdef CONFIG_FB
@@ -353,12 +370,18 @@ struct synaptics_rmi4_data {
unsigned short f01_cmd_base_addr;
unsigned short f01_ctrl_base_addr;
unsigned short f01_data_base_addr;
- unsigned short f54_cmd_base_addr;
+#ifdef F51_DISCRETE_FORCE
+ unsigned short f51_query_base_addr;
+#endif
+ unsigned int hw_version;
unsigned int firmware_id;
unsigned char lockdown_info[LOCKDOWN_INFO_SIZE];
+ unsigned char valid_button_count;
int irq;
int sensor_max_x;
int sensor_max_y;
+ int force_min;
+ int force_max;
int chip_id;
bool flash_prog_mode;
bool irq_enabled;
@@ -375,18 +398,26 @@ struct synaptics_rmi4_data {
bool report_pressure;
bool stylus_enable;
bool eraser_enable;
+ bool external_afe_buttons;
bool fw_updating;
bool wakeup_en;
+ bool homekey_wakeup;
int (*reset_device)(struct synaptics_rmi4_data *rmi4_data,
bool rebuild);
int (*irq_enable)(struct synaptics_rmi4_data *rmi4_data, bool enable,
bool attn_only);
void (*sleep_enable)(struct synaptics_rmi4_data *rmi4_data,
bool enable);
+ void (*report_touch)(struct synaptics_rmi4_data *rmi4_data,
+ struct synaptics_rmi4_fn *fhandler);
struct pinctrl *ts_pinctrl;
struct pinctrl_state *pinctrl_state_active;
struct pinctrl_state *pinctrl_state_suspend;
+#ifdef CONFIG_TOUCH_DEBUG_FS
+ struct dentry *debugfs;
+#endif
+
#if defined(CONFIG_SECURE_TOUCH)
atomic_t st_enabled;
atomic_t st_pending_irqs;
@@ -437,11 +468,11 @@ struct synaptics_rmi4_mode_switch {
struct work_struct switch_mode_work;
};
-int synaptics_rmi4_bus_init(void);
+int synaptics_rmi4_bus_init_force(void);
-void synaptics_rmi4_bus_exit(void);
+void synaptics_rmi4_bus_exit_force(void);
-void synaptics_rmi4_new_function(struct synaptics_rmi4_exp_fn *exp_fn_module,
+void synaptics_rmi4_new_function_force(struct synaptics_rmi4_exp_fn *exp_fn_module,
bool insert);
int synaptics_fw_updater(const unsigned char *fw_data);
@@ -505,4 +536,5 @@ static inline void hstoba(unsigned char *dest, unsigned short src)
dest[0] = src % 0x100;
dest[1] = src / 0x100;
}
+
#endif
diff --git a/synaptics_dsx_fw_update.c b/synaptics_dsx_fw_update.c
index ab725ee..e177bd7 100644
--- a/synaptics_dsx_fw_update.c
+++ b/synaptics_dsx_fw_update.c
@@ -16,7 +16,22 @@
* 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.
+ *
+ * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS
+ * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
+ * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS.
+ * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED
+ * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES
+ * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS'
+ * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S.
+ * DOLLARS.
*/
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -27,18 +42,13 @@
#include <linux/platform_device.h>
#include <linux/input/synaptics_dsx.h>
#include "synaptics_dsx_core.h"
+
+#define FW_IHEX_NAME "synaptics/startup_fw_update.bin"
#define FW_IMAGE_NAME "synaptics/startup_fw_update.img"
#define DO_STARTUP_FW_UPDATE
-/*
-#ifdef DO_STARTUP_FW_UPDATE
-#ifdef CONFIG_FB
-#define WAIT_FOR_FB_READY
-#define FB_READY_WAIT_MS 100
-#define FB_READY_TIMEOUT_S 30
-#endif
-#endif
-*/
+#define MAX_WRITE_SIZE 4096
+
#define FORCE_UPDATE false
#define DO_LOCKDOWN false
@@ -52,6 +62,8 @@
#define IMAGE_AREA_OFFSET 0x100
#define LOCKDOWN_SIZE 0x50
+#define MAX_UTILITY_PARAMS 20
+
#define V5V6_BOOTLOADER_ID_OFFSET 0
#define V5V6_CONFIG_ID_SIZE 4
@@ -82,6 +94,7 @@
#define V7_PARTITION_SUPPORT_BYTES 4
#define F35_ERROR_CODE_OFFSET 0
+#define F35_FLASH_STATUS_OFFSET 5
#define F35_CHUNK_NUM_LSB_OFFSET 0
#define F35_CHUNK_NUM_MSB_OFFSET 1
#define F35_CHUNK_DATA_OFFSET 2
@@ -106,12 +119,12 @@
#define INT_DISABLE_WAIT_MS 20
#define ENTER_FLASH_PROG_WAIT_MS 20
-static int fwu_read_f34_blocks(unsigned short block_cnt, unsigned char cmd);
-
static int fwu_do_reflash(void);
static int fwu_recovery_check_status(void);
+static int fwu_read_f34_blocks(unsigned short block_cnt, unsigned char cmd);
+
static ssize_t fwu_sysfs_show_image(struct file *data_file,
struct kobject *kobj, struct bin_attribute *attributes,
char *buf, loff_t pos, size_t count);
@@ -198,6 +211,7 @@ enum config_area {
BL_CONFIG_AREA,
DP_CONFIG_AREA,
FLASH_CONFIG_AREA,
+ INVALID_CONFIG_AREA = 0xff,
};
enum v7_status {
@@ -225,6 +239,8 @@ enum v7_partition_id {
CORE_CONFIG_PARTITION,
GUEST_CODE_PARTITION,
DISPLAY_CONFIG_PARTITION,
+ EXTERNAL_TOUCH_AFE_CONFIG_PARTITION,
+ UTILITY_PARAMETER_PARTITION,
};
enum v7_flash_command {
@@ -259,6 +275,8 @@ enum flash_command {
CMD_WRITE_CONFIG,
CMD_WRITE_LOCKDOWN,
CMD_WRITE_GUEST_CODE,
+ CMD_WRITE_BOOTLOADER,
+ CMD_WRITE_UTILITY_PARAM,
CMD_READ_CONFIG,
CMD_ERASE_ALL,
CMD_ERASE_UI_FIRMWARE,
@@ -267,6 +285,8 @@ enum flash_command {
CMD_ERASE_DISP_CONFIG,
CMD_ERASE_FLASH_CONFIG,
CMD_ERASE_GUEST_CODE,
+ CMD_ERASE_BOOTLOADER,
+ CMD_ERASE_UTILITY_PARAMETER,
CMD_ENABLE_FLASH_PROG,
CMD_READ_LOCKDOWN_DATA,
};
@@ -301,6 +321,15 @@ enum container_id {
CORE_CODE_CONTAINER,
CORE_CONFIG_CONTAINER,
DISPLAY_CONFIG_CONTAINER,
+ EXTERNAL_TOUCH_AFE_CONFIG_CONTAINER,
+ UTILITY_CONTAINER,
+ UTILITY_PARAMETER_CONTAINER,
+};
+
+enum utility_parameter_id {
+ UNUSED = 0,
+ FORCE_PARAMETER,
+ ANTI_BENDING_PARAMETER,
};
struct pdt_properties {
@@ -486,6 +515,7 @@ struct block_count {
unsigned short fl_config;
unsigned short bl_image;
unsigned short bl_config;
+ unsigned short utility_param;
unsigned short lockdown;
unsigned short guest_code;
unsigned short lockdown_data;
@@ -496,7 +526,12 @@ struct physical_address {
unsigned short ui_firmware;
unsigned short ui_config;
unsigned short dp_config;
+ unsigned short pm_config;
unsigned short fl_config;
+ unsigned short bl_image;
+ unsigned short bl_config;
+ unsigned short utility_param;
+ unsigned short lockdown;
unsigned short guest_code;
};
@@ -582,6 +617,7 @@ struct image_metadata {
bool contains_disp_config;
bool contains_perm_config;
bool contains_flash_config;
+ bool contains_utility_param;
unsigned int firmware_id;
unsigned int checksum;
unsigned int bootloader_size;
@@ -589,7 +625,9 @@ struct image_metadata {
unsigned char bl_version;
unsigned char product_id[PRODUCT_ID_SIZE + 1];
unsigned char cstmr_product_id[PRODUCT_ID_SIZE + 1];
+ unsigned char utility_param_id[MAX_UTILITY_PARAMS];
struct block_data bootloader;
+ struct block_data utility;
struct block_data ui_firmware;
struct block_data ui_config;
struct block_data dp_config;
@@ -597,6 +635,7 @@ struct image_metadata {
struct block_data fl_config;
struct block_data bl_image;
struct block_data bl_config;
+ struct block_data utility_param[MAX_UTILITY_PARAMS];
struct block_data lockdown;
struct block_data guest_code;
struct block_count blkcount;
@@ -608,11 +647,15 @@ struct synaptics_rmi4_fwu_handle {
bool initialized;
bool in_bl_mode;
bool in_ub_mode;
+ bool bl_mode_device;
bool force_update;
bool do_lockdown;
bool has_guest_code;
bool has_lockdown_data;
+ bool has_utility_param;
bool new_partition_table;
+ bool incompatible_partition_tables;
+ bool write_bootloader;
unsigned int data_pos;
unsigned char *ext_data_source;
unsigned char *read_config_buf;
@@ -622,6 +665,13 @@ struct synaptics_rmi4_fwu_handle {
unsigned char config_id[32];
unsigned char flash_status;
unsigned char partitions;
+#ifdef F51_DISCRETE_FORCE
+ unsigned char *cal_data;
+ unsigned short cal_data_off;
+ unsigned short cal_data_size;
+ unsigned short cal_data_buf_size;
+ unsigned short cal_packet_data_size;
+#endif
unsigned short block_size;
unsigned short config_size;
unsigned short config_area;
@@ -706,10 +756,42 @@ static struct device_attribute attrs[] = {
static struct synaptics_rmi4_fwu_handle *fwu;
-DECLARE_COMPLETION(fwu_remove_complete);
-
+DECLARE_COMPLETION(fwu_remove_complete_force);
static int fwu_read_f34_guest_serialization_partition(void);
+static void calculate_checksum(unsigned short *data, unsigned long len,
+ unsigned long *result)
+{
+ unsigned long temp;
+ unsigned long sum1 = 0xffff;
+ unsigned long sum2 = 0xffff;
+
+ *result = 0xffffffff;
+
+ while (len--) {
+ temp = *data;
+ sum1 += temp;
+ sum2 += sum1;
+ sum1 = (sum1 & 0xffff) + (sum1 >> 16);
+ sum2 = (sum2 & 0xffff) + (sum2 >> 16);
+ data++;
+ }
+
+ *result = sum2 << 16 | sum1;
+
+ return;
+}
+
+static void convert_to_little_endian(unsigned char *dest, unsigned long src)
+{
+ dest[0] = (unsigned char)(src & 0xff);
+ dest[1] = (unsigned char)((src >> 8) & 0xff);
+ dest[2] = (unsigned char)((src >> 16) & 0xff);
+ dest[3] = (unsigned char)((src >> 24) & 0xff);
+
+ return;
+}
+
static unsigned int le_to_uint(const unsigned char *ptr)
{
return (unsigned int)ptr[0] +
@@ -718,6 +800,79 @@ static unsigned int le_to_uint(const unsigned char *ptr)
(unsigned int)ptr[3] * 0x1000000;
}
+#ifdef F51_DISCRETE_FORCE
+static int fwu_f51_force_data_init(void)
+{
+ int retval;
+ unsigned char query_count;
+ unsigned char packet_info;
+ unsigned char offset[2];
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ rmi4_data->f51_query_base_addr + 7,
+ offset,
+ sizeof(offset));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read force data offset\n",
+ __func__);
+ return retval;
+ }
+
+ fwu->cal_data_off = offset[0] | offset[1] << 8;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ rmi4_data->f51_query_base_addr,
+ &query_count,
+ sizeof(query_count));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read number of F51 query registers\n",
+ __func__);
+ return retval;
+ }
+
+ if (query_count >= 10) {
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ rmi4_data->f51_query_base_addr + 9,
+ &packet_info,
+ sizeof(packet_info));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read F51 packet register info\n",
+ __func__);
+ return retval;
+ }
+
+ if (packet_info & MASK_1BIT) {
+ fwu->cal_packet_data_size = packet_info >> 1;
+ fwu->cal_packet_data_size *= 2;
+ } else {
+ fwu->cal_packet_data_size = 0;
+ }
+ } else {
+ fwu->cal_packet_data_size = 0;
+ }
+
+ fwu->cal_data_size = CAL_DATA_SIZE + fwu->cal_packet_data_size;
+ if (fwu->cal_data_size > fwu->cal_data_buf_size) {
+ kfree(fwu->cal_data);
+ fwu->cal_data_buf_size = fwu->cal_data_size;
+ fwu->cal_data = kmalloc(fwu->cal_data_buf_size, GFP_KERNEL);
+ if (!fwu->cal_data) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to alloc mem for fwu->cal_data\n",
+ __func__);
+ fwu->cal_data_buf_size = 0;
+ return -ENOMEM;
+ }
+ }
+
+ return 0;
+}
+#endif
+
static int fwu_allocate_read_config_buf(unsigned int count)
{
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
@@ -740,32 +895,39 @@ static int fwu_allocate_read_config_buf(unsigned int count)
static void fwu_compare_partition_tables(void)
{
- if (fwu->phyaddr.ui_firmware != fwu->img.phyaddr.ui_firmware) {
- fwu->new_partition_table = true;
- return;
+ fwu->incompatible_partition_tables = false;
+
+ if (fwu->phyaddr.bl_image != fwu->img.phyaddr.bl_image)
+ fwu->incompatible_partition_tables = true;
+ else if (fwu->phyaddr.lockdown != fwu->img.phyaddr.lockdown)
+ fwu->incompatible_partition_tables = true;
+ else if (fwu->phyaddr.bl_config != fwu->img.phyaddr.bl_config)
+ fwu->incompatible_partition_tables = true;
+ else if (fwu->phyaddr.utility_param != fwu->img.phyaddr.utility_param)
+ fwu->incompatible_partition_tables = true;
+
+ if (fwu->bl_version == BL_V7) {
+ if (fwu->phyaddr.fl_config != fwu->img.phyaddr.fl_config)
+ fwu->incompatible_partition_tables = true;
}
- if (fwu->phyaddr.ui_config != fwu->img.phyaddr.ui_config) {
+ fwu->new_partition_table = false;
+
+ if (fwu->phyaddr.ui_firmware != fwu->img.phyaddr.ui_firmware)
+ fwu->new_partition_table = true;
+ else if (fwu->phyaddr.ui_config != fwu->img.phyaddr.ui_config)
fwu->new_partition_table = true;
- return;
- }
if (fwu->flash_properties.has_disp_config) {
- if (fwu->phyaddr.dp_config != fwu->img.phyaddr.dp_config) {
+ if (fwu->phyaddr.dp_config != fwu->img.phyaddr.dp_config)
fwu->new_partition_table = true;
- return;
- }
}
if (fwu->has_guest_code) {
- if (fwu->phyaddr.guest_code != fwu->img.phyaddr.guest_code) {
+ if (fwu->phyaddr.guest_code != fwu->img.phyaddr.guest_code)
fwu->new_partition_table = true;
- return;
- }
}
- fwu->new_partition_table = false;
-
return;
}
@@ -815,9 +977,18 @@ static void fwu_parse_partition_table(const unsigned char *partition_table,
break;
case BOOTLOADER_PARTITION:
blkcount->bl_image = partition_length;
+ phyaddr->bl_image = physical_address;
dev_dbg(rmi4_data->pdev->dev.parent,
- "%s: Core config block count: %d\n",
- __func__, blkcount->ui_config);
+ "%s: Bootloader block count: %d\n",
+ __func__, blkcount->bl_image);
+ blkcount->total_count += partition_length;
+ break;
+ case UTILITY_PARAMETER_PARTITION:
+ blkcount->utility_param = partition_length;
+ phyaddr->utility_param = physical_address;
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Utility parameter block count: %d\n",
+ __func__, blkcount->utility_param);
blkcount->total_count += partition_length;
break;
case DISPLAY_CONFIG_PARTITION:
@@ -846,6 +1017,7 @@ static void fwu_parse_partition_table(const unsigned char *partition_table,
break;
case GUEST_SERIALIZATION_PARTITION:
blkcount->pm_config = partition_length;
+ phyaddr->pm_config = physical_address;
dev_dbg(rmi4_data->pdev->dev.parent,
"%s: Guest serialization block count: %d\n",
__func__, blkcount->pm_config);
@@ -853,6 +1025,7 @@ static void fwu_parse_partition_table(const unsigned char *partition_table,
break;
case GLOBAL_PARAMETERS_PARTITION:
blkcount->bl_config = partition_length;
+ phyaddr->bl_config = physical_address;
dev_dbg(rmi4_data->pdev->dev.parent,
"%s: Global parameters block count: %d\n",
__func__, blkcount->bl_config);
@@ -860,6 +1033,7 @@ static void fwu_parse_partition_table(const unsigned char *partition_table,
break;
case DEVICE_CONFIG_PARTITION:
blkcount->lockdown = partition_length;
+ phyaddr->lockdown = physical_address;
dev_dbg(rmi4_data->pdev->dev.parent,
"%s: Device config block count: %d\n",
__func__, blkcount->lockdown);
@@ -871,7 +1045,42 @@ static void fwu_parse_partition_table(const unsigned char *partition_table,
return;
}
-static void fwu_parse_image_header_10_bl_container(const unsigned char *image)
+static void fwu_parse_image_header_10_utility(const unsigned char *image)
+{
+ unsigned char ii;
+ unsigned char num_of_containers;
+ unsigned int addr;
+ unsigned int container_id;
+ unsigned int length;
+ const unsigned char *content;
+ struct container_descriptor *descriptor;
+
+ num_of_containers = fwu->img.utility.size / 4;
+
+ for (ii = 0; ii < num_of_containers; ii++) {
+ if (ii >= MAX_UTILITY_PARAMS)
+ continue;
+ addr = le_to_uint(fwu->img.utility.data + (ii * 4));
+ descriptor = (struct container_descriptor *)(image + addr);
+ container_id = descriptor->container_id[0] |
+ descriptor->container_id[1] << 8;
+ content = image + le_to_uint(descriptor->content_address);
+ length = le_to_uint(descriptor->content_length);
+ switch (container_id) {
+ case UTILITY_PARAMETER_CONTAINER:
+ fwu->img.utility_param[ii].data = content;
+ fwu->img.utility_param[ii].size = length;
+ fwu->img.utility_param_id[ii] = content[0];
+ break;
+ default:
+ break;
+ };
+ }
+
+ return;
+}
+
+static void fwu_parse_image_header_10_bootloader(const unsigned char *image)
{
unsigned char ii;
unsigned char num_of_containers;
@@ -962,7 +1171,12 @@ static void fwu_parse_image_header_10(void)
fwu->img.bl_version = *content;
fwu->img.bootloader.data = content;
fwu->img.bootloader.size = length;
- fwu_parse_image_header_10_bl_container(image);
+ fwu_parse_image_header_10_bootloader(image);
+ break;
+ case UTILITY_CONTAINER:
+ fwu->img.utility.data = content;
+ fwu->img.utility.size = length;
+ fwu_parse_image_header_10_utility(image);
break;
case GUEST_CODE_CONTAINER:
fwu->img.contains_guest_code = true;
@@ -1031,8 +1245,7 @@ static void fwu_parse_image_header_05_06(void)
fwu->img.ui_firmware.size;
}
- if ((fwu->img.bl_version == BL_V5 && fwu->img.contains_bootloader) ||
- (fwu->img.bl_version == BL_V6 && header->options_tddi))
+ if (fwu->img.contains_bootloader || header->options_tddi)
fwu->img.contains_disp_config = true;
else
fwu->img.contains_disp_config = false;
@@ -1112,9 +1325,13 @@ static int fwu_parse_image_info(void)
fwu_parse_partition_table(fwu->img.fl_config.data,
&fwu->img.blkcount, &fwu->img.phyaddr);
+ if (fwu->img.blkcount.utility_param)
+ fwu->img.contains_utility_param = true;
+
fwu_compare_partition_tables();
} else {
fwu->new_partition_table = false;
+ fwu->incompatible_partition_tables = false;
}
return 0;
@@ -1147,12 +1364,18 @@ static int fwu_read_flash_status(void)
else if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8)
fwu->flash_status = status & MASK_5BIT;
+ if (fwu->write_bootloader)
+ fwu->flash_status = 0x00;
+
if (fwu->flash_status != 0x00) {
dev_err(rmi4_data->pdev->dev.parent,
- "%s: Flash status = %d, command = 0x%02x\n",
- __func__, fwu->flash_status, fwu->command);
+ "%s: Flash status = %d, command = 0x%02x, config area = 0x%02x\n",
+ __func__, fwu->flash_status, fwu->command, fwu->config_area);
}
+ if (fwu->flash_status == 0x08)
+ fwu->flash_status = 0;
+
retval = synaptics_rmi4_reg_read(rmi4_data,
fwu->f34_fd.data_base_addr + fwu->off.flash_cmd,
&command,
@@ -1171,6 +1394,9 @@ static int fwu_read_flash_status(void)
else if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8)
fwu->command = command;
+ if (fwu->write_bootloader)
+ fwu->command = 0x00;
+
return 0;
}
@@ -1201,11 +1427,11 @@ static int fwu_wait_for_idle(int timeout_ms, bool poll)
static int fwu_write_f34_v7_command_single_transaction(unsigned char cmd)
{
int retval;
- unsigned char base;
+ unsigned char data_base;
struct f34_v7_data_1_5 data_1_5;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
- base = fwu->f34_fd.data_base_addr;
+ data_base = fwu->f34_fd.data_base_addr;
memset(data_1_5.data, 0x00, sizeof(data_1_5.data));
@@ -1238,6 +1464,14 @@ static int fwu_write_f34_v7_command_single_transaction(unsigned char cmd)
data_1_5.partition_id = GUEST_CODE_PARTITION;
data_1_5.command = CMD_V7_ERASE;
break;
+ case CMD_ERASE_BOOTLOADER:
+ data_1_5.partition_id = BOOTLOADER_PARTITION;
+ data_1_5.command = CMD_V7_ERASE;
+ break;
+ case CMD_ERASE_UTILITY_PARAMETER:
+ data_1_5.partition_id = UTILITY_PARAMETER_PARTITION;
+ data_1_5.command = CMD_V7_ERASE;
+ break;
case CMD_ENABLE_FLASH_PROG:
data_1_5.partition_id = BOOTLOADER_PARTITION;
data_1_5.command = CMD_V7_ENTER_BL;
@@ -1248,7 +1482,7 @@ static int fwu_write_f34_v7_command_single_transaction(unsigned char cmd)
data_1_5.payload_1 = fwu->bootloader_id[1];
retval = synaptics_rmi4_reg_write(rmi4_data,
- base + fwu->off.partition_id,
+ data_base + fwu->off.partition_id,
data_1_5.data,
sizeof(data_1_5.data));
if (retval < 0) {
@@ -1264,17 +1498,19 @@ static int fwu_write_f34_v7_command_single_transaction(unsigned char cmd)
static int fwu_write_f34_v7_command(unsigned char cmd)
{
int retval;
- unsigned char base;
+ unsigned char data_base;
unsigned char command;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
- base = fwu->f34_fd.data_base_addr;
+ data_base = fwu->f34_fd.data_base_addr;
switch (cmd) {
case CMD_WRITE_FW:
case CMD_WRITE_CONFIG:
case CMD_WRITE_LOCKDOWN:
case CMD_WRITE_GUEST_CODE:
+ case CMD_WRITE_BOOTLOADER:
+ case CMD_WRITE_UTILITY_PARAM:
command = CMD_V7_WRITE;
break;
case CMD_READ_CONFIG:
@@ -1289,6 +1525,8 @@ static int fwu_write_f34_v7_command(unsigned char cmd)
case CMD_ERASE_DISP_CONFIG:
case CMD_ERASE_FLASH_CONFIG:
case CMD_ERASE_GUEST_CODE:
+ case CMD_ERASE_BOOTLOADER:
+ case CMD_ERASE_UTILITY_PARAMETER:
command = CMD_V7_ERASE;
break;
case CMD_ENABLE_FLASH_PROG:
@@ -1311,6 +1549,8 @@ static int fwu_write_f34_v7_command(unsigned char cmd)
case CMD_ERASE_DISP_CONFIG:
case CMD_ERASE_FLASH_CONFIG:
case CMD_ERASE_GUEST_CODE:
+ case CMD_ERASE_BOOTLOADER:
+ case CMD_ERASE_UTILITY_PARAMETER:
case CMD_ENABLE_FLASH_PROG:
retval = fwu_write_f34_v7_command_single_transaction(cmd);
if (retval < 0)
@@ -1322,7 +1562,7 @@ static int fwu_write_f34_v7_command(unsigned char cmd)
};
retval = synaptics_rmi4_reg_write(rmi4_data,
- base + fwu->off.flash_cmd,
+ data_base + fwu->off.flash_cmd,
&command,
sizeof(command));
if (retval < 0) {
@@ -1338,11 +1578,11 @@ static int fwu_write_f34_v7_command(unsigned char cmd)
static int fwu_write_f34_v5v6_command(unsigned char cmd)
{
int retval;
- unsigned char base;
+ unsigned char data_base;
unsigned char command;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
- base = fwu->f34_fd.data_base_addr;
+ data_base = fwu->f34_fd.data_base_addr;
switch (cmd) {
case CMD_IDLE:
@@ -1395,7 +1635,7 @@ static int fwu_write_f34_v5v6_command(unsigned char cmd)
case CMD_ERASE_GUEST_CODE:
case CMD_ENABLE_FLASH_PROG:
retval = synaptics_rmi4_reg_write(rmi4_data,
- base + fwu->off.payload,
+ data_base + fwu->off.payload,
fwu->bootloader_id,
sizeof(fwu->bootloader_id));
if (retval < 0) {
@@ -1412,7 +1652,7 @@ static int fwu_write_f34_v5v6_command(unsigned char cmd)
fwu->command = command;
retval = synaptics_rmi4_reg_write(rmi4_data,
- base + fwu->off.flash_cmd,
+ data_base + fwu->off.flash_cmd,
&command,
sizeof(command));
if (retval < 0) {
@@ -1440,11 +1680,11 @@ static int fwu_write_f34_command(unsigned char cmd)
static int fwu_write_f34_v7_partition_id(unsigned char cmd)
{
int retval;
- unsigned char base;
+ unsigned char data_base;
unsigned char partition;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
- base = fwu->f34_fd.data_base_addr;
+ data_base = fwu->f34_fd.data_base_addr;
switch (cmd) {
case CMD_WRITE_FW:
@@ -1469,6 +1709,12 @@ static int fwu_write_f34_v7_partition_id(unsigned char cmd)
case CMD_WRITE_GUEST_CODE:
partition = GUEST_CODE_PARTITION;
break;
+ case CMD_WRITE_BOOTLOADER:
+ partition = BOOTLOADER_PARTITION;
+ break;
+ case CMD_WRITE_UTILITY_PARAM:
+ partition = UTILITY_PARAMETER_PARTITION;
+ break;
case CMD_ERASE_ALL:
partition = CORE_CODE_PARTITION;
break;
@@ -1487,6 +1733,9 @@ static int fwu_write_f34_v7_partition_id(unsigned char cmd)
case CMD_ERASE_GUEST_CODE:
partition = GUEST_CODE_PARTITION;
break;
+ case CMD_ERASE_BOOTLOADER:
+ partition = BOOTLOADER_PARTITION;
+ break;
case CMD_ENABLE_FLASH_PROG:
partition = BOOTLOADER_PARTITION;
break;
@@ -1498,7 +1747,7 @@ static int fwu_write_f34_v7_partition_id(unsigned char cmd)
};
retval = synaptics_rmi4_reg_write(rmi4_data,
- base + fwu->off.partition_id,
+ data_base + fwu->off.partition_id,
&partition,
sizeof(partition));
if (retval < 0) {
@@ -1526,12 +1775,12 @@ static int fwu_write_f34_partition_id(unsigned char cmd)
static int fwu_read_f34_v7_partition_table(unsigned char *partition_table)
{
int retval;
- unsigned char base;
+ unsigned char data_base;
unsigned char length[2];
unsigned short block_number = 0;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
- base = fwu->f34_fd.data_base_addr;
+ data_base = fwu->f34_fd.data_base_addr;
fwu->config_area = FLASH_CONFIG_AREA;
@@ -1540,7 +1789,7 @@ static int fwu_read_f34_v7_partition_table(unsigned char *partition_table)
return retval;
retval = synaptics_rmi4_reg_write(rmi4_data,
- base + fwu->off.block_number,
+ data_base + fwu->off.block_number,
(unsigned char *)&block_number,
sizeof(block_number));
if (retval < 0) {
@@ -1554,7 +1803,7 @@ static int fwu_read_f34_v7_partition_table(unsigned char *partition_table)
length[1] = (unsigned char)(fwu->flash_config_length >> 8);
retval = synaptics_rmi4_reg_write(rmi4_data,
- base + fwu->off.transfer_length,
+ data_base + fwu->off.transfer_length,
length,
sizeof(length));
if (retval < 0) {
@@ -1581,7 +1830,7 @@ static int fwu_read_f34_v7_partition_table(unsigned char *partition_table)
}
retval = synaptics_rmi4_reg_read(rmi4_data,
- base + fwu->off.payload,
+ data_base + fwu->off.payload,
partition_table,
fwu->partition_table_bytes);
if (retval < 0) {
@@ -1598,7 +1847,7 @@ static int fwu_read_f34_v7_queries(void)
{
int retval;
unsigned char ii;
- unsigned char base;
+ unsigned char query_base;
unsigned char index;
unsigned char offset;
unsigned char *ptable;
@@ -1606,10 +1855,10 @@ static int fwu_read_f34_v7_queries(void)
struct f34_v7_query_1_7 query_1_7;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
- base = fwu->f34_fd.query_base_addr;
+ query_base = fwu->f34_fd.query_base_addr;
retval = synaptics_rmi4_reg_read(rmi4_data,
- base,
+ query_base,
query_0.data,
sizeof(query_0.data));
if (retval < 0) {
@@ -1622,7 +1871,7 @@ static int fwu_read_f34_v7_queries(void)
offset = query_0.subpacket_1_size + 1;
retval = synaptics_rmi4_reg_read(rmi4_data,
- base + offset,
+ query_base + offset,
query_1_7.data,
sizeof(query_1_7.data));
if (retval < 0) {
@@ -1709,6 +1958,11 @@ static int fwu_read_f34_v7_queries(void)
else
fwu->has_guest_code = 0;
+ if (fwu->blkcount.utility_param)
+ fwu->has_utility_param = 1;
+ else
+ fwu->has_utility_param = 0;
+
kfree(ptable);
if (rmi4_data->hw_if->board_data->lockdown_area == LOCKDOWN_AREA_GUEST_SERIALIZATION)
@@ -1755,15 +2009,15 @@ static int fwu_read_f34_v5v6_queries(void)
{
int retval;
unsigned char count;
- unsigned char base;
+ unsigned char query_base;
unsigned char buf[10];
struct f34_v5v6_flash_properties_2 properties_2;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
- base = fwu->f34_fd.query_base_addr;
+ query_base = fwu->f34_fd.query_base_addr;
retval = synaptics_rmi4_reg_read(rmi4_data,
- base + V5V6_BOOTLOADER_ID_OFFSET,
+ query_base + V5V6_BOOTLOADER_ID_OFFSET,
fwu->bootloader_id,
sizeof(fwu->bootloader_id));
if (retval < 0) {
@@ -1789,7 +2043,7 @@ static int fwu_read_f34_v5v6_queries(void)
}
retval = synaptics_rmi4_reg_read(rmi4_data,
- base + fwu->off.block_size,
+ query_base + fwu->off.block_size,
buf,
2);
if (retval < 0) {
@@ -1810,7 +2064,7 @@ static int fwu_read_f34_v5v6_queries(void)
}
retval = synaptics_rmi4_reg_read(rmi4_data,
- base + fwu->off.properties,
+ query_base + fwu->off.properties,
fwu->flash_properties.data,
sizeof(fwu->flash_properties.data));
if (retval < 0) {
@@ -1832,7 +2086,7 @@ static int fwu_read_f34_v5v6_queries(void)
count += 2;
retval = synaptics_rmi4_reg_read(rmi4_data,
- base + fwu->off.block_count,
+ query_base + fwu->off.block_count,
buf,
count);
if (retval < 0) {
@@ -1866,7 +2120,7 @@ static int fwu_read_f34_v5v6_queries(void)
if (fwu->flash_properties.has_query4) {
retval = synaptics_rmi4_reg_read(rmi4_data,
- base + fwu->off.properties_2,
+ query_base + fwu->off.properties_2,
properties_2.data,
sizeof(properties_2.data));
if (retval < 0) {
@@ -1881,7 +2135,7 @@ static int fwu_read_f34_v5v6_queries(void)
if (properties_2.has_guest_code) {
count++;
retval = synaptics_rmi4_reg_read(rmi4_data,
- base + fwu->off.properties_2 + count,
+ query_base + fwu->off.properties_2 + count,
buf,
2);
if (retval < 0) {
@@ -1904,7 +2158,7 @@ static int fwu_read_f34_v5v6_queries(void)
if (properties_2.has_lockdown_data_block) {
count++;
retval = synaptics_rmi4_reg_read(rmi4_data,
- base + fwu->off.properties_2 + count,
+ query_base + fwu->off.properties_2 + count,
buf,
2);
if (retval < 0) {
@@ -1921,6 +2175,8 @@ static int fwu_read_f34_v5v6_queries(void)
}
}
+ fwu->has_utility_param = false;
+
return 0;
}
@@ -1943,22 +2199,24 @@ static int fwu_write_f34_v7_blocks(unsigned char *block_ptr,
unsigned short block_cnt, unsigned char command)
{
int retval;
- unsigned char base;
+ unsigned char data_base;
unsigned char length[2];
unsigned short transfer;
- unsigned short max_transfer;
unsigned short remaining = block_cnt;
unsigned short block_number = 0;
+ unsigned short left_bytes;
+ unsigned short write_size;
+ unsigned short max_write_size;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
- base = fwu->f34_fd.data_base_addr;
+ data_base = fwu->f34_fd.data_base_addr;
retval = fwu_write_f34_partition_id(command);
if (retval < 0)
return retval;
retval = synaptics_rmi4_reg_write(rmi4_data,
- base + fwu->off.block_number,
+ data_base + fwu->off.block_number,
(unsigned char *)&block_number,
sizeof(block_number));
if (retval < 0) {
@@ -1968,14 +2226,9 @@ static int fwu_write_f34_v7_blocks(unsigned char *block_ptr,
return retval;
}
- if (fwu->payload_length > (PAGE_SIZE / fwu->block_size))
- max_transfer = PAGE_SIZE / fwu->block_size;
- else
- max_transfer = fwu->payload_length;
-
do {
- if (remaining / max_transfer)
- transfer = max_transfer;
+ if (remaining / fwu->payload_length)
+ transfer = fwu->payload_length;
else
transfer = remaining;
@@ -1983,12 +2236,12 @@ static int fwu_write_f34_v7_blocks(unsigned char *block_ptr,
length[1] = (unsigned char)(transfer >> 8);
retval = synaptics_rmi4_reg_write(rmi4_data,
- base + fwu->off.transfer_length,
+ data_base + fwu->off.transfer_length,
length,
sizeof(length));
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to write transfer length (%d blocks remaining)\n",
+ "%s: Failed to write transfer length (remaining = %d)\n",
__func__, remaining);
return retval;
}
@@ -1996,31 +2249,53 @@ static int fwu_write_f34_v7_blocks(unsigned char *block_ptr,
retval = fwu_write_f34_command(command);
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to write command (%d blocks remaining)\n",
+ "%s: Failed to write command (remaining = %d)\n",
__func__, remaining);
return retval;
}
- retval = synaptics_rmi4_reg_write(rmi4_data,
- base + fwu->off.payload,
- block_ptr,
- transfer * fwu->block_size);
- if (retval < 0) {
- dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to write block data (%d blocks remaining)\n",
- __func__, remaining);
- return retval;
- }
+#ifdef MAX_WRITE_SIZE
+ max_write_size = MAX_WRITE_SIZE;
+ if (max_write_size >= transfer * fwu->block_size)
+ max_write_size = transfer * fwu->block_size;
+ else if (max_write_size > fwu->block_size)
+ max_write_size -= max_write_size % fwu->block_size;
+ else
+ max_write_size = fwu->block_size;
+#else
+ max_write_size = transfer * fwu->block_size;
+#endif
+ left_bytes = transfer * fwu->block_size;
+
+ do {
+ if (left_bytes / max_write_size)
+ write_size = max_write_size;
+ else
+ write_size = left_bytes;
+
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ data_base + fwu->off.payload,
+ block_ptr,
+ write_size);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to write block data (remaining = %d)\n",
+ __func__, remaining);
+ return retval;
+ }
+
+ block_ptr += write_size;
+ left_bytes -= write_size;
+ } while (left_bytes);
retval = fwu_wait_for_idle(WRITE_WAIT_MS, false);
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to wait for idle status (%d blocks remaining)\n",
+ "%s: Failed to wait for idle status (remaining = %d)\n",
__func__, remaining);
return retval;
}
- block_ptr += (transfer * fwu->block_size);
remaining -= transfer;
} while (remaining);
@@ -2031,17 +2306,17 @@ static int fwu_write_f34_v5v6_blocks(unsigned char *block_ptr,
unsigned short block_cnt, unsigned char command)
{
int retval;
- unsigned char base;
+ unsigned char data_base;
unsigned char block_number[] = {0, 0};
unsigned short blk;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
- base = fwu->f34_fd.data_base_addr;
+ data_base = fwu->f34_fd.data_base_addr;
block_number[1] |= (fwu->config_area << 5);
retval = synaptics_rmi4_reg_write(rmi4_data,
- base + fwu->off.block_number,
+ data_base + fwu->off.block_number,
block_number,
sizeof(block_number));
if (retval < 0) {
@@ -2053,7 +2328,7 @@ static int fwu_write_f34_v5v6_blocks(unsigned char *block_ptr,
for (blk = 0; blk < block_cnt; blk++) {
retval = synaptics_rmi4_reg_write(rmi4_data,
- base + fwu->off.payload,
+ data_base + fwu->off.payload,
block_ptr,
fwu->block_size);
if (retval < 0) {
@@ -2102,23 +2377,22 @@ static int fwu_read_f34_v7_blocks(unsigned short block_cnt,
unsigned char command)
{
int retval;
- unsigned char base;
+ unsigned char data_base;
unsigned char length[2];
unsigned short transfer;
- unsigned short max_transfer;
unsigned short remaining = block_cnt;
unsigned short block_number = 0;
unsigned short index = 0;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
- base = fwu->f34_fd.data_base_addr;
+ data_base = fwu->f34_fd.data_base_addr;
retval = fwu_write_f34_partition_id(command);
if (retval < 0)
return retval;
retval = synaptics_rmi4_reg_write(rmi4_data,
- base + fwu->off.block_number,
+ data_base + fwu->off.block_number,
(unsigned char *)&block_number,
sizeof(block_number));
if (retval < 0) {
@@ -2128,14 +2402,9 @@ static int fwu_read_f34_v7_blocks(unsigned short block_cnt,
return retval;
}
- if (fwu->payload_length > (PAGE_SIZE / fwu->block_size))
- max_transfer = PAGE_SIZE / fwu->block_size;
- else
- max_transfer = fwu->payload_length;
-
do {
- if (remaining / max_transfer)
- transfer = max_transfer;
+ if (remaining / fwu->payload_length)
+ transfer = fwu->payload_length;
else
transfer = remaining;
@@ -2143,12 +2412,12 @@ static int fwu_read_f34_v7_blocks(unsigned short block_cnt,
length[1] = (unsigned char)(transfer >> 8);
retval = synaptics_rmi4_reg_write(rmi4_data,
- base + fwu->off.transfer_length,
+ data_base + fwu->off.transfer_length,
length,
sizeof(length));
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to write transfer length (%d blocks remaining)\n",
+ "%s: Failed to write transfer length (remaining = %d)\n",
__func__, remaining);
return retval;
}
@@ -2156,7 +2425,7 @@ static int fwu_read_f34_v7_blocks(unsigned short block_cnt,
retval = fwu_write_f34_command(command);
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to write command (%d blocks remaining)\n",
+ "%s: Failed to write command (remaining = %d)\n",
__func__, remaining);
return retval;
}
@@ -2164,18 +2433,18 @@ static int fwu_read_f34_v7_blocks(unsigned short block_cnt,
retval = fwu_wait_for_idle(WRITE_WAIT_MS, true);
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to wait for idle status (%d blocks remaining)\n",
+ "%s: Failed to wait for idle status (remaining = %d)\n",
__func__, remaining);
return retval;
}
retval = synaptics_rmi4_reg_read(rmi4_data,
- base + fwu->off.payload,
+ data_base + fwu->off.payload,
&fwu->read_config_buf[index],
transfer * fwu->block_size);
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to read block data (%d blocks remaining)\n",
+ "%s: Failed to read block data (remaining = %d)\n",
__func__, remaining);
return retval;
}
@@ -2191,18 +2460,18 @@ static int fwu_read_f34_v5v6_blocks(unsigned short block_cnt,
unsigned char command)
{
int retval;
- unsigned char base;
+ unsigned char data_base;
unsigned char block_number[] = {0, 0};
unsigned short blk;
unsigned short index = 0;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
- base = fwu->f34_fd.data_base_addr;
+ data_base = fwu->f34_fd.data_base_addr;
block_number[1] |= (fwu->config_area << 5);
retval = synaptics_rmi4_reg_write(rmi4_data,
- base + fwu->off.block_number,
+ data_base + fwu->off.block_number,
block_number,
sizeof(block_number));
if (retval < 0) {
@@ -2230,7 +2499,7 @@ static int fwu_read_f34_v5v6_blocks(unsigned short block_cnt,
}
retval = synaptics_rmi4_reg_read(rmi4_data,
- base + fwu->off.payload,
+ data_base + fwu->off.payload,
&fwu->read_config_buf[index],
fwu->block_size);
if (retval < 0) {
@@ -2390,7 +2659,7 @@ static enum flash_area fwu_go_nogo(void)
}
/* Update both UI and config if device is in bootloader mode */
- if (fwu->in_bl_mode) {
+ if (fwu->bl_mode_device) {
flash_area = UI_FIRMWARE;
goto exit;
}
@@ -2541,6 +2810,8 @@ static int fwu_scan_pdt(void)
rmi_fd.ctrl_base_addr;
fwu->f35_fd.data_base_addr =
rmi_fd.data_base_addr;
+ fwu->f35_fd.cmd_base_addr =
+ rmi_fd.cmd_base_addr;
break;
}
} else {
@@ -2631,6 +2902,8 @@ static int fwu_enter_flash_prog(void)
if (retval < 0)
return retval;
+ pr_err("%s: fwu->in_ub_mode = %d\n", __func__, fwu->in_ub_mode);
+
retval = fwu_read_f34_queries();
if (retval < 0)
return retval;
@@ -2766,16 +3039,6 @@ static int fwu_check_guest_code_size(void)
return 0;
}
-static int fwu_write_firmware(void)
-{
- unsigned short firmware_block_count;
-
- firmware_block_count = fwu->img.ui_firmware.size / fwu->block_size;
-
- return fwu_write_f34_blocks((unsigned char *)fwu->img.ui_firmware.data,
- firmware_block_count, CMD_WRITE_FW);
-}
-
static int fwu_erase_configuration(void)
{
int retval;
@@ -2797,6 +3060,16 @@ static int fwu_erase_configuration(void)
if (retval < 0)
return retval;
break;
+ case FLASH_CONFIG_AREA:
+ retval = fwu_write_f34_command(CMD_ERASE_FLASH_CONFIG);
+ if (retval < 0)
+ return retval;
+ break;
+ default:
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Invalid config area\n",
+ __func__);
+ return -EINVAL;
}
dev_dbg(rmi4_data->pdev->dev.parent,
@@ -2814,6 +3087,54 @@ static int fwu_erase_configuration(void)
return retval;
}
+static int fwu_erase_bootloader(void)
+{
+ int retval;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ retval = fwu_write_f34_command(CMD_ERASE_BOOTLOADER);
+ if (retval < 0)
+ return retval;
+
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Erase command written\n",
+ __func__);
+
+ retval = fwu_wait_for_idle(ERASE_WAIT_MS, false);
+ if (retval < 0)
+ return retval;
+
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Idle status detected\n",
+ __func__);
+
+ return 0;
+}
+
+static int fwu_erase_utility_parameter(void)
+{
+ int retval;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ retval = fwu_write_f34_command(CMD_ERASE_UTILITY_PARAMETER);
+ if (retval < 0)
+ return retval;
+
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Erase command written\n",
+ __func__);
+
+ retval = fwu_wait_for_idle(ERASE_WAIT_MS, false);
+ if (retval < 0)
+ return retval;
+
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Idle status detected\n",
+ __func__);
+
+ return 0;
+}
+
static int fwu_erase_guest_code(void)
{
int retval;
@@ -2844,6 +3165,7 @@ static int fwu_erase_all(void)
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
if (fwu->bl_version == BL_V7) {
+ fwu->config_area = INVALID_CONFIG_AREA;
retval = fwu_write_f34_command(CMD_ERASE_UI_FIRMWARE);
if (retval < 0)
return retval;
@@ -2860,10 +3182,14 @@ static int fwu_erase_all(void)
"%s: Idle status detected\n",
__func__);
+ pr_err("erased core code\n");
+
fwu->config_area = UI_CONFIG_AREA;
retval = fwu_erase_configuration();
if (retval < 0)
return retval;
+
+ pr_err("erased core config\n");
} else {
retval = fwu_write_f34_command(CMD_ERASE_ALL);
if (retval < 0)
@@ -2905,33 +3231,153 @@ static int fwu_erase_all(void)
return 0;
}
-static int fwu_write_configuration(void)
+static int fwu_write_firmware(void)
{
- return fwu_write_f34_blocks((unsigned char *)fwu->config_data,
- fwu->config_block_count, CMD_WRITE_CONFIG);
-}
+ unsigned short firmware_block_count;
-static int fwu_write_ui_configuration(void)
-{
- fwu->config_area = UI_CONFIG_AREA;
- fwu->config_data = fwu->img.ui_config.data;
- fwu->config_size = fwu->img.ui_config.size;
- fwu->config_block_count = fwu->config_size / fwu->block_size;
+ firmware_block_count = fwu->img.ui_firmware.size / fwu->block_size;
- return fwu_write_configuration();
+ pr_err("core code block count = %d\n", firmware_block_count);
+
+ return fwu_write_f34_blocks((unsigned char *)fwu->img.ui_firmware.data,
+ firmware_block_count, CMD_WRITE_FW);
}
-static int fwu_write_dp_configuration(void)
+static int fwu_write_bootloader(void)
{
- fwu->config_area = DP_CONFIG_AREA;
- fwu->config_data = fwu->img.dp_config.data;
- fwu->config_size = fwu->img.dp_config.size;
- fwu->config_block_count = fwu->config_size / fwu->block_size;
+ int retval;
+ unsigned short bootloader_block_count;
- return fwu_write_configuration();
+ bootloader_block_count = fwu->img.bl_image.size / fwu->block_size;
+
+ pr_err("bootloader block count = %d\n", bootloader_block_count);
+
+ fwu->write_bootloader = true;
+ retval = fwu_write_f34_blocks((unsigned char *)fwu->img.bl_image.data,
+ bootloader_block_count, CMD_WRITE_BOOTLOADER);
+ fwu->write_bootloader = false;
+
+ return retval;
}
-static int fwu_write_pm_configuration(void)
+static int fwu_write_utility_parameter(void)
+{
+ int retval;
+ unsigned char ii;
+ unsigned char checksum_array[4];
+ unsigned char *pbuf;
+ unsigned short remaining_size;
+ unsigned short utility_param_size;
+ unsigned long checksum;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ utility_param_size = fwu->blkcount.utility_param * fwu->block_size;
+ retval = fwu_allocate_read_config_buf(utility_param_size);
+ if (retval < 0)
+ return retval;
+ memset(fwu->read_config_buf, 0x00, utility_param_size);
+
+ pbuf = fwu->read_config_buf;
+ remaining_size = utility_param_size - 4;
+
+ for (ii = 0; ii < MAX_UTILITY_PARAMS; ii++) {
+ if (fwu->img.utility_param_id[ii] == UNUSED)
+ continue;
+
+#ifdef F51_DISCRETE_FORCE
+ if (fwu->img.utility_param_id[ii] == FORCE_PARAMETER) {
+ if (fwu->bl_mode_device) {
+ dev_info(rmi4_data->pdev->dev.parent,
+ "%s: Device in bootloader mode, skipping calibration data restoration\n",
+ __func__);
+ goto image_param;
+ }
+ retval = secure_memcpy(&(pbuf[4]),
+ remaining_size - 4,
+ fwu->cal_data,
+ fwu->cal_data_buf_size,
+ fwu->cal_data_size);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to copy force calibration data\n",
+ __func__);
+ return retval;
+ }
+ pbuf[0] = FORCE_PARAMETER;
+ pbuf[1] = 0x00;
+ pbuf[2] = (4 + fwu->cal_data_size) / 2;
+ pbuf += (fwu->cal_data_size + 4);
+ remaining_size -= (fwu->cal_data_size + 4);
+ continue;
+ }
+image_param:
+#endif
+
+ retval = secure_memcpy(pbuf,
+ remaining_size,
+ fwu->img.utility_param[ii].data,
+ fwu->img.utility_param[ii].size,
+ fwu->img.utility_param[ii].size);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to copy utility parameter data\n",
+ __func__);
+ return retval;
+ }
+ pbuf += fwu->img.utility_param[ii].size;
+ remaining_size -= fwu->img.utility_param[ii].size;
+ }
+
+ calculate_checksum((unsigned short *)fwu->read_config_buf,
+ ((utility_param_size - 4) / 2),
+ &checksum);
+
+ convert_to_little_endian(checksum_array, checksum);
+
+ fwu->read_config_buf[utility_param_size - 4] = checksum_array[0];
+ fwu->read_config_buf[utility_param_size - 3] = checksum_array[1];
+ fwu->read_config_buf[utility_param_size - 2] = checksum_array[2];
+ fwu->read_config_buf[utility_param_size - 1] = checksum_array[3];
+
+ pr_err("utility parameter block count = %d\n", fwu->blkcount.utility_param);
+
+ retval = fwu_write_f34_blocks((unsigned char *)fwu->read_config_buf,
+ fwu->blkcount.utility_param, CMD_WRITE_UTILITY_PARAM);
+ if (retval < 0)
+ return retval;
+
+ return 0;
+}
+
+static int fwu_write_configuration(void)
+{
+ return fwu_write_f34_blocks((unsigned char *)fwu->config_data,
+ fwu->config_block_count, CMD_WRITE_CONFIG);
+}
+
+static int fwu_write_ui_configuration(void)
+{
+ fwu->config_area = UI_CONFIG_AREA;
+ fwu->config_data = fwu->img.ui_config.data;
+ fwu->config_size = fwu->img.ui_config.size;
+ fwu->config_block_count = fwu->config_size / fwu->block_size;
+
+ pr_err("core config block count = %d\n", fwu->config_block_count);
+
+ return fwu_write_configuration();
+}
+
+static int fwu_write_dp_configuration(void)
+{
+ fwu->config_area = DP_CONFIG_AREA;
+ fwu->config_data = fwu->img.dp_config.data;
+ fwu->config_size = fwu->img.dp_config.size;
+ fwu->config_block_count = fwu->config_size / fwu->block_size;
+
+ return fwu_write_configuration();
+}
+
+static int fwu_write_pm_configuration(void)
{
fwu->config_area = PM_CONFIG_AREA;
fwu->config_data = fwu->img.pm_config.data;
@@ -2958,22 +3404,10 @@ static int fwu_write_flash_configuration(void)
return -EINVAL;
}
- retval = fwu_write_f34_command(CMD_ERASE_FLASH_CONFIG);
- if (retval < 0)
- return retval;
-
- dev_dbg(rmi4_data->pdev->dev.parent,
- "%s: Erase flash configuration command written\n",
- __func__);
-
- retval = fwu_wait_for_idle(ERASE_WAIT_MS, false);
+ retval = fwu_erase_configuration();
if (retval < 0)
return retval;
- dev_dbg(rmi4_data->pdev->dev.parent,
- "%s: Idle status detected\n",
- __func__);
-
retval = fwu_write_configuration();
if (retval < 0)
return retval;
@@ -3071,9 +3505,95 @@ static int fwu_write_partition_table_v7(void)
return 0;
}
+static int fwu_write_bl_area_v7(void)
+{
+ int retval;
+ bool has_utility_param;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ has_utility_param = fwu->has_utility_param;
+
+ if (fwu->has_utility_param) {
+ retval = fwu_erase_utility_parameter();
+ if (retval < 0)
+ return retval;
+
+ pr_err("erased utility parameter\n");
+ }
+
+ fwu->config_area = BL_CONFIG_AREA;
+ retval = fwu_erase_configuration();
+ if (retval < 0)
+ return retval;
+
+ pr_err("erased bootloader config\n");
+
+ fwu->config_area = FLASH_CONFIG_AREA;
+ retval = fwu_erase_configuration();
+ if (retval < 0)
+ return retval;
+
+ pr_err("erased flash config\n");
+
+ retval = fwu_erase_bootloader();
+ if (retval < 0)
+ return retval;
+
+ pr_err("erased bootloader\n");
+
+ retval = fwu_write_bootloader();
+ if (retval < 0)
+ return retval;
+
+ pr_err("bootloader written\n");
+
+ msleep(rmi4_data->hw_if->board_data->reset_delay_ms);
+ rmi4_data->reset_device(rmi4_data, false);
+
+ pr_err("reset after writing bootloader\n");
+
+ fwu->config_area = FLASH_CONFIG_AREA;
+ fwu->config_data = fwu->img.fl_config.data;
+ fwu->config_size = fwu->img.fl_config.size;
+ fwu->config_block_count = fwu->config_size / fwu->block_size;
+ pr_err("flash config block count = %d\n", fwu->config_block_count);
+ retval = fwu_write_configuration();
+ if (retval < 0)
+ return retval;
+
+ pr_err("flash config written\n");
+
+ rmi4_data->reset_device(rmi4_data, false);
+
+ pr_err("reset after writing flash config\n");
+
+ fwu->config_area = BL_CONFIG_AREA;
+ fwu->config_data = fwu->img.bl_config.data;
+ fwu->config_size = fwu->img.bl_config.size;
+ fwu->config_block_count = fwu->config_size / fwu->block_size;
+ pr_err("bootloader config block count = %d\n", fwu->config_block_count);
+ retval = fwu_write_configuration();
+ if (retval < 0)
+ return retval;
+
+ pr_err("bootloader config written\n");
+
+ if (fwu->img.contains_utility_param) {
+ retval = fwu_write_utility_parameter();
+ if (retval < 0)
+ return retval;
+
+ pr_err("utility parameter written\n");
+ }
+
+ return 0;
+}
+
static int fwu_do_reflash(void)
{
int retval;
+ bool do_bl_update = false;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
if (!fwu->new_partition_table) {
retval = fwu_check_ui_firmware_size();
@@ -3102,11 +3622,44 @@ static int fwu_do_reflash(void)
return retval;
}
+ if (!fwu->has_utility_param && fwu->img.contains_utility_param) {
+ if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8)
+ do_bl_update = true;
+ }
+
+ if (fwu->has_utility_param && !fwu->img.contains_utility_param) {
+ if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8)
+ do_bl_update = true;
+ }
+
+ pr_err("fwu->has_utility_param = %d\n", fwu->has_utility_param);
+ pr_err("fwu->img.contains_utility_param = %d\n", fwu->img.contains_utility_param);
+ pr_err("do_bl_update = %d\n", do_bl_update);
+
+ if (!do_bl_update && fwu->incompatible_partition_tables) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Incompatible partition tables\n",
+ __func__);
+ return -EINVAL;
+ } else if (!do_bl_update && fwu->new_partition_table) {
+ if (!fwu->force_update) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Partition table mismatch\n",
+ __func__);
+ return -EINVAL;
+ }
+ }
+
retval = fwu_erase_all();
if (retval < 0)
return retval;
- if (fwu->bl_version == BL_V7 && fwu->new_partition_table) {
+ if (do_bl_update) {
+ retval = fwu_write_bl_area_v7();
+ if (retval < 0)
+ return retval;
+ pr_notice("%s: Bootloader area programmed\n", __func__);
+ } else if (fwu->bl_version == BL_V7 && fwu->new_partition_table) {
retval = fwu_write_partition_table_v7();
if (retval < 0)
return retval;
@@ -3201,13 +3754,13 @@ static int fwu_do_read_config(void)
mutex_lock(&rmi4_data->rmi4_exp_init_mutex);
- config_area = fwu->config_area;
-
- retval = fwu_enter_flash_prog();
- if (retval < 0)
- goto exit;
-
- fwu->config_area = config_area;
+ if (fwu->bl_version == BL_V5 || fwu->bl_version == BL_V6) {
+ config_area = fwu->config_area;
+ retval = fwu_enter_flash_prog();
+ fwu->config_area = config_area;
+ if (retval < 0)
+ goto exit;
+ }
fwu->config_size = fwu->block_size * block_count;
@@ -3218,7 +3771,8 @@ static int fwu_do_read_config(void)
retval = fwu_read_f34_blocks(block_count, CMD_READ_CONFIG);
exit:
- rmi4_data->reset_device(rmi4_data, false);
+ if (fwu->bl_version == BL_V5 || fwu->bl_version == BL_V6)
+ rmi4_data->reset_device(rmi4_data, false);
mutex_unlock(&rmi4_data->rmi4_exp_init_mutex);
@@ -3298,6 +3852,68 @@ static int fwu_do_lockdown_v5v6(void)
return retval;
}
+#ifdef F51_DISCRETE_FORCE
+static int fwu_do_restore_f51_cal_data(void)
+{
+ int retval;
+ unsigned char checksum_array[4];
+ unsigned short block_count;
+ unsigned long checksum;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ block_count = fwu->blkcount.ui_config;
+ fwu->config_size = fwu->block_size * block_count;
+ fwu->config_area = UI_CONFIG_AREA;
+
+ retval = fwu_allocate_read_config_buf(fwu->config_size);
+ if (retval < 0)
+ return retval;
+
+ retval = fwu_read_f34_blocks(block_count, CMD_READ_CONFIG);
+ if (retval < 0)
+ return retval;
+
+ retval = secure_memcpy(&fwu->read_config_buf[fwu->cal_data_off],
+ fwu->cal_data_size, fwu->cal_data,
+ fwu->cal_data_buf_size, fwu->cal_data_size);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to restore calibration data\n",
+ __func__);
+ return retval;
+ }
+
+ calculate_checksum((unsigned short *)fwu->read_config_buf,
+ ((fwu->config_size - 4) / 2),
+ &checksum);
+
+ convert_to_little_endian(checksum_array, checksum);
+
+ fwu->read_config_buf[fwu->config_size - 4] = checksum_array[0];
+ fwu->read_config_buf[fwu->config_size - 3] = checksum_array[1];
+ fwu->read_config_buf[fwu->config_size - 2] = checksum_array[2];
+ fwu->read_config_buf[fwu->config_size - 1] = checksum_array[3];
+
+ retval = fwu_enter_flash_prog();
+ if (retval < 0)
+ return retval;
+
+ fwu->config_area = UI_CONFIG_AREA;
+ fwu->config_data = fwu->read_config_buf;
+ fwu->config_block_count = fwu->config_size / fwu->block_size;
+
+ retval = fwu_erase_configuration();
+ if (retval < 0)
+ return retval;
+
+ retval = fwu_write_configuration();
+ if (retval < 0)
+ return retval;
+
+ return 0;
+}
+#endif
+
static int fwu_start_write_guest_code(void)
{
int retval;
@@ -3509,12 +4125,17 @@ static const char *fwu_get_firmware_name(struct synaptics_rmi4_data *rmi4_data)
const char *fw_name = NULL;
const struct synaptics_dsx_board_data *bdata =
rmi4_data->hw_if->board_data;
- int i, j;
+ int i, j, def = -1;
bool found = false;
if (bdata->tp_id_num != 0) {
for (i = 0; i < bdata->config_array_size; i++) {
found = true;
+ if (rmi4_data->chip_id != bdata->config_array[i].chip_id)
+ continue;
+ else
+ def = i;
+
for (j = 0; j < bdata->tp_id_num; j++) {
if (bdata->config_array[i].tp_ids[j] !=
rmi4_data->lockdown_info[bdata->tp_id_bytes[j]]) {
@@ -3530,12 +4151,11 @@ static const char *fwu_get_firmware_name(struct synaptics_rmi4_data *rmi4_data)
}
}
- if (!fw_name && rmi4_data->chip_id > 0)
- fw_name = bdata->config_array[rmi4_data->chip_id - 1].fw_name;
+ if (!fw_name && (def >= 0))
+ fw_name = bdata->config_array[def].fw_name;
- if (fw_name)
- dev_info(rmi4_data->pdev->dev.parent,
- "%s: Choose firmware %s\n", __func__, fw_name);
+ dev_info(rmi4_data->pdev->dev.parent,
+ "%s: Choose firmware %s\n", __func__, fw_name);
return fw_name;
}
@@ -3544,6 +4164,7 @@ static int fwu_start_reflash(void)
{
int retval = 0;
enum flash_area flash_area;
+ bool do_rebuild = false;
const struct firmware *fw_entry = NULL;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
const char *fw_name;
@@ -3558,10 +4179,12 @@ static int fwu_start_reflash(void)
fw_name = fwu_get_firmware_name(rmi4_data);
if (fw_name == NULL) {
- dev_err(rmi4_data->pdev->dev.parent, "%s: do not found fw need by ic\n", __func__);
- return 0;
+ dev_err(rmi4_data->pdev->dev.parent, "%s: do not found fw to update\n", __func__);
+
+ return -EINVAL;
}
+
rmi4_data->stay_awake = true;
mutex_lock(&rmi4_data->rmi4_exp_init_mutex);
@@ -3620,22 +4243,17 @@ static int fwu_start_reflash(void)
goto exit;
}
- if (!fwu->force_update && fwu->new_partition_table) {
- dev_err(rmi4_data->pdev->dev.parent,
- "%s: Partition table mismatch\n",
- __func__);
- retval = -EINVAL;
- goto exit;
- }
-
retval = fwu_read_flash_status();
if (retval < 0)
goto exit;
if (fwu->in_bl_mode) {
+ fwu->bl_mode_device = true;
dev_info(rmi4_data->pdev->dev.parent,
"%s: Device in bootloader mode\n",
__func__);
+ } else {
+ fwu->bl_mode_device = false;
}
flash_area = fwu_go_nogo();
@@ -3648,12 +4266,62 @@ static int fwu_start_reflash(void)
}
}
+#ifdef F51_DISCRETE_FORCE
+ if (flash_area != NONE && !fwu->bl_mode_device) {
+ fwu->config_size = fwu->block_size * fwu->blkcount.ui_config;
+ fwu->config_area = UI_CONFIG_AREA;
+
+ retval = fwu_allocate_read_config_buf(fwu->config_size);
+ if (retval < 0) {
+ rmi4_data->reset_device(rmi4_data, false);
+ goto exit;
+ }
+
+ retval = fwu_read_f34_blocks(fwu->blkcount.ui_config,
+ CMD_READ_CONFIG);
+ if (retval < 0) {
+ rmi4_data->reset_device(rmi4_data, false);
+ goto exit;
+ }
+
+ retval = secure_memcpy(fwu->cal_data, fwu->cal_data_buf_size,
+ &fwu->read_config_buf[fwu->cal_data_off],
+ fwu->cal_data_size, fwu->cal_data_size);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to save calibration data\n",
+ __func__);
+ rmi4_data->reset_device(rmi4_data, false);
+ goto exit;
+ }
+ }
+#endif
+
switch (flash_area) {
case UI_FIRMWARE:
+ do_rebuild = true;
retval = fwu_do_reflash();
- rmi4_data->reset_device(rmi4_data, true);
+#ifdef F51_DISCRETE_FORCE
+ if (retval < 0)
+ break;
+
+ if (fwu->has_utility_param || fwu->img.contains_utility_param)
+ break;
+
+ rmi4_data->reset_device(rmi4_data, false);
+
+ if (fwu->bl_mode_device || fwu->in_bl_mode) {
+ dev_info(rmi4_data->pdev->dev.parent,
+ "%s: Device in bootloader mode, skipping calibration data restoration\n",
+ __func__);
+ break;
+ }
+
+ retval = fwu_do_restore_f51_cal_data();
+#endif
break;
case UI_CONFIG:
+ do_rebuild = true;
retval = fwu_check_ui_configuration_size();
if (retval < 0)
break;
@@ -3662,15 +4330,25 @@ static int fwu_start_reflash(void)
if (retval < 0)
break;
retval = fwu_write_ui_configuration();
- rmi4_data->reset_device(rmi4_data, true);
+#ifdef F51_DISCRETE_FORCE
+ if (retval < 0)
+ break;
+
+ if (fwu->has_utility_param)
+ break;
+
+ retval = fwu_do_restore_f51_cal_data();
+#endif
break;
case NONE:
default:
- rmi4_data->reset_device(rmi4_data, false);
break;
}
if (retval < 0) {
+ do_rebuild = false;
+ rmi4_data->reset_device(rmi4_data, false);
+ pr_err("%s: fwu->in_ub_mode = %d\n", __func__, fwu->in_ub_mode);
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to do reflash\n",
__func__);
@@ -3708,6 +4386,9 @@ exit:
if (fw_entry)
release_firmware(fw_entry);
+ if (do_rebuild)
+ rmi4_data->reset_device(rmi4_data, true);
+
pr_notice("%s: End of reflash process\n", __func__);
mutex_unlock(&rmi4_data->rmi4_exp_init_mutex);
@@ -3720,14 +4401,14 @@ exit:
static int fwu_recovery_check_status(void)
{
int retval;
- unsigned char base;
+ unsigned char data_base;
unsigned char status;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
- base = fwu->f35_fd.data_base_addr;
+ data_base = fwu->f35_fd.data_base_addr;
retval = synaptics_rmi4_reg_read(rmi4_data,
- base + F35_ERROR_CODE_OFFSET,
+ data_base + F35_ERROR_CODE_OFFSET,
&status,
1);
if (retval < 0) {
@@ -3749,17 +4430,92 @@ static int fwu_recovery_check_status(void)
return 0;
}
+static int fwu_recovery_erase_completion(void)
+{
+ int retval;
+ unsigned char data_base;
+ unsigned char command;
+ unsigned char status;
+ unsigned int timeout = F35_ERASE_ALL_WAIT_MS / 20;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ data_base = fwu->f35_fd.data_base_addr;
+
+ do {
+ command = 0x01;
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ fwu->f35_fd.cmd_base_addr,
+ &command,
+ sizeof(command));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to issue command\n",
+ __func__);
+ return retval;
+ }
+
+ do {
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ fwu->f35_fd.cmd_base_addr,
+ &command,
+ sizeof(command));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read command status\n",
+ __func__);
+ return retval;
+ }
+
+ if ((command & 0x01) == 0x00)
+ break;
+
+ msleep(20);
+ timeout--;
+ } while (timeout > 0);
+
+ if (timeout == 0)
+ goto exit;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ data_base + F35_FLASH_STATUS_OFFSET,
+ &status,
+ sizeof(status));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read flash status\n",
+ __func__);
+ return retval;
+ }
+
+ if ((status & 0x01) == 0x00)
+ break;
+
+ msleep(20);
+ timeout--;
+ } while (timeout > 0);
+
+exit:
+ if (timeout == 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Timed out waiting for flash erase completion\n",
+ __func__);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
static int fwu_recovery_erase_all(void)
{
int retval;
- unsigned char base;
+ unsigned char ctrl_base;
unsigned char command = CMD_F35_ERASE_ALL;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
- base = fwu->f35_fd.ctrl_base_addr;
+ ctrl_base = fwu->f35_fd.ctrl_base_addr;
retval = synaptics_rmi4_reg_write(rmi4_data,
- base + F35_CHUNK_COMMAND_OFFSET,
+ ctrl_base + F35_CHUNK_COMMAND_OFFSET,
&command,
sizeof(command));
if (retval < 0) {
@@ -3769,7 +4525,13 @@ static int fwu_recovery_erase_all(void)
return retval;
}
- msleep(F35_ERASE_ALL_WAIT_MS);
+ if (fwu->f35_fd.cmd_base_addr) {
+ retval = fwu_recovery_erase_completion();
+ if (retval < 0)
+ return retval;
+ } else {
+ msleep(F35_ERASE_ALL_WAIT_MS);
+ }
retval = fwu_recovery_check_status();
if (retval < 0)
@@ -3781,7 +4543,7 @@ static int fwu_recovery_erase_all(void)
static int fwu_recovery_write_chunk(void)
{
int retval;
- unsigned char base;
+ unsigned char ctrl_base;
unsigned char chunk_number[] = {0, 0};
unsigned char chunk_spare;
unsigned char chunk_size;
@@ -3792,10 +4554,10 @@ static int fwu_recovery_write_chunk(void)
unsigned char *chunk_ptr = (unsigned char *)fwu->image;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
- base = fwu->f35_fd.ctrl_base_addr;
+ ctrl_base = fwu->f35_fd.ctrl_base_addr;
retval = synaptics_rmi4_reg_write(rmi4_data,
- base + F35_CHUNK_NUM_LSB_OFFSET,
+ ctrl_base + F35_CHUNK_NUM_LSB_OFFSET,
chunk_number,
sizeof(chunk_number));
if (retval < 0) {
@@ -3824,7 +4586,7 @@ static int fwu_recovery_write_chunk(void)
chunk_size);
retval = synaptics_rmi4_reg_write(rmi4_data,
- base + F35_CHUNK_DATA_OFFSET,
+ ctrl_base + F35_CHUNK_DATA_OFFSET,
buf,
sizeof(buf));
if (retval < 0) {
@@ -3851,14 +4613,14 @@ static int fwu_recovery_write_chunk(void)
static int fwu_recovery_reset(void)
{
int retval;
- unsigned char base;
+ unsigned char ctrl_base;
unsigned char command = CMD_F35_RESET;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
- base = fwu->f35_fd.ctrl_base_addr;
+ ctrl_base = fwu->f35_fd.ctrl_base_addr;
retval = synaptics_rmi4_reg_write(rmi4_data,
- base + F35_CHUNK_COMMAND_OFFSET,
+ ctrl_base + F35_CHUNK_COMMAND_OFFSET,
&command,
sizeof(command));
if (retval < 0) {
@@ -3876,6 +4638,7 @@ static int fwu_recovery_reset(void)
static int fwu_start_recovery(void)
{
int retval;
+ const struct firmware *fw_entry = NULL;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
if (rmi4_data->sensor_sleep) {
@@ -3891,6 +4654,38 @@ static int fwu_start_recovery(void)
pr_notice("%s: Start of recovery process\n", __func__);
+ if (fwu->image == NULL) {
+ retval = secure_memcpy(fwu->image_name, MAX_IMAGE_NAME_LEN,
+ FW_IHEX_NAME, sizeof(FW_IHEX_NAME),
+ sizeof(FW_IHEX_NAME));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to copy ihex file name\n",
+ __func__);
+ goto exit;
+ }
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Requesting firmware ihex %s\n",
+ __func__, fwu->image_name);
+
+ retval = request_firmware(&fw_entry, fwu->image_name,
+ rmi4_data->pdev->dev.parent);
+ if (retval != 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Firmware ihex %s not available\n",
+ __func__, fwu->image_name);
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Firmware image size = %d\n",
+ __func__, (unsigned int)fw_entry->size);
+
+ fwu->image = fw_entry->data;
+ fwu->image_size = fw_entry->size;
+ }
+
retval = rmi4_data->irq_enable(rmi4_data, false, false);
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
@@ -3934,6 +4729,9 @@ static int fwu_start_recovery(void)
retval = 0;
exit:
+ if (fw_entry)
+ release_firmware(fw_entry);
+
pr_notice("%s: End of recovery process\n", __func__);
mutex_unlock(&rmi4_data->rmi4_exp_init_mutex);
@@ -3943,7 +4741,7 @@ exit:
return retval;
}
-int synaptics_fw_updater(const unsigned char *fw_data)
+int synaptics_fw_updater_force(const unsigned char *fw_data)
{
int retval;
@@ -3966,21 +4764,20 @@ int synaptics_fw_updater(const unsigned char *fw_data)
return retval;
}
-EXPORT_SYMBOL(synaptics_fw_updater);
+EXPORT_SYMBOL(synaptics_fw_updater_force);
#ifdef DO_STARTUP_FW_UPDATE
static void fwu_startup_fw_update_work(struct work_struct *work)
{
static unsigned char do_once = 1;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
#ifdef WAIT_FOR_FB_READY
unsigned int timeout;
#endif
-
if (!do_once)
return;
do_once = 0;
-
#ifdef WAIT_FOR_FB_READY
timeout = FB_READY_TIMEOUT_S * 1000 / FB_READY_WAIT_MS + 1;
@@ -3996,9 +4793,10 @@ static void fwu_startup_fw_update_work(struct work_struct *work)
}
#endif
- synaptics_fw_updater(NULL);
+ synaptics_fw_updater_force(NULL);
- if (rmi4_data->chip_id == CHIP_ID_4322)
+ if (rmi4_data->chip_id == rmi4_data->hw_if->board_data->chip_4322 ||
+ rmi4_data->chip_id == rmi4_data->hw_if->board_data->chip_4722)
firmware_force_update(rmi4_data);
return;
@@ -4064,6 +4862,12 @@ static ssize_t fwu_sysfs_do_recovery_store(struct device *dev,
goto exit;
}
+ retval = fwu_scan_pdt();
+ if (retval < 0)
+ goto exit;
+
+ pr_err("%s: fwu->in_ub_mode = %d\n", __func__, fwu->in_ub_mode);
+
if (!fwu->in_ub_mode) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Not in microbootloader mode\n",
@@ -4132,7 +4936,7 @@ static ssize_t fwu_sysfs_do_reflash_store(struct device *dev,
if (input == FORCE)
fwu->force_update = true;
- retval = synaptics_fw_updater(fwu->image);
+ retval = synaptics_fw_updater_force(fwu->image);
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to do reflash\n",
@@ -4393,11 +5197,11 @@ static void firmware_force_update(struct synaptics_rmi4_data *rmi4_data)
{
int retval;
const struct firmware *fw_entry = NULL;
-
+ const struct synaptics_dsx_board_data *bdata = rmi4_data->hw_if->board_data;
if (!fwu->in_ub_mode)
return;
- retval = request_firmware(&fw_entry, "synaptics_lgd_incell_backup.fw",
+ retval = request_firmware(&fw_entry, bdata->backup_fw_name,
rmi4_data->pdev->dev.parent);
if (retval != 0) {
dev_err(rmi4_data->pdev->dev.parent,
@@ -4476,6 +5280,8 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
if (retval < 0)
goto exit_free_mem;
+ pr_err("%s: fwu->in_ub_mode = %d\n", __func__, fwu->in_ub_mode);
+
if (!fwu->in_ub_mode) {
retval = fwu_read_f34_queries();
if (retval < 0)
@@ -4522,6 +5328,15 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
&fwu->fwu_work);
#endif
+#ifdef F51_DISCRETE_FORCE
+ fwu_read_flash_status();
+ if (!fwu->in_bl_mode) {
+ retval = fwu_f51_force_data_init();
+ if (retval < 0)
+ goto exit_remove_attrs;
+ }
+#endif
+
return 0;
exit_remove_attrs:
@@ -4563,13 +5378,16 @@ static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data)
sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
+#ifdef F51_DISCRETE_FORCE
+ kfree(fwu->cal_data);
+#endif
kfree(fwu->read_config_buf);
kfree(fwu->image_name);
kfree(fwu);
fwu = NULL;
exit:
- complete(&fwu_remove_complete);
+ complete(&fwu_remove_complete_force);
return;
}
@@ -4587,9 +5405,17 @@ static void synaptics_rmi4_fwu_reset(struct synaptics_rmi4_data *rmi4_data)
if (retval < 0)
return;
+ pr_err("%s: fwu->in_ub_mode = %d\n", __func__, fwu->in_ub_mode);
+
if (!fwu->in_ub_mode)
fwu_read_f34_queries();
+#ifdef F51_DISCRETE_FORCE
+ fwu_read_flash_status();
+ if (!fwu->in_bl_mode)
+ fwu_f51_force_data_init();
+#endif
+
return;
}
@@ -4608,16 +5434,16 @@ static struct synaptics_rmi4_exp_fn fwu_module = {
static int __init rmi4_fw_update_module_init(void)
{
- synaptics_rmi4_new_function(&fwu_module, true);
+ synaptics_rmi4_new_function_force(&fwu_module, true);
return 0;
}
static void __exit rmi4_fw_update_module_exit(void)
{
- synaptics_rmi4_new_function(&fwu_module, false);
+ synaptics_rmi4_new_function_force(&fwu_module, false);
- wait_for_completion(&fwu_remove_complete);
+ wait_for_completion(&fwu_remove_complete_force);
return;
}
diff --git a/synaptics_dsx_gesture.c b/synaptics_dsx_gesture.c
index 8a8f371..f58d843 100644
--- a/synaptics_dsx_gesture.c
+++ b/synaptics_dsx_gesture.c
@@ -2290,14 +2290,14 @@ static struct synaptics_rmi4_exp_fn gesture_module = {
static int __init rmi4_gesture_module_init(void)
{
- synaptics_rmi4_new_function(&gesture_module, true);
+ synaptics_rmi4_new_function_force(&gesture_module, true);
return 0;
}
static void __exit rmi4_gesture_module_exit(void)
{
- synaptics_rmi4_new_function(&gesture_module, false);
+ synaptics_rmi4_new_function_force(&gesture_module, false);
wait_for_completion(&udg_remove_complete);
diff --git a/synaptics_dsx_i2c.c b/synaptics_dsx_i2c.c
index 9994dae..dfb738f 100644
--- a/synaptics_dsx_i2c.c
+++ b/synaptics_dsx_i2c.c
@@ -16,7 +16,22 @@
* 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.
+ *
+ * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS
+ * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
+ * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS.
+ * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED
+ * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES
+ * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS'
+ * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S.
+ * DOLLARS.
*/
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -31,12 +46,9 @@
#define SYN_I2C_RETRY_TIMES 4
-/*
-#define I2C_BURST_LIMIT 255
-*/
-/*
-#define XFER_MSGS_LIMIT 8
-*/
+#define I2C_BURST_LIMIT 2048
+
+#define MAX_WRITE_SIZE 4096
static unsigned char *wr_buf;
@@ -174,6 +186,10 @@ static int parse_dt(struct device *dev, struct synaptics_dsx_board_data *bdata)
bdata->cut_off_power = of_property_read_bool(np, "synaptics,cut-off-power");
+ bdata->captouch_use = of_property_read_bool(np, "synaptics,captouch-use");
+
+ bdata->power_ctrl = of_property_read_bool(np, "synaptics,power-ctrl");
+
bdata->power_gpio = of_get_named_gpio_flags(np,
"synaptics,power-gpio", 0, NULL);
if (bdata->power_gpio >= 0) {
@@ -227,7 +243,7 @@ static int parse_dt(struct device *dev, struct synaptics_dsx_board_data *bdata)
retval = of_property_read_u32(np, "synaptics,reset-delay-ms",
&value);
if (retval < 0)
- bdata->reset_delay_ms = 200; /* No reset delay by default */
+ bdata->reset_delay_ms = 0; /* No reset delay by default */
else
bdata->reset_delay_ms = value;
@@ -251,6 +267,42 @@ static int parse_dt(struct device *dev, struct synaptics_dsx_board_data *bdata)
else
bdata->ub_i2c_addr = (unsigned short)value;
+ retval = of_property_read_string(np, "synaptics,backup-fw", &name);
+ if (retval == -EINVAL)
+ bdata->backup_fw_name = NULL;
+ else if (retval < 0)
+ return retval;
+ else
+ bdata->backup_fw_name = name;
+
+ retval = of_property_read_u32(np, "synaptics,chip-3330",
+ &value);
+ if (retval < 0)
+ bdata->chip_3330 = 0;
+ else
+ bdata->chip_3330 = value;
+
+ retval = of_property_read_u32(np, "synaptics,chip-3331",
+ &value);
+ if (retval < 0)
+ bdata->chip_3331 = 1;
+ else
+ bdata->chip_3331 = value;
+
+ retval = of_property_read_u32(np, "synaptics,chip-4322",
+ &value);
+ if (retval < 0)
+ bdata->chip_4322 = 2;
+ else
+ bdata->chip_4322 = value;
+
+ retval = of_property_read_u32(np, "synaptics,chip-4722",
+ &value);
+ if (retval < 0)
+ bdata->chip_4722 = 3;
+ else
+ bdata->chip_4722 = value;
+
prop = of_find_property(np, "synaptics,cap-button-codes", NULL);
if (prop && prop->length) {
bdata->cap_button_map->map = devm_kzalloc(dev,
@@ -351,6 +403,13 @@ static int parse_dt(struct device *dev, struct synaptics_dsx_board_data *bdata)
config_info = bdata->config_array;
for_each_child_of_node(np, temp) {
+ retval = of_property_read_u32(temp, "synaptics,chip-id",
+ &value);
+ if (retval < 0)
+ config_info->chip_id = -1;
+ else
+ config_info->chip_id = value;
+
prop = of_find_property(temp, "synaptics,tp-id", NULL);
if (prop && prop->length) {
if (bdata->tp_id_num != prop->length / sizeof(u8)) {
@@ -479,21 +538,15 @@ static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data,
int retval;
unsigned char retry;
unsigned char buf;
-#ifdef I2C_BURST_LIMIT
- unsigned char ii;
- unsigned char rd_msgs = ((length - 1) / I2C_BURST_LIMIT) + 1;
-#else
- unsigned char rd_msgs = 1;
-#endif
- unsigned char index = 0;
- unsigned char xfer_msgs;
- unsigned char remaining_msgs;
unsigned short i2c_addr;
unsigned short data_offset = 0;
- unsigned short remaining_length = length;
struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent);
struct i2c_adapter *adap = i2c->adapter;
- struct i2c_msg msg[rd_msgs + 1];
+ struct i2c_msg msg[2];
+ unsigned short index = 0;
+ unsigned short read_size;
+ unsigned short max_read_size;
+ unsigned short left_bytes = length;
mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex);
@@ -508,39 +561,36 @@ static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data,
msg[0].len = 1;
msg[0].buf = &buf;
+ msg[1].addr = hw_if.board_data->i2c_addr;
+ msg[1].flags = I2C_M_RD;
+
#ifdef I2C_BURST_LIMIT
- for (ii = 0; ii < (rd_msgs - 1); ii++) {
- msg[ii + 1].addr = hw_if.board_data->i2c_addr;
- msg[ii + 1].flags = I2C_M_RD;
- msg[ii + 1].len = I2C_BURST_LIMIT;
- msg[ii + 1].buf = &data[data_offset];
- data_offset += I2C_BURST_LIMIT;
- remaining_length -= I2C_BURST_LIMIT;
- }
+ max_read_size = I2C_BURST_LIMIT;
+#else
+ max_read_size = length;
#endif
- msg[rd_msgs].addr = hw_if.board_data->i2c_addr;
- msg[rd_msgs].flags = I2C_M_RD;
- msg[rd_msgs].len = remaining_length;
- msg[rd_msgs].buf = &data[data_offset];
+ do {
+ if (left_bytes / max_read_size)
+ read_size = max_read_size;
+ else
+ read_size = left_bytes;
- buf = addr & MASK_8BIT;
+ msg[1].len = read_size;
+ msg[1].buf = &data[data_offset + index];
- remaining_msgs = rd_msgs + 1;
+ buf = addr & MASK_8BIT;
- while (remaining_msgs) {
-#ifdef XFER_MSGS_LIMIT
- if (remaining_msgs > XFER_MSGS_LIMIT)
- xfer_msgs = XFER_MSGS_LIMIT;
- else
- xfer_msgs = remaining_msgs;
-#else
- xfer_msgs = remaining_msgs;
-#endif
for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) {
- retval = i2c_transfer(adap, &msg[index], xfer_msgs);
- if (retval == xfer_msgs)
- break;
+ if (left_bytes == length) {
+ retval = i2c_transfer(adap, &msg[0], 2);
+ if (retval == 2)
+ break;
+ } else {
+ retval = i2c_transfer(adap, &msg[1], 1);
+ if (retval == 1)
+ break;
+ }
dev_err(rmi4_data->pdev->dev.parent,
"%s: I2C retry %d\n",
@@ -551,11 +601,7 @@ static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data,
synaptics_rmi4_i2c_check_addr(rmi4_data, i2c);
i2c_addr = hw_if.board_data->i2c_addr;
msg[0].addr = i2c_addr;
-#ifdef I2C_BURST_LIMIT
- for (ii = 0; ii < (rd_msgs - 1); ii++)
- msg[ii + 1].addr = i2c_addr;
-#endif
- msg[rd_msgs].addr = i2c_addr;
+ msg[1].addr = i2c_addr;
}
}
@@ -567,9 +613,9 @@ static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data,
goto exit;
}
- remaining_msgs -= xfer_msgs;
- index += xfer_msgs;
- }
+ index += read_size;
+ left_bytes -= read_size;
+ } while (left_bytes);
retval = length;
@@ -586,8 +632,18 @@ static int synaptics_rmi4_i2c_write(struct synaptics_rmi4_data *rmi4_data,
unsigned char retry;
struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent);
struct i2c_msg msg[1];
+ unsigned short index = 0;
+ unsigned short write_size;
+ unsigned short max_write_size;
+ unsigned short left_bytes = length;
- retval = synaptics_rmi4_i2c_alloc_buf(rmi4_data, length + 1);
+#ifdef MAX_WRITE_SIZE
+ max_write_size = MAX_WRITE_SIZE;
+#else
+ max_write_size = length;
+#endif
+
+ retval = synaptics_rmi4_i2c_alloc_buf(rmi4_data, max_write_size + 1);
if (retval < 0)
return retval;
@@ -599,42 +655,52 @@ static int synaptics_rmi4_i2c_write(struct synaptics_rmi4_data *rmi4_data,
goto exit;
}
- msg[0].addr = hw_if.board_data->i2c_addr;
- msg[0].flags = 0;
- msg[0].len = length + 1;
- msg[0].buf = wr_buf;
+ do {
+ if (left_bytes / max_write_size)
+ write_size = max_write_size;
+ else
+ write_size = left_bytes;
- wr_buf[0] = addr & MASK_8BIT;
- retval = secure_memcpy(&wr_buf[1], length, &data[0], length, length);
- if (retval < 0) {
- dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to copy data\n",
- __func__);
- goto exit;
- }
+ msg[0].addr = hw_if.board_data->i2c_addr;
+ msg[0].flags = 0;
+ msg[0].len = write_size + 1;
+ msg[0].buf = wr_buf;
+
+ wr_buf[0] = addr & MASK_8BIT;
+ retval = secure_memcpy(&wr_buf[1], write_size, &data[index], write_size, write_size);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to copy data\n",
+ __func__);
+ goto exit;
+ }
+
+ for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) {
+ if (i2c_transfer(i2c->adapter, msg, 1) == 1) {
+ retval = length;
+ break;
+ }
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: I2C retry %d\n",
+ __func__, retry + 1);
+ msleep(20);
- for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) {
- if (i2c_transfer(i2c->adapter, msg, 1) == 1) {
- retval = length;
- break;
+ if (retry == SYN_I2C_RETRY_TIMES / 2) {
+ synaptics_rmi4_i2c_check_addr(rmi4_data, i2c);
+ msg[0].addr = hw_if.board_data->i2c_addr;
+ }
}
- dev_err(rmi4_data->pdev->dev.parent,
- "%s: I2C retry %d\n",
- __func__, retry + 1);
- msleep(20);
-
- if (retry == SYN_I2C_RETRY_TIMES / 2) {
- synaptics_rmi4_i2c_check_addr(rmi4_data, i2c);
- msg[0].addr = hw_if.board_data->i2c_addr;
+
+ if (retry == SYN_I2C_RETRY_TIMES) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: I2C write over retry limit\n",
+ __func__);
+ retval = -EIO;
}
- }
- if (retry == SYN_I2C_RETRY_TIMES) {
- dev_err(rmi4_data->pdev->dev.parent,
- "%s: I2C write over retry limit\n",
- __func__);
- retval = -EIO;
- }
+ index += write_size;
+ left_bytes -= write_size;
+ } while (left_bytes);
exit:
mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex);
@@ -716,7 +782,7 @@ static int synaptics_rmi4_i2c_probe(struct i2c_client *client,
hw_if.bus_access = &bus_access;
hw_if.board_data->i2c_addr = client->addr;
- synaptics_dsx_i2c_device->name = PLATFORM_DRIVER_NAME;
+ synaptics_dsx_i2c_device->name = PLATFORM_DRIVER_FORCE;
synaptics_dsx_i2c_device->id = 0;
synaptics_dsx_i2c_device->num_resources = 0;
synaptics_dsx_i2c_device->dev.parent = &client->dev;
@@ -742,41 +808,40 @@ static int synaptics_rmi4_i2c_remove(struct i2c_client *client)
}
static const struct i2c_device_id synaptics_rmi4_id_table[] = {
- {I2C_DRIVER_NAME, 0},
+ {I2C_DRIVER_FORCE, 0},
{},
};
MODULE_DEVICE_TABLE(i2c, synaptics_rmi4_id_table);
#ifdef CONFIG_OF
-static struct of_device_id synaptics_rmi4_of_match_table[] = {
+static struct of_device_id synaptics_rmi4_of_match_table_force[] = {
{
- .compatible = "synaptics,dsx-i2c",
+ .compatible = "synaptics,dsx-i2c-force",
},
{},
};
-MODULE_DEVICE_TABLE(of, synaptics_rmi4_of_match_table);
+MODULE_DEVICE_TABLE(of, synaptics_rmi4_of_match_table_force);
#else
#define synaptics_rmi4_of_match_table NULL
#endif
static struct i2c_driver synaptics_rmi4_i2c_driver = {
.driver = {
- .name = I2C_DRIVER_NAME,
+ .name = "synaptics_dsi_force",
.owner = THIS_MODULE,
- .of_match_table = synaptics_rmi4_of_match_table,
+ .of_match_table = synaptics_rmi4_of_match_table_force,
},
.probe = synaptics_rmi4_i2c_probe,
.remove = synaptics_rmi4_i2c_remove,
.id_table = synaptics_rmi4_id_table,
};
-int synaptics_rmi4_bus_init(void)
+int synaptics_rmi4_bus_init_force(void)
{
return i2c_add_driver(&synaptics_rmi4_i2c_driver);
}
-EXPORT_SYMBOL(synaptics_rmi4_bus_init);
-void synaptics_rmi4_bus_exit(void)
+void synaptics_rmi4_bus_exit_force(void)
{
kfree(wr_buf);
@@ -784,7 +849,6 @@ void synaptics_rmi4_bus_exit(void)
return;
}
-EXPORT_SYMBOL(synaptics_rmi4_bus_exit);
MODULE_AUTHOR("Synaptics, Inc.");
MODULE_DESCRIPTION("Synaptics DSX I2C Bus Support Module");
diff --git a/synaptics_dsx_proximity.c b/synaptics_dsx_proximity.c
index 6dcc4d2..a4c92ce 100644
--- a/synaptics_dsx_proximity.c
+++ b/synaptics_dsx_proximity.c
@@ -16,7 +16,22 @@
* 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.
+ *
+ * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS
+ * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
+ * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS.
+ * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED
+ * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES
+ * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS'
+ * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S.
+ * DOLLARS.
*/
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -656,14 +671,14 @@ static struct synaptics_rmi4_exp_fn proximity_module = {
static int __init rmi4_proximity_module_init(void)
{
- synaptics_rmi4_new_function(&proximity_module, true);
+ synaptics_rmi4_new_function_force(&proximity_module, true);
return 0;
}
static void __exit rmi4_proximity_module_exit(void)
{
- synaptics_rmi4_new_function(&proximity_module, false);
+ synaptics_rmi4_new_function_force(&proximity_module, false);
wait_for_completion(&prox_remove_complete);
diff --git a/synaptics_dsx_rmi_dev.c b/synaptics_dsx_rmi_dev.c
index 3ba6d46..2d888b8 100644
--- a/synaptics_dsx_rmi_dev.c
+++ b/synaptics_dsx_rmi_dev.c
@@ -16,7 +16,22 @@
* 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.
+ *
+ * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS
+ * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
+ * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS.
+ * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED
+ * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES
+ * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS'
+ * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S.
+ * DOLLARS.
*/
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -70,6 +85,12 @@ static ssize_t rmidev_sysfs_intr_mask_show(struct device *dev,
static ssize_t rmidev_sysfs_intr_mask_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t rmidev_sysfs_concurrent_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t rmidev_sysfs_concurrent_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+
struct rmidev_handle {
dev_t dev_no;
pid_t pid;
@@ -83,7 +104,7 @@ struct rmidev_handle {
struct siginfo terminate_signal;
struct task_struct *task;
void *data;
- bool irq_enabled;
+ bool concurrent;
};
struct rmidev_data {
@@ -123,6 +144,9 @@ static struct device_attribute attrs[] = {
__ATTR(intr_mask, S_IRUGO | S_IWUSR,
rmidev_sysfs_intr_mask_show,
rmidev_sysfs_intr_mask_store),
+ __ATTR(concurrent, S_IRUGO | S_IWUSR,
+ rmidev_sysfs_concurrent_show,
+ rmidev_sysfs_concurrent_store),
};
static int rmidev_major_num;
@@ -131,7 +155,7 @@ static struct class *rmidev_device_class;
static struct rmidev_handle *rmidev;
-DECLARE_COMPLETION(rmidev_remove_complete);
+DECLARE_COMPLETION(rmidev_remove_complete_force);
static irqreturn_t rmidev_sysfs_irq(int irq, void *data)
{
@@ -151,9 +175,15 @@ static int rmidev_sysfs_irq_enable(struct synaptics_rmi4_data *rmi4_data,
unsigned long irq_flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
IRQF_ONESHOT;
+ mutex_lock(&(rmi4_data->rmi4_irq_enable_mutex));
+
if (enable) {
- if (rmidev->irq_enabled)
- return retval;
+ if (rmi4_data->irq_enabled) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Interrupt already enabled\n",
+ __func__);
+ goto exit;
+ }
/* Clear interrupts first */
retval = synaptics_rmi4_reg_read(rmi4_data,
@@ -161,7 +191,7 @@ static int rmidev_sysfs_irq_enable(struct synaptics_rmi4_data *rmi4_data,
intr_status,
rmi4_data->num_of_intr_regs);
if (retval < 0)
- return retval;
+ goto exit;
retval = request_threaded_irq(rmi4_data->irq, NULL,
rmidev_sysfs_irq, irq_flags,
@@ -170,18 +200,21 @@ static int rmidev_sysfs_irq_enable(struct synaptics_rmi4_data *rmi4_data,
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to create irq thread\n",
__func__);
- return retval;
+ goto exit;
}
- rmidev->irq_enabled = true;
+ rmi4_data->irq_enabled = true;
} else {
- if (rmidev->irq_enabled) {
+ if (rmi4_data->irq_enabled) {
disable_irq(rmi4_data->irq);
free_irq(rmi4_data->irq, rmi4_data);
- rmidev->irq_enabled = false;
+ rmi4_data->irq_enabled = false;
}
}
+exit:
+ mutex_unlock(&(rmi4_data->rmi4_irq_enable_mutex));
+
return retval;
}
@@ -190,10 +223,15 @@ static ssize_t rmidev_sysfs_data_show(struct file *data_file,
char *buf, loff_t pos, size_t count)
{
int retval;
+ unsigned char intr_status = 0;
unsigned int length = (unsigned int)count;
unsigned short address = (unsigned short)pos;
+ struct synaptics_rmi4_fn *fhandler;
+ struct synaptics_rmi4_device_info *rmi;
struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data;
+ rmi = &(rmi4_data->rmi4_mod_info);
+
if (length > (REG_ADDR_LIMIT - address)) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Out of register map limit\n",
@@ -216,6 +254,29 @@ static ssize_t rmidev_sysfs_data_show(struct file *data_file,
return -EINVAL;
}
+ if (!rmidev->concurrent)
+ goto exit;
+
+ if (address != rmi4_data->f01_data_base_addr)
+ goto exit;
+
+ if (length <= 1)
+ goto exit;
+
+ intr_status = buf[1];
+
+ if (!list_empty(&rmi->support_fn_list)) {
+ list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
+ if (fhandler->num_of_data_sources) {
+ if (fhandler->intr_mask & intr_status) {
+ rmi4_data->report_touch(rmi4_data,
+ fhandler);
+ }
+ }
+ }
+ }
+
+exit:
return length;
}
@@ -297,11 +358,6 @@ static ssize_t rmidev_sysfs_release_store(struct device *dev,
return -EINVAL;
rmidev_sysfs_irq_enable(rmi4_data, false);
- rmi4_data->irq_enable(rmi4_data, true, false);
-
- dev_dbg(rmi4_data->pdev->dev.parent,
- "%s: Attention interrupt enabled\n",
- __func__);
rmi4_data->reset_device(rmi4_data, false);
@@ -389,6 +445,25 @@ static ssize_t rmidev_sysfs_intr_mask_store(struct device *dev,
return count;
}
+static ssize_t rmidev_sysfs_concurrent_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", rmidev->concurrent);
+}
+
+static ssize_t rmidev_sysfs_concurrent_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned int input;
+
+ if (sscanf(buf, "%u", &input) != 1)
+ return -EINVAL;
+
+ rmidev->concurrent = input > 0 ? true : false;
+
+ return count;
+}
+
static int rmidev_allocate_buffer(int count)
{
if (count + 1 > rmidev->tmpbuf_size) {
@@ -477,7 +552,14 @@ static ssize_t rmidev_read(struct file *filp, char __user *buf,
size_t count, loff_t *f_pos)
{
ssize_t retval;
+ unsigned char intr_status = 0;
+ unsigned short address;
struct rmidev_data *dev_data = filp->private_data;
+ struct synaptics_rmi4_fn *fhandler;
+ struct synaptics_rmi4_device_info *rmi;
+ struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data;
+
+ rmi = &(rmi4_data->rmi4_mod_info);
if (IS_ERR(dev_data)) {
pr_err("%s: Pointer of char device data is invalid", __func__);
@@ -490,10 +572,12 @@ static ssize_t rmidev_read(struct file *filp, char __user *buf,
if (count > (REG_ADDR_LIMIT - *f_pos))
count = REG_ADDR_LIMIT - *f_pos;
- rmidev_allocate_buffer(count);
+ address = (unsigned short)(*f_pos);
mutex_lock(&(dev_data->file_mutex));
+ rmidev_allocate_buffer(count);
+
retval = synaptics_rmi4_reg_read(rmidev->rmi4_data,
*f_pos,
rmidev->tmpbuf,
@@ -506,6 +590,28 @@ static ssize_t rmidev_read(struct file *filp, char __user *buf,
else
*f_pos += retval;
+ if (!rmidev->concurrent)
+ goto clean_up;
+
+ if (address != rmi4_data->f01_data_base_addr)
+ goto clean_up;
+
+ if (count <= 1)
+ goto clean_up;
+
+ intr_status = rmidev->tmpbuf[1];
+
+ if (!list_empty(&rmi->support_fn_list)) {
+ list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
+ if (fhandler->num_of_data_sources) {
+ if (fhandler->intr_mask & intr_status) {
+ rmi4_data->report_touch(rmi4_data,
+ fhandler);
+ }
+ }
+ }
+ }
+
clean_up:
mutex_unlock(&(dev_data->file_mutex));
@@ -537,12 +643,14 @@ static ssize_t rmidev_write(struct file *filp, const char __user *buf,
if (count > (REG_ADDR_LIMIT - *f_pos))
count = REG_ADDR_LIMIT - *f_pos;
+ mutex_lock(&(dev_data->file_mutex));
+
rmidev_allocate_buffer(count);
- if (copy_from_user(rmidev->tmpbuf, buf, count))
+ if (copy_from_user(rmidev->tmpbuf, buf, count)) {
+ mutex_unlock(&(dev_data->file_mutex));
return -EFAULT;
-
- mutex_lock(&(dev_data->file_mutex));
+ }
retval = synaptics_rmi4_reg_write(rmidev->rmi4_data,
*f_pos,
@@ -609,17 +717,13 @@ static int rmidev_release(struct inode *inp, struct file *filp)
if (dev_data->ref_count < 0)
dev_data->ref_count = 0;
- rmi4_data->irq_enable(rmi4_data, true, false);
- dev_dbg(rmi4_data->pdev->dev.parent,
- "%s: Attention interrupt enabled\n",
- __func__);
-
- mutex_unlock(&(dev_data->file_mutex));
- rmi4_data->reset_device(rmi4_data, false);
+ rmi4_data->irq_enable(rmi4_data, true, false);
rmi4_data->stay_awake = false;
+ mutex_unlock(&(dev_data->file_mutex));
+
return 0;
}
@@ -914,7 +1018,7 @@ static void rmidev_remove_device(struct synaptics_rmi4_data *rmi4_data)
rmidev = NULL;
exit:
- complete(&rmidev_remove_complete);
+ complete(&rmidev_remove_complete_force);
return;
}
@@ -934,16 +1038,16 @@ static struct synaptics_rmi4_exp_fn rmidev_module = {
static int __init rmidev_module_init(void)
{
- synaptics_rmi4_new_function(&rmidev_module, true);
+ synaptics_rmi4_new_function_force(&rmidev_module, true);
return 0;
}
static void __exit rmidev_module_exit(void)
{
- synaptics_rmi4_new_function(&rmidev_module, false);
+ synaptics_rmi4_new_function_force(&rmidev_module, false);
- wait_for_completion(&rmidev_remove_complete);
+ wait_for_completion(&rmidev_remove_complete_force);
return;
}
diff --git a/synaptics_dsx_rmi_hid_i2c.c b/synaptics_dsx_rmi_hid_i2c.c
index 568fe35..cb17318 100644
--- a/synaptics_dsx_rmi_hid_i2c.c
+++ b/synaptics_dsx_rmi_hid_i2c.c
@@ -130,7 +130,8 @@ static int parse_dt(struct device *dev, struct synaptics_dsx_board_data *bdata)
struct device_node *np = dev->of_node;
bdata->irq_gpio = of_get_named_gpio_flags(np,
- "synaptics,irq-gpio", 0, NULL);
+ "synaptics,irq-gpio", 0,
+ (enum of_gpio_flags *)&bdata->irq_flags);
retval = of_property_read_u32(np, "synaptics,irq-on-state",
&value);
@@ -139,117 +140,141 @@ static int parse_dt(struct device *dev, struct synaptics_dsx_board_data *bdata)
else
bdata->irq_on_state = value;
- retval = of_property_read_u32(np, "synaptics,irq-flags", &value);
- if (retval < 0)
- return retval;
- else
- bdata->irq_flags = value;
-
retval = of_property_read_string(np, "synaptics,pwr-reg-name", &name);
- if (retval == -EINVAL)
+ if (retval < 0)
bdata->pwr_reg_name = NULL;
- else if (retval < 0)
- return retval;
else
bdata->pwr_reg_name = name;
retval = of_property_read_string(np, "synaptics,bus-reg-name", &name);
- if (retval == -EINVAL)
+ if (retval < 0)
bdata->bus_reg_name = NULL;
- else if (retval < 0)
- return retval;
else
bdata->bus_reg_name = name;
- if (of_property_read_bool(np, "synaptics,power-gpio")) {
+ prop = of_find_property(np, "synaptics,power-gpio", NULL);
+ if (prop && prop->length) {
bdata->power_gpio = of_get_named_gpio_flags(np,
"synaptics,power-gpio", 0, NULL);
retval = of_property_read_u32(np, "synaptics,power-on-state",
&value);
- if (retval < 0)
+ if (retval < 0) {
+ dev_err(dev, "%s: Unable to read synaptics,power-on-state property\n",
+ __func__);
return retval;
- else
+ } else {
bdata->power_on_state = value;
+ }
} else {
bdata->power_gpio = -1;
}
- if (of_property_read_bool(np, "synaptics,power-delay-ms")) {
+ prop = of_find_property(np, "synaptics,power-delay-ms", NULL);
+ if (prop && prop->length) {
retval = of_property_read_u32(np, "synaptics,power-delay-ms",
&value);
- if (retval < 0)
+ if (retval < 0) {
+ dev_err(dev, "%s: Unable to read synaptics,power-delay-ms property\n",
+ __func__);
return retval;
- else
+ } else {
bdata->power_delay_ms = value;
+ }
} else {
bdata->power_delay_ms = 0;
}
- if (of_property_read_bool(np, "synaptics,reset-gpio")) {
+ prop = of_find_property(np, "synaptics,reset-gpio", NULL);
+ if (prop && prop->length) {
bdata->reset_gpio = of_get_named_gpio_flags(np,
"synaptics,reset-gpio", 0, NULL);
retval = of_property_read_u32(np, "synaptics,reset-on-state",
&value);
- if (retval < 0)
+ if (retval < 0) {
+ dev_err(dev, "%s: Unable to read synaptics,reset-on-state property\n",
+ __func__);
return retval;
- else
+ } else {
bdata->reset_on_state = value;
+ }
retval = of_property_read_u32(np, "synaptics,reset-active-ms",
&value);
- if (retval < 0)
+ if (retval < 0) {
+ dev_err(dev, "%s: Unable to read synaptics,reset-active-ms property\n",
+ __func__);
return retval;
- else
+ } else {
bdata->reset_active_ms = value;
+ }
} else {
bdata->reset_gpio = -1;
}
- if (of_property_read_bool(np, "synaptics,reset-delay-ms")) {
+ prop = of_find_property(np, "synaptics,reset-delay-ms", NULL);
+ if (prop && prop->length) {
retval = of_property_read_u32(np, "synaptics,reset-delay-ms",
&value);
- if (retval < 0)
+ if (retval < 0) {
+ dev_err(dev, "%s: Unable to read synaptics,reset-delay-ms property\n",
+ __func__);
return retval;
- else
+ } else {
bdata->reset_delay_ms = value;
+ }
} else {
bdata->reset_delay_ms = 0;
}
- if (of_property_read_bool(np, "synaptics,dev-dscrptr-addr")) {
+ prop = of_find_property(np, "synaptics,dev-dscrptr-addr", NULL);
+ if (prop && prop->length) {
retval = of_property_read_u32(np, "synaptics,dev-dscrptr-addr",
&value);
- if (retval < 0)
+ if (retval < 0) {
+ dev_err(dev, "%s: Unable to read synaptics,dev-dscrptr-addr property\n",
+ __func__);
return retval;
- else
+ } else {
bdata->device_descriptor_addr = (unsigned short)value;
+ }
} else {
bdata->device_descriptor_addr = 0;
}
- if (of_property_read_bool(np, "synaptics,max-y-for-2d")) {
+ prop = of_find_property(np, "synaptics,max-y-for-2d", NULL);
+ if (prop && prop->length) {
retval = of_property_read_u32(np, "synaptics,max-y-for-2d",
&value);
- if (retval < 0)
+ if (retval < 0) {
+ dev_err(dev, "%s: Unable to read synaptics,max-y-for-2d property\n",
+ __func__);
return retval;
- else
+ } else {
bdata->max_y_for_2d = value;
+ }
} else {
bdata->max_y_for_2d = -1;
}
- bdata->swap_axes = of_property_read_bool(np, "synaptics,swap-axes");
+ prop = of_find_property(np, "synaptics,swap-axes", NULL);
+ bdata->swap_axes = prop > 0 ? true : false;
- bdata->x_flip = of_property_read_bool(np, "synaptics,x-flip");
+ prop = of_find_property(np, "synaptics,x-flip", NULL);
+ bdata->x_flip = prop > 0 ? true : false;
- bdata->y_flip = of_property_read_bool(np, "synaptics,y-flip");
+ prop = of_find_property(np, "synaptics,y-flip", NULL);
+ bdata->y_flip = prop > 0 ? true : false;
- if (of_property_read_bool(np, "synaptics,ub-i2c-addr")) {
+ prop = of_find_property(np, "synaptics,ub-i2c-addr", NULL);
+ if (prop && prop->length) {
retval = of_property_read_u32(np, "synaptics,ub-i2c-addr",
&value);
- if (retval < 0)
+ if (retval < 0) {
+ dev_err(dev, "%s: Unable to read synaptics,ub-i2c-addr property\n",
+ __func__);
return retval;
- else
+ } else {
bdata->ub_i2c_addr = (unsigned short)value;
+ }
} else {
bdata->ub_i2c_addr = -1;
}
@@ -963,19 +988,17 @@ static struct i2c_driver synaptics_rmi4_i2c_driver = {
.id_table = synaptics_rmi4_id_table,
};
-int synaptics_rmi4_bus_init(void)
+int synaptics_rmi4_bus_init_force(void)
{
return i2c_add_driver(&synaptics_rmi4_i2c_driver);
}
-EXPORT_SYMBOL(synaptics_rmi4_bus_init);
-void synaptics_rmi4_bus_exit(void)
+void synaptics_rmi4_bus_exit_force(void)
{
i2c_del_driver(&synaptics_rmi4_i2c_driver);
return;
}
-EXPORT_SYMBOL(synaptics_rmi4_bus_exit);
MODULE_AUTHOR("Synaptics, Inc.");
MODULE_DESCRIPTION("Synaptics DSX I2C Bus Support Module");
diff --git a/synaptics_dsx_spi.c b/synaptics_dsx_spi.c
index 7e86cf8..2acd05d 100644
--- a/synaptics_dsx_spi.c
+++ b/synaptics_dsx_spi.c
@@ -5,6 +5,7 @@
*
* Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
* Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
+ * Copyright (C) 2016 XiaoMi, Inc.
*
* 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
@@ -15,7 +16,22 @@
* 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.
+ *
+ * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS
+ * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
+ * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS.
+ * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED
+ * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES
+ * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS'
+ * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S.
+ * DOLLARS.
*/
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -31,6 +47,10 @@
#define SPI_READ 0x80
#define SPI_WRITE 0x00
+static unsigned char *buf;
+
+static struct spi_transfer *xfer;
+
#ifdef CONFIG_OF
static int parse_dt(struct device *dev, struct synaptics_dsx_board_data *bdata)
{
@@ -41,7 +61,8 @@ static int parse_dt(struct device *dev, struct synaptics_dsx_board_data *bdata)
struct device_node *np = dev->of_node;
bdata->irq_gpio = of_get_named_gpio_flags(np,
- "synaptics,irq-gpio", 0, NULL);
+ "synaptics,irq-gpio", 0,
+ (enum of_gpio_flags *)&bdata->irq_flags);
retval = of_property_read_u32(np, "synaptics,irq-on-state",
&value);
@@ -50,120 +71,174 @@ static int parse_dt(struct device *dev, struct synaptics_dsx_board_data *bdata)
else
bdata->irq_on_state = value;
- retval = of_property_read_u32(np, "synaptics,irq-flags", &value);
- if (retval < 0)
- return retval;
- else
- bdata->irq_flags = value;
-
retval = of_property_read_string(np, "synaptics,pwr-reg-name", &name);
- if (retval == -EINVAL)
+ if (retval < 0)
bdata->pwr_reg_name = NULL;
- else if (retval < 0)
- return retval;
else
bdata->pwr_reg_name = name;
retval = of_property_read_string(np, "synaptics,bus-reg-name", &name);
- if (retval == -EINVAL)
+ if (retval < 0)
bdata->bus_reg_name = NULL;
- else if (retval < 0)
- return retval;
else
bdata->bus_reg_name = name;
- if (of_property_read_bool(np, "synaptics,power-gpio")) {
+ prop = of_find_property(np, "synaptics,power-gpio", NULL);
+ if (prop && prop->length) {
bdata->power_gpio = of_get_named_gpio_flags(np,
"synaptics,power-gpio", 0, NULL);
retval = of_property_read_u32(np, "synaptics,power-on-state",
&value);
- if (retval < 0)
+ if (retval < 0) {
+ dev_err(dev, "%s: Unable to read synaptics,power-on-state property\n",
+ __func__);
return retval;
- else
+ } else {
bdata->power_on_state = value;
+ }
} else {
bdata->power_gpio = -1;
}
- if (of_property_read_bool(np, "synaptics,power-delay-ms")) {
+ prop = of_find_property(np, "synaptics,power-delay-ms", NULL);
+ if (prop && prop->length) {
retval = of_property_read_u32(np, "synaptics,power-delay-ms",
&value);
- if (retval < 0)
+ if (retval < 0) {
+ dev_err(dev, "%s: Unable to read synaptics,power-delay-ms property\n",
+ __func__);
return retval;
- else
+ } else {
bdata->power_delay_ms = value;
+ }
} else {
bdata->power_delay_ms = 0;
}
- if (of_property_read_bool(np, "synaptics,reset-gpio")) {
+ prop = of_find_property(np, "synaptics,reset-gpio", NULL);
+ if (prop && prop->length) {
bdata->reset_gpio = of_get_named_gpio_flags(np,
"synaptics,reset-gpio", 0, NULL);
retval = of_property_read_u32(np, "synaptics,reset-on-state",
&value);
- if (retval < 0)
+ if (retval < 0) {
+ dev_err(dev, "%s: Unable to read synaptics,reset-on-state property\n",
+ __func__);
return retval;
- else
+ } else {
bdata->reset_on_state = value;
+ }
retval = of_property_read_u32(np, "synaptics,reset-active-ms",
&value);
- if (retval < 0)
+ if (retval < 0) {
+ dev_err(dev, "%s: Unable to read synaptics,reset-active-ms property\n",
+ __func__);
return retval;
- else
+ } else {
bdata->reset_active_ms = value;
+ }
} else {
bdata->reset_gpio = -1;
}
- if (of_property_read_bool(np, "synaptics,reset-delay-ms")) {
+ prop = of_find_property(np, "synaptics,reset-delay-ms", NULL);
+ if (prop && prop->length) {
retval = of_property_read_u32(np, "synaptics,reset-delay-ms",
&value);
- if (retval < 0)
+ if (retval < 0) {
+ dev_err(dev, "%s: Unable to read synaptics,reset-delay-ms property\n",
+ __func__);
return retval;
- else
+ } else {
bdata->reset_delay_ms = value;
+ }
} else {
bdata->reset_delay_ms = 0;
}
- if (of_property_read_bool(np, "synaptics,byte-delay-us")) {
+ prop = of_find_property(np, "synaptics,byte-delay-us", NULL);
+ if (prop && prop->length) {
retval = of_property_read_u32(np, "synaptics,byte-delay-us",
&value);
- if (retval < 0)
+ if (retval < 0) {
+ dev_err(dev, "%s: Unable to read synaptics,byte-delay-us property\n",
+ __func__);
return retval;
- else
+ } else {
bdata->byte_delay_us = value;
+ }
} else {
bdata->byte_delay_us = 0;
}
- if (of_property_read_bool(np, "synaptics,block-delay-us")) {
+ prop = of_find_property(np, "synaptics,block-delay-us", NULL);
+ if (prop && prop->length) {
retval = of_property_read_u32(np, "synaptics,block-delay-us",
&value);
- if (retval < 0)
+ if (retval < 0) {
+ dev_err(dev, "%s: Unable to read synaptics,block-delay-us property\n",
+ __func__);
return retval;
- else
+ } else {
bdata->block_delay_us = value;
+ }
} else {
bdata->block_delay_us = 0;
}
- if (of_property_read_bool(np, "synaptics,max-y-for-2d")) {
+ prop = of_find_property(np, "synaptics,address-delay-us", NULL);
+ if (prop && prop->length) {
+ retval = of_property_read_u32(np, "synaptics,address-delay-us",
+ &value);
+ if (retval < 0) {
+ dev_err(dev, "%s: Unable to read synaptics,address-delay-us property\n",
+ __func__);
+ return retval;
+ } else {
+ bdata->addr_delay_us = value;
+ }
+ } else {
+ bdata->addr_delay_us = 0;
+ }
+
+ prop = of_find_property(np, "synaptics,max-y-for-2d", NULL);
+ if (prop && prop->length) {
retval = of_property_read_u32(np, "synaptics,max-y-for-2d",
&value);
- if (retval < 0)
+ if (retval < 0) {
+ dev_err(dev, "%s: Unable to read synaptics,max-y-for-2d property\n",
+ __func__);
return retval;
- else
+ } else {
bdata->max_y_for_2d = value;
+ }
} else {
bdata->max_y_for_2d = -1;
}
- bdata->swap_axes = of_property_read_bool(np, "synaptics,swap-axes");
+ prop = of_find_property(np, "synaptics,swap-axes", NULL);
+ bdata->swap_axes = prop > 0 ? true : false;
- bdata->x_flip = of_property_read_bool(np, "synaptics,x-flip");
+ prop = of_find_property(np, "synaptics,x-flip", NULL);
+ bdata->x_flip = prop > 0 ? true : false;
- bdata->y_flip = of_property_read_bool(np, "synaptics,y-flip");
+ prop = of_find_property(np, "synaptics,y-flip", NULL);
+ bdata->y_flip = prop > 0 ? true : false;
+
+ prop = of_find_property(np, "synaptics,ub-i2c-addr", NULL);
+ if (prop && prop->length) {
+ retval = of_property_read_u32(np, "synaptics,ub-i2c-addr",
+ &value);
+ if (retval < 0) {
+ dev_err(dev, "%s: Unable to read synaptics,ub-i2c-addr property\n",
+ __func__);
+ return retval;
+ } else {
+ bdata->ub_i2c_addr = (unsigned short)value;
+ }
+ } else {
+ bdata->ub_i2c_addr = -1;
+ }
prop = of_find_property(np, "synaptics,cap-button-codes", NULL);
if (prop && prop->length) {
@@ -212,50 +287,100 @@ static int parse_dt(struct device *dev, struct synaptics_dsx_board_data *bdata)
}
#endif
+static int synaptics_rmi4_spi_alloc_buf(struct synaptics_rmi4_data *rmi4_data,
+ unsigned int size, unsigned int count)
+{
+ static unsigned int buf_size;
+ static unsigned int xfer_count;
+
+ if (size > buf_size) {
+ if (buf_size)
+ kfree(buf);
+ buf = kmalloc(size, GFP_KERNEL);
+ if (!buf) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to alloc mem for buf\n",
+ __func__);
+ buf_size = 0;
+ return -ENOMEM;
+ }
+ buf_size = size;
+ }
+
+ if (count > xfer_count) {
+ if (xfer_count)
+ kfree(xfer);
+ xfer = kcalloc(count, sizeof(struct spi_transfer), GFP_KERNEL);
+ if (!xfer) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to alloc mem for xfer\n",
+ __func__);
+ xfer_count = 0;
+ return -ENOMEM;
+ }
+ xfer_count = count;
+ } else {
+ memset(xfer, 0, count * sizeof(struct spi_transfer));
+ }
+
+ return 0;
+}
+
static int synaptics_rmi4_spi_set_page(struct synaptics_rmi4_data *rmi4_data,
unsigned short addr)
{
int retval;
unsigned int index;
- unsigned int xfer_count = PAGE_SELECT_LEN + 1;
- unsigned char txbuf[xfer_count];
+ unsigned int byte_count = PAGE_SELECT_LEN + 1;
unsigned char page;
struct spi_message msg;
- struct spi_transfer xfers[xfer_count];
struct spi_device *spi = to_spi_device(rmi4_data->pdev->dev.parent);
const struct synaptics_dsx_board_data *bdata =
rmi4_data->hw_if->board_data;
- page = ((addr >> 8) & ~MASK_7BIT);
- if (page != rmi4_data->current_page) {
- spi_message_init(&msg);
+ page = ((addr >> 8) & MASK_8BIT);
+ if ((page >> 7) == (rmi4_data->current_page >> 7))
+ return PAGE_SELECT_LEN;
- txbuf[0] = SPI_WRITE;
- txbuf[1] = MASK_8BIT;
- txbuf[2] = page;
+ spi_message_init(&msg);
- for (index = 0; index < xfer_count; index++) {
- memset(&xfers[index], 0, sizeof(struct spi_transfer));
- xfers[index].len = 1;
- xfers[index].delay_usecs = bdata->byte_delay_us;
- xfers[index].tx_buf = &txbuf[index];
- spi_message_add_tail(&xfers[index], &msg);
- }
+ retval = synaptics_rmi4_spi_alloc_buf(rmi4_data, byte_count,
+ byte_count);
+ if (retval < 0)
+ return retval;
- if (bdata->block_delay_us)
- xfers[index - 1].delay_usecs = bdata->block_delay_us;
+ buf[0] = SPI_WRITE;
+ buf[1] = MASK_8BIT;
+ buf[2] = page;
- retval = spi_sync(spi, &msg);
- if (retval == 0) {
- rmi4_data->current_page = page;
- retval = PAGE_SELECT_LEN;
- } else {
- dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to complete SPI transfer, error = %d\n",
- __func__, retval);
- }
+ if (bdata->byte_delay_us == 0) {
+ xfer[0].len = byte_count;
+ xfer[0].tx_buf = &buf[0];
+ if (bdata->block_delay_us)
+ xfer[0].delay_usecs = bdata->block_delay_us;
+ spi_message_add_tail(&xfer[0], &msg);
} else {
+ for (index = 0; index < byte_count; index++) {
+ xfer[index].len = 1;
+ xfer[index].tx_buf = &buf[index];
+ if (index == 1)
+ xfer[index].delay_usecs = bdata->addr_delay_us;
+ else
+ xfer[index].delay_usecs = bdata->byte_delay_us;
+ spi_message_add_tail(&xfer[index], &msg);
+ }
+ if (bdata->block_delay_us)
+ xfer[index - 1].delay_usecs = bdata->block_delay_us;
+ }
+
+ retval = spi_sync(spi, &msg);
+ if (retval == 0) {
+ rmi4_data->current_page = page;
retval = PAGE_SELECT_LEN;
+ } else {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to complete SPI transfer, error = %d\n",
+ __func__, retval);
}
return retval;
@@ -266,63 +391,67 @@ static int synaptics_rmi4_spi_read(struct synaptics_rmi4_data *rmi4_data,
{
int retval;
unsigned int index;
- unsigned int xfer_count = length + ADDRESS_WORD_LEN;
- unsigned char txbuf[ADDRESS_WORD_LEN];
- unsigned char *rxbuf = NULL;
+ unsigned int byte_count = length + ADDRESS_LEN;
+ unsigned char txbuf[ADDRESS_LEN];
struct spi_message msg;
- struct spi_transfer *xfers = NULL;
struct spi_device *spi = to_spi_device(rmi4_data->pdev->dev.parent);
const struct synaptics_dsx_board_data *bdata =
rmi4_data->hw_if->board_data;
spi_message_init(&msg);
- xfers = kcalloc(xfer_count, sizeof(struct spi_transfer), GFP_KERNEL);
- if (!xfers) {
- dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to allocate memory for xfers\n",
- __func__);
- retval = -ENOMEM;
- goto exit;
- }
-
txbuf[0] = (addr >> 8) | SPI_READ;
txbuf[1] = addr & MASK_8BIT;
- rxbuf = kmalloc(length, GFP_KERNEL);
- if (!rxbuf) {
- dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to allocate memory for rxbuf\n",
- __func__);
- retval = -ENOMEM;
- goto exit;
- }
-
mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex);
retval = synaptics_rmi4_spi_set_page(rmi4_data, addr);
if (retval != PAGE_SELECT_LEN) {
mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex);
- retval = -EIO;
- goto exit;
+ return -EIO;
}
- for (index = 0; index < xfer_count; index++) {
- xfers[index].len = 1;
- xfers[index].delay_usecs = bdata->byte_delay_us;
- if (index < ADDRESS_WORD_LEN)
- xfers[index].tx_buf = &txbuf[index];
- else
- xfers[index].rx_buf = &rxbuf[index - ADDRESS_WORD_LEN];
- spi_message_add_tail(&xfers[index], &msg);
+ if (bdata->byte_delay_us == 0) {
+ retval = synaptics_rmi4_spi_alloc_buf(rmi4_data, length,
+ 2);
+ } else {
+ retval = synaptics_rmi4_spi_alloc_buf(rmi4_data, length,
+ byte_count);
+ }
+ if (retval < 0) {
+ mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex);
+ return retval;
}
- if (bdata->block_delay_us)
- xfers[index - 1].delay_usecs = bdata->block_delay_us;
+ if (bdata->byte_delay_us == 0) {
+ xfer[0].len = ADDRESS_LEN;
+ xfer[0].tx_buf = &txbuf[0];
+ spi_message_add_tail(&xfer[0], &msg);
+ xfer[1].len = length;
+ xfer[1].rx_buf = &buf[0];
+ if (bdata->block_delay_us)
+ xfer[1].delay_usecs = bdata->block_delay_us;
+ spi_message_add_tail(&xfer[1], &msg);
+ } else {
+ for (index = 0; index < byte_count; index++) {
+ xfer[index].len = 1;
+ if (index < ADDRESS_LEN)
+ xfer[index].tx_buf = &txbuf[index];
+ else
+ xfer[index].rx_buf = &buf[index - ADDRESS_LEN];
+ if (index == 1)
+ xfer[index].delay_usecs = bdata->addr_delay_us;
+ else
+ xfer[index].delay_usecs = bdata->byte_delay_us;
+ spi_message_add_tail(&xfer[index], &msg);
+ }
+ if (bdata->block_delay_us)
+ xfer[index - 1].delay_usecs = bdata->block_delay_us;
+ }
retval = spi_sync(spi, &msg);
if (retval == 0) {
- retval = secure_memcpy(data, length, rxbuf, length, length);
+ retval = secure_memcpy(data, length, buf, length, length);
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to copy data\n",
@@ -338,10 +467,6 @@ static int synaptics_rmi4_spi_read(struct synaptics_rmi4_data *rmi4_data,
mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex);
-exit:
- kfree(rxbuf);
- kfree(xfers);
-
return retval;
}
@@ -350,64 +475,66 @@ static int synaptics_rmi4_spi_write(struct synaptics_rmi4_data *rmi4_data,
{
int retval;
unsigned int index;
- unsigned int xfer_count = length + ADDRESS_WORD_LEN;
- unsigned char *txbuf = NULL;
+ unsigned int byte_count = length + ADDRESS_LEN;
struct spi_message msg;
- struct spi_transfer *xfers = NULL;
struct spi_device *spi = to_spi_device(rmi4_data->pdev->dev.parent);
const struct synaptics_dsx_board_data *bdata =
rmi4_data->hw_if->board_data;
spi_message_init(&msg);
- xfers = kcalloc(xfer_count, sizeof(struct spi_transfer), GFP_KERNEL);
- if (!xfers) {
- dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to allocate memory for xfers\n",
- __func__);
- retval = -ENOMEM;
- goto exit;
+ mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex);
+
+ retval = synaptics_rmi4_spi_set_page(rmi4_data, addr);
+ if (retval != PAGE_SELECT_LEN) {
+ mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex);
+ return -EIO;
}
- txbuf = kmalloc(xfer_count, GFP_KERNEL);
- if (!txbuf) {
- dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to allocate memory for txbuf\n",
- __func__);
- retval = -ENOMEM;
- goto exit;
+ if (bdata->byte_delay_us == 0) {
+ retval = synaptics_rmi4_spi_alloc_buf(rmi4_data, byte_count,
+ 1);
+ } else {
+ retval = synaptics_rmi4_spi_alloc_buf(rmi4_data, byte_count,
+ byte_count);
+ }
+ if (retval < 0) {
+ mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex);
+ return retval;
}
- txbuf[0] = (addr >> 8) & ~SPI_READ;
- txbuf[1] = addr & MASK_8BIT;
- retval = secure_memcpy(&txbuf[ADDRESS_WORD_LEN],
- xfer_count - ADDRESS_WORD_LEN, data, length, length);
+ buf[0] = (addr >> 8) & ~SPI_READ;
+ buf[1] = addr & MASK_8BIT;
+ retval = secure_memcpy(&buf[ADDRESS_LEN],
+ byte_count - ADDRESS_LEN, data, length, length);
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to copy data\n",
__func__);
- goto exit;
- }
-
- mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex);
-
- retval = synaptics_rmi4_spi_set_page(rmi4_data, addr);
- if (retval != PAGE_SELECT_LEN) {
mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex);
- retval = -EIO;
- goto exit;
+ return retval;
}
- for (index = 0; index < xfer_count; index++) {
- xfers[index].len = 1;
- xfers[index].delay_usecs = bdata->byte_delay_us;
- xfers[index].tx_buf = &txbuf[index];
- spi_message_add_tail(&xfers[index], &msg);
+ if (bdata->byte_delay_us == 0) {
+ xfer[0].len = byte_count;
+ xfer[0].tx_buf = &buf[0];
+ if (bdata->block_delay_us)
+ xfer[0].delay_usecs = bdata->block_delay_us;
+ spi_message_add_tail(xfer, &msg);
+ } else {
+ for (index = 0; index < byte_count; index++) {
+ xfer[index].len = 1;
+ xfer[index].tx_buf = &buf[index];
+ if (index == 1)
+ xfer[index].delay_usecs = bdata->addr_delay_us;
+ else
+ xfer[index].delay_usecs = bdata->byte_delay_us;
+ spi_message_add_tail(&xfer[index], &msg);
+ }
+ if (bdata->block_delay_us)
+ xfer[index - 1].delay_usecs = bdata->block_delay_us;
}
- if (bdata->block_delay_us)
- xfers[index - 1].delay_usecs = bdata->block_delay_us;
-
retval = spi_sync(spi, &msg);
if (retval == 0) {
retval = length;
@@ -419,10 +546,6 @@ static int synaptics_rmi4_spi_write(struct synaptics_rmi4_data *rmi4_data,
mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex);
-exit:
- kfree(txbuf);
- kfree(xfers);
-
return retval;
}
@@ -537,6 +660,12 @@ static int synaptics_rmi4_spi_remove(struct spi_device *spi)
return 0;
}
+static const struct spi_device_id synaptics_rmi4_id_table[] = {
+ {SPI_DRIVER_NAME, 0},
+ {},
+};
+MODULE_DEVICE_TABLE(spi, synaptics_rmi4_id_table);
+
#ifdef CONFIG_OF
static struct of_device_id synaptics_rmi4_of_match_table[] = {
{
@@ -557,22 +686,25 @@ static struct spi_driver synaptics_rmi4_spi_driver = {
},
.probe = synaptics_rmi4_spi_probe,
.remove = synaptics_rmi4_spi_remove,
+ .id_table = synaptics_rmi4_id_table,
};
-int synaptics_rmi4_bus_init(void)
+int synaptics_rmi4_bus_init_force(void)
{
return spi_register_driver(&synaptics_rmi4_spi_driver);
}
-EXPORT_SYMBOL(synaptics_rmi4_bus_init);
-void synaptics_rmi4_bus_exit(void)
+void synaptics_rmi4_bus_exit_force(void)
{
+ kfree(buf);
+
+ kfree(xfer);
+
spi_unregister_driver(&synaptics_rmi4_spi_driver);
return;
}
-EXPORT_SYMBOL(synaptics_rmi4_bus_exit);
MODULE_AUTHOR("Synaptics, Inc.");
MODULE_DESCRIPTION("Synaptics DSX SPI Bus Support Module");
diff --git a/synaptics_dsx_test_reporting.c b/synaptics_dsx_test_reporting.c
index e063a60..b52ac26 100644
--- a/synaptics_dsx_test_reporting.c
+++ b/synaptics_dsx_test_reporting.c
@@ -48,7 +48,9 @@
#define SYSFS_FOLDER_NAME "f54"
-#define USE_RT8
+
+
+#define BUTTON_COUNT 3
#define GET_REPORT_TIMEOUT_S 3
#define CALIBRATION_TIMEOUT_S 10
@@ -66,9 +68,6 @@
#define SENSOR_RX_MAPPING_OFFSET 1
#define SENSOR_TX_MAPPING_OFFSET 2
-/* td43xx start */
-#define AMP_SENSOR_CHAR_OFFSET 5
-/* td43xx end */
#define COMMAND_GET_REPORT 1
#define COMMAND_FORCE_CAL 2
@@ -188,13 +187,37 @@
#define CONTROL_147_SIZE 1
#define CONTROL_148_SIZE 1
#define CONTROL_149_SIZE 1
+#define CONTROL_150_SIZE 1
+#define CONTROL_151_SIZE 1
+#define CONTROL_152_SIZE 1
+#define CONTROL_153_SIZE 1
+#define CONTROL_154_SIZE 1
+#define CONTROL_155_SIZE 1
+#define CONTROL_156_SIZE 1
+#define CONTROL_157_158_SIZE 2
#define CONTROL_163_SIZE 1
#define CONTROL_165_SIZE 1
#define CONTROL_166_SIZE 1
#define CONTROL_167_SIZE 1
+#define CONTROL_168_SIZE 1
+#define CONTROL_169_SIZE 1
+#define CONTROL_171_SIZE 1
+#define CONTROL_172_SIZE 1
+#define CONTROL_173_SIZE 1
+#define CONTROL_174_SIZE 1
+#define CONTROL_175_SIZE 1
#define CONTROL_176_SIZE 1
+#define CONTROL_177_178_SIZE 2
#define CONTROL_179_SIZE 1
+#define CONTROL_182_SIZE 1
+#define CONTROL_183_SIZE 1
+#define CONTROL_185_SIZE 1
+#define CONTROL_186_SIZE 1
+#define CONTROL_187_SIZE 1
#define CONTROL_188_SIZE 1
+#define CONTROL_196_SIZE 1
+#define CONTROL_218_SIZE 1
+#define CONTROL_223_SIZE 1
#define HIGH_RESISTANCE_DATA_SIZE 6
#define FULL_RAW_CAP_MIN_MAX_DATA_SIZE 4
@@ -207,6 +230,9 @@
#define TDDI_OPEN_TEST_INT_DUR_TWO 15
#define TDDI_OPEN_TEST_LIMIT_PHASE2_LOWER 50
+#define ABS_0D_OPEN_FACTOR 8
+#define ABS_0D_OPEN_TEST_LIMIT 30
+
#define TEST_INVALID 0
#define TEST_FAILED 1
#define TEST_OK 2
@@ -214,7 +240,8 @@
#define TEST_TYPE_20_333X "20"
#define TEST_TYPE_25_333X "25"
#define TEST_TYPE_26_333X "26"
-
+#define TEST_TYPE_02 "2"
+#define TEST_TYPE_03 "3"
#define CHIP_ID_OFFSET 11
@@ -300,11 +327,8 @@ enum f54_report_types {
F54_RX_TO_RX_SHORTS_2 = 17,
F54_RX_OPENS_2 = 18,
F54_FULL_RAW_CAP = 19,
-#ifdef USE_RT8
- F54_FULL_RAW_CAP_NO_RX_COUPLING = 8,
-#else
+ F54_FULL_RAW_CAP_NO_RX_SELF_COUPLING = 8,
F54_FULL_RAW_CAP_NO_RX_COUPLING = 20,
-#endif
F54_SENSOR_SPEED = 22,
F54_ADC_RANGE = 23,
F54_TRX_OPENS = 24,
@@ -571,7 +595,7 @@ struct f54_query_30 {
unsigned char has_ctrl121:1;
unsigned char has_ctrl122_query31:1;
unsigned char has_ctrl123:1;
- unsigned char f54_query30_b6:1;
+ unsigned char has_ctrl124:1;
unsigned char has_query32:1;
} __packed;
unsigned char data[1];
@@ -597,10 +621,10 @@ struct f54_query_32 {
struct f54_query_33 {
union {
struct {
- unsigned char f54_query33_b0:1;
- unsigned char f54_query33_b1:1;
- unsigned char f54_query33_b2:1;
- unsigned char f54_query33_b3:1;
+ unsigned char has_ctrl128:1;
+ unsigned char has_ctrl129:1;
+ unsigned char has_ctrl130:1;
+ unsigned char has_ctrl131:1;
unsigned char has_ctrl132:1;
unsigned char has_ctrl133:1;
unsigned char has_ctrl134:1;
@@ -614,8 +638,8 @@ struct f54_query_35 {
union {
struct {
unsigned char has_data25:1;
- unsigned char f54_query35_b1:1;
- unsigned char f54_query35_b2:1;
+ unsigned char has_ctrl135:1;
+ unsigned char has_ctrl136:1;
unsigned char has_ctrl137:1;
unsigned char has_ctrl138:1;
unsigned char has_ctrl139:1;
@@ -629,7 +653,7 @@ struct f54_query_35 {
struct f54_query_36 {
union {
struct {
- unsigned char f54_query36_b0:1;
+ unsigned char has_ctrl141:1;
unsigned char has_ctrl142:1;
unsigned char has_query37:1;
unsigned char has_ctrl143:1;
@@ -648,7 +672,10 @@ struct f54_query_38 {
unsigned char has_ctrl147:1;
unsigned char has_ctrl148:1;
unsigned char has_ctrl149:1;
- unsigned char f54_query38_b3__6:4;
+ unsigned char has_ctrl150:1;
+ unsigned char has_ctrl151:1;
+ unsigned char has_ctrl152:1;
+ unsigned char has_ctrl153:1;
unsigned char has_query39:1;
} __packed;
unsigned char data[1];
@@ -658,7 +685,12 @@ struct f54_query_38 {
struct f54_query_39 {
union {
struct {
- unsigned char f54_query39_b0__6:7;
+ unsigned char has_ctrl154:1;
+ unsigned char has_ctrl155:1;
+ unsigned char has_ctrl156:1;
+ unsigned char has_ctrl160:1;
+ unsigned char has_ctrl157_ctrl158:1;
+ unsigned char f54_query39_b5__6:2;
unsigned char has_query40:1;
} __packed;
unsigned char data[1];
@@ -668,13 +700,13 @@ struct f54_query_39 {
struct f54_query_40 {
union {
struct {
- unsigned char f54_query40_b0:1;
+ unsigned char has_ctrl169:1;
unsigned char has_ctrl163_query41:1;
unsigned char f54_query40_b2:1;
unsigned char has_ctrl165_query42:1;
unsigned char has_ctrl166:1;
unsigned char has_ctrl167:1;
- unsigned char f54_query40_b6:1;
+ unsigned char has_ctrl168:1;
unsigned char has_query43:1;
} __packed;
unsigned char data[1];
@@ -684,7 +716,12 @@ struct f54_query_40 {
struct f54_query_43 {
union {
struct {
- unsigned char f54_query43_b0__6:7;
+ unsigned char f54_query43_b0__1:2;
+ unsigned char has_ctrl171:1;
+ unsigned char has_ctrl172_query44_query45:1;
+ unsigned char has_ctrl173:1;
+ unsigned char has_ctrl174:1;
+ unsigned char has_ctrl175:1;
unsigned char has_query46:1;
} __packed;
unsigned char data[1];
@@ -695,7 +732,7 @@ struct f54_query_46 {
union {
struct {
unsigned char has_ctrl176:1;
- unsigned char f54_query46_b1:1;
+ unsigned char has_ctrl177_ctrl178:1;
unsigned char has_ctrl179:1;
unsigned char f54_query46_b3:1;
unsigned char has_data27:1;
@@ -710,7 +747,13 @@ struct f54_query_46 {
struct f54_query_47 {
union {
struct {
- unsigned char f54_query47_b0__6:7;
+ unsigned char f54_query47_b0:1;
+ unsigned char has_ctrl182:1;
+ unsigned char has_ctrl183:1;
+ unsigned char f54_query47_b3:1;
+ unsigned char has_ctrl185:1;
+ unsigned char has_ctrl186:1;
+ unsigned char has_ctrl187:1;
unsigned char has_query49:1;
} __packed;
unsigned char data[1];
@@ -743,7 +786,11 @@ struct f54_query_50 {
struct f54_query_51 {
union {
struct {
- unsigned char f54_query51_b0__4:5;
+ unsigned char f54_query51_b0:1;
+ unsigned char has_ctrl196:1;
+ unsigned char f54_query51_b2:1;
+ unsigned char f54_query51_b3:1;
+ unsigned char f54_query51_b4:1;
unsigned char has_query53_query54_ctrl198:1;
unsigned char has_ctrl199:1;
unsigned char has_query55:1;
@@ -806,7 +853,7 @@ struct f54_query_61 {
unsigned char has_ctrl214:1;
unsigned char has_ctrl215_query62_query63:1;
unsigned char f54_query61_b2__4:3;
- unsigned char has_misc_host_ctrl:1;
+ unsigned char has_ctrl218:1;
unsigned char has_hybrid_abs_buttons:1;
unsigned char has_query64:1;
} __packed;
@@ -821,7 +868,7 @@ struct f54_query_64 {
unsigned char has_ctrl220:1;
unsigned char f54_query64_b2__3:2;
unsigned char has_ctrl219_sub1:1;
- unsigned char f54_query64_b5:1;
+ unsigned char has_ctrl103_sub3:1;
unsigned char has_ctrl224_ctrl226_ctrl227:1;
unsigned char has_query65:1;
} __packed;
@@ -1068,6 +1115,18 @@ struct f54_control_188 {
};
};
+struct f54_control_223 {
+ union {
+ struct {
+ unsigned char voltages_for_0d:8;
+ } __packed;
+ struct {
+ unsigned char data[1];
+ unsigned short address;
+ } __packed;
+ };
+};
+
struct f54_control {
struct f54_control_7 *reg_7;
struct f54_control_41 *reg_41;
@@ -1082,6 +1141,7 @@ struct f54_control {
struct f54_control_110 *reg_110;
struct f54_control_149 *reg_149;
struct f54_control_188 *reg_188;
+ struct f54_control_223 *reg_223;
};
struct synaptics_rmi4_f54_handle {
@@ -1325,6 +1385,7 @@ struct f55_control_43 {
struct synaptics_rmi4_f55_handle {
bool amp_sensor;
bool extended_amp;
+ bool extended_amp_btn;
bool has_force;
unsigned char size_of_column2mux;
unsigned char afe_mux_offset;
@@ -1372,6 +1433,7 @@ show_store_prototype(td43xx_full_raw)
show_store_prototype(td43xx_noise)
show_store_prototype(td43xx_ee_short)
show_store_prototype(td43xx_amp_open)
+show_store_prototype(abs_0d_open_w_autoservo)
/* td43xx end */
static struct attribute *attrs[] = {
@@ -1397,6 +1459,7 @@ static struct attribute *attrs[] = {
attrify(td43xx_noise),
attrify(td43xx_ee_short),
attrify(td43xx_amp_open),
+ attrify(abs_0d_open_w_autoservo),
/* td43xx end */
NULL,
};
@@ -1404,6 +1467,20 @@ static struct attribute *attrs[] = {
static struct attribute_group attr_group = {
.attrs = attrs,
};
+/*
+static ssize_t test_sysfs_data_read(struct file *data_file,
+ struct kobject *kobj, struct bin_attribute *attributes,
+ char *buf, loff_t pos, size_t count);
+
+static struct bin_attribute test_report_data = {
+ .attr = {
+ .name = "report_data",
+ .mode = S_IRUGO,
+ },
+ .size = 0,
+ .read = test_sysfs_data_read,
+};
+*/
static struct synaptics_rmi4_f54_handle *f54;
static struct synaptics_rmi4_f55_handle *f55;
@@ -1413,8 +1490,10 @@ static signed short *td43xx_noise_delta;
static unsigned char *td43xx_ee_short_data;
static unsigned char *td43xx_amp_open_data;
/* td43xx end */
+static int *g_abs_0d_open_data_output;
+static char g_flag_read_report_fail;
-DECLARE_COMPLETION(test_remove_complete);
+DECLARE_COMPLETION(test_remove_complete_force);
static bool test_report_type_valid(enum f54_report_types report_type)
{
@@ -1433,6 +1512,7 @@ static bool test_report_type_valid(enum f54_report_types report_type)
case F54_RX_TO_RX_SHORTS_2:
case F54_RX_OPENS_2:
case F54_FULL_RAW_CAP:
+ case F54_FULL_RAW_CAP_NO_RX_SELF_COUPLING:
case F54_FULL_RAW_CAP_NO_RX_COUPLING:
case F54_SENSOR_SPEED:
case F54_ADC_RANGE:
@@ -1474,6 +1554,7 @@ static void test_set_report_size(void)
case F54_RAW_16BIT_IMAGE:
case F54_TRUE_BASELINE:
case F54_FULL_RAW_CAP:
+ case F54_FULL_RAW_CAP_NO_RX_SELF_COUPLING:
case F54_FULL_RAW_CAP_NO_RX_COUPLING:
case F54_SENSOR_SPEED:
case F54_AMP_FULL_RAW_CAP:
@@ -1697,35 +1778,37 @@ static int test_do_preparation(void)
int retval;
unsigned char value;
unsigned char zero = 0x00;
-#ifndef USE_RT8
- unsigned char device_ctrl;
-#endif
struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data;
+ const struct synaptics_dsx_board_data *bdata =
+ rmi4_data->hw_if->board_data;
#ifndef USE_RT8
- retval = synaptics_rmi4_reg_read(rmi4_data,
- rmi4_data->f01_ctrl_base_addr,
- &device_ctrl,
- sizeof(device_ctrl));
- if (retval < 0) {
- dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to set no sleep\n",
- __func__);
- return retval;
- }
+ unsigned char device_ctrl;
- device_ctrl |= NO_SLEEP_ON;
+ if (!bdata->captouch_use) {
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ rmi4_data->f01_ctrl_base_addr,
+ &device_ctrl,
+ sizeof(device_ctrl));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to set no sleep\n",
+ __func__);
+ return retval;
+ }
- retval = synaptics_rmi4_reg_write(rmi4_data,
- rmi4_data->f01_ctrl_base_addr,
- &device_ctrl,
- sizeof(device_ctrl));
- if (retval < 0) {
- dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to set no sleep\n",
- __func__);
- return retval;
- }
+ device_ctrl |= NO_SLEEP_ON;
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ rmi4_data->f01_ctrl_base_addr,
+ &device_ctrl,
+ sizeof(device_ctrl));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to set no sleep\n",
+ __func__);
+ return retval;
+ }
+ }
#endif
if (f54->skip_preparation)
return 0;
@@ -1739,6 +1822,7 @@ static int test_do_preparation(void)
case F54_ABS_DELTA_CAP:
case F54_ABS_HYBRID_DELTA_CAP:
case F54_ABS_HYBRID_RAW_CAP:
+ case F54_FULL_RAW_CAP_NO_RX_SELF_COUPLING:
#ifdef USE_RT8
case F54_FULL_RAW_CAP_NO_RX_COUPLING:
#endif
@@ -2014,30 +2098,36 @@ static int test_do_resume_touch(void)
{
int retval = 0;
struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data;
+ const struct synaptics_dsx_board_data *bdata =
+ rmi4_data->hw_if->board_data;
#ifndef USE_RT8
- retval = synaptics_rmi4_reg_read(rmi4_data,
- rmi4_data->f01_ctrl_base_addr,
- &device_ctrl,
- sizeof(device_ctrl));
- if (retval < 0) {
- dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to restore no sleep setting\n",
- __func__);
- return retval;
- }
+ unsigned char device_ctrl;
- device_ctrl = device_ctrl & ~NO_SLEEP_ON;
- device_ctrl |= rmi4_data->no_sleep_setting;
+ if (!bdata->captouch_use) {
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ rmi4_data->f01_ctrl_base_addr,
+ &device_ctrl,
+ sizeof(device_ctrl));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to restore no sleep setting\n",
+ __func__);
+ return retval;
+ }
- retval = synaptics_rmi4_reg_write(rmi4_data,
- rmi4_data->f01_ctrl_base_addr,
- &device_ctrl,
- sizeof(device_ctrl));
- if (retval < 0) {
- dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to restore no sleep setting\n",
- __func__);
- return retval;
+ device_ctrl = device_ctrl & ~NO_SLEEP_ON;
+ device_ctrl |= rmi4_data->no_sleep_setting;
+
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ rmi4_data->f01_ctrl_base_addr,
+ &device_ctrl,
+ sizeof(device_ctrl));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to restore no sleep setting\n",
+ __func__);
+ return retval;
+ }
}
#endif
test_set_interrupt(false);
@@ -2054,6 +2144,7 @@ static int test_do_resume_touch(void)
case F54_ABS_DELTA_CAP:
case F54_ABS_HYBRID_DELTA_CAP:
case F54_ABS_HYBRID_RAW_CAP:
+ case F54_FULL_RAW_CAP_NO_RX_SELF_COUPLING:
#ifdef USE_RT8
case F54_FULL_RAW_CAP_NO_RX_COUPLING:
#endif
@@ -2376,6 +2467,11 @@ static ssize_t test_sysfs_get_report_store(struct device *dev,
f54->status = STATUS_BUSY;
f54->report_size = 0;
f54->data_pos = 0;
+/*
+ hrtimer_start(&f54->watchdog,
+ ktime_set(GET_REPORT_TIMEOUT_S, 0),
+ HRTIMER_MODE_REL);
+*/
retval = count;
exit:
@@ -2450,7 +2546,11 @@ static ssize_t test_sysfs_report_type_store(struct device *dev,
unsigned char data;
unsigned long setting;
struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data;
+ const struct synaptics_dsx_board_data *bdata =
+ rmi4_data->hw_if->board_data;
+#ifdef USE_RT8
static bool do_once;
+#endif
retval = sstrtoul(buf, 10, &setting);
if (retval)
@@ -2462,9 +2562,11 @@ static ssize_t test_sysfs_report_type_store(struct device *dev,
if (retval < 0)
goto exit;
+ if (bdata->captouch_use && setting == F54_FULL_RAW_CAP_NO_RX_COUPLING)
+ setting = F54_FULL_RAW_CAP_NO_RX_SELF_COUPLING;
#ifdef USE_RT8
- if (setting == 20)
- setting = 8;
+ if (setting == F54_FULL_RAW_CAP_NO_RX_COUPLING)
+ setting = F54_FULL_RAW_CAP_NO_RX_SELF_COUPLING;
#endif
if (!test_report_type_valid((enum f54_report_types)setting)) {
@@ -2475,6 +2577,8 @@ static ssize_t test_sysfs_report_type_store(struct device *dev,
goto exit;
}
+ if (bdata->captouch_use && setting == 20)
+ setting = 8;
#ifdef USE_RT8
if ((f54->report_type == F54_FULL_RAW_CAP_NO_RX_COUPLING) && do_once) {
rmi4_data->reset_device(rmi4_data, false);
@@ -2675,6 +2779,7 @@ static ssize_t test_sysfs_read_report_show(struct device *dev,
case F54_RAW_16BIT_IMAGE:
case F54_TRUE_BASELINE:
case F54_FULL_RAW_CAP:
+ case F54_FULL_RAW_CAP_NO_RX_SELF_COUPLING:
case F54_FULL_RAW_CAP_NO_RX_COUPLING:
case F54_SENSOR_SPEED:
case F54_AMP_FULL_RAW_CAP:
@@ -2939,7 +3044,8 @@ static ssize_t test_sysfs_read_report_store(struct device *dev,
pr_err("%s: done test_wait_for_command_completion\n", __func__);
- if (rmi4_data->chip_id == CHIP_ID_4322)
+ if (rmi4_data->chip_id == rmi4_data->hw_if->board_data->chip_4322 ||
+ rmi4_data->chip_id == rmi4_data->hw_if->board_data->chip_4722)
queue_work(f54->test_report_workqueue, &f54->test_report_work);
timeout_count = 0;
@@ -3813,6 +3919,268 @@ static ssize_t test_sysfs_td43xx_amp_open_show(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%s\n", (result == 1) ? "PASS" : "FAIL");
}
+
+
+static ssize_t test_sysfs_abs_0d_open_w_autoservo_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int retval = 0;
+ int i, j, k;
+ int tx_num = f54->tx_assigned;
+ int rx_num = f54->rx_assigned;
+ struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data;
+ struct f54_control control = f54->control;
+ unsigned long setting;
+
+ unsigned char original_data_f54_ctr223 = 0x00;
+ unsigned char data = 0x00;
+
+ signed char *p_report_data_8 = NULL;
+ signed short *p_rt92_image_1 = NULL;
+ signed short *p_rt92_image_2 = NULL;
+
+ unsigned char button_count = rmi4_data->valid_button_count;
+
+ button_count = BUTTON_COUNT;
+
+ retval = sstrtoul(buf, 10, &setting);
+ if (retval)
+ return retval;
+
+ if (setting != 1)
+ return -EINVAL;
+
+ if (button_count == 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to get rmi button (count = %d)\n",
+ __func__, rmi4_data->valid_button_count);
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ /* allocate the g_tddi_amp_open_data_output */
+ if (g_abs_0d_open_data_output)
+ kfree(g_abs_0d_open_data_output);
+ g_abs_0d_open_data_output = kzalloc(button_count * sizeof(int), GFP_KERNEL);
+ if (!g_abs_0d_open_data_output) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to alloc mem for g_abs_0d_open_data_output\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ g_flag_read_report_fail = 0;
+
+ /* allocate the buffer */
+ p_report_data_8 = kzalloc(tx_num * rx_num * 2, GFP_KERNEL);
+ if (!p_report_data_8) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to alloc mem for p_report_data_8\n",
+ __func__);
+ retval = -ENOMEM;
+ goto exit;
+ }
+
+ p_rt92_image_1 = kzalloc(tx_num * rx_num * sizeof(signed short), GFP_KERNEL);
+ if (!p_rt92_image_1) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to alloc mem for p_rt92_image_1\n",
+ __func__);
+ retval = -ENOMEM;
+ goto exit;
+ }
+
+ p_rt92_image_2 = kzalloc(tx_num * rx_num * sizeof(signed short), GFP_KERNEL);
+ if (!p_rt92_image_2) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to alloc mem for p_rt92_image_2\n",
+ __func__);
+ retval = -ENOMEM;
+ goto exit;
+ }
+
+ /* step 1 */
+ /* get first rt92 image */
+ retval = test_sysfs_read_report_td43xx(dev, attr, "92", count,
+ false, false);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read report 92 in step 1\n",
+ __func__);
+ g_flag_read_report_fail = 1; /* special code to indicate the failure of report reading */
+ retval = -EIO;
+ goto exit;
+ }
+
+ secure_memcpy(p_report_data_8, tx_num * rx_num * 2,
+ f54->report_data, f54->report_size, f54->report_size);
+
+ /* normalize the rt92 image with 16-bit */
+ k = 0;
+ for (i = 0; i < tx_num; i++) {
+ for (j = 0; j < rx_num; j++) {
+ p_rt92_image_1[i * rx_num + j] =
+ (signed short)(p_report_data_8[k] & 0xff) | (signed short)(p_report_data_8[k + 1] << 8);
+
+ k += 2;
+ }
+ }
+
+ memset(p_report_data_8, 0x00, tx_num * rx_num * 2);
+
+ /* step 2 */
+ /* read original 0d voltages */
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ control.reg_223->address,
+ &original_data_f54_ctr223,
+ sizeof(original_data_f54_ctr223));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read original 0d_voltaes in step 2\n",
+ __func__);
+ retval = -EIO;
+ goto exit;
+ }
+
+ /* step 3 */
+ /* modify 0d voltages and force update */
+ data = original_data_f54_ctr223 - ABS_0D_OPEN_FACTOR;
+ if (data < 0)
+ data = 0;
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ control.reg_223->address,
+ &data,
+ sizeof(data));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to modify 0d voltages to f54_ctrl_223 in step 3\n",
+ __func__);
+ retval = -EIO;
+ goto exit;
+ }
+ retval = test_do_command(COMMAND_FORCE_UPDATE);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to do force update in step 3\n",
+ __func__);
+ retval = -EIO;
+ goto exit;
+ }
+ msleep(100);
+
+ /* step 4 */
+ /* get second rt92 image */
+ retval = test_sysfs_read_report_td43xx(dev, attr, "92", count,
+ false, false);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read report 92 in step 4\n",
+ __func__);
+ g_flag_read_report_fail = 1; /* special code to indicate the failure of report reading */
+ retval = -EIO;
+ goto exit;
+ }
+
+ secure_memcpy(p_report_data_8, tx_num * rx_num * 2,
+ f54->report_data, f54->report_size, f54->report_size);
+
+ /* normalize the rt92 image with 16-bit */
+ k = 0;
+ for (i = 0; i < tx_num; i++) {
+ for (j = 0; j < rx_num; j++) {
+ p_rt92_image_2[i * rx_num + j] =
+ (signed short)(p_report_data_8[k] & 0xff) | (signed short)(p_report_data_8[k + 1] << 8);
+
+ k += 2;
+ }
+ }
+
+ /* step 5 */
+ /* restore original 0d voltages and force update */
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ control.reg_223->address,
+ &original_data_f54_ctr223,
+ sizeof(original_data_f54_ctr223));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to restore 0d voltages to f54_ctrl_223 in step 5\n",
+ __func__);
+ retval = -EIO;
+ goto exit;
+ }
+ retval = test_do_command(COMMAND_FORCE_UPDATE);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to do force update in step 5\n",
+ __func__);
+ retval = -EIO;
+ goto exit;
+ }
+
+ /* step 6 */
+ /* calculation */
+ for (i = 0; i < button_count; i++) {
+ g_abs_0d_open_data_output[i] = abs(p_rt92_image_1[(tx_num-1)*rx_num + i] - p_rt92_image_2[(tx_num-1)*rx_num + i]);
+ g_abs_0d_open_data_output[i] = (g_abs_0d_open_data_output[i] * 100)/p_rt92_image_1[(tx_num-1)*rx_num + i];
+ printk(KERN_ERR "ref value is %d value1 is %d value2 is %d\n", g_abs_0d_open_data_output[i], p_rt92_image_1[(tx_num-1)*rx_num + i], p_rt92_image_2[(tx_num-1)*rx_num + i]);
+ if (g_abs_0d_open_data_output[i] < ABS_0D_OPEN_TEST_LIMIT)
+ g_abs_0d_open_data_output[i] = 1; /* fail */
+ else
+ g_abs_0d_open_data_output[i] = 0; /* pass */
+ }
+
+exit:
+ /* release resource */
+ kfree(p_rt92_image_1);
+ kfree(p_rt92_image_2);
+ kfree(p_report_data_8);
+
+ pr_err("%s: resetting device\n", __func__);
+ rmi4_data->reset_device(rmi4_data, false);
+ pr_err("%s: done resetting device\n", __func__);
+
+ return count;
+}
+
+
+static ssize_t test_sysfs_abs_0d_open_w_autoservo_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ bool result = 0;
+ struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data;
+ unsigned char button_count = rmi4_data->valid_button_count;
+ int i;
+
+ if (!g_abs_0d_open_data_output)
+ return -EINVAL;
+
+ /* check the special code if the failure of report image reading */
+ if (1 == g_flag_read_report_fail) {
+ kfree(g_abs_0d_open_data_output);
+ g_abs_0d_open_data_output = NULL;
+ return snprintf(buf, PAGE_SIZE, "ERROR: Fail to read RT92 image\n");
+ }
+
+ button_count = BUTTON_COUNT;
+
+ for (i = 0; i < button_count; i++) {
+ if (g_abs_0d_open_data_output[i] != 0) {
+
+ result = 0; /* 0: fail */
+ break;
+ /*dev_err(f54->rmi4_data->pdev->dev.parent,
+ "%s: Failed at 0D_button_%d\n", __func__, i); */
+ }
+ }
+
+ if (i == button_count)
+ result = 1;
+
+ kfree(g_abs_0d_open_data_output);
+ g_abs_0d_open_data_output = NULL;
+ return snprintf(buf, PAGE_SIZE, "%s\n", (result == 1) ? "PASS" : "FAIL");
+}
+
static void test_report_work(struct work_struct *work)
{
int retval;
@@ -4509,7 +4877,9 @@ static int test_set_controls(void)
if (f54->query_30.has_ctrl123)
reg_addr += CONTROL_123_SIZE;
- /* control 124 reserved */
+ /* control 124 */
+ if (f54->query_30.has_ctrl124)
+ reg_addr += CONTROL_124_SIZE;
/* control 125 */
if (f54->query_32.has_ctrl125)
@@ -4523,7 +4893,21 @@ static int test_set_controls(void)
if (f54->query_32.has_ctrl127)
reg_addr += CONTROL_127_SIZE;
- /* controls 128 129 130 131 reserved */
+ /* control 128 */
+ if (f54->query_33.has_ctrl128)
+ reg_addr += CONTROL_128_SIZE;
+
+ /* control 129 */
+ if (f54->query_33.has_ctrl129)
+ reg_addr += CONTROL_129_SIZE;
+
+ /* control 130 */
+ if (f54->query_33.has_ctrl130)
+ reg_addr += CONTROL_130_SIZE;
+
+ /* control 131 */
+ if (f54->query_33.has_ctrl131)
+ reg_addr += CONTROL_131_SIZE;
/* control 132 */
if (f54->query_33.has_ctrl132)
@@ -4537,7 +4921,13 @@ static int test_set_controls(void)
if (f54->query_33.has_ctrl134)
reg_addr += CONTROL_134_SIZE;
- /* controls 135 136 reserved */
+ /* control 135 */
+ if (f54->query_35.has_ctrl135)
+ reg_addr += CONTROL_135_SIZE;
+
+ /* control 136 */
+ if (f54->query_35.has_ctrl136)
+ reg_addr += CONTROL_136_SIZE;
/* control 137 */
if (f54->query_35.has_ctrl137)
@@ -4555,7 +4945,9 @@ static int test_set_controls(void)
if (f54->query_35.has_ctrl140)
reg_addr += CONTROL_140_SIZE;
- /* control 141 reserved */
+ /* control 141 */
+ if (f54->query_36.has_ctrl141)
+ reg_addr += CONTROL_141_SIZE;
/* control 142 */
if (f54->query_36.has_ctrl142)
@@ -4595,7 +4987,39 @@ static int test_set_controls(void)
reg_addr += CONTROL_149_SIZE;
}
- /* controls 150 to 162 reserved */
+ /* control 150 */
+ if (f54->query_38.has_ctrl150)
+ reg_addr += CONTROL_150_SIZE;
+
+ /* control 151 */
+ if (f54->query_38.has_ctrl151)
+ reg_addr += CONTROL_151_SIZE;
+
+ /* control 152 */
+ if (f54->query_38.has_ctrl152)
+ reg_addr += CONTROL_152_SIZE;
+
+ /* control 153 */
+ if (f54->query_38.has_ctrl153)
+ reg_addr += CONTROL_153_SIZE;
+
+ /* control 154 */
+ if (f54->query_39.has_ctrl154)
+ reg_addr += CONTROL_154_SIZE;
+
+ /* control 155 */
+ if (f54->query_39.has_ctrl155)
+ reg_addr += CONTROL_155_SIZE;
+
+ /* control 156 */
+ if (f54->query_39.has_ctrl156)
+ reg_addr += CONTROL_156_SIZE;
+
+ /* controls 157 158 */
+ if (f54->query_39.has_ctrl157_ctrl158)
+ reg_addr += CONTROL_157_158_SIZE;
+
+ /* controls 159 to 162 reserved */
/* control 163 */
if (f54->query_40.has_ctrl163_query41)
@@ -4615,19 +5039,71 @@ static int test_set_controls(void)
if (f54->query_40.has_ctrl167)
reg_addr += CONTROL_167_SIZE;
- /* controls 168 to 175 reserved */
+ /* control 168 */
+ if (f54->query_40.has_ctrl168)
+ reg_addr += CONTROL_168_SIZE;
+
+ /* control 169 */
+ if (f54->query_40.has_ctrl169)
+ reg_addr += CONTROL_169_SIZE;
+
+ /* control 170 reserved */
+
+ /* control 171 */
+ if (f54->query_43.has_ctrl171)
+ reg_addr += CONTROL_171_SIZE;
+
+ /* control 172 */
+ if (f54->query_43.has_ctrl172_query44_query45)
+ reg_addr += CONTROL_172_SIZE;
+
+ /* control 173 */
+ if (f54->query_43.has_ctrl173)
+ reg_addr += CONTROL_173_SIZE;
+
+ /* control 174 */
+ if (f54->query_43.has_ctrl174)
+ reg_addr += CONTROL_174_SIZE;
+
+ /* control 175 */
+ if (f54->query_43.has_ctrl175)
+ reg_addr += CONTROL_175_SIZE;
/* control 176 */
if (f54->query_46.has_ctrl176)
reg_addr += CONTROL_176_SIZE;
- /* controls 177 178 reserved */
+ /* controls 177 178 */
+ if (f54->query_46.has_ctrl177_ctrl178)
+ reg_addr += CONTROL_177_178_SIZE;
/* control 179 */
if (f54->query_46.has_ctrl179)
reg_addr += CONTROL_179_SIZE;
- /* controls 180 to 187 reserved */
+ /* controls 180 to 181 reserved */
+
+ /* control 182 */
+ if (f54->query_47.has_ctrl182)
+ reg_addr += CONTROL_182_SIZE;
+
+ /* control 183 */
+ if (f54->query_47.has_ctrl183)
+ reg_addr += CONTROL_183_SIZE;
+
+ /* control 184 reserved */
+
+ /* control 185 */
+ if (f54->query_47.has_ctrl185)
+ reg_addr += CONTROL_185_SIZE;
+
+ /* control 186 */
+ if (f54->query_47.has_ctrl186)
+ reg_addr += CONTROL_186_SIZE;
+
+ /* control 187 */
+ if (f54->query_47.has_ctrl187)
+ reg_addr += CONTROL_187_SIZE;
/* control 188 */
if (f54->query_49.has_ctrl188) {
@@ -4639,6 +5115,30 @@ static int test_set_controls(void)
reg_addr += CONTROL_188_SIZE;
}
+ /* control 189 - 195 reserved */
+
+ /* control 196 */
+ if (f54->query_51.has_ctrl196)
+ reg_addr += CONTROL_196_SIZE;
+
+ /* control 197 - 217 reserved */
+
+ /* control 218 reserved */
+ if (f54->query_61.has_ctrl218)
+ reg_addr += CONTROL_218_SIZE;
+
+ /* control 219 - 222 reserved */
+
+ /* control 223 reserved */
+ if (f54->query_64.has_ctrl103_sub3) {
+ control->reg_223 = kzalloc(sizeof(*(control->reg_223)),
+ GFP_KERNEL);
+ if (!control->reg_223)
+ goto exit_no_mem;
+ control->reg_223->address = reg_addr;
+ reg_addr += CONTROL_223_SIZE;
+ }
+
return 0;
exit_no_mem:
@@ -4917,7 +5417,8 @@ static int test_set_queries(void)
offset += 1;
}
- /* queries 44 45 reserved */
+ if (f54->query_43.has_ctrl172_query44_query45)
+ offset += 2;
/* query 46 */
if (f54->query_43.has_query46) {
@@ -5459,6 +5960,7 @@ static int test_f55_set_queries(void)
offset += 1;
f55->extended_amp = f55->query_33.has_extended_amp_pad;
+ f55->extended_amp_btn = f55->query_33.has_extended_amp_btn;
}
return 0;
@@ -5900,12 +6402,12 @@ static ssize_t syna_selftest_write(struct file *file, const char __user *buf, si
}
if (!strncmp(buf, "short", 5)) {
- if (f54->rmi4_data->chip_id == CHIP_ID_3330)
+ if (f54->rmi4_data->chip_id == f54->rmi4_data->hw_if->board_data->chip_3330 || f54->rmi4_data->chip_id == f54->rmi4_data->hw_if->board_data->chip_3331)
retval = short_test_333x();
else
retval = short_test_4x22();
} else if (!strncmp(buf, "open", 4)) {
- if (f54->rmi4_data->chip_id == CHIP_ID_3330)
+ if (f54->rmi4_data->chip_id == f54->rmi4_data->hw_if->board_data->chip_3330 || f54->rmi4_data->chip_id == f54->rmi4_data->hw_if->board_data->chip_3331)
retval = open_test_333x();
else
retval = open_test_4x22();
@@ -5931,6 +6433,71 @@ static const struct file_operations syna_selftest_ops = {
.release = syna_selftest_release,
};
+static int syna_datadump_open(struct inode *inode, struct file *file)
+{
+ f54->data = vmalloc(PAGE_SIZE);
+
+ return 0;
+}
+
+static ssize_t syna_datadump_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
+{
+ int retval;
+ int cnt;
+
+ if (*pos != 0)
+ return 0;
+
+ retval = test_sysfs_read_report_store(NULL, NULL, TEST_TYPE_02, strlen(TEST_TYPE_02));
+ if (retval < 0) {
+ snprintf(buf, PAGE_SIZE, "data test error: start\n");
+ goto out;
+ }
+
+ retval = test_sysfs_read_report_show(NULL, NULL, f54->data);
+ if (retval < 0) {
+ snprintf(buf, PAGE_SIZE, "data test error: read\n");
+ goto out;
+ }
+
+ cnt = snprintf(buf, PAGE_SIZE, "data:\n%s\n", f54->data);
+
+ memset(f54->data, 0, PAGE_SIZE);
+
+ retval = test_sysfs_read_report_store(NULL, NULL, TEST_TYPE_03, strlen(TEST_TYPE_03));
+ if (retval < 0) {
+ snprintf(buf, PAGE_SIZE, "data test error: start\n");
+ goto out;
+ }
+
+ retval = test_sysfs_read_report_show(NULL, NULL, f54->data);
+ if (retval < 0) {
+ snprintf(buf, PAGE_SIZE, "data test error: read\n");
+ goto out;
+ }
+
+ snprintf(buf + cnt, PAGE_SIZE, "raw data:\n%s\n", f54->data);
+
+out:
+
+ *pos += strlen(buf);
+
+ return strlen(buf);
+}
+
+static int syna_datadump_release(struct inode *inode, struct file *file)
+{
+ vfree(f54->data);
+
+ return 0;
+}
+
+static const struct file_operations syna_datadump_ops = {
+ .open = syna_datadump_open,
+ .read = syna_datadump_read,
+ .release = syna_datadump_release,
+};
+
static int synaptics_rmi4_test_init(struct synaptics_rmi4_data *rmi4_data)
{
int retval;
@@ -5986,6 +6553,9 @@ static int synaptics_rmi4_test_init(struct synaptics_rmi4_data *rmi4_data)
if (f55)
test_f55_init(rmi4_data);
+ if (rmi4_data->external_afe_buttons)
+ f54->tx_assigned++;
+
retval = test_set_sysfs();
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
@@ -6010,6 +6580,7 @@ static int synaptics_rmi4_test_init(struct synaptics_rmi4_data *rmi4_data)
if (!proc_already) {
proc_already = true;
proc_create("tp_selftest", 0, NULL, &syna_selftest_ops);
+ proc_create("tp_data_dump", 0, NULL, &syna_datadump_ops);
}
return 0;
@@ -6069,7 +6640,7 @@ static void synaptics_rmi4_test_remove(struct synaptics_rmi4_data *rmi4_data)
f54 = NULL;
exit:
- complete(&test_remove_complete);
+ complete(&test_remove_complete_force);
return;
}
@@ -6123,6 +6694,9 @@ static void synaptics_rmi4_test_reset(struct synaptics_rmi4_data *rmi4_data)
if (f55)
test_f55_init(rmi4_data);
+ if (rmi4_data->external_afe_buttons)
+ f54->tx_assigned++;
+
f54->status = STATUS_IDLE;
return;
@@ -6166,16 +6740,16 @@ static struct synaptics_rmi4_exp_fn test_module = {
static int __init rmi4_test_module_init(void)
{
- synaptics_rmi4_new_function(&test_module, true);
+ synaptics_rmi4_new_function_force(&test_module, true);
return 0;
}
static void __exit rmi4_test_module_exit(void)
{
- synaptics_rmi4_new_function(&test_module, false);
+ synaptics_rmi4_new_function_force(&test_module, false);
- wait_for_completion(&test_remove_complete);
+ wait_for_completion(&test_remove_complete_force);
return;
}
diff --git a/synaptics_dsx_video.c b/synaptics_dsx_video.c
index 1539e61..b52b4be 100644
--- a/synaptics_dsx_video.c
+++ b/synaptics_dsx_video.c
@@ -43,6 +43,10 @@
#define SYSFS_FOLDER_NAME "video"
+/*
+#define RMI_DCS_SUSPEND_RESUME
+*/
+
static ssize_t video_sysfs_dcs_write_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count);
@@ -391,14 +395,14 @@ static struct synaptics_rmi4_exp_fn video_module = {
static int __init rmi4_video_module_init(void)
{
- synaptics_rmi4_new_function(&video_module, true);
+ synaptics_rmi4_new_function_force(&video_module, true);
return 0;
}
static void __exit rmi4_video_module_exit(void)
{
- synaptics_rmi4_new_function(&video_module, false);
+ synaptics_rmi4_new_function_force(&video_module, false);
wait_for_completion(&video_remove_complete);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment