huangcm
2025-02-26 a813214788f6e7b512df54f1c659cd0bdc9ac175
feat(mipi): add 5' mipi & touchscreen config

1. add 5' mipi config
2. add FT8756M touchscreen config
8 files modified
21 files added
11426 ■■■■■ changed files
longan/brandy/brandy-2.0/u-boot-2018/drivers/video/sunxi/disp2/disp/Makefile 1 ●●●● patch | view | raw | blame | history
longan/brandy/brandy-2.0/u-boot-2018/drivers/video/sunxi/disp2/disp/lcd/mipi_5_720x1280.c 374 ●●●●● patch | view | raw | blame | history
longan/brandy/brandy-2.0/u-boot-2018/drivers/video/sunxi/disp2/disp/lcd/mipi_5_720x1280.h 20 ●●●●● patch | view | raw | blame | history
longan/brandy/brandy-2.0/u-boot-2018/drivers/video/sunxi/disp2/disp/lcd/panels.c 2 ●●● patch | view | raw | blame | history
longan/brandy/brandy-2.0/u-boot-2018/drivers/video/sunxi/disp2/disp/lcd/panels.h 1 ●●●● patch | view | raw | blame | history
longan/device/config/chips/a133/configs/c3/kickpi-k5c.dts 19 ●●●● patch | view | raw | blame | history
longan/kernel/linux-4.9/arch/arm64/boot/dts/sunxi/lcd-mipi-5-720-1280.dtsi 260 ●●●●● patch | view | raw | blame | history
longan/kernel/linux-4.9/drivers/input/touchscreen/Makefile 1 ●●●● patch | view | raw | blame | history
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/Kconfig 10 ●●●●● patch | view | raw | blame | history
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/Makefile 14 ●●●●● patch | view | raw | blame | history
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_common.h 193 ●●●●● patch | view | raw | blame | history
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_config.h 362 ●●●●● patch | view | raw | blame | history
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_core.c 2411 ●●●●● patch | view | raw | blame | history
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_core.h 426 ●●●●● patch | view | raw | blame | history
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_esdcheck.c 442 ●●●●● patch | view | raw | blame | history
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_ex_fun.c 1269 ●●●●● patch | view | raw | blame | history
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_ex_mode.c 390 ●●●●● patch | view | raw | blame | history
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_flash.c 2273 ●●●●● patch | view | raw | blame | history
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_flash.h 235 ●●●●● patch | view | raw | blame | history
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_flash/focaltech_upgrade_ft8756m.c 446 ●●●●● patch | view | raw | blame | history
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_gesture.c 511 ●●●●● patch | view | raw | blame | history
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_i2c.c 335 ●●●●● patch | view | raw | blame | history
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_point_report_check.c 185 ●●●●● patch | view | raw | blame | history
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_proximity.c 827 ●●●●● patch | view | raw | blame | history
longan/kernel/linux-4.9/drivers/video/fbdev/sunxi/disp2/disp/Makefile 2 ●●●●● patch | view | raw | blame | history
longan/kernel/linux-4.9/drivers/video/fbdev/sunxi/disp2/disp/lcd/mipi_5_720x1280.c 392 ●●●●● patch | view | raw | blame | history
longan/kernel/linux-4.9/drivers/video/fbdev/sunxi/disp2/disp/lcd/mipi_5_720x1280.h 23 ●●●●● patch | view | raw | blame | history
longan/kernel/linux-4.9/drivers/video/fbdev/sunxi/disp2/disp/lcd/panels.c 1 ●●●● patch | view | raw | blame | history
longan/kernel/linux-4.9/drivers/video/fbdev/sunxi/disp2/disp/lcd/panels.h 1 ●●●● patch | view | raw | blame | history
longan/brandy/brandy-2.0/u-boot-2018/drivers/video/sunxi/disp2/disp/Makefile
....@@ -53,6 +53,7 @@
5353 disp-$(CONFIG_LCD_SUPPORT_K101_IM2BYL02_L_800X1280) += lcd/K101_IM2BYL02_L_800X1280.o
5454 disp-y += lcd/mipi_8_800x1280.o
5555 disp-y += lcd/mipi_10_800x1280.o
56
+disp-y += lcd/mipi_5_720x1280.o
5657
5758 ifeq ($(CONFIG_MACH_SUN8IW6),y)
5859 export MIPI_DSI_IP_VERSION := 28
longan/brandy/brandy-2.0/u-boot-2018/drivers/video/sunxi/disp2/disp/lcd/mipi_5_720x1280.c
....@@ -0,0 +1,374 @@
1
+#include "mipi_5_720x1280.h"
2
+
3
+static void lcd_power_on(u32 sel);
4
+static void lcd_power_off(u32 sel);
5
+static void lcd_bl_open(u32 sel);
6
+static void lcd_bl_close(u32 sel);
7
+
8
+static void lcd_panel_init1(u32 sel);
9
+static void lcd_panel_exit(u32 sel);
10
+
11
+#define panel_reset(sel, val) sunxi_lcd_gpio_set_value(sel, 0, val)
12
+
13
+static void lcd_cfg_panel_info(panel_extend_para *info)
14
+{
15
+ u32 i = 0, j = 0;
16
+ u32 items;
17
+ u8 lcd_gamma_tbl[][2] = {
18
+ {0, 0},
19
+ {15, 15},
20
+ {30, 30},
21
+ {45, 45},
22
+ {60, 60},
23
+ {75, 75},
24
+ {90, 90},
25
+ {105, 105},
26
+ {120, 120},
27
+ {135, 135},
28
+ {150, 150},
29
+ {165, 165},
30
+ {180, 180},
31
+ {195, 195},
32
+ {210, 210},
33
+ {225, 225},
34
+ {240, 240},
35
+ {255, 255},
36
+ };
37
+
38
+ u32 lcd_cmap_tbl[2][3][4] = {
39
+ {
40
+ {LCD_CMAP_G0, LCD_CMAP_B1, LCD_CMAP_G2, LCD_CMAP_B3},
41
+ {LCD_CMAP_B0, LCD_CMAP_R1, LCD_CMAP_B2, LCD_CMAP_R3},
42
+ {LCD_CMAP_R0, LCD_CMAP_G1, LCD_CMAP_R2, LCD_CMAP_G3},
43
+ },
44
+ {
45
+ {LCD_CMAP_B3, LCD_CMAP_G2, LCD_CMAP_B1, LCD_CMAP_G0},
46
+ {LCD_CMAP_R3, LCD_CMAP_B2, LCD_CMAP_R1, LCD_CMAP_B0},
47
+ {LCD_CMAP_G3, LCD_CMAP_R2, LCD_CMAP_G1, LCD_CMAP_R0},
48
+ },
49
+ };
50
+
51
+ items = sizeof(lcd_gamma_tbl) / 2;
52
+ for (i = 0; i < items - 1; i++) {
53
+ u32 num = lcd_gamma_tbl[i+1][0] - lcd_gamma_tbl[i][0];
54
+
55
+ for (j = 0; j < num; j++) {
56
+ u32 value = 0;
57
+
58
+ value = lcd_gamma_tbl[i][1] +
59
+ ((lcd_gamma_tbl[i+1][1] - lcd_gamma_tbl[i][1])
60
+ * j) / num;
61
+ info->lcd_gamma_tbl[lcd_gamma_tbl[i][0] + j] =
62
+ (value<<16)
63
+ + (value<<8) + value;
64
+ }
65
+ }
66
+ info->lcd_gamma_tbl[255] = (lcd_gamma_tbl[items-1][1]<<16) +
67
+ (lcd_gamma_tbl[items-1][1]<<8)
68
+ + lcd_gamma_tbl[items-1][1];
69
+
70
+ memcpy(info->lcd_cmap_tbl, lcd_cmap_tbl, sizeof(lcd_cmap_tbl));
71
+
72
+}
73
+
74
+static s32 lcd_open_flow(u32 sel)
75
+{
76
+ LCD_OPEN_FUNC(sel, lcd_power_on, 50);
77
+ LCD_OPEN_FUNC(sel, lcd_panel_init1, 20);
78
+ LCD_OPEN_FUNC(sel, sunxi_lcd_tcon_enable, 20);
79
+ lcd_bl_open(sel);
80
+
81
+ return 0;
82
+}
83
+
84
+static s32 lcd_close_flow(u32 sel)
85
+{
86
+ LCD_CLOSE_FUNC(sel, lcd_bl_close, 0);
87
+ LCD_CLOSE_FUNC(sel, lcd_panel_exit, 1);
88
+ LCD_CLOSE_FUNC(sel, sunxi_lcd_tcon_disable, 10);
89
+ LCD_CLOSE_FUNC(sel, lcd_power_off, 0);
90
+
91
+ return 0;
92
+}
93
+
94
+static void lcd_power_on(u32 sel)
95
+{
96
+ sunxi_lcd_pin_cfg(sel, 1);
97
+
98
+ panel_reset(sel, 0);
99
+ sunxi_lcd_power_enable(sel, 0);
100
+ sunxi_lcd_power_enable(sel, 1);
101
+ sunxi_lcd_delay_ms(50);
102
+ panel_reset(sel, 1);
103
+ sunxi_lcd_delay_ms(10);
104
+ panel_reset(sel, 0);
105
+ sunxi_lcd_delay_ms(20);
106
+ panel_reset(sel, 1);
107
+ sunxi_lcd_delay_ms(120);
108
+}
109
+
110
+static void lcd_power_off(u32 sel)
111
+{
112
+ panel_reset(sel, 0);
113
+ sunxi_lcd_delay_ms(1);
114
+ sunxi_lcd_power_disable(sel, 1);
115
+ sunxi_lcd_delay_ms(1);
116
+ sunxi_lcd_power_disable(sel, 0);
117
+ sunxi_lcd_pin_cfg(sel, 0);
118
+}
119
+
120
+static void lcd_bl_open(u32 sel)
121
+{
122
+ sunxi_lcd_pwm_enable(sel);
123
+ sunxi_lcd_backlight_enable(sel);
124
+}
125
+
126
+static void lcd_bl_close(u32 sel)
127
+{
128
+ sunxi_lcd_backlight_disable(sel);
129
+ sunxi_lcd_pwm_disable(sel);
130
+}
131
+
132
+#define ROWS 171
133
+#define COLS 44
134
+
135
+u8 data[ROWS][COLS] = {
136
+ // CMD2 ENABLE
137
+ {0x15, 0x00, 0x02, 0x00, 0x00},
138
+ {0x39, 0x00, 0x04, 0xFF, 0x87, 0x56, 0x01},
139
+ {0x15, 0x00, 0x02, 0x00, 0x80},
140
+ {0x39, 0x00, 0x03, 0xFF, 0x87, 0x56},
141
+ // Panel Resolution 720x1280
142
+ {0x15, 0x00, 0x02, 0x00, 0xA1},
143
+ {0x39, 0x00, 0x07, 0xB3, 0x02, 0xD0, 0x05, 0x00, 0x20, 0xFC},
144
+ // TCON
145
+ {0x15, 0x00, 0x02, 0x00, 0x80},
146
+ {0x39, 0x00, 0x07, 0xC0, 0x00, 0xF6, 0x00, 0x10, 0x00, 0x24},
147
+ {0x15, 0x00, 0x02, 0x00, 0x90},
148
+ {0x39, 0x00, 0x07, 0xC0, 0x00, 0xF6, 0x00, 0x10, 0x00, 0x24},
149
+ {0x15, 0x00, 0x02, 0x00, 0xA0},
150
+ {0x39, 0x00, 0x07, 0xC0, 0x02, 0x14, 0x00, 0x10, 0x00, 0x24},
151
+ {0x15, 0x00, 0x02, 0x00, 0xB0},
152
+ {0x39, 0x00, 0x07, 0xC0, 0x00, 0xF6, 0x00, 0x10, 0x00, 0x24},
153
+ {0x15, 0x00, 0x02, 0x00, 0xC1},
154
+ {0x39, 0x00, 0x09, 0xC0, 0x01, 0x27, 0x00, 0xEA, 0x00, 0xC5, 0x01, 0x5F},
155
+ {0x15, 0x00, 0x02, 0x00, 0xD7},
156
+ {0x39, 0x00, 0x07, 0xC0, 0x00, 0xC5, 0x00, 0x10, 0x00, 0x24},
157
+ {0x15, 0x00, 0x02, 0x00, 0xA3},
158
+ {0x39, 0x00, 0x07, 0xC1, 0x00, 0x20, 0x00, 0x20, 0x00, 0x02},
159
+ {0x15, 0x00, 0x02, 0x00, 0x80},
160
+ {0x39, 0x00, 0x11, 0xCE, 0x01, 0x81, 0x09, 0x13, 0x00, 0x78, 0x00, 0x78, 0x00, 0x50, 0x00, 0x50, 0x00, 0x78, 0x00, 0x78},
161
+ {0x15, 0x00, 0x02, 0x00, 0x90},
162
+ {0x39, 0x00, 0x10, 0xCE, 0x00, 0x8E, 0x0E, 0xB6, 0x00, 0x8E, 0x80, 0x09, 0x13, 0x00, 0x04, 0x00, 0x1C, 0x1F, 0x16},
163
+ {0x15, 0x00, 0x02, 0x00, 0xA0},
164
+ {0x39, 0x00, 0x04, 0xCE, 0x20, 0x00, 0x00},
165
+ {0x15, 0x00, 0x02, 0x00, 0xB0},
166
+ {0x39, 0x00, 0x04, 0xCE, 0x22, 0x00, 0x00},
167
+ {0x15, 0x00, 0x02, 0x00, 0xD1},
168
+ {0x39, 0x00, 0x08, 0xCE, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00},
169
+ {0x15, 0x00, 0x02, 0x00, 0xE1},
170
+ {0x39, 0x00, 0x0C, 0xCE, 0x08, 0x02, 0x4D, 0x02, 0x4D, 0x02, 0x4D, 0x00, 0x00, 0x00, 0x00},
171
+ {0x15, 0x00, 0x02, 0x00, 0xF1},
172
+ {0x39, 0x00, 0x0A, 0xCE, 0x0C, 0x06, 0x0A, 0x00, 0xE9, 0x00, 0xE9, 0x00, 0xF8},
173
+ {0x15, 0x00, 0x02, 0x00, 0xB0},
174
+ {0x39, 0x00, 0x05, 0xCF, 0x00, 0x00, 0x6E, 0x72},
175
+ {0x15, 0x00, 0x02, 0x00, 0xB5},
176
+ {0x39, 0x00, 0x05, 0xCF, 0x02, 0x02, 0x94, 0x98},
177
+ {0x15, 0x00, 0x02, 0x00, 0xC0},
178
+ {0x39, 0x00, 0x05, 0xCF, 0x04, 0x04, 0xD8, 0xDC},
179
+ {0x15, 0x00, 0x02, 0x00, 0xC5},
180
+ {0x39, 0x00, 0x05, 0xCF, 0x00, 0x00, 0x08, 0x0C},
181
+ // Scan Mode
182
+ {0x15, 0x00, 0x02, 0x00, 0xE8},
183
+ {0x15, 0x00, 0x02, 0xC0, 0x40},
184
+ // VST1&VST2
185
+ {0x15, 0x00, 0x02, 0x00, 0x80},
186
+ {0x39, 0x00, 0x09, 0xC2, 0x84, 0x00, 0x05, 0x89, 0x83, 0x00, 0x05, 0x89},
187
+ // CKV1-3
188
+ {0x15, 0x00, 0x02, 0x00, 0xA0},
189
+ {0x39, 0x00, 0x10, 0xC2, 0x82, 0x04, 0x00, 0x05, 0x89, 0x81, 0x04, 0x00, 0x05, 0x89, 0x00, 0x04, 0x00, 0x05, 0x89},
190
+ // CKV4-6
191
+ {0x15, 0x00, 0x02, 0x00, 0xB0},
192
+ {0x39, 0x00, 0x10, 0xC2, 0x01, 0x04, 0x00, 0x05, 0x89, 0x02, 0x04, 0x00, 0x05, 0x89, 0x03, 0x04, 0x00, 0x05, 0x89},
193
+ // CKV7-8
194
+ {0x15, 0x00, 0x02, 0x00, 0xC0},
195
+ {0x39, 0x00, 0x0B, 0xC2, 0x04, 0x04, 0x00, 0x05, 0x89, 0x05, 0x04, 0x00, 0x05, 0x89},
196
+ {0x15, 0x00, 0x02, 0x00, 0xE0},
197
+ {0x39, 0x00, 0x05, 0xC2, 0x77, 0x77, 0x77, 0x77},
198
+ {0x15, 0x00, 0x02, 0x00, 0xC0},
199
+ {0x39, 0x00, 0x05, 0xC3, 0x99, 0x99, 0x99, 0x99},
200
+ {0x15, 0x00, 0x02, 0x00, 0x80},
201
+ {0x39, 0x00, 0x11, 0xCB, 0x00, 0xC5, 0x00, 0x00, 0x05, 0x05, 0x00, 0x05, 0x0A, 0x05, 0xC5, 0x00, 0x05, 0x05, 0x00, 0xC0},
202
+ {0x15, 0x00, 0x02, 0x00, 0x90},
203
+ {0x39, 0x00, 0x11, 0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
204
+ {0x15, 0x00, 0x02, 0x00, 0xA0},
205
+ {0x39, 0x00, 0x05, 0xCB, 0x00, 0x00, 0x00, 0x00},
206
+ {0x15, 0x00, 0x02, 0x00, 0xB0},
207
+ {0x39, 0x00, 0x05, 0xCB, 0x10, 0x51, 0x94, 0x50},
208
+ {0x15, 0x00, 0x02, 0x00, 0xC0},
209
+ {0x39, 0x00, 0x05, 0xCB, 0x10, 0x51, 0x94, 0x50},
210
+ {0x15, 0x00, 0x02, 0x00, 0x80},
211
+ {0x39, 0x00, 0x11, 0xCC, 0x2D, 0x2D, 0x2D, 0x2D, 0x07, 0x09, 0x0B, 0x0D, 0x25, 0x25, 0x03, 0x2D, 0x22, 0x2D, 0x24, 0x2D},
212
+ {0x15, 0x00, 0x02, 0x00, 0x90},
213
+ {0x39, 0x00, 0x09, 0xCC, 0x29, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x26},
214
+ {0x15, 0x00, 0x02, 0x00, 0x80},
215
+ {0x39, 0x00, 0x11, 0xCD, 0x2D, 0x2D, 0x2D, 0x2D, 0x06, 0x08, 0x0A, 0x0C, 0x25, 0x00, 0x02, 0x2D, 0x22, 0x2D, 0x24, 0x2D},
216
+ {0x15, 0x00, 0x02, 0x00, 0x90},
217
+ {0x39, 0x00, 0x09, 0xCD, 0x29, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x26},
218
+ {0x15, 0x00, 0x02, 0x00, 0xA0},
219
+ {0x39, 0x00, 0x11, 0xCC, 0x2D, 0x2D, 0x2D, 0x2D, 0x08, 0x06, 0x0C, 0x0A, 0x25, 0x25, 0x02, 0x2D, 0x24, 0x2D, 0x23, 0x2D},
220
+ {0x15, 0x00, 0x02, 0x00, 0xB0},
221
+ {0x39, 0x00, 0x09, 0xCC, 0x29, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x26},
222
+ {0x15, 0x00, 0x02, 0x00, 0xA0},
223
+ {0x39, 0x00, 0x11, 0xCD, 0x2D, 0x2D, 0x2D, 0x2D, 0x09, 0x07, 0x0D, 0x0B, 0x25, 0x00, 0x03, 0x2D, 0x24, 0x2D, 0x23, 0x2D},
224
+ {0x15, 0x00, 0x02, 0x00, 0xB0},
225
+ {0x39, 0x00, 0x09, 0xCD, 0x29, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x26},
226
+ {0x15, 0x00, 0x02, 0x00, 0x80},
227
+ {0x15, 0x00, 0x02, 0xA7, 0x13},
228
+ {0x15, 0x00, 0x02, 0x00, 0x82},
229
+ {0x39, 0x00, 0x03, 0xA7, 0x22, 0x02},
230
+ {0x15, 0x00, 0x02, 0x00, 0x85},
231
+ {0x15, 0x00, 0x02, 0xC4, 0x1C},
232
+ {0x15, 0x00, 0x02, 0x00, 0xA0},
233
+ {0x39, 0x00, 0x04, 0xC4, 0x8D, 0xD8, 0x8D},
234
+ {0x15, 0x00, 0x02, 0x00, 0x93},
235
+ {0x15, 0x00, 0x02, 0xC5, 0x37},
236
+ {0x15, 0x00, 0x02, 0x00, 0x97},
237
+ {0x15, 0x00, 0x02, 0xC5, 0x37},
238
+ {0x15, 0x00, 0x02, 0x00, 0xB6},
239
+ {0x39, 0x00, 0x03, 0xC5, 0x2D, 0x2D},
240
+ {0x15, 0x00, 0x02, 0x00, 0x9A},
241
+ {0x15, 0x00, 0x02, 0xC5, 0x19},
242
+ {0x15, 0x00, 0x02, 0x00, 0x9C},
243
+ {0x15, 0x00, 0x02, 0xC5, 0x19},
244
+ {0x15, 0x00, 0x02, 0x00, 0x97},
245
+ {0x15, 0x00, 0x02, 0xC4, 0x01},
246
+ {0x15, 0x00, 0x02, 0x00, 0x9B},
247
+ {0x15, 0x00, 0x02, 0xF5, 0x4B},
248
+ {0x15, 0x00, 0x02, 0x00, 0x93},
249
+ {0x39, 0x00, 0x03, 0xF5, 0x00, 0x00},
250
+ {0x15, 0x00, 0x02, 0x00, 0x9D},
251
+ {0x15, 0x00, 0x02, 0xF5, 0x49},
252
+ {0x15, 0x00, 0x02, 0x00, 0x82},
253
+ {0x39, 0x00, 0x03, 0xF5, 0x00, 0x00},
254
+ {0x15, 0x00, 0x02, 0x00, 0x8C},
255
+ {0x39, 0x00, 0x04, 0xC3, 0x00, 0x00, 0x00},
256
+ {0x15, 0x00, 0x02, 0x00, 0x84},
257
+ {0x39, 0x00, 0x03, 0xC5, 0x28, 0x28},
258
+ {0x15, 0x00, 0x02, 0x00, 0xA4},
259
+ {0x15, 0x00, 0x02, 0xD7, 0x00},
260
+ {0x15, 0x00, 0x02, 0x00, 0x80},
261
+ {0x39, 0x00, 0x03, 0xF5, 0x59, 0x59},
262
+ {0x15, 0x00, 0x02, 0x00, 0x84},
263
+ {0x39, 0x00, 0x04, 0xF5, 0x59, 0x59, 0x59},
264
+ {0x15, 0x00, 0x02, 0x00, 0x96},
265
+ {0x15, 0x00, 0x02, 0xF5, 0x59},
266
+ {0x15, 0x00, 0x02, 0x00, 0xA6},
267
+ {0x15, 0x00, 0x02, 0xF5, 0x59},
268
+ {0x15, 0x00, 0x02, 0x00, 0xCA},
269
+ {0x15, 0x00, 0x02, 0xC0, 0x80},
270
+ {0x15, 0x00, 0x02, 0x00, 0xB1},
271
+ {0x15, 0x00, 0x02, 0xF5, 0x1F},
272
+ {0x15, 0x00, 0x02, 0x00, 0x00},
273
+ {0x39, 0x00, 0x03, 0xD8, 0x29, 0x2D},
274
+ {0x15, 0x00, 0x02, 0x00, 0x86},
275
+ {0x39, 0x00, 0x07, 0xC0, 0x01, 0x04, 0x01, 0x01, 0x22, 0x03},
276
+ {0x15, 0x00, 0x02, 0x00, 0x96},
277
+ {0x39, 0x00, 0x07, 0xC0, 0x01, 0x04, 0x01, 0x01, 0x1B, 0x03},
278
+ {0x15, 0x00, 0x02, 0x00, 0xA6},
279
+ {0x39, 0x00, 0x07, 0xC0, 0x01, 0x04, 0x01, 0x01, 0x3E, 0x03},
280
+ {0x15, 0x00, 0x02, 0x00, 0xE9},
281
+ {0x39, 0x00, 0x07, 0xC0, 0x01, 0x04, 0x01, 0x01, 0x1B, 0x03},
282
+ {0x15, 0x00, 0x02, 0x00, 0xA3},
283
+ {0x39, 0x00, 0x07, 0xCE, 0x01, 0x04, 0x01, 0x01, 0x1B, 0x03},
284
+ {0x15, 0x00, 0x02, 0x00, 0xB3},
285
+ {0x39, 0x00, 0x07, 0xCE, 0x01, 0x04, 0x01, 0x01, 0x1B, 0x03},
286
+ // gamma2.2
287
+ {0x15, 0x00, 0x02, 0x00, 0x00},
288
+ {0x39, 0x00, 0x29, 0xE1, 0x05, 0x06, 0x09, 0x10, 0x69, 0x1A, 0x22, 0x28, 0x33, 0x98, 0x3A, 0x41, 0x47, 0x4C, 0xE5, 0x51, 0x59, 0x60, 0x67, 0x05, 0x6E, 0x75, 0x7C, 0x85, 0x08, 0x8F, 0x94, 0x9B, 0xA2, 0x22, 0xAB, 0xB6, 0xC4, 0xCE, 0x9E, 0xDA, 0xEA, 0xF7, 0xFF, 0x7B},
289
+ {0x15, 0x00, 0x02, 0x00, 0x00},
290
+ {0x39, 0x00, 0x29, 0xE2, 0x05, 0x06, 0x09, 0x10, 0x69, 0x1A, 0x22, 0x28, 0x33, 0x98, 0x3A, 0x41, 0x47, 0x4C, 0xE5, 0x51, 0x59, 0x60, 0x67, 0x05, 0x6E, 0x75, 0x7C, 0x85, 0x08, 0x8F, 0x94, 0x9B, 0xA2, 0x22, 0xAB, 0xB6, 0xC4, 0xCE, 0x9E, 0xDA, 0xEA, 0xF7, 0xFF, 0x7B},
291
+ {0x15, 0x00, 0x02, 0x00, 0x00},
292
+ {0x39, 0x00, 0x29, 0xE3, 0x05, 0x06, 0x09, 0x10, 0x69, 0x1A, 0x22, 0x28, 0x33, 0x98, 0x3A, 0x41, 0x47, 0x4C, 0xE5, 0x51, 0x59, 0x60, 0x67, 0x05, 0x6E, 0x75, 0x7C, 0x85, 0x08, 0x8F, 0x94, 0x9B, 0xA2, 0x22, 0xAB, 0xB6, 0xC4, 0xCE, 0x9E, 0xDA, 0xEA, 0xF7, 0xFF, 0x7B},
293
+ {0x15, 0x00, 0x02, 0x00, 0x00},
294
+ {0x39, 0x00, 0x29, 0xE4, 0x05, 0x06, 0x09, 0x10, 0x69, 0x1A, 0x22, 0x28, 0x33, 0x98, 0x3A, 0x41, 0x47, 0x4C, 0xE5, 0x51, 0x59, 0x60, 0x67, 0x05, 0x6E, 0x75, 0x7C, 0x85, 0x08, 0x8F, 0x94, 0x9B, 0xA2, 0x22, 0xAB, 0xB6, 0xC4, 0xCE, 0x9E, 0xDA, 0xEA, 0xF7, 0xFF, 0x7B},
295
+ {0x15, 0x00, 0x02, 0x00, 0x00},
296
+ {0x39, 0x00, 0x29, 0xE5, 0x05, 0x06, 0x09, 0x10, 0x69, 0x1A, 0x22, 0x28, 0x33, 0x98, 0x3A, 0x41, 0x47, 0x4C, 0xE5, 0x51, 0x59, 0x60, 0x67, 0x05, 0x6E, 0x75, 0x7C, 0x85, 0x08, 0x8F, 0x94, 0x9B, 0xA2, 0x22, 0xAB, 0xB6, 0xC4, 0xCE, 0x9E, 0xDA, 0xEA, 0xF7, 0xFF, 0x7B},
297
+ {0x15, 0x00, 0x02, 0x00, 0x00},
298
+ {0x39, 0x00, 0x29, 0xE6, 0x05, 0x06, 0x09, 0x10, 0x69, 0x1A, 0x22, 0x28, 0x33, 0x98, 0x3A, 0x41, 0x47, 0x4C, 0xE5, 0x51, 0x59, 0x60, 0x67, 0x05, 0x6E, 0x75, 0x7C, 0x85, 0x08, 0x8F, 0x94, 0x9B, 0xA2, 0x22, 0xAB, 0xB6, 0xC4, 0xCE, 0x9E, 0xDA, 0xEA, 0xF7, 0xFF, 0x7B},
299
+ // EN GND 4 frame
300
+ {0x15, 0x00, 0x02, 0x00, 0xCC},
301
+ {0x15, 0x00, 0x02, 0xC0, 0x13},
302
+ // LVD detect Voltage
303
+ {0x15, 0x00, 0x02, 0x00, 0x82},
304
+ {0x15, 0x00, 0x02, 0xC5, 0x35},
305
+ {0x15, 0x00, 0x02, 0x00, 0x94},
306
+ {0x39, 0x00, 0x04, 0xC5, 0x02, 0x01, 0x01},
307
+ {0x15, 0x00, 0x02, 0x00, 0x98},
308
+ {0x39, 0x00, 0x03, 0xC5, 0x25, 0x01},
309
+ {0x15, 0x00, 0x02, 0x00, 0x9B},
310
+ {0x15, 0x00, 0x02, 0xC5, 0x21},
311
+ {0x15, 0x00, 0x02, 0x00, 0x9D},
312
+ {0x15, 0x00, 0x02, 0xC5, 0x25},
313
+ // Write ID
314
+ {0x15, 0x00, 0x02, 0x00, 0xD0},
315
+ {0x15, 0x00, 0x02, 0xD0, 0x56},
316
+ //LCD initial code End
317
+ {0x05, 0x78, 0x01, 0x11},
318
+ {0x05, 0x00, 0x01, 0x29},
319
+ {0x15, 0x00, 0x02, 0x35, 0x00}
320
+};
321
+
322
+static void lcd_panel_init1(u32 sel)
323
+{
324
+ int i;
325
+ u8 command;
326
+ u8 *para;
327
+ u32 para_num;
328
+ u8 *tmp;
329
+ printk(KERN_ERR"------uboot----> mipi_5_720x1280 init\n");
330
+ sunxi_lcd_dsi_clk_enable(sel);
331
+ sunxi_lcd_delay_ms(5);
332
+
333
+ for(i = 0; i < ROWS; i++) {
334
+ tmp = data[i];
335
+ if (tmp[0] == 0x05) {
336
+ sunxi_lcd_dsi_dcs_write_0para(sel, tmp[3]);
337
+ } else {
338
+ command = tmp[3];
339
+ para_num = tmp[2] - 1;
340
+ para = tmp + 4;
341
+ sunxi_lcd_dsi_dcs_write(sel, command, para, para_num);
342
+ }
343
+ if (tmp[1] != 0x0)
344
+ sunxi_lcd_delay_ms(tmp[1]);
345
+ }
346
+}
347
+
348
+
349
+static void lcd_panel_exit(u32 sel)
350
+{
351
+ sunxi_lcd_dsi_dcs_write_0para(sel, 0x28);
352
+ sunxi_lcd_delay_ms(1);
353
+ sunxi_lcd_dsi_dcs_write_0para(sel, 0x10);
354
+ sunxi_lcd_delay_ms(1);
355
+}
356
+
357
+/*sel: 0:lcd0; 1:lcd1*/
358
+static s32 lcd_user_defined_func(u32 sel, u32 para1, u32 para2, u32 para3)
359
+{
360
+ return 0;
361
+}
362
+
363
+__lcd_panel_t mipi_5_720x1280_panel = {
364
+ /* panel driver name, must mach the name of
365
+ * lcd_drv_name in sys_config.fex
366
+ */
367
+ .name = "mipi_5_720x1280",
368
+ .func = {
369
+ .cfg_panel_info = lcd_cfg_panel_info,
370
+ .cfg_open_flow = lcd_open_flow,
371
+ .cfg_close_flow = lcd_close_flow,
372
+ .lcd_user_defined_func = lcd_user_defined_func,
373
+ },
374
+};
longan/brandy/brandy-2.0/u-boot-2018/drivers/video/sunxi/disp2/disp/lcd/mipi_5_720x1280.h
....@@ -0,0 +1,20 @@
1
+/* drivers/video/sunxi/disp2/disp/lcd/k101im2qa04.h
2
+ *
3
+ * Copyright (c) 2017 Allwinnertech Co., Ltd.
4
+ * Author: zhengxiaobin <zhengxiaobin@allwinnertech.com>
5
+ *
6
+ * k101im2qa04 panel driver
7
+ *
8
+ * This program is free software; you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License version 2 as
10
+ * published by the Free Software Foundation.
11
+*/
12
+
13
+#ifndef _MIPI_5_720X1280_H
14
+#define _MIPI_5_720X1280_H
15
+
16
+#include "panels.h"
17
+
18
+extern __lcd_panel_t mipi_5_720x1280_panel;
19
+
20
+#endif /*End of file*/
longan/brandy/brandy-2.0/u-boot-2018/drivers/video/sunxi/disp2/disp/lcd/panels.c
....@@ -138,7 +138,7 @@
138138 &mipi_8_800x1280_panel,
139139 &mipi_10_800x1280_panel,
140140 /* add new panel below */
141
-
141
+ &mipi_5_720x1280_panel,
142142 NULL,
143143 };
144144
longan/brandy/brandy-2.0/u-boot-2018/drivers/video/sunxi/disp2/disp/lcd/panels.h
....@@ -239,5 +239,6 @@
239239
240240 extern __lcd_panel_t mipi_8_800x1280_panel;
241241 extern __lcd_panel_t mipi_10_800x1280_panel;
242
+extern __lcd_panel_t mipi_5_720x1280_panel;
242243
243244 #endif
longan/device/config/chips/a133/configs/c3/kickpi-k5c.dts
....@@ -443,14 +443,14 @@
443443
444444 pmu_chg_ic_temp = <0>;
445445 pmu_battery_rdc= <93>;
446
- pmu_battery_cap = <5067>;
446
+ pmu_battery_cap = <5000>;
447447 pmu_runtime_chgcur = <1000>;
448448 pmu_suspend_chgcur = <2000>;
449449 pmu_shutdown_chgcur = <2000>;
450450 pmu_init_chgvol = <4200>;
451451 pmu_battery_warning_level1 = <15>;
452452 pmu_battery_warning_level2 = <0>;
453
- pmu_chgled_func = <0>;
453
+ pmu_chgled_func = <1>;
454454 pmu_chgled_type = <0>;
455455 ocv_coulumb_100 = <1>;
456456 pmu_bat_para1 = <0>;
....@@ -476,12 +476,12 @@
476476 pmu_bat_para21 = <75>;
477477 pmu_bat_para22 = <80>;
478478 pmu_bat_para23 = <83>;
479
- pmu_bat_para24 = <84>;
480
- pmu_bat_para25 = <86>;
481
- pmu_bat_para26 = <90>;
482
- pmu_bat_para27 = <94>;
483
- pmu_bat_para28 = <97>;
484
- pmu_bat_para29 = <99>;
479
+ pmu_bat_para24 = <88>;
480
+ pmu_bat_para25 = <92>;
481
+ pmu_bat_para26 = <97>;
482
+ pmu_bat_para27 = <100>;
483
+ pmu_bat_para28 = <100>;
484
+ pmu_bat_para29 = <100>;
485485 pmu_bat_para30 = <100>;
486486 pmu_bat_para31 = <100>;
487487 pmu_bat_para32 = <100>;
....@@ -1465,6 +1465,7 @@
14651465
14661466
14671467 //#include "lcd-lvds-21-1920-1080.dtsi"
1468
-#include "lcd-lvds-7-1024-600.dtsi"
1468
+//#include "lcd-lvds-7-1024-600.dtsi"
14691469 //#include "lcd-mipi-10-800-1280.dtsi"
14701470 //#include "lcd-mipi-8-800-1280.dtsi"
1471
+#include "lcd-mipi-5-720-1280.dtsi"
longan/kernel/linux-4.9/arch/arm64/boot/dts/sunxi/lcd-mipi-5-720-1280.dtsi
....@@ -0,0 +1,260 @@
1
+&soc {
2
+/*----------------------------------------------------------------------------------
3
+disp init configuration
4
+
5
+disp_mode (0:screen0<screen0,fb0>)
6
+screenx_output_type (0:none; 1:lcd; 2:tv; 3:hdmi;5:vdpo)
7
+screenx_output_mode (used for hdmi output, 0:480i 1:576i 2:480p 3:576p 4:720p50)
8
+ (5:720p60 6:1080i50 7:1080i60 8:1080p24 9:1080p50 10:1080p60)
9
+screenx_output_format (for hdmi, 0:RGB 1:yuv444 2:yuv422 3:yuv420)
10
+screenx_output_bits (for hdmi, 0:8bit 1:10bit 2:12bit 2:16bit)
11
+screenx_output_eotf (for hdmi, 0:reserve 4:SDR 16:HDR10 18:HLG)
12
+screenx_output_cs (for hdmi, 0:undefined 257:BT709 260:BT601 263:BT2020)
13
+screenx_output_dvi_hdmi (for hdmi, 0:undefined 1:dvi mode 2:hdmi mode)
14
+screen0_output_range (for hdmi, 0:default 1:full 2:limited)
15
+screen0_output_scan (for hdmi, 0:no data 1:overscan 2:underscan)
16
+screen0_output_aspect_ratio (for hdmi, 8-same as original picture 9-4:3 10-16:9 11-14:9)
17
+fbx format (4:RGB655 5:RGB565 6:RGB556 7:ARGB1555 8:RGBA5551 9:RGB888 10:ARGB8888 12:ARGB4444)
18
+fbx pixel sequence (0:ARGB 1:BGRA 2:ABGR 3:RGBA)
19
+fb0_scaler_mode_enable(scaler mode enable, used FE)
20
+fbx_width,fbx_height (framebuffer horizontal/vertical pixels, fix to output resolution while equal 0)
21
+lcdx_backlight (lcd init backlight,the range:[0,256],default:197
22
+lcdx_yy (lcd init screen bright/contrast/saturation/hue, value:0~100, default:50/50/57/50)
23
+lcd0_contrast (LCD contrast, 0~100)
24
+lcd0_saturation (LCD saturation, 0~100)
25
+lcd0_hue (LCD hue, 0~100)
26
+framebuffer software rotation setting:
27
+disp_rotation_used: (0:disable; 1:enable,you must set fbX_width to lcd_y,
28
+set fbX_height to lcd_x)
29
+degreeX: (X:screen index; 0:0 degree; 1:90 degree; 3:270 degree)
30
+degreeX_Y: (X:screen index; Y:layer index 0~15; 0:0 degree; 1:90 degree; 3:270 degree)
31
+devX_output_type : config output type in bootGUI framework in UBOOT-2018.
32
+ (0:none; 1:lcd; 2:tv; 4:hdmi;)
33
+devX_output_mode : config output resolution(see include/video/sunxi_display2.h) of bootGUI framework in UBOOT-2018
34
+devX_screen_id : config display index of bootGUI framework in UBOOT-2018
35
+devX_do_hpd : whether do hpd detectation or not in UBOOT-2018
36
+chn_cfg_mode : Hardware DE channel allocation config. 0:single display with 6
37
+ channel, 1:dual display with 4 channel in main display and 2 channel in second
38
+ display, 2:dual display with 3 channel in main display and 3 channel in second
39
+ in display.
40
+----------------------------------------------------------------------------------*/
41
+ disp: disp@06000000 {
42
+ disp_init_enable = <1>;
43
+ disp_mode = <0>;
44
+
45
+ screen0_output_type = <1>;
46
+ screen0_output_mode = <4>;
47
+
48
+ screen1_output_type = <1>;
49
+ screen1_output_mode = <4>;
50
+
51
+ screen1_output_format = <0>;
52
+ screen1_output_bits = <0>;
53
+ screen1_output_eotf = <4>;
54
+ screen1_output_cs = <257>;
55
+ screen1_output_dvi_hdmi = <2>;
56
+ screen1_output_range = <2>;
57
+ screen1_output_scan = <0>;
58
+ screen1_output_aspect_ratio = <8>;
59
+
60
+ dev0_output_type = <1>;
61
+ dev0_output_mode = <4>;
62
+ dev0_screen_id = <0>;
63
+ dev0_do_hpd = <0>;
64
+
65
+ dev1_output_type = <4>;
66
+ dev1_output_mode = <10>;
67
+ dev1_screen_id = <1>;
68
+ dev1_do_hpd = <1>;
69
+
70
+ def_output_dev = <0>;
71
+ hdmi_mode_check = <1>;
72
+
73
+ fb0_format = <0>;
74
+ fb0_width = <720>;
75
+ fb0_height = <1280>;
76
+
77
+ fb1_format = <0>;
78
+ fb1_width = <0>;
79
+ fb1_height = <0>;
80
+ chn_cfg_mode = <1>;
81
+
82
+ disp_para_zone = <1>;
83
+ dc1sw-supply = <&reg_dc1sw>;
84
+ eldo3-supply = <&reg_eldo3>;
85
+ dldo2-supply = <&reg_dldo2>;
86
+ dcdc1-supply = <&reg_dcdc1>;
87
+ };
88
+/*----------------------------------------------------------------------------------
89
+;lcd0 configuration
90
+
91
+;lcd_if: 0:hv(sync+de); 1:8080; 2:ttl; 3:lvds; 4:dsi; 5:edp; 6:extend dsi
92
+;lcd_hv_if 0:Parallel RGB; 8:Serial RGB; 10:Dummy RGB; 11: RGB Dummy;12:CCIR656
93
+;lcd_hv_clk_phase 0:0 degree;1:90 degree;2:180 degree;3:270 degree
94
+;lcd_hv_sync_polarity 0:vs low,hs low; 1:vs high,hslow; 2:vs low,hs high; 3:vs high,hs high
95
+;lcd_hv_syuv_seq 0:YUYV; 1:YVYU; 2:UYVY; 3:VYUY
96
+;lcd_cpu_if 0:18bit/1 cycle parallel(RGB666); 4:16bit/1cycle parallel (RGB565)
97
+; 6:18bit/3 cycle parallel(RGB666); 7:16bit/2cycle parallel (RGB565)
98
+;lcd_cpu_te 0:frame auto trigger; 1:frame triggered by te rising edge; 2:frame triggered by te falling edge;
99
+;lcd_dsi_if 0:video mode; 1: Command mode; 2:video burst mode
100
+;lcd_dsi_te 0:frame auto trigger; 1:frame triggered by te rising edge; 2:frame triggered by te falling edge;
101
+;lcd_x: lcd horizontal resolution
102
+;lcd_y: lcd vertical resolution
103
+;lcd_width: width of lcd in mm
104
+;lcd_height: height of lcd in mm
105
+;lcd_dclk_freq: in MHZ unit
106
+;lcd_pwm_freq: in HZ unit
107
+;lcd_pwm_pol: lcd backlight PWM polarity
108
+;lcd_pwm_max_limit lcd backlight PWM max limit(<=255)
109
+;lcd_hbp: hsync back porch(pixel) + hsync plus width(pixel);
110
+;lcd_ht: hsync total cycle(pixel)
111
+;lcd_vbp: vsync back porch(line) + vysnc plus width(line)
112
+;lcd_vt: vysnc total cycle(line)
113
+;lcd_hspw: hsync plus width(pixel)
114
+;lcd_vspw: vysnc plus width(pixel)
115
+;lcd_lvds_if: 0:single link; 1:dual link
116
+;lcd_lvds_colordepth: 0:8bit; 1:6bit
117
+;lcd_lvds_mode: 0:NS mode; 1:JEIDA mode
118
+;lcd_frm: 0:disable; 1:enable rgb666 dither; 2:enable rgb656 dither
119
+;lcd_io_phase: 0:noraml; 1:intert phase(0~3bit: vsync phase; 4~7bit:hsync phase;
120
+; 8~11bit:dclk phase; 12~15bit:de phase)
121
+;lcd_gamma_en lcd gamma correction enable
122
+;lcd_bright_curve_en lcd bright curve correction enable
123
+;lcd_cmap_en lcd color map function enable
124
+;deu_mode 0:smoll lcd screen; 1:large lcd screen(larger than 10inch)
125
+;lcdgamma4iep: Smart Backlight parameter, lcd gamma vale * 10;
126
+; decrease it while lcd is not bright enough; increase while lcd is too bright
127
+;smart_color 90:normal lcd screen 65:retina lcd screen(9.7inch)
128
+;Pin setting for special function ie.LVDS, RGB data or vsync
129
+; name(donot care) = port:PD12<pin function><pull up or pull down><drive ability><output level>
130
+;Pin setting for gpio:
131
+; lcd_gpio_X = port:PD12<pin function><pull up or pull down><drive ability><output level>
132
+;Pin setting for backlight enable pin
133
+; lcd_bl_en = port:PD12<pin function><pull up or pull down><drive ability><output level>
134
+;fsync setting, pulse to csi
135
+;lcd_fsync_en (0:disable fsync,1:enable)
136
+;lcd_fsync_act_time (active time of fsync, unit:pixel)
137
+;lcd_fsync_dis_time (disactive time of fsync, unit:pixel)
138
+;lcd_fsync_pol (0:positive;1:negative)
139
+;gpio config: <&pio for cpu or &r_pio for cpus, port, port num, pio function,
140
+pull up or pull down(default 0), driver level(default 1), data>
141
+;For dual link lvds: use lvds2link_pins_a and lvds2link_pins_b instead
142
+;For rgb24: use rgb24_pins_a and rgb24_pins_b instead
143
+;For lvds1: use lvds1_pins_a and lvds1_pins_b instead
144
+;For lvds0: use lvds0_pins_a and lvds0_pins_b instead
145
+;----------------------------------------------------------------------------------*/
146
+ lcd0: lcd0@01c0c000 {
147
+ lcd_used = <1>;
148
+
149
+ lcd_driver_name = "mipi_5_720x1280";
150
+ lcd_backlight = <50>;
151
+ lcd_if = <4>;
152
+
153
+ lcd_x = <720>;
154
+ lcd_y = <1280>;
155
+ lcd_width = <62>;
156
+ lcd_height = <110>;
157
+ lcd_dclk_freq = <68>;
158
+
159
+ lcd_pwm_used = <1>;
160
+ lcd_pwm_ch = <2>;
161
+ lcd_pwm_freq = <50000>;
162
+ lcd_pwm_pol = <1>;
163
+ lcd_pwm_max_limit = <255>;
164
+
165
+ //lcd_hbp = <18>;
166
+ //lcd_ht = <934>;
167
+ //lcd_hspw = <4>;
168
+
169
+ //lcd_vbp = <38>;
170
+ //lcd_vt = <1344>;
171
+ //lcd_vspw = <2>;
172
+
173
+ lcd_hbp = <47>;
174
+ lcd_ht = <782>;
175
+ lcd_hspw = <15>;
176
+ lcd_vbp = <27>;
177
+ lcd_vt = <1322>;
178
+ lcd_vspw = <15>;
179
+
180
+
181
+ lcd_frm = <0>;
182
+ lcd_gamma_en = <0>;
183
+ lcd_bright_curve_en = <0>;
184
+ lcd_cmap_en = <0>;
185
+
186
+ deu_mode = <0>;
187
+ lcdgamma4iep = <22>;
188
+ smart_color = <90>;
189
+
190
+ lcd_dsi_if = <0>;
191
+ lcd_dsi_lane = <4>;
192
+ lcd_dsi_format = <0>;
193
+ lcd_dsi_te = <0>;
194
+ lcd_dsi_eotp = <0>;
195
+
196
+ //lcd_lvds_if = <0>;
197
+ //lcd_lvds_colordepth = <0>;
198
+ //lcd_lvds_mode = <1>;
199
+
200
+ lcd_pin_power = "dcdc1";
201
+ lcd_pin_power1 = "eldo3";
202
+ //lcd_pin_power2 = "dldo2";
203
+
204
+ lcd_power = "dc1sw";
205
+ lcd_bl_en = <&pio PD 21 1 0 3 1>;
206
+
207
+ // reset
208
+ lcd_gpio_0 = <&pio PE 5 1 0 3 1>;
209
+ // power
210
+ //lcd_gpio_1 = <&pio PD 21 1 0 3 1>;
211
+
212
+ pinctrl-0 = <&dsi4lane_pins_a>;
213
+ pinctrl-1 = <&dsi4lane_pins_b>;
214
+ //pinctrl-0 = <&lvds0_pins_a>;
215
+ //pinctrl-1 = <&lvds0_pins_b>;
216
+ };
217
+ };
218
+
219
+&twi0 {
220
+ myft5x06: my-ft5x06@38 {
221
+ compatible = "focaltech,fts";
222
+ reg = <0x38>;
223
+ status = "okay";
224
+
225
+ // focaltech,reset-gpio = <&gpio0 RK_PB6 GPIO_ACTIVE_LOW>;
226
+ // focaltech,irq-gpio = <&gpio3 RK_PA3 IRQ_TYPE_LEVEL_LOW>;
227
+
228
+ focaltech,reset-gpio = <&pio PE 4 1 0xffffffff 0xffffffff 1>;
229
+ focaltech,irq-gpio = <&pio PE 3 6 0xffffffff 0xffffffff 0>;
230
+
231
+ // pinctrl-names = "default";
232
+ // pinctrl-0 = <&touch1_gpio>;
233
+
234
+ focaltech,display-coords = <0 0 720 1280>;
235
+ focaltech,max-touch-number = <10>;
236
+
237
+ };
238
+
239
+ /*
240
+ ctp {
241
+ compatible = "gt9xx_ts";
242
+ ctp_used = <1>;
243
+ device_type = "ctp";
244
+ status = "okay";
245
+ ctp_twi_id = <0x0>;
246
+ ctp_name = "gt9xx";
247
+ reg = <0x5D>;
248
+ ctp_screen_max_x = <1024>;
249
+ ctp_screen_max_y = <600>;
250
+ ctp_revert_x_flag = <0x1>;
251
+ ctp_revert_y_flag = <0x1>;
252
+ ctp_exchange_x_y_flag = <0x0>;
253
+ ctp_int_port = <&pio PE 3 6 0xffffffff 0xffffffff 0>;
254
+ ctp_wakeup = <&pio PE 4 1 0xffffffff 0xffffffff 1>;
255
+ ctp_power_ldo = <3300>;
256
+ ctp_power_ldo_vol = <3300>;
257
+ ctp_power = <3300>;
258
+ };
259
+ */
260
+};
longan/kernel/linux-4.9/drivers/input/touchscreen/Makefile
....@@ -97,3 +97,4 @@
9797 obj-$(CONFIG_TOUCHSCREEN_FTS_TS) += focaltech_touch/
9898 obj-$(CONFIG_INPUT_TOUCHSCREEN) += gt9xxnew/
9999 obj-$(CONFIG_INPUT_TOUCHSCREEN) += gt9xx/
100
+obj-y += focaltech_touch_ft8756/
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/Kconfig
....@@ -0,0 +1,10 @@
1
+#
2
+# Focaltech Touchscreen driver configuration
3
+#
4
+
5
+config TOUCHSCREEN_FTS
6
+ tristate "Focaltech Touchscreen"
7
+ default m
8
+ help
9
+ Say Y here if you have Focaltech touch panel.
10
+ If unsure, say N.
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/Makefile
....@@ -0,0 +1,14 @@
1
+# Makefile for the focaltech touchscreen drivers.
2
+
3
+obj-y += focaltech_tp.o
4
+focaltech_tp-y := focaltech_core.o \
5
+ focaltech_ex_fun.o \
6
+ focaltech_ex_mode.o \
7
+ focaltech_gesture.o \
8
+ focaltech_esdcheck.o \
9
+ focaltech_point_report_check.o \
10
+ focaltech_proximity.o
11
+
12
+focaltech_tp-y += focaltech_i2c.o
13
+focaltech_tp-y += focaltech_flash.o
14
+focaltech_tp-y += focaltech_flash/focaltech_upgrade_ft8756m.o
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_common.h
....@@ -0,0 +1,193 @@
1
+/*
2
+ *
3
+ * FocalTech fts TouchScreen driver.
4
+ *
5
+ * Copyright (c) 2012-2020, Focaltech Ltd. All rights reserved.
6
+ *
7
+ * This software is licensed under the terms of the GNU General Public
8
+ * License version 2, as published by the Free Software Foundation, and
9
+ * may be copied, distributed, and modified under those terms.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ */
17
+/*****************************************************************************
18
+*
19
+* File Name: focaltech_common.h
20
+*
21
+* Author: Focaltech Driver Team
22
+*
23
+* Created: 2016-08-16
24
+*
25
+* Abstract:
26
+*
27
+* Reference:
28
+*
29
+*****************************************************************************/
30
+
31
+#ifndef __LINUX_FOCALTECH_COMMON_H__
32
+#define __LINUX_FOCALTECH_COMMON_H__
33
+
34
+#include "focaltech_config.h"
35
+
36
+/*****************************************************************************
37
+* Macro definitions using #define
38
+*****************************************************************************/
39
+#define FTS_DRIVER_VERSION "FocalTech V4.2 20240407"
40
+
41
+#define BYTE_OFF_0(x) (u8)((x) & 0xFF)
42
+#define BYTE_OFF_8(x) (u8)(((x) >> 8) & 0xFF)
43
+#define BYTE_OFF_16(x) (u8)(((x) >> 16) & 0xFF)
44
+#define BYTE_OFF_24(x) (u8)(((x) >> 24) & 0xFF)
45
+#define FLAGBIT(x) (0x00000001 << (x))
46
+#define FLAGBITS(x, y) ((0xFFFFFFFF >> (32 - (y) - 1)) & (0xFFFFFFFF << (x)))
47
+
48
+#define FLAG_ICSERIALS_LEN 8
49
+#define FLAG_HID_BIT 10
50
+#define FLAG_IDC_BIT 11
51
+#define INTERVAL_READ_REG 200 /* unit:ms */
52
+#define TIMEOUT_READ_REG 1000 /* unit:ms */
53
+
54
+#define FTS_DELAY_RESUME_RESET 50 /* unit:ms */
55
+
56
+#define IC_SERIALS (FTS_CHIP_TYPE & FLAGBITS(0, FLAG_ICSERIALS_LEN-1))
57
+#define IC_TO_SERIALS(x) ((x) & FLAGBITS(0, FLAG_ICSERIALS_LEN-1))
58
+#define FTS_CHIP_IDC ((FTS_CHIP_TYPE & FLAGBIT(FLAG_IDC_BIT)) == FLAGBIT(FLAG_IDC_BIT))
59
+#define FTS_HID_SUPPORTTED ((FTS_CHIP_TYPE & FLAGBIT(FLAG_HID_BIT)) == FLAGBIT(FLAG_HID_BIT))
60
+
61
+#define FTS_MAX_CHIP_IDS 8
62
+
63
+#define FTS_CHIP_TYPE_MAPPING {{0x15, 0x87, 0x56, 0x87, 0x56, 0xF7, 0xA6, 0x00, 0x00}}
64
+
65
+
66
+#define FILE_NAME_LENGTH 128
67
+#define ENABLE 1
68
+#define DISABLE 0
69
+#define VALID 1
70
+#define INVALID 0
71
+#define FTS_CMD_START1 0x55
72
+#define FTS_CMD_START2 0xAA
73
+#define FTS_CMD_START_DELAY 12
74
+#define FTS_CMD_READ_ID 0x90
75
+#define FTS_CMD_READ_ID_LEN 4
76
+#define FTS_CMD_READ_ID_LEN_INCELL 1
77
+#define FTS_CMD_READ_BOOT_STATE 0xD0
78
+#define FTS_CMD_READ_INFO 0x5E
79
+
80
+/*register address*/
81
+#define FTS_REG_INT_CNT 0x8F
82
+#define FTS_REG_FLOW_WORK_CNT 0x91
83
+#define FTS_REG_WORKMODE 0x00
84
+#define FTS_REG_WORKMODE_FACTORY_VALUE 0x40
85
+#define FTS_REG_WORKMODE_WORK_VALUE 0x00
86
+#define FTS_REG_ESDCHECK_DISABLE 0x8D
87
+#define FTS_REG_CHIP_ID 0xA3
88
+#define FTS_REG_CHIP_ID2 0x9F
89
+#define FTS_REG_POWER_MODE 0xA5
90
+#define FTS_REG_POWER_MODE_SLEEP 0x03
91
+#define FTS_REG_FW_VER 0xA6
92
+#define FTS_REG_VENDOR_ID 0xA8
93
+#define FTS_REG_LCD_BUSY_NUM 0xAB
94
+#define FTS_REG_FACE_DEC_MODE_EN 0xB0
95
+#define FTS_REG_FW_MODE 0xB4
96
+#define FTS_REG_FACE_DEC_MODE_STATUS 0x01
97
+#define FTS_REG_IDE_PARA_VER_ID 0xB5
98
+#define FTS_REG_IDE_PARA_STATUS 0xB6
99
+#define FTS_REG_CHARGER_MODE_EN 0x8B
100
+#define FTS_REG_EDGEPALM_MODE_EN 0x8C
101
+#define FTS_REG_GLOVE_MODE_EN 0xC0
102
+#define FTS_REG_COVER_MODE_EN 0xC1
103
+#define FTS_REG_EARPHONE_MODE_EN 0xC3
104
+#define FTS_REG_GESTURE_EN 0xD0
105
+#define FTS_REG_GESTURE_OUTPUT_ADDRESS 0xD3
106
+#define FTS_REG_PANEL_ID 0xE3
107
+#define FTS_REG_LIC_VER 0xE4
108
+#define FTS_REG_ESD_SATURATE 0xED
109
+#define FTS_REG_FOD_MODE_EN 0xCF
110
+#define FTS_VAL_FOD_ENABLE 0x02
111
+#define FTS_REG_FOD_DATA 0xE1
112
+#define FTS_REG_TPINFO 0x96
113
+#define FTS_REG_TPCFG 0x9D
114
+#define FTS_MAX_RETRIES_READID 10
115
+#define FTS_MAX_RETRIES_READID_RESUME 5
116
+#define FTS_MAX_RETRIES_READ_BOOTID 5
117
+#define FTS_MAX_RETRIES_WRITEREG 5
118
+
119
+#define FTS_SYSFS_ECHO_ON(buf) (buf[0] == '1')
120
+#define FTS_SYSFS_ECHO_OFF(buf) (buf[0] == '0')
121
+
122
+#define kfree_safe(pbuf) do {\
123
+ if (pbuf) {\
124
+ kfree(pbuf);\
125
+ pbuf = NULL;\
126
+ }\
127
+} while(0)
128
+
129
+/*****************************************************************************
130
+* Alternative mode (When something goes wrong, the modules may be able to solve the problem.)
131
+*****************************************************************************/
132
+/*
133
+ * point report check
134
+ * default: disable
135
+ */
136
+#define FTS_POINT_REPORT_CHECK_EN 0
137
+
138
+/*****************************************************************************
139
+* Global variable or extern global variabls/functions
140
+*****************************************************************************/
141
+struct ft_chip_t {
142
+ u16 type;
143
+ u8 chip_idh;
144
+ u8 chip_idl;
145
+ u8 rom_idh;
146
+ u8 rom_idl;
147
+ u8 pb_idh;
148
+ u8 pb_idl;
149
+ u8 bl_idh;
150
+ u8 bl_idl;
151
+};
152
+
153
+struct ft_chip_id_t {
154
+ u16 type;
155
+ u16 chip_ids[FTS_MAX_CHIP_IDS];
156
+};
157
+
158
+struct ts_ic_info {
159
+ bool is_incell;
160
+ bool hid_supported;
161
+ struct ft_chip_t ids;
162
+ struct ft_chip_id_t cid;
163
+};
164
+
165
+/*****************************************************************************
166
+* DEBUG function define here
167
+*****************************************************************************/
168
+#if FTS_DEBUG_EN
169
+#define FTS_DEBUG(fmt, args...) do { \
170
+ printk(KERN_DEBUG "[FTS_TS]%s:"fmt"\n", __func__, ##args); \
171
+} while (0)
172
+
173
+#define FTS_FUNC_ENTER() do { \
174
+ printk(KERN_DEBUG "[FTS_TS]%s: Enter\n", __func__); \
175
+} while (0)
176
+
177
+#define FTS_FUNC_EXIT() do { \
178
+ printk(KERN_DEBUG "[FTS_TS]%s: Exit(%d)\n", __func__, __LINE__); \
179
+} while (0)
180
+#else /* #if FTS_DEBUG_EN*/
181
+#define FTS_DEBUG(fmt, args...)
182
+#define FTS_FUNC_ENTER()
183
+#define FTS_FUNC_EXIT()
184
+#endif
185
+
186
+#define FTS_INFO(fmt, args...) do { \
187
+ printk(KERN_ERR "[FTS_TS/I]%s:"fmt"\n", __func__, ##args); \
188
+} while (0)
189
+
190
+#define FTS_ERROR(fmt, args...) do { \
191
+ printk(KERN_ERR "[FTS_TS/E]%s:"fmt"\n", __func__, ##args); \
192
+} while (0)
193
+#endif /* __LINUX_FOCALTECH_COMMON_H__ */
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_config.h
....@@ -0,0 +1,362 @@
1
+/*
2
+ *
3
+ * FocalTech TouchScreen driver.
4
+ *
5
+ * Copyright (c) 2012-2020, FocalTech Systems, Ltd., all rights reserved.
6
+ *
7
+ * This software is licensed under the terms of the GNU General Public
8
+ * License version 2, as published by the Free Software Foundation, and
9
+ * may be copied, distributed, and modified under those terms.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ */
17
+/************************************************************************
18
+*
19
+* File Name: focaltech_config.h
20
+*
21
+* Author: Focaltech Driver Team
22
+*
23
+* Created: 2016-08-08
24
+*
25
+* Abstract: global configurations
26
+*
27
+* Version: v1.0
28
+*
29
+************************************************************************/
30
+#ifndef _LINUX_FOCLATECH_CONFIG_H_
31
+#define _LINUX_FOCLATECH_CONFIG_H_
32
+
33
+/**************************************************/
34
+/****** G: A, I: B, S: C, U: D ******************/
35
+/****** chip type defines, do not modify *********/
36
+#define _FT8716 0x87160805
37
+#define _FT8736 0x87360806
38
+#define _FT8607 0x86070809
39
+#define _FT8006U 0x8006D80B
40
+#define _FT8006S 0x8006A80B
41
+#define _FT8613 0x8613080C
42
+#define _FT8719 0x8719080D
43
+#define _FT8739 0x8739080E
44
+#define _FT8615 0x8615080F
45
+#define _FT8201 0x82010810
46
+#define _FT8201AA 0x8201A810
47
+#define _FT8006P 0x86220811
48
+#define _FT8613S 0x8613C814
49
+#define _FT8756 0x87560815
50
+#define _FT8656 0x86560815
51
+#define _FT8756M 0x8756A815
52
+#define _FT8302 0x83020816
53
+#define _FT8009 0x80090817
54
+#define _FT8006S_AA 0x86320819
55
+#define _FT7250 0x7250081A
56
+#define _FT7120 0x7120081B
57
+#define _FT8720 0x8720081C
58
+#define _FT8726 0x8726081C
59
+#define _FT8720H 0x8720E81C
60
+#define _FT8720M 0x8720F81C
61
+#define _FT8016 0x8016081D
62
+#define _FT8006S_AB 0x8642081F
63
+#define _FT8722 0x87220820
64
+#define _FT8201AB 0x8201B821
65
+#define _FT8203 0x82030821
66
+#define _FT8201M 0x8201C821
67
+#define _FT8006S_AN 0x8006B822
68
+#define _FT7131 0x71310823
69
+#define _FT7250AB 0x7250B824
70
+#define _FT7130 0x71300825
71
+#define _FT8205 0x82050826
72
+#define _FT2389 0x23890827
73
+#define _FT8057 0x80570828
74
+#define _FT8057S 0x8057C828
75
+#define _FT8725 0x87250829
76
+#define _FT7135 0x71350829
77
+#define _FT8206 0x8206082A
78
+#define _FT8057P 0x8057082B
79
+#define _FT7133 0x7133082B
80
+#define _FT8205P 0x8205082C
81
+#define _FT8201P 0x8201082C
82
+#define _FT8201S 0x8201C82C
83
+#define _FT7250P 0x7250082C
84
+
85
+
86
+#define _FT5426 0x54260402
87
+#define _FT5436 0x54360402
88
+#define _FT5526 0x55260402
89
+#define _FT5446 0x54460402
90
+#define _FT5346 0x53460402
91
+#define _FT7661 0x76610402
92
+#define _FT7511 0x75110402
93
+#define _FT7421 0x74210402
94
+#define _FT7681 0x76810402
95
+#define _FT3417 0x34170402
96
+#define _FT3517 0x35170402
97
+#define _FT3327 0x33270402
98
+#define _FT3427 0x34270402
99
+#define _FT7311 0x73110402
100
+#define _FT5526_V00 0x5526C402
101
+
102
+#define _FT5726 0x57260401
103
+#define _FT5826S 0x5826C401
104
+#define _FT7811 0x78110401
105
+#define _FT3617 0x36170401
106
+#define _FT3717 0x37170401
107
+
108
+#define _FT6236U 0x6236D003
109
+#define _FT6336G 0x6336A003
110
+#define _FT6336U 0x6336D003
111
+#define _FT6436U 0x6436D003
112
+#define _FT6436T 0x6436E003
113
+
114
+#define _FT3267 0x32670004
115
+#define _FT3367 0x33670004
116
+
117
+#define _FT5446_Q03 0x5446C482
118
+#define _FT5446_P03 0x5446A481
119
+#define _FT5446_N03 0x5446A489
120
+#define _FT5426_003 0x5426D482
121
+#define _FT5526_003 0x5526D482
122
+#define _FT3437_003 0x34370482
123
+
124
+#define _FT3518 0x35180481
125
+#define _FT3518U 0x3518D481
126
+#define _FT3558 0x35580481
127
+#define _FT3528 0x35280481
128
+#define _FT5536 0x55360481
129
+#define _FT3418 0x34180481
130
+#define _FT5536G 0x5536A481
131
+
132
+#define _FT5446U 0x5446D083
133
+#define _FT5456U 0x5456D083
134
+#define _FT5426U 0x5426D083
135
+
136
+#define _FT7302 0x73020084
137
+#define _FT7202 0x72020084
138
+#define _FT3308 0x33080084
139
+#define _FT6446 0x64460084
140
+
141
+#define _FT6346U 0x6346D085
142
+#define _FT6346G 0x6346A085
143
+#define _FT3067 0x30670085
144
+#define _FT3068 0x30680085
145
+#define _FT3168 0x31680085
146
+#define _FT3268 0x32680085
147
+#define _FT6146 0x61460085
148
+#define _FT3168G 0x3168A085
149
+#define _FT6347 0x63470085
150
+
151
+#define _FT5726_003 0x5726D486
152
+#define _FT5726_V03 0x5726C486
153
+#define _FT3617_003 0x3617D486
154
+
155
+#define _FT3618 0x36180487
156
+#define _FT5646 0x56460487
157
+#define _FT3A58 0x3A580487
158
+#define _FT3B58 0x3B580487
159
+#define _FT3D58 0x3D580487
160
+#define _FT3D59 0x3D590487
161
+#define _FT5936 0x59360487
162
+#define _FT5A36 0x5A360487
163
+#define _FT5B36 0x5B360487
164
+#define _FT5D36 0x5D360487
165
+#define _FT5946 0x59460487
166
+#define _FT5A46 0x5A460487
167
+#define _FT5B46 0x5B460487
168
+#define _FT5D46 0x5D460487
169
+
170
+#define _FT3658U 0x3658D488
171
+#define _FT3658G 0x3658A488
172
+
173
+#define _FT3519 0x35190489
174
+#define _FT3519T 0x3519E489
175
+#define _FT3519U 0x3519D489
176
+#define _FT3419 0x34190489
177
+#define _FT5536U_003 0x5536D489
178
+#define _FT5426G 0x5426A489
179
+#define _FT3437_N03 0x34370489
180
+#define _FT7411 0x74110489
181
+#define _FT7411A 0x7411A489
182
+#define _FT7511A 0x7511A489
183
+#define _FT7511U 0x7511D489
184
+
185
+#define _FT3680 0x3680008A
186
+#define _FT368A 0x368A008A
187
+#define _FT3681 0x3681008A
188
+#define _FT3881 0x3881008A
189
+
190
+#define _FT3169 0x3169008B
191
+#define _FT3269 0x3269008B
192
+
193
+#define _FT3658S 0x3658C48C
194
+
195
+#define _FT3A81 0x3A81048D
196
+#define _FT3B81 0x3B81048D
197
+#define _FT3D81 0x3D81048D
198
+
199
+#define _FT5B36U 0x5B36D48E
200
+
201
+#define _FT3682 0x3682008F
202
+#define _FT3C82 0x3C82008F
203
+
204
+#define _FT3683G 0x56720090
205
+#define _FT3683U 0x3683D090
206
+#define _FT7510 0x75100090
207
+#define _FT7512 0x75120090
208
+#define _FT3683 0x36830092
209
+
210
+#define _FT3D81_003 0x3D81B491
211
+
212
+#define _FT3510 0x35100093
213
+#define _FT3610 0x36100093
214
+#define _FT3383 0x33830093
215
+
216
+
217
+
218
+/*************************************************/
219
+
220
+/*
221
+ * choose your ic chip type of focaltech
222
+ */
223
+#define FTS_CHIP_TYPE _FT8756M
224
+
225
+/******************* Enables *********************/
226
+/*********** 1 to enable, 0 to disable ***********/
227
+
228
+/*
229
+ * show debug log info
230
+ * enable it for debug, disable it for release
231
+ */
232
+#define FTS_DEBUG_EN 1
233
+
234
+/*
235
+ * Linux MultiTouch Protocol
236
+ * 1: Protocol B(default), 0: Protocol A
237
+ */
238
+#define FTS_MT_PROTOCOL_B_EN 1
239
+
240
+/*
241
+ * Report Pressure in multitouch
242
+ * 1:enable(default),0:disable
243
+*/
244
+#define FTS_REPORT_PRESSURE_EN 0
245
+
246
+/*
247
+ * Stylus PEN enable
248
+ * 1:enable(default),0:disable
249
+*/
250
+#define FTS_PEN_EN 0
251
+
252
+/*
253
+ * Proximity function enable
254
+ * default: disable
255
+ */
256
+#define FTS_PSENSOR_EN 0
257
+
258
+/*
259
+ * FOD function enable
260
+ * default: disable
261
+ */
262
+#define FTS_FOD_EN 0
263
+
264
+/*
265
+ * ESD check & protection
266
+ * default: disable
267
+ */
268
+#define FTS_ESDCHECK_EN 0
269
+
270
+/*
271
+ * Pinctrl enable
272
+ * default: disable
273
+ */
274
+#define FTS_PINCTRL_EN 0
275
+
276
+/* power policy:
277
+ * FTS_POWER_SOURCE_CUST_EN,FTS_POWER_SUSPEND_OFF_EN
278
+ * 0,0:typically for IDC chip,not control power when probing and suspending.
279
+ * 0,1:only for IDC,LCD driver sets IDC power to off when suspending,so need
280
+ * set tp_rst pin to low in tp driver.
281
+ * 1,0:typically for OLED touch chip, not set power to off when suspending.
282
+ * 1,1:typically for touch chip,control power when probing and suspending.
283
+ */
284
+/*
285
+ * Customer power enable
286
+ * enable it when customer need control TP power
287
+ * default: disable
288
+ */
289
+#define FTS_POWER_SOURCE_CUST_EN 0
290
+
291
+/* Set power to off state when entering into suspend
292
+ * default:disable
293
+ */
294
+#define FTS_POWER_SUSPEND_OFF_EN 0
295
+
296
+
297
+/****************************************************/
298
+
299
+/********************** Upgrade ****************************/
300
+/*
301
+ * auto upgrade
302
+ */
303
+#define FTS_AUTO_UPGRADE_EN 1
304
+
305
+/* for none flash project, set it to be the using FW number */
306
+#define FTS_MULTI_FW_NUM 0
307
+
308
+/*
309
+ * auto upgrade for lcd cfg
310
+ */
311
+#define FTS_AUTO_LIC_UPGRADE_EN 0
312
+
313
+/*
314
+ * Numbers of modules support
315
+ */
316
+#define FTS_GET_MODULE_NUM 0
317
+
318
+/*
319
+ * module_id: mean vendor_id generally, also maybe gpio or lcm_id...
320
+ * If means vendor_id, the FTS_MODULE_ID = PANEL_ID << 8 + VENDOR_ID
321
+ * FTS_GET_MODULE_NUM == 0/1, no check module id, you may ignore them
322
+ * FTS_GET_MODULE_NUM >= 2, compatible with FTS_MODULE2_ID
323
+ * FTS_GET_MODULE_NUM >= 3, compatible with FTS_MODULE3_ID
324
+ */
325
+#define FTS_MODULE_ID 0x0000
326
+#define FTS_MODULE2_ID 0x0000
327
+#define FTS_MODULE3_ID 0x0000
328
+
329
+/*
330
+ * Need set the following when get firmware via firmware_request()
331
+ * For example: if module'vendor is tianma,
332
+ * #define FTS_MODULE_NAME "tianma"
333
+ * then file_name will be "focaltech_ts_fw_tianma"
334
+ * You should rename fw to "focaltech_ts_fw_tianma", and push it into
335
+ * etc/firmware or by customers
336
+ */
337
+#define FTS_MODULE_NAME ""
338
+#define FTS_MODULE2_NAME ""
339
+#define FTS_MODULE3_NAME ""
340
+
341
+/*
342
+ * FW.i file for auto upgrade, you must replace it with your own
343
+ * define your own fw_file, the sample one to be replaced is invalid
344
+ * NOTE: if FTS_GET_MODULE_NUM > 1, it's the fw corresponding with FTS_MODULE_ID
345
+ */
346
+#define FTS_UPGRADE_FW_FILE "include/firmware/fw_sample.i"
347
+
348
+/*
349
+ * if FTS_GET_MODULE_NUM >= 2, fw corrsponding with FTS_MODULE2_ID
350
+ * define your own fw_file, the sample one is invalid
351
+ */
352
+#define FTS_UPGRADE_FW2_FILE "include/firmware/fw_sample.i"
353
+
354
+/*
355
+ * if FTS_GET_MODULE_NUM >= 3, fw corrsponding with FTS_MODULE3_ID
356
+ * define your own fw_file, the sample one is invalid
357
+ */
358
+#define FTS_UPGRADE_FW3_FILE "include/firmware/fw_sample.i"
359
+
360
+/*********************************************************/
361
+
362
+#endif /* _LINUX_FOCLATECH_CONFIG_H_ */
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_core.c
....@@ -0,0 +1,2411 @@
1
+/*
2
+ *
3
+ * FocalTech TouchScreen driver.
4
+ *
5
+ * Copyright (c) 2012-2020, FocalTech Systems, Ltd., all rights reserved.
6
+ *
7
+ * This software is licensed under the terms of the GNU General Public
8
+ * License version 2, as published by the Free Software Foundation, and
9
+ * may be copied, distributed, and modified under those terms.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ */
17
+/*****************************************************************************
18
+*
19
+* File Name: focaltech_core.c
20
+*
21
+* Author: Focaltech Driver Team
22
+*
23
+* Created: 2016-08-08
24
+*
25
+* Abstract: entrance for focaltech ts driver
26
+*
27
+* Version: V1.0
28
+*
29
+*****************************************************************************/
30
+
31
+/*****************************************************************************
32
+* Included header files
33
+*****************************************************************************/
34
+#include <linux/of.h>
35
+#include <linux/of_device.h>
36
+#include <linux/of_gpio.h>
37
+#include <linux/of_irq.h>
38
+
39
+// #if IS_ENABLED(CONFIG_DRM)
40
+// #if IS_ENABLED(CONFIG_DRM_PANEL)
41
+// #include <drm/drm_panel.h>
42
+// #else
43
+// #include <linux/msm_drm_notify.h>
44
+// #endif //CONFIG_DRM_PANEL
45
+
46
+// #elif IS_ENABLED(CONFIG_FB)
47
+// #include <linux/notifier.h>
48
+// #include <linux/fb.h>
49
+// #endif //CONFIG_DRM
50
+#include "focaltech_core.h"
51
+
52
+/*****************************************************************************
53
+* Private constant and macro definitions using #define
54
+*****************************************************************************/
55
+#define FTS_DRIVER_PEN_NAME "fts_ts,pen"
56
+
57
+#if FTS_POWER_SOURCE_CUST_EN
58
+#define FTS_VTG_MIN_UV 2800000
59
+#define FTS_VTG_MAX_UV 3300000
60
+#define FTS_IOVCC_VTG_MIN_UV 1800000
61
+#define FTS_IOVCC_VTG_MAX_UV 1800000
62
+#endif
63
+
64
+#define FTS_WAKELOCK_TIMEOUT 5000
65
+
66
+/*****************************************************************************
67
+* Global variable or extern global variabls/functions
68
+*****************************************************************************/
69
+struct fts_ts_data *fts_data;
70
+
71
+#if FTS_FOD_EN
72
+static int fts_fod_recovery(struct fts_ts_data *ts_data);
73
+#endif
74
+
75
+/*****************************************************************************
76
+* Static function prototypes
77
+*****************************************************************************/
78
+void fts_msleep(unsigned long msecs)
79
+{
80
+ if (msecs > 20) {
81
+ msleep(msecs);
82
+ } else if (msecs > 0) {
83
+ usleep_range(msecs * 1000, (msecs + 2) * 1000);
84
+ }
85
+}
86
+
87
+int fts_check_cid(struct fts_ts_data *ts_data, u8 id_h)
88
+{
89
+ int i = 0;
90
+ struct ft_chip_id_t *cid = &ts_data->ic_info.cid;
91
+ u8 cid_h = 0x0;
92
+
93
+ if (cid->type == 0)
94
+ return -ENODATA;
95
+
96
+ for (i = 0; i < FTS_MAX_CHIP_IDS; i++) {
97
+ cid_h = ((cid->chip_ids[i] >> 8) & 0x00FF);
98
+ if (cid_h && (id_h == cid_h)) {
99
+ return 0;
100
+ }
101
+ }
102
+
103
+ return -ENODATA;
104
+}
105
+
106
+/*****************************************************************************
107
+* Name: fts_wait_tp_to_valid
108
+* Brief: Read chip id until TP FW become valid(Timeout: TIMEOUT_READ_REG),
109
+* need call when reset/power on/resume...
110
+* Input:
111
+* Output:
112
+* Return: return 0 if tp valid, otherwise return error code
113
+*****************************************************************************/
114
+int fts_wait_tp_to_valid(void)
115
+{
116
+ int ret = 0;
117
+ int i = 0;
118
+ u8 idh = 0xFF;
119
+ struct fts_ts_data *ts_data = fts_data;
120
+ u8 chip_idh = ts_data->ic_info.ids.chip_idh;
121
+
122
+ for (i = 0; i < FTS_MAX_RETRIES_READID; i++) {
123
+ ret = fts_read_reg(FTS_REG_CHIP_ID, &idh);
124
+ if ((idh == chip_idh) || (fts_check_cid(ts_data, idh) == 0)) {
125
+ FTS_INFO("TP Ready,Device ID:0x%02x", idh);
126
+ return 0;
127
+ }
128
+ if ((i + 1) < FTS_MAX_RETRIES_READID) fts_msleep((i + 1) * 20);
129
+ }
130
+
131
+ FTS_ERROR("TP Not Ready,ReadData:0x%02x,ret:%d", idh, ret);
132
+ return -EIO;
133
+}
134
+
135
+/*****************************************************************************
136
+* Name: fts_tp_state_recovery
137
+* Brief: Need execute this function when reset
138
+* Input:
139
+* Output:
140
+* Return:
141
+*****************************************************************************/
142
+void fts_tp_state_recovery(struct fts_ts_data *ts_data)
143
+{
144
+ fts_wait_tp_to_valid();
145
+ fts_ex_mode_recovery(ts_data);
146
+#if FTS_PSENSOR_EN
147
+ if (ts_data->proximity_mode) {
148
+ fts_proximity_recovery(ts_data);
149
+ return;
150
+ }
151
+#endif
152
+#if FTS_FOD_EN
153
+ fts_fod_recovery(ts_data);
154
+#endif
155
+ fts_gesture_recovery(ts_data);
156
+}
157
+
158
+static int fts_reset_pre(struct fts_ts_data *ts_data, int value)
159
+{
160
+ u16 ic_type = ts_data->ic_info.ids.type;
161
+ if (!value) {
162
+ if ((ic_type == 0x90) || (ic_type == 0x92) || (ic_type == 0x93)) {
163
+ if (!ts_data->power_disabled) {
164
+ FTS_DEBUG("write regb6");
165
+ fts_write_reg(0xB6, 1);
166
+ fts_msleep(20);
167
+ }
168
+ }
169
+ }
170
+ return 0;
171
+}
172
+
173
+static int fts_reset_post(struct fts_ts_data *ts_data, int value)
174
+{
175
+
176
+ return 0;
177
+}
178
+
179
+int fts_set_reset(struct fts_ts_data *ts_data, int value)
180
+{
181
+ int ret = 0;
182
+
183
+ FTS_INFO("set reset to %d", !!value);
184
+ fts_reset_pre(ts_data, value);
185
+ ret = gpio_direction_output(ts_data->pdata->reset_gpio, !!value);
186
+ if (ret) {
187
+ FTS_ERROR("[GPIO]set reset gpio to %d failed", !!value);
188
+ return ret;
189
+ }
190
+ fts_reset_post(ts_data, value);
191
+ return 0;
192
+}
193
+
194
+int fts_reset_proc(struct fts_ts_data *ts_data, int force, int hdelayms)
195
+{
196
+ if (force || (!ts_data->fw_loading)) {
197
+ fts_set_reset(ts_data, 0);
198
+ fts_msleep(2);
199
+ fts_set_reset(ts_data, 1);
200
+ if (hdelayms) fts_msleep(hdelayms);
201
+ } else {
202
+ FTS_INFO("fw upgrade in process, no reset");
203
+ }
204
+
205
+ return 0;
206
+}
207
+
208
+void fts_irq_disable(void)
209
+{
210
+ unsigned long irqflags;
211
+
212
+ FTS_FUNC_ENTER();
213
+ spin_lock_irqsave(&fts_data->irq_lock, irqflags);
214
+
215
+ if (!fts_data->irq_disabled) {
216
+ disable_irq_nosync(fts_data->irq);
217
+ fts_data->irq_disabled = true;
218
+ }
219
+
220
+ spin_unlock_irqrestore(&fts_data->irq_lock, irqflags);
221
+ FTS_FUNC_EXIT();
222
+}
223
+
224
+void fts_irq_enable(void)
225
+{
226
+ unsigned long irqflags = 0;
227
+
228
+ FTS_FUNC_ENTER();
229
+ spin_lock_irqsave(&fts_data->irq_lock, irqflags);
230
+
231
+ if (fts_data->irq_disabled) {
232
+ enable_irq(fts_data->irq);
233
+ fts_data->irq_disabled = false;
234
+ }
235
+
236
+ spin_unlock_irqrestore(&fts_data->irq_lock, irqflags);
237
+ FTS_FUNC_EXIT();
238
+}
239
+
240
+int fts_hid2std(int mode)
241
+{
242
+ int ret = 0;
243
+ u8 buf[3] = {0xEB, 0xAA, 0x09};
244
+ u8 val[3] = { 0 };
245
+
246
+ if (fts_data->bus_type != BUS_TYPE_I2C)
247
+ return 0;
248
+
249
+ if (mode == 1) {
250
+ /* Don't need delay */
251
+ ret = fts_read(buf, 3, val, 3);
252
+ if (ret < 0) {
253
+ FTS_ERROR("send hid2std cmd failed");
254
+ return ret;
255
+ }
256
+ } else {
257
+ ret = fts_write(buf, 3);
258
+ if (ret < 0) {
259
+ FTS_ERROR("hid2std cmd write fail");
260
+ return ret;
261
+ }
262
+
263
+ fts_msleep(10);
264
+ ret = fts_read(NULL, 0, val, 3);
265
+ if (ret < 0) {
266
+ FTS_ERROR("hid2std cmd read fail");
267
+ return ret;
268
+ }
269
+ }
270
+
271
+ if ((0xEB == val[0]) && (0xAA == val[1]) && (0x08 == val[2])) {
272
+ FTS_INFO("hidi2c change to stdi2c successful");
273
+ } else {
274
+ FTS_INFO("hidi2c change to stdi2c not support or fail");
275
+ }
276
+ return 0;
277
+}
278
+
279
+static int fts_match_cid(struct fts_ts_data *ts_data,
280
+ u16 type, u8 id_h, u8 id_l, bool force)
281
+{
282
+#ifdef FTS_CHIP_ID_MAPPING
283
+ u32 i = 0;
284
+ u32 j = 0;
285
+ struct ft_chip_id_t chip_id_list[] = FTS_CHIP_ID_MAPPING;
286
+ u32 cid_entries = sizeof(chip_id_list) / sizeof(struct ft_chip_id_t);
287
+ u16 id = (id_h << 8) + id_l;
288
+
289
+ memset(&ts_data->ic_info.cid, 0, sizeof(struct ft_chip_id_t));
290
+ for (i = 0; i < cid_entries; i++) {
291
+ if (!force && (type == chip_id_list[i].type)) {
292
+ break;
293
+ } else if (force && (type == chip_id_list[i].type)) {
294
+ FTS_INFO("match cid,type:0x%x", (int)chip_id_list[i].type);
295
+ ts_data->ic_info.cid = chip_id_list[i];
296
+ return 0;
297
+ }
298
+ }
299
+
300
+ if (i >= cid_entries) {
301
+ return -ENODATA;
302
+ }
303
+
304
+ for (j = 0; j < FTS_MAX_CHIP_IDS; j++) {
305
+ if (id == chip_id_list[i].chip_ids[j]) {
306
+ FTS_DEBUG("cid:%x==%x", id, chip_id_list[i].chip_ids[j]);
307
+ FTS_INFO("match cid,type:0x%x", (int)chip_id_list[i].type);
308
+ ts_data->ic_info.cid = chip_id_list[i];
309
+ return 0;
310
+ }
311
+ }
312
+
313
+ return -ENODATA;
314
+#else
315
+ return -EINVAL;
316
+#endif
317
+}
318
+
319
+
320
+static int fts_get_chip_types(
321
+ struct fts_ts_data *ts_data,
322
+ u8 id_h, u8 id_l, bool fw_valid)
323
+{
324
+ u32 i = 0;
325
+ struct ft_chip_t ctype[] = FTS_CHIP_TYPE_MAPPING;
326
+ u32 ctype_entries = sizeof(ctype) / sizeof(struct ft_chip_t);
327
+
328
+ if ((0x0 == id_h) || (0x0 == id_l)) {
329
+ FTS_ERROR("id_h/id_l is 0");
330
+ return -EINVAL;
331
+ }
332
+
333
+ FTS_INFO("verify id:0x%02x%02x", id_h, id_l);
334
+ for (i = 0; i < ctype_entries; i++) {
335
+ if (VALID == fw_valid) {
336
+ if (((id_h == ctype[i].chip_idh) && (id_l == ctype[i].chip_idl))
337
+ || (!fts_match_cid(ts_data, ctype[i].type, id_h, id_l, 0)))
338
+ break;
339
+ } else {
340
+ if (((id_h == ctype[i].rom_idh) && (id_l == ctype[i].rom_idl))
341
+ || ((id_h == ctype[i].pb_idh) && (id_l == ctype[i].pb_idl))
342
+ || ((id_h == ctype[i].bl_idh) && (id_l == ctype[i].bl_idl))) {
343
+ break;
344
+ }
345
+ }
346
+ }
347
+
348
+ if (i >= ctype_entries) {
349
+ return -ENODATA;
350
+ }
351
+
352
+ fts_match_cid(ts_data, ctype[i].type, id_h, id_l, 1);
353
+ ts_data->ic_info.ids = ctype[i];
354
+ return 0;
355
+}
356
+
357
+static int fts_read_bootid(struct fts_ts_data *ts_data, u8 *id)
358
+{
359
+ int ret = 0;
360
+ u8 chip_id[2] = { 0 };
361
+ u8 id_cmd[4] = { 0 };
362
+ u32 id_cmd_len = 0;
363
+
364
+ id_cmd[0] = FTS_CMD_START1;
365
+ id_cmd[1] = FTS_CMD_START2;
366
+ ret = fts_write(id_cmd, 2);
367
+ if (ret < 0) {
368
+ FTS_ERROR("start cmd write fail");
369
+ return ret;
370
+ }
371
+
372
+ fts_msleep(FTS_CMD_START_DELAY);
373
+ id_cmd[0] = FTS_CMD_READ_ID;
374
+ id_cmd[1] = id_cmd[2] = id_cmd[3] = 0x00;
375
+ if (ts_data->ic_info.is_incell)
376
+ id_cmd_len = FTS_CMD_READ_ID_LEN_INCELL;
377
+ else
378
+ id_cmd_len = FTS_CMD_READ_ID_LEN;
379
+ ret = fts_read(id_cmd, id_cmd_len, chip_id, 2);
380
+ if ((ret < 0) || (0x0 == chip_id[0]) || (0x0 == chip_id[1])) {
381
+ FTS_ERROR("read boot id fail,read:0x%02x%02x", chip_id[0], chip_id[1]);
382
+ return -EIO;
383
+ }
384
+
385
+ id[0] = chip_id[0];
386
+ id[1] = chip_id[1];
387
+ return 0;
388
+}
389
+
390
+/*****************************************************************************
391
+* Name: fts_get_ic_information
392
+* Brief: read chip id to get ic information, after run the function, driver w-
393
+* ill know which IC is it.
394
+* If cant get the ic information, maybe not focaltech's touch IC, need
395
+* unregister the driver
396
+* Input:
397
+* Output:
398
+* Return: return 0 if get correct ic information, otherwise return error code
399
+*****************************************************************************/
400
+static int fts_get_ic_information(struct fts_ts_data *ts_data)
401
+{
402
+ int ret = 0;
403
+ int cnt = 0;
404
+ u8 chip_id[2] = { 0 };
405
+
406
+ ts_data->ic_info.is_incell = FTS_CHIP_IDC;
407
+ ts_data->ic_info.hid_supported = FTS_HID_SUPPORTTED;
408
+
409
+
410
+ do {
411
+ ret = fts_read_reg(FTS_REG_CHIP_ID, &chip_id[0]);
412
+ ret = fts_read_reg(FTS_REG_CHIP_ID2, &chip_id[1]);
413
+ if ((ret < 0) || (0x0 == chip_id[0]) || (0x0 == chip_id[1])) {
414
+ FTS_INFO("chip id read invalid, read:0x%02x%02x",
415
+ chip_id[0], chip_id[1]);
416
+ } else {
417
+ ret = fts_get_chip_types(ts_data, chip_id[0], chip_id[1], VALID);
418
+ if (!ret)
419
+ break;
420
+ else
421
+ FTS_INFO("TP not ready, read:0x%02x%02x",
422
+ chip_id[0], chip_id[1]);
423
+ }
424
+
425
+ cnt++;
426
+ fts_msleep(INTERVAL_READ_REG);
427
+ } while ((cnt * INTERVAL_READ_REG) < TIMEOUT_READ_REG);
428
+
429
+ if ((cnt * INTERVAL_READ_REG) >= TIMEOUT_READ_REG) {
430
+ FTS_INFO("fw is invalid, need read boot id");
431
+ for (cnt = 0; cnt < FTS_MAX_RETRIES_READ_BOOTID; cnt++) {
432
+ if (cnt < 2) {
433
+ if (ts_data->ic_info.hid_supported) fts_hid2std(0);
434
+ } else {
435
+ fts_reset_proc(ts_data, true, 0);
436
+ mdelay(FTS_CMD_START_DELAY + (cnt - 2) * 8);
437
+ if (ts_data->ic_info.hid_supported) {
438
+ fts_hid2std(1);
439
+ fts_write_reg(0x55, 0xAA);
440
+ fts_msleep(FTS_CMD_START_DELAY);
441
+ fts_hid2std(1);
442
+ }
443
+ }
444
+
445
+ ret = fts_read_bootid(ts_data, &chip_id[0]);
446
+ if (ret < 0) {
447
+ FTS_ERROR("read boot id fail");
448
+ continue;
449
+ }
450
+
451
+ ret = fts_get_chip_types(ts_data, chip_id[0], chip_id[1], INVALID);
452
+ if (ret < 0) {
453
+ FTS_ERROR("can't get ic informaton");
454
+ continue;
455
+ }
456
+ break;
457
+ }
458
+ }
459
+
460
+ FTS_INFO("get ic information, chip id = 0x%02x%02x(cid type=0x%x)",
461
+ ts_data->ic_info.ids.chip_idh, ts_data->ic_info.ids.chip_idl,
462
+ ts_data->ic_info.cid.type);
463
+
464
+ return ret;
465
+}
466
+
467
+#if FTS_READ_CUSTOMER_INFO
468
+static int fts_read_customer_information(struct fts_ts_data *ts_data)
469
+{
470
+ /* If some customer's code had written to touch chip, please do the followings:
471
+ * Step 1: read customer information here.
472
+ * Step 2: save customer information to ts_data->customer_info variable, maximum 32.
473
+ * Step 3: return ts_data->customer_info to APP via sysfs node.
474
+ *
475
+ * Warning: please check the information is read from FW or not, if from FW, please
476
+ * take care that FW maybe isn't valid.
477
+ */
478
+
479
+
480
+ FTS_INFO("customer info:%s", ts_data->customer_info);
481
+ return 0;
482
+}
483
+#endif
484
+
485
+#if FTS_FOD_EN
486
+static void fts_fod_set_reg(int value)
487
+{
488
+ int i = 0;
489
+ u8 fod_val = value ? FTS_VAL_FOD_ENABLE : DISABLE;
490
+ u8 regval = 0xFF;
491
+
492
+ for (i = 0; i < FTS_MAX_RETRIES_WRITEREG; i++) {
493
+ fts_read_reg(FTS_REG_FOD_MODE_EN, &regval);
494
+ if (regval == fod_val)
495
+ break;
496
+ fts_write_reg(FTS_REG_FOD_MODE_EN, fod_val);
497
+ fts_msleep(1);
498
+ }
499
+
500
+ if (i >= FTS_MAX_RETRIES_WRITEREG)
501
+ FTS_ERROR("set fod mode to %x failed,reg_val:%x", fod_val, regval);
502
+ else if (i > 0)
503
+ FTS_INFO("set fod mode to %x successfully", fod_val);
504
+}
505
+
506
+void fts_fod_enable(int enable)
507
+{
508
+ struct fts_ts_data *ts_data = fts_data;
509
+
510
+ ts_data->fod_fp_down = false;
511
+ if (enable) {
512
+ FTS_INFO("Fod enable");
513
+ ts_data->fod_mode = ENABLE;
514
+ fts_fod_set_reg(FTS_VAL_FOD_ENABLE);
515
+ } else {
516
+ FTS_INFO("Fod disable");
517
+ ts_data->fod_mode = DISABLE;
518
+ fts_fod_set_reg(DISABLE);
519
+ }
520
+}
521
+
522
+/*****************************************************************************
523
+* Name: fts_fod_readdata
524
+* Brief: read fod value from TP, check whether having FOD event or not,
525
+* and report the state to host if need.
526
+*
527
+* Input: ts_data
528
+* Output:
529
+* Return: return negative code if error occurs,return 0 or 1 if success.
530
+* return 0 if continue report finger touches.
531
+* return 1(FTS_RETVAL_IGNORE_TOUCHES) if you want to ingore this
532
+* finger reporting, As default, the following situation will report 1:
533
+* a.System in suspend state, now not handle gesture.
534
+*****************************************************************************/
535
+static int fts_fod_readdata(struct fts_ts_data *ts_data)
536
+{
537
+ int ret = 0;
538
+ int fod_x = 0;
539
+ int fod_y = 0;
540
+ int fod_pointid = 0;
541
+ int fod_down = 0;
542
+ u8 fod_val[FTS_FOD_BUF_LEN] = { 0 };
543
+ u8 fod_cmd = FTS_REG_FOD_DATA;
544
+
545
+ ret = fts_read(&fod_cmd, 1, fod_val, FTS_FOD_BUF_LEN);
546
+ if (ret < 0) {
547
+ FTS_ERROR("read fod data failed,ret=%d", ret);
548
+ return ret;
549
+ }
550
+
551
+ if (fod_val[1] == 0x26) {
552
+ fod_pointid = fod_val[0];
553
+ fod_x = (fod_val[4] << 8) + fod_val[5];
554
+ fod_y = (fod_val[6] << 8) + fod_val[7];
555
+ fod_down = (fod_val[8] == 0) ? 1 : 0;
556
+ FTS_DEBUG("FOD data:%x %x %x %x[%x,%x][%x]", fod_val[0], fod_val[1],
557
+ fod_val[2], fod_val[3], fod_x, fod_x, fod_val[8]);
558
+ if (fod_down) {
559
+ /* FOD down, need do something to tell host */
560
+ ts_data->fod_fp_down = true;
561
+ } else {
562
+ /* FOD up, need do something to tell host */
563
+ ts_data->fod_fp_down = false;
564
+ }
565
+
566
+ ret = (ts_data->suspended) ? FTS_RETVAL_IGNORE_TOUCHES : 0;
567
+ } else {
568
+ ret = 0;
569
+ }
570
+
571
+ return ret;
572
+}
573
+
574
+static int fts_fod_recovery(struct fts_ts_data *ts_data)
575
+{
576
+ if (ts_data->fod_mode) {
577
+ fts_fod_set_reg(FTS_VAL_FOD_ENABLE);
578
+ }
579
+ return 0;
580
+}
581
+
582
+/*****************************************************************************
583
+* Name: fts_fod_checkdown
584
+* Brief: check fod down event is triggered, it's used to reset TP or not when
585
+* resuming.
586
+*
587
+* Input: ts_data
588
+* Output:
589
+* Return: return 1 if having fod down event, or else return 0
590
+*****************************************************************************/
591
+static int fts_fod_checkdown(struct fts_ts_data *ts_data)
592
+{
593
+ return (ts_data->fod_mode && ts_data->fod_fp_down);
594
+}
595
+
596
+static int fts_fod_suspend(struct fts_ts_data *ts_data)
597
+{
598
+ ts_data->fod_fp_down = false;
599
+ fts_fod_set_reg(FTS_VAL_FOD_ENABLE);
600
+ return 0;
601
+}
602
+
603
+static int fts_fod_resume(struct fts_ts_data *ts_data)
604
+{
605
+ if (!fts_fod_checkdown(ts_data)) fts_fod_set_reg(FTS_VAL_FOD_ENABLE);
606
+ ts_data->fod_fp_down = false;
607
+ return 0;
608
+}
609
+#endif
610
+
611
+/*****************************************************************************
612
+* Reprot related
613
+*****************************************************************************/
614
+static void fts_show_touch_buffer(u8 *data, u32 datalen)
615
+{
616
+ u32 i = 0;
617
+ u32 count = 0;
618
+ char *tmpbuf = NULL;
619
+
620
+ tmpbuf = kzalloc(1024, GFP_KERNEL);
621
+ if (!tmpbuf) {
622
+ FTS_ERROR("tmpbuf zalloc fail");
623
+ return;
624
+ }
625
+
626
+ for (i = 0; i < datalen; i++) {
627
+ count += snprintf(tmpbuf + count, 1024 - count, "%02X,", data[i]);
628
+ if (count >= 1024)
629
+ break;
630
+ }
631
+ FTS_DEBUG("touch_buf:%s", tmpbuf);
632
+
633
+ if (tmpbuf) {
634
+ kfree(tmpbuf);
635
+ tmpbuf = NULL;
636
+ }
637
+}
638
+
639
+void fts_release_all_finger(void)
640
+{
641
+ struct fts_ts_data *ts_data = fts_data;
642
+ struct input_dev *input_dev = ts_data->input_dev;
643
+#if FTS_MT_PROTOCOL_B_EN
644
+ u32 finger_count = 0;
645
+ u32 max_touches = ts_data->pdata->max_touch_number;
646
+#endif
647
+
648
+ mutex_lock(&ts_data->report_mutex);
649
+#if FTS_MT_PROTOCOL_B_EN
650
+ for (finger_count = 0; finger_count < max_touches; finger_count++) {
651
+ input_mt_slot(input_dev, finger_count);
652
+ input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, false);
653
+ }
654
+#else
655
+ input_mt_sync(input_dev);
656
+#endif
657
+ input_report_key(input_dev, BTN_TOUCH, 0);
658
+ input_sync(input_dev);
659
+
660
+#if FTS_PEN_EN
661
+ input_report_key(ts_data->pen_dev, BTN_TOOL_PEN, 0);
662
+ input_report_key(ts_data->pen_dev, BTN_TOUCH, 0);
663
+ input_sync(ts_data->pen_dev);
664
+#endif
665
+
666
+ ts_data->touch_points = 0;
667
+ ts_data->key_state = 0;
668
+ mutex_unlock(&ts_data->report_mutex);
669
+}
670
+
671
+/*****************************************************************************
672
+* Name: fts_input_report_key
673
+* Brief: process key events,need report key-event if key enable.
674
+* if point's coordinate is in (x_dim-50,y_dim-50) ~ (x_dim+50,y_dim+50),
675
+* need report it to key event.
676
+* x_dim: parse from dts, means key x_coordinate, dimension:+-50
677
+* y_dim: parse from dts, means key y_coordinate, dimension:+-50
678
+* Input:
679
+* Output:
680
+* Return: return 0 if it's key event, otherwise return error code
681
+*****************************************************************************/
682
+static int fts_input_report_key(struct fts_ts_data *ts_data, struct ts_event *kevent)
683
+{
684
+ int i = 0;
685
+ int x = kevent->x;
686
+ int y = kevent->y;
687
+ int *x_dim = &ts_data->pdata->key_x_coords[0];
688
+ int *y_dim = &ts_data->pdata->key_y_coords[0];
689
+
690
+ if (!ts_data->pdata->have_key) {
691
+ return -EINVAL;
692
+ }
693
+ for (i = 0; i < ts_data->pdata->key_number; i++) {
694
+ if ((x >= x_dim[i] - FTS_KEY_DIM) && (x <= x_dim[i] + FTS_KEY_DIM) &&
695
+ (y >= y_dim[i] - FTS_KEY_DIM) && (y <= y_dim[i] + FTS_KEY_DIM)) {
696
+ if (EVENT_DOWN(kevent->flag)
697
+ && !(ts_data->key_state & (1 << i))) {
698
+ input_report_key(ts_data->input_dev, ts_data->pdata->keys[i], 1);
699
+ ts_data->key_state |= (1 << i);
700
+ FTS_DEBUG("Key%d(%d,%d) DOWN!", i, x, y);
701
+ } else if (EVENT_UP(kevent->flag)
702
+ && (ts_data->key_state & (1 << i))) {
703
+ input_report_key(ts_data->input_dev, ts_data->pdata->keys[i], 0);
704
+ ts_data->key_state &= ~(1 << i);
705
+ FTS_DEBUG("Key%d(%d,%d) Up!", i, x, y);
706
+ }
707
+ return 0;
708
+ }
709
+ }
710
+ return -EINVAL;
711
+}
712
+
713
+#if FTS_MT_PROTOCOL_B_EN
714
+static int fts_input_report_b(struct fts_ts_data *ts_data, struct ts_event *events)
715
+{
716
+ int i = 0;
717
+ int touch_down_point_cur = 0;
718
+ int touch_point_pre = ts_data->touch_points;
719
+ u32 max_touch_num = ts_data->pdata->max_touch_number;
720
+ bool touch_event_coordinate = false;
721
+ struct input_dev *input_dev = ts_data->input_dev;
722
+
723
+ for (i = 0; i < ts_data->touch_event_num; i++) {
724
+ if (fts_input_report_key(ts_data, &events[i]) == 0) {
725
+ continue;
726
+ }
727
+
728
+ touch_event_coordinate = true;
729
+ if (EVENT_DOWN(events[i].flag)) {
730
+ input_mt_slot(input_dev, events[i].id);
731
+ input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, true);
732
+#if FTS_REPORT_PRESSURE_EN
733
+ input_report_abs(input_dev, ABS_MT_PRESSURE, events[i].p);
734
+#endif
735
+ input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, events[i].area);
736
+ input_report_abs(input_dev, ABS_MT_TOUCH_MINOR, events[i].minor);
737
+
738
+ input_report_abs(input_dev, ABS_MT_POSITION_X, events[i].x);
739
+ input_report_abs(input_dev, ABS_MT_POSITION_Y, events[i].y);
740
+
741
+ touch_down_point_cur |= (1 << events[i].id);
742
+ touch_point_pre |= (1 << events[i].id);
743
+
744
+ if ((ts_data->log_level >= 2) ||
745
+ ((1 == ts_data->log_level) && (FTS_TOUCH_DOWN == events[i].flag))) {
746
+ FTS_DEBUG("[B]P%d(%d, %d)[p:%d,tm:%d] DOWN!",
747
+ events[i].id, events[i].x, events[i].y,
748
+ events[i].p, events[i].area);
749
+ }
750
+ } else {
751
+ input_mt_slot(input_dev, events[i].id);
752
+ input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, false);
753
+ touch_point_pre &= ~(1 << events[i].id);
754
+ if (ts_data->log_level >= 1) FTS_DEBUG("[B]P%d UP!", events[i].id);
755
+ }
756
+ }
757
+
758
+ if (unlikely(touch_point_pre ^ touch_down_point_cur)) {
759
+ for (i = 0; i < max_touch_num; i++) {
760
+ if ((1 << i) & (touch_point_pre ^ touch_down_point_cur)) {
761
+ if (ts_data->log_level >= 1) FTS_DEBUG("[B]P%d UP!", i);
762
+ input_mt_slot(input_dev, i);
763
+ input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, false);
764
+ }
765
+ }
766
+ }
767
+
768
+ if (touch_down_point_cur)
769
+ input_report_key(input_dev, BTN_TOUCH, 1);
770
+ else if (touch_event_coordinate || ts_data->touch_points) {
771
+ if (ts_data->touch_points && (ts_data->log_level >= 1))
772
+ FTS_DEBUG("[B]Points All Up!");
773
+ input_report_key(input_dev, BTN_TOUCH, 0);
774
+ }
775
+
776
+ ts_data->touch_points = touch_down_point_cur;
777
+ input_sync(input_dev);
778
+ return 0;
779
+}
780
+#else
781
+static int fts_input_report_a(struct fts_ts_data *ts_data, struct ts_event *events)
782
+{
783
+ int i = 0;
784
+ int touch_down_point_num_cur = 0;
785
+ bool touch_event_coordinate = false;
786
+ struct input_dev *input_dev = ts_data->input_dev;
787
+
788
+ for (i = 0; i < ts_data->touch_event_num; i++) {
789
+ if (fts_input_report_key(ts_data, &events[i]) == 0) {
790
+ continue;
791
+ }
792
+
793
+ touch_event_coordinate = true;
794
+ if (EVENT_DOWN(events[i].flag)) {
795
+ input_report_abs(input_dev, ABS_MT_TRACKING_ID, events[i].id);
796
+#if FTS_REPORT_PRESSURE_EN
797
+ input_report_abs(input_dev, ABS_MT_PRESSURE, events[i].p);
798
+#endif
799
+ input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, events[i].area);
800
+ input_report_abs(input_dev, ABS_MT_TOUCH_MINOR, events[i].minor);
801
+
802
+ input_report_abs(input_dev, ABS_MT_POSITION_X, events[i].x);
803
+ input_report_abs(input_dev, ABS_MT_POSITION_Y, events[i].y);
804
+ input_mt_sync(input_dev);
805
+
806
+ touch_down_point_num_cur++;
807
+ if ((ts_data->log_level >= 2) ||
808
+ ((1 == ts_data->log_level) && (FTS_TOUCH_DOWN == events[i].flag))) {
809
+ FTS_DEBUG("[A]P%d(%d, %d)[p:%d,tm:%d] DOWN!",
810
+ events[i].id, events[i].x, events[i].y,
811
+ events[i].p, events[i].area);
812
+ }
813
+ }
814
+ }
815
+
816
+ if (touch_down_point_num_cur)
817
+ input_report_key(input_dev, BTN_TOUCH, 1);
818
+ else if (touch_event_coordinate || ts_data->touch_points) {
819
+ if (ts_data->touch_points && (ts_data->log_level >= 1))
820
+ FTS_DEBUG("[A]Points All Up!");
821
+ input_report_key(input_dev, BTN_TOUCH, 0);
822
+ input_mt_sync(input_dev);
823
+ }
824
+
825
+ ts_data->touch_points = touch_down_point_num_cur;
826
+ input_sync(input_dev);
827
+ return 0;
828
+}
829
+#endif
830
+
831
+#if FTS_PEN_EN
832
+static int fts_input_pen_report(struct fts_ts_data *ts_data, u8 *pen_buf)
833
+{
834
+ struct input_dev *pen_dev = ts_data->pen_dev;
835
+ struct pen_event *pevt = &ts_data->pevent;
836
+
837
+ /*get information of stylus*/
838
+ pevt->inrange = (pen_buf[2] & 0x20) ? 1 : 0;
839
+ pevt->tip = (pen_buf[2] & 0x01) ? 1 : 0;
840
+ pevt->flag = pen_buf[3] >> 6;
841
+#if FTS_PEN_HIRES_EN
842
+ pevt->id = 0;
843
+ pevt->x = ((u32)((pen_buf[3] & 0x0F) << 12) + (pen_buf[4] << 4) + ((pen_buf[5] >> 4) & 0x0F));
844
+ pevt->y = ((u32)((pen_buf[5] & 0x0F) << 12) + (pen_buf[6] << 4) + ((pen_buf[7] >> 4) & 0x0F));
845
+ pevt->x = (pevt->x * FTS_PEN_HIRES_X ) / FTS_HI_RES_X_MAX;
846
+ pevt->y = (pevt->y * FTS_PEN_HIRES_X ) / FTS_HI_RES_X_MAX;
847
+#else
848
+ pevt->id = pen_buf[5] >> 4;
849
+ pevt->x = ((pen_buf[3] & 0x0F) << 8) + pen_buf[4];
850
+ pevt->y = ((pen_buf[5] & 0x0F) << 8) + pen_buf[6];
851
+#endif
852
+ pevt->p = ((pen_buf[7] & 0x0F) << 8) + pen_buf[8];
853
+ pevt->tilt_x = (short)((pen_buf[9] << 8) + pen_buf[10]);
854
+ pevt->tilt_y = (short)((pen_buf[11] << 8) + pen_buf[12]);
855
+ pevt->azimuth = ((pen_buf[13] << 8) + pen_buf[14]);
856
+ pevt->tool_type = BTN_TOOL_PEN;
857
+
858
+ input_report_key(pen_dev, BTN_STYLUS, !!(pen_buf[2] & 0x02));
859
+ input_report_key(pen_dev, BTN_STYLUS2, !!(pen_buf[2] & 0x08));
860
+
861
+ switch (ts_data->pen_etype) {
862
+ case STYLUS_DEFAULT:
863
+ if (pevt->tip && pevt->p) {
864
+ if ((ts_data->log_level >= 2) || (!pevt->down))
865
+ FTS_DEBUG("[PEN]x:%d,y:%d,p:%d,tip:%d,flag:%d,tilt:%d,%d DOWN",
866
+ pevt->x, pevt->y, pevt->p, pevt->tip, pevt->flag,
867
+ pevt->tilt_x, pevt->tilt_y);
868
+ input_report_abs(pen_dev, ABS_X, pevt->x);
869
+ input_report_abs(pen_dev, ABS_Y, pevt->y);
870
+ input_report_abs(pen_dev, ABS_PRESSURE, pevt->p);
871
+ input_report_abs(pen_dev, ABS_TILT_X, pevt->tilt_x);
872
+ input_report_abs(pen_dev, ABS_TILT_Y, pevt->tilt_y);
873
+ input_report_key(pen_dev, BTN_TOUCH, 1);
874
+ input_report_key(pen_dev, BTN_TOOL_PEN, 1);
875
+ pevt->down = 1;
876
+ } else if (!pevt->tip && pevt->down) {
877
+ FTS_DEBUG("[PEN]x:%d,y:%d,p:%d,tip:%d,flag:%d,tilt:%d,%d UP",
878
+ pevt->x, pevt->y, pevt->p, pevt->tip, pevt->flag,
879
+ pevt->tilt_x, pevt->tilt_y);
880
+ input_report_abs(pen_dev, ABS_X, pevt->x);
881
+ input_report_abs(pen_dev, ABS_Y, pevt->y);
882
+ input_report_abs(pen_dev, ABS_PRESSURE, pevt->p);
883
+ input_report_key(pen_dev, BTN_TOUCH, 0);
884
+ input_report_key(pen_dev, BTN_TOOL_PEN, 0);
885
+ pevt->down = 0;
886
+ }
887
+ input_sync(pen_dev);
888
+ break;
889
+ case STYLUS_HOVER:
890
+ if (ts_data->log_level >= 1)
891
+ FTS_DEBUG("[PEN][%02X]x:%d,y:%d,p:%d,tip:%d,flag:%d,tilt:%d,%d,%d",
892
+ pen_buf[2], pevt->x, pevt->y, pevt->p, pevt->tip,
893
+ pevt->flag, pevt->tilt_x, pevt->tilt_y, pevt->azimuth);
894
+ input_report_abs(pen_dev, ABS_X, pevt->x);
895
+ input_report_abs(pen_dev, ABS_Y, pevt->y);
896
+ input_report_abs(pen_dev, ABS_Z, pevt->azimuth);
897
+ input_report_abs(pen_dev, ABS_PRESSURE, pevt->p);
898
+ input_report_abs(pen_dev, ABS_TILT_X, pevt->tilt_x);
899
+ input_report_abs(pen_dev, ABS_TILT_Y, pevt->tilt_y);
900
+ input_report_key(pen_dev, BTN_TOOL_PEN, EVENT_DOWN(pevt->flag));
901
+ input_report_key(pen_dev, BTN_TOUCH, pevt->tip);
902
+ input_sync(pen_dev);
903
+ break;
904
+ default:
905
+ FTS_ERROR("Unknown stylus event");
906
+ break;
907
+ }
908
+
909
+ return 0;
910
+}
911
+#endif
912
+
913
+static int fts_input_report_touch(struct fts_ts_data *ts_data, u8 *touch_buf)
914
+{
915
+ int i = 0;
916
+ int event_num = 0;
917
+ int finger_num = 0;
918
+ int pointid = 0;
919
+ int base = 0;
920
+ int max_touch_num = ts_data->pdata->max_touch_number;
921
+ struct ts_event *events = ts_data->events;
922
+
923
+ finger_num = touch_buf[FTS_TOUCH_E_NUM] & 0x0F;
924
+ if (finger_num > max_touch_num) {
925
+ FTS_ERROR("invalid point_num(%d)", finger_num);
926
+ return -EIO;
927
+ }
928
+
929
+ for (i = 0; i < max_touch_num; i++) {
930
+ base = FTS_ONE_TCH_LEN * i + 2;
931
+ pointid = (touch_buf[FTS_TOUCH_OFF_ID_YH + base]) >> 4;
932
+ if (pointid >= FTS_MAX_ID)
933
+ break;
934
+ else if (pointid >= max_touch_num) {
935
+ FTS_ERROR("ID(%d) beyond max_touch_number", pointid);
936
+ return -EINVAL;
937
+ }
938
+
939
+ events[i].id = pointid;
940
+ events[i].flag = touch_buf[FTS_TOUCH_OFF_E_XH + base] >> 6;
941
+#if FTS_TOUCH_HIRES_EN
942
+ events[i].x = ((touch_buf[FTS_TOUCH_OFF_E_XH + base] & 0x0F) << 12) \
943
+ + ((touch_buf[FTS_TOUCH_OFF_XL + base] & 0xFF) << 4) \
944
+ + ((touch_buf[FTS_TOUCH_OFF_PRE + base] >> 4) & 0x0F);
945
+ events[i].y = ((touch_buf[FTS_TOUCH_OFF_ID_YH + base] & 0x0F) << 12) \
946
+ + ((touch_buf[FTS_TOUCH_OFF_YL + base] & 0xFF) << 4) \
947
+ + (touch_buf[FTS_TOUCH_OFF_PRE + base] & 0x0F);
948
+ events[i].x = (events[i].x * FTS_TOUCH_HIRES_X ) / FTS_HI_RES_X_MAX;
949
+ events[i].y = (events[i].y * FTS_TOUCH_HIRES_X ) / FTS_HI_RES_X_MAX;
950
+ events[i].p = 0x3F;
951
+#if FTS_REPORT_PRESSURE_EN
952
+ FTS_ERROR("high solution project doesn't support pressure property");
953
+#endif
954
+#else
955
+ events[i].x = ((touch_buf[FTS_TOUCH_OFF_E_XH + base] & 0x0F) << 8) \
956
+ + (touch_buf[FTS_TOUCH_OFF_XL + base] & 0xFF);
957
+ events[i].y = ((touch_buf[FTS_TOUCH_OFF_ID_YH + base] & 0x0F) << 8) \
958
+ + (touch_buf[FTS_TOUCH_OFF_YL + base] & 0xFF);
959
+ events[i].p = touch_buf[FTS_TOUCH_OFF_PRE + base];
960
+ if (events[i].p <= 0) events[i].p = 0x3F;
961
+#endif
962
+ events[i].area = touch_buf[FTS_TOUCH_OFF_AREA + base];
963
+ if (events[i].area <= 0) events[i].area = 0x09;
964
+ events[i].minor = events[i].area;
965
+
966
+ event_num++;
967
+ if (EVENT_DOWN(events[i].flag) && (finger_num == 0)) {
968
+ FTS_INFO("abnormal touch data from fw");
969
+ return -EIO;
970
+ }
971
+ }
972
+
973
+ if (event_num == 0) {
974
+ FTS_INFO("no touch point information(%02x)", touch_buf[2]);
975
+ return -EIO;
976
+ }
977
+ ts_data->touch_event_num = event_num;
978
+
979
+ mutex_lock(&ts_data->report_mutex);
980
+#if FTS_MT_PROTOCOL_B_EN
981
+ fts_input_report_b(ts_data, events);
982
+#else
983
+ fts_input_report_a(ts_data, events);
984
+#endif
985
+ mutex_unlock(&ts_data->report_mutex);
986
+ return 0;
987
+}
988
+
989
+static int fts_input_report_touch_pv2(struct fts_ts_data *ts_data, u8 *touch_buf)
990
+{
991
+ int i = 0;
992
+ int event_num = 0;
993
+ int pointid = 0;
994
+ int base = 0;
995
+ int max_touch_num = ts_data->pdata->max_touch_number;
996
+ struct ts_event *events = ts_data->events;
997
+
998
+ event_num = touch_buf[FTS_TOUCH_E_NUM] & 0x0F;
999
+ if (!event_num || (event_num > max_touch_num)) {
1000
+ FTS_ERROR("invalid touch event num(%d)", event_num);
1001
+ return -EIO;
1002
+ }
1003
+
1004
+ ts_data->touch_event_num = event_num;
1005
+ for (i = 0; i < event_num; i++) {
1006
+ base = FTS_ONE_TCH_LEN_V2 * i + 4;
1007
+ pointid = (touch_buf[FTS_TOUCH_OFF_ID_YH + base]) >> 4;
1008
+ if (pointid >= max_touch_num) {
1009
+ FTS_ERROR("touch point ID(%d) beyond max_touch_number(%d)",
1010
+ pointid, max_touch_num);
1011
+ return -EINVAL;
1012
+ }
1013
+
1014
+ events[i].id = pointid;
1015
+ events[i].flag = touch_buf[FTS_TOUCH_OFF_E_XH + base] >> 6;
1016
+
1017
+ events[i].x = ((touch_buf[FTS_TOUCH_OFF_E_XH + base] & 0x0F) << 12) \
1018
+ + ((touch_buf[FTS_TOUCH_OFF_XL + base] & 0xFF) << 4) \
1019
+ + ((touch_buf[FTS_TOUCH_OFF_PRE + base] >> 4) & 0x0F);
1020
+
1021
+ events[i].y = ((touch_buf[FTS_TOUCH_OFF_ID_YH + base] & 0x0F) << 12) \
1022
+ + ((touch_buf[FTS_TOUCH_OFF_YL + base] & 0xFF) << 4) \
1023
+ + (touch_buf[FTS_TOUCH_OFF_PRE + base] & 0x0F);
1024
+#if FTS_TOUCH_HIRES_EN
1025
+ events[i].x = (events[i].x * FTS_TOUCH_HIRES_X ) / FTS_HI_RES_X_MAX;
1026
+ events[i].y = (events[i].y * FTS_TOUCH_HIRES_X ) / FTS_HI_RES_X_MAX;
1027
+#else
1028
+ events[i].x = events[i].x / FTS_HI_RES_X_MAX;
1029
+ events[i].y = events[i].y / FTS_HI_RES_X_MAX;
1030
+#endif
1031
+ events[i].area = touch_buf[FTS_TOUCH_OFF_AREA + base];
1032
+ events[i].minor = touch_buf[FTS_TOUCH_OFF_MINOR + base];
1033
+ events[i].p = 0x3F;
1034
+#if FTS_REPORT_PRESSURE_EN
1035
+ FTS_ERROR("The pressure property isn't supported");
1036
+#endif
1037
+ if (events[i].area <= 0) events[i].area = 0x09;
1038
+ if (events[i].minor <= 0) events[i].minor = 0x09;
1039
+ }
1040
+
1041
+ mutex_lock(&ts_data->report_mutex);
1042
+#if FTS_MT_PROTOCOL_B_EN
1043
+ fts_input_report_b(ts_data, events);
1044
+#else
1045
+ fts_input_report_a(ts_data, events);
1046
+#endif
1047
+ mutex_unlock(&ts_data->report_mutex);
1048
+ return 0;
1049
+}
1050
+
1051
+int fts_input_report_buffer(struct fts_ts_data *ts_data, u8 *report_buf)
1052
+{
1053
+ int ret = 0;
1054
+ int touch_etype = 0;
1055
+
1056
+ if (!ts_data || !report_buf) {
1057
+ FTS_ERROR("ts_data/report_buf is null");
1058
+ return -EINVAL;
1059
+ }
1060
+
1061
+ touch_etype = ((report_buf[FTS_TOUCH_E_NUM] >> 4) & 0x0F);
1062
+ switch (touch_etype) {
1063
+ case TOUCH_DEFAULT:
1064
+ ret = fts_input_report_touch(ts_data, report_buf);
1065
+ break;
1066
+
1067
+ case TOUCH_PROTOCOL_v2:
1068
+ ret = fts_input_report_touch_pv2(ts_data, report_buf);
1069
+ break;
1070
+
1071
+#if FTS_PEN_EN
1072
+ case TOUCH_PEN:
1073
+ mutex_lock(&ts_data->report_mutex);
1074
+ ret = fts_input_pen_report(ts_data, report_buf);
1075
+ mutex_unlock(&ts_data->report_mutex);
1076
+ break;
1077
+#endif
1078
+
1079
+ default:
1080
+ FTS_INFO("unknown touch event(%d)", touch_etype);
1081
+ break;
1082
+ }
1083
+
1084
+ return ret;
1085
+}
1086
+
1087
+static int fts_read_touchdata_spi(struct fts_ts_data *ts_data, u8 *buf)
1088
+{
1089
+ int ret = 0;
1090
+
1091
+ ts_data->touch_addr = 0x01;
1092
+ ret = fts_read(&ts_data->touch_addr, 1, buf, ts_data->touch_size);
1093
+
1094
+
1095
+ if (ret < 0) {
1096
+ FTS_ERROR("touch data(%x) abnormal,ret:%d", buf[1], ret);
1097
+ return ret;
1098
+ }
1099
+
1100
+ return 0;
1101
+}
1102
+
1103
+static int fts_read_touchdata_i2c(struct fts_ts_data *ts_data, u8 *buf)
1104
+{
1105
+ int ret = 0;
1106
+ u32 touch_max_size = 0;
1107
+ u32 max_touch_num = ts_data->pdata->max_touch_number;
1108
+ u8 event = 0xFF;
1109
+
1110
+ ts_data->touch_addr = 0x01;
1111
+ ret = fts_read(&ts_data->touch_addr, 1, buf, ts_data->touch_size);
1112
+ if (ret < 0) {
1113
+ FTS_ERROR("read touchdata fails,ret:%d", ret);
1114
+ return ret;
1115
+ }
1116
+
1117
+ event = (buf[FTS_TOUCH_E_NUM] >> 4) & 0x0F;
1118
+ if (event == TOUCH_DEFAULT) {
1119
+ if (buf[ts_data->touch_size - 1] != 0xFF)
1120
+ touch_max_size = max_touch_num * FTS_ONE_TCH_LEN + 2;
1121
+ } else if (event == TOUCH_PROTOCOL_v2) {
1122
+ touch_max_size = (buf[FTS_TOUCH_E_NUM] & 0x0F) * FTS_ONE_TCH_LEN_V2 + 4;
1123
+ }
1124
+#if FTS_PEN_EN
1125
+ else if (event == TOUCH_PEN) {
1126
+ touch_max_size = FTS_SIZE_PEN;
1127
+ if (touch_max_size > ts_data->touch_size) {
1128
+ FTS_INFO("read next touch message of pen,size:%d-%d",
1129
+ touch_max_size, ts_data->touch_size);
1130
+ }
1131
+ }
1132
+#endif
1133
+
1134
+ if (touch_max_size > ts_data->touch_size) {
1135
+ ts_data->ta_size = touch_max_size;
1136
+ ts_data->touch_addr += ts_data->touch_size;
1137
+ ret = fts_read(&ts_data->touch_addr, 1, buf + ts_data->touch_size, \
1138
+ touch_max_size - ts_data->touch_size);
1139
+ if (ret < 0) {
1140
+ FTS_ERROR("read touchdata2 fails,ret:%d", ret);
1141
+ return ret;
1142
+ }
1143
+ }
1144
+
1145
+ return 0;
1146
+}
1147
+
1148
+static int fts_read_parse_touchdata(struct fts_ts_data *ts_data, u8 *touch_buf)
1149
+{
1150
+ int ret = 0;
1151
+
1152
+ memset(touch_buf, 0xFF, FTS_MAX_TOUCH_BUF);
1153
+ ts_data->ta_size = ts_data->touch_size;
1154
+
1155
+ /*read touch data*/
1156
+ if (ts_data->bus_type == BUS_TYPE_SPI)
1157
+ ret = fts_read_touchdata_spi(ts_data, touch_buf);
1158
+ else if (ts_data->bus_type == BUS_TYPE_I2C)
1159
+ ret = fts_read_touchdata_i2c(ts_data, touch_buf);
1160
+ else FTS_ERROR("unknown bus type:%d", ts_data->bus_type);
1161
+ if (ret < 0) {
1162
+ FTS_ERROR("unknown BUS type");
1163
+ return TOUCH_ERROR;
1164
+ }
1165
+
1166
+ if (ts_data->log_level >= 3)
1167
+ fts_show_touch_buffer(touch_buf, ts_data->ta_size);
1168
+
1169
+ if (ret)
1170
+ return TOUCH_IGNORE;
1171
+
1172
+ if ((touch_buf[1] == 0xFF) && (touch_buf[2] == 0xFF)
1173
+ && (touch_buf[3] == 0xFF) && (touch_buf[4] == 0xFF)) {
1174
+ FTS_INFO("touch buff is 0xff, FW initialized");
1175
+ return TOUCH_FW_INIT;
1176
+ }
1177
+
1178
+#if FTS_PSENSOR_EN
1179
+ if (ts_data->proximity_mode) {
1180
+ if (fts_proximity_readdata(ts_data) == FTS_RETVAL_IGNORE_TOUCHES)
1181
+ return TOUCH_IGNORE;
1182
+ }
1183
+#endif
1184
+
1185
+#if FTS_FOD_EN
1186
+ if (ts_data->fod_mode) {
1187
+ if (fts_fod_readdata(ts_data) == FTS_RETVAL_IGNORE_TOUCHES)
1188
+ return TOUCH_IGNORE;
1189
+ }
1190
+#endif
1191
+
1192
+ if (ts_data->suspended && ts_data->gesture_support) {
1193
+ if (fts_gesture_readdata(ts_data, touch_buf) == FTS_RETVAL_IGNORE_TOUCHES)
1194
+ return TOUCH_IGNORE;
1195
+ }
1196
+
1197
+ if (ts_data->suspended) {
1198
+ FTS_INFO("In suspend state, not report touch points");
1199
+ return TOUCH_IGNORE;
1200
+ }
1201
+
1202
+ return ((touch_buf[FTS_TOUCH_E_NUM] >> 4) & 0x0F);
1203
+}
1204
+
1205
+static int fts_irq_read_report(struct fts_ts_data *ts_data)
1206
+{
1207
+ int ret = 0;
1208
+ int touch_etype = 0;
1209
+ u8 *touch_buf = ts_data->touch_buf;
1210
+
1211
+ touch_etype = fts_read_parse_touchdata(ts_data, touch_buf);
1212
+ switch (touch_etype) {
1213
+ case TOUCH_DEFAULT:
1214
+ ret = fts_input_report_touch(ts_data, touch_buf);
1215
+ break;
1216
+
1217
+ case TOUCH_PROTOCOL_v2:
1218
+ ret = fts_input_report_touch_pv2(ts_data, touch_buf);
1219
+ break;
1220
+
1221
+#if FTS_PEN_EN
1222
+ case TOUCH_PEN:
1223
+ mutex_lock(&ts_data->report_mutex);
1224
+ ret = fts_input_pen_report(ts_data, touch_buf);
1225
+ mutex_unlock(&ts_data->report_mutex);
1226
+ break;
1227
+#endif
1228
+
1229
+ case TOUCH_FW_INIT:
1230
+ fts_release_all_finger();
1231
+ fts_tp_state_recovery(ts_data);
1232
+ break;
1233
+
1234
+ case TOUCH_IGNORE:
1235
+ case TOUCH_ERROR:
1236
+ case TOUCH_FWDBG:
1237
+ break;
1238
+
1239
+ default:
1240
+ FTS_INFO("unknown touch event(%d)", touch_etype);
1241
+ break;
1242
+ }
1243
+
1244
+ return ret;
1245
+}
1246
+
1247
+static irqreturn_t fts_irq_handler(int irq, void *data)
1248
+{
1249
+ struct fts_ts_data *ts_data = fts_data;
1250
+#if IS_ENABLED(CONFIG_PM) && FTS_PATCH_COMERR_PM
1251
+ int ret = 0;
1252
+
1253
+ if ((ts_data->suspended) && (ts_data->pm_suspend)) {
1254
+ ret = wait_for_completion_timeout(
1255
+ &ts_data->pm_completion,
1256
+ msecs_to_jiffies(FTS_TIMEOUT_COMERR_PM));
1257
+ if (!ret) {
1258
+ FTS_ERROR("Bus don't resume from pm(deep),timeout,skip irq");
1259
+ return IRQ_HANDLED;
1260
+ }
1261
+ }
1262
+#endif
1263
+
1264
+ if (ts_data->suspended)
1265
+ __pm_wakeup_event(ts_data->p_ws, jiffies_to_msecs(FTS_WAKELOCK_TIMEOUT));
1266
+
1267
+
1268
+ ts_data->intr_jiffies = jiffies;
1269
+ fts_prc_queue_work(ts_data);
1270
+ fts_irq_read_report(ts_data);
1271
+ if (ts_data->touch_analysis_support && ts_data->ta_flag) {
1272
+ ts_data->ta_flag = 0;
1273
+ if (ts_data->ta_buf && ts_data->ta_size)
1274
+ memcpy(ts_data->ta_buf, ts_data->touch_buf, ts_data->ta_size);
1275
+ wake_up_interruptible(&ts_data->ts_waitqueue);
1276
+ }
1277
+
1278
+ return IRQ_HANDLED;
1279
+}
1280
+
1281
+static int fts_irq_registration(struct fts_ts_data *ts_data)
1282
+{
1283
+ int ret = 0;
1284
+ struct fts_ts_platform_data *pdata = ts_data->pdata;
1285
+
1286
+ ts_data->irq = gpio_to_irq(pdata->irq_gpio);
1287
+ pdata->irq_gpio_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
1288
+ FTS_INFO("irq:%d, flag:%x", ts_data->irq, pdata->irq_gpio_flags);
1289
+ ret = request_threaded_irq(ts_data->irq, NULL, fts_irq_handler,
1290
+ pdata->irq_gpio_flags,
1291
+ FTS_DRIVER_NAME, ts_data);
1292
+
1293
+ return ret;
1294
+}
1295
+
1296
+#if FTS_PEN_EN
1297
+static int fts_input_pen_init(struct fts_ts_data *ts_data)
1298
+{
1299
+ int ret = 0;
1300
+ struct input_dev *pen_dev;
1301
+ struct fts_ts_platform_data *pdata = ts_data->pdata;
1302
+ u32 pen_x_max = pdata->x_max;
1303
+ u32 pen_y_max = pdata->y_max;
1304
+
1305
+ FTS_FUNC_ENTER();
1306
+ pen_dev = input_allocate_device();
1307
+ if (!pen_dev) {
1308
+ FTS_ERROR("Failed to allocate memory for input_pen device");
1309
+ return -ENOMEM;
1310
+ }
1311
+
1312
+#if FTS_PEN_HIRES_EN
1313
+ pen_x_max = (pdata->x_max + 1) * FTS_PEN_HIRES_X - 1;
1314
+ pen_y_max = (pdata->y_max + 1) * FTS_PEN_HIRES_X - 1;
1315
+#endif
1316
+ pen_dev->dev.parent = ts_data->dev;
1317
+ pen_dev->name = FTS_DRIVER_PEN_NAME;
1318
+ pen_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
1319
+ __set_bit(ABS_X, pen_dev->absbit);
1320
+ __set_bit(ABS_Y, pen_dev->absbit);
1321
+ __set_bit(BTN_STYLUS, pen_dev->keybit);
1322
+ __set_bit(BTN_STYLUS2, pen_dev->keybit);
1323
+ __set_bit(BTN_TOUCH, pen_dev->keybit);
1324
+ __set_bit(BTN_TOOL_PEN, pen_dev->keybit);
1325
+ __set_bit(INPUT_PROP_DIRECT, pen_dev->propbit);
1326
+ input_set_abs_params(pen_dev, ABS_X, pdata->x_min, pen_x_max, 0, 0);
1327
+ input_set_abs_params(pen_dev, ABS_Y, pdata->y_min, pen_y_max, 0, 0);
1328
+ input_set_abs_params(pen_dev, ABS_PRESSURE, 0, 4096, 0, 0);
1329
+ input_set_abs_params(pen_dev, ABS_TILT_X, -9000, 9000, 0, 0);
1330
+ input_set_abs_params(pen_dev, ABS_TILT_Y, -9000, 9000, 0, 0);
1331
+ input_set_abs_params(pen_dev, ABS_Z, 0, 36000, 0, 0);
1332
+
1333
+ ret = input_register_device(pen_dev);
1334
+ if (ret) {
1335
+ FTS_ERROR("Input device registration failed");
1336
+ input_free_device(pen_dev);
1337
+ pen_dev = NULL;
1338
+ return ret;
1339
+ }
1340
+
1341
+ ts_data->pen_dev = pen_dev;
1342
+ ts_data->pen_etype = STYLUS_DEFAULT;
1343
+ FTS_FUNC_EXIT();
1344
+ return 0;
1345
+}
1346
+#endif
1347
+
1348
+static int fts_input_init(struct fts_ts_data *ts_data)
1349
+{
1350
+ int ret = 0;
1351
+ int key_num = 0;
1352
+ struct fts_ts_platform_data *pdata = ts_data->pdata;
1353
+ struct input_dev *input_dev;
1354
+ u32 touch_x_max = pdata->x_max;
1355
+ u32 touch_y_max = pdata->y_max;
1356
+
1357
+ FTS_FUNC_ENTER();
1358
+ input_dev = input_allocate_device();
1359
+ if (!input_dev) {
1360
+ FTS_ERROR("Failed to allocate memory for input device");
1361
+ return -ENOMEM;
1362
+ }
1363
+
1364
+ /* Init and register Input device */
1365
+ input_dev->name = FTS_DRIVER_NAME;
1366
+ if (ts_data->bus_type == BUS_TYPE_I2C)
1367
+ input_dev->id.bustype = BUS_I2C;
1368
+ else
1369
+ input_dev->id.bustype = BUS_SPI;
1370
+ input_dev->dev.parent = ts_data->dev;
1371
+
1372
+ input_set_drvdata(input_dev, ts_data);
1373
+
1374
+ __set_bit(EV_SYN, input_dev->evbit);
1375
+ __set_bit(EV_ABS, input_dev->evbit);
1376
+ __set_bit(EV_KEY, input_dev->evbit);
1377
+ __set_bit(BTN_TOUCH, input_dev->keybit);
1378
+ __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
1379
+
1380
+ if (pdata->have_key) {
1381
+ FTS_INFO("set key capabilities");
1382
+ for (key_num = 0; key_num < pdata->key_number; key_num++)
1383
+ input_set_capability(input_dev, EV_KEY, pdata->keys[key_num]);
1384
+ }
1385
+
1386
+#if FTS_TOUCH_HIRES_EN
1387
+ touch_x_max = (pdata->x_max + 1) * FTS_TOUCH_HIRES_X - 1;
1388
+ touch_y_max = (pdata->y_max + 1) * FTS_TOUCH_HIRES_X - 1;
1389
+#endif
1390
+
1391
+#if FTS_MT_PROTOCOL_B_EN
1392
+ input_mt_init_slots(input_dev, pdata->max_touch_number, INPUT_MT_DIRECT);
1393
+#else
1394
+ input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, 0x0F, 0, 0);
1395
+#endif
1396
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min, touch_x_max, 0, 0);
1397
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min, touch_y_max, 0, 0);
1398
+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 0xFF, 0, 0);
1399
+#if FTS_REPORT_PRESSURE_EN
1400
+ input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 0xFF, 0, 0);
1401
+#endif
1402
+
1403
+ ret = input_register_device(input_dev);
1404
+ if (ret) {
1405
+ FTS_ERROR("Input device registration failed");
1406
+ input_set_drvdata(input_dev, NULL);
1407
+ input_free_device(input_dev);
1408
+ input_dev = NULL;
1409
+ return ret;
1410
+ }
1411
+
1412
+#if FTS_PEN_EN
1413
+ ret = fts_input_pen_init(ts_data);
1414
+ if (ret) {
1415
+ FTS_ERROR("Input-pen device registration failed");
1416
+ input_set_drvdata(input_dev, NULL);
1417
+ input_free_device(input_dev);
1418
+ input_dev = NULL;
1419
+ return ret;
1420
+ }
1421
+#endif
1422
+
1423
+ ts_data->input_dev = input_dev;
1424
+ FTS_FUNC_EXIT();
1425
+ return 0;
1426
+}
1427
+
1428
+static int fts_buffer_init(struct fts_ts_data *ts_data)
1429
+{
1430
+ ts_data->touch_buf = (u8 *)kzalloc(FTS_MAX_TOUCH_BUF, GFP_KERNEL);
1431
+ if (!ts_data->touch_buf) {
1432
+ FTS_ERROR("failed to alloc memory for touch buf");
1433
+ return -ENOMEM;
1434
+ }
1435
+
1436
+ if (ts_data->bus_type == BUS_TYPE_SPI)
1437
+ ts_data->touch_size = FTS_TOUCH_DATA_LEN_V2;
1438
+ else if (ts_data->bus_type == BUS_TYPE_I2C)
1439
+ ts_data->touch_size = FTS_SIZE_DEFAULT_V2;
1440
+ else FTS_ERROR("unknown bus type:%d", ts_data->bus_type);
1441
+
1442
+ ts_data->touch_analysis_support = 0;
1443
+ ts_data->ta_flag = 0;
1444
+ ts_data->ta_size = 0;
1445
+
1446
+ return 0;
1447
+}
1448
+
1449
+#if FTS_PINCTRL_EN
1450
+static int fts_pinctrl_init(struct fts_ts_data *ts)
1451
+{
1452
+ int ret = 0;
1453
+
1454
+ ts->pinctrl = devm_pinctrl_get(ts->dev);
1455
+ if (IS_ERR_OR_NULL(ts->pinctrl)) {
1456
+ FTS_ERROR("Failed to get pinctrl, please check dts");
1457
+ ret = PTR_ERR(ts->pinctrl);
1458
+ goto err_pinctrl_get;
1459
+ }
1460
+
1461
+ ts->pins_active = pinctrl_lookup_state(ts->pinctrl, "pmx_ts_active");
1462
+ if (IS_ERR_OR_NULL(ts->pins_active)) {
1463
+ FTS_ERROR("Pin state[active] not found");
1464
+ ret = PTR_ERR(ts->pins_active);
1465
+ goto err_pinctrl_lookup;
1466
+ }
1467
+
1468
+ ts->pins_suspend = pinctrl_lookup_state(ts->pinctrl, "pmx_ts_suspend");
1469
+ if (IS_ERR_OR_NULL(ts->pins_suspend)) {
1470
+ FTS_ERROR("Pin state[suspend] not found");
1471
+ ret = PTR_ERR(ts->pins_suspend);
1472
+ goto err_pinctrl_lookup;
1473
+ }
1474
+
1475
+ ts->pins_release = pinctrl_lookup_state(ts->pinctrl, "pmx_ts_release");
1476
+ if (IS_ERR_OR_NULL(ts->pins_release)) {
1477
+ FTS_ERROR("Pin state[release] not found");
1478
+ ret = PTR_ERR(ts->pins_release);
1479
+ }
1480
+
1481
+ return 0;
1482
+err_pinctrl_lookup:
1483
+ if (ts->pinctrl) {
1484
+ devm_pinctrl_put(ts->pinctrl);
1485
+ }
1486
+err_pinctrl_get:
1487
+ ts->pinctrl = NULL;
1488
+ ts->pins_release = NULL;
1489
+ ts->pins_suspend = NULL;
1490
+ ts->pins_active = NULL;
1491
+ return ret;
1492
+}
1493
+#endif /* FTS_PINCTRL_EN */
1494
+
1495
+#if FTS_POWER_SOURCE_CUST_EN
1496
+/*****************************************************************************
1497
+* Power Control
1498
+*****************************************************************************/
1499
+static int fts_power_source_ctrl(struct fts_ts_data *ts_data, int enable)
1500
+{
1501
+ int ret = 0;
1502
+
1503
+ if (IS_ERR_OR_NULL(ts_data->vdd)) {
1504
+ FTS_ERROR("vdd is invalid");
1505
+ return -EINVAL;
1506
+ }
1507
+
1508
+ FTS_FUNC_ENTER();
1509
+ if (enable) {
1510
+ if (ts_data->power_disabled) {
1511
+ fts_set_reset(ts_data, 0);
1512
+ fts_msleep(2);
1513
+ FTS_INFO("set power to on");
1514
+ ret = regulator_enable(ts_data->vdd);
1515
+ if (ret) {
1516
+ FTS_ERROR("enable vdd regulator failed,ret=%d", ret);
1517
+ }
1518
+
1519
+ if (!IS_ERR_OR_NULL(ts_data->iovcc)) {
1520
+ ret = regulator_enable(ts_data->iovcc);
1521
+ if (ret) {
1522
+ FTS_ERROR("enable iovcc regulator failed,ret=%d", ret);
1523
+ }
1524
+ }
1525
+ fts_msleep(2);
1526
+ fts_set_reset(ts_data, 1);
1527
+ ts_data->power_disabled = false;
1528
+ }
1529
+ } else {
1530
+ if (!ts_data->power_disabled) {
1531
+ fts_set_reset(ts_data, 0);
1532
+ fts_msleep(2);
1533
+ FTS_INFO("set power to off");
1534
+ if (!IS_ERR_OR_NULL(ts_data->iovcc)) {
1535
+ ret = regulator_disable(ts_data->iovcc);
1536
+ if (ret) {
1537
+ FTS_ERROR("disable iovcc regulator failed,ret=%d", ret);
1538
+ }
1539
+ }
1540
+ ret = regulator_disable(ts_data->vdd);
1541
+ if (ret) {
1542
+ FTS_ERROR("disable vdd regulator failed,ret=%d", ret);
1543
+ }
1544
+ ts_data->power_disabled = true;
1545
+ }
1546
+ }
1547
+
1548
+ FTS_FUNC_EXIT();
1549
+ return ret;
1550
+}
1551
+
1552
+/*****************************************************************************
1553
+* Name: fts_power_source_init
1554
+* Brief: Init regulator power:vdd/vcc_io(if have), generally, no vcc_io
1555
+* vdd---->vdd-supply in dts, kernel will auto add "-supply" to parse
1556
+* Must be call after fts_gpio_configure() execute,because this function
1557
+* will operate reset-gpio which request gpio in fts_gpio_configure()
1558
+* Input:
1559
+* Output:
1560
+* Return: return 0 if init power successfully, otherwise return error code
1561
+*****************************************************************************/
1562
+static int fts_power_source_init(struct fts_ts_data *ts_data)
1563
+{
1564
+ int ret = 0;
1565
+
1566
+ FTS_FUNC_ENTER();
1567
+ ts_data->vdd = regulator_get(ts_data->dev, "vdd");
1568
+ if (IS_ERR_OR_NULL(ts_data->vdd)) {
1569
+ ret = PTR_ERR(ts_data->vdd);
1570
+ FTS_ERROR("get vdd regulator failed,ret=%d", ret);
1571
+ return ret;
1572
+ }
1573
+
1574
+ if (regulator_count_voltages(ts_data->vdd) > 0) {
1575
+ ret = regulator_set_voltage(ts_data->vdd, FTS_VTG_MIN_UV,
1576
+ FTS_VTG_MAX_UV);
1577
+ if (ret) {
1578
+ FTS_ERROR("vdd regulator set_vtg failed ret=%d", ret);
1579
+ regulator_put(ts_data->vdd);
1580
+ return ret;
1581
+ }
1582
+ }
1583
+
1584
+ ts_data->iovcc = regulator_get(ts_data->dev, "iovcc");
1585
+ if (!IS_ERR_OR_NULL(ts_data->iovcc)) {
1586
+ if (regulator_count_voltages(ts_data->iovcc) > 0) {
1587
+ ret = regulator_set_voltage(ts_data->iovcc,
1588
+ FTS_IOVCC_VTG_MIN_UV,
1589
+ FTS_IOVCC_VTG_MAX_UV);
1590
+ if (ret) {
1591
+ FTS_ERROR("iovcc regulator set_vtg failed,ret=%d", ret);
1592
+ regulator_put(ts_data->iovcc);
1593
+ }
1594
+ }
1595
+ }
1596
+
1597
+ ret = fts_power_source_ctrl(ts_data, ENABLE);
1598
+ if (ret) {
1599
+ FTS_ERROR("fail to enable power(regulator)");
1600
+ }
1601
+
1602
+ FTS_FUNC_EXIT();
1603
+ return ret;
1604
+}
1605
+
1606
+static int fts_power_source_exit(struct fts_ts_data *ts_data)
1607
+{
1608
+ fts_power_source_ctrl(ts_data, DISABLE);
1609
+
1610
+ if (!IS_ERR_OR_NULL(ts_data->vdd)) {
1611
+ if (regulator_count_voltages(ts_data->vdd) > 0)
1612
+ regulator_set_voltage(ts_data->vdd, 0, FTS_VTG_MAX_UV);
1613
+ regulator_put(ts_data->vdd);
1614
+ }
1615
+
1616
+ if (!IS_ERR_OR_NULL(ts_data->iovcc)) {
1617
+ if (regulator_count_voltages(ts_data->iovcc) > 0)
1618
+ regulator_set_voltage(ts_data->iovcc, 0, FTS_IOVCC_VTG_MAX_UV);
1619
+ regulator_put(ts_data->iovcc);
1620
+ }
1621
+
1622
+ return 0;
1623
+}
1624
+#endif /* FTS_POWER_SOURCE_CUST_EN */
1625
+
1626
+static int fts_power_init(struct fts_ts_data *ts_data)
1627
+{
1628
+ int ret = 0;
1629
+
1630
+ ts_data->power_disabled = true;
1631
+#if FTS_POWER_SOURCE_CUST_EN
1632
+ ret = fts_power_source_init(ts_data);
1633
+ if (ret) {
1634
+ FTS_ERROR("fail to get power(regulator)");
1635
+ return ret;
1636
+ }
1637
+#else
1638
+#if (!FTS_CHIP_IDC)
1639
+ ret = fts_set_reset(ts_data, 0);
1640
+ if (ret) return ret;
1641
+#endif
1642
+ fts_msleep(2);
1643
+ ret = fts_set_reset(ts_data, 1);
1644
+ if (ret) return ret;
1645
+#endif /* FTS_POWER_SOURCE_CUST_EN */
1646
+
1647
+ /* Init BUS pins(SPI/I2C) after powring on if enabling FTS_PINCTRL_EN*/
1648
+#if FTS_PINCTRL_EN
1649
+ fts_pinctrl_init(ts_data);
1650
+ if (ts_data->pinctrl && ts_data->pins_active) {
1651
+ ret = pinctrl_select_state(ts_data->pinctrl, ts_data->pins_active);
1652
+ if (ret < 0) {
1653
+ FTS_ERROR("Set bus pins to active state failed,ret=%d", ret);
1654
+ }
1655
+ }
1656
+#endif
1657
+
1658
+ fts_msleep(200);
1659
+ return 0;
1660
+}
1661
+
1662
+// static int fts_power_suspend(struct fts_ts_data *ts_data)
1663
+// {
1664
+// int ret = 0;
1665
+
1666
+// FTS_FUNC_ENTER();
1667
+// FTS_INFO("make TP enter into sleep mode");
1668
+// ret = fts_write_reg(FTS_REG_POWER_MODE, FTS_REG_POWER_MODE_SLEEP);
1669
+// if (ret < 0) {
1670
+// FTS_ERROR("set TP to sleep mode failed, ret=%d", ret);
1671
+// }
1672
+
1673
+// #if FTS_POWER_SUSPEND_OFF_EN
1674
+// #if FTS_PINCTRL_EN
1675
+// if (ts_data->pinctrl && ts_data->pins_suspend) {
1676
+// if (pinctrl_select_state(ts_data->pinctrl, ts_data->pins_suspend)) {
1677
+// FTS_ERROR("Set bus pins to suspend state failed");
1678
+// }
1679
+// }
1680
+// #endif /* FTS_PINCTRL_EN */
1681
+
1682
+// #if FTS_POWER_SOURCE_CUST_EN
1683
+// if (fts_power_source_ctrl(ts_data, DISABLE)) {
1684
+// FTS_ERROR("set power to off failed");
1685
+// }
1686
+// #else
1687
+// FTS_ERROR("FTS_POWER_SOURCE_CUST_EN=0,FTS_POWER_SUSPEND_OFF_EN=1");
1688
+// #endif /* FTS_POWER_SOURCE_CUST_EN */
1689
+// #endif /* FTS_POWER_SUSPEND_OFF_EN */
1690
+
1691
+// FTS_FUNC_EXIT();
1692
+// return 0;
1693
+// }
1694
+
1695
+// static int fts_power_resume(struct fts_ts_data *ts_data)
1696
+// {
1697
+// FTS_FUNC_ENTER();
1698
+// #if FTS_POWER_SUSPEND_OFF_EN
1699
+// #if FTS_POWER_SOURCE_CUST_EN
1700
+// if (fts_power_source_ctrl(ts_data, ENABLE)) {
1701
+// FTS_ERROR("set power to on failed");
1702
+// }
1703
+// fts_msleep(FTS_DELAY_RESUME_RESET);
1704
+// #else
1705
+// FTS_ERROR("FTS_POWER_SOURCE_CUST_EN=0,FTS_POWER_SUSPEND_OFF_EN=1");
1706
+// #endif /* FTS_POWER_SOURCE_CUST_EN */
1707
+
1708
+// #if FTS_PINCTRL_EN
1709
+// if (ts_data->pinctrl && ts_data->pins_active) {
1710
+// if (pinctrl_select_state(ts_data->pinctrl, ts_data->pins_active)) {
1711
+// FTS_ERROR("Set bus pins to active state failed");
1712
+// }
1713
+// }
1714
+// #endif /* FTS_PINCTRL_EN */
1715
+
1716
+// #else /* else FTS_POWER_SUSPEND_OFF_EN */
1717
+// if (!ts_data->ic_info.is_incell) {
1718
+// fts_reset_proc(ts_data, false, FTS_DELAY_RESUME_RESET);
1719
+// }
1720
+// #endif /* FTS_POWER_SUSPEND_OFF_EN */
1721
+
1722
+// FTS_FUNC_EXIT();
1723
+// return 0;
1724
+// }
1725
+
1726
+static int fts_gpio_configure(struct fts_ts_data *ts_data)
1727
+{
1728
+ int ret = 0;
1729
+
1730
+ FTS_FUNC_ENTER();
1731
+ /* request irq gpio */
1732
+ if (gpio_is_valid(ts_data->pdata->irq_gpio)) {
1733
+ ret = gpio_request(ts_data->pdata->irq_gpio, "fts_irq_gpio");
1734
+ if (ret) {
1735
+ FTS_ERROR("[GPIO]irq gpio request failed");
1736
+ goto err_irq_gpio_req;
1737
+ }
1738
+
1739
+ ret = gpio_direction_input(ts_data->pdata->irq_gpio);
1740
+ if (ret) {
1741
+ FTS_ERROR("[GPIO]set_direction for irq gpio failed");
1742
+ goto err_irq_gpio_dir;
1743
+ }
1744
+ }
1745
+
1746
+ /* request reset gpio */
1747
+ if (gpio_is_valid(ts_data->pdata->reset_gpio)) {
1748
+ ret = gpio_request(ts_data->pdata->reset_gpio, "fts_reset_gpio");
1749
+ if (ret) {
1750
+ FTS_ERROR("[GPIO]reset gpio request failed");
1751
+ goto err_irq_gpio_dir;
1752
+ }
1753
+ }
1754
+
1755
+ FTS_FUNC_EXIT();
1756
+ return 0;
1757
+
1758
+err_irq_gpio_dir:
1759
+ if (gpio_is_valid(ts_data->pdata->irq_gpio))
1760
+ gpio_free(ts_data->pdata->irq_gpio);
1761
+err_irq_gpio_req:
1762
+ FTS_FUNC_EXIT();
1763
+ return ret;
1764
+}
1765
+
1766
+static int fts_bus_init(struct fts_ts_data *ts_data)
1767
+{
1768
+ FTS_FUNC_ENTER();
1769
+ ts_data->bus_tx_buf = kzalloc(FTS_MAX_BUS_BUF, GFP_KERNEL);
1770
+ if (NULL == ts_data->bus_tx_buf) {
1771
+ FTS_ERROR("failed to allocate memory for bus_tx_buf");
1772
+ return -ENOMEM;
1773
+ }
1774
+
1775
+ ts_data->bus_rx_buf = kzalloc(FTS_MAX_BUS_BUF, GFP_KERNEL);
1776
+ if (NULL == ts_data->bus_rx_buf) {
1777
+ FTS_ERROR("failed to allocate memory for bus_rx_buf");
1778
+ return -ENOMEM;
1779
+ }
1780
+
1781
+ FTS_FUNC_EXIT();
1782
+ return 0;
1783
+}
1784
+
1785
+static int fts_get_dt_coords(struct device *dev, char *name,
1786
+ struct fts_ts_platform_data *pdata)
1787
+{
1788
+ int ret = 0;
1789
+ u32 coords[FTS_COORDS_ARR_SIZE] = { 0 };
1790
+ struct property *prop;
1791
+ struct device_node *np = dev->of_node;
1792
+ int coords_size;
1793
+
1794
+ prop = of_find_property(np, name, NULL);
1795
+ if (!prop)
1796
+ return -EINVAL;
1797
+ if (!prop->value)
1798
+ return -ENODATA;
1799
+
1800
+ coords_size = prop->length / sizeof(u32);
1801
+ if (coords_size != FTS_COORDS_ARR_SIZE) {
1802
+ FTS_ERROR("invalid:%s, size:%d", name, coords_size);
1803
+ return -EINVAL;
1804
+ }
1805
+
1806
+ ret = of_property_read_u32_array(np, name, coords, coords_size);
1807
+ if (ret < 0) {
1808
+ FTS_ERROR("Unable to read %s, please check dts", name);
1809
+ pdata->x_min = FTS_X_MIN_DISPLAY_DEFAULT;
1810
+ pdata->y_min = FTS_Y_MIN_DISPLAY_DEFAULT;
1811
+ pdata->x_max = FTS_X_MAX_DISPLAY_DEFAULT;
1812
+ pdata->y_max = FTS_Y_MAX_DISPLAY_DEFAULT;
1813
+ return -ENODATA;
1814
+ } else {
1815
+ pdata->x_min = coords[0];
1816
+ pdata->y_min = coords[1];
1817
+ pdata->x_max = coords[2];
1818
+ pdata->y_max = coords[3];
1819
+ }
1820
+
1821
+ FTS_INFO("display x(%d %d) y(%d %d)", pdata->x_min, pdata->x_max,
1822
+ pdata->y_min, pdata->y_max);
1823
+ return 0;
1824
+}
1825
+
1826
+static int fts_parse_dt(struct device *dev, struct fts_ts_platform_data *pdata)
1827
+{
1828
+ int ret = 0;
1829
+ struct device_node *np = dev->of_node;
1830
+ u32 temp_val = 0;
1831
+
1832
+ FTS_FUNC_ENTER();
1833
+ if (!np || !pdata) {
1834
+ FTS_ERROR("np/pdata is null");
1835
+ return -EINVAL;
1836
+ }
1837
+
1838
+ ret = fts_get_dt_coords(dev, "focaltech,display-coords", pdata);
1839
+ if (ret < 0)
1840
+ FTS_ERROR("Unable to get display-coords");
1841
+
1842
+ /* key */
1843
+ pdata->have_key = of_property_read_bool(np, "focaltech,have-key");
1844
+ if (pdata->have_key) {
1845
+ ret = of_property_read_u32(np, "focaltech,key-number", &pdata->key_number);
1846
+ if (ret < 0)
1847
+ FTS_ERROR("Key number undefined!");
1848
+
1849
+ ret = of_property_read_u32_array(np, "focaltech,keys",
1850
+ pdata->keys, pdata->key_number);
1851
+ if (ret < 0)
1852
+ FTS_ERROR("Keys undefined!");
1853
+ else if (pdata->key_number > FTS_MAX_KEYS)
1854
+ pdata->key_number = FTS_MAX_KEYS;
1855
+
1856
+ ret = of_property_read_u32_array(np, "focaltech,key-x-coords",
1857
+ pdata->key_x_coords,
1858
+ pdata->key_number);
1859
+ if (ret < 0)
1860
+ FTS_ERROR("Key Y Coords undefined!");
1861
+
1862
+ ret = of_property_read_u32_array(np, "focaltech,key-y-coords",
1863
+ pdata->key_y_coords,
1864
+ pdata->key_number);
1865
+ if (ret < 0)
1866
+ FTS_ERROR("Key X Coords undefined!");
1867
+
1868
+ FTS_INFO("VK Number:%d, key:(%d,%d,%d), "
1869
+ "coords:(%d,%d),(%d,%d),(%d,%d)",
1870
+ pdata->key_number,
1871
+ pdata->keys[0], pdata->keys[1], pdata->keys[2],
1872
+ pdata->key_x_coords[0], pdata->key_y_coords[0],
1873
+ pdata->key_x_coords[1], pdata->key_y_coords[1],
1874
+ pdata->key_x_coords[2], pdata->key_y_coords[2]);
1875
+ }
1876
+
1877
+ /* reset, irq gpio info */
1878
+ pdata->reset_gpio = of_get_named_gpio_flags(np, "focaltech,reset-gpio",
1879
+ 0, &pdata->reset_gpio_flags);
1880
+ if (pdata->reset_gpio < 0)
1881
+ FTS_ERROR("Unable to get reset_gpio");
1882
+
1883
+ pdata->irq_gpio = of_get_named_gpio_flags(np, "focaltech,irq-gpio",
1884
+ 0, &pdata->irq_gpio_flags);
1885
+ if (pdata->irq_gpio < 0)
1886
+ FTS_ERROR("Unable to get irq_gpio");
1887
+
1888
+ ret = of_property_read_u32(np, "focaltech,max-touch-number", &temp_val);
1889
+ if (ret < 0) {
1890
+ FTS_ERROR("Unable to get max-touch-number, please check dts");
1891
+ pdata->max_touch_number = FTS_MAX_POINTS_SUPPORT;
1892
+ } else {
1893
+ if (temp_val < 2)
1894
+ pdata->max_touch_number = 2; /* max_touch_number must >= 2 */
1895
+ else if (temp_val > FTS_MAX_POINTS_SUPPORT)
1896
+ pdata->max_touch_number = FTS_MAX_POINTS_SUPPORT;
1897
+ else
1898
+ pdata->max_touch_number = temp_val;
1899
+ }
1900
+
1901
+ FTS_INFO("max touch number:%d, irq gpio:%d, reset gpio:%d",
1902
+ pdata->max_touch_number, pdata->irq_gpio, pdata->reset_gpio);
1903
+
1904
+ FTS_FUNC_EXIT();
1905
+ return 0;
1906
+}
1907
+
1908
+// static int fts_ts_suspend(struct device *dev)
1909
+// {
1910
+// struct fts_ts_data *ts_data = fts_data;
1911
+
1912
+// FTS_FUNC_ENTER();
1913
+// if (ts_data->suspended) {
1914
+// FTS_INFO("Already in suspend state");
1915
+// return 0;
1916
+// }
1917
+
1918
+// if (ts_data->fw_loading) {
1919
+// FTS_INFO("fw upgrade in process, can't suspend");
1920
+// return 0;
1921
+// }
1922
+
1923
+// ts_data->need_work_in_suspend = false;
1924
+// fts_esdcheck_suspend(ts_data);
1925
+// #if FTS_PSENSOR_EN
1926
+// if (ts_data->proximity_mode) {
1927
+// fts_proximity_suspend(ts_data);
1928
+// ts_data->need_work_in_suspend = true;
1929
+// fts_release_all_finger();
1930
+// ts_data->suspended = true;
1931
+// return 0;
1932
+// }
1933
+// #endif
1934
+
1935
+// #if FTS_FOD_EN
1936
+// if (ts_data->fod_mode) {
1937
+// fts_fod_suspend(ts_data);
1938
+// ts_data->need_work_in_suspend = true;
1939
+// }
1940
+// #endif
1941
+
1942
+// if (ts_data->gesture_support) {
1943
+// fts_gesture_suspend(ts_data);
1944
+// ts_data->need_work_in_suspend = true;
1945
+// }
1946
+
1947
+// if (ts_data->need_work_in_suspend) {
1948
+// if (enable_irq_wake(ts_data->irq)) {
1949
+// FTS_ERROR("enable_irq_wake(irq:%d) fail", ts_data->irq);
1950
+// }
1951
+// } else {
1952
+// fts_irq_disable();
1953
+// fts_power_suspend(ts_data);
1954
+// }
1955
+
1956
+// fts_release_all_finger();
1957
+// ts_data->suspended = true;
1958
+// FTS_FUNC_EXIT();
1959
+// return 0;
1960
+// }
1961
+
1962
+// static int fts_ts_resume(struct device *dev)
1963
+// {
1964
+// struct fts_ts_data *ts_data = fts_data;
1965
+
1966
+// FTS_FUNC_ENTER();
1967
+// if (!ts_data->suspended) {
1968
+// FTS_DEBUG("Already in awake state");
1969
+// return 0;
1970
+// }
1971
+
1972
+// if (ts_data->fw_loading) {
1973
+// FTS_INFO("fw upgrade in process, don't resume");
1974
+// return 0;
1975
+// }
1976
+
1977
+// ts_data->suspended = false;
1978
+// fts_release_all_finger();
1979
+// #if FTS_PSENSOR_EN
1980
+// if (ts_data->proximity_mode) {
1981
+// fts_wait_tp_to_valid();
1982
+// fts_proximity_resume(ts_data);
1983
+// fts_esdcheck_resume(ts_data);
1984
+// if (ts_data->gesture_support) fts_gesture_resume(ts_data);
1985
+// return 0;
1986
+// }
1987
+// #endif
1988
+
1989
+// if (ts_data->need_work_in_suspend) {
1990
+// #if FTS_FOD_EN
1991
+// if ((!ts_data->ic_info.is_incell) && (!fts_fod_checkdown(ts_data))) {
1992
+// fts_reset_proc(ts_data, false, FTS_DELAY_RESUME_RESET);
1993
+// }
1994
+// #else
1995
+// if (!ts_data->ic_info.is_incell) {
1996
+// fts_reset_proc(ts_data, false, FTS_DELAY_RESUME_RESET);
1997
+// }
1998
+// #endif
1999
+// } else {
2000
+// fts_power_resume(ts_data);
2001
+// }
2002
+
2003
+// fts_enter_normal_fw();
2004
+// if (ts_data->gesture_support) {
2005
+// fts_gesture_resume(ts_data);
2006
+// }
2007
+// #if FTS_FOD_EN
2008
+// if (ts_data->fod_mode) {
2009
+// fts_fod_resume(ts_data);
2010
+// }
2011
+// #endif
2012
+// fts_ex_mode_recovery(ts_data);
2013
+// fts_esdcheck_resume(ts_data);
2014
+
2015
+// if (ts_data->need_work_in_suspend) {
2016
+// if (disable_irq_wake(ts_data->irq)) {
2017
+// FTS_ERROR("disable_irq_wake(irq:%d) fail", ts_data->irq);
2018
+// }
2019
+// } else {
2020
+// fts_irq_enable();
2021
+// }
2022
+
2023
+// FTS_FUNC_EXIT();
2024
+// return 0;
2025
+// }
2026
+
2027
+static void fts_resume_work(struct work_struct *work)
2028
+{
2029
+ struct fts_ts_data *ts_data = container_of(work, struct fts_ts_data, resume_work);
2030
+ // fts_ts_resume(ts_data->dev);
2031
+}
2032
+
2033
+
2034
+// #if IS_ENABLED(CONFIG_DRM)
2035
+// #if IS_ENABLED(CONFIG_DRM_PANEL)
2036
+// static struct drm_panel *active_panel;
2037
+
2038
+// static int drm_check_dt(struct fts_ts_data *ts_data)
2039
+// {
2040
+// int i = 0;
2041
+// int count = 0;
2042
+// struct device_node *node = NULL;
2043
+// struct drm_panel *panel = NULL;
2044
+// struct device_node *np = NULL;
2045
+
2046
+// if (ts_data && ts_data->dev && ts_data->dev->of_node) {
2047
+// np = ts_data->dev->of_node;
2048
+// count = of_count_phandle_with_args(np, "panel", NULL);
2049
+// if (count <= 0) {
2050
+// FTS_ERROR("find drm_panel count(%d) fail", count);
2051
+// return -ENODEV;
2052
+// }
2053
+
2054
+// for (i = 0; i < count; i++) {
2055
+// node = of_parse_phandle(np, "panel", i);
2056
+// panel = of_drm_find_panel(node);
2057
+// of_node_put(node);
2058
+// if (!IS_ERR(panel)) {
2059
+// FTS_INFO("find drm_panel successfully");
2060
+// active_panel = panel;
2061
+// return 0;
2062
+// }
2063
+// }
2064
+// }
2065
+
2066
+// FTS_ERROR("no find drm_panel");
2067
+// return -ENODEV;
2068
+// }
2069
+// #endif //CONFIG_DRM_PANEL
2070
+// #endif //CONFIG_DRM
2071
+
2072
+
2073
+// static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *v)
2074
+// {
2075
+// struct fts_ts_data *ts_data = container_of(self, struct fts_ts_data, fb_notif);
2076
+// FTS_FUNC_ENTER();
2077
+// if (ts_data && v) {
2078
+// #if IS_ENABLED(CONFIG_DRM)
2079
+
2080
+// #if IS_ENABLED(CONFIG_DRM_PANEL)
2081
+// int blank_value = *((int *)(((struct drm_panel_notifier *)v)->data));
2082
+// const unsigned long event_enum[2] = {DRM_PANEL_EARLY_EVENT_BLANK, DRM_PANEL_EVENT_BLANK};
2083
+// const int blank_enum[2] = {DRM_PANEL_BLANK_POWERDOWN, DRM_PANEL_BLANK_UNBLANK};
2084
+// #else //CONFIG_DRM_PANEL
2085
+// int blank_value = *((int *)(((struct msm_drm_notifier *)v)->data));
2086
+// const unsigned long event_enum[2] = {MSM_DRM_EARLY_EVENT_BLANK, MSM_DRM_EVENT_BLANK};
2087
+// const int blank_enum[2] = {MSM_DRM_BLANK_POWERDOWN, MSM_DRM_BLANK_UNBLANK};
2088
+// #endif //CONFIG_DRM_PANEL
2089
+
2090
+// #elif IS_ENABLED(CONFIG_FB)
2091
+// const unsigned long event_enum[2] = {FB_EARLY_EVENT_BLANK, FB_EVENT_BLANK};
2092
+// const int blank_enum[2] = {FB_BLANK_POWERDOWN, FB_BLANK_UNBLANK};
2093
+// int blank_value = *((int *)(((struct fb_event *)v)->data));
2094
+// #endif //CONFIG_DRM
2095
+// FTS_INFO("notifier,event:%lu,blank:%d", event, blank_value);
2096
+// if ((blank_enum[1] == blank_value) && (event_enum[1] == event)) {
2097
+// queue_work(fts_data->ts_workqueue, &fts_data->resume_work);
2098
+// } else if ((blank_enum[0] == blank_value) && (event_enum[0] == event)) {
2099
+// cancel_work_sync(&fts_data->resume_work);
2100
+// fts_ts_suspend(ts_data->dev);
2101
+// } else {
2102
+// FTS_DEBUG("notifier,event:%lu,blank:%d, not care", event, blank_value);
2103
+// }
2104
+// } else {
2105
+// FTS_ERROR("ts_data/v is null");
2106
+// return -EINVAL;
2107
+// }
2108
+// FTS_FUNC_EXIT();
2109
+// return 0;
2110
+// }
2111
+
2112
+
2113
+static int fts_notifier_callback_init(struct fts_ts_data *ts_data)
2114
+{
2115
+ int ret = 0;
2116
+ FTS_FUNC_ENTER();
2117
+// #if IS_ENABLED(CONFIG_DRM)
2118
+// ts_data->fb_notif.notifier_call = fb_notifier_callback;
2119
+// #if IS_ENABLED(CONFIG_DRM_PANEL)
2120
+// ret = drm_check_dt(ts_data);
2121
+// if (ret) FTS_ERROR("parse drm-panel fail");
2122
+// FTS_INFO("init notifier with drm_panel_notifier_register");
2123
+// if (active_panel) {
2124
+// ret = drm_panel_notifier_register(active_panel, &ts_data->fb_notif);
2125
+// if (ret) FTS_ERROR("[DRM]drm_panel_notifier_register fail: %d", ret);
2126
+// }
2127
+// #else
2128
+// FTS_INFO("init notifier with msm_drm_register_client");
2129
+// ret = msm_drm_register_client(&ts_data->fb_notif);
2130
+// if (ret) FTS_ERROR("[DRM]msm_drm_register_client fail: %d", ret);
2131
+// #endif //CONFIG_DRM_PANEL
2132
+
2133
+// #elif IS_ENABLED(CONFIG_FB)
2134
+// FTS_INFO("init notifier with fb_register_client");
2135
+// ts_data->fb_notif.notifier_call = fb_notifier_callback;
2136
+// ret = fb_register_client(&ts_data->fb_notif);
2137
+// if (ret) {
2138
+// FTS_ERROR("[FB]Unable to register fb_notifier: %d", ret);
2139
+// }
2140
+
2141
+// #endif //CONFIG_DRM
2142
+ FTS_FUNC_EXIT();
2143
+ return ret;
2144
+}
2145
+
2146
+// static int fts_notifier_callback_exit(struct fts_ts_data *ts_data)
2147
+// {
2148
+// FTS_FUNC_ENTER();
2149
+// #if IS_ENABLED(CONFIG_DRM)
2150
+// #if IS_ENABLED(CONFIG_DRM_PANEL)
2151
+// if (active_panel)
2152
+// drm_panel_notifier_unregister(active_panel, &ts_data->fb_notif);
2153
+// #else
2154
+// if (msm_drm_unregister_client(&ts_data->fb_notif))
2155
+// FTS_ERROR("[DRM]Error occurred while unregistering fb_notifier.");
2156
+// #endif
2157
+
2158
+// #elif IS_ENABLED(CONFIG_FB)
2159
+// if (fb_unregister_client(&ts_data->fb_notif))
2160
+// FTS_ERROR("[FB]Error occurred while unregistering fb_notifier.");
2161
+// #endif //CONFIG_DRM
2162
+// FTS_FUNC_EXIT();
2163
+// return 0;
2164
+// }
2165
+
2166
+
2167
+int fts_ts_probe_entry(struct fts_ts_data *ts_data)
2168
+{
2169
+ int ret = 0;
2170
+
2171
+ FTS_FUNC_ENTER();
2172
+ FTS_INFO("%s", FTS_DRIVER_VERSION);
2173
+ fts_data = ts_data;
2174
+ ts_data->pdata = kzalloc(sizeof(struct fts_ts_platform_data), GFP_KERNEL);
2175
+ if (!ts_data->pdata) {
2176
+ FTS_ERROR("allocate memory for platform_data fail");
2177
+ return -ENOMEM;
2178
+ }
2179
+
2180
+ ret = fts_parse_dt(ts_data->dev, ts_data->pdata);
2181
+ if (ret) {
2182
+ FTS_ERROR("device-tree parse fail");
2183
+ }
2184
+
2185
+ ts_data->ts_workqueue = create_singlethread_workqueue("fts_wq");
2186
+ if (!ts_data->ts_workqueue) {
2187
+ FTS_ERROR("create fts workqueue fail");
2188
+ } else {
2189
+ INIT_WORK(&ts_data->resume_work, fts_resume_work);
2190
+ }
2191
+ spin_lock_init(&ts_data->irq_lock);
2192
+ mutex_init(&ts_data->report_mutex);
2193
+ mutex_init(&ts_data->bus_lock);
2194
+ init_waitqueue_head(&ts_data->ts_waitqueue);
2195
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
2196
+ wakeup_source_init(&ts_data->ws, "fts_ws");
2197
+ ts_data->p_ws = &ts_data->ws;
2198
+#else
2199
+ ts_data->p_ws = wakeup_source_register(ts_data->dev, "fts_ws");
2200
+#endif
2201
+
2202
+ ret = fts_bus_init(ts_data);
2203
+ if (ret) {
2204
+ FTS_ERROR("bus initialize fail");
2205
+ goto err_bus_init;
2206
+ }
2207
+
2208
+ ret = fts_buffer_init(ts_data);
2209
+ if (ret) {
2210
+ FTS_ERROR("buffer init fail");
2211
+ goto err_bus_init;
2212
+ }
2213
+
2214
+ ret = fts_gpio_configure(ts_data);
2215
+ if (ret) {
2216
+ FTS_ERROR("configure the gpios fail");
2217
+ goto err_gpio_config;
2218
+ }
2219
+
2220
+ ret = fts_power_init(ts_data);
2221
+ if (ret) {
2222
+ FTS_ERROR("fail to init power");
2223
+ goto err_power_init;
2224
+ }
2225
+
2226
+ ret = fts_get_ic_information(ts_data);
2227
+ if (ret) {
2228
+ FTS_ERROR("not focal IC, unregister driver");
2229
+ goto err_power_init;
2230
+ }
2231
+
2232
+ ret = fts_input_init(ts_data);
2233
+ if (ret) {
2234
+ FTS_ERROR("input initialize fail");
2235
+ goto err_power_init;
2236
+ }
2237
+
2238
+#if FTS_READ_CUSTOMER_INFO
2239
+ ret = fts_read_customer_information(ts_data);
2240
+ if (ret) {
2241
+ FTS_ERROR("read customer information fail");
2242
+ }
2243
+#endif
2244
+
2245
+ ret = fts_create_apk_debug_channel(ts_data);
2246
+ if (ret) {
2247
+ FTS_ERROR("create apk debug node fail");
2248
+ }
2249
+
2250
+ ret = fts_create_sysfs(ts_data);
2251
+ if (ret) {
2252
+ FTS_ERROR("create sysfs node fail");
2253
+ }
2254
+
2255
+
2256
+
2257
+ ret = fts_point_report_check_init(ts_data);
2258
+ if (ret) {
2259
+ FTS_ERROR("init point report check fail");
2260
+ }
2261
+
2262
+ ret = fts_ex_mode_init(ts_data);
2263
+ if (ret) {
2264
+ FTS_ERROR("init glove/cover/charger fail");
2265
+ }
2266
+
2267
+ ret = fts_gesture_init(ts_data);
2268
+ if (ret) {
2269
+ FTS_ERROR("init gesture fail");
2270
+ }
2271
+
2272
+#if FTS_PSENSOR_EN
2273
+ ret = fts_proximity_init(ts_data);
2274
+ if (ret) {
2275
+ FTS_ERROR("init proximity fail");
2276
+ }
2277
+#endif
2278
+
2279
+
2280
+ ret = fts_esdcheck_init(ts_data);
2281
+ if (ret) {
2282
+ FTS_ERROR("init esd check fail");
2283
+ }
2284
+
2285
+ ret = fts_irq_registration(ts_data);
2286
+ if (ret) {
2287
+ FTS_ERROR("request irq failed");
2288
+ goto err_irq_req;
2289
+ }
2290
+
2291
+ ret = fts_fwupg_init(ts_data);
2292
+ if (ret) {
2293
+ FTS_ERROR("init fw upgrade fail");
2294
+ }
2295
+
2296
+#if IS_ENABLED(CONFIG_PM) && FTS_PATCH_COMERR_PM
2297
+ init_completion(&ts_data->pm_completion);
2298
+ ts_data->pm_suspend = false;
2299
+#endif
2300
+
2301
+ ret = fts_notifier_callback_init(ts_data);
2302
+ if (ret) {
2303
+ FTS_ERROR("init notifier callback fail");
2304
+ }
2305
+
2306
+ FTS_FUNC_EXIT();
2307
+ return 0;
2308
+
2309
+err_irq_req:
2310
+ fts_esdcheck_exit(ts_data);
2311
+#if FTS_PSENSOR_EN
2312
+ fts_proximity_exit(ts_data);
2313
+#endif
2314
+ fts_gesture_exit(ts_data);
2315
+ fts_ex_mode_exit(ts_data);
2316
+ fts_point_report_check_exit(ts_data);
2317
+ fts_remove_sysfs(ts_data);
2318
+ fts_release_apk_debug_channel(ts_data);
2319
+ input_unregister_device(ts_data->input_dev);
2320
+#if FTS_PEN_EN
2321
+ input_unregister_device(ts_data->pen_dev);
2322
+#endif
2323
+err_power_init:
2324
+#if FTS_PINCTRL_EN
2325
+ if (ts_data->pinctrl) {
2326
+ if (ts_data->pins_release) {
2327
+ pinctrl_select_state(ts_data->pinctrl, ts_data->pins_release);
2328
+ }
2329
+ devm_pinctrl_put(ts_data->pinctrl);
2330
+ ts_data->pinctrl = NULL;
2331
+ }
2332
+#endif
2333
+#if FTS_POWER_SOURCE_CUST_EN
2334
+ fts_power_source_exit(ts_data);
2335
+#endif
2336
+ if (gpio_is_valid(ts_data->pdata->reset_gpio))
2337
+ gpio_free(ts_data->pdata->reset_gpio);
2338
+ if (gpio_is_valid(ts_data->pdata->irq_gpio))
2339
+ gpio_free(ts_data->pdata->irq_gpio);
2340
+err_gpio_config:
2341
+ kfree_safe(ts_data->touch_buf);
2342
+err_bus_init:
2343
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
2344
+ wakeup_source_trash(&ts_data->ws);
2345
+ ts_data->p_ws = NULL;
2346
+#else
2347
+ wakeup_source_unregister(ts_data->p_ws);
2348
+#endif
2349
+ cancel_work_sync(&ts_data->resume_work);
2350
+ if (ts_data->ts_workqueue) destroy_workqueue(ts_data->ts_workqueue);
2351
+ kfree_safe(ts_data->bus_tx_buf);
2352
+ kfree_safe(ts_data->bus_rx_buf);
2353
+ kfree_safe(ts_data->pdata);
2354
+
2355
+ FTS_FUNC_EXIT();
2356
+ return ret;
2357
+}
2358
+
2359
+int fts_ts_remove_entry(struct fts_ts_data *ts_data)
2360
+{
2361
+ FTS_FUNC_ENTER();
2362
+ cancel_work_sync(&ts_data->resume_work);
2363
+ // fts_notifier_callback_exit(ts_data);
2364
+ free_irq(ts_data->irq, ts_data);
2365
+ fts_fwupg_exit(ts_data);
2366
+ fts_esdcheck_exit(ts_data);
2367
+#if FTS_PSENSOR_EN
2368
+ fts_proximity_exit(ts_data);
2369
+#endif
2370
+ fts_gesture_exit(ts_data);
2371
+ fts_ex_mode_exit(ts_data);
2372
+ fts_point_report_check_exit(ts_data);
2373
+ fts_remove_sysfs(ts_data);
2374
+ fts_release_apk_debug_channel(ts_data);
2375
+ input_unregister_device(ts_data->input_dev);
2376
+#if FTS_PEN_EN
2377
+ input_unregister_device(ts_data->pen_dev);
2378
+#endif
2379
+ if (ts_data->ts_workqueue) destroy_workqueue(ts_data->ts_workqueue);
2380
+ if (gpio_is_valid(ts_data->pdata->reset_gpio))
2381
+ gpio_free(ts_data->pdata->reset_gpio);
2382
+ if (gpio_is_valid(ts_data->pdata->irq_gpio))
2383
+ gpio_free(ts_data->pdata->irq_gpio);
2384
+
2385
+#if FTS_PINCTRL_EN
2386
+ if (ts_data->pinctrl) {
2387
+ if (ts_data->pins_release) {
2388
+ pinctrl_select_state(ts_data->pinctrl, ts_data->pins_release);
2389
+ }
2390
+ devm_pinctrl_put(ts_data->pinctrl);
2391
+ ts_data->pinctrl = NULL;
2392
+ }
2393
+#endif
2394
+
2395
+#if FTS_POWER_SOURCE_CUST_EN
2396
+ fts_power_source_exit(ts_data);
2397
+#endif
2398
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
2399
+ wakeup_source_trash(&ts_data->ws);
2400
+ ts_data->p_ws = NULL;
2401
+#else
2402
+ wakeup_source_unregister(ts_data->p_ws);
2403
+#endif
2404
+ kfree_safe(ts_data->touch_buf);
2405
+ kfree_safe(ts_data->bus_tx_buf);
2406
+ kfree_safe(ts_data->bus_rx_buf);
2407
+ kfree_safe(ts_data->pdata);
2408
+
2409
+ FTS_FUNC_EXIT();
2410
+ return 0;
2411
+}
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_core.h
....@@ -0,0 +1,426 @@
1
+/*
2
+ *
3
+ * FocalTech TouchScreen driver.
4
+ *
5
+ * Copyright (c) 2012-2020, Focaltech Ltd. All rights reserved.
6
+ *
7
+ * This software is licensed under the terms of the GNU General Public
8
+ * License version 2, as published by the Free Software Foundation, and
9
+ * may be copied, distributed, and modified under those terms.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ */
17
+/*****************************************************************************
18
+*
19
+* File Name: focaltech_core.h
20
+
21
+* Author: Focaltech Driver Team
22
+*
23
+* Created: 2016-08-08
24
+*
25
+* Abstract:
26
+*
27
+* Reference:
28
+*
29
+*****************************************************************************/
30
+
31
+#ifndef __LINUX_FOCALTECH_CORE_H__
32
+#define __LINUX_FOCALTECH_CORE_H__
33
+/*****************************************************************************
34
+* Included header files
35
+*****************************************************************************/
36
+#include <linux/kernel.h>
37
+#include <linux/module.h>
38
+#include <linux/init.h>
39
+#include <linux/device.h>
40
+#include <linux/i2c.h>
41
+#include <linux/spi/spi.h>
42
+#include <linux/input.h>
43
+#include <linux/input/mt.h>
44
+#include <linux/interrupt.h>
45
+#include <linux/irq.h>
46
+#include <linux/delay.h>
47
+#include <linux/slab.h>
48
+#include <linux/vmalloc.h>
49
+#include <linux/gpio.h>
50
+#include <linux/regulator/consumer.h>
51
+#include <linux/uaccess.h>
52
+#include <linux/firmware.h>
53
+#include <linux/debugfs.h>
54
+#include <linux/mutex.h>
55
+#include <linux/workqueue.h>
56
+#include <linux/wait.h>
57
+#include <linux/jiffies.h>
58
+#include <linux/fs.h>
59
+#include <linux/proc_fs.h>
60
+#include <linux/version.h>
61
+#include <linux/types.h>
62
+#include <linux/sched.h>
63
+#include <linux/kthread.h>
64
+#include <linux/dma-mapping.h>
65
+#include <linux/miscdevice.h>
66
+#include <linux/poll.h>
67
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
68
+#include <linux/ktime.h>
69
+#include <linux/timekeeping.h>
70
+#endif
71
+#include "focaltech_common.h"
72
+
73
+/*****************************************************************************
74
+* Private constant and macro definitions using #define
75
+*****************************************************************************/
76
+#define FTS_DRIVER_NAME "fts_ts"
77
+
78
+#define FTS_MAX_POINTS_SUPPORT 10 /* constant value, can't be changed */
79
+#define FTS_MAX_KEYS 4
80
+#define FTS_KEY_DIM 10
81
+#define FTS_COORDS_ARR_SIZE 4
82
+#define FTS_ONE_TCH_LEN 6
83
+#define FTS_ONE_TCH_LEN_V2 8
84
+#define FTS_TOUCH_DATA_LEN_V2 (FTS_MAX_POINTS_SUPPORT * FTS_ONE_TCH_LEN_V2 + 4)
85
+
86
+
87
+#define FTS_TOUCH_DATA_LEN (FTS_MAX_POINTS_SUPPORT * FTS_ONE_TCH_LEN + 2)
88
+
89
+#define FTS_GESTURE_POINTS_MAX 6
90
+#define FTS_GESTURE_DATA_LEN (FTS_GESTURE_POINTS_MAX * 4 + 4)
91
+
92
+#define FTS_SIZE_PEN 15
93
+#define FTS_SIZE_DEFAULT 15
94
+#define FTS_SIZE_DEFAULT_V2 21
95
+
96
+
97
+#define FTS_MAX_ID 0x0A
98
+#define FTS_TOUCH_OFF_E_XH 0
99
+#define FTS_TOUCH_OFF_XL 1
100
+#define FTS_TOUCH_OFF_ID_YH 2
101
+#define FTS_TOUCH_OFF_YL 3
102
+#define FTS_TOUCH_OFF_PRE 4
103
+#define FTS_TOUCH_OFF_AREA 5
104
+#define FTS_TOUCH_OFF_MINOR 6
105
+
106
+#define FTS_TOUCH_E_NUM 1
107
+#define FTS_X_MIN_DISPLAY_DEFAULT 0
108
+#define FTS_Y_MIN_DISPLAY_DEFAULT 0
109
+#define FTS_X_MAX_DISPLAY_DEFAULT (720 - 1)
110
+#define FTS_Y_MAX_DISPLAY_DEFAULT (1280 - 1)
111
+
112
+#define FTS_TOUCH_DOWN 0
113
+#define FTS_TOUCH_UP 1
114
+#define FTS_TOUCH_CONTACT 2
115
+#define EVENT_DOWN(flag) ((FTS_TOUCH_DOWN == flag) || (FTS_TOUCH_CONTACT == flag))
116
+#define EVENT_UP(flag) (FTS_TOUCH_UP == flag)
117
+
118
+#define FTS_MAX_COMPATIBLE_TYPE 8
119
+#define FTS_MAX_COMMMAND_LENGTH 16
120
+
121
+#define FTS_MAX_TOUCH_BUF 4096
122
+#define FTS_MAX_BUS_BUF 4096
123
+
124
+#define FTS_MAX_CUSTOMER_INFO 32
125
+#define FTS_FOD_BUF_LEN 9
126
+
127
+#define FTS_RETVAL_IGNORE_TOUCHES 1
128
+
129
+
130
+/*****************************************************************************
131
+* Alternative mode (When something goes wrong, the modules may be able to solve the problem.)
132
+*****************************************************************************/
133
+/*
134
+ * For commnication error in PM(deep sleep) state
135
+ */
136
+#define FTS_PATCH_COMERR_PM 0
137
+#define FTS_TIMEOUT_COMERR_PM 700
138
+
139
+/*
140
+ * For high resolution
141
+ * Set FTS_TOUCH_HIRES_EN to 1 to support high resolution reporting of touch finger.
142
+ * Set FTS_PEN_HIRES_EN to 1 to support high resolution reporting of stylus pen.
143
+ *
144
+ * FTS_XXX_HIRES_X, a multiple relative to the original resolution
145
+ * FTS_HI_RES_X_MAX, const value, can't be modified
146
+ */
147
+#define FTS_TOUCH_HIRES_EN 0
148
+#define FTS_TOUCH_HIRES_X 10
149
+
150
+#define FTS_PEN_HIRES_EN 1
151
+#define FTS_PEN_HIRES_X 10
152
+
153
+
154
+#define FTS_HI_RES_X_MAX 16
155
+
156
+
157
+/* If need read customer info when probing, max:FTS_MAX_CUSTOMER_INFO */
158
+#define FTS_READ_CUSTOMER_INFO 0
159
+
160
+/*****************************************************************************
161
+* Private enumerations, structures and unions using typedef
162
+*****************************************************************************/
163
+struct ftxxxx_proc {
164
+ struct proc_dir_entry *proc_entry;
165
+ u8 opmode;
166
+ u8 cmd_len;
167
+ u8 cmd[FTS_MAX_COMMMAND_LENGTH];
168
+};
169
+
170
+struct fts_ts_platform_data {
171
+ u32 irq_gpio;
172
+ u32 irq_gpio_flags;
173
+ u32 reset_gpio;
174
+ u32 reset_gpio_flags;
175
+ bool have_key;
176
+ u32 key_number;
177
+ u32 keys[FTS_MAX_KEYS];
178
+ u32 key_y_coords[FTS_MAX_KEYS];
179
+ u32 key_x_coords[FTS_MAX_KEYS];
180
+ u32 x_max;
181
+ u32 y_max;
182
+ u32 x_min;
183
+ u32 y_min;
184
+ u32 max_touch_number;
185
+};
186
+
187
+struct ts_event {
188
+ int x; /*x coordinate */
189
+ int y; /*y coordinate */
190
+ int p; /* pressure */
191
+ int flag; /* touch event flag: 0 -- down; 1-- up; 2 -- contact */
192
+ int id; /*touch ID */
193
+ int area;
194
+ int minor;
195
+};
196
+
197
+struct pen_event {
198
+ int down;
199
+ int inrange;
200
+ int tip;
201
+ int x; /*x coordinate */
202
+ int y; /*y coordinate */
203
+ int p; /* pressure */
204
+ int flag; /* touch event flag: 0 -- down; 1-- up; 2 -- contact */
205
+ int id; /*touch ID */
206
+ int tilt_x;
207
+ int tilt_y;
208
+ int azimuth;
209
+ int tool_type;
210
+};
211
+
212
+struct fts_ts_data {
213
+ struct i2c_client *client;
214
+ struct spi_device *spi;
215
+ u32 spi_speed;
216
+ struct device *dev;
217
+ struct input_dev *input_dev;
218
+ struct input_dev *pen_dev;
219
+ struct fts_ts_platform_data *pdata;
220
+ struct ts_ic_info ic_info;
221
+ struct workqueue_struct *ts_workqueue;
222
+ struct work_struct resume_work;
223
+ struct delayed_work esdcheck_work;
224
+ struct delayed_work prc_work;
225
+ struct delayed_work fwdbg_work;
226
+ wait_queue_head_t ts_waitqueue;
227
+ struct ftxxxx_proc proc;
228
+ struct ftxxxx_proc proc_ta;
229
+ spinlock_t irq_lock;
230
+ struct mutex report_mutex;
231
+ struct mutex bus_lock;
232
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
233
+ struct wakeup_source ws;
234
+#endif
235
+ struct wakeup_source *p_ws;
236
+ unsigned long intr_jiffies;
237
+ int irq;
238
+ int log_level;
239
+ int fw_is_running; /* confirm fw is running when using spi:default 0 */
240
+ int dummy_byte;
241
+#if IS_ENABLED(CONFIG_PM) && FTS_PATCH_COMERR_PM
242
+ struct completion pm_completion;
243
+ bool pm_suspend;
244
+#endif
245
+ bool suspended;
246
+ bool need_work_in_suspend;
247
+ bool fw_loading;
248
+ bool irq_disabled;
249
+ bool power_disabled;
250
+ bool glove_mode;
251
+ bool cover_mode;
252
+ bool charger_mode;
253
+ bool earphone_mode;
254
+ bool edgepalm_mode;
255
+ bool touch_analysis_support;
256
+ bool prc_support;
257
+ bool prc_mode;
258
+ bool esd_support;
259
+ bool fod_mode;
260
+ bool proximity_mode;
261
+ bool fhp_mode;
262
+
263
+ bool fwdbg_support;
264
+ bool gesture_support; /* gesture enable or disable, default: disable */
265
+ u8 gesture_bmode; /*gesture buffer mode*/
266
+
267
+ int fod_fp_down;
268
+ int edgepalm_value;
269
+ int fwdbg_value;
270
+
271
+ u8 pen_etype;
272
+ struct pen_event pevent;
273
+ struct ts_event events[FTS_MAX_POINTS_SUPPORT]; /* multi-touch */
274
+ u8 touch_addr;
275
+ u32 touch_size;
276
+ u8 *touch_buf;
277
+ int touch_event_num;
278
+ int touch_points;
279
+ int key_state;
280
+ int ta_flag;
281
+ u32 ta_size;
282
+ u8 *ta_buf;
283
+
284
+ u8 *bus_tx_buf;
285
+ u8 *bus_rx_buf;
286
+ int bus_type;
287
+ int bus_ver;
288
+ char customer_info[FTS_MAX_CUSTOMER_INFO];
289
+ struct regulator *vdd;
290
+ struct regulator *iovcc;
291
+#if FTS_PINCTRL_EN
292
+ struct pinctrl *pinctrl;
293
+ struct pinctrl_state *pins_active;
294
+ struct pinctrl_state *pins_suspend;
295
+ struct pinctrl_state *pins_release;
296
+#endif
297
+ struct notifier_block fb_notif;
298
+};
299
+
300
+enum _FTS_BUS_TYPE {
301
+ BUS_TYPE_NONE,
302
+ BUS_TYPE_I2C,
303
+ BUS_TYPE_SPI,
304
+};
305
+
306
+enum _FTS_BUS_VER {
307
+ BUS_VER_DEFAULT = 1,
308
+ BUS_VER_V2,
309
+};
310
+
311
+enum _FTS_TOUCH_ETYPE {
312
+ TOUCH_DEFAULT = 0x00,
313
+ TOUCH_PROTOCOL_v2 = 0x02,
314
+ TOUCH_PEN = 0x0B,
315
+ TOUCH_FW_INIT = 0x81,
316
+ TOUCH_IGNORE = 0xFE,
317
+ TOUCH_FWDBG = 0x0E,
318
+ TOUCH_ERROR = 0xFF,
319
+};
320
+
321
+enum _FTS_STYLUS_ETYPE {
322
+ STYLUS_DEFAULT,
323
+ STYLUS_HOVER,
324
+};
325
+
326
+enum _FTS_GESTURE_BMODE {
327
+ GESTURE_BM_REG,
328
+ GESTURE_BM_TOUCH,
329
+};
330
+
331
+enum _FTS_FW_MODE {
332
+ FW_MODE_NORMAL = 0xAA,
333
+ FW_MODE_FACTORY = 0x55,
334
+ FW_MODE_GESTURE = 0x66,
335
+};
336
+
337
+
338
+/*****************************************************************************
339
+* Global variable or extern global variabls/functions
340
+*****************************************************************************/
341
+extern struct fts_ts_data *fts_data;
342
+
343
+
344
+/* communication interface */
345
+int fts_read(u8 *cmd, u32 cmdlen, u8 *data, u32 datalen);
346
+int fts_read_reg(u8 addr, u8 *value);
347
+int fts_write(u8 *writebuf, u32 writelen);
348
+int fts_write_reg(u8 addr, u8 value);
349
+int fts_bus_configure(struct fts_ts_data *ts_data, u8 *buf, u32 size);
350
+int fts_bus_transfer_direct(u8 *writebuf, u32 writelen, u8 *readbuf, u32 readlen);
351
+int fts_bus_set_speed(struct fts_ts_data *ts_data, u32 speed);
352
+int fts_hid2std(int mode);
353
+int fts_ts_probe_entry(struct fts_ts_data *ts_data);
354
+int fts_ts_remove_entry(struct fts_ts_data *ts_data);
355
+
356
+/* Gesture functions */
357
+int fts_gesture_init(struct fts_ts_data *ts_data);
358
+int fts_gesture_exit(struct fts_ts_data *ts_data);
359
+void fts_gesture_recovery(struct fts_ts_data *ts_data);
360
+int fts_gesture_readdata(struct fts_ts_data *ts_data, u8 *data);
361
+int fts_gesture_suspend(struct fts_ts_data *ts_data);
362
+int fts_gesture_resume(struct fts_ts_data *ts_data);
363
+
364
+#if FTS_FOD_EN
365
+void fts_fod_enable(int enable);
366
+#endif
367
+
368
+/* Apk and functions */
369
+int fts_create_apk_debug_channel(struct fts_ts_data *);
370
+void fts_release_apk_debug_channel(struct fts_ts_data *);
371
+
372
+/* ADB functions */
373
+int fts_create_sysfs(struct fts_ts_data *ts_data);
374
+int fts_remove_sysfs(struct fts_ts_data *ts_data);
375
+
376
+/* ESD */
377
+int fts_esdcheck_init(struct fts_ts_data *ts_data);
378
+int fts_esdcheck_exit(struct fts_ts_data *ts_data);
379
+void fts_esdcheck_switch(struct fts_ts_data *ts_data, bool enable);
380
+void fts_esdcheck_proc_busy(struct fts_ts_data *ts_data, bool proc_debug);
381
+void fts_esdcheck_suspend(struct fts_ts_data *ts_data);
382
+void fts_esdcheck_resume(struct fts_ts_data *ts_data);
383
+bool fts_esdcheck_is_running(struct fts_ts_data *ts_data);
384
+
385
+
386
+/* Host test */
387
+
388
+/* Point Report Check*/
389
+int fts_point_report_check_init(struct fts_ts_data *ts_data);
390
+int fts_point_report_check_exit(struct fts_ts_data *ts_data);
391
+void fts_prc_queue_work(struct fts_ts_data *ts_data);
392
+
393
+/* FW upgrade */
394
+int fts_fwupg_init(struct fts_ts_data *ts_data);
395
+int fts_fwupg_exit(struct fts_ts_data *ts_data);
396
+int fts_upgrade_bin(char *fw_name, bool force);
397
+int fts_enter_test_environment(bool test_state);
398
+int fts_enter_normal_fw(void);
399
+
400
+/* Other */
401
+void fts_msleep(unsigned long msecs);
402
+int fts_set_reset(struct fts_ts_data *ts_data, int value);
403
+int fts_reset_proc(struct fts_ts_data *ts_data, int force, int hdelayms);
404
+int fts_check_cid(struct fts_ts_data *ts_data, u8 id_h);
405
+int fts_wait_tp_to_valid(void);
406
+void fts_release_all_finger(void);
407
+void fts_tp_state_recovery(struct fts_ts_data *ts_data);
408
+int fts_ex_mode_init(struct fts_ts_data *ts_data);
409
+int fts_ex_mode_exit(struct fts_ts_data *ts_data);
410
+int fts_ex_mode_recovery(struct fts_ts_data *ts_data);
411
+int fts_input_report_buffer(struct fts_ts_data *ts_data, u8 *touch_buf);
412
+
413
+void fts_irq_disable(void);
414
+void fts_irq_enable(void);
415
+
416
+#if FTS_PSENSOR_EN
417
+int fts_proximity_init(struct fts_ts_data *ts_data);
418
+int fts_proximity_exit(struct fts_ts_data *ts_data);
419
+int fts_proximity_readdata(struct fts_ts_data *ts_data);
420
+int fts_proximity_suspend(struct fts_ts_data *ts_data);
421
+int fts_proximity_resume(struct fts_ts_data *ts_data);
422
+int fts_proximity_recovery(struct fts_ts_data *ts_data);
423
+#endif
424
+
425
+
426
+#endif /* __LINUX_FOCALTECH_CORE_H__ */
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_esdcheck.c
....@@ -0,0 +1,442 @@
1
+/*
2
+ *
3
+ * FocalTech TouchScreen driver.
4
+ *
5
+ * Copyright (c) 2012-2020, FocalTech Systems, Ltd., all rights reserved.
6
+ *
7
+ * This software is licensed under the terms of the GNU General Public
8
+ * License version 2, as published by the Free Software Foundation, and
9
+ * may be copied, distributed, and modified under those terms.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ */
17
+
18
+/*****************************************************************************
19
+*
20
+* File Name: focaltech_esdcheck.c
21
+*
22
+* Author: Focaltech Driver Team
23
+*
24
+* Created: 2016-08-03
25
+*
26
+* Abstract: ESD check function
27
+*
28
+* Version: v1.0
29
+*
30
+* Revision History:
31
+* v1.0:
32
+* First release. By luougojin 2016-08-03
33
+* v1.1: By luougojin 2017-02-15
34
+* 1. Add LCD_ESD_PATCH to control idc_esdcheck_lcderror
35
+*****************************************************************************/
36
+
37
+/*****************************************************************************
38
+* Included header files
39
+*****************************************************************************/
40
+#include "focaltech_core.h"
41
+
42
+/*****************************************************************************
43
+* Private constant and macro definitions using #define
44
+*****************************************************************************/
45
+#define ESDCHECK_WAIT_TIME 1000 /* ms */
46
+#define LCD_ESD_PATCH 0
47
+#define ESDCHECK_INTRCNT_MAX 2
48
+#define ESD_INTR_INTERVALS 200 /* unit:ms */
49
+
50
+/*****************************************************************************
51
+* Private enumerations, structures and unions using typedef
52
+*****************************************************************************/
53
+struct fts_esdcheck_st {
54
+ u8 mode : 1; /* 1- esd check is running 0- esd check is stop */
55
+ u8 suspend : 1;
56
+ u8 proc_debug : 1; /* apk or adb use */
57
+ u8 intr : 1; /* 1- Interrupt trigger */
58
+ u8 unused : 4;
59
+ u8 intr_cnt;
60
+ u8 flow_work_hold_cnt; /* Flow Work Cnt(reg0x91) keep a same value for x times. >=5 times is ESD, need reset */
61
+ u8 flow_work_cnt_last; /* Save Flow Work Cnt(reg0x91) value */
62
+ u32 hardware_reset_cnt;
63
+ u32 nack_cnt;
64
+ u32 dataerror_cnt;
65
+};
66
+
67
+
68
+/*****************************************************************************
69
+* Static variables
70
+*****************************************************************************/
71
+static struct fts_esdcheck_st fts_esdcheck_data;
72
+
73
+/*****************************************************************************
74
+* Global variable or extern global variabls/functions
75
+*****************************************************************************/
76
+
77
+/*****************************************************************************
78
+* Static function prototypes
79
+*****************************************************************************/
80
+
81
+/*****************************************************************************
82
+* functions body
83
+*****************************************************************************/
84
+#if LCD_ESD_PATCH
85
+int lcd_need_reset;
86
+static int tp_need_recovery; /* LCD reset cause Tp reset */
87
+int idc_esdcheck_lcderror(struct fts_ts_data *ts_data)
88
+{
89
+ int ret = 0;
90
+ u8 val = 0;
91
+
92
+ FTS_DEBUG("check LCD ESD");
93
+ if ( (tp_need_recovery == 1) && (lcd_need_reset == 0) ) {
94
+ tp_need_recovery = 0;
95
+ /* LCD reset, need recover TP state */
96
+ fts_release_all_finger();
97
+ fts_tp_state_recovery(ts_data);
98
+ }
99
+
100
+ ret = fts_read_reg(FTS_REG_ESD_SATURATE, &val);
101
+ if ( ret < 0) {
102
+ FTS_ERROR("read reg0xED fail,ret:%d", ret);
103
+ return -EIO;
104
+ }
105
+
106
+ if (val == 0xAA) {
107
+ /*
108
+ * 1. Set flag lcd_need_reset = 1;
109
+ * 2. LCD driver need reset(recovery) LCD and set lcd_need_reset to 0
110
+ * 3. recover TP state
111
+ */
112
+ FTS_INFO("LCD ESD, need execute LCD reset");
113
+ lcd_need_reset = 1;
114
+ tp_need_recovery = 1;
115
+ }
116
+
117
+ return 0;
118
+}
119
+#endif
120
+
121
+static int fts_esdcheck_tp_reset(struct fts_ts_data *ts_data)
122
+{
123
+ FTS_FUNC_ENTER();
124
+
125
+ fts_esdcheck_data.flow_work_hold_cnt = 0;
126
+ fts_esdcheck_data.hardware_reset_cnt++;
127
+
128
+ fts_reset_proc(ts_data, false, 200);
129
+ fts_release_all_finger();
130
+ fts_tp_state_recovery(ts_data);
131
+
132
+ FTS_FUNC_EXIT();
133
+ return 0;
134
+}
135
+
136
+static bool get_chip_id(struct fts_ts_data *ts_data)
137
+{
138
+ int ret = 0;
139
+ int i = 0;
140
+ u8 idh = 0;
141
+ u8 chip_id = ts_data->ic_info.ids.chip_idh;
142
+
143
+ for (i = 0; i < 3; i++) {
144
+ ret = fts_read_reg(FTS_REG_CHIP_ID, &idh);
145
+ if (ret < 0) {
146
+ FTS_ERROR("read chip id fail,ret:%d", ret);
147
+ fts_esdcheck_data.nack_cnt++;
148
+ } else {
149
+ if ((idh == chip_id) || (fts_check_cid(ts_data, idh) == 0)) {
150
+ break;
151
+ } else {
152
+ FTS_DEBUG("read chip_id:%x,retry:%d", idh, i);
153
+ fts_esdcheck_data.dataerror_cnt++;
154
+ }
155
+ }
156
+ fts_msleep(10);
157
+ }
158
+
159
+ /* if can't get correct data in 3 times, then need hardware reset */
160
+ if (i >= 3) {
161
+ FTS_ERROR("read chip id 3 times fail, need execute TP reset");
162
+ return true;
163
+ }
164
+
165
+ return false;
166
+}
167
+
168
+/*****************************************************************************
169
+* Name: get_flow_cnt
170
+* Brief: Read flow cnt(0x91)
171
+* Input:
172
+* Output:
173
+* Return: 1(true) - Reg 0x91(flow cnt) abnormal: hold a value for 5 times
174
+* 0(false) - Reg 0x91(flow cnt) normal
175
+*****************************************************************************/
176
+static bool get_flow_cnt(struct fts_ts_data *ts_data)
177
+{
178
+ int ret = 0;
179
+ u8 reg_value = 0;
180
+ u8 reg_addr = 0;
181
+
182
+ reg_addr = FTS_REG_FLOW_WORK_CNT;
183
+ ret = fts_read(&reg_addr, 1, &reg_value, 1);
184
+ if (ret < 0) {
185
+ FTS_ERROR("read reg0x91 fail,ret:%d", ret);
186
+ fts_esdcheck_data.nack_cnt++;
187
+ } else {
188
+ if ( reg_value == fts_esdcheck_data.flow_work_cnt_last ) {
189
+ FTS_DEBUG("reg0x91,val:%x,last:%x", reg_value,
190
+ fts_esdcheck_data.flow_work_cnt_last);
191
+ fts_esdcheck_data.flow_work_hold_cnt++;
192
+ } else {
193
+ fts_esdcheck_data.flow_work_hold_cnt = 0;
194
+ }
195
+
196
+ fts_esdcheck_data.flow_work_cnt_last = reg_value;
197
+ }
198
+
199
+ /* Flow Work Cnt keep a value for 5 times, need execute TP reset */
200
+ if (fts_esdcheck_data.flow_work_hold_cnt >= 5) {
201
+ FTS_DEBUG("reg0x91 keep a value for 5 times, need execute TP reset");
202
+ return true;
203
+ }
204
+
205
+ return false;
206
+}
207
+
208
+static int esdcheck_algorithm(struct fts_ts_data *ts_data)
209
+{
210
+ int ret = 0;
211
+ u8 reg_value = 0;
212
+ u8 reg_addr = 0;
213
+ bool hardware_reset = 0;
214
+ unsigned long intr_timeout = msecs_to_jiffies(ESD_INTR_INTERVALS);
215
+
216
+ /* 1. esdcheck is interrupt, then return */
217
+ intr_timeout += ts_data->intr_jiffies;
218
+ if (time_before(jiffies, intr_timeout)) {
219
+ return 0;
220
+ }
221
+
222
+ /* 2. check power state, if suspend, no need check esd */
223
+ if (fts_esdcheck_data.suspend == 1) {
224
+ FTS_DEBUG("In suspend, not check esd");
225
+ /* because in suspend state, adb can be used, when upgrade FW, will
226
+ * active ESD check(active = 1); But in suspend, then will don't
227
+ * queue_delayed_work, when resume, don't check ESD again
228
+ */
229
+ return 0;
230
+ }
231
+
232
+ /* 3. check fts_esdcheck_data.proc_debug state, if 1-proc busy, no need check esd*/
233
+ if (fts_esdcheck_data.proc_debug == 1) {
234
+ FTS_INFO("In apk/adb command mode, not check esd");
235
+ return 0;
236
+ }
237
+
238
+ /* 4. In factory mode, can't check esd */
239
+ reg_addr = FTS_REG_WORKMODE;
240
+ ret = fts_read_reg(reg_addr, &reg_value);
241
+ if ( ret < 0 ) {
242
+ fts_esdcheck_data.nack_cnt++;
243
+ } else if ( (reg_value & 0x70) == FTS_REG_WORKMODE_FACTORY_VALUE) {
244
+ FTS_DEBUG("in factory mode(%x), no check esd", reg_value);
245
+ return 0;
246
+ }
247
+
248
+ /* 5. Get Chip ID */
249
+ hardware_reset = get_chip_id(ts_data);
250
+
251
+ /* 6. get Flow work cnt: 0x91 If no change for 5 times, then ESD and reset */
252
+ if (!hardware_reset) {
253
+ hardware_reset = get_flow_cnt(ts_data);
254
+ }
255
+
256
+ /* 7. If need hardware reset, then handle it here */
257
+ if (hardware_reset == 1) {
258
+ FTS_DEBUG("NoACK=%d, Error Data=%d, Hardware Reset=%d",
259
+ fts_esdcheck_data.nack_cnt,
260
+ fts_esdcheck_data.dataerror_cnt,
261
+ fts_esdcheck_data.hardware_reset_cnt);
262
+ fts_esdcheck_tp_reset(ts_data);
263
+ }
264
+
265
+ return 0;
266
+}
267
+
268
+static void esdcheck_func(struct work_struct *work)
269
+{
270
+ struct fts_ts_data *ts_data = container_of(work,
271
+ struct fts_ts_data, esdcheck_work.work);
272
+
273
+ if (ts_data->esd_support) {
274
+#if LCD_ESD_PATCH
275
+ idc_esdcheck_lcderror(ts_data);
276
+#endif
277
+ esdcheck_algorithm(ts_data);
278
+ queue_delayed_work(ts_data->ts_workqueue, &ts_data->esdcheck_work,
279
+ msecs_to_jiffies(ESDCHECK_WAIT_TIME));
280
+ }
281
+}
282
+
283
+/*****************************************************************************
284
+* Name: fts_esdcheck_proc_busy
285
+* Brief: When APK or ADB command access TP via driver, then need set proc_debug,
286
+* then will not check ESD.
287
+* Input:
288
+* Output:
289
+* Return:
290
+*****************************************************************************/
291
+void fts_esdcheck_proc_busy(struct fts_ts_data *ts_data, bool proc_debug)
292
+{
293
+ if (ts_data->esd_support) {
294
+ fts_esdcheck_data.proc_debug = proc_debug;
295
+ }
296
+}
297
+
298
+/*****************************************************************************
299
+* Name: fts_esdcheck_switch
300
+* Brief: FTS esd check function switch.
301
+* Input: enable: 1 - Enable esd check
302
+* 0 - Disable esd check
303
+* Output:
304
+* Return:
305
+*****************************************************************************/
306
+void fts_esdcheck_switch(struct fts_ts_data *ts_data, bool enable)
307
+{
308
+ if (ts_data->esd_support) {
309
+ if (fts_esdcheck_data.mode ^ enable) {
310
+ if (enable) {
311
+ FTS_INFO("ESD check start");
312
+ fts_esdcheck_data.flow_work_hold_cnt = 0;
313
+ fts_esdcheck_data.flow_work_cnt_last = 0;
314
+ fts_esdcheck_data.intr = 0;
315
+ fts_esdcheck_data.intr_cnt = 0;
316
+ fts_esdcheck_data.mode = ENABLE;
317
+ queue_delayed_work(ts_data->ts_workqueue,
318
+ &ts_data->esdcheck_work,
319
+ msecs_to_jiffies(ESDCHECK_WAIT_TIME));
320
+ } else {
321
+ FTS_INFO("ESD check stop");
322
+ cancel_delayed_work_sync(&ts_data->esdcheck_work);
323
+ fts_esdcheck_data.mode = DISABLE;
324
+ }
325
+ }
326
+ }
327
+}
328
+
329
+void fts_esdcheck_suspend(struct fts_ts_data *ts_data)
330
+{
331
+ if (ts_data->esd_support) {
332
+ FTS_FUNC_ENTER();
333
+ fts_esdcheck_switch(ts_data, DISABLE);
334
+ fts_esdcheck_data.suspend = 1;
335
+ fts_esdcheck_data.intr = 0;
336
+ fts_esdcheck_data.intr_cnt = 0;
337
+ FTS_FUNC_EXIT();
338
+ }
339
+}
340
+
341
+void fts_esdcheck_resume(struct fts_ts_data *ts_data)
342
+{
343
+ if (ts_data->esd_support) {
344
+ FTS_FUNC_ENTER();
345
+ fts_esdcheck_switch(ts_data, ENABLE);
346
+ fts_esdcheck_data.suspend = 0;
347
+ fts_esdcheck_data.intr = 0;
348
+ fts_esdcheck_data.intr_cnt = 0;
349
+ FTS_FUNC_EXIT();
350
+ }
351
+}
352
+
353
+static ssize_t fts_esdcheck_store(
354
+ struct device *dev,
355
+ struct device_attribute *attr, const char *buf, size_t count)
356
+{
357
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
358
+ struct input_dev *input_dev = ts_data->input_dev;
359
+
360
+ mutex_lock(&input_dev->mutex);
361
+ if (FTS_SYSFS_ECHO_ON(buf)) {
362
+ FTS_INFO("enable esdcheck");
363
+ ts_data->esd_support = ENABLE;
364
+ if (!ts_data->suspended) fts_esdcheck_switch(ts_data, ENABLE);
365
+ } else if (FTS_SYSFS_ECHO_OFF(buf)) {
366
+ FTS_INFO("disable esdcheck");
367
+ fts_esdcheck_switch(ts_data, DISABLE);
368
+ ts_data->esd_support = DISABLE;
369
+ }
370
+ mutex_unlock(&input_dev->mutex);
371
+
372
+ return count;
373
+}
374
+
375
+static ssize_t fts_esdcheck_show(
376
+ struct device *dev, struct device_attribute *attr, char *buf)
377
+{
378
+ int count;
379
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
380
+ struct input_dev *input_dev = ts_data->input_dev;
381
+
382
+ mutex_lock(&input_dev->mutex);
383
+ count = snprintf(buf, PAGE_SIZE, "Esd check: %s\n", \
384
+ ts_data->esd_support ? "On" : "Off");
385
+ mutex_unlock(&input_dev->mutex);
386
+
387
+ return count;
388
+}
389
+
390
+/* sysfs esd node
391
+ * read example: cat fts_esd_mode ---read esd mode
392
+ * write example:echo 01 > fts_esd_mode ---make esdcheck enable
393
+ *
394
+ */
395
+static DEVICE_ATTR (fts_esd_mode, S_IRUGO | S_IWUSR, fts_esdcheck_show, fts_esdcheck_store);
396
+
397
+static struct attribute *fts_esd_mode_attrs[] = {
398
+
399
+ &dev_attr_fts_esd_mode.attr,
400
+ NULL,
401
+};
402
+
403
+static struct attribute_group fts_esdcheck_group = {
404
+ .attrs = fts_esd_mode_attrs,
405
+};
406
+
407
+bool fts_esdcheck_is_running(struct fts_ts_data *ts_data)
408
+{
409
+ return fts_esdcheck_data.mode;
410
+}
411
+
412
+int fts_esdcheck_init(struct fts_ts_data *ts_data)
413
+{
414
+ FTS_FUNC_ENTER();
415
+
416
+ if (ts_data->ts_workqueue) {
417
+ INIT_DELAYED_WORK(&ts_data->esdcheck_work, esdcheck_func);
418
+ } else {
419
+ FTS_ERROR("fts workqueue is NULL, can't run esd check function");
420
+ return -EINVAL;
421
+ }
422
+
423
+ memset((u8 *)&fts_esdcheck_data, 0, sizeof(struct fts_esdcheck_st));
424
+ fts_esdcheck_data.mode = DISABLE;
425
+ ts_data->esd_support = FTS_ESDCHECK_EN;
426
+ if (sysfs_create_group(&ts_data->dev->kobj, &fts_esdcheck_group)) {
427
+ FTS_ERROR("fts_create_esd_sysfs(sysfs) create fail");
428
+ sysfs_remove_group(&ts_data->dev->kobj, &fts_esdcheck_group);
429
+ }
430
+ fts_esdcheck_switch(ts_data, ENABLE);
431
+ FTS_FUNC_EXIT();
432
+ return 0;
433
+}
434
+
435
+int fts_esdcheck_exit(struct fts_ts_data *ts_data)
436
+{
437
+ fts_esdcheck_data.mode = DISABLE;
438
+ ts_data->esd_support = DISABLE;
439
+ cancel_delayed_work_sync(&ts_data->esdcheck_work);
440
+ sysfs_remove_group(&ts_data->dev->kobj, &fts_esdcheck_group);
441
+ return 0;
442
+}
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_ex_fun.c
....@@ -0,0 +1,1269 @@
1
+/*
2
+ *
3
+ * FocalTech TouchScreen driver.
4
+ *
5
+ * Copyright (c) 2012-2020, Focaltech Ltd. All rights reserved.
6
+ *
7
+ * This software is licensed under the terms of the GNU General Public
8
+ * License version 2, as published by the Free Software Foundation, and
9
+ * may be copied, distributed, and modified under those terms.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ */
17
+
18
+/*****************************************************************************
19
+*
20
+* File Name: Focaltech_ex_fun.c
21
+*
22
+* Author: Focaltech Driver Team
23
+*
24
+* Created: 2016-08-08
25
+*
26
+* Abstract:
27
+*
28
+* Reference:
29
+*
30
+*****************************************************************************/
31
+
32
+/*****************************************************************************
33
+* 1.Included header files
34
+*****************************************************************************/
35
+#include "focaltech_core.h"
36
+
37
+/*****************************************************************************
38
+* Private constant and macro definitions using #define
39
+*****************************************************************************/
40
+#define PROC_UPGRADE 0
41
+#define PROC_READ_REGISTER 1
42
+#define PROC_WRITE_REGISTER 2
43
+#define PROC_AUTOCLB 4
44
+#define PROC_UPGRADE_INFO 5
45
+#define PROC_WRITE_DATA 6
46
+#define PROC_READ_DATA 7
47
+#define PROC_SET_TEST_FLAG 8
48
+#define PROC_SET_SLAVE_ADDR 10
49
+#define PROC_HW_RESET 11
50
+#define PROC_READ_STATUS 12
51
+#define PROC_SET_BOOT_MODE 13
52
+#define PROC_ENTER_TEST_ENVIRONMENT 14
53
+#define PROC_WRITE_DATA_DIRECT 16
54
+#define PROC_READ_DATA_DIRECT 17
55
+#define PROC_CONFIGURE 18
56
+#define PROC_CONFIGURE_INTR 20
57
+#define PROC_GET_DRIVER_INFO 21
58
+#define PROC_NAME "ftxxxx-debug"
59
+#define PROC_BUF_SIZE 256
60
+
61
+/*****************************************************************************
62
+* Private enumerations, structures and unions using typedef
63
+*****************************************************************************/
64
+enum {
65
+ RWREG_OP_READ = 0,
66
+ RWREG_OP_WRITE = 1,
67
+};
68
+
69
+/*****************************************************************************
70
+* Static variables
71
+*****************************************************************************/
72
+static struct rwreg_operation_t {
73
+ int type; /* 0: read, 1: write */
74
+ int reg; /* register */
75
+ int len; /* read/write length */
76
+ int val; /* length = 1; read: return value, write: op return */
77
+ int res; /* 0: success, otherwise: fail */
78
+ char *opbuf; /* length >= 1, read return value, write: op return */
79
+} rw_op;
80
+
81
+/*****************************************************************************
82
+* Global variable or extern global variabls/functions
83
+*****************************************************************************/
84
+
85
+/*****************************************************************************
86
+* Static function prototypes
87
+*****************************************************************************/
88
+static ssize_t fts_debug_write(
89
+ struct file *filp, const char __user *buff, size_t count, loff_t *ppos)
90
+{
91
+ u8 *writebuf = NULL;
92
+ u8 tmpbuf[PROC_BUF_SIZE] = { 0 };
93
+ int buflen = count;
94
+ int writelen = 0;
95
+ int ret = 0;
96
+ char tmp[PROC_BUF_SIZE];
97
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0))
98
+ struct fts_ts_data *ts_data = pde_data(file_inode(filp));
99
+#else
100
+ struct fts_ts_data *ts_data = PDE_DATA(file_inode(filp));
101
+#endif
102
+ struct ftxxxx_proc *proc = &ts_data->proc;
103
+
104
+ if (buflen < 1) {
105
+ FTS_ERROR("apk proc count(%d) fail", buflen);
106
+ return -EINVAL;
107
+ }
108
+
109
+ if (buflen > PROC_BUF_SIZE) {
110
+ writebuf = (u8 *)kzalloc(buflen * sizeof(u8), GFP_KERNEL);
111
+ if (NULL == writebuf) {
112
+ FTS_ERROR("apk proc wirte buf zalloc fail");
113
+ return -ENOMEM;
114
+ }
115
+ } else {
116
+ writebuf = tmpbuf;
117
+ }
118
+
119
+ if (copy_from_user(writebuf, buff, buflen)) {
120
+ FTS_ERROR("[APK]: copy from user error!!");
121
+ ret = -EFAULT;
122
+ goto proc_write_err;
123
+ }
124
+
125
+ proc->opmode = writebuf[0];
126
+ if (buflen == 1) {
127
+ ret = buflen;
128
+ goto proc_write_err;
129
+ }
130
+
131
+ switch (proc->opmode) {
132
+ case PROC_SET_TEST_FLAG:
133
+ FTS_DEBUG("[APK]: PROC_SET_TEST_FLAG = %x", writebuf[1]);
134
+ if (writebuf[1] == 0) {
135
+ if (!ts_data->suspended) fts_esdcheck_switch(ts_data, ENABLE);
136
+ } else {
137
+ fts_esdcheck_switch(ts_data, DISABLE);
138
+ }
139
+ break;
140
+
141
+ case PROC_READ_REGISTER:
142
+ proc->cmd[0] = writebuf[1];
143
+ break;
144
+
145
+ case PROC_WRITE_REGISTER:
146
+ ret = fts_write_reg(writebuf[1], writebuf[2]);
147
+ if (ret < 0) {
148
+ FTS_ERROR("PROC_WRITE_REGISTER write error");
149
+ goto proc_write_err;
150
+ }
151
+ break;
152
+
153
+ case PROC_READ_DATA:
154
+ writelen = buflen - 1;
155
+ if (writelen >= FTS_MAX_COMMMAND_LENGTH) {
156
+ FTS_ERROR("cmd(PROC_READ_DATA) length(%d) fail", writelen);
157
+ goto proc_write_err;
158
+ }
159
+ memcpy(proc->cmd, writebuf + 1, writelen);
160
+ proc->cmd_len = writelen;
161
+ if (ts_data->bus_type == BUS_TYPE_I2C) {
162
+ ret = fts_write(writebuf + 1, writelen);
163
+ if (ret < 0) {
164
+ FTS_ERROR("PROC_READ_DATA write error");
165
+ goto proc_write_err;
166
+ }
167
+ }
168
+ break;
169
+
170
+ case PROC_WRITE_DATA:
171
+ writelen = buflen - 1;
172
+ ret = fts_write(writebuf + 1, writelen);
173
+ if (ret < 0) {
174
+ FTS_ERROR("PROC_WRITE_DATA write error");
175
+ goto proc_write_err;
176
+ }
177
+ break;
178
+
179
+ case PROC_SET_SLAVE_ADDR:
180
+ if (ts_data->bus_type == BUS_TYPE_I2C) {
181
+ fts_bus_configure(ts_data, &writebuf[1], buflen - 1);
182
+ }
183
+ break;
184
+
185
+ case PROC_HW_RESET:
186
+ if (buflen < PROC_BUF_SIZE) {
187
+ memcpy(tmp, writebuf + 1, buflen - 1);
188
+ tmp[buflen - 1] = '\0';
189
+ if (strncmp(tmp, "focal_driver", 12) == 0) {
190
+ FTS_INFO("APK execute HW Reset");
191
+ fts_reset_proc(ts_data, false, 0);
192
+ }
193
+ }
194
+ break;
195
+
196
+ case PROC_SET_BOOT_MODE:
197
+ FTS_DEBUG("[APK]: PROC_SET_BOOT_MODE = %x", writebuf[1]);
198
+ if (0 == writebuf[1]) {
199
+ ts_data->fw_is_running = true;
200
+ } else {
201
+ ts_data->fw_is_running = false;
202
+ }
203
+ break;
204
+
205
+ case PROC_ENTER_TEST_ENVIRONMENT:
206
+ FTS_DEBUG("[APK]: PROC_ENTER_TEST_ENVIRONMENT = %x", writebuf[1]);
207
+ if (0 == writebuf[1]) {
208
+ fts_enter_test_environment(0);
209
+ } else {
210
+ fts_enter_test_environment(1);
211
+ }
212
+ break;
213
+
214
+ case PROC_READ_DATA_DIRECT:
215
+ writelen = buflen - 1;
216
+ if (writelen >= FTS_MAX_COMMMAND_LENGTH) {
217
+ FTS_ERROR("cmd(PROC_READ_DATA_DIRECT) length(%d) fail", writelen);
218
+ goto proc_write_err;
219
+ }
220
+ memcpy(proc->cmd, writebuf + 1, writelen);
221
+ proc->cmd_len = writelen;
222
+ break;
223
+
224
+ case PROC_WRITE_DATA_DIRECT:
225
+ writelen = buflen - 1;
226
+ ret = fts_bus_transfer_direct(writebuf + 1, writelen, NULL, 0);
227
+ if (ret < 0) {
228
+ FTS_ERROR("PROC_WRITE_DATA_DIRECT write error");
229
+ goto proc_write_err;
230
+ }
231
+ break;
232
+
233
+ case PROC_CONFIGURE:
234
+ if (ts_data->bus_type == BUS_TYPE_SPI) {
235
+ fts_bus_configure(ts_data, &writebuf[1], buflen - 1);
236
+ }
237
+ break;
238
+
239
+ case PROC_CONFIGURE_INTR:
240
+ if (writebuf[1] == 0)
241
+ fts_irq_disable();
242
+ else
243
+ fts_irq_enable();
244
+ break;
245
+
246
+ default:
247
+ break;
248
+ }
249
+
250
+ ret = buflen;
251
+proc_write_err:
252
+ if ((buflen > PROC_BUF_SIZE) && writebuf) {
253
+ kfree(writebuf);
254
+ writebuf = NULL;
255
+ }
256
+ return ret;
257
+}
258
+
259
+static ssize_t fts_debug_read(
260
+ struct file *filp, char __user *buff, size_t count, loff_t *ppos)
261
+{
262
+ int ret = 0;
263
+ int num_read_chars = 0;
264
+ int buflen = count;
265
+ u8 *readbuf = NULL;
266
+ u8 tmpbuf[PROC_BUF_SIZE] = { 0 };
267
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0))
268
+ struct fts_ts_data *ts_data = pde_data(file_inode(filp));
269
+#else
270
+ struct fts_ts_data *ts_data = PDE_DATA(file_inode(filp));
271
+#endif
272
+ struct ftxxxx_proc *proc = &ts_data->proc;
273
+
274
+ if (buflen <= 0) {
275
+ FTS_ERROR("apk proc read count(%d) fail", buflen);
276
+ return -EINVAL;
277
+ }
278
+
279
+ if (buflen > PROC_BUF_SIZE) {
280
+ readbuf = (u8 *)kzalloc(buflen * sizeof(u8), GFP_KERNEL);
281
+ if (NULL == readbuf) {
282
+ FTS_ERROR("apk proc buf zalloc fail");
283
+ return -ENOMEM;
284
+ }
285
+ } else {
286
+ readbuf = tmpbuf;
287
+ }
288
+
289
+ switch (proc->opmode) {
290
+ case PROC_READ_REGISTER:
291
+ num_read_chars = 1;
292
+ ret = fts_read_reg(proc->cmd[0], &readbuf[0]);
293
+ if (ret < 0) {
294
+ FTS_ERROR("PROC_READ_REGISTER read error");
295
+ goto proc_read_err;
296
+ }
297
+ break;
298
+
299
+ case PROC_READ_DATA:
300
+ num_read_chars = buflen;
301
+ if (ts_data->bus_type == BUS_TYPE_SPI)
302
+ ret = fts_read(proc->cmd, proc->cmd_len, readbuf, num_read_chars);
303
+ else if (ts_data->bus_type == BUS_TYPE_I2C)
304
+ ret = fts_read(NULL, 0, readbuf, num_read_chars);
305
+ else FTS_ERROR("unknown bus type:%d", ts_data->bus_type);
306
+ if (ret < 0) {
307
+ FTS_ERROR("PROC_READ_DATA read error");
308
+ goto proc_read_err;
309
+ }
310
+ break;
311
+
312
+ case PROC_READ_DATA_DIRECT:
313
+ num_read_chars = buflen;
314
+ ret = fts_bus_transfer_direct(proc->cmd, proc->cmd_len, readbuf, num_read_chars);
315
+ if (ret < 0) {
316
+ FTS_ERROR("PROC_READ_DATA_DIRECT read error");
317
+ goto proc_read_err;
318
+ }
319
+ break;
320
+
321
+ case PROC_GET_DRIVER_INFO:
322
+ if (buflen >= 64) {
323
+ num_read_chars = buflen;
324
+ readbuf[0] = ts_data->bus_type;
325
+ snprintf(&readbuf[32], buflen - 32, "%s", FTS_DRIVER_VERSION);
326
+ }
327
+ break;
328
+
329
+ default:
330
+ break;
331
+ }
332
+
333
+ ret = num_read_chars;
334
+proc_read_err:
335
+ if ((num_read_chars > 0) && copy_to_user(buff, readbuf, num_read_chars)) {
336
+ FTS_ERROR("copy to user error");
337
+ ret = -EFAULT;
338
+ }
339
+
340
+ if ((buflen > PROC_BUF_SIZE) && readbuf) {
341
+ kfree(readbuf);
342
+ readbuf = NULL;
343
+ }
344
+ return ret;
345
+}
346
+
347
+/*/proc/fts_ta*/
348
+static int fts_ta_open(struct inode *inode, struct file *file)
349
+{
350
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0))
351
+ struct fts_ts_data *ts_data = pde_data(inode);
352
+#else
353
+ struct fts_ts_data *ts_data = PDE_DATA(inode);
354
+#endif
355
+
356
+ if (ts_data->touch_analysis_support) {
357
+ FTS_INFO("fts_ta open");
358
+ ts_data->ta_buf = kzalloc(FTS_MAX_TOUCH_BUF, GFP_KERNEL);
359
+ if (!ts_data->ta_buf) {
360
+ FTS_ERROR("kzalloc for ta_buf fails");
361
+ return -ENOMEM;
362
+ }
363
+ }
364
+ return 0;
365
+}
366
+
367
+static int fts_ta_release(struct inode *inode, struct file *file)
368
+{
369
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0))
370
+ struct fts_ts_data *ts_data = pde_data(inode);
371
+#else
372
+ struct fts_ts_data *ts_data = PDE_DATA(inode);
373
+#endif
374
+
375
+ if (ts_data->touch_analysis_support) {
376
+ FTS_INFO("fts_ta close");
377
+ ts_data->ta_flag = 0;
378
+ if (ts_data->ta_buf) {
379
+ kfree(ts_data->ta_buf);
380
+ ts_data->ta_buf = NULL;
381
+ }
382
+ }
383
+ return 0;
384
+}
385
+
386
+static ssize_t fts_ta_read(
387
+ struct file *filp, char __user *buff, size_t count, loff_t *ppos)
388
+{
389
+ int read_num = (int)count;
390
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0))
391
+ struct fts_ts_data *ts_data = pde_data(file_inode(filp));
392
+#else
393
+ struct fts_ts_data *ts_data = PDE_DATA(file_inode(filp));
394
+#endif
395
+
396
+ if (!ts_data->touch_analysis_support || !ts_data->ta_buf) {
397
+ FTS_ERROR("touch_analysis is disabled, or ta_buf is NULL");
398
+ return -EINVAL;
399
+ }
400
+
401
+ if (!(filp->f_flags & O_NONBLOCK)) {
402
+ ts_data->ta_flag = 1;
403
+ wait_event_interruptible(ts_data->ts_waitqueue, !ts_data->ta_flag);
404
+ }
405
+
406
+ read_num = (ts_data->ta_size < read_num) ? ts_data->ta_size : read_num;
407
+ if ((read_num > 0) && (copy_to_user(buff, ts_data->ta_buf, read_num))) {
408
+ FTS_ERROR("copy to user error");
409
+ return -EFAULT;
410
+ }
411
+
412
+ return read_num;
413
+}
414
+
415
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
416
+static const struct proc_ops fts_proc_fops = {
417
+ .proc_read = fts_debug_read,
418
+ .proc_write = fts_debug_write,
419
+};
420
+
421
+static const struct proc_ops fts_procta_fops = {
422
+ .proc_open = fts_ta_open,
423
+ .proc_release = fts_ta_release,
424
+ .proc_read = fts_ta_read,
425
+};
426
+#else
427
+static const struct file_operations fts_proc_fops = {
428
+ .owner = THIS_MODULE,
429
+ .read = fts_debug_read,
430
+ .write = fts_debug_write,
431
+};
432
+
433
+static const struct file_operations fts_procta_fops = {
434
+ .open = fts_ta_open,
435
+ .release = fts_ta_release,
436
+ .read = fts_ta_read,
437
+};
438
+#endif
439
+
440
+int fts_create_apk_debug_channel(struct fts_ts_data *ts_data)
441
+{
442
+ struct ftxxxx_proc *proc = &ts_data->proc;
443
+ proc->proc_entry = proc_create_data(PROC_NAME, 0777, NULL, &fts_proc_fops, ts_data);
444
+ if (NULL == proc->proc_entry) {
445
+ FTS_ERROR("create proc entry fail");
446
+ return -ENOMEM;
447
+ }
448
+
449
+ ts_data->proc_ta.proc_entry = proc_create_data("fts_ta", 0777, NULL, \
450
+ &fts_procta_fops, ts_data);
451
+ if (!ts_data->proc_ta.proc_entry) {
452
+ FTS_ERROR("create proc_ta entry fail");
453
+ return -ENOMEM;
454
+ }
455
+
456
+ FTS_INFO("Create proc entry success!");
457
+ return 0;
458
+}
459
+
460
+void fts_release_apk_debug_channel(struct fts_ts_data *ts_data)
461
+{
462
+ FTS_FUNC_ENTER();
463
+ if (ts_data->proc.proc_entry)
464
+ proc_remove(ts_data->proc.proc_entry);
465
+ if (ts_data->proc_ta.proc_entry)
466
+ proc_remove(ts_data->proc_ta.proc_entry);
467
+ FTS_FUNC_EXIT();
468
+}
469
+
470
+/************************************************************************
471
+ * sysfs interface
472
+ ***********************************************************************/
473
+/* fts_hw_reset interface */
474
+static ssize_t fts_hw_reset_show(
475
+ struct device *dev, struct device_attribute *attr, char *buf)
476
+{
477
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
478
+ struct input_dev *input_dev = ts_data->input_dev;
479
+ ssize_t count = 0;
480
+
481
+ mutex_lock(&input_dev->mutex);
482
+ fts_reset_proc(ts_data, false, 0);
483
+ count = snprintf(buf, PAGE_SIZE, "hw reset executed\n");
484
+ mutex_unlock(&input_dev->mutex);
485
+
486
+ return count;
487
+}
488
+
489
+static ssize_t fts_hw_reset_store(
490
+ struct device *dev,
491
+ struct device_attribute *attr, const char *buf, size_t count)
492
+{
493
+ return -EPERM;
494
+}
495
+
496
+/* fts_irq interface */
497
+static ssize_t fts_irq_show(
498
+ struct device *dev, struct device_attribute *attr, char *buf)
499
+{
500
+ ssize_t count = 0;
501
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
502
+ struct irq_desc *desc = irq_to_desc(ts_data->irq);
503
+
504
+ count = snprintf(buf, PAGE_SIZE, "irq_depth:%d\n", desc->depth);
505
+
506
+ return count;
507
+}
508
+
509
+static ssize_t fts_irq_store(
510
+ struct device *dev,
511
+ struct device_attribute *attr, const char *buf, size_t count)
512
+{
513
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
514
+ struct input_dev *input_dev = ts_data->input_dev;
515
+
516
+ mutex_lock(&input_dev->mutex);
517
+ if (FTS_SYSFS_ECHO_ON(buf)) {
518
+ FTS_INFO("enable irq");
519
+ fts_irq_enable();
520
+ } else if (FTS_SYSFS_ECHO_OFF(buf)) {
521
+ FTS_INFO("disable irq");
522
+ fts_irq_disable();
523
+ }
524
+ mutex_unlock(&input_dev->mutex);
525
+ return count;
526
+}
527
+
528
+/* fts_boot_mode interface */
529
+static ssize_t fts_bootmode_store(
530
+ struct device *dev,
531
+ struct device_attribute *attr, const char *buf, size_t count)
532
+{
533
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
534
+ struct input_dev *input_dev = ts_data->input_dev;
535
+
536
+ FTS_FUNC_ENTER();
537
+ mutex_lock(&input_dev->mutex);
538
+ if (FTS_SYSFS_ECHO_ON(buf)) {
539
+ FTS_INFO("[EX-FUN]set to boot mode");
540
+ ts_data->fw_is_running = false;
541
+ } else if (FTS_SYSFS_ECHO_OFF(buf)) {
542
+ FTS_INFO("[EX-FUN]set to fw mode");
543
+ ts_data->fw_is_running = true;
544
+ }
545
+ mutex_unlock(&input_dev->mutex);
546
+ FTS_FUNC_EXIT();
547
+
548
+ return count;
549
+}
550
+
551
+static ssize_t fts_bootmode_show(
552
+ struct device *dev, struct device_attribute *attr, char *buf)
553
+{
554
+ ssize_t count = 0;
555
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
556
+ struct input_dev *input_dev = ts_data->input_dev;
557
+
558
+ FTS_FUNC_ENTER();
559
+ mutex_lock(&input_dev->mutex);
560
+ if (true == ts_data->fw_is_running) {
561
+ count = snprintf(buf, PAGE_SIZE, "tp is in fw mode\n");
562
+ } else {
563
+ count = snprintf(buf, PAGE_SIZE, "tp is in boot mode\n");
564
+ }
565
+ mutex_unlock(&input_dev->mutex);
566
+ FTS_FUNC_EXIT();
567
+
568
+ return count;
569
+}
570
+
571
+/* fts_tpfwver interface */
572
+static ssize_t fts_tpfwver_show(
573
+ struct device *dev, struct device_attribute *attr, char *buf)
574
+{
575
+ int ret = 0;
576
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
577
+ struct input_dev *input_dev = ts_data->input_dev;
578
+ ssize_t num_read_chars = 0;
579
+ u8 fwver = 0;
580
+
581
+ mutex_lock(&input_dev->mutex);
582
+
583
+ ret = fts_read_reg(FTS_REG_FW_VER, &fwver);
584
+ if ((ret < 0) || (fwver == 0xFF) || (fwver == 0x00))
585
+ num_read_chars = snprintf(buf, PAGE_SIZE, "get tp fw version fail!\n");
586
+ else
587
+ num_read_chars = snprintf(buf, PAGE_SIZE, "%02x\n", fwver);
588
+
589
+ mutex_unlock(&input_dev->mutex);
590
+ return num_read_chars;
591
+}
592
+
593
+static ssize_t fts_tpfwver_store(
594
+ struct device *dev,
595
+ struct device_attribute *attr, const char *buf, size_t count)
596
+{
597
+ return -EPERM;
598
+}
599
+
600
+/* fts_rw_reg */
601
+static ssize_t fts_tprwreg_show(
602
+ struct device *dev, struct device_attribute *attr, char *buf)
603
+{
604
+ int count;
605
+ int i;
606
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
607
+ struct input_dev *input_dev = ts_data->input_dev;
608
+
609
+ mutex_lock(&input_dev->mutex);
610
+
611
+ if (rw_op.len < 0) {
612
+ count = snprintf(buf, PAGE_SIZE, "Invalid cmd line\n");
613
+ } else if (rw_op.len == 1) {
614
+ if (RWREG_OP_READ == rw_op.type) {
615
+ if (rw_op.res == 0) {
616
+ count = snprintf(buf, PAGE_SIZE, "Read %02X: %02X\n", rw_op.reg, rw_op.val);
617
+ } else {
618
+ count = snprintf(buf, PAGE_SIZE, "Read %02X failed, ret: %d\n", rw_op.reg, rw_op.res);
619
+ }
620
+ } else {
621
+ if (rw_op.res == 0) {
622
+ count = snprintf(buf, PAGE_SIZE, "Write %02X, %02X success\n", rw_op.reg, rw_op.val);
623
+ } else {
624
+ count = snprintf(buf, PAGE_SIZE, "Write %02X failed, ret: %d\n", rw_op.reg, rw_op.res);
625
+ }
626
+ }
627
+ } else {
628
+ if (RWREG_OP_READ == rw_op.type) {
629
+ count = snprintf(buf, PAGE_SIZE, "Read Reg: [%02X]-[%02X]\n", rw_op.reg, rw_op.reg + rw_op.len);
630
+ count += snprintf(buf + count, PAGE_SIZE, "Result: ");
631
+ if (rw_op.res) {
632
+ count += snprintf(buf + count, PAGE_SIZE, "failed, ret: %d\n", rw_op.res);
633
+ } else {
634
+ if (rw_op.opbuf) {
635
+ for (i = 0; i < rw_op.len; i++) {
636
+ count += snprintf(buf + count, PAGE_SIZE, "%02X ", rw_op.opbuf[i]);
637
+ }
638
+ count += snprintf(buf + count, PAGE_SIZE, "\n");
639
+ }
640
+ }
641
+ } else {
642
+ ;
643
+ count = snprintf(buf, PAGE_SIZE, "Write Reg: [%02X]-[%02X]\n", rw_op.reg, rw_op.reg + rw_op.len - 1);
644
+ count += snprintf(buf + count, PAGE_SIZE, "Write Data: ");
645
+ if (rw_op.opbuf) {
646
+ for (i = 1; i < rw_op.len; i++) {
647
+ count += snprintf(buf + count, PAGE_SIZE, "%02X ", rw_op.opbuf[i]);
648
+ }
649
+ count += snprintf(buf + count, PAGE_SIZE, "\n");
650
+ }
651
+ if (rw_op.res) {
652
+ count += snprintf(buf + count, PAGE_SIZE, "Result: failed, ret: %d\n", rw_op.res);
653
+ } else {
654
+ count += snprintf(buf + count, PAGE_SIZE, "Result: success\n");
655
+ }
656
+ }
657
+ /*if (rw_op.opbuf) {
658
+ kfree(rw_op.opbuf);
659
+ rw_op.opbuf = NULL;
660
+ }*/
661
+ }
662
+ mutex_unlock(&input_dev->mutex);
663
+
664
+ return count;
665
+}
666
+
667
+static int shex_to_int(const char *hex_buf, int size)
668
+{
669
+ int i;
670
+ int base = 1;
671
+ int value = 0;
672
+ char single;
673
+
674
+ for (i = size - 1; i >= 0; i--) {
675
+ single = hex_buf[i];
676
+
677
+ if ((single >= '0') && (single <= '9')) {
678
+ value += (single - '0') * base;
679
+ } else if ((single >= 'a') && (single <= 'z')) {
680
+ value += (single - 'a' + 10) * base;
681
+ } else if ((single >= 'A') && (single <= 'Z')) {
682
+ value += (single - 'A' + 10) * base;
683
+ } else {
684
+ return -EINVAL;
685
+ }
686
+
687
+ base *= 16;
688
+ }
689
+
690
+ return value;
691
+}
692
+
693
+
694
+static u8 shex_to_u8(const char *hex_buf, int size)
695
+{
696
+ return (u8)shex_to_int(hex_buf, size);
697
+}
698
+/*
699
+ * Format buf:
700
+ * [0]: '0' write, '1' read(reserved)
701
+ * [1-2]: addr, hex
702
+ * [3-4]: length, hex
703
+ * [5-6]...[n-(n+1)]: data, hex
704
+ */
705
+static int fts_parse_buf(const char *buf, size_t cmd_len)
706
+{
707
+ int length;
708
+ int i;
709
+ char *tmpbuf;
710
+
711
+ rw_op.reg = shex_to_u8(buf + 1, 2);
712
+ length = shex_to_int(buf + 3, 2);
713
+
714
+ if (buf[0] == '1') {
715
+ rw_op.len = length;
716
+ rw_op.type = RWREG_OP_READ;
717
+ FTS_DEBUG("read %02X, %d bytes", rw_op.reg, rw_op.len);
718
+ } else {
719
+ if (cmd_len < (length * 2 + 5)) {
720
+ pr_err("data invalided!\n");
721
+ return -EINVAL;
722
+ }
723
+ FTS_DEBUG("write %02X, %d bytes", rw_op.reg, length);
724
+
725
+ /* first byte is the register addr */
726
+ rw_op.type = RWREG_OP_WRITE;
727
+ rw_op.len = length + 1;
728
+ }
729
+
730
+ if (rw_op.len > 0) {
731
+ tmpbuf = (char *)kzalloc(rw_op.len, GFP_KERNEL);
732
+ if (!tmpbuf) {
733
+ FTS_ERROR("allocate memory failed!\n");
734
+ return -ENOMEM;
735
+ }
736
+
737
+ if (RWREG_OP_WRITE == rw_op.type) {
738
+ tmpbuf[0] = rw_op.reg & 0xFF;
739
+ FTS_DEBUG("write buffer: ");
740
+ for (i = 1; i < rw_op.len; i++) {
741
+ tmpbuf[i] = shex_to_u8(buf + 5 + i * 2 - 2, 2);
742
+ FTS_DEBUG("buf[%d]: %02X", i, tmpbuf[i] & 0xFF);
743
+ }
744
+ }
745
+ rw_op.opbuf = tmpbuf;
746
+ }
747
+
748
+ return rw_op.len;
749
+}
750
+
751
+static ssize_t fts_tprwreg_store(
752
+ struct device *dev,
753
+ struct device_attribute *attr, const char *buf, size_t count)
754
+{
755
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
756
+ struct input_dev *input_dev = ts_data->input_dev;
757
+ ssize_t cmd_length = 0;
758
+
759
+ mutex_lock(&input_dev->mutex);
760
+ cmd_length = count - 1; //remove "\n"
761
+
762
+ if (rw_op.opbuf) {
763
+ kfree(rw_op.opbuf);
764
+ rw_op.opbuf = NULL;
765
+ }
766
+
767
+ FTS_DEBUG("cmd len: %d, buf: %s", (int)cmd_length, buf);
768
+ /* compatible old ops */
769
+ if (2 == cmd_length) {
770
+ rw_op.type = RWREG_OP_READ;
771
+ rw_op.len = 1;
772
+ rw_op.reg = shex_to_int(buf, 2);
773
+ } else if (4 == cmd_length) {
774
+ rw_op.type = RWREG_OP_WRITE;
775
+ rw_op.len = 1;
776
+ rw_op.reg = shex_to_int(buf, 2);
777
+ rw_op.val = shex_to_int(buf + 2, 2);
778
+ } else if (cmd_length < 5) {
779
+ FTS_ERROR("Invalid cmd buffer");
780
+ mutex_unlock(&input_dev->mutex);
781
+ return -EINVAL;
782
+ } else {
783
+ rw_op.len = fts_parse_buf(buf, cmd_length);
784
+ }
785
+
786
+ if (rw_op.len < 0) {
787
+ FTS_ERROR("cmd buffer error!");
788
+
789
+ } else {
790
+ if (RWREG_OP_READ == rw_op.type) {
791
+ if (rw_op.len == 1) {
792
+ u8 reg, val;
793
+ reg = rw_op.reg & 0xFF;
794
+ rw_op.res = fts_read_reg(reg, &val);
795
+ rw_op.val = val;
796
+ } else {
797
+ char reg;
798
+ reg = rw_op.reg & 0xFF;
799
+
800
+ rw_op.res = fts_read(&reg, 1, rw_op.opbuf, rw_op.len);
801
+ }
802
+
803
+ if (rw_op.res < 0) {
804
+ FTS_ERROR("Could not read 0x%02x", rw_op.reg);
805
+ } else {
806
+ FTS_INFO("read 0x%02x, %d bytes successful", rw_op.reg, rw_op.len);
807
+ rw_op.res = 0;
808
+ }
809
+
810
+ } else {
811
+ if (rw_op.len == 1) {
812
+ u8 reg, val;
813
+ reg = rw_op.reg & 0xFF;
814
+ val = rw_op.val & 0xFF;
815
+ rw_op.res = fts_write_reg(reg, val);
816
+ } else {
817
+ rw_op.res = fts_write(rw_op.opbuf, rw_op.len);
818
+ }
819
+ if (rw_op.res < 0) {
820
+ FTS_ERROR("Could not write 0x%02x", rw_op.reg);
821
+
822
+ } else {
823
+ FTS_INFO("Write 0x%02x, %d bytes successful", rw_op.val, rw_op.len);
824
+ rw_op.res = 0;
825
+ }
826
+ }
827
+ }
828
+
829
+ mutex_unlock(&input_dev->mutex);
830
+ return count;
831
+}
832
+
833
+/* fts_upgrade_bin interface */
834
+static ssize_t fts_fwupgradebin_show(
835
+ struct device *dev, struct device_attribute *attr, char *buf)
836
+{
837
+ return -EPERM;
838
+}
839
+
840
+static ssize_t fts_fwupgradebin_store(
841
+ struct device *dev,
842
+ struct device_attribute *attr, const char *buf, size_t count)
843
+{
844
+ char fwname[FILE_NAME_LENGTH] = { 0 };
845
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
846
+ struct input_dev *input_dev = ts_data->input_dev;
847
+
848
+ if ((count <= 1) || (count >= FILE_NAME_LENGTH - 32)) {
849
+ FTS_ERROR("fw bin name's length(%d) fail", (int)count);
850
+ return -EINVAL;
851
+ }
852
+ memset(fwname, 0, sizeof(fwname));
853
+ snprintf(fwname, FILE_NAME_LENGTH, "%s", buf);
854
+ fwname[count - 1] = '\0';
855
+
856
+ FTS_INFO("upgrade with bin file through sysfs node");
857
+ mutex_lock(&input_dev->mutex);
858
+ fts_upgrade_bin(fwname, 0);
859
+ mutex_unlock(&input_dev->mutex);
860
+
861
+ return count;
862
+}
863
+
864
+/* fts_force_upgrade interface */
865
+static ssize_t fts_fwforceupg_show(
866
+ struct device *dev, struct device_attribute *attr, char *buf)
867
+{
868
+ return -EPERM;
869
+}
870
+
871
+static ssize_t fts_fwforceupg_store(
872
+ struct device *dev,
873
+ struct device_attribute *attr, const char *buf, size_t count)
874
+{
875
+ char fwname[FILE_NAME_LENGTH];
876
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
877
+ struct input_dev *input_dev = ts_data->input_dev;
878
+
879
+ if ((count <= 1) || (count >= FILE_NAME_LENGTH - 32)) {
880
+ FTS_ERROR("fw bin name's length(%d) fail", (int)count);
881
+ return -EINVAL;
882
+ }
883
+ memset(fwname, 0, sizeof(fwname));
884
+ snprintf(fwname, FILE_NAME_LENGTH, "%s", buf);
885
+ fwname[count - 1] = '\0';
886
+
887
+ FTS_INFO("force upgrade through sysfs node");
888
+ mutex_lock(&input_dev->mutex);
889
+ fts_upgrade_bin(fwname, 1);
890
+ mutex_unlock(&input_dev->mutex);
891
+
892
+ return count;
893
+}
894
+
895
+/* fts_driver_info interface */
896
+static ssize_t fts_driverinfo_show(
897
+ struct device *dev, struct device_attribute *attr, char *buf)
898
+{
899
+ int count = 0;
900
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
901
+ struct fts_ts_platform_data *pdata = ts_data->pdata;
902
+ struct input_dev *input_dev = ts_data->input_dev;
903
+
904
+ mutex_lock(&input_dev->mutex);
905
+ count += snprintf(buf + count, PAGE_SIZE, "Driver Ver:%s\n",
906
+ FTS_DRIVER_VERSION);
907
+
908
+ count += snprintf(buf + count, PAGE_SIZE, "Resolution:(%d,%d)~(%d,%d)\n",
909
+ pdata->x_min, pdata->y_min, pdata->x_max, pdata->y_max);
910
+
911
+ count += snprintf(buf + count, PAGE_SIZE, "Max Touchs:%d\n",
912
+ pdata->max_touch_number);
913
+
914
+ count += snprintf(buf + count, PAGE_SIZE,
915
+ "reset gpio:%d,int gpio:%d,irq:%d\n",
916
+ pdata->reset_gpio, pdata->irq_gpio, ts_data->irq);
917
+
918
+ count += snprintf(buf + count, PAGE_SIZE, "IC ID:0x%02x%02x\n",
919
+ ts_data->ic_info.ids.chip_idh,
920
+ ts_data->ic_info.ids.chip_idl);
921
+ mutex_unlock(&input_dev->mutex);
922
+ return count;
923
+}
924
+
925
+static ssize_t fts_driverinfo_store(
926
+ struct device *dev,
927
+ struct device_attribute *attr, const char *buf, size_t count)
928
+{
929
+ return -EPERM;
930
+}
931
+
932
+/* fts_dump_reg interface */
933
+static ssize_t fts_dumpreg_show(
934
+ struct device *dev, struct device_attribute *attr, char *buf)
935
+{
936
+ int count = 0;
937
+ u8 val = 0;
938
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
939
+ struct input_dev *input_dev = ts_data->input_dev;
940
+
941
+ mutex_lock(&input_dev->mutex);
942
+
943
+ fts_read_reg(FTS_REG_POWER_MODE, &val);
944
+ count += snprintf(buf + count, PAGE_SIZE, "Power Mode:0x%02x\n", val);
945
+
946
+ fts_read_reg(FTS_REG_FW_VER, &val);
947
+ count += snprintf(buf + count, PAGE_SIZE, "FW Ver:0x%02x\n", val);
948
+
949
+ fts_read_reg(FTS_REG_LIC_VER, &val);
950
+ count += snprintf(buf + count, PAGE_SIZE, "LCD Initcode Ver:0x%02x\n", val);
951
+
952
+ fts_read_reg(FTS_REG_IDE_PARA_VER_ID, &val);
953
+ count += snprintf(buf + count, PAGE_SIZE, "Param Ver:0x%02x\n", val);
954
+
955
+ fts_read_reg(FTS_REG_IDE_PARA_STATUS, &val);
956
+ count += snprintf(buf + count, PAGE_SIZE, "Param status:0x%02x\n", val);
957
+
958
+ fts_read_reg(FTS_REG_VENDOR_ID, &val);
959
+ count += snprintf(buf + count, PAGE_SIZE, "Vendor ID:0x%02x\n", val);
960
+
961
+ fts_read_reg(FTS_REG_GESTURE_EN, &val);
962
+ count += snprintf(buf + count, PAGE_SIZE, "Gesture Mode:0x%02x\n", val);
963
+
964
+ fts_read_reg(FTS_REG_CHARGER_MODE_EN, &val);
965
+ count += snprintf(buf + count, PAGE_SIZE, "charge stat:0x%02x\n", val);
966
+
967
+ fts_read_reg(FTS_REG_INT_CNT, &val);
968
+ count += snprintf(buf + count, PAGE_SIZE, "INT count:0x%02x\n", val);
969
+
970
+ fts_read_reg(FTS_REG_FLOW_WORK_CNT, &val);
971
+ count += snprintf(buf + count, PAGE_SIZE, "ESD count:0x%02x\n", val);
972
+
973
+ mutex_unlock(&input_dev->mutex);
974
+ return count;
975
+}
976
+
977
+static ssize_t fts_dumpreg_store(
978
+ struct device *dev,
979
+ struct device_attribute *attr, const char *buf, size_t count)
980
+{
981
+ return -EPERM;
982
+}
983
+
984
+/* fts_dump_reg interface */
985
+static ssize_t fts_tpbuf_show(
986
+ struct device *dev, struct device_attribute *attr, char *buf)
987
+{
988
+ int count = 0;
989
+ int i = 0;
990
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
991
+ struct input_dev *input_dev = ts_data->input_dev;
992
+
993
+ mutex_lock(&input_dev->mutex);
994
+ count += snprintf(buf + count, PAGE_SIZE, "touch point buffer:\n");
995
+ for (i = 0; i < FTS_TOUCH_DATA_LEN; i++) {
996
+ count += snprintf(buf + count, PAGE_SIZE, "%02x ", ts_data->touch_buf[i]);
997
+ }
998
+ count += snprintf(buf + count, PAGE_SIZE, "\n");
999
+ mutex_unlock(&input_dev->mutex);
1000
+
1001
+ return count;
1002
+}
1003
+
1004
+static ssize_t fts_tpbuf_store(
1005
+ struct device *dev,
1006
+ struct device_attribute *attr, const char *buf, size_t count)
1007
+{
1008
+ return -EPERM;
1009
+}
1010
+
1011
+/* fts_log_level node */
1012
+static ssize_t fts_log_level_show(
1013
+ struct device *dev, struct device_attribute *attr, char *buf)
1014
+{
1015
+ int count = 0;
1016
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
1017
+ struct input_dev *input_dev = ts_data->input_dev;
1018
+
1019
+ mutex_lock(&input_dev->mutex);
1020
+ count += snprintf(buf + count, PAGE_SIZE, "log level:%d\n",
1021
+ ts_data->log_level);
1022
+ mutex_unlock(&input_dev->mutex);
1023
+
1024
+ return count;
1025
+}
1026
+
1027
+static ssize_t fts_log_level_store(
1028
+ struct device *dev,
1029
+ struct device_attribute *attr, const char *buf, size_t count)
1030
+{
1031
+ int value = 0;
1032
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
1033
+ struct input_dev *input_dev = ts_data->input_dev;
1034
+
1035
+ FTS_FUNC_ENTER();
1036
+ mutex_lock(&input_dev->mutex);
1037
+ sscanf(buf, "%d", &value);
1038
+ FTS_DEBUG("log level:%d->%d", ts_data->log_level, value);
1039
+ ts_data->log_level = value;
1040
+ mutex_unlock(&input_dev->mutex);
1041
+ FTS_FUNC_EXIT();
1042
+
1043
+ return count;
1044
+}
1045
+
1046
+/* fts_pen node */
1047
+static ssize_t fts_pen_show(
1048
+ struct device *dev, struct device_attribute *attr, char *buf)
1049
+{
1050
+ int count = 0;
1051
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
1052
+ struct input_dev *input_dev = ts_data->input_dev;
1053
+
1054
+ mutex_lock(&input_dev->mutex);
1055
+ count += snprintf(buf + count, PAGE_SIZE, "pen event:%s\n",
1056
+ ts_data->pen_etype ? "hover" : "default");
1057
+ mutex_unlock(&input_dev->mutex);
1058
+
1059
+ return count;
1060
+}
1061
+
1062
+static ssize_t fts_pen_store(
1063
+ struct device *dev,
1064
+ struct device_attribute *attr, const char *buf, size_t count)
1065
+{
1066
+ int value = 0;
1067
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
1068
+ struct input_dev *input_dev = ts_data->input_dev;
1069
+
1070
+ FTS_FUNC_ENTER();
1071
+ mutex_lock(&input_dev->mutex);
1072
+ sscanf(buf, "%d", &value);
1073
+ FTS_DEBUG("pen event:%d->%d", ts_data->pen_etype, value);
1074
+ ts_data->pen_etype = value;
1075
+ mutex_unlock(&input_dev->mutex);
1076
+ FTS_FUNC_EXIT();
1077
+
1078
+ return count;
1079
+}
1080
+
1081
+/* fts_touch_size node */
1082
+static ssize_t fts_touchsize_show(
1083
+ struct device *dev, struct device_attribute *attr, char *buf)
1084
+{
1085
+ int count = 0;
1086
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
1087
+ struct input_dev *input_dev = ts_data->input_dev;
1088
+
1089
+ mutex_lock(&input_dev->mutex);
1090
+ count += snprintf(buf + count, PAGE_SIZE, "touch size:%d\n", ts_data->touch_size);
1091
+ mutex_unlock(&input_dev->mutex);
1092
+
1093
+ return count;
1094
+}
1095
+
1096
+static ssize_t fts_touchsize_store(
1097
+ struct device *dev,
1098
+ struct device_attribute *attr, const char *buf, size_t count)
1099
+{
1100
+ int value = 0;
1101
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
1102
+ struct input_dev *input_dev = ts_data->input_dev;
1103
+
1104
+ FTS_FUNC_ENTER();
1105
+ mutex_lock(&input_dev->mutex);
1106
+ sscanf(buf, "%d", &value);
1107
+ if ((value > 2) && (value < FTS_MAX_TOUCH_BUF)) {
1108
+ FTS_DEBUG("touch size:%d->%d", ts_data->touch_size, value);
1109
+ ts_data->touch_size = value;
1110
+ } else
1111
+ FTS_DEBUG("touch size:%d invalid", value);
1112
+ mutex_unlock(&input_dev->mutex);
1113
+ FTS_FUNC_EXIT();
1114
+
1115
+ return count;
1116
+}
1117
+
1118
+/* fts_ta_mode node */
1119
+static ssize_t fts_tamode_show(
1120
+ struct device *dev, struct device_attribute *attr, char *buf)
1121
+{
1122
+ int count = 0;
1123
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
1124
+ struct input_dev *input_dev = ts_data->input_dev;
1125
+
1126
+ mutex_lock(&input_dev->mutex);
1127
+ count += snprintf(buf + count, PAGE_SIZE, "touch analysis:%s\n", \
1128
+ ts_data->touch_analysis_support ? "Enable" : "Disable");
1129
+ mutex_unlock(&input_dev->mutex);
1130
+
1131
+ return count;
1132
+}
1133
+
1134
+static ssize_t fts_tamode_store(
1135
+ struct device *dev,
1136
+ struct device_attribute *attr, const char *buf, size_t count)
1137
+{
1138
+ int value = 0;
1139
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
1140
+ struct input_dev *input_dev = ts_data->input_dev;
1141
+
1142
+ FTS_FUNC_ENTER();
1143
+ mutex_lock(&input_dev->mutex);
1144
+ sscanf(buf, "%d", &value);
1145
+ ts_data->touch_analysis_support = !!value;
1146
+ FTS_DEBUG("set touch analysis:%d", ts_data->touch_analysis_support);
1147
+ mutex_unlock(&input_dev->mutex);
1148
+ FTS_FUNC_EXIT();
1149
+
1150
+ return count;
1151
+}
1152
+
1153
+#if FTS_FOD_EN
1154
+/* fts_fod_mode node */
1155
+static ssize_t fts_fod_show(
1156
+ struct device *dev, struct device_attribute *attr, char *buf)
1157
+{
1158
+ int count = 0;
1159
+ u8 val = 0;
1160
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
1161
+
1162
+ mutex_lock(&ts_data->input_dev->mutex);
1163
+ fts_read_reg(FTS_REG_FOD_MODE_EN, &val);
1164
+ count = snprintf(buf, PAGE_SIZE, "FOD Mode:%s\n", ts_data->fod_mode ? "On" : "Off");
1165
+ count += snprintf(buf + count, PAGE_SIZE, "Reg(0xCF)=%d\n", val);
1166
+ mutex_unlock(&ts_data->input_dev->mutex);
1167
+
1168
+ return count;
1169
+}
1170
+
1171
+static ssize_t fts_fod_store(
1172
+ struct device *dev,
1173
+ struct device_attribute *attr, const char *buf, size_t count)
1174
+{
1175
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
1176
+
1177
+ mutex_lock(&ts_data->input_dev->mutex);
1178
+ if (FTS_SYSFS_ECHO_ON(buf)) {
1179
+ fts_fod_enable(ENABLE);
1180
+ } else if (FTS_SYSFS_ECHO_OFF(buf)) {
1181
+ fts_fod_enable(DISABLE);
1182
+ }
1183
+ mutex_unlock(&ts_data->input_dev->mutex);
1184
+
1185
+ return count;
1186
+}
1187
+#endif
1188
+
1189
+/* get the fw version example:cat fw_version */
1190
+static DEVICE_ATTR(fts_fw_version, S_IRUGO | S_IWUSR, fts_tpfwver_show, fts_tpfwver_store);
1191
+
1192
+/* read and write register(s)
1193
+* All data type is **HEX**
1194
+* Single Byte:
1195
+* read: echo 88 > rw_reg ---read register 0x88
1196
+* write: echo 8807 > rw_reg ---write 0x07 into register 0x88
1197
+* Multi-bytes:
1198
+* [0:rw-flag][1-2: reg addr, hex][3-4: length, hex][5-6...n-n+1: write data, hex]
1199
+* rw-flag: 0, write; 1, read
1200
+* read: echo 10005 > rw_reg ---read reg 0x00-0x05
1201
+* write: echo 000050102030405 > rw_reg ---write reg 0x00-0x05 as 01,02,03,04,05
1202
+* Get result:
1203
+* cat rw_reg
1204
+*/
1205
+static DEVICE_ATTR(fts_rw_reg, S_IRUGO | S_IWUSR, fts_tprwreg_show, fts_tprwreg_store);
1206
+/* upgrade from fw bin file example:echo "*.bin" > fts_upgrade_bin */
1207
+static DEVICE_ATTR(fts_upgrade_bin, S_IRUGO | S_IWUSR, fts_fwupgradebin_show, fts_fwupgradebin_store);
1208
+static DEVICE_ATTR(fts_force_upgrade, S_IRUGO | S_IWUSR, fts_fwforceupg_show, fts_fwforceupg_store);
1209
+static DEVICE_ATTR(fts_driver_info, S_IRUGO | S_IWUSR, fts_driverinfo_show, fts_driverinfo_store);
1210
+static DEVICE_ATTR(fts_dump_reg, S_IRUGO | S_IWUSR, fts_dumpreg_show, fts_dumpreg_store);
1211
+static DEVICE_ATTR(fts_hw_reset, S_IRUGO | S_IWUSR, fts_hw_reset_show, fts_hw_reset_store);
1212
+static DEVICE_ATTR(fts_irq, S_IRUGO | S_IWUSR, fts_irq_show, fts_irq_store);
1213
+static DEVICE_ATTR(fts_boot_mode, S_IRUGO | S_IWUSR, fts_bootmode_show, fts_bootmode_store);
1214
+static DEVICE_ATTR(fts_touch_point, S_IRUGO | S_IWUSR, fts_tpbuf_show, fts_tpbuf_store);
1215
+static DEVICE_ATTR(fts_log_level, S_IRUGO | S_IWUSR, fts_log_level_show, fts_log_level_store);
1216
+static DEVICE_ATTR(fts_pen, S_IRUGO | S_IWUSR, fts_pen_show, fts_pen_store);
1217
+static DEVICE_ATTR(fts_touch_size, S_IRUGO | S_IWUSR, fts_touchsize_show, fts_touchsize_store);
1218
+static DEVICE_ATTR(fts_ta_mode, S_IRUGO | S_IWUSR, fts_tamode_show, fts_tamode_store);
1219
+#if FTS_FOD_EN
1220
+static DEVICE_ATTR(fts_fod_mode, S_IRUGO | S_IWUSR, fts_fod_show, fts_fod_store);
1221
+#endif
1222
+
1223
+/* add your attr in here*/
1224
+static struct attribute *fts_attributes[] = {
1225
+ &dev_attr_fts_fw_version.attr,
1226
+ &dev_attr_fts_rw_reg.attr,
1227
+ &dev_attr_fts_dump_reg.attr,
1228
+ &dev_attr_fts_upgrade_bin.attr,
1229
+ &dev_attr_fts_force_upgrade.attr,
1230
+ &dev_attr_fts_driver_info.attr,
1231
+ &dev_attr_fts_hw_reset.attr,
1232
+ &dev_attr_fts_irq.attr,
1233
+ &dev_attr_fts_boot_mode.attr,
1234
+ &dev_attr_fts_touch_point.attr,
1235
+ &dev_attr_fts_log_level.attr,
1236
+ &dev_attr_fts_pen.attr,
1237
+ &dev_attr_fts_touch_size.attr,
1238
+ &dev_attr_fts_ta_mode.attr,
1239
+#if FTS_FOD_EN
1240
+ &dev_attr_fts_fod_mode.attr,
1241
+#endif
1242
+ NULL
1243
+};
1244
+
1245
+static struct attribute_group fts_attribute_group = {
1246
+ .attrs = fts_attributes
1247
+};
1248
+
1249
+int fts_create_sysfs(struct fts_ts_data *ts_data)
1250
+{
1251
+ int ret = 0;
1252
+
1253
+ ret = sysfs_create_group(&ts_data->dev->kobj, &fts_attribute_group);
1254
+ if (ret) {
1255
+ FTS_ERROR("[EX]: sysfs_create_group() failed!!");
1256
+ sysfs_remove_group(&ts_data->dev->kobj, &fts_attribute_group);
1257
+ return -ENOMEM;
1258
+ } else {
1259
+ FTS_INFO("[EX]: sysfs_create_group() succeeded!!");
1260
+ }
1261
+
1262
+ return ret;
1263
+}
1264
+
1265
+int fts_remove_sysfs(struct fts_ts_data *ts_data)
1266
+{
1267
+ sysfs_remove_group(&ts_data->dev->kobj, &fts_attribute_group);
1268
+ return 0;
1269
+}
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_ex_mode.c
....@@ -0,0 +1,390 @@
1
+/*
2
+ *
3
+ * FocalTech ftxxxx TouchScreen driver.
4
+ *
5
+ * Copyright (c) 2012-2020, Focaltech Ltd. All rights reserved.
6
+ *
7
+ * This software is licensed under the terms of the GNU General Public
8
+ * License version 2, as published by the Free Software Foundation, and
9
+ * may be copied, distributed, and modified under those terms.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ */
17
+
18
+/*****************************************************************************
19
+*
20
+* File Name: focaltech_ex_mode.c
21
+*
22
+* Author: Focaltech Driver Team
23
+*
24
+* Created: 2016-08-31
25
+*
26
+* Abstract:
27
+*
28
+* Reference:
29
+*
30
+*****************************************************************************/
31
+
32
+/*****************************************************************************
33
+* 1.Included header files
34
+*****************************************************************************/
35
+#include "focaltech_core.h"
36
+
37
+/*****************************************************************************
38
+* 2.Private constant and macro definitions using #define
39
+*****************************************************************************/
40
+
41
+/*****************************************************************************
42
+* 3.Private enumerations, structures and unions using typedef
43
+*****************************************************************************/
44
+enum _ex_mode {
45
+ MODE_GLOVE = 0,
46
+ MODE_COVER,
47
+ MODE_CHARGER,
48
+ MODE_EARPHONE,
49
+ MODE_EDGEPALM
50
+};
51
+
52
+/*****************************************************************************
53
+* 4.Static variables
54
+*****************************************************************************/
55
+
56
+/*****************************************************************************
57
+* 5.Global variable or extern global variabls/functions
58
+*****************************************************************************/
59
+
60
+/*****************************************************************************
61
+* 6.Static function prototypes
62
+*******************************************************************************/
63
+static int fts_ex_mode_set_reg(u8 mode_regaddr, u8 mode_regval)
64
+{
65
+ int i = 0;
66
+ u8 val = 0xFF;
67
+
68
+ for (i = 0; i < FTS_MAX_RETRIES_WRITEREG; i++) {
69
+ fts_read_reg(mode_regaddr, &val);
70
+ if (val == mode_regval)
71
+ break;
72
+ fts_write_reg(mode_regaddr, mode_regval);
73
+ fts_msleep(1);
74
+ }
75
+
76
+ if (i >= FTS_MAX_RETRIES_WRITEREG) {
77
+ FTS_ERROR("set mode(%x) to %x failed,read val:%x", mode_regaddr, mode_regval, val);
78
+ return -EIO;
79
+ } else if (i > 0) {
80
+ FTS_INFO("set mode(%x) to %x successfully", mode_regaddr, mode_regval);
81
+ }
82
+ return 0;
83
+}
84
+
85
+static int fts_ex_mode_switch(enum _ex_mode mode, int value)
86
+{
87
+ int ret = 0;
88
+
89
+ switch (mode) {
90
+ case MODE_GLOVE:
91
+ ret = fts_ex_mode_set_reg(FTS_REG_GLOVE_MODE_EN, (value ? 0x01 : 0x00));
92
+ if (ret) FTS_ERROR("Set MODE_GLOVE to %d failed", value);
93
+ break;
94
+ case MODE_COVER:
95
+ ret = fts_ex_mode_set_reg(FTS_REG_COVER_MODE_EN, (value ? 0x01 : 0x00));
96
+ if (ret) FTS_ERROR("Set MODE_COVER to %d failed", value);
97
+ break;
98
+ case MODE_CHARGER:
99
+ ret = fts_ex_mode_set_reg(FTS_REG_CHARGER_MODE_EN, (value ? 0x01 : 0x00));
100
+ if (ret) FTS_ERROR("Set MODE_CHARGER to %d failed", value);
101
+ break;
102
+ case MODE_EARPHONE:
103
+ ret = fts_ex_mode_set_reg(FTS_REG_EARPHONE_MODE_EN, (value ? 0x01 : 0x00));
104
+ if (ret) FTS_ERROR("Set MODE_EARPHONE to %d failed", value);
105
+ break;
106
+ case MODE_EDGEPALM:
107
+ /* FW defines the following values: 0:vertical, 1:horizontal, USB on the right,
108
+ * 2:horizontal, USB on the left
109
+ * If host set the value not defined above, you should have a transition.
110
+ */
111
+ ret = fts_ex_mode_set_reg(FTS_REG_EDGEPALM_MODE_EN, (u8)value);
112
+ if (ret) FTS_ERROR("Set MODE_EDGEPALM to %d failed", value);
113
+ break;
114
+ default:
115
+ FTS_ERROR("mode(%d) unsupport", mode);
116
+ ret = -EINVAL;
117
+ break;
118
+ }
119
+
120
+ return ret;
121
+}
122
+
123
+static ssize_t fts_glove_mode_show(
124
+ struct device *dev, struct device_attribute *attr, char *buf)
125
+{
126
+ int count = 0;
127
+ u8 reg_addr = FTS_REG_GLOVE_MODE_EN;
128
+ u8 reg_val = 0;
129
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
130
+
131
+ mutex_lock(&ts_data->input_dev->mutex);
132
+ fts_read_reg(reg_addr, &reg_val);
133
+ count = snprintf(buf + count, PAGE_SIZE, "Glove Mode:%s\n",
134
+ ts_data->glove_mode ? "On" : "Off");
135
+ count += snprintf(buf + count, PAGE_SIZE, "Glove Reg:0x%02x,val:%d\n", reg_addr, reg_val);
136
+ mutex_unlock(&ts_data->input_dev->mutex);
137
+
138
+ return count;
139
+}
140
+
141
+static ssize_t fts_glove_mode_store(
142
+ struct device *dev,
143
+ struct device_attribute *attr, const char *buf, size_t count)
144
+{
145
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
146
+
147
+ mutex_lock(&ts_data->input_dev->mutex);
148
+ if (FTS_SYSFS_ECHO_ON(buf)) {
149
+ FTS_DEBUG("enter glove mode");
150
+ ts_data->glove_mode = ENABLE;
151
+ fts_ex_mode_switch(MODE_GLOVE, ENABLE);
152
+ } else if (FTS_SYSFS_ECHO_OFF(buf)) {
153
+ FTS_DEBUG("exit glove mode");
154
+ ts_data->glove_mode = DISABLE;
155
+ fts_ex_mode_switch(MODE_GLOVE, DISABLE);
156
+ }
157
+ mutex_unlock(&ts_data->input_dev->mutex);
158
+ return count;
159
+}
160
+
161
+
162
+static ssize_t fts_cover_mode_show(
163
+ struct device *dev, struct device_attribute *attr, char *buf)
164
+{
165
+ int count = 0;
166
+ u8 reg_addr = FTS_REG_COVER_MODE_EN;
167
+ u8 reg_val = 0;
168
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
169
+
170
+ mutex_lock(&ts_data->input_dev->mutex);
171
+ fts_read_reg(reg_addr, &reg_val);
172
+ count = snprintf(buf + count, PAGE_SIZE, "Cover Mode:%s\n",
173
+ ts_data->cover_mode ? "On" : "Off");
174
+ count += snprintf(buf + count, PAGE_SIZE, "Cover Reg:0x%02x,val:%d\n", reg_addr, reg_val);
175
+ mutex_unlock(&ts_data->input_dev->mutex);
176
+
177
+ return count;
178
+}
179
+
180
+static ssize_t fts_cover_mode_store(
181
+ struct device *dev,
182
+ struct device_attribute *attr, const char *buf, size_t count)
183
+{
184
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
185
+
186
+ mutex_lock(&ts_data->input_dev->mutex);
187
+ if (FTS_SYSFS_ECHO_ON(buf)) {
188
+ FTS_DEBUG("enter cover mode");
189
+ ts_data->cover_mode = ENABLE;
190
+ fts_ex_mode_switch(MODE_COVER, ENABLE);
191
+ } else if (FTS_SYSFS_ECHO_OFF(buf)) {
192
+ FTS_DEBUG("exit cover mode");
193
+ ts_data->cover_mode = DISABLE;
194
+ fts_ex_mode_switch(MODE_COVER, DISABLE);
195
+ }
196
+ mutex_unlock(&ts_data->input_dev->mutex);
197
+ return count;
198
+}
199
+
200
+static ssize_t fts_charger_mode_show(
201
+ struct device *dev, struct device_attribute *attr, char *buf)
202
+{
203
+ int count = 0;
204
+ u8 reg_addr = FTS_REG_CHARGER_MODE_EN;
205
+ u8 reg_val = 0;
206
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
207
+
208
+ mutex_lock(&ts_data->input_dev->mutex);
209
+ fts_read_reg(reg_addr, &reg_val);
210
+ count = snprintf(buf + count, PAGE_SIZE, "Charger Mode:%s\n",
211
+ ts_data->charger_mode ? "On" : "Off");
212
+ count += snprintf(buf + count, PAGE_SIZE, "Charger Reg:0x%02x,val:%d\n", reg_addr, reg_val);
213
+ mutex_unlock(&ts_data->input_dev->mutex);
214
+
215
+ return count;
216
+}
217
+
218
+static ssize_t fts_charger_mode_store(
219
+ struct device *dev,
220
+ struct device_attribute *attr, const char *buf, size_t count)
221
+{
222
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
223
+
224
+ mutex_lock(&ts_data->input_dev->mutex);
225
+ if (FTS_SYSFS_ECHO_ON(buf)) {
226
+ FTS_DEBUG("enter charger mode");
227
+ ts_data->charger_mode = ENABLE;
228
+ fts_ex_mode_switch(MODE_CHARGER, ENABLE);
229
+ } else if (FTS_SYSFS_ECHO_OFF(buf)) {
230
+ FTS_DEBUG("exit charger mode");
231
+ ts_data->charger_mode = DISABLE;
232
+ fts_ex_mode_switch(MODE_CHARGER, DISABLE);
233
+ }
234
+ mutex_unlock(&ts_data->input_dev->mutex);
235
+ return count;
236
+}
237
+
238
+/* sysfs node: fts_earphone_mode */
239
+static ssize_t fts_earphone_show(
240
+ struct device *dev, struct device_attribute *attr, char *buf)
241
+{
242
+ int count = 0;
243
+ u8 reg_addr = FTS_REG_EARPHONE_MODE_EN;
244
+ u8 reg_val = 0;
245
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
246
+
247
+ mutex_lock(&ts_data->input_dev->mutex);
248
+ fts_read_reg(reg_addr, &reg_val);
249
+ count = snprintf(buf + count, PAGE_SIZE, "Earphone Mode:%s\n",
250
+ ts_data->earphone_mode ? "On" : "Off");
251
+ count += snprintf(buf + count, PAGE_SIZE, "Earphone Reg:0x%02x,val:%d\n", reg_addr, reg_val);
252
+ mutex_unlock(&ts_data->input_dev->mutex);
253
+
254
+ return count;
255
+}
256
+
257
+static ssize_t fts_earphone_store(
258
+ struct device *dev,
259
+ struct device_attribute *attr, const char *buf, size_t count)
260
+{
261
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
262
+
263
+ mutex_lock(&ts_data->input_dev->mutex);
264
+ if (FTS_SYSFS_ECHO_ON(buf)) {
265
+ FTS_DEBUG("enter earphone mode");
266
+ ts_data->earphone_mode = ENABLE;
267
+ fts_ex_mode_switch(MODE_EARPHONE, ENABLE);
268
+ } else if (FTS_SYSFS_ECHO_OFF(buf)) {
269
+ FTS_DEBUG("exit earphone mode");
270
+ ts_data->earphone_mode = DISABLE;
271
+ fts_ex_mode_switch(MODE_EARPHONE, DISABLE);
272
+ }
273
+ mutex_unlock(&ts_data->input_dev->mutex);
274
+ return count;
275
+}
276
+
277
+/* sysfs node: fts_edgepalm_mode */
278
+static ssize_t fts_edgepalm_show(
279
+ struct device *dev, struct device_attribute *attr, char *buf)
280
+{
281
+ int count = 0;
282
+ u8 reg_addr = FTS_REG_EDGEPALM_MODE_EN;
283
+ u8 reg_val = 0;
284
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
285
+
286
+ mutex_lock(&ts_data->input_dev->mutex);
287
+ fts_read_reg(reg_addr, &reg_val);
288
+ count = snprintf(buf + count, PAGE_SIZE, "Edgepalm Mode:%s,value:%d\n",
289
+ ts_data->edgepalm_mode ? "On" : "Off", ts_data->edgepalm_value);
290
+ count += snprintf(buf + count, PAGE_SIZE, "Edgepalm Reg:0x%02x,val:%d\n", reg_addr, reg_val);
291
+ mutex_unlock(&ts_data->input_dev->mutex);
292
+
293
+ return count;
294
+}
295
+
296
+static ssize_t fts_edgepalm_store(
297
+ struct device *dev,
298
+ struct device_attribute *attr, const char *buf, size_t count)
299
+{
300
+ int value = 0;
301
+ int n = 0;
302
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
303
+
304
+ mutex_lock(&ts_data->input_dev->mutex);
305
+ n = sscanf(buf, "%d", &value);
306
+ if (n == 1) {
307
+ ts_data->edgepalm_value = value;
308
+ ts_data->edgepalm_mode = !!value;
309
+ fts_ex_mode_switch(MODE_EDGEPALM, value);
310
+ }
311
+ mutex_unlock(&ts_data->input_dev->mutex);
312
+ return count;
313
+}
314
+
315
+
316
+/* read and write charger mode
317
+ * read example: cat fts_glove_mode ---read glove mode
318
+ * write example:echo 1 > fts_glove_mode ---write glove mode to 01
319
+ */
320
+static DEVICE_ATTR(fts_glove_mode, S_IRUGO | S_IWUSR, fts_glove_mode_show, fts_glove_mode_store);
321
+static DEVICE_ATTR(fts_cover_mode, S_IRUGO | S_IWUSR, fts_cover_mode_show, fts_cover_mode_store);
322
+static DEVICE_ATTR(fts_charger_mode, S_IRUGO | S_IWUSR, fts_charger_mode_show, fts_charger_mode_store);
323
+static DEVICE_ATTR(fts_earphone_mode, S_IRUGO | S_IWUSR, fts_earphone_show, fts_earphone_store);
324
+static DEVICE_ATTR(fts_edgepalm_mode, S_IRUGO | S_IWUSR, fts_edgepalm_show, fts_edgepalm_store);
325
+
326
+static struct attribute *fts_touch_mode_attrs[] = {
327
+ &dev_attr_fts_glove_mode.attr,
328
+ &dev_attr_fts_cover_mode.attr,
329
+ &dev_attr_fts_charger_mode.attr,
330
+ &dev_attr_fts_earphone_mode.attr,
331
+ &dev_attr_fts_edgepalm_mode.attr,
332
+ NULL,
333
+};
334
+
335
+static struct attribute_group fts_touch_mode_group = {
336
+ .attrs = fts_touch_mode_attrs,
337
+};
338
+
339
+int fts_ex_mode_recovery(struct fts_ts_data *ts_data)
340
+{
341
+ if (ts_data->glove_mode) {
342
+ fts_ex_mode_switch(MODE_GLOVE, ENABLE);
343
+ }
344
+
345
+ if (ts_data->cover_mode) {
346
+ fts_ex_mode_switch(MODE_COVER, ENABLE);
347
+ }
348
+
349
+ if (ts_data->charger_mode) {
350
+ fts_ex_mode_switch(MODE_CHARGER, ENABLE);
351
+ }
352
+
353
+ if (ts_data->earphone_mode) {
354
+ fts_ex_mode_switch(MODE_EARPHONE, ENABLE);
355
+ }
356
+
357
+ if (ts_data->edgepalm_mode) {
358
+ fts_ex_mode_switch(MODE_EDGEPALM, ts_data->edgepalm_value);
359
+ }
360
+
361
+ return 0;
362
+}
363
+
364
+int fts_ex_mode_init(struct fts_ts_data *ts_data)
365
+{
366
+ int ret = 0;
367
+
368
+ ts_data->glove_mode = DISABLE;
369
+ ts_data->cover_mode = DISABLE;
370
+ ts_data->charger_mode = DISABLE;
371
+ ts_data->earphone_mode = DISABLE;
372
+ ts_data->edgepalm_mode = DISABLE;
373
+
374
+ ret = sysfs_create_group(&ts_data->dev->kobj, &fts_touch_mode_group);
375
+ if (ret < 0) {
376
+ FTS_ERROR("create sysfs(ex_mode) fail");
377
+ sysfs_remove_group(&ts_data->dev->kobj, &fts_touch_mode_group);
378
+ return ret;
379
+ } else {
380
+ FTS_DEBUG("create sysfs(ex_mode) successfully");
381
+ }
382
+
383
+ return 0;
384
+}
385
+
386
+int fts_ex_mode_exit(struct fts_ts_data *ts_data)
387
+{
388
+ sysfs_remove_group(&ts_data->dev->kobj, &fts_touch_mode_group);
389
+ return 0;
390
+}
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_flash.c
....@@ -0,0 +1,2273 @@
1
+/*
2
+ *
3
+ * FocalTech fts TouchScreen driver.
4
+ *
5
+ * Copyright (c) 2012-2020, Focaltech Ltd. All rights reserved.
6
+ *
7
+ * This software is licensed under the terms of the GNU General Public
8
+ * License version 2, as published by the Free Software Foundation, and
9
+ * may be copied, distributed, and modified under those terms.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ */
17
+
18
+/*****************************************************************************
19
+*
20
+* File Name: focaltech_flash.c
21
+*
22
+* Author: Focaltech Driver Team
23
+*
24
+* Created: 2016-08-08
25
+*
26
+* Abstract:
27
+*
28
+* Reference:
29
+*
30
+*****************************************************************************/
31
+
32
+/*****************************************************************************
33
+* 1.Included header files
34
+*****************************************************************************/
35
+#include "focaltech_core.h"
36
+#include "focaltech_flash.h"
37
+
38
+/*****************************************************************************
39
+* Private constant and macro definitions using #define
40
+*****************************************************************************/
41
+#define FTS_FW_REQUEST_SUPPORT 1
42
+/* Example: focaltech_ts_fw_tianma.bin */
43
+#define FTS_FW_NAME_PREX_WITH_REQUEST "focaltech_ts_fw_"
44
+
45
+/*****************************************************************************
46
+* Global variable or extern global variabls/functions
47
+*****************************************************************************/
48
+u8 fw_file[] = {
49
+#include FTS_UPGRADE_FW_FILE
50
+};
51
+
52
+u8 fw_file2[] = {
53
+#include FTS_UPGRADE_FW2_FILE
54
+};
55
+
56
+u8 fw_file3[] = {
57
+#include FTS_UPGRADE_FW3_FILE
58
+};
59
+
60
+struct upgrade_module module_list[] = {
61
+ {FTS_MODULE_ID, FTS_MODULE_NAME, fw_file, sizeof(fw_file)},
62
+ {FTS_MODULE2_ID, FTS_MODULE2_NAME, fw_file2, sizeof(fw_file2)},
63
+ {FTS_MODULE3_ID, FTS_MODULE3_NAME, fw_file3, sizeof(fw_file3)},
64
+};
65
+
66
+struct upgrade_func *upgrade_func_list[] = {
67
+ &upgrade_func_ft8756,
68
+};
69
+
70
+struct fts_upgrade *fwupgrade;
71
+
72
+/*****************************************************************************
73
+* Static function prototypes
74
+*****************************************************************************/
75
+static bool fts_fwupg_check_state(
76
+ struct fts_upgrade *upg, enum FW_STATUS rstate);
77
+
78
+/************************************************************************
79
+* Name: fts_fwupg_get_boot_state
80
+* Brief: read boot id(rom/pram/bootloader), confirm boot environment
81
+* Input:
82
+* Output:
83
+* Return: return 0 if success, otherwise return error code
84
+***********************************************************************/
85
+static int fts_fwupg_get_boot_state(
86
+ struct fts_upgrade *upg,
87
+ enum FW_STATUS *fw_sts)
88
+{
89
+ int ret = 0;
90
+ u8 cmd[4] = { 0 };
91
+ u32 cmd_len = 0;
92
+ u8 val[2] = { 0 };
93
+ struct ft_chip_t *ids = NULL;
94
+
95
+ FTS_INFO("**********read boot id**********");
96
+ if ((!upg) || (!upg->func) || (!upg->ts_data) || (!fw_sts)) {
97
+ FTS_ERROR("upg/func/ts_data/fw_sts is null");
98
+ return -EINVAL;
99
+ }
100
+
101
+ if (upg->func->hid_supported)
102
+ fts_hid2std(0);
103
+
104
+ cmd[0] = FTS_CMD_START1;
105
+ cmd[1] = FTS_CMD_START2;
106
+ if (upg->func->upgspec_version >= UPGRADE_SPEC_V_1_0)
107
+ cmd_len = 1;
108
+ else
109
+ cmd_len = 2;
110
+ ret = fts_write(cmd, cmd_len);
111
+ if (ret < 0) {
112
+ FTS_ERROR("write 55 cmd fail");
113
+ return ret;
114
+ }
115
+
116
+ fts_msleep(FTS_CMD_START_DELAY);
117
+ cmd[0] = FTS_CMD_READ_ID;
118
+ cmd[1] = cmd[2] = cmd[3] = 0x00;
119
+ if (upg->ts_data->ic_info.is_incell ||
120
+ (upg->func->upgspec_version >= UPGRADE_SPEC_V_1_0))
121
+ cmd_len = FTS_CMD_READ_ID_LEN_INCELL;
122
+ else
123
+ cmd_len = FTS_CMD_READ_ID_LEN;
124
+ ret = fts_read(cmd, cmd_len, val, 2);
125
+ if (ret < 0) {
126
+ FTS_ERROR("write 90 cmd fail");
127
+ return ret;
128
+ }
129
+ FTS_INFO("read boot id:0x%02x%02x", val[0], val[1]);
130
+
131
+ ids = &upg->ts_data->ic_info.ids;
132
+ if ((val[0] == ids->rom_idh) && (val[1] == ids->rom_idl)) {
133
+ FTS_INFO("tp run in romboot");
134
+ *fw_sts = FTS_RUN_IN_ROM;
135
+ } else if ((val[0] == ids->pb_idh) && (val[1] == ids->pb_idl)) {
136
+ FTS_INFO("tp run in pramboot");
137
+ *fw_sts = FTS_RUN_IN_PRAM;
138
+ } else if ((val[0] == ids->bl_idh) && (val[1] == ids->bl_idl)) {
139
+ FTS_INFO("tp run in bootloader");
140
+ *fw_sts = FTS_RUN_IN_BOOTLOADER;
141
+ }
142
+
143
+ return 0;
144
+}
145
+
146
+static int fts_fwupg_reset_to_boot(struct fts_upgrade *upg)
147
+{
148
+ int ret = 0;
149
+ u8 reg = FTS_REG_UPGRADE;
150
+
151
+ FTS_INFO("send 0xAA and 0x55 to FW, reset to boot environment");
152
+ if (upg && upg->func && upg->func->is_reset_register_BC) {
153
+ reg = FTS_REG_UPGRADE2;
154
+ }
155
+
156
+ ret = fts_write_reg(reg, FTS_UPGRADE_AA);
157
+ if (ret < 0) {
158
+ FTS_ERROR("write FC=0xAA fail");
159
+ return ret;
160
+ }
161
+ fts_msleep(FTS_DELAY_UPGRADE_AA);
162
+
163
+ ret = fts_write_reg(reg, FTS_UPGRADE_55);
164
+ if (ret < 0) {
165
+ FTS_ERROR("write FC=0x55 fail");
166
+ return ret;
167
+ }
168
+
169
+ fts_msleep(FTS_DELAY_UPGRADE_RESET);
170
+ return 0;
171
+}
172
+
173
+/************************************************************************
174
+* Name: fts_fwupg_reset_to_romboot
175
+* Brief: reset to romboot, to load pramboot
176
+* Input:
177
+* Output:
178
+* Return: return 0 if success, otherwise return error code
179
+***********************************************************************/
180
+static int fts_fwupg_reset_to_romboot(struct fts_upgrade *upg)
181
+{
182
+ int ret = 0;
183
+ int i = 0;
184
+ u8 cmd = FTS_CMD_RESET;
185
+ enum FW_STATUS state = FTS_RUN_IN_ERROR;
186
+
187
+ ret = fts_write(&cmd, 1);
188
+ if (ret < 0) {
189
+ FTS_ERROR("pram/rom/bootloader reset cmd write fail");
190
+ return ret;
191
+ }
192
+ mdelay(10);
193
+
194
+ for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
195
+ ret = fts_fwupg_get_boot_state(upg, &state);
196
+ if (FTS_RUN_IN_ROM == state)
197
+ break;
198
+ fts_msleep(5);
199
+ }
200
+ if (i >= FTS_UPGRADE_LOOP) {
201
+ FTS_ERROR("reset to romboot fail");
202
+ return -EIO;
203
+ }
204
+
205
+ return 0;
206
+}
207
+
208
+static u16 fts_crc16_calc_host(u8 *pbuf, u32 length)
209
+{
210
+ u16 ecc = 0;
211
+ u32 i = 0;
212
+ u32 j = 0;
213
+
214
+ for ( i = 0; i < length; i += 2 ) {
215
+ ecc ^= ((pbuf[i] << 8) | (pbuf[i + 1]));
216
+ for (j = 0; j < 16; j ++) {
217
+ if (ecc & 0x01)
218
+ ecc = (u16)((ecc >> 1) ^ AL2_FCS_COEF);
219
+ else
220
+ ecc >>= 1;
221
+ }
222
+ }
223
+
224
+ return ecc;
225
+}
226
+
227
+static u16 fts_pram_ecc_calc_host(u8 *pbuf, u32 length)
228
+{
229
+ return fts_crc16_calc_host(pbuf, length);
230
+}
231
+
232
+static int fts_pram_ecc_cal_algo(
233
+ struct fts_upgrade *upg,
234
+ u32 start_addr,
235
+ u32 ecc_length)
236
+{
237
+ int ret = 0;
238
+ int i = 0;
239
+ int ecc = 0;
240
+ u8 val[2] = { 0 };
241
+ u8 tmp = 0;
242
+ u8 cmd[FTS_ROMBOOT_CMD_ECC_NEW_LEN] = { 0 };
243
+
244
+ FTS_INFO("read out pramboot checksum");
245
+ if ((!upg) || (!upg->func)) {
246
+ FTS_ERROR("upg/func is null");
247
+ return -EINVAL;
248
+ }
249
+
250
+ cmd[0] = FTS_ROMBOOT_CMD_ECC;
251
+ cmd[1] = BYTE_OFF_16(start_addr);
252
+ cmd[2] = BYTE_OFF_8(start_addr);
253
+ cmd[3] = BYTE_OFF_0(start_addr);
254
+ cmd[4] = BYTE_OFF_16(ecc_length);
255
+ cmd[5] = BYTE_OFF_8(ecc_length);
256
+ cmd[6] = BYTE_OFF_0(ecc_length);
257
+ ret = fts_write(cmd, FTS_ROMBOOT_CMD_ECC_NEW_LEN);
258
+ if (ret < 0) {
259
+ FTS_ERROR("write pramboot ecc cal cmd fail");
260
+ return ret;
261
+ }
262
+
263
+ cmd[0] = FTS_ROMBOOT_CMD_ECC_FINISH;
264
+ for (i = 0; i < FTS_ECC_FINISH_TIMEOUT; i++) {
265
+ fts_msleep(1);
266
+ ret = fts_read(cmd, 1, val, 1);
267
+ if (ret < 0) {
268
+ FTS_ERROR("ecc_finish read cmd fail");
269
+ return ret;
270
+ }
271
+ if (upg->func->new_return_value_from_ic ||
272
+ (upg->func->upgspec_version >= UPGRADE_SPEC_V_1_0)) {
273
+ tmp = FTS_ROMBOOT_CMD_ECC_FINISH_OK_A5;
274
+ } else {
275
+ tmp = FTS_ROMBOOT_CMD_ECC_FINISH_OK_00;
276
+ }
277
+ if (tmp == val[0])
278
+ break;
279
+ }
280
+ if (i >= FTS_ECC_FINISH_TIMEOUT) {
281
+ FTS_ERROR("wait ecc finish fail");
282
+ return -EIO;
283
+ }
284
+
285
+ cmd[0] = FTS_ROMBOOT_CMD_ECC_READ;
286
+ ret = fts_read(cmd, 1, val, 2);
287
+ if (ret < 0) {
288
+ FTS_ERROR("read pramboot ecc fail");
289
+ return ret;
290
+ }
291
+
292
+ ecc = ((u16)(val[0] << 8) + val[1]) & 0x0000FFFF;
293
+ return ecc;
294
+}
295
+
296
+static int fts_pram_ecc_cal_xor(void)
297
+{
298
+ int ret = 0;
299
+ u8 reg_val = 0;
300
+
301
+ FTS_INFO("read out pramboot checksum");
302
+
303
+ ret = fts_read_reg(FTS_ROMBOOT_CMD_ECC, &reg_val);
304
+ if (ret < 0) {
305
+ FTS_ERROR("read pramboot ecc fail");
306
+ return ret;
307
+ }
308
+
309
+ return (int)reg_val;
310
+}
311
+
312
+static int fts_pram_ecc_cal(struct fts_upgrade *upg, u32 saddr, u32 len)
313
+{
314
+ if ((!upg) || (!upg->func)) {
315
+ FTS_ERROR("upg/func is null");
316
+ return -EINVAL;
317
+ }
318
+
319
+ if ((ECC_CHECK_MODE_CRC16 == upg->func->pram_ecc_check_mode) ||
320
+ (upg->func->upgspec_version >= UPGRADE_SPEC_V_1_0)) {
321
+ return fts_pram_ecc_cal_algo(upg, saddr, len);
322
+ } else {
323
+ return fts_pram_ecc_cal_xor();
324
+ }
325
+}
326
+
327
+static int fts_pram_write_buf(struct fts_upgrade *upg, u8 *buf, u32 len)
328
+{
329
+ int ret = 0;
330
+ u32 i = 0;
331
+ u32 j = 0;
332
+ u32 offset = 0;
333
+ u32 remainder = 0;
334
+ u32 packet_number;
335
+ u32 packet_len = 0;
336
+ u8 packet_buf[FTS_FLASH_PACKET_LENGTH + FTS_CMD_WRITE_LEN] = { 0 };
337
+ u8 ecc_tmp = 0;
338
+ int ecc_in_host = 0;
339
+ u32 cmdlen = 0;
340
+
341
+ FTS_INFO("write pramboot to pram");
342
+ if ((!upg) || (!upg->func) || !buf) {
343
+ FTS_ERROR("upg/func/buf is null");
344
+ return -EINVAL;
345
+ }
346
+
347
+ FTS_INFO("pramboot len=%d", len);
348
+ if ((len < PRAMBOOT_MIN_SIZE) || (len > PRAMBOOT_MAX_SIZE)) {
349
+ FTS_ERROR("pramboot length(%d) fail", len);
350
+ return -EINVAL;
351
+ }
352
+
353
+ packet_number = len / FTS_FLASH_PACKET_LENGTH;
354
+ remainder = len % FTS_FLASH_PACKET_LENGTH;
355
+ if (remainder > 0)
356
+ packet_number++;
357
+ packet_len = FTS_FLASH_PACKET_LENGTH;
358
+
359
+ for (i = 0; i < packet_number; i++) {
360
+ offset = i * FTS_FLASH_PACKET_LENGTH;
361
+ /* last packet */
362
+ if ((i == (packet_number - 1)) && remainder)
363
+ packet_len = remainder;
364
+
365
+ if ((upg->ts_data->bus_type == BUS_TYPE_SPI) && (upg->ts_data->bus_ver == BUS_VER_V2)) {
366
+ packet_buf[0] = FTS_ROMBOOT_CMD_SET_PRAM_ADDR;
367
+ packet_buf[1] = BYTE_OFF_16(offset);
368
+ packet_buf[2] = BYTE_OFF_8(offset);
369
+ packet_buf[3] = BYTE_OFF_0(offset);
370
+
371
+ ret = fts_write(packet_buf, FTS_ROMBOOT_CMD_SET_PRAM_ADDR_LEN);
372
+ if (ret < 0) {
373
+ FTS_ERROR("pramboot set write address(%d) fail", i);
374
+ return ret;
375
+ }
376
+
377
+ packet_buf[0] = FTS_ROMBOOT_CMD_WRITE;
378
+ cmdlen = 1;
379
+ } else {
380
+ packet_buf[0] = FTS_ROMBOOT_CMD_WRITE;
381
+ packet_buf[1] = BYTE_OFF_16(offset);
382
+ packet_buf[2] = BYTE_OFF_8(offset);
383
+ packet_buf[3] = BYTE_OFF_0(offset);
384
+
385
+ packet_buf[4] = BYTE_OFF_8(packet_len);
386
+ packet_buf[5] = BYTE_OFF_0(packet_len);
387
+ cmdlen = 6;
388
+ }
389
+
390
+ for (j = 0; j < packet_len; j++) {
391
+ packet_buf[cmdlen + j] = buf[offset + j];
392
+ if (ECC_CHECK_MODE_XOR == upg->func->pram_ecc_check_mode) {
393
+ ecc_tmp ^= packet_buf[cmdlen + j];
394
+ }
395
+ }
396
+
397
+ ret = fts_write(packet_buf, packet_len + cmdlen);
398
+ if (ret < 0) {
399
+ FTS_ERROR("pramboot write data(%d) fail", i);
400
+ return ret;
401
+ }
402
+ }
403
+
404
+ if ((ECC_CHECK_MODE_CRC16 == upg->func->pram_ecc_check_mode) ||
405
+ (upg->func->upgspec_version >= UPGRADE_SPEC_V_1_0)) {
406
+ ecc_in_host = (int)fts_pram_ecc_calc_host(buf, len);
407
+ } else {
408
+ ecc_in_host = (int)ecc_tmp;
409
+ }
410
+
411
+ return ecc_in_host;
412
+}
413
+
414
+static int fts_pram_start(void)
415
+{
416
+ u8 cmd = FTS_ROMBOOT_CMD_START_APP;
417
+ int ret = 0;
418
+
419
+ FTS_INFO("remap to start pramboot");
420
+
421
+ ret = fts_write(&cmd, 1);
422
+ if (ret < 0) {
423
+ FTS_ERROR("write start pram cmd fail");
424
+ return ret;
425
+ }
426
+ fts_msleep(FTS_DELAY_PRAMBOOT_START);
427
+
428
+ return 0;
429
+}
430
+
431
+static int fts_pram_write_remap(struct fts_upgrade *upg)
432
+{
433
+ int ret = 0;
434
+ int ecc_in_host = 0;
435
+ int ecc_in_tp = 0;
436
+ u8 *pb_buf = NULL;
437
+ u32 pb_len = 0;
438
+
439
+ FTS_INFO("write pram and remap");
440
+ if (!upg || !upg->func || !upg->func->pramboot) {
441
+ FTS_ERROR("upg/func/pramboot is null");
442
+ return -EINVAL;
443
+ }
444
+
445
+ if (upg->func->pb_length < FTS_MIN_LEN) {
446
+ FTS_ERROR("pramboot length(%d) fail", upg->func->pb_length);
447
+ return -EINVAL;
448
+ }
449
+
450
+ pb_buf = upg->func->pramboot;
451
+ pb_len = upg->func->pb_length;
452
+
453
+ /* write pramboot to pram */
454
+ ecc_in_host = fts_pram_write_buf(upg, pb_buf, pb_len);
455
+ if (ecc_in_host < 0) {
456
+ FTS_ERROR( "write pramboot fail");
457
+ return ecc_in_host;
458
+ }
459
+
460
+ /* read out checksum */
461
+ ecc_in_tp = fts_pram_ecc_cal(upg, 0, pb_len);
462
+ if (ecc_in_tp < 0) {
463
+ FTS_ERROR( "read pramboot ecc fail");
464
+ return ecc_in_tp;
465
+ }
466
+
467
+ FTS_INFO("pram ecc in tp:%x, host:%x", ecc_in_tp, ecc_in_host);
468
+ /* pramboot checksum != fw checksum, upgrade fail */
469
+ if (ecc_in_host != ecc_in_tp) {
470
+ FTS_ERROR("pramboot ecc check fail");
471
+ return -EIO;
472
+ }
473
+
474
+ /*start pram*/
475
+ ret = fts_pram_start();
476
+ if (ret < 0) {
477
+ FTS_ERROR("pram start fail");
478
+ return ret;
479
+ }
480
+
481
+ return 0;
482
+}
483
+
484
+static int fts_pram_init(void)
485
+{
486
+ int ret = 0;
487
+ u8 reg_val = 0;
488
+ u8 wbuf[3] = { 0 };
489
+
490
+ FTS_INFO("pramboot initialization");
491
+
492
+ /* read flash ID */
493
+ wbuf[0] = FTS_CMD_FLASH_TYPE;
494
+ ret = fts_read(wbuf, 1, &reg_val, 1);
495
+ if (ret < 0) {
496
+ FTS_ERROR("read flash type fail");
497
+ return ret;
498
+ }
499
+
500
+ /* set flash clk */
501
+ wbuf[0] = FTS_CMD_FLASH_TYPE;
502
+ wbuf[1] = reg_val;
503
+ wbuf[2] = 0x00;
504
+ ret = fts_write(wbuf, 3);
505
+ if (ret < 0) {
506
+ FTS_ERROR("write flash type fail");
507
+ return ret;
508
+ }
509
+
510
+ return 0;
511
+}
512
+
513
+static int fts_pram_write_init(struct fts_upgrade *upg)
514
+{
515
+ int ret = 0;
516
+ bool state = 0;
517
+ enum FW_STATUS status = FTS_RUN_IN_ERROR;
518
+
519
+ FTS_INFO("**********pram write and init**********");
520
+ if ((NULL == upg) || (NULL == upg->func)) {
521
+ FTS_ERROR("upgrade/func is null");
522
+ return -EINVAL;
523
+ }
524
+
525
+ if (!upg->func->pramboot_supported) {
526
+ FTS_ERROR("ic not support pram");
527
+ return -EINVAL;
528
+ }
529
+
530
+ FTS_DEBUG("check whether tp is in romboot or not ");
531
+ /* need reset to romboot when non-romboot state */
532
+ ret = fts_fwupg_get_boot_state(upg, &status);
533
+ if (status != FTS_RUN_IN_ROM) {
534
+ if (FTS_RUN_IN_PRAM == status) {
535
+ FTS_INFO("tp is in pramboot, need send reset cmd before upgrade");
536
+ ret = fts_pram_init();
537
+ if (ret < 0) {
538
+ FTS_ERROR("pramboot(before) init fail");
539
+ return ret;
540
+ }
541
+ }
542
+
543
+ FTS_INFO("tp isn't in romboot, need send reset to romboot");
544
+ ret = fts_fwupg_reset_to_romboot(upg);
545
+ if (ret < 0) {
546
+ FTS_ERROR("reset to romboot fail");
547
+ return ret;
548
+ }
549
+ }
550
+
551
+ /* check the length of the pramboot */
552
+ ret = fts_pram_write_remap(upg);
553
+ if (ret < 0) {
554
+ FTS_ERROR("pram write fail, ret=%d", ret);
555
+ return ret;
556
+ }
557
+
558
+ FTS_DEBUG("after write pramboot, confirm run in pramboot");
559
+ state = fts_fwupg_check_state(upg, FTS_RUN_IN_PRAM);
560
+ if (!state) {
561
+ FTS_ERROR("not in pramboot");
562
+ return -EIO;
563
+ }
564
+
565
+ ret = fts_pram_init();
566
+ if (ret < 0) {
567
+ FTS_ERROR("pramboot init fail");
568
+ return ret;
569
+ }
570
+
571
+ return 0;
572
+}
573
+
574
+static bool fts_fwupg_check_fw_valid(void)
575
+{
576
+ int ret = 0;
577
+
578
+ ret = fts_wait_tp_to_valid();
579
+ if (ret < 0) {
580
+ FTS_INFO("tp fw invaild");
581
+ return false;
582
+ }
583
+
584
+ FTS_INFO("tp fw vaild");
585
+ return true;
586
+}
587
+
588
+/************************************************************************
589
+* Name: fts_fwupg_check_state
590
+* Brief: confirm tp run in which mode: romboot/pramboot/bootloader
591
+* Input:
592
+* Output:
593
+* Return: return true if state is match, otherwise return false
594
+***********************************************************************/
595
+static bool fts_fwupg_check_state(
596
+ struct fts_upgrade *upg, enum FW_STATUS rstate)
597
+{
598
+ int ret = 0;
599
+ int i = 0;
600
+ enum FW_STATUS cstate = FTS_RUN_IN_ERROR;
601
+
602
+ for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
603
+ ret = fts_fwupg_get_boot_state(upg, &cstate);
604
+ /* FTS_DEBUG("fw state=%d, retries=%d", cstate, i); */
605
+ if (cstate == rstate)
606
+ return true;
607
+ fts_msleep(FTS_DELAY_READ_ID);
608
+
609
+ /* try to hardware reset to boot mode */
610
+ if ((rstate == FTS_RUN_IN_BOOTLOADER) || (rstate == FTS_RUN_IN_ROM)) {
611
+ if (i >= FTS_UPGRADE_RESET_LOOP) {
612
+ fts_reset_proc(upg->ts_data, true, 0);
613
+ mdelay(FTS_CMD_START_DELAY + ((i - FTS_UPGRADE_RESET_LOOP) * 4));
614
+ if (upg->func->hid_supported) {
615
+ fts_hid2std(1);
616
+ fts_write_reg(0x55, 0xAA);
617
+ fts_msleep(FTS_CMD_START_DELAY);
618
+ fts_hid2std(1);
619
+ }
620
+ }
621
+ }
622
+ }
623
+
624
+ return false;
625
+}
626
+
627
+/************************************************************************
628
+* Name: fts_fwupg_reset_in_boot
629
+* Brief: RST CMD(07), reset to romboot(bootloader) in boot environment
630
+* Input:
631
+* Output:
632
+* Return: return 0 if success, otherwise return error code
633
+***********************************************************************/
634
+int fts_fwupg_reset_in_boot(void)
635
+{
636
+ int ret = 0;
637
+ u8 cmd = FTS_CMD_RESET;
638
+
639
+ FTS_INFO("reset in boot environment");
640
+ ret = fts_write(&cmd, 1);
641
+ if (ret < 0) {
642
+ FTS_ERROR("pram/rom/bootloader reset cmd write fail");
643
+ return ret;
644
+ }
645
+
646
+ fts_msleep(FTS_DELAY_UPGRADE_RESET);
647
+ return 0;
648
+}
649
+
650
+/************************************************************************
651
+* Name: fts_fwupg_enter_into_boot
652
+* Brief: enter into boot environment, ready for upgrade
653
+* Input:
654
+* Output:
655
+* Return: return 0 if success, otherwise return error code
656
+***********************************************************************/
657
+int fts_fwupg_enter_into_boot(void)
658
+{
659
+ int ret = 0;
660
+ bool fwvalid = false;
661
+ bool state = false;
662
+ struct fts_upgrade *upg = fwupgrade;
663
+
664
+ FTS_INFO("***********enter into pramboot/bootloader***********");
665
+ if ((!upg) || (NULL == upg->func)) {
666
+ FTS_ERROR("upgrade/func is null");
667
+ return -EINVAL;
668
+ }
669
+
670
+ fwvalid = fts_fwupg_check_fw_valid();
671
+ if (fwvalid) {
672
+ ret = fts_fwupg_reset_to_boot(upg);
673
+ if (ret < 0) {
674
+ FTS_ERROR("enter into romboot/bootloader fail");
675
+ return ret;
676
+ }
677
+ } else if (upg->func->read_boot_id_need_reset) {
678
+ ret = fts_fwupg_reset_in_boot();
679
+ if (ret < 0) {
680
+ FTS_ERROR("reset before read boot id when fw invalid fail");
681
+ return ret;
682
+ }
683
+ }
684
+
685
+ if (upg->func->pramboot_supported) {
686
+ FTS_INFO("pram supported, write pramboot and init");
687
+ /* pramboot */
688
+ if (upg->func->write_pramboot_private)
689
+ ret = upg->func->write_pramboot_private();
690
+ else
691
+ ret = fts_pram_write_init(upg);
692
+ if (ret < 0) {
693
+ FTS_ERROR("pram write_init fail");
694
+ return ret;
695
+ }
696
+ } else {
697
+ FTS_DEBUG("pram not supported, confirm in bootloader");
698
+ /* bootloader */
699
+ state = fts_fwupg_check_state(upg, FTS_RUN_IN_BOOTLOADER);
700
+ if (!state) {
701
+ FTS_ERROR("fw not in bootloader, fail");
702
+ return -EIO;
703
+ }
704
+ }
705
+
706
+ return 0;
707
+}
708
+
709
+/************************************************************************
710
+* Name: fts_fwupg_hwrst_to_boot
711
+* Brief: Hardware reset to enter into boot environment, ready for upgrade
712
+* Input:
713
+* Output:
714
+* Return: return 0 if success, otherwise return error code
715
+***********************************************************************/
716
+int fts_fwupg_hwrst_to_boot(void)
717
+{
718
+ int ret = 0;
719
+ int i = 0;
720
+ bool state = false;
721
+ enum FW_STATUS cstate = FTS_RUN_IN_ERROR;
722
+ struct fts_upgrade *upg = fwupgrade;
723
+
724
+ FTS_INFO("***********enter into pramboot/bootloader***********");
725
+ if ((!upg) || (!upg->func) || (!upg->ts_data)) {
726
+ FTS_ERROR("upgrade/func/ts_data is null");
727
+ return -EINVAL;
728
+ }
729
+
730
+ FTS_INFO("enter into boot environment");
731
+ for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
732
+ /* hardware tp reset to boot */
733
+ fts_reset_proc(upg->ts_data, true, 0);
734
+ mdelay(FTS_CMD_START_DELAY + i * 2);
735
+ fts_fwupg_get_boot_state(upg, &cstate);
736
+ if (cstate != FTS_RUN_IN_ERROR) {
737
+ FTS_INFO("get boot state:%d", cstate);
738
+ break;
739
+ }
740
+ }
741
+
742
+ if (upg->func->pramboot_supported) {
743
+ FTS_INFO("pram supported, write pramboot and init");
744
+ /* pramboot */
745
+ if (upg->func->write_pramboot_private)
746
+ ret = upg->func->write_pramboot_private();
747
+ else
748
+ ret = fts_pram_write_init(upg);
749
+ if (ret < 0) {
750
+ FTS_ERROR("pram write_init fail");
751
+ return ret;
752
+ }
753
+ } else {
754
+ FTS_DEBUG("pram not supported, confirm in bootloader");
755
+ /* bootloader */
756
+ state = fts_fwupg_check_state(upg, FTS_RUN_IN_BOOTLOADER);
757
+ if (!state) {
758
+ FTS_ERROR("fw not in bootloader, fail");
759
+ return -EIO;
760
+ }
761
+ }
762
+
763
+ return 0;
764
+}
765
+
766
+/************************************************************************
767
+ * Name: fts_fwupg_check_flash_status
768
+ * Brief: read status from tp
769
+ * Input: flash_status: correct value from tp
770
+ * retries: read retry times
771
+ * retries_delay: retry delay
772
+ * Output:
773
+ * Return: return true if flash status check pass, otherwise return false
774
+***********************************************************************/
775
+static bool fts_fwupg_check_flash_status(
776
+ u16 flash_status,
777
+ int retries,
778
+ int retries_delay)
779
+{
780
+ int ret = 0;
781
+ int i = 0;
782
+ u8 cmd = 0;
783
+ u8 val[FTS_CMD_FLASH_STATUS_LEN] = { 0 };
784
+ u16 read_status = 0;
785
+
786
+ for (i = 0; i < retries; i++) {
787
+ cmd = FTS_CMD_FLASH_STATUS;
788
+ ret = fts_read(&cmd , 1, val, FTS_CMD_FLASH_STATUS_LEN);
789
+ read_status = (((u16)val[0]) << 8) + val[1];
790
+ if (flash_status == read_status) {
791
+ /* FTS_DEBUG("[UPGRADE]flash status ok"); */
792
+ return true;
793
+ }
794
+ /* FTS_DEBUG("flash status fail,ok:%04x read:%04x, retries:%d", flash_status, read_status, i); */
795
+ fts_msleep(retries_delay);
796
+ }
797
+
798
+ FTS_ERROR("flash status fail,ok:%04x,read:%04x,retries:%d",
799
+ flash_status, read_status, i);
800
+ return false;
801
+}
802
+
803
+/************************************************************************
804
+ * Name: fts_fwupg_erase
805
+ * Brief: erase flash area
806
+ * Input: delay - delay after erase
807
+ * Output:
808
+ * Return: return 0 if success, otherwise return error code
809
+ ***********************************************************************/
810
+int fts_fwupg_erase(u32 delay)
811
+{
812
+ int ret = 0;
813
+ u8 cmd = 0;
814
+ bool flag = false;
815
+
816
+ FTS_INFO("**********erase now**********");
817
+
818
+ /*send to erase flash*/
819
+ cmd = FTS_CMD_ERASE_APP;
820
+ ret = fts_write(&cmd, 1);
821
+ if (ret < 0) {
822
+ FTS_ERROR("erase cmd fail");
823
+ return ret;
824
+ }
825
+ fts_msleep(delay);
826
+
827
+ /* read status 0xF0AA: success */
828
+ flag = fts_fwupg_check_flash_status(FTS_CMD_FLASH_STATUS_ERASE_OK,
829
+ FTS_RETRIES_REASE,
830
+ FTS_RETRIES_DELAY_REASE);
831
+ if (!flag) {
832
+ FTS_ERROR("ecc flash status check fail");
833
+ return -EIO;
834
+ }
835
+
836
+ return 0;
837
+}
838
+
839
+/************************************************************************
840
+ * Name: fts_fwupg_ecc_cal
841
+ * Brief: calculate and get ecc from tp
842
+ * Input: saddr - start address need calculate ecc
843
+ * len - length need calculate ecc
844
+ * Output:
845
+ * Return: return data ecc of tp if success, otherwise return error code
846
+ ***********************************************************************/
847
+int fts_fwupg_ecc_cal(u32 saddr, u32 len)
848
+{
849
+ int ret = 0;
850
+ u32 i = 0;
851
+ u32 cmdlen = FTS_CMD_ECC_CAL_LEN;
852
+ u8 wbuf[FTS_CMD_ECC_CAL_LEN] = { 0 };
853
+ u8 val[FTS_CMD_FLASH_STATUS_LEN] = { 0 };
854
+ int ecc = 0;
855
+ int ecc_len = 0;
856
+ u32 packet_num = 0;
857
+ u32 packet_len = 0;
858
+ u32 remainder = 0;
859
+ u32 addr = 0;
860
+ u32 offset = 0;
861
+ bool bflag = false;
862
+ struct fts_upgrade *upg = fwupgrade;
863
+
864
+ FTS_INFO( "**********read out checksum**********");
865
+ if ((NULL == upg) || (NULL == upg->func)) {
866
+ FTS_ERROR("upgrade/func is null");
867
+ return -EINVAL;
868
+ }
869
+
870
+ /* check sum init */
871
+ wbuf[0] = FTS_CMD_ECC_INIT;
872
+ ret = fts_write(wbuf, 1);
873
+ if (ret < 0) {
874
+ FTS_ERROR("ecc init cmd write fail");
875
+ return ret;
876
+ }
877
+
878
+ if (upg->func->upgspec_version >= UPGRADE_SPEC_V_1_0) {
879
+ packet_num = 1;
880
+ remainder = 0;
881
+ packet_len = len;
882
+ } else {
883
+ packet_num = len / FTS_MAX_LEN_ECC_CALC;
884
+ remainder = len % FTS_MAX_LEN_ECC_CALC;
885
+ if (remainder)
886
+ packet_num++;
887
+ packet_len = FTS_MAX_LEN_ECC_CALC;
888
+ }
889
+ FTS_INFO("ecc calc num:%d, remainder:%d", packet_num, remainder);
890
+
891
+ /* send commond to start checksum */
892
+ wbuf[0] = FTS_CMD_ECC_CAL;
893
+ for (i = 0; i < packet_num; i++) {
894
+ offset = FTS_MAX_LEN_ECC_CALC * i;
895
+ addr = saddr + offset;
896
+ wbuf[1] = BYTE_OFF_16(addr);
897
+ wbuf[2] = BYTE_OFF_8(addr);
898
+ wbuf[3] = BYTE_OFF_0(addr);
899
+
900
+ if ((upg->func->upgspec_version >= UPGRADE_SPEC_V_1_0)) {
901
+ wbuf[4] = BYTE_OFF_16(packet_len);
902
+ wbuf[5] = BYTE_OFF_8(packet_len);
903
+ wbuf[6] = BYTE_OFF_0(packet_len);
904
+ cmdlen = FTS_CMD_ECC_CAL_LEN;
905
+ } else {
906
+ if ((i == (packet_num - 1)) && remainder)
907
+ packet_len = remainder;
908
+ wbuf[4] = BYTE_OFF_8(packet_len);
909
+ wbuf[5] = BYTE_OFF_0(packet_len);
910
+ cmdlen = FTS_CMD_ECC_CAL_LEN - 1;
911
+ }
912
+
913
+ FTS_DEBUG("ecc calc startaddr:0x%04x, len:%d", addr, packet_len);
914
+ ret = fts_write(wbuf, cmdlen);
915
+ if (ret < 0) {
916
+ FTS_ERROR("ecc calc cmd write fail");
917
+ return ret;
918
+ }
919
+
920
+ fts_msleep(packet_len / 256);
921
+
922
+ /* read status if check sum is finished */
923
+ bflag = fts_fwupg_check_flash_status(FTS_CMD_FLASH_STATUS_ECC_OK,
924
+ FTS_RETRIES_ECC_CAL,
925
+ FTS_RETRIES_DELAY_ECC_CAL);
926
+ if (!bflag) {
927
+ FTS_ERROR("ecc flash status read fail");
928
+ return -EIO;
929
+ }
930
+ }
931
+
932
+ ecc_len = 1;
933
+ if ((ECC_CHECK_MODE_CRC16 == upg->func->fw_ecc_check_mode) ||
934
+ (upg->func->upgspec_version >= UPGRADE_SPEC_V_1_0)) {
935
+ ecc_len = 2;
936
+ }
937
+
938
+ /* read out check sum */
939
+ wbuf[0] = FTS_CMD_ECC_READ;
940
+ ret = fts_read(wbuf, 1, val, ecc_len);
941
+ if (ret < 0) {
942
+ FTS_ERROR( "ecc read cmd write fail");
943
+ return ret;
944
+ }
945
+
946
+ if ((ECC_CHECK_MODE_CRC16 == upg->func->fw_ecc_check_mode) ||
947
+ (upg->func->upgspec_version >= UPGRADE_SPEC_V_1_0)) {
948
+ ecc = (int)((u16)(val[0] << 8) + val[1]);
949
+ } else {
950
+ ecc = (int)val[0];
951
+ }
952
+
953
+ return ecc;
954
+}
955
+
956
+/************************************************************************
957
+ * Name: fts_flash_write_buf
958
+ * Brief: write buf data to flash address
959
+ * Input: saddr - start address data write to flash
960
+ * buf - data buffer
961
+ * len - data length
962
+ * delay - delay after write
963
+ * Output:
964
+ * Return: return data ecc of host if success, otherwise return error code
965
+ ***********************************************************************/
966
+int fts_flash_write_buf(
967
+ u32 saddr,
968
+ u8 *buf,
969
+ u32 len,
970
+ u32 delay)
971
+{
972
+ int ret = 0;
973
+ u32 i = 0;
974
+ u32 j = 0;
975
+ u32 packet_number = 0;
976
+ u32 packet_len = 0;
977
+ u32 addr = 0;
978
+ u32 offset = 0;
979
+ u32 remainder = 0;
980
+ u32 cmdlen = 0;
981
+ u8 packet_buf[FTS_FLASH_PACKET_LENGTH + FTS_CMD_WRITE_LEN] = { 0 };
982
+ u8 ecc_tmp = 0;
983
+ int ecc_in_host = 0;
984
+ u8 cmd = 0;
985
+ u8 val[FTS_CMD_FLASH_STATUS_LEN] = { 0 };
986
+ u16 read_status = 0;
987
+ u16 wr_ok = 0;
988
+ struct fts_upgrade *upg = fwupgrade;
989
+
990
+ FTS_INFO( "**********write data to flash**********");
991
+ if ((!upg) || (!upg->func || !buf || !len)) {
992
+ FTS_ERROR("upgrade/func/buf/len is invalid");
993
+ return -EINVAL;
994
+ }
995
+
996
+ FTS_INFO("data buf start addr=0x%x, len=0x%x", saddr, len);
997
+ packet_number = len / FTS_FLASH_PACKET_LENGTH;
998
+ remainder = len % FTS_FLASH_PACKET_LENGTH;
999
+ if (remainder > 0)
1000
+ packet_number++;
1001
+ packet_len = FTS_FLASH_PACKET_LENGTH;
1002
+ FTS_INFO("write data, num:%d remainder:%d", packet_number, remainder);
1003
+
1004
+ for (i = 0; i < packet_number; i++) {
1005
+ offset = i * FTS_FLASH_PACKET_LENGTH;
1006
+ addr = saddr + offset;
1007
+
1008
+ /* last packet */
1009
+ if ((i == (packet_number - 1)) && remainder)
1010
+ packet_len = remainder;
1011
+
1012
+ if ((upg->ts_data->bus_type == BUS_TYPE_SPI) && (upg->ts_data->bus_ver == BUS_VER_V2)) {
1013
+ packet_buf[0] = FTS_CMD_SET_WFLASH_ADDR;
1014
+ packet_buf[1] = BYTE_OFF_16(addr);
1015
+ packet_buf[2] = BYTE_OFF_8(addr);
1016
+ packet_buf[3] = BYTE_OFF_0(addr);
1017
+ ret = fts_write(packet_buf, FTS_LEN_SET_ADDR);
1018
+ if (ret < 0) {
1019
+ FTS_ERROR("set flash address fail");
1020
+ return ret;
1021
+ }
1022
+
1023
+ packet_buf[0] = FTS_CMD_WRITE;
1024
+ cmdlen = 1;
1025
+ } else {
1026
+ packet_buf[0] = FTS_CMD_WRITE;
1027
+ packet_buf[1] = BYTE_OFF_16(addr);
1028
+ packet_buf[2] = BYTE_OFF_8(addr);
1029
+ packet_buf[3] = BYTE_OFF_0(addr);
1030
+ packet_buf[4] = BYTE_OFF_8(packet_len);
1031
+ packet_buf[5] = BYTE_OFF_0(packet_len);
1032
+ cmdlen = 6;
1033
+ }
1034
+
1035
+ for (j = 0; j < packet_len; j++) {
1036
+ packet_buf[cmdlen + j] = buf[offset + j];
1037
+ ecc_tmp ^= packet_buf[cmdlen + j];
1038
+ }
1039
+
1040
+ ret = fts_write(packet_buf, packet_len + cmdlen);
1041
+ if (ret < 0) {
1042
+ FTS_ERROR("app write fail");
1043
+ return ret;
1044
+ }
1045
+ mdelay(delay);
1046
+
1047
+ /* read status */
1048
+ wr_ok = FTS_CMD_FLASH_STATUS_WRITE_OK + addr / packet_len;
1049
+ for (j = 0; j < FTS_RETRIES_WRITE; j++) {
1050
+ cmd = FTS_CMD_FLASH_STATUS;
1051
+ ret = fts_read(&cmd , 1, val, FTS_CMD_FLASH_STATUS_LEN);
1052
+ read_status = (((u16)val[0]) << 8) + val[1];
1053
+ /* FTS_INFO("%x %x", wr_ok, read_status); */
1054
+ if (wr_ok == read_status) {
1055
+ break;
1056
+ }
1057
+ mdelay(FTS_RETRIES_DELAY_WRITE);
1058
+ }
1059
+ }
1060
+
1061
+ ecc_in_host = (int)ecc_tmp;
1062
+ if ((ECC_CHECK_MODE_CRC16 == upg->func->fw_ecc_check_mode) ||
1063
+ (upg->func->upgspec_version >= UPGRADE_SPEC_V_1_0)) {
1064
+ ecc_in_host = (int)fts_crc16_calc_host(buf, len);
1065
+ }
1066
+
1067
+ return ecc_in_host;
1068
+}
1069
+
1070
+/************************************************************************
1071
+ * Name: fts_flash_read_buf
1072
+ * Brief: read data from flash
1073
+ * Input: saddr - start address data write to flash
1074
+ * buf - buffer to store data read from flash
1075
+ * len - read length
1076
+ * Output:
1077
+ * Return: return 0 if success, otherwise return error code
1078
+ *
1079
+ * Warning: can't call this function directly, need call in boot environment
1080
+ ***********************************************************************/
1081
+int fts_flash_read_buf(u32 saddr, u8 *buf, u32 len)
1082
+{
1083
+ int ret = 0;
1084
+ u32 i = 0;
1085
+ u32 packet_number = 0;
1086
+ u32 packet_len = 0;
1087
+ u32 addr = 0;
1088
+ u32 offset = 0;
1089
+ u32 remainder = 0;
1090
+ u8 wbuf[FTS_CMD_READ_LEN_SPI] = { 0 };
1091
+ struct fts_upgrade *upg = fwupgrade;
1092
+
1093
+ if (!upg || !buf || !len) {
1094
+ FTS_ERROR("upgrade/buf is NULL or len is 0");
1095
+ return -EINVAL;
1096
+ }
1097
+
1098
+ packet_number = len / FTS_FLASH_PACKET_LENGTH;
1099
+ remainder = len % FTS_FLASH_PACKET_LENGTH;
1100
+ if (remainder > 0) {
1101
+ packet_number++;
1102
+ }
1103
+ packet_len = FTS_FLASH_PACKET_LENGTH;
1104
+ FTS_INFO("read packet_number:%d, remainder:%d", packet_number, remainder);
1105
+
1106
+
1107
+ for (i = 0; i < packet_number; i++) {
1108
+ offset = i * FTS_FLASH_PACKET_LENGTH;
1109
+ addr = saddr + offset;
1110
+ /* last packet */
1111
+ if ((i == (packet_number - 1)) && remainder)
1112
+ packet_len = remainder;
1113
+
1114
+ if (upg->ts_data->bus_type == BUS_TYPE_I2C) {
1115
+ wbuf[0] = FTS_CMD_READ;
1116
+ wbuf[1] = BYTE_OFF_16(addr);
1117
+ wbuf[2] = BYTE_OFF_8(addr);
1118
+ wbuf[3] = BYTE_OFF_0(addr);
1119
+ ret = fts_write(wbuf, FTS_CMD_READ_LEN);
1120
+ if (ret < 0) {
1121
+ FTS_ERROR("pram/bootloader write 03 command fail");
1122
+ return ret;
1123
+ }
1124
+
1125
+ fts_msleep(FTS_CMD_READ_DELAY); /* must wait, otherwise read wrong data */
1126
+ ret = fts_read(NULL, 0, buf + offset, packet_len);
1127
+ if (ret < 0) {
1128
+ FTS_ERROR("pram/bootloader read 03 command fail");
1129
+ return ret;
1130
+ }
1131
+ } else if (upg->ts_data->bus_type == BUS_TYPE_SPI) {
1132
+ FTS_INFO("bus ver:%d", upg->ts_data->bus_ver);
1133
+ if (upg->ts_data->bus_ver == BUS_VER_V2) {
1134
+ wbuf[0] = FTS_CMD_SET_RFLASH_ADDR;
1135
+ wbuf[1] = BYTE_OFF_16(addr);
1136
+ wbuf[2] = BYTE_OFF_8(addr);
1137
+ wbuf[3] = BYTE_OFF_0(addr);
1138
+ ret = fts_write(wbuf, FTS_LEN_SET_ADDR);
1139
+ if (ret < 0) {
1140
+ FTS_ERROR("set flash address fail");
1141
+ return ret;
1142
+ }
1143
+
1144
+ fts_msleep(FTS_CMD_READ_DELAY);
1145
+ wbuf[0] = FTS_CMD_READ;
1146
+ ret = fts_read(wbuf, 1, buf + offset, packet_len);
1147
+ if (ret < 0) {
1148
+ FTS_ERROR("pram/bootloader read 03(SPI_V2) command fail");
1149
+ return ret;
1150
+ }
1151
+ } else if (upg->ts_data->bus_ver == BUS_VER_DEFAULT) {
1152
+ wbuf[0] = FTS_CMD_READ;
1153
+ wbuf[1] = BYTE_OFF_16(addr);
1154
+ wbuf[2] = BYTE_OFF_8(addr);
1155
+ wbuf[3] = BYTE_OFF_0(addr);
1156
+ wbuf[4] = BYTE_OFF_8(packet_len);
1157
+ wbuf[5] = BYTE_OFF_0(packet_len);
1158
+ ret = fts_read(wbuf, FTS_CMD_READ_LEN_SPI, \
1159
+ buf + offset, packet_len);
1160
+ if (ret < 0) {
1161
+ FTS_ERROR("pram/bootloader read 03(SPI) command fail");
1162
+ return ret;
1163
+ }
1164
+ }
1165
+ } else FTS_ERROR("unknown bus type:%d", upg->ts_data->bus_type);
1166
+ }
1167
+
1168
+ return 0;
1169
+}
1170
+
1171
+/************************************************************************
1172
+ * Name: fts_flash_read
1173
+ * Brief:
1174
+ * Input: addr - address of flash
1175
+ * len - length of read
1176
+ * Output: buf - data read from flash
1177
+ * Return: return 0 if success, otherwise return error code
1178
+ ***********************************************************************/
1179
+static int fts_flash_read(u32 addr, u8 *buf, u32 len)
1180
+{
1181
+ int ret = 0;
1182
+
1183
+ FTS_INFO("***********read flash***********");
1184
+ if ((NULL == buf) || (0 == len)) {
1185
+ FTS_ERROR("buf is NULL or len is 0");
1186
+ return -EINVAL;
1187
+ }
1188
+
1189
+ ret = fts_fwupg_enter_into_boot();
1190
+ if (ret < 0) {
1191
+ FTS_ERROR("enter into pramboot/bootloader fail");
1192
+ goto read_flash_err;
1193
+ }
1194
+
1195
+ ret = fts_flash_read_buf(addr, buf, len);
1196
+ if (ret < 0) {
1197
+ FTS_ERROR("read flash fail");
1198
+ goto read_flash_err;
1199
+ }
1200
+
1201
+read_flash_err:
1202
+ /* reset to normal boot */
1203
+ ret = fts_fwupg_reset_in_boot();
1204
+ if (ret < 0) {
1205
+ FTS_ERROR("reset to normal boot fail");
1206
+ }
1207
+ return ret;
1208
+}
1209
+
1210
+static int fts_read_file_default(char *file_name, u8 **file_buf)
1211
+{
1212
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
1213
+ int ret = 0;
1214
+ char file_path[FILE_NAME_LENGTH] = { 0 };
1215
+ struct file *filp = NULL;
1216
+ struct inode *inode;
1217
+ mm_segment_t old_fs;
1218
+ loff_t pos;
1219
+ loff_t file_len = 0;
1220
+
1221
+ if ((NULL == file_name) || (NULL == file_buf)) {
1222
+ FTS_ERROR("filename/filebuf is NULL");
1223
+ return -EINVAL;
1224
+ }
1225
+
1226
+ snprintf(file_path, FILE_NAME_LENGTH, "%s%s", FTS_FW_BIN_FILEPATH, file_name);
1227
+ filp = filp_open(file_path, O_RDONLY, 0);
1228
+ if (IS_ERR(filp)) {
1229
+ FTS_ERROR("open %s file fail", file_path);
1230
+ return -ENOENT;
1231
+ }
1232
+
1233
+#if 1
1234
+ inode = filp->f_inode;
1235
+#else
1236
+ /* reserved for linux earlier verion */
1237
+ inode = filp->f_dentry->d_inode;
1238
+#endif
1239
+
1240
+ file_len = inode->i_size;
1241
+ *file_buf = (u8 *)vmalloc(file_len);
1242
+ if (NULL == *file_buf) {
1243
+ FTS_ERROR("file buf malloc fail");
1244
+ filp_close(filp, NULL);
1245
+ return -ENOMEM;
1246
+ }
1247
+ old_fs = get_fs();
1248
+ set_fs(KERNEL_DS);
1249
+ pos = 0;
1250
+ ret = vfs_read(filp, *file_buf, file_len , &pos);
1251
+ if (ret < 0)
1252
+ FTS_ERROR("read file fail");
1253
+ FTS_INFO("file len:%d read len:%d pos:%d", (u32)file_len, ret, (u32)pos);
1254
+ filp_close(filp, NULL);
1255
+ set_fs(old_fs);
1256
+ return ret;
1257
+#else
1258
+ FTS_INFO("not support vfs_read to get fw file");
1259
+ return -EINVAL;
1260
+#endif
1261
+}
1262
+
1263
+static int fts_read_file_request_firmware(char *file_name, u8 **file_buf)
1264
+{
1265
+#if FTS_FW_REQUEST_SUPPORT
1266
+ int ret = 0;
1267
+ const struct firmware *fw = NULL;
1268
+ char fwname[FILE_NAME_LENGTH] = { 0 };
1269
+ struct fts_upgrade *upg = fwupgrade;
1270
+
1271
+ snprintf(fwname, FILE_NAME_LENGTH, "%s", file_name);
1272
+ ret = request_firmware(&fw, fwname, upg->ts_data->dev);
1273
+ if (0 == ret) {
1274
+ FTS_INFO("firmware(%s) request successfully", fwname);
1275
+ *file_buf = vmalloc(fw->size);
1276
+ if (NULL == *file_buf) {
1277
+ FTS_ERROR("fw buffer vmalloc fail");
1278
+ ret = -ENOMEM;
1279
+ } else {
1280
+ memcpy(*file_buf, fw->data, fw->size);
1281
+ ret = fw->size;
1282
+ }
1283
+ } else {
1284
+ FTS_INFO("firmware(%s) request fail,ret=%d", fwname, ret);
1285
+ ret = -EIO;
1286
+ }
1287
+
1288
+ if (fw != NULL) {
1289
+ release_firmware(fw);
1290
+ fw = NULL;
1291
+ }
1292
+
1293
+ return ret;
1294
+#else
1295
+ FTS_INFO("not support request_firmware to get fw file");
1296
+ return -EINVAL;
1297
+#endif
1298
+}
1299
+
1300
+static int fts_read_file(char *file_name, u8 **file_buf)
1301
+{
1302
+ int ret = 0;
1303
+
1304
+ ret = fts_read_file_request_firmware(file_name, file_buf);
1305
+ if (ret < 0) {
1306
+ ret = fts_read_file_default(file_name, file_buf);
1307
+ if (ret < 0) {
1308
+ FTS_INFO("get fw file(default) abnormal");
1309
+ return ret;
1310
+ }
1311
+ }
1312
+
1313
+ return ret;
1314
+}
1315
+
1316
+int fts_upgrade_bin(char *fw_name, bool force)
1317
+{
1318
+ int ret = 0;
1319
+ int irq_need_recovery = false;
1320
+ int esd_need_recovery = false;
1321
+ u32 fw_file_len = 0;
1322
+ u8 *fw_file_buf = NULL;
1323
+ struct fts_upgrade *upg = fwupgrade;
1324
+
1325
+ FTS_INFO("start upgrade with fw bin");
1326
+ if ((!upg) || (!upg->func) || !upg->ts_data) {
1327
+ FTS_ERROR("upgrade/func/ts_data is null");
1328
+ return -EINVAL;
1329
+ }
1330
+
1331
+ if (upg->ts_data->fw_loading) {
1332
+ FTS_INFO("fw is loading, not download again");
1333
+ return -EINVAL;
1334
+ }
1335
+
1336
+ upg->ts_data->fw_loading = 1;
1337
+ if (!upg->ts_data->irq_disabled) {
1338
+ fts_irq_disable();
1339
+ irq_need_recovery = true;
1340
+ }
1341
+ if (fts_esdcheck_is_running(upg->ts_data)) {
1342
+ fts_esdcheck_switch(upg->ts_data, DISABLE);
1343
+ esd_need_recovery = true;
1344
+ }
1345
+
1346
+ ret = fts_read_file(fw_name, &fw_file_buf);
1347
+ if ((ret < 0) || (ret < FTS_MIN_LEN)) {
1348
+ FTS_ERROR("read fw bin file(%s) fail, len:%d", fw_name, ret);
1349
+ goto err_bin;
1350
+ }
1351
+
1352
+ fw_file_len = ret;
1353
+ FTS_INFO("fw bin file len:%d", fw_file_len);
1354
+ if (force) {
1355
+ if (upg->func->force_upgrade) {
1356
+ ret = upg->func->force_upgrade(fw_file_buf, fw_file_len);
1357
+ } else {
1358
+ FTS_INFO("force_upgrade function is null, no upgrade");
1359
+ goto err_bin;
1360
+ }
1361
+ } else {
1362
+#if FTS_AUTO_LIC_UPGRADE_EN
1363
+ if (upg->func->lic_upgrade) {
1364
+ ret = upg->func->lic_upgrade(fw_file_buf, fw_file_len);
1365
+ } else {
1366
+ FTS_INFO("lic_upgrade function is null, no upgrade");
1367
+ }
1368
+#endif
1369
+ if (upg->func->upgrade) {
1370
+ ret = upg->func->upgrade(fw_file_buf, fw_file_len);
1371
+ } else {
1372
+ FTS_INFO("upgrade function is null, no upgrade");
1373
+ }
1374
+ }
1375
+
1376
+ if (ret < 0) {
1377
+ FTS_ERROR("upgrade fw bin failed");
1378
+ fts_fwupg_reset_in_boot();
1379
+ goto err_bin;
1380
+ }
1381
+
1382
+ FTS_INFO("upgrade fw bin success");
1383
+ if (esd_need_recovery) fts_esdcheck_switch(upg->ts_data, ENABLE);
1384
+ ret = 0;
1385
+
1386
+err_bin:
1387
+ if (irq_need_recovery) fts_irq_enable();
1388
+ upg->ts_data->fw_loading = 0;
1389
+
1390
+ if (fw_file_buf) {
1391
+ vfree(fw_file_buf);
1392
+ fw_file_buf = NULL;
1393
+ }
1394
+ return ret;
1395
+}
1396
+
1397
+int fts_enter_test_environment(bool test_state)
1398
+{
1399
+ return 0;
1400
+}
1401
+#if FTS_AUTO_LIC_UPGRADE_EN
1402
+static int fts_lic_get_vid_in_tp(u16 *vid)
1403
+{
1404
+ int ret = 0;
1405
+ u8 val[2] = { 0 };
1406
+
1407
+ if (NULL == vid) {
1408
+ FTS_ERROR("vid is NULL");
1409
+ return -EINVAL;
1410
+ }
1411
+
1412
+ ret = fts_read_reg(FTS_REG_VENDOR_ID, &val[0]);
1413
+ if (fts_data->ic_info.is_incell)
1414
+ ret = fts_read_reg(FTS_REG_PANEL_ID, &val[1]);
1415
+ if (ret < 0) {
1416
+ FTS_ERROR("read vid from tp fail");
1417
+ return ret;
1418
+ }
1419
+
1420
+ *vid = *(u16 *)val;
1421
+ return 0;
1422
+}
1423
+
1424
+static int fts_lic_get_vid_in_host(struct fts_upgrade *upg, u16 *vid)
1425
+{
1426
+ u8 val[2] = { 0 };
1427
+ u8 *licbuf = NULL;
1428
+ u32 conf_saddr = 0;
1429
+
1430
+ if (!upg || !upg->func || !upg->ts_data || !upg->lic || !vid) {
1431
+ FTS_ERROR("upgrade/func/ts_data/get_hlic_ver/lic/vid is null");
1432
+ return -EINVAL;
1433
+ }
1434
+
1435
+ if (upg->lic_length < FTS_MAX_LEN_SECTOR) {
1436
+ FTS_ERROR("lic length(%x) fail", upg->lic_length);
1437
+ return -EINVAL;
1438
+ }
1439
+
1440
+ licbuf = upg->lic;
1441
+ conf_saddr = upg->func->fwcfgoff;
1442
+ val[0] = licbuf[conf_saddr + FTS_CONIFG_VENDORID_OFF];
1443
+ if (upg->ts_data->ic_info.is_incell)
1444
+ val[1] = licbuf[conf_saddr + FTS_CONIFG_PANELID_OFF];
1445
+
1446
+ *vid = *(u16 *)val;
1447
+ return 0;
1448
+}
1449
+
1450
+static int fts_lic_get_ver_in_tp(u8 *ver)
1451
+{
1452
+ int ret = 0;
1453
+
1454
+ if (NULL == ver) {
1455
+ FTS_ERROR("ver is NULL");
1456
+ return -EINVAL;
1457
+ }
1458
+
1459
+ ret = fts_read_reg(FTS_REG_LIC_VER, ver);
1460
+ if (ret < 0) {
1461
+ FTS_ERROR("read lcd initcode ver from tp fail");
1462
+ return ret;
1463
+ }
1464
+
1465
+ return 0;
1466
+}
1467
+
1468
+static int fts_lic_get_ver_in_host(struct fts_upgrade *upg, u8 *ver)
1469
+{
1470
+ int ret = 0;
1471
+
1472
+ if (!upg || !upg->func || !upg->func->get_hlic_ver || !upg->lic) {
1473
+ FTS_ERROR("upgrade/func/get_hlic_ver/lic is null");
1474
+ return -EINVAL;
1475
+ }
1476
+
1477
+ ret = upg->func->get_hlic_ver(upg->lic);
1478
+ if (ret < 0) {
1479
+ FTS_ERROR("get host lcd initial code version fail");
1480
+ return ret;
1481
+ }
1482
+
1483
+ *ver = (u8)ret;
1484
+ return ret;
1485
+}
1486
+
1487
+static bool fts_lic_need_upgrade(struct fts_upgrade *upg)
1488
+{
1489
+ int ret = 0;
1490
+ u8 initcode_ver_in_tp = 0;
1491
+ u8 initcode_ver_in_host = 0;
1492
+ u16 vid_in_tp = 0;
1493
+ u16 vid_in_host = 0;
1494
+ bool fwvalid = false;
1495
+
1496
+ fwvalid = fts_fwupg_check_fw_valid();
1497
+ if ( !fwvalid) {
1498
+ FTS_INFO("fw is invalid, no upgrade lcd init code");
1499
+ return false;
1500
+ }
1501
+
1502
+ ret = fts_lic_get_vid_in_host(upg, &vid_in_host);
1503
+ if (ret < 0) {
1504
+ FTS_ERROR("vendor id in host invalid");
1505
+ return false;
1506
+ }
1507
+
1508
+ ret = fts_lic_get_vid_in_tp(&vid_in_tp);
1509
+ if (ret < 0) {
1510
+ FTS_ERROR("vendor id in tp invalid");
1511
+ return false;
1512
+ }
1513
+
1514
+ FTS_DEBUG("vid in tp:0x%04x, host:0x%04x", vid_in_tp, vid_in_host);
1515
+ if (vid_in_tp != vid_in_host) {
1516
+ FTS_INFO("vendor id in tp&host are different, no upgrade lic");
1517
+ return false;
1518
+ }
1519
+
1520
+ ret = fts_lic_get_ver_in_host(upg, &initcode_ver_in_host);
1521
+ if (ret < 0) {
1522
+ FTS_ERROR("init code in host invalid");
1523
+ return false;
1524
+ }
1525
+
1526
+ ret = fts_lic_get_ver_in_tp(&initcode_ver_in_tp);
1527
+ if (ret < 0) {
1528
+ FTS_ERROR("read reg0xE4 fail");
1529
+ return false;
1530
+ }
1531
+
1532
+ FTS_DEBUG("lcd initial code version in tp:%x, host:%x",
1533
+ initcode_ver_in_tp, initcode_ver_in_host);
1534
+ if (0xA5 == initcode_ver_in_tp) {
1535
+ FTS_INFO("lcd init code ver is 0xA5, don't upgade init code");
1536
+ return false;
1537
+ } else if (0xFF == initcode_ver_in_tp) {
1538
+ FTS_DEBUG("lcd init code in tp is invalid, need upgrade init code");
1539
+ return true;
1540
+ } else if (initcode_ver_in_tp < initcode_ver_in_host)
1541
+ return true;
1542
+ else
1543
+ return false;
1544
+}
1545
+
1546
+static int fts_lic_upgrade(struct fts_upgrade *upg)
1547
+{
1548
+ int ret = 0;
1549
+ bool hlic_upgrade = false;
1550
+ int upgrade_count = 0;
1551
+ u8 ver = 0;
1552
+
1553
+ FTS_INFO("lcd initial code auto upgrade function");
1554
+ if ((!upg) || (!upg->func) || (!upg->func->lic_upgrade)) {
1555
+ FTS_ERROR("lcd upgrade function is null");
1556
+ return -EINVAL;
1557
+ }
1558
+
1559
+ hlic_upgrade = fts_lic_need_upgrade(upg);
1560
+ FTS_INFO("lcd init code upgrade flag:%d", hlic_upgrade);
1561
+ if (hlic_upgrade) {
1562
+ FTS_INFO("lcd initial code need upgrade, upgrade begin...");
1563
+ do {
1564
+ FTS_INFO("lcd initial code upgrade times:%d", upgrade_count);
1565
+ upgrade_count++;
1566
+
1567
+ ret = upg->func->lic_upgrade(upg->lic, upg->lic_length);
1568
+ if (ret < 0) {
1569
+ fts_fwupg_reset_in_boot();
1570
+ } else {
1571
+ fts_lic_get_ver_in_tp(&ver);
1572
+ FTS_INFO("success upgrade to lcd initcode ver:%02x", ver);
1573
+ break;
1574
+ }
1575
+ } while (upgrade_count < 2);
1576
+ } else {
1577
+ FTS_INFO("lcd initial code don't need upgrade");
1578
+ }
1579
+
1580
+ return ret;
1581
+}
1582
+#endif /* FTS_AUTO_LIC_UPGRADE_EN */
1583
+
1584
+
1585
+static int fts_param_get_ver_in_tp(u8 *ver)
1586
+{
1587
+ int ret = 0;
1588
+
1589
+ if (NULL == ver) {
1590
+ FTS_ERROR("ver is NULL");
1591
+ return -EINVAL;
1592
+ }
1593
+
1594
+ ret = fts_read_reg(FTS_REG_IDE_PARA_VER_ID, ver);
1595
+ if (ret < 0) {
1596
+ FTS_ERROR("read fw param ver from tp fail");
1597
+ return ret;
1598
+ }
1599
+
1600
+ if ((0x00 == *ver) || (0xFF == *ver)) {
1601
+ FTS_INFO("param version in tp invalid");
1602
+ return -EIO;
1603
+ }
1604
+
1605
+ return 0;
1606
+}
1607
+
1608
+static int fts_param_get_ver_in_host(struct fts_upgrade *upg, u8 *ver)
1609
+{
1610
+ if ((!upg) || (!upg->func) || (!upg->fw) || (!ver)) {
1611
+ FTS_ERROR("upgrade/func/fw/ver is NULL");
1612
+ return -EINVAL;
1613
+ }
1614
+
1615
+ if (upg->fw_length < upg->func->paramcfgveroff) {
1616
+ FTS_ERROR("fw len(%x) < paramcfg ver offset(%x)",
1617
+ upg->fw_length, upg->func->paramcfgveroff);
1618
+ return -EINVAL;
1619
+ }
1620
+
1621
+ FTS_INFO("fw paramcfg version offset:%x", upg->func->paramcfgveroff);
1622
+ *ver = upg->fw[upg->func->paramcfgveroff];
1623
+
1624
+ if ((0x00 == *ver) || (0xFF == *ver)) {
1625
+ FTS_INFO("param version in host invalid");
1626
+ return -EIO;
1627
+ }
1628
+
1629
+ return 0;
1630
+}
1631
+
1632
+/*
1633
+ * return: < 0 : error
1634
+ * == 0: no ide
1635
+ * == 1: ide
1636
+ */
1637
+static int fts_param_ide_in_host(struct fts_upgrade *upg)
1638
+{
1639
+ u32 off = 0;
1640
+
1641
+ if ((!upg) || (!upg->func) || (!upg->fw)) {
1642
+ FTS_ERROR("upgrade/func/fw is NULL");
1643
+ return -EINVAL;
1644
+ }
1645
+
1646
+ if (upg->fw_length < upg->func->paramcfgoff + FTS_FW_IDE_SIG_LEN) {
1647
+ FTS_INFO("fw len(%x) < paramcfg offset(%x), no IDE",
1648
+ upg->fw_length, upg->func->paramcfgoff + FTS_FW_IDE_SIG_LEN);
1649
+ return 0;
1650
+ }
1651
+
1652
+ off = upg->func->paramcfgoff;
1653
+ if (0 == memcmp(&upg->fw[off], FTS_FW_IDE_SIG, FTS_FW_IDE_SIG_LEN)) {
1654
+ FTS_INFO("fw in host is IDE version");
1655
+ return 1;
1656
+ }
1657
+
1658
+ FTS_INFO("fw in host isn't IDE version");
1659
+ return 0;
1660
+}
1661
+
1662
+/*
1663
+ * return: < 0 : error
1664
+ * 0 : no ide
1665
+ * 1 : ide
1666
+ */
1667
+static int fts_param_ide_in_tp(u8 *val)
1668
+{
1669
+ int ret = 0;
1670
+
1671
+ ret = fts_read_reg(FTS_REG_IDE_PARA_STATUS, val);
1672
+ if (ret < 0) {
1673
+ FTS_ERROR("read IDE PARAM STATUS in tp fail");
1674
+ return ret;
1675
+ }
1676
+
1677
+ if ((*val != 0xFF) && ((*val & 0x80) == 0x80)) {
1678
+ FTS_INFO("fw in tp is IDE version");
1679
+ return 1;
1680
+ }
1681
+
1682
+ FTS_INFO("fw in tp isn't IDE version");
1683
+ return 0;
1684
+}
1685
+
1686
+/************************************************************************
1687
+ * fts_param_need_upgrade - check fw paramcfg need upgrade or not
1688
+ *
1689
+ * Return: < 0 : error if paramcfg need upgrade
1690
+ * 0 : no need upgrade
1691
+ * 1 : need upgrade app + param
1692
+ * 2 : need upgrade param
1693
+ ***********************************************************************/
1694
+static int fts_param_need_upgrade(struct fts_upgrade *upg)
1695
+{
1696
+ int ret = 0;
1697
+ u8 val = 0;
1698
+ int ide_in_host = 0;
1699
+ int ide_in_tp = 0;
1700
+ u8 ver_in_host = 0;
1701
+ u8 ver_in_tp = 0;
1702
+ bool fwvalid = false;
1703
+
1704
+ fwvalid = fts_fwupg_check_fw_valid();
1705
+ if ( !fwvalid) {
1706
+ FTS_INFO("fw is invalid, upgrade app+param");
1707
+ return 1;
1708
+ }
1709
+
1710
+ ide_in_host = fts_param_ide_in_host(upg);
1711
+ if (ide_in_host < 0) {
1712
+ FTS_INFO("fts_param_ide_in_host fail");
1713
+ return ide_in_host;
1714
+ }
1715
+
1716
+ ide_in_tp = fts_param_ide_in_tp(&val);
1717
+ if (ide_in_tp < 0) {
1718
+ FTS_INFO("fts_param_ide_in_tp fail");
1719
+ return ide_in_tp;
1720
+ }
1721
+
1722
+ if ((0 == ide_in_host) && (0 == ide_in_tp)) {
1723
+ FTS_INFO("fw in host&tp are both no ide");
1724
+ return 0;
1725
+ } else if (ide_in_host != ide_in_tp) {
1726
+ FTS_INFO("fw in host&tp not equal, need upgrade app+param");
1727
+ return 1;
1728
+ } else if ((1 == ide_in_host) && (1 == ide_in_tp)) {
1729
+ FTS_INFO("fw in host&tp are both ide");
1730
+ if ((val & 0x7F) != 0x00) {
1731
+ FTS_INFO("param invalid, need upgrade param");
1732
+ return 2;
1733
+ }
1734
+
1735
+ ret = fts_param_get_ver_in_host(upg, &ver_in_host);
1736
+ if (ret < 0) {
1737
+ FTS_ERROR("param version in host invalid");
1738
+ return ret;
1739
+ }
1740
+
1741
+ ret = fts_param_get_ver_in_tp(&ver_in_tp);
1742
+ if (ret < 0) {
1743
+ FTS_ERROR("get IDE param ver in tp fail");
1744
+ return ret;
1745
+ }
1746
+
1747
+ FTS_INFO("fw paramcfg version in tp:%x, host:%x",
1748
+ ver_in_tp, ver_in_host);
1749
+ if (ver_in_tp != ver_in_host) {
1750
+ return 2;
1751
+ }
1752
+ }
1753
+
1754
+ return 0;
1755
+}
1756
+
1757
+static int fts_fwupg_get_ver_in_tp(u8 *ver)
1758
+{
1759
+ int ret = 0;
1760
+
1761
+ if (NULL == ver) {
1762
+ FTS_ERROR("ver is NULL");
1763
+ return -EINVAL;
1764
+ }
1765
+
1766
+ ret = fts_read_reg(FTS_REG_FW_VER, ver);
1767
+ if (ret < 0) {
1768
+ FTS_ERROR("read fw ver from tp fail");
1769
+ return ret;
1770
+ }
1771
+
1772
+ return 0;
1773
+}
1774
+
1775
+static int fts_fwupg_get_ver_in_host(struct fts_upgrade *upg, u8 *ver)
1776
+{
1777
+ if ((!upg) || (!upg->func) || (!upg->fw) || (!ver)) {
1778
+ FTS_ERROR("upgrade/func/fw/ver is NULL");
1779
+ return -EINVAL;
1780
+ }
1781
+
1782
+ if (upg->fw_length < upg->func->fwveroff) {
1783
+ FTS_ERROR("fw len(0x%0x) < fw ver offset(0x%x)",
1784
+ upg->fw_length, upg->func->fwveroff);
1785
+ return -EINVAL;
1786
+ }
1787
+
1788
+ FTS_INFO("fw version offset:0x%x", upg->func->fwveroff);
1789
+ *ver = upg->fw[upg->func->fwveroff];
1790
+ return 0;
1791
+}
1792
+
1793
+static bool fts_fwupg_need_upgrade(struct fts_upgrade *upg)
1794
+{
1795
+ int ret = 0;
1796
+ bool fwvalid = false;
1797
+ u8 fw_ver_in_host = 0;
1798
+ u8 fw_ver_in_tp = 0;
1799
+
1800
+ fwvalid = fts_fwupg_check_fw_valid();
1801
+ if (fwvalid) {
1802
+ ret = fts_fwupg_get_ver_in_host(upg, &fw_ver_in_host);
1803
+ if (ret < 0) {
1804
+ FTS_ERROR("get fw ver in host fail");
1805
+ return false;
1806
+ }
1807
+
1808
+ ret = fts_fwupg_get_ver_in_tp(&fw_ver_in_tp);
1809
+ if (ret < 0) {
1810
+ FTS_ERROR("get fw ver in tp fail");
1811
+ return false;
1812
+ }
1813
+
1814
+ FTS_INFO("fw version in tp:%x, host:%x", fw_ver_in_tp, fw_ver_in_host);
1815
+ if (fw_ver_in_tp != fw_ver_in_host) {
1816
+ return true;
1817
+ }
1818
+ } else {
1819
+ FTS_INFO("fw invalid, need upgrade fw");
1820
+ return true;
1821
+ }
1822
+
1823
+ return false;
1824
+}
1825
+
1826
+/************************************************************************
1827
+ * Name: fts_fw_upgrade
1828
+ * Brief: fw upgrade main entry, run in following steps
1829
+ * 1. check fw version(A6), not equal, will upgrade app(+param)
1830
+ * 2. if fw version equal, will check ide, will upgrade app(+param)
1831
+ * in the follow situation
1832
+ * a. host&tp IDE's type are not equal, will upgrade app+param
1833
+ * b. host&tp are both IDE's type, and param's version are not
1834
+ * equal, will upgrade param
1835
+ * Input:
1836
+ * Output:
1837
+ * Return: return 0 if success, otherwise return error code
1838
+ ***********************************************************************/
1839
+int fts_fwupg_upgrade(struct fts_upgrade *upg)
1840
+{
1841
+ int ret = 0;
1842
+ bool upgrade_flag = false;
1843
+ int upgrade_count = 0;
1844
+ u8 ver = 0;
1845
+
1846
+ FTS_INFO("fw auto upgrade function");
1847
+ if ((NULL == upg) || (NULL == upg->func)) {
1848
+ FTS_ERROR("upg/upg->func is null");
1849
+ return -EINVAL;
1850
+ }
1851
+
1852
+ upgrade_flag = fts_fwupg_need_upgrade(upg);
1853
+ FTS_INFO("fw upgrade flag:%d", upgrade_flag);
1854
+ do {
1855
+ upgrade_count++;
1856
+ if (upgrade_flag) {
1857
+ FTS_INFO("upgrade fw app(times:%d)", upgrade_count);
1858
+ if (upg->func->upgrade) {
1859
+ ret = upg->func->upgrade(upg->fw, upg->fw_length);
1860
+ if (ret < 0) {
1861
+ fts_fwupg_reset_in_boot();
1862
+ } else {
1863
+ fts_fwupg_get_ver_in_tp(&ver);
1864
+ FTS_INFO("success upgrade to fw version %02x", ver);
1865
+ break;
1866
+ }
1867
+ } else {
1868
+ FTS_ERROR("upgrade func/upgrade is null, return immediately");
1869
+ ret = -ENODATA;
1870
+ break;
1871
+ }
1872
+ } else {
1873
+ if (upg->func->param_upgrade) {
1874
+ ret = fts_param_need_upgrade(upg);
1875
+ if (ret <= 0) {
1876
+ FTS_INFO("param don't need upgrade");
1877
+ break;
1878
+ } else if (1 == ret) {
1879
+ FTS_INFO("force upgrade fw app(times:%d)", upgrade_count);
1880
+ if (upg->func->upgrade) {
1881
+ ret = upg->func->upgrade(upg->fw, upg->fw_length);
1882
+ if (ret < 0) {
1883
+ fts_fwupg_reset_in_boot();
1884
+ } else {
1885
+ break;
1886
+ }
1887
+ }
1888
+ } else if (2 == ret) {
1889
+ FTS_INFO("upgrade param area(times:%d)", upgrade_count);
1890
+ ret = upg->func->param_upgrade(upg->fw, upg->fw_length);
1891
+ if (ret < 0) {
1892
+ fts_fwupg_reset_in_boot();
1893
+ } else {
1894
+ fts_param_get_ver_in_tp(&ver);
1895
+ FTS_INFO("success upgrade to fw param version %02x", ver);
1896
+ break;
1897
+ }
1898
+ } else
1899
+ break;
1900
+ } else {
1901
+ break;
1902
+ }
1903
+ }
1904
+ } while (upgrade_count < 2);
1905
+
1906
+ return ret;
1907
+}
1908
+
1909
+/************************************************************************
1910
+ * fts_fwupg_auto_upgrade - upgrade main entry
1911
+ ***********************************************************************/
1912
+static int fts_fwupg_auto_upgrade(struct fts_upgrade *upg)
1913
+{
1914
+ int ret = 0;
1915
+
1916
+ FTS_INFO("********************FTS enter upgrade********************");
1917
+ if (!upg || !upg->ts_data) {
1918
+ FTS_ERROR("upg/ts_data is null");
1919
+ return -EINVAL;
1920
+ }
1921
+
1922
+ ret = fts_fwupg_upgrade(upg);
1923
+ if (ret < 0)
1924
+ FTS_ERROR("**********tp fw(app/param) upgrade failed**********");
1925
+ else
1926
+ FTS_INFO("**********tp fw(app/param) no upgrade/upgrade success**********");
1927
+
1928
+#if FTS_AUTO_LIC_UPGRADE_EN
1929
+ ret = fts_lic_upgrade(upg);
1930
+ if (ret < 0)
1931
+ FTS_ERROR("**********lcd init code upgrade failed**********");
1932
+ else
1933
+ FTS_INFO("**********lcd init code no upgrade/upgrade success**********");
1934
+#endif
1935
+
1936
+ FTS_INFO("********************FTS exit upgrade********************");
1937
+ return ret;
1938
+}
1939
+
1940
+static int fts_fwupg_get_moduleid(struct fts_upgrade *upg, int *module_id)
1941
+{
1942
+ int ret = 0;
1943
+ bool fwvalid = false;
1944
+ u8 vendor_id = 0;
1945
+ u8 panel_id = 0;
1946
+ u8 cmd = FTS_CMD_READ_FWCFG;
1947
+ u32 fwcfg_addr = 0;
1948
+ u8 cfgbuf[FTS_HEADER_LEN] = { 0 };
1949
+
1950
+ FTS_INFO("read module id from tp");
1951
+ if ((!upg) || (!upg->func) || (!upg->ts_data) || (!module_id)) {
1952
+ FTS_ERROR("upgrade/func/ts_data/vid is null");
1953
+ return -EINVAL;
1954
+ }
1955
+
1956
+ fwvalid = fts_fwupg_check_fw_valid();
1957
+ if (fwvalid) {
1958
+ ret = fts_read_reg(FTS_REG_VENDOR_ID, &vendor_id);
1959
+ if (upg->ts_data->ic_info.is_incell)
1960
+ ret = fts_read_reg(FTS_REG_PANEL_ID, &panel_id);
1961
+ } else {
1962
+ if (upg->func->upgspec_version >= UPGRADE_SPEC_V_1_1) {
1963
+ ret = fts_read(&cmd, 1, cfgbuf, FTS_HEADER_LEN);
1964
+ } else {
1965
+ fwcfg_addr = upg->func->fwcfgoff;
1966
+ ret = fts_flash_read(fwcfg_addr, cfgbuf, FTS_HEADER_LEN);
1967
+ }
1968
+
1969
+ if ((cfgbuf[FTS_CONIFG_VENDORID_OFF] +
1970
+ cfgbuf[FTS_CONIFG_VENDORID_OFF + 1]) == 0xFF)
1971
+ vendor_id = cfgbuf[FTS_CONIFG_VENDORID_OFF];
1972
+ if (upg->ts_data->ic_info.is_incell) {
1973
+ if ((cfgbuf[FTS_CONIFG_PANELID_OFF] +
1974
+ cfgbuf[FTS_CONIFG_PANELID_OFF + 1]) == 0xFF)
1975
+ panel_id = cfgbuf[FTS_CONIFG_PANELID_OFF];
1976
+ }
1977
+ }
1978
+
1979
+ if (ret < 0) {
1980
+ FTS_ERROR("fail to get module id from tp");
1981
+ return ret;
1982
+ }
1983
+
1984
+ *module_id = (int)((panel_id << 8) + vendor_id);
1985
+ return 0;
1986
+}
1987
+
1988
+
1989
+int fts_enter_normal_fw(void)
1990
+{
1991
+
1992
+ fts_wait_tp_to_valid();
1993
+ return 0;
1994
+}
1995
+
1996
+static int fts_fwupg_get_module_info(struct fts_upgrade *upg)
1997
+{
1998
+ int ret = 0;
1999
+ int i = 0;
2000
+ struct upgrade_module *info = &module_list[0];
2001
+
2002
+ if (!upg || !upg->ts_data) {
2003
+ FTS_ERROR("upg/ts_data is null");
2004
+ return -EINVAL;
2005
+ }
2006
+
2007
+ if (FTS_GET_MODULE_NUM > 1) {
2008
+ /* support multi modules, must read correct module id */
2009
+ ret = fts_fwupg_get_moduleid(upg, &upg->module_id);
2010
+ if (ret < 0) {
2011
+ FTS_ERROR("get module id failed");
2012
+ return ret;
2013
+ }
2014
+ FTS_INFO("module id:%04x", upg->module_id);
2015
+ for (i = 0; i < FTS_GET_MODULE_NUM; i++) {
2016
+ info = &module_list[i];
2017
+ if (upg->module_id == info->id) {
2018
+ FTS_INFO("module id match, get module info pass");
2019
+ break;
2020
+ }
2021
+ }
2022
+ if (i >= FTS_GET_MODULE_NUM) {
2023
+ FTS_ERROR("no module id match, don't get file");
2024
+ return -ENODATA;
2025
+ }
2026
+ }
2027
+
2028
+ upg->module_info = info;
2029
+ return 0;
2030
+}
2031
+
2032
+static int fts_get_fw_file_via_request_firmware(struct fts_upgrade *upg)
2033
+{
2034
+ int ret = 0;
2035
+ const struct firmware *fw = NULL;
2036
+ u8 *tmpbuf = NULL;
2037
+ char fwname[FILE_NAME_LENGTH] = { 0 };
2038
+
2039
+ if (!upg || !upg->ts_data || !upg->ts_data->dev) {
2040
+ FTS_ERROR("upg/ts_data/dev is null");
2041
+ return -EINVAL;
2042
+ }
2043
+
2044
+ snprintf(fwname, FILE_NAME_LENGTH, "%s%s.bin", \
2045
+ FTS_FW_NAME_PREX_WITH_REQUEST, \
2046
+ upg->module_info->vendor_name);
2047
+
2048
+ ret = request_firmware(&fw, fwname, upg->ts_data->dev);
2049
+ if (0 == ret) {
2050
+ FTS_INFO("firmware(%s) request successfully", fwname);
2051
+ tmpbuf = vmalloc(fw->size);
2052
+ if (NULL == tmpbuf) {
2053
+ FTS_ERROR("fw buffer vmalloc fail");
2054
+ ret = -ENOMEM;
2055
+ } else {
2056
+ memcpy(tmpbuf, fw->data, fw->size);
2057
+ upg->fw = tmpbuf;
2058
+ upg->fw_length = fw->size;
2059
+ upg->fw_from_request = 1;
2060
+ }
2061
+ } else {
2062
+ FTS_INFO("firmware(%s) request fail,ret=%d", fwname, ret);
2063
+ }
2064
+
2065
+ if (fw != NULL) {
2066
+ release_firmware(fw);
2067
+ fw = NULL;
2068
+ }
2069
+
2070
+ return ret;
2071
+}
2072
+
2073
+static int fts_get_fw_file_via_i(struct fts_upgrade *upg)
2074
+{
2075
+ upg->fw = upg->module_info->fw_file;
2076
+ upg->fw_length = upg->module_info->fw_len;
2077
+ upg->fw_from_request = 0;
2078
+
2079
+ return 0;
2080
+}
2081
+
2082
+/*****************************************************************************
2083
+ * Name: fts_fwupg_get_fw_file
2084
+ * Brief: get fw image/file,
2085
+ * If support muitl modules, please set FTS_GET_MODULE_NUM, and FTS_-
2086
+ * MODULE_ID/FTS_MODULE_NAME;
2087
+ * If get fw via .i file, please set FTS_FW_REQUEST_SUPPORT=0, and F-
2088
+ * TS_MODULE_ID; will use module id to distingwish different modules;
2089
+ * If get fw via reques_firmware(), please set FTS_FW_REQUEST_SUPPORT
2090
+ * =1, and FTS_MODULE_NAME; fw file name will be composed of "focalt-
2091
+ * ech_ts_fw_" & FTS_MODULE_NAME;
2092
+ *
2093
+ * If have flash, module_id=vendor_id, If non-flash,module_id need
2094
+ * transfer from LCD driver(gpio or lcm_id or ...);
2095
+ * Input:
2096
+ * Output:
2097
+ * Return: return 0 if success, otherwise return error code
2098
+ *****************************************************************************/
2099
+static int fts_fwupg_get_fw_file(struct fts_upgrade *upg)
2100
+{
2101
+ int ret = 0;
2102
+ bool get_fw_i_flag = false;
2103
+
2104
+ FTS_DEBUG("get upgrade fw file");
2105
+ if (!upg || !upg->ts_data) {
2106
+ FTS_ERROR("upg/ts_data is null");
2107
+ return -EINVAL;
2108
+ }
2109
+
2110
+ ret = fts_fwupg_get_module_info(upg);
2111
+ if ((ret < 0) || (!upg->module_info)) {
2112
+ FTS_ERROR("get module info fail");
2113
+ return ret;
2114
+ }
2115
+
2116
+ if (FTS_FW_REQUEST_SUPPORT) {
2117
+ ret = fts_get_fw_file_via_request_firmware(upg);
2118
+ if (ret != 0) {
2119
+ get_fw_i_flag = true;
2120
+ }
2121
+ } else {
2122
+ get_fw_i_flag = true;
2123
+ }
2124
+
2125
+ if (get_fw_i_flag) {
2126
+ ret = fts_get_fw_file_via_i(upg);
2127
+ }
2128
+
2129
+ upg->lic = upg->fw;
2130
+ upg->lic_length = upg->fw_length;
2131
+
2132
+ FTS_INFO("upgrade fw file len:%d", upg->fw_length);
2133
+ if (upg->fw_length < FTS_MIN_LEN) {
2134
+ FTS_ERROR("fw file len(%d) fail", upg->fw_length);
2135
+ return -ENODATA;
2136
+ }
2137
+
2138
+ return ret;
2139
+}
2140
+
2141
+static void fts_fwupg_init_ic_detail(struct fts_upgrade *upg)
2142
+{
2143
+ if (upg && upg->func && upg->func->init) {
2144
+ upg->func->init(upg->fw, upg->fw_length);
2145
+ }
2146
+}
2147
+
2148
+/*****************************************************************************
2149
+ * Name: fts_fwupg_work
2150
+ * Brief: 1. get fw image/file
2151
+ * 2. ic init if have
2152
+ * 3. call upgrade main function(fts_fwupg_auto_upgrade)
2153
+ * Input:
2154
+ * Output:
2155
+ * Return:
2156
+ *****************************************************************************/
2157
+static void fts_fwupg_work(struct work_struct *work)
2158
+{
2159
+ int ret = 0;
2160
+ int irq_need_recovery = false;
2161
+ struct fts_upgrade *upg = fwupgrade;
2162
+
2163
+#if !FTS_AUTO_UPGRADE_EN
2164
+ FTS_INFO("FTS_AUTO_UPGRADE_EN is disabled, not upgrade when power on");
2165
+ return ;
2166
+#endif
2167
+
2168
+ FTS_INFO("fw upgrade work function");
2169
+ if (!upg || !upg->ts_data) {
2170
+ FTS_ERROR("upg/ts_data is null");
2171
+ return ;
2172
+ }
2173
+
2174
+ upg->ts_data->fw_loading = 1;
2175
+ if (!upg->ts_data->irq_disabled) {
2176
+ fts_irq_disable();
2177
+ irq_need_recovery = true;
2178
+ }
2179
+ if (fts_esdcheck_is_running(upg->ts_data)) {
2180
+ fts_esdcheck_switch(upg->ts_data, DISABLE);
2181
+ }
2182
+
2183
+ /* get fw */
2184
+ ret = fts_fwupg_get_fw_file(upg);
2185
+ if (ret < 0) {
2186
+ FTS_ERROR("get file fail, can't upgrade");
2187
+ } else {
2188
+ /* ic init if have */
2189
+ fts_fwupg_init_ic_detail(upg);
2190
+ /* run auto upgrade */
2191
+ ret = fts_fwupg_auto_upgrade(upg);
2192
+ }
2193
+
2194
+ if (ret >= 0)
2195
+ fts_esdcheck_switch(upg->ts_data, ENABLE);
2196
+ if (irq_need_recovery)
2197
+ fts_irq_enable();
2198
+ upg->ts_data->fw_loading = 0;
2199
+}
2200
+
2201
+int fts_fwupg_init(struct fts_ts_data *ts_data)
2202
+{
2203
+ int i = 0;
2204
+ int j = 0;
2205
+ u16 ic_stype = 0;
2206
+ struct upgrade_func *func = upgrade_func_list[0];
2207
+ int func_count = sizeof(upgrade_func_list) / sizeof(upgrade_func_list[0]);
2208
+
2209
+ FTS_INFO("fw upgrade init function");
2210
+
2211
+ if (!ts_data || !ts_data->ts_workqueue) {
2212
+ FTS_ERROR("ts_data/workqueue is NULL, can't run upgrade function");
2213
+ return -EINVAL;
2214
+ }
2215
+
2216
+ if (0 == func_count) {
2217
+ FTS_ERROR("no upgrade function in tp driver");
2218
+ return -ENODATA;
2219
+ }
2220
+
2221
+ fwupgrade = (struct fts_upgrade *)kzalloc(sizeof(*fwupgrade), GFP_KERNEL);
2222
+ if (NULL == fwupgrade) {
2223
+ FTS_ERROR("malloc memory for upgrade fail");
2224
+ return -ENOMEM;
2225
+ }
2226
+
2227
+ ic_stype = ts_data->ic_info.ids.type;
2228
+ if (1 == func_count) {
2229
+ fwupgrade->func = func;
2230
+ } else {
2231
+ for (i = 0; i < func_count; i++) {
2232
+ func = upgrade_func_list[i];
2233
+ for (j = 0; j < FTS_MAX_COMPATIBLE_TYPE; j++) {
2234
+ if (0 == func->ctype[j])
2235
+ break;
2236
+ else if (func->ctype[j] == ic_stype) {
2237
+ FTS_INFO("match upgrade function,type:%x", (int)func->ctype[j]);
2238
+ fwupgrade->func = func;
2239
+ }
2240
+ }
2241
+ }
2242
+ }
2243
+
2244
+ if (NULL == fwupgrade->func) {
2245
+ FTS_ERROR("no upgrade function match, can't upgrade");
2246
+ kfree(fwupgrade);
2247
+ fwupgrade = NULL;
2248
+ return -ENODATA;
2249
+ }
2250
+
2251
+ fwupgrade->ts_data = ts_data;
2252
+ INIT_WORK(&fwupgrade->fwupg_work, fts_fwupg_work);
2253
+ queue_work(ts_data->ts_workqueue, &fwupgrade->fwupg_work);
2254
+
2255
+ return 0;
2256
+}
2257
+
2258
+int fts_fwupg_exit(struct fts_ts_data *ts_data)
2259
+{
2260
+ FTS_FUNC_ENTER();
2261
+ if (fwupgrade) {
2262
+ cancel_work_sync(&fwupgrade->fwupg_work);
2263
+ if (fwupgrade->fw_from_request) {
2264
+ vfree(fwupgrade->fw);
2265
+ fwupgrade->fw = NULL;
2266
+ }
2267
+
2268
+ kfree(fwupgrade);
2269
+ fwupgrade = NULL;
2270
+ }
2271
+ FTS_FUNC_EXIT();
2272
+ return 0;
2273
+}
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_flash.h
....@@ -0,0 +1,235 @@
1
+/************************************************************************
2
+* Copyright (c) 2012-2020, Focaltech Systems (R) All Rights Reserved.
3
+*
4
+* File Name: focaltech_flash.h
5
+*
6
+* Author: Focaltech Driver Team
7
+*
8
+* Created: 2016-08-07
9
+*
10
+* Abstract:
11
+*
12
+************************************************************************/
13
+#ifndef __LINUX_FOCALTECH_FLASH_H__
14
+#define __LINUX_FOCALTECH_FLASH_H__
15
+
16
+/*****************************************************************************
17
+* 1.Included header files
18
+*****************************************************************************/
19
+#include "focaltech_core.h"
20
+
21
+/*****************************************************************************
22
+* Private constant and macro definitions using #define
23
+*****************************************************************************/
24
+#define FTS_CMD_RESET 0x07
25
+#define FTS_ROMBOOT_CMD_SET_PRAM_ADDR 0xAD
26
+#define FTS_ROMBOOT_CMD_SET_PRAM_ADDR_LEN 4
27
+#define FTS_ROMBOOT_CMD_WRITE 0xAE
28
+#define FTS_ROMBOOT_CMD_START_APP 0x08
29
+#define FTS_DELAY_PRAMBOOT_START 100
30
+#define FTS_ROMBOOT_CMD_ECC 0xCC
31
+#define FTS_PRAM_SADDR 0x000000
32
+#define FTS_DRAM_SADDR 0xD00000
33
+
34
+#define FTS_CMD_READ_FWCFG 0xA8
35
+
36
+#define FTS_CMD_READ 0x03
37
+#define FTS_CMD_READ_DELAY 1
38
+#define FTS_CMD_READ_LEN 4
39
+#define FTS_CMD_READ_LEN_SPI 6
40
+#define FTS_CMD_FLASH_TYPE 0x05
41
+#define FTS_CMD_FLASH_MODE 0x09
42
+#define FLASH_MODE_WRITE_FLASH_VALUE 0x0A
43
+#define FLASH_MODE_UPGRADE_VALUE 0x0B
44
+#define FLASH_MODE_LIC_VALUE 0x0C
45
+#define FLASH_MODE_PARAM_VALUE 0x0D
46
+#define FTS_CMD_ERASE_APP 0x61
47
+#define FTS_REASE_APP_DELAY 1350
48
+#define FTS_ERASE_SECTOR_DELAY 60
49
+#define FTS_RETRIES_REASE 50
50
+#define FTS_RETRIES_DELAY_REASE 400
51
+#define FTS_CMD_FLASH_STATUS 0x6A
52
+#define FTS_CMD_FLASH_STATUS_LEN 2
53
+#define FTS_CMD_FLASH_STATUS_NOP 0x0000
54
+#define FTS_CMD_FLASH_STATUS_ECC_OK 0xF055
55
+#define FTS_CMD_FLASH_STATUS_ERASE_OK 0xF0AA
56
+#define FTS_CMD_FLASH_STATUS_WRITE_OK 0x1000
57
+#define FTS_CMD_ECC_INIT 0x64
58
+#define FTS_CMD_ECC_CAL 0x65
59
+#define FTS_CMD_ECC_CAL_LEN 7
60
+#define FTS_RETRIES_ECC_CAL 10
61
+#define FTS_RETRIES_DELAY_ECC_CAL 50
62
+#define FTS_CMD_ECC_READ 0x66
63
+#define FTS_CMD_DATA_LEN 0xB0
64
+#define FTS_CMD_APP_DATA_LEN_INCELL 0x7A
65
+#define FTS_CMD_DATA_LEN_LEN 4
66
+#define FTS_CMD_SET_WFLASH_ADDR 0xAB
67
+#define FTS_CMD_SET_RFLASH_ADDR 0xAC
68
+#define FTS_LEN_SET_ADDR 4
69
+#define FTS_CMD_WRITE 0xBF
70
+#define FTS_RETRIES_WRITE 100
71
+#define FTS_RETRIES_DELAY_WRITE 1
72
+#define FTS_CMD_WRITE_LEN 6
73
+#define FTS_DELAY_READ_ID 20
74
+#define FTS_DELAY_UPGRADE_RESET 80
75
+#define PRAMBOOT_MIN_SIZE 0x120
76
+#define PRAMBOOT_MAX_SIZE (64*1024)
77
+#define FTS_FLASH_PACKET_LENGTH 32 /* max=128 */
78
+#define FTS_MAX_LEN_ECC_CALC 0xFFFE /* must be even */
79
+#define FTS_MIN_LEN 0x120
80
+#define FTS_MAX_LEN_FILE (256 * 1024)
81
+#define FTS_MAX_LEN_APP (64 * 1024)
82
+#define FTS_MAX_LEN_SECTOR (4 * 1024)
83
+#define FTS_CONIFG_VENDORID_OFF 0x04
84
+#define FTS_CONIFG_PANELID_OFF 0x1E
85
+#define FTS_CONIFG_PROJECTID_OFF 0x20
86
+#define FTS_APPINFO_OFF 0x100
87
+#define FTS_APPINFO_APPLEN_OFF 0x00
88
+#define FTS_APPINFO_APPLEN2_OFF 0x12
89
+#define FTS_REG_UPGRADE 0xFC
90
+#define FTS_REG_UPGRADE2 0xBC
91
+#define FTS_UPGRADE_AA 0xAA
92
+#define FTS_UPGRADE_55 0x55
93
+#define FTS_DELAY_UPGRADE_AA 10
94
+#define FTS_UPGRADE_LOOP 30
95
+#define FTS_UPGRADE_RESET_LOOP 20
96
+#define FTS_HEADER_LEN 32
97
+#define FTS_FW_BIN_FILEPATH "/sdcard/"
98
+#define FTS_FW_IDE_SIG "IDE_"
99
+#define FTS_FW_IDE_SIG_LEN 4
100
+#define MAX_MODULE_VENDOR_NAME_LEN 16
101
+
102
+#define FTS_ROMBOOT_CMD_ECC_NEW_LEN 7
103
+#define FTS_ECC_FINISH_TIMEOUT 100
104
+#define FTS_ROMBOOT_CMD_ECC_FINISH 0xCE
105
+#define FTS_ROMBOOT_CMD_ECC_FINISH_OK_A5 0xA5
106
+#define FTS_ROMBOOT_CMD_ECC_FINISH_OK_00 0x00
107
+#define FTS_ROMBOOT_CMD_ECC_READ 0xCD
108
+#define AL2_FCS_COEF ((1 << 15) + (1 << 10) + (1 << 3))
109
+
110
+#define FTS_APP_INFO_OFFSET 0x100
111
+
112
+enum FW_STATUS {
113
+ FTS_RUN_IN_ERROR,
114
+ FTS_RUN_IN_APP,
115
+ FTS_RUN_IN_ROM,
116
+ FTS_RUN_IN_PRAM,
117
+ FTS_RUN_IN_BOOTLOADER,
118
+};
119
+
120
+enum FW_FLASH_MODE {
121
+ FLASH_MODE_APP,
122
+ FLASH_MODE_LIC,
123
+ FLASH_MODE_PARAM,
124
+ FLASH_MODE_ALL,
125
+};
126
+
127
+enum ECC_CHECK_MODE {
128
+ ECC_CHECK_MODE_XOR,
129
+ ECC_CHECK_MODE_CRC16,
130
+};
131
+
132
+enum UPGRADE_SPEC {
133
+ UPGRADE_SPEC_V_1_0 = 0x0100,
134
+ UPGRADE_SPEC_V_1_1 = 0x0101,
135
+ UPGRADE_SPEC_V_1_2 = 0x0102,
136
+};
137
+
138
+
139
+enum FW_TYPE {
140
+ FW_AUTO,
141
+ FW_GESTURE,
142
+ FW_NORMAL,
143
+};
144
+
145
+/*****************************************************************************
146
+* Private enumerations, structures and unions using typedef
147
+*****************************************************************************/
148
+/* IC info */
149
+struct upgrade_func {
150
+ u16 ctype[FTS_MAX_COMPATIBLE_TYPE];
151
+ u32 fwveroff;
152
+ u32 fwcfgoff;
153
+ u32 appoff;
154
+ u32 licoff;
155
+ u32 paramcfgoff;
156
+ u32 paramcfgveroff;
157
+ u32 paramcfg2off;
158
+ int pram_ecc_check_mode;
159
+ int fw_ecc_check_mode;
160
+ int upgspec_version;
161
+ bool new_return_value_from_ic;
162
+ bool appoff_handle_in_ic;
163
+ bool is_reset_register_BC;
164
+ bool read_boot_id_need_reset;
165
+ bool hid_supported;
166
+ bool pramboot_supported;
167
+ u8 *pramboot;
168
+ u32 pb_length;
169
+ int (*init)(u8 *, u32);
170
+ int (*write_pramboot_private)(void);
171
+ int (*upgrade)(u8 *, u32);
172
+ int (*get_hlic_ver)(u8 *);
173
+ int (*lic_upgrade)(u8 *, u32);
174
+ int (*param_upgrade)(u8 *, u32);
175
+ int (*force_upgrade)(u8 *, u32);
176
+};
177
+
178
+struct upgrade_setting_nf {
179
+ u8 rom_idh;
180
+ u8 rom_idl;
181
+ u16 reserved;
182
+ u32 app2_offset;
183
+ u32 ecclen_max;
184
+ u8 eccok_val;
185
+ u8 upgsts_boot;
186
+ u8 delay_init;
187
+ u8 spi_pe;
188
+ u8 length_coefficient;
189
+ u8 fd_check;
190
+ u8 drwr_support;
191
+ u8 ecc_delay;
192
+};
193
+
194
+struct upgrade_module {
195
+ int id;
196
+ char vendor_name[MAX_MODULE_VENDOR_NAME_LEN];
197
+ u8 *fw_file;
198
+ u32 fw_len;
199
+};
200
+
201
+struct fts_upgrade {
202
+ struct fts_ts_data *ts_data;
203
+ struct upgrade_module *module_info;
204
+ struct upgrade_func *func;
205
+ struct upgrade_setting_nf *setting_nf;
206
+ struct work_struct fwupg_work;
207
+ struct work_struct fwload_work;
208
+ struct work_struct fwrecover_work;
209
+ int module_id;
210
+ bool fw_from_request;
211
+ u8 *fw;
212
+ u32 fw_length;
213
+ u8 *lic;
214
+ u32 lic_length;
215
+};
216
+
217
+/*****************************************************************************
218
+* Global variable or extern global variabls/functions
219
+*****************************************************************************/
220
+extern struct upgrade_func upgrade_func_ft8756;
221
+
222
+
223
+
224
+/*****************************************************************************
225
+* Static function prototypes
226
+*****************************************************************************/
227
+int fts_fwupg_reset_in_boot(void);
228
+int fts_fwupg_enter_into_boot(void);
229
+int fts_fwupg_hwrst_to_boot(void);
230
+int fts_fwupg_erase(u32 delay);
231
+int fts_fwupg_ecc_cal(u32 saddr, u32 len);
232
+int fts_flash_write_buf(u32 saddr, u8 *buf, u32 len, u32 delay);
233
+int fts_flash_read_buf(u32 saddr, u8 *buf, u32 len);
234
+int fts_fwupg_upgrade(struct fts_upgrade *upg);
235
+#endif
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_flash/focaltech_upgrade_ft8756m.c
....@@ -0,0 +1,446 @@
1
+/*
2
+ *
3
+ * FocalTech fts TouchScreen driver.
4
+ *
5
+ * Copyright (c) 2012-2020, Focaltech Ltd. All rights reserved.
6
+ *
7
+ * This software is licensed under the terms of the GNU General Public
8
+ * License version 2, as published by the Free Software Foundation, and
9
+ * may be copied, distributed, and modified under those terms.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ */
17
+
18
+/*****************************************************************************
19
+*
20
+* File Name: focaltech_upgrade_ft8756.c
21
+*
22
+* Author: Focaltech Driver Team
23
+*
24
+* Created: 2018-09-01
25
+*
26
+* Abstract:
27
+*
28
+* Reference:
29
+*
30
+*****************************************************************************/
31
+
32
+/*****************************************************************************
33
+* 1.Included header files
34
+*****************************************************************************/
35
+#include "../focaltech_flash.h"
36
+
37
+/*****************************************************************************
38
+* Global variable or extern global variabls/functions
39
+*****************************************************************************/
40
+u8 pb_file_ft8756[] = {
41
+#include "../include/pramboot/FT8756_Pramboot_V1.3_20200116.i"
42
+};
43
+
44
+/*****************************************************************************
45
+* Private constant and macro definitions using #define
46
+*****************************************************************************/
47
+
48
+/*****************************************************************************
49
+* Static function prototypes
50
+*****************************************************************************/
51
+#define LIC_FS_H_OFF 0
52
+#define LIC_FS_L_OFF 1
53
+#define LIC_CHECKSUM_H_OFF 2
54
+#define LIC_CHECKSUM_L_OFF 3
55
+#define LIC_LCD_LEN_H_OFF 4
56
+#define LIC_LCD_LEN_L_OFF 5
57
+#define LIC_ECC_H_OFF 6
58
+#define LIC_ECC_L_OFF 7
59
+#define LIC_ECC_START_OFF 12
60
+
61
+/*****************************************************************************
62
+* Global variable or extern global variabls/functions
63
+*****************************************************************************/
64
+static u16 lcd_crc16(u8 *buf, u16 len)
65
+{
66
+ int i = 0;
67
+ u16 crc_in = 0xFFFF;
68
+ u16 c_poly = 0x8005;
69
+ u8 ch = 0;
70
+
71
+ while (len--) {
72
+ ch = *(buf++);
73
+ crc_in ^= (ch << 8);
74
+ for (i = 0; i < 8; i++) {
75
+ if (crc_in & 0x8000)
76
+ crc_in = (crc_in << 1) ^ c_poly;
77
+ else
78
+ crc_in = crc_in << 1;
79
+ }
80
+ }
81
+
82
+ return crc_in;
83
+}
84
+
85
+static int cal_lcdinitcode_ecc(u8 *buf, u16 *ecc_val)
86
+{
87
+ u8 bank_len = 0;
88
+ u16 bank_pos = 0;
89
+ u16 lcd_len = 0;
90
+ u16 pos = 0;
91
+ u16 i = 0;
92
+ u16 idx = 0;
93
+ u16 addr_h = 0;
94
+ u16 addr_l = 0;
95
+ u8 tmp = 0;
96
+ u8 *ecc_buf = NULL;
97
+
98
+ if ((NULL == buf) || (NULL == ecc_val)) {
99
+ FTS_ERROR("buf/ecc_val is NULL");
100
+ return -EINVAL;
101
+ }
102
+
103
+ lcd_len = ((u16)buf[LIC_LCD_LEN_H_OFF] << 8) + buf[LIC_LCD_LEN_L_OFF];
104
+ if ((lcd_len >= FTS_MAX_LEN_SECTOR) || (lcd_len <= 0)) {
105
+ FTS_ERROR("host lcd len(0x%x) invalid", lcd_len);
106
+ return -EINVAL;
107
+ }
108
+
109
+ ecc_buf = kzalloc(lcd_len, GFP_KERNEL);
110
+ if (NULL == ecc_buf) {
111
+ FTS_ERROR("initial code ecc buf malloc fail");
112
+ return -EINVAL;
113
+ }
114
+ memset(ecc_buf, 0xFF, lcd_len);
115
+
116
+ for (i = 0; i < lcd_len - 4; i++) {
117
+ tmp = buf[i + LIC_ECC_START_OFF]; /* cal from bank0(offset 12) */
118
+
119
+ if (idx == 0) {
120
+ addr_h = tmp;
121
+ ecc_buf[pos++] = tmp;
122
+ idx = 1;
123
+ } else if (idx == 1) {
124
+ addr_l = tmp;
125
+ idx = 2;
126
+ } else if (idx == 2) {
127
+ bank_len = tmp;
128
+ bank_pos = 0;
129
+ idx = 3;
130
+ } else if (idx == 3) {
131
+ ecc_buf[pos++] = tmp + addr_l + bank_pos;
132
+ if (bank_pos < bank_len - 1) {
133
+ bank_pos++;
134
+ } else {
135
+ idx = 0;
136
+ addr_h = 0;
137
+ addr_l = 0;
138
+ }
139
+ }
140
+ }
141
+ /* abnormal terminal */
142
+ if ((idx == 1) || (idx == 2)) {
143
+ pos--;
144
+ }
145
+
146
+ *ecc_val = lcd_crc16(ecc_buf, pos);
147
+ if (NULL == ecc_buf) {
148
+ kfree(ecc_buf);
149
+ ecc_buf = NULL;
150
+ }
151
+ return 0;
152
+}
153
+
154
+/* calculate lcd init code checksum */
155
+static u16 cal_lcdinitcode_checksum(u8 *ptr , int length)
156
+{
157
+ /* CRC16 */
158
+ u16 cfcs = 0;
159
+ int i = 0;
160
+ int j = 0;
161
+
162
+ if (length % 2) {
163
+ return 0xFFFF;
164
+ }
165
+
166
+ for (i = 0; i < length; i += 2) {
167
+ cfcs ^= (((u16)ptr[i] << 8) + ptr[i + 1]);
168
+ for (j = 0; j < 16; j++) {
169
+ if (cfcs & 1) {
170
+ cfcs = (u16)((cfcs >> 1) ^ ((1 << 15) + (1 << 10) + (1 << 3)));
171
+ } else {
172
+ cfcs >>= 1;
173
+ }
174
+ }
175
+ }
176
+ return cfcs;
177
+}
178
+
179
+/*
180
+ * check_initial_code_valid - check initial code valid or not
181
+ */
182
+static int check_initial_code_valid(u8 *buf)
183
+{
184
+ int ret = 0;
185
+ u16 initcode_ecc = 0;
186
+ u16 buf_ecc = 0;
187
+ u16 initcode_checksum = 0;
188
+ u16 buf_checksum = 0;
189
+ u16 hlic_len = 0;
190
+
191
+ hlic_len = (u16)(((u16)buf[LIC_FS_H_OFF]) << 8) + buf[LIC_FS_L_OFF];
192
+ FTS_INFO("host lcd init code len:0x%x", hlic_len);
193
+ if ((hlic_len >= FTS_MAX_LEN_SECTOR) || (hlic_len <= 0)) {
194
+ FTS_ERROR("host lcd init code len(0x%x) invalid", hlic_len);
195
+ return -EINVAL;
196
+ }
197
+ initcode_checksum = cal_lcdinitcode_checksum(buf + 4, hlic_len - 4);
198
+ buf_checksum =
199
+ ((u16)((u16)buf[LIC_CHECKSUM_H_OFF] << 8) + buf[LIC_CHECKSUM_L_OFF]);
200
+ FTS_INFO("lcd init code calc checksum:0x%04x,0x%04x",
201
+ initcode_checksum, buf_checksum);
202
+ if (initcode_checksum != buf_checksum) {
203
+ FTS_ERROR("Initial Code checksum fail");
204
+ return -EINVAL;
205
+ }
206
+
207
+ ret = cal_lcdinitcode_ecc(buf, &initcode_ecc);
208
+ if (ret < 0) {
209
+ FTS_ERROR("lcd init code ecc calculate fail");
210
+ return ret;
211
+ }
212
+ buf_ecc = ((u16)((u16)buf[LIC_ECC_H_OFF] << 8) + buf[LIC_ECC_L_OFF]);
213
+ FTS_INFO("lcd init code cal ecc:%04x, %04x", initcode_ecc, buf_ecc);
214
+ if (initcode_ecc != buf_ecc) {
215
+ FTS_ERROR("Initial Code ecc check fail");
216
+ return -EINVAL;
217
+ }
218
+
219
+ return 0;
220
+}
221
+
222
+static int fts_ft8756_get_hlic_ver(u8 *initcode)
223
+{
224
+ u8 *hlic_buf = initcode;
225
+ u16 hlic_len = 0;
226
+ u8 hlic_ver[2] = { 0 };
227
+
228
+ hlic_len =
229
+ (u16)(((u16)hlic_buf[LIC_FS_H_OFF]) << 8) + hlic_buf[LIC_FS_L_OFF];
230
+ FTS_INFO("host lcd init code len:0x%x", hlic_len);
231
+ if ((hlic_len >= FTS_MAX_LEN_SECTOR) || (hlic_len <= 0)) {
232
+ FTS_ERROR("host lcd init code len(0x%x) invalid", hlic_len);
233
+ return -EINVAL;
234
+ }
235
+
236
+ hlic_ver[0] = hlic_buf[hlic_len];
237
+ hlic_ver[1] = hlic_buf[hlic_len + 1];
238
+
239
+ FTS_INFO("host lcd init code ver:0x%x 0x%x", hlic_ver[0], hlic_ver[1]);
240
+ if (0xFF != (hlic_ver[0] + hlic_ver[1])) {
241
+ FTS_ERROR("host lcd init code version check fail");
242
+ return -EINVAL;
243
+ }
244
+
245
+ return hlic_ver[0];
246
+}
247
+
248
+static int fts_ft8756_upgrade_mode(enum FW_FLASH_MODE mode, u8 *buf, u32 len)
249
+{
250
+ int ret = 0;
251
+ u32 start_addr = 0;
252
+ u8 cmd[4] = { 0 };
253
+ u32 delay = 0;
254
+ int ecc_in_host = 0;
255
+ int ecc_in_tp = 0;
256
+
257
+ if ((NULL == buf) || (len < FTS_MIN_LEN)) {
258
+ FTS_ERROR("buffer/len(%x) is invalid", len);
259
+ return -EINVAL;
260
+ }
261
+
262
+ /* enter into upgrade environment */
263
+ ret = fts_fwupg_enter_into_boot();
264
+ if (ret < 0) {
265
+ FTS_ERROR("enter into pramboot/bootloader fail,ret=%d", ret);
266
+ goto fw_reset;
267
+ }
268
+
269
+ cmd[0] = FTS_CMD_FLASH_MODE;
270
+ cmd[1] = FLASH_MODE_UPGRADE_VALUE;
271
+ if (upgrade_func_ft8756.appoff_handle_in_ic) {
272
+ start_addr = 0; /* offset handle in pramboot */
273
+ } else {
274
+ start_addr = upgrade_func_ft8756.appoff;
275
+ }
276
+ if (FLASH_MODE_LIC == mode) {
277
+ /* lcd initial code upgrade */
278
+ cmd[1] = FLASH_MODE_LIC_VALUE;
279
+ } else if (FLASH_MODE_PARAM == mode) {
280
+ cmd[1] = FLASH_MODE_PARAM_VALUE;
281
+ }
282
+ FTS_INFO("flash mode:0x%02x, start addr=0x%04x", cmd[1], start_addr);
283
+
284
+ ret = fts_write(cmd, 2);
285
+ if (ret < 0) {
286
+ FTS_ERROR("upgrade mode(09) cmd write fail");
287
+ goto fw_reset;
288
+ }
289
+
290
+ cmd[0] = FTS_CMD_APP_DATA_LEN_INCELL;
291
+ cmd[1] = BYTE_OFF_16(len);
292
+ cmd[2] = BYTE_OFF_8(len);
293
+ cmd[3] = BYTE_OFF_0(len);
294
+ ret = fts_write(cmd, FTS_CMD_DATA_LEN_LEN);
295
+ if (ret < 0) {
296
+ FTS_ERROR("data len cmd write fail");
297
+ goto fw_reset;
298
+ }
299
+
300
+ delay = FTS_ERASE_SECTOR_DELAY * (len / FTS_MAX_LEN_SECTOR);
301
+ ret = fts_fwupg_erase(delay);
302
+ if (ret < 0) {
303
+ FTS_ERROR("erase cmd write fail");
304
+ goto fw_reset;
305
+ }
306
+
307
+ /* write app */
308
+ ecc_in_host = fts_flash_write_buf(start_addr, buf, len, 1);
309
+ if (ecc_in_host < 0 ) {
310
+ FTS_ERROR("flash write fail");
311
+ goto fw_reset;
312
+ }
313
+
314
+ /* ecc */
315
+ ecc_in_tp = fts_fwupg_ecc_cal(start_addr, len);
316
+ if (ecc_in_tp < 0 ) {
317
+ FTS_ERROR("ecc read fail");
318
+ goto fw_reset;
319
+ }
320
+
321
+ FTS_INFO("ecc in tp:%x, host:%x", ecc_in_tp, ecc_in_host);
322
+ if (ecc_in_tp != ecc_in_host) {
323
+ FTS_ERROR("ecc check fail");
324
+ goto fw_reset;
325
+ }
326
+
327
+ FTS_INFO("upgrade success, reset to normal boot");
328
+ ret = fts_fwupg_reset_in_boot();
329
+ if (ret < 0) {
330
+ FTS_ERROR("reset to normal boot fail");
331
+ }
332
+
333
+ fts_msleep(400);
334
+ return 0;
335
+
336
+fw_reset:
337
+ return -EIO;
338
+}
339
+
340
+/************************************************************************
341
+* Name: fts_ft8756_upgrade
342
+* Brief:
343
+* Input:
344
+* Output:
345
+* Return: return 0 if success, otherwise return error code
346
+***********************************************************************/
347
+static int fts_ft8756_upgrade(u8 *buf, u32 len)
348
+{
349
+ int ret = 0;
350
+ u8 *tmpbuf = NULL;
351
+ u32 app_len = 0;
352
+
353
+ FTS_INFO("fw app upgrade...");
354
+ if (NULL == buf) {
355
+ FTS_ERROR("fw buf is null");
356
+ return -EINVAL;
357
+ }
358
+
359
+ if ((len < FTS_MIN_LEN) || (len > FTS_MAX_LEN_FILE)) {
360
+ FTS_ERROR("fw buffer len(%x) fail", len);
361
+ return -EINVAL;
362
+ }
363
+
364
+ app_len = len - upgrade_func_ft8756.appoff;
365
+ tmpbuf = buf + upgrade_func_ft8756.appoff;
366
+ ret = fts_ft8756_upgrade_mode(FLASH_MODE_APP, tmpbuf, app_len);
367
+ if (ret < 0) {
368
+ FTS_INFO("fw upgrade fail,reset to normal boot");
369
+ if (fts_fwupg_reset_in_boot() < 0) {
370
+ FTS_ERROR("reset to normal boot fail");
371
+ }
372
+ return ret;
373
+ }
374
+
375
+ return 0;
376
+}
377
+
378
+static int fts_ft8756_lic_upgrade(u8 *buf, u32 len)
379
+{
380
+ int ret = 0;
381
+ u8 *tmpbuf = NULL;
382
+ u32 lic_len = 0;
383
+
384
+ FTS_INFO("lcd initial code upgrade...");
385
+ if (NULL == buf) {
386
+ FTS_ERROR("lcd initial code buffer is null");
387
+ return -EINVAL;
388
+ }
389
+
390
+ if ((len < FTS_MIN_LEN) || (len > FTS_MAX_LEN_FILE)) {
391
+ FTS_ERROR("lcd initial code buffer len(%x) fail", len);
392
+ return -EINVAL;
393
+ }
394
+
395
+ ret = check_initial_code_valid(buf);
396
+ if (ret < 0) {
397
+ FTS_ERROR("initial code invalid, not upgrade lcd init code");
398
+ return -EINVAL;
399
+ }
400
+
401
+ /* remalloc memory for initcode, need change content of initcode afterwise */
402
+ lic_len = FTS_MAX_LEN_SECTOR;
403
+ tmpbuf = kzalloc(lic_len, GFP_KERNEL);
404
+ if (NULL == tmpbuf) {
405
+ FTS_ERROR("initial code buf malloc fail");
406
+ return -EINVAL;
407
+ }
408
+ memcpy(tmpbuf, buf, lic_len);
409
+
410
+ ret = fts_ft8756_upgrade_mode(FLASH_MODE_LIC, tmpbuf, lic_len);
411
+ if (ret < 0) {
412
+ FTS_INFO("lcd initial code upgrade fail,reset to normal boot");
413
+ if (fts_fwupg_reset_in_boot() < 0) {
414
+ FTS_ERROR("reset to normal boot fail");
415
+ }
416
+ if (tmpbuf) {
417
+ kfree(tmpbuf);
418
+ tmpbuf = NULL;
419
+ }
420
+ return ret;
421
+ }
422
+
423
+ if (tmpbuf) {
424
+ kfree(tmpbuf);
425
+ tmpbuf = NULL;
426
+ }
427
+ return 0;
428
+}
429
+
430
+struct upgrade_func upgrade_func_ft8756 = {
431
+ .ctype = {0x15, 0x18, 0x23},
432
+ .fwveroff = 0x110E,
433
+ .fwcfgoff = 0xF80,
434
+ .appoff = 0x1000,
435
+ .licoff = 0x0000,
436
+ .appoff_handle_in_ic = true,
437
+ .pramboot_supported = true,
438
+ .pramboot = pb_file_ft8756,
439
+ .pb_length = sizeof(pb_file_ft8756),
440
+ .pram_ecc_check_mode = ECC_CHECK_MODE_CRC16,
441
+ .new_return_value_from_ic = true,
442
+ .hid_supported = false,
443
+ .upgrade = fts_ft8756_upgrade,
444
+ .get_hlic_ver = fts_ft8756_get_hlic_ver,
445
+ .lic_upgrade = fts_ft8756_lic_upgrade,
446
+};
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_gesture.c
....@@ -0,0 +1,511 @@
1
+/*
2
+ *
3
+ * FocalTech TouchScreen driver.
4
+ *
5
+ * Copyright (c) 2012-2020, Focaltech Ltd. All rights reserved.
6
+ *
7
+ * This software is licensed under the terms of the GNU General Public
8
+ * License version 2, as published by the Free Software Foundation, and
9
+ * may be copied, distributed, and modified under those terms.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ */
17
+
18
+/*****************************************************************************
19
+*
20
+* File Name: focaltech_gestrue.c
21
+*
22
+* Author: Focaltech Driver Team
23
+*
24
+* Created: 2016-08-08
25
+*
26
+* Abstract:
27
+*
28
+* Reference:
29
+*
30
+*****************************************************************************/
31
+
32
+/*****************************************************************************
33
+* 1.Included header files
34
+*****************************************************************************/
35
+#include "focaltech_core.h"
36
+
37
+/******************************************************************************
38
+* Private constant and macro definitions using #define
39
+*****************************************************************************/
40
+#define KEY_GESTURE_U KEY_U
41
+#define KEY_GESTURE_UP KEY_UP
42
+#define KEY_GESTURE_DOWN KEY_DOWN
43
+#define KEY_GESTURE_LEFT KEY_LEFT
44
+#define KEY_GESTURE_RIGHT KEY_RIGHT
45
+#define KEY_GESTURE_O KEY_O
46
+#define KEY_GESTURE_E KEY_E
47
+#define KEY_GESTURE_M KEY_M
48
+#define KEY_GESTURE_L KEY_L
49
+#define KEY_GESTURE_W KEY_W
50
+#define KEY_GESTURE_S KEY_S
51
+#define KEY_GESTURE_V KEY_V
52
+#define KEY_GESTURE_C KEY_C
53
+#define KEY_GESTURE_Z KEY_Z
54
+
55
+#define GESTURE_LEFT 0x20
56
+#define GESTURE_RIGHT 0x21
57
+#define GESTURE_UP 0x22
58
+#define GESTURE_DOWN 0x23
59
+#define GESTURE_DOUBLECLICK 0x24
60
+#define GESTURE_O 0x30
61
+#define GESTURE_W 0x31
62
+#define GESTURE_M 0x32
63
+#define GESTURE_E 0x33
64
+#define GESTURE_L 0x44
65
+#define GESTURE_S 0x46
66
+#define GESTURE_V 0x54
67
+#define GESTURE_Z 0x41
68
+#define GESTURE_C 0x34
69
+
70
+/*****************************************************************************
71
+* Private enumerations, structures and unions using typedef
72
+*****************************************************************************/
73
+/*
74
+* gesture_id - mean which gesture is recognised
75
+* point_num - points number of this gesture
76
+* coordinate_x - All gesture point x coordinate
77
+* coordinate_y - All gesture point y coordinate
78
+* mode - gesture enable/disable, need enable by host
79
+* - 1:enable gesture function(default) 0:disable
80
+* active - gesture work flag,
81
+* always set 1 when suspend, set 0 when resume
82
+*/
83
+struct fts_gesture_st {
84
+ u8 gesture_id;
85
+ u8 point_num;
86
+ u16 coordinate_x[FTS_GESTURE_POINTS_MAX];
87
+ u16 coordinate_y[FTS_GESTURE_POINTS_MAX];
88
+};
89
+
90
+/*****************************************************************************
91
+* Static variables
92
+*****************************************************************************/
93
+static struct fts_gesture_st fts_gesture_data;
94
+
95
+/*****************************************************************************
96
+* Global variable or extern global variabls/functions
97
+*****************************************************************************/
98
+
99
+/*****************************************************************************
100
+* Static function prototypes
101
+*****************************************************************************/
102
+static ssize_t fts_gesture_show(
103
+ struct device *dev, struct device_attribute *attr, char *buf)
104
+{
105
+ int count = 0;
106
+ u8 val = 0;
107
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
108
+
109
+ mutex_lock(&ts_data->input_dev->mutex);
110
+ fts_read_reg(FTS_REG_GESTURE_EN, &val);
111
+ count = snprintf(buf, PAGE_SIZE, "Gesture Mode:%s\n",
112
+ ts_data->gesture_support ? "On" : "Off");
113
+ count += snprintf(buf + count, PAGE_SIZE, "Reg(0xD0)=%d\n", val);
114
+ mutex_unlock(&ts_data->input_dev->mutex);
115
+
116
+ return count;
117
+}
118
+
119
+static ssize_t fts_gesture_store(
120
+ struct device *dev,
121
+ struct device_attribute *attr, const char *buf, size_t count)
122
+{
123
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
124
+
125
+ if (ts_data->suspended) {
126
+ FTS_INFO("In suspend,not operation gesture mode!");
127
+ return count;
128
+ }
129
+ mutex_lock(&ts_data->input_dev->mutex);
130
+ if (FTS_SYSFS_ECHO_ON(buf)) {
131
+ FTS_DEBUG("enable gesture");
132
+ ts_data->gesture_support = ENABLE;
133
+ } else if (FTS_SYSFS_ECHO_OFF(buf)) {
134
+ FTS_DEBUG("disable gesture");
135
+ ts_data->gesture_support = DISABLE;
136
+ }
137
+ mutex_unlock(&ts_data->input_dev->mutex);
138
+
139
+ return count;
140
+}
141
+
142
+static ssize_t fts_gesture_buf_show(
143
+ struct device *dev, struct device_attribute *attr, char *buf)
144
+{
145
+ int count = 0;
146
+ int i = 0;
147
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
148
+ struct input_dev *input_dev = ts_data->input_dev;
149
+ struct fts_gesture_st *gesture = &fts_gesture_data;
150
+
151
+ mutex_lock(&input_dev->mutex);
152
+ count = snprintf(buf, PAGE_SIZE, "Gesture ID:%d\n", gesture->gesture_id);
153
+ count += snprintf(buf + count, PAGE_SIZE, "Gesture PointNum:%d\n",
154
+ gesture->point_num);
155
+ count += snprintf(buf + count, PAGE_SIZE, "Gesture Points Buffer:\n");
156
+
157
+ /* save point data,max:6 */
158
+ for (i = 0; i < FTS_GESTURE_POINTS_MAX; i++) {
159
+ count += snprintf(buf + count, PAGE_SIZE, "%3d(%4d,%4d) ", i,
160
+ gesture->coordinate_x[i], gesture->coordinate_y[i]);
161
+ if ((i + 1) % 4 == 0)
162
+ count += snprintf(buf + count, PAGE_SIZE, "\n");
163
+ }
164
+ count += snprintf(buf + count, PAGE_SIZE, "\n");
165
+ mutex_unlock(&input_dev->mutex);
166
+
167
+ return count;
168
+}
169
+
170
+static ssize_t fts_gesture_buf_store(
171
+ struct device *dev,
172
+ struct device_attribute *attr, const char *buf, size_t count)
173
+{
174
+ return -EPERM;
175
+}
176
+
177
+static ssize_t fts_gesture_bm_show(
178
+ struct device *dev, struct device_attribute *attr, char *buf)
179
+{
180
+ int count = 0;
181
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
182
+
183
+ mutex_lock(&ts_data->input_dev->mutex);
184
+ count = snprintf(buf, PAGE_SIZE, "gesture bmode:%d\n",
185
+ ts_data->gesture_bmode);
186
+ mutex_unlock(&ts_data->input_dev->mutex);
187
+
188
+ return count;
189
+}
190
+
191
+static ssize_t fts_gesture_bm_store(
192
+ struct device *dev,
193
+ struct device_attribute *attr, const char *buf, size_t count)
194
+{
195
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
196
+ int value = 0xFF;
197
+ int ret = 0;
198
+
199
+ mutex_lock(&ts_data->input_dev->mutex);
200
+ ret = sscanf(buf, "%d", &value);
201
+ if (ret == 1) {
202
+ FTS_DEBUG("gesture bmode:%d->%d", ts_data->gesture_bmode, value);
203
+ ts_data->gesture_bmode = value;
204
+ }
205
+ mutex_unlock(&ts_data->input_dev->mutex);
206
+
207
+ return count;
208
+}
209
+
210
+/* sysfs gesture node
211
+ * read example: cat fts_gesture_mode ---read gesture mode
212
+ * write example:echo 1 > fts_gesture_mode --- write gesture mode to 1
213
+ *
214
+ */
215
+static DEVICE_ATTR(fts_gesture_mode, S_IRUGO | S_IWUSR, fts_gesture_show,
216
+ fts_gesture_store);
217
+/*
218
+ * read example: cat fts_gesture_buf --- read gesture buf
219
+ */
220
+static DEVICE_ATTR(fts_gesture_buf, S_IRUGO | S_IWUSR,
221
+ fts_gesture_buf_show, fts_gesture_buf_store);
222
+
223
+static DEVICE_ATTR(fts_gesture_bm, S_IRUGO | S_IWUSR,
224
+ fts_gesture_bm_show, fts_gesture_bm_store);
225
+
226
+static struct attribute *fts_gesture_mode_attrs[] = {
227
+ &dev_attr_fts_gesture_mode.attr,
228
+ &dev_attr_fts_gesture_buf.attr,
229
+ &dev_attr_fts_gesture_bm.attr,
230
+ NULL,
231
+};
232
+
233
+static struct attribute_group fts_gesture_group = {
234
+ .attrs = fts_gesture_mode_attrs,
235
+};
236
+
237
+static int fts_create_gesture_sysfs(struct device *dev)
238
+{
239
+ int ret = 0;
240
+
241
+ ret = sysfs_create_group(&dev->kobj, &fts_gesture_group);
242
+ if (ret) {
243
+ FTS_ERROR("gesture sys node create fail");
244
+ sysfs_remove_group(&dev->kobj, &fts_gesture_group);
245
+ return ret;
246
+ }
247
+
248
+ return 0;
249
+}
250
+
251
+static void fts_gesture_report(struct input_dev *input_dev, int gesture_id)
252
+{
253
+ int gesture;
254
+
255
+ FTS_DEBUG("gesture_id:0x%x", gesture_id);
256
+ switch (gesture_id) {
257
+ case GESTURE_LEFT:
258
+ gesture = KEY_GESTURE_LEFT;
259
+ break;
260
+ case GESTURE_RIGHT:
261
+ gesture = KEY_GESTURE_RIGHT;
262
+ break;
263
+ case GESTURE_UP:
264
+ gesture = KEY_GESTURE_UP;
265
+ break;
266
+ case GESTURE_DOWN:
267
+ gesture = KEY_GESTURE_DOWN;
268
+ break;
269
+ case GESTURE_DOUBLECLICK:
270
+ gesture = KEY_GESTURE_U;
271
+ break;
272
+ case GESTURE_O:
273
+ gesture = KEY_GESTURE_O;
274
+ break;
275
+ case GESTURE_W:
276
+ gesture = KEY_GESTURE_W;
277
+ break;
278
+ case GESTURE_M:
279
+ gesture = KEY_GESTURE_M;
280
+ break;
281
+ case GESTURE_E:
282
+ gesture = KEY_GESTURE_E;
283
+ break;
284
+ case GESTURE_L:
285
+ gesture = KEY_GESTURE_L;
286
+ break;
287
+ case GESTURE_S:
288
+ gesture = KEY_GESTURE_S;
289
+ break;
290
+ case GESTURE_V:
291
+ gesture = KEY_GESTURE_V;
292
+ break;
293
+ case GESTURE_Z:
294
+ gesture = KEY_GESTURE_Z;
295
+ break;
296
+ case GESTURE_C:
297
+ gesture = KEY_GESTURE_C;
298
+ break;
299
+ default:
300
+ gesture = -1;
301
+ break;
302
+ }
303
+ /* report event key */
304
+ if (gesture != -1) {
305
+ FTS_DEBUG("Gesture Code=%d", gesture);
306
+ input_report_key(input_dev, gesture, 1);
307
+ input_sync(input_dev);
308
+ input_report_key(input_dev, gesture, 0);
309
+ input_sync(input_dev);
310
+ }
311
+}
312
+
313
+/*****************************************************************************
314
+* Name: fts_gesture_readdata
315
+* Brief: Read information about gesture: enable flag/gesture points..., if ges-
316
+* ture enable, save gesture points' information, and report to OS.
317
+* It will be called this function every intrrupt when gesture is supported.
318
+*
319
+* gesture data length: 1(enable) + 1(reserve) + 2(header) + 6 * 4
320
+* Input: ts_data - global struct data
321
+* data - gesture data buffer
322
+* Output:
323
+* Return: 0 - read gesture data successfully, the report data is gesture data
324
+* 1 - tp not in suspend/gesture not enable in TP FW
325
+* -Exx - error
326
+*****************************************************************************/
327
+int fts_gesture_readdata(struct fts_ts_data *ts_data, u8 *touch_buf)
328
+{
329
+ int ret = 0;
330
+ int i = 0;
331
+ int index = 0;
332
+ u8 buf[FTS_GESTURE_DATA_LEN] = { 0 };
333
+ u8 gesture_en = 0xFF;
334
+ struct input_dev *input_dev = ts_data->input_dev;
335
+ struct fts_gesture_st *gesture = &fts_gesture_data;
336
+
337
+ ret = fts_read_reg(FTS_REG_GESTURE_EN, &gesture_en);
338
+ if (gesture_en != ENABLE) {
339
+ FTS_DEBUG("gesture not enable in fw, don't process gesture");
340
+ return 0;
341
+ }
342
+
343
+ if ((ts_data->gesture_bmode == GESTURE_BM_TOUCH) && touch_buf &&
344
+ (TOUCH_DEFAULT == ((touch_buf[FTS_TOUCH_E_NUM] >> 4) & 0x0F))) {
345
+ memcpy(buf, touch_buf + FTS_TOUCH_DATA_LEN, FTS_GESTURE_DATA_LEN);
346
+ } else {
347
+ buf[2] = FTS_REG_GESTURE_OUTPUT_ADDRESS;
348
+ ret = fts_read(&buf[2], 1, &buf[2], FTS_GESTURE_DATA_LEN - 2);
349
+ if (ret < 0) {
350
+ FTS_ERROR("read gesture header data fail");
351
+ return ret;
352
+ }
353
+ }
354
+
355
+ /* init variable before read gesture point */
356
+ memset(gesture->coordinate_x, 0, FTS_GESTURE_POINTS_MAX * sizeof(u16));
357
+ memset(gesture->coordinate_y, 0, FTS_GESTURE_POINTS_MAX * sizeof(u16));
358
+ gesture->gesture_id = buf[2];
359
+ gesture->point_num = buf[3];
360
+ FTS_DEBUG("gesture_id=%d, point_num=%d",
361
+ gesture->gesture_id, gesture->point_num);
362
+
363
+ /* save point data,max:6 */
364
+ for (i = 0; i < FTS_GESTURE_POINTS_MAX; i++) {
365
+ index = 4 * i + 4;
366
+ gesture->coordinate_x[i] = (u16)(((buf[0 + index] & 0x0F) << 8)
367
+ + buf[1 + index]);
368
+ gesture->coordinate_y[i] = (u16)(((buf[2 + index] & 0x0F) << 8)
369
+ + buf[3 + index]);
370
+ }
371
+
372
+ /* report gesture to OS */
373
+ fts_gesture_report(input_dev, gesture->gesture_id);
374
+ return FTS_RETVAL_IGNORE_TOUCHES;
375
+}
376
+
377
+void fts_gesture_recovery(struct fts_ts_data *ts_data)
378
+{
379
+ u8 state = 0xFF;
380
+ if (ts_data->gesture_support && ts_data->suspended) {
381
+ fts_write_reg(0xD1, 0xFF);
382
+ fts_write_reg(0xD2, 0xFF);
383
+ fts_write_reg(0xD5, 0xFF);
384
+ fts_write_reg(0xD6, 0xFF);
385
+ fts_write_reg(0xD7, 0xFF);
386
+ fts_write_reg(0xD8, 0xFF);
387
+ fts_write_reg(FTS_REG_GESTURE_EN, ENABLE);
388
+ fts_msleep(1);
389
+ fts_read_reg(FTS_REG_GESTURE_EN, &state);
390
+ if (state != ENABLE) {
391
+ FTS_ERROR("set gesture mode failed");
392
+ }
393
+ }
394
+}
395
+
396
+int fts_gesture_suspend(struct fts_ts_data *ts_data)
397
+{
398
+ int i = 0;
399
+ u8 state = 0xFF;
400
+
401
+ FTS_FUNC_ENTER();
402
+
403
+ for (i = 0; i < FTS_MAX_RETRIES_WRITEREG; i++) {
404
+ fts_write_reg(0xD1, 0xFF);
405
+ fts_write_reg(0xD2, 0xFF);
406
+ fts_write_reg(0xD5, 0xFF);
407
+ fts_write_reg(0xD6, 0xFF);
408
+ fts_write_reg(0xD7, 0xFF);
409
+ fts_write_reg(0xD8, 0xFF);
410
+ fts_write_reg(FTS_REG_GESTURE_EN, ENABLE);
411
+ fts_msleep(1);
412
+ fts_read_reg(FTS_REG_GESTURE_EN, &state);
413
+ if (state == ENABLE)
414
+ break;
415
+ }
416
+
417
+ if (i >= FTS_MAX_RETRIES_WRITEREG)
418
+ FTS_ERROR("make IC enter into gesture(suspend) fail,state:%x", state);
419
+ else
420
+ FTS_INFO("Enter into gesture(suspend) successfully");
421
+
422
+ FTS_FUNC_EXIT();
423
+ return 0;
424
+}
425
+
426
+int fts_gesture_resume(struct fts_ts_data *ts_data)
427
+{
428
+ int i = 0;
429
+ u8 state = 0xFF;
430
+
431
+ FTS_FUNC_ENTER();
432
+ for (i = 0; i < FTS_MAX_RETRIES_WRITEREG; i++) {
433
+ fts_write_reg(FTS_REG_GESTURE_EN, DISABLE);
434
+ fts_msleep(1);
435
+ fts_read_reg(FTS_REG_GESTURE_EN, &state);
436
+ if (state == DISABLE)
437
+ break;
438
+ }
439
+
440
+ if (i >= FTS_MAX_RETRIES_WRITEREG)
441
+ FTS_ERROR("make IC exit gesture(resume) fail,state:%x", state);
442
+ else
443
+ FTS_INFO("resume from gesture successfully");
444
+
445
+ FTS_FUNC_EXIT();
446
+ return 0;
447
+}
448
+
449
+int fts_gesture_init(struct fts_ts_data *ts_data)
450
+{
451
+ struct input_dev *input_dev = ts_data->input_dev;
452
+
453
+ FTS_FUNC_ENTER();
454
+ input_set_capability(input_dev, EV_KEY, KEY_POWER);
455
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_U);
456
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_UP);
457
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_DOWN);
458
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_LEFT);
459
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_RIGHT);
460
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_O);
461
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_E);
462
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_M);
463
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_L);
464
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_W);
465
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_S);
466
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_V);
467
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_Z);
468
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_C);
469
+
470
+ __set_bit(KEY_GESTURE_RIGHT, input_dev->keybit);
471
+ __set_bit(KEY_GESTURE_LEFT, input_dev->keybit);
472
+ __set_bit(KEY_GESTURE_UP, input_dev->keybit);
473
+ __set_bit(KEY_GESTURE_DOWN, input_dev->keybit);
474
+ __set_bit(KEY_GESTURE_U, input_dev->keybit);
475
+ __set_bit(KEY_GESTURE_O, input_dev->keybit);
476
+ __set_bit(KEY_GESTURE_E, input_dev->keybit);
477
+ __set_bit(KEY_GESTURE_M, input_dev->keybit);
478
+ __set_bit(KEY_GESTURE_W, input_dev->keybit);
479
+ __set_bit(KEY_GESTURE_L, input_dev->keybit);
480
+ __set_bit(KEY_GESTURE_S, input_dev->keybit);
481
+ __set_bit(KEY_GESTURE_V, input_dev->keybit);
482
+ __set_bit(KEY_GESTURE_C, input_dev->keybit);
483
+ __set_bit(KEY_GESTURE_Z, input_dev->keybit);
484
+
485
+ fts_create_gesture_sysfs(ts_data->dev);
486
+
487
+ memset(&fts_gesture_data, 0, sizeof(struct fts_gesture_st));
488
+ ts_data->gesture_bmode = GESTURE_BM_REG;
489
+ ts_data->gesture_support = DISABLE;
490
+
491
+ if (ts_data->bus_type == BUS_TYPE_SPI) {
492
+ if ((ts_data->ic_info.ids.type <= 0x25)
493
+ || (ts_data->ic_info.ids.type == 0x87)
494
+ || (ts_data->ic_info.ids.type == 0x88)) {
495
+ FTS_INFO("ic type:0x%02x,GESTURE_BM_TOUCH", ts_data->ic_info.ids.type);
496
+ ts_data->touch_size += FTS_GESTURE_DATA_LEN;
497
+ ts_data->gesture_bmode = GESTURE_BM_TOUCH;
498
+ }
499
+ }
500
+
501
+ FTS_FUNC_EXIT();
502
+ return 0;
503
+}
504
+
505
+int fts_gesture_exit(struct fts_ts_data *ts_data)
506
+{
507
+ FTS_FUNC_ENTER();
508
+ sysfs_remove_group(&ts_data->dev->kobj, &fts_gesture_group);
509
+ FTS_FUNC_EXIT();
510
+ return 0;
511
+}
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_i2c.c
....@@ -0,0 +1,335 @@
1
+/*
2
+ *
3
+ * FocalTech TouchScreen driver.
4
+ *
5
+ * Copyright (c) 2012-2020, FocalTech Systems, Ltd., all rights reserved.
6
+ *
7
+ * This software is licensed under the terms of the GNU General Public
8
+ * License version 2, as published by the Free Software Foundation, and
9
+ * may be copied, distributed, and modified under those terms.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ */
17
+
18
+/************************************************************************
19
+*
20
+* File Name: focaltech_i2c.c
21
+*
22
+* Author: Focaltech Driver Team
23
+*
24
+* Created: 2016-08-04
25
+*
26
+* Abstract: i2c communication with TP
27
+*
28
+* Version: v2.0
29
+*
30
+* Revision History:
31
+*
32
+************************************************************************/
33
+
34
+/*****************************************************************************
35
+* Included header files
36
+*****************************************************************************/
37
+#include "focaltech_core.h"
38
+
39
+/*****************************************************************************
40
+* Private constant and macro definitions using #define
41
+*****************************************************************************/
42
+#define I2C_RETRY_NUMBER 3
43
+
44
+/*****************************************************************************
45
+* Private enumerations, structures and unions using typedef
46
+*****************************************************************************/
47
+
48
+/*****************************************************************************
49
+* Static variables
50
+*****************************************************************************/
51
+
52
+/*****************************************************************************
53
+* Global variable or extern global variabls/functions
54
+*****************************************************************************/
55
+
56
+/*****************************************************************************
57
+* Static function prototypes
58
+*****************************************************************************/
59
+
60
+/*****************************************************************************
61
+* functions body
62
+*****************************************************************************/
63
+int fts_read(u8 *cmd, u32 cmdlen, u8 *data, u32 datalen)
64
+{
65
+ int ret = 0;
66
+ int i = 0;
67
+ struct fts_ts_data *ts_data = fts_data;
68
+ struct i2c_msg msg_list[2];
69
+ struct i2c_msg *msg = NULL;
70
+ int msg_num = 0;
71
+
72
+ /* must have data when read */
73
+ if (!ts_data || !ts_data->client || !data || !datalen
74
+ || (datalen > FTS_MAX_BUS_BUF) || (cmdlen > FTS_MAX_BUS_BUF)) {
75
+ FTS_ERROR("fts_data/client/cmdlen(%d)/data/datalen(%d) is invalid",
76
+ cmdlen, datalen);
77
+ return -EINVAL;
78
+ }
79
+
80
+ mutex_lock(&ts_data->bus_lock);
81
+ memset(&msg_list[0], 0, sizeof(struct i2c_msg));
82
+ memset(&msg_list[1], 0, sizeof(struct i2c_msg));
83
+ memcpy(ts_data->bus_tx_buf, cmd, cmdlen);
84
+ msg_list[0].addr = ts_data->client->addr;
85
+ msg_list[0].flags = 0;
86
+ msg_list[0].len = cmdlen;
87
+ msg_list[0].buf = ts_data->bus_tx_buf;
88
+ msg_list[1].addr = ts_data->client->addr;
89
+ msg_list[1].flags = I2C_M_RD;
90
+ msg_list[1].len = datalen;
91
+ msg_list[1].buf = ts_data->bus_rx_buf;
92
+ if (cmd && cmdlen) {
93
+ msg = &msg_list[0];
94
+ msg_num = 2;
95
+ } else {
96
+ msg = &msg_list[1];
97
+ msg_num = 1;
98
+ }
99
+
100
+ for (i = 0; i < I2C_RETRY_NUMBER; i++) {
101
+ ret = i2c_transfer(ts_data->client->adapter, msg, msg_num);
102
+ if (ret < 0) {
103
+ FTS_ERROR("i2c_transfer(read) fail,ret:%d", ret);
104
+ } else {
105
+ memcpy(data, ts_data->bus_rx_buf, datalen);
106
+ break;
107
+ }
108
+ }
109
+
110
+ mutex_unlock(&ts_data->bus_lock);
111
+ return ret;
112
+}
113
+
114
+int fts_write(u8 *writebuf, u32 writelen)
115
+{
116
+ int ret = 0;
117
+ int i = 0;
118
+ struct fts_ts_data *ts_data = fts_data;
119
+ struct i2c_msg msgs;
120
+
121
+ if (!ts_data || !ts_data->client || !writebuf || !writelen
122
+ || (writelen > FTS_MAX_BUS_BUF)) {
123
+ FTS_ERROR("fts_data/client/data/datalen(%d) is invalid", writelen);
124
+ return -EINVAL;
125
+ }
126
+
127
+ mutex_lock(&ts_data->bus_lock);
128
+ memset(&msgs, 0, sizeof(struct i2c_msg));
129
+ memcpy(ts_data->bus_tx_buf, writebuf, writelen);
130
+ msgs.addr = ts_data->client->addr;
131
+ msgs.flags = 0;
132
+ msgs.len = writelen;
133
+ msgs.buf = ts_data->bus_tx_buf;
134
+ for (i = 0; i < I2C_RETRY_NUMBER; i++) {
135
+ ret = i2c_transfer(ts_data->client->adapter, &msgs, 1);
136
+ if (ret < 0) {
137
+ FTS_ERROR("i2c_transfer(write) fail,ret:%d", ret);
138
+ } else {
139
+ break;
140
+ }
141
+ }
142
+ mutex_unlock(&ts_data->bus_lock);
143
+ return ret;
144
+}
145
+
146
+int fts_read_reg(u8 addr, u8 *value)
147
+{
148
+ return fts_read(&addr, 1, value, 1);
149
+}
150
+
151
+int fts_write_reg(u8 addr, u8 value)
152
+{
153
+ u8 buf[2] = { 0 };
154
+
155
+ buf[0] = addr;
156
+ buf[1] = value;
157
+ return fts_write(buf, sizeof(buf));
158
+}
159
+
160
+int fts_bus_transfer_direct(u8 *writebuf, u32 writelen, u8 *readbuf, u32 readlen)
161
+{
162
+ return 0;
163
+}
164
+
165
+int fts_bus_configure(struct fts_ts_data *ts_data, u8 *buf, u32 size)
166
+{
167
+ FTS_FUNC_ENTER();
168
+ if (ts_data->client && buf && size && (buf[0] != ts_data->client->addr)) {
169
+ ts_data->client->addr = buf[0];
170
+ FTS_INFO("Change i2c addr 0x%x to 0x%x", (ts_data->client->addr << 1), (buf[0] << 1));
171
+ }
172
+ FTS_FUNC_EXIT();
173
+ return 0;
174
+}
175
+
176
+int fts_bus_set_speed(struct fts_ts_data *ts_data, u32 speed)
177
+{
178
+ return 0;
179
+}
180
+
181
+
182
+/*****************************************************************************
183
+* TP Driver
184
+*****************************************************************************/
185
+static int fts_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
186
+{
187
+ int ret = 0;
188
+ struct fts_ts_data *ts_data = NULL;
189
+
190
+ FTS_INFO("Touch Screen(I2C BUS) driver prboe...");
191
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
192
+ FTS_ERROR("I2C not supported");
193
+ return -ENODEV;
194
+ }
195
+
196
+ /* malloc memory for global struct variable */
197
+ ts_data = (struct fts_ts_data *)kzalloc(sizeof(*ts_data), GFP_KERNEL);
198
+ if (!ts_data) {
199
+ FTS_ERROR("allocate memory for fts_data fail");
200
+ return -ENOMEM;
201
+ }
202
+
203
+ ts_data->client = client;
204
+ ts_data->dev = &client->dev;
205
+ ts_data->log_level = 1;
206
+ ts_data->fw_is_running = 0;
207
+ ts_data->bus_type = BUS_TYPE_I2C;
208
+ ts_data->bus_ver = BUS_VER_DEFAULT;
209
+ i2c_set_clientdata(client, ts_data);
210
+
211
+ ret = fts_ts_probe_entry(ts_data);
212
+ if (ret) {
213
+ FTS_ERROR("Touch Screen(I2C BUS) driver probe fail");
214
+ i2c_set_clientdata(client, NULL);
215
+ kfree_safe(ts_data);
216
+ return ret;
217
+ }
218
+
219
+ FTS_INFO("Touch Screen(I2C BUS) driver prboe successfully");
220
+ return 0;
221
+}
222
+
223
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0))
224
+static void fts_ts_remove(struct i2c_client *client)
225
+{
226
+ struct fts_ts_data *ts_data = i2c_get_clientdata(client);
227
+ FTS_INFO("Touch Screen(I2C BUS) driver remove...");
228
+ if (ts_data) {
229
+ fts_ts_remove_entry(ts_data);
230
+ i2c_set_clientdata(client, NULL);
231
+ kfree_safe(ts_data);
232
+ }
233
+}
234
+#else
235
+static int fts_ts_remove(struct i2c_client *client)
236
+{
237
+ struct fts_ts_data *ts_data = i2c_get_clientdata(client);
238
+ FTS_INFO("Touch Screen(I2C BUS) driver remove...");
239
+ if (ts_data) {
240
+ fts_ts_remove_entry(ts_data);
241
+ i2c_set_clientdata(client, NULL);
242
+ kfree_safe(ts_data);
243
+ }
244
+ return 0;
245
+}
246
+#endif
247
+
248
+static void fts_ts_shutdown(struct i2c_client *client)
249
+{
250
+ struct fts_ts_data *ts_data = i2c_get_clientdata(client);
251
+ FTS_FUNC_ENTER();
252
+ if (ts_data) {
253
+ fts_ts_remove_entry(ts_data);
254
+ i2c_set_clientdata(client, NULL);
255
+ kfree_safe(ts_data);
256
+ }
257
+ FTS_FUNC_EXIT();
258
+}
259
+
260
+#if IS_ENABLED(CONFIG_PM) && FTS_PATCH_COMERR_PM
261
+static int fts_pm_suspend(struct device *dev)
262
+{
263
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
264
+
265
+ FTS_INFO("system enters into pm_suspend");
266
+ ts_data->pm_suspend = true;
267
+ reinit_completion(&ts_data->pm_completion);
268
+ return 0;
269
+}
270
+
271
+static int fts_pm_resume(struct device *dev)
272
+{
273
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
274
+
275
+ FTS_INFO("system resumes from pm_suspend");
276
+ ts_data->pm_suspend = false;
277
+ complete(&ts_data->pm_completion);
278
+ return 0;
279
+}
280
+
281
+static const struct dev_pm_ops fts_dev_pm_ops = {
282
+ .suspend = fts_pm_suspend,
283
+ .resume = fts_pm_resume,
284
+};
285
+#endif
286
+
287
+static const struct i2c_device_id fts_ts_id[] = {
288
+ {FTS_DRIVER_NAME, 0},
289
+ {},
290
+};
291
+static const struct of_device_id fts_dt_match[] = {
292
+ {.compatible = "focaltech,fts", },
293
+ {},
294
+};
295
+MODULE_DEVICE_TABLE(of, fts_dt_match);
296
+
297
+static struct i2c_driver fts_ts_i2c_driver = {
298
+ .probe = fts_ts_probe,
299
+ .remove = fts_ts_remove,
300
+ .shutdown = fts_ts_shutdown,
301
+ .driver = {
302
+ .name = FTS_DRIVER_NAME,
303
+ .owner = THIS_MODULE,
304
+#if IS_ENABLED(CONFIG_PM) && FTS_PATCH_COMERR_PM
305
+ .pm = &fts_dev_pm_ops,
306
+#endif
307
+ .of_match_table = of_match_ptr(fts_dt_match),
308
+ },
309
+ .id_table = fts_ts_id,
310
+};
311
+
312
+static int __init fts_ts_i2c_init(void)
313
+{
314
+ int ret = 0;
315
+
316
+ FTS_FUNC_ENTER();
317
+ ret = i2c_add_driver(&fts_ts_i2c_driver);
318
+ if ( ret != 0 ) {
319
+ FTS_ERROR("Focaltech touch screen driver(I2C) init failed!");
320
+ }
321
+ FTS_FUNC_EXIT();
322
+ return ret;
323
+}
324
+
325
+static void __exit fts_ts_i2c_exit(void)
326
+{
327
+ i2c_del_driver(&fts_ts_i2c_driver);
328
+}
329
+
330
+module_init(fts_ts_i2c_init);
331
+module_exit(fts_ts_i2c_exit);
332
+
333
+MODULE_AUTHOR("FocalTech Driver Team");
334
+MODULE_DESCRIPTION("FocalTech Touchscreen Driver(I2C)");
335
+MODULE_LICENSE("GPL v2");
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_point_report_check.c
....@@ -0,0 +1,185 @@
1
+/*
2
+ *
3
+ * FocalTech TouchScreen driver.
4
+ *
5
+ * Copyright (c) 2012-2020, FocalTech Systems, Ltd., all rights reserved.
6
+ *
7
+ * This software is licensed under the terms of the GNU General Public
8
+ * License version 2, as published by the Free Software Foundation, and
9
+ * may be copied, distributed, and modified under those terms.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ */
17
+
18
+/*****************************************************************************
19
+*
20
+* File Name: focaltech_point_report_check.c
21
+*
22
+* Author: Focaltech Driver Team
23
+*
24
+* Created: 2016-11-16
25
+*
26
+* Abstract: point report check function
27
+*
28
+* Version: v1.0
29
+*
30
+* Revision History:
31
+*
32
+*****************************************************************************/
33
+
34
+/*****************************************************************************
35
+* Included header files
36
+*****************************************************************************/
37
+#include "focaltech_core.h"
38
+
39
+/*****************************************************************************
40
+* Private constant and macro definitions using #define
41
+*****************************************************************************/
42
+#define POINT_REPORT_CHECK_WAIT_TIME 200 /* unit:ms */
43
+#define PRC_INTR_INTERVALS 100 /* unit:ms */
44
+
45
+/*****************************************************************************
46
+* Static variables
47
+*****************************************************************************/
48
+
49
+/*****************************************************************************
50
+* functions body
51
+*****************************************************************************/
52
+/*****************************************************************************
53
+* Name: fts_prc_func
54
+* Brief: fts point report check work func, report whole up of points
55
+* Input:
56
+* Output:
57
+* Return:
58
+*****************************************************************************/
59
+static void fts_prc_func(struct work_struct *work)
60
+{
61
+ struct fts_ts_data *ts_data = container_of(work,
62
+ struct fts_ts_data, prc_work.work);
63
+ unsigned long cur_jiffies = jiffies;
64
+ unsigned long intr_timeout = msecs_to_jiffies(PRC_INTR_INTERVALS);
65
+
66
+ if (ts_data->prc_support && !ts_data->suspended) {
67
+ intr_timeout += ts_data->intr_jiffies;
68
+ if (time_after(cur_jiffies, intr_timeout)) {
69
+ if (ts_data->touch_points) {
70
+ fts_release_all_finger();
71
+ if (ts_data->log_level >= 3)
72
+ FTS_DEBUG("prc trigger interval:%dms",
73
+ jiffies_to_msecs(cur_jiffies - ts_data->intr_jiffies));
74
+ }
75
+ ts_data->prc_mode = 0;
76
+ } else {
77
+ queue_delayed_work(ts_data->ts_workqueue, &ts_data->prc_work,
78
+ msecs_to_jiffies(POINT_REPORT_CHECK_WAIT_TIME));
79
+ ts_data->prc_mode = 1;
80
+ }
81
+ } else {
82
+ ts_data->prc_mode = 0;
83
+ }
84
+}
85
+
86
+/*****************************************************************************
87
+* Name: fts_prc_queue_work
88
+* Brief: fts point report check queue work, call it when interrupt comes
89
+* Input:
90
+* Output:
91
+* Return:
92
+*****************************************************************************/
93
+void fts_prc_queue_work(struct fts_ts_data *ts_data)
94
+{
95
+ if (ts_data->prc_support && !ts_data->prc_mode && !ts_data->suspended) {
96
+ queue_delayed_work(ts_data->ts_workqueue, &ts_data->prc_work,
97
+ msecs_to_jiffies(POINT_REPORT_CHECK_WAIT_TIME));
98
+ ts_data->prc_mode = 1;
99
+ }
100
+}
101
+
102
+
103
+static ssize_t fts_prc_store(
104
+ struct device *dev,
105
+ struct device_attribute *attr, const char *buf, size_t count)
106
+{
107
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
108
+ struct input_dev *input_dev = ts_data->input_dev;
109
+
110
+ mutex_lock(&input_dev->mutex);
111
+ if (FTS_SYSFS_ECHO_ON(buf)) {
112
+ FTS_DEBUG("enable prc");
113
+ ts_data->prc_support = ENABLE;
114
+ } else if (FTS_SYSFS_ECHO_OFF(buf)) {
115
+ FTS_DEBUG("disable prc");
116
+ cancel_delayed_work_sync(&ts_data->prc_work);
117
+ ts_data->prc_support = DISABLE;
118
+ }
119
+ mutex_unlock(&input_dev->mutex);
120
+
121
+ return count;
122
+}
123
+
124
+static ssize_t fts_prc_show(
125
+ struct device *dev, struct device_attribute *attr, char *buf)
126
+{
127
+ int count;
128
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
129
+ struct input_dev *input_dev = ts_data->input_dev;
130
+
131
+ mutex_lock(&input_dev->mutex);
132
+ count = snprintf(buf, PAGE_SIZE, "PRC: %s\n", \
133
+ ts_data->prc_support ? "Enable" : "Disable");
134
+ mutex_unlock(&input_dev->mutex);
135
+
136
+ return count;
137
+}
138
+
139
+static DEVICE_ATTR(fts_prc, S_IRUGO | S_IWUSR, fts_prc_show, fts_prc_store);
140
+
141
+/*****************************************************************************
142
+* Name: fts_point_report_check_init
143
+* Brief:
144
+* Input:
145
+* Output:
146
+* Return: < 0: Fail to create esd check queue
147
+*****************************************************************************/
148
+int fts_point_report_check_init(struct fts_ts_data *ts_data)
149
+{
150
+ int ret = 0;
151
+
152
+ FTS_FUNC_ENTER();
153
+
154
+ if (ts_data->ts_workqueue) {
155
+ INIT_DELAYED_WORK(&ts_data->prc_work, fts_prc_func);
156
+ } else {
157
+ FTS_ERROR("fts workqueue is NULL, can't run point report check function");
158
+ return -EINVAL;
159
+ }
160
+
161
+ ret = sysfs_create_file(&ts_data->dev->kobj, &dev_attr_fts_prc.attr);
162
+ if ( ret < 0) {
163
+ FTS_ERROR("create prc sysfs fail");
164
+ }
165
+
166
+ ts_data->prc_support = FTS_POINT_REPORT_CHECK_EN;
167
+ FTS_FUNC_EXIT();
168
+ return 0;
169
+}
170
+
171
+/*****************************************************************************
172
+* Name: fts_point_report_check_exit
173
+* Brief:
174
+* Input:
175
+* Output:
176
+* Return:
177
+*****************************************************************************/
178
+int fts_point_report_check_exit(struct fts_ts_data *ts_data)
179
+{
180
+ FTS_FUNC_ENTER();
181
+ cancel_delayed_work_sync(&ts_data->prc_work);
182
+ sysfs_remove_file(&ts_data->dev->kobj, &dev_attr_fts_prc.attr);
183
+ FTS_FUNC_EXIT();
184
+ return 0;
185
+}
longan/kernel/linux-4.9/drivers/input/touchscreen/focaltech_touch_ft8756/focaltech_proximity.c
....@@ -0,0 +1,827 @@
1
+/*
2
+ *
3
+ * FocalTech TouchScreen driver.
4
+ *
5
+ * Copyright (c) 2012-2020, FocalTech Systems, Ltd., all rights reserved.
6
+ *
7
+ * This software is licensed under the terms of the GNU General Public
8
+ * License version 2, as published by the Free Software Foundation, and
9
+ * may be copied, distributed, and modified under those terms.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ */
17
+
18
+/*****************************************************************************
19
+*
20
+* File Name: focaltech_proximity.c
21
+*
22
+* Author: Focaltech Driver Team
23
+*
24
+* Created: 2016-09-19
25
+*
26
+* Abstract: close proximity function
27
+*
28
+* Version: v1.0
29
+*
30
+* Revision History:
31
+* v1.0:
32
+* First release based on xiaguobin's solution. By luougojin 2016-08-19
33
+*****************************************************************************/
34
+
35
+/*****************************************************************************
36
+* Included header files
37
+*****************************************************************************/
38
+#include "focaltech_core.h"
39
+#include "focaltech_common.h"
40
+
41
+#if FTS_PSENSOR_EN
42
+/*****************************************************************************
43
+ * Private constant and macro definitions using #define
44
+ *****************************************************************************/
45
+/* proximity register address*/
46
+#define FTS_REG_PSENSOR_ENABLE 0xB0
47
+#define FTS_REG_PSENSOR_STATUS 0xB5
48
+#define FTS_REG_PSENSOR_CLEAR_STATUS 0xB6
49
+
50
+/* proximity register value read from TP */
51
+#define PROXIMITY_TP_VAL_NEAR 0xC0
52
+#define PROXIMITY_TP_VAL_FAR 0xE0
53
+#define PROXIMITY_TP_VAL_ERROR 0xEE
54
+#define PROXIMITY_TP_VAL_DEFAULT 0xFF
55
+
56
+/* host state : far or near */
57
+#define PROXIMITY_HOST_STATE_NEAR 0
58
+#define PROXIMITY_HOST_STATE_FAR 1
59
+#define PROXIMITY_HOST_STATE_DEFAULT PROXIMITY_HOST_STATE_FAR
60
+
61
+/* proximity solutions */
62
+#define PROXIMITY_SOLUTION_SAMPLE 0
63
+#define PROXIMITY_SOLUTION_QCOM 1
64
+#define PROXIMITY_SOLUTION_MTK 2
65
+#define PROXIMITY_SOLUTION_SAMPLE_1 3
66
+#define PROXIMITY_SOLUTION PROXIMITY_SOLUTION_SAMPLE
67
+
68
+/*****************************************************************************
69
+* Private enumerations, structures and unions using typedef
70
+*****************************************************************************/
71
+struct fts_proximity_ops;
72
+
73
+/*
74
+ * @tp_val, proximity value read from TP register, the value is:
75
+ * PROXIMITY_TP_VAL_NEAR/PROXIMITY_TP_VAL_FAR and so on.
76
+ *
77
+ * @tp_val_last, the backup proximity value
78
+ * @host_state, the proximity state of host, tp driver will report the
79
+ * value to Android, the value is:
80
+ * PROXIMITY_HOST_STATE_NEAR
81
+ * PROXIMITY_HOST_STATE_FAR
82
+ */
83
+struct fts_proximity {
84
+ struct fts_ts_data *ts_data;
85
+ struct input_dev *proximity_input_dev;
86
+ struct fts_proximity_ops *ops;
87
+ u8 tp_val;
88
+ u8 tp_val_last;
89
+ int host_state;
90
+};
91
+
92
+struct fts_proximity_ops {
93
+ int (*init)(struct fts_proximity *proximity_data);
94
+ int (*exit)(struct fts_proximity *proximity_data);
95
+ int (*report)(struct fts_proximity *proximity_data);
96
+};
97
+
98
+/*****************************************************************************
99
+* variables or functions
100
+*****************************************************************************/
101
+static struct fts_proximity fts_proximity_data;
102
+
103
+
104
+static void fts_proximity_set_reg(int value)
105
+{
106
+ int i = 0;
107
+ u8 enable_value = value ? 0x01 : 0x00;
108
+ u8 regval = 0xFF;
109
+
110
+ for (i = 0; i < FTS_MAX_RETRIES_WRITEREG; i++) {
111
+ fts_read_reg(FTS_REG_PSENSOR_ENABLE, &regval);
112
+ if (regval == enable_value)
113
+ break;
114
+ fts_write_reg(FTS_REG_PSENSOR_ENABLE, enable_value);
115
+ fts_msleep(1);
116
+ }
117
+
118
+ if (i >= FTS_MAX_RETRIES_WRITEREG)
119
+ FTS_ERROR("set proximity mode to %x failed,reg_val:%x", enable_value, regval);
120
+ else if (i > 0)
121
+ FTS_INFO("set proximity mode to %x successfully", value);
122
+}
123
+
124
+/************************************************************************
125
+* Name: fts_proximity_enable
126
+* Brief: enable or disable proximity function, set variable and write it
127
+* to TP FW.
128
+*
129
+* Input: proximity_data, global structure variable.
130
+* @enable, 0 is to disable proximity, 1 to enable.
131
+* Output:
132
+*
133
+* Return: 0 for success
134
+***********************************************************************/
135
+static int fts_proximity_enable(struct fts_proximity *proximity_data, int enable)
136
+{
137
+ int ret = 0;
138
+ if (!proximity_data || !proximity_data->ts_data || !proximity_data->proximity_input_dev) {
139
+ FTS_ERROR("proximity/ts/input is null");
140
+ return -EINVAL;
141
+ }
142
+
143
+ FTS_INFO("set proximity mode to %s", !!enable ? "enable" : "disable");
144
+ mutex_lock(&proximity_data->proximity_input_dev->mutex);
145
+ proximity_data->ts_data->proximity_mode = !!enable;
146
+ fts_proximity_set_reg(enable);
147
+ proximity_data->tp_val = PROXIMITY_TP_VAL_DEFAULT;
148
+ proximity_data->tp_val_last = PROXIMITY_TP_VAL_DEFAULT;
149
+ proximity_data->host_state = PROXIMITY_HOST_STATE_DEFAULT;
150
+ mutex_unlock(&proximity_data->proximity_input_dev->mutex);
151
+ return ret;
152
+}
153
+
154
+
155
+
156
+
157
+#if (PROXIMITY_SOLUTION == PROXIMITY_SOLUTION_MTK)
158
+#include <hwmsensor.h>
159
+#include <sensors_io.h>
160
+#include <alsps.h>
161
+
162
+/*****************************************************************************
163
+* Private constant and macro definitions using #define
164
+*****************************************************************************/
165
+/*
166
+ * FTS_ALSPS_SUPPORT is choose structure hwmsen_object or control_path, data_path
167
+ * FTS_ALSPS_SUPPORT = 1, is control_path, data_path
168
+ * FTS_ALSPS_SUPPORT = 0, hwmsen_object
169
+ */
170
+#define FTS_ALSPS_SUPPORT 1
171
+/*
172
+ * FTS_OPEN_DATA_HAL_SUPPORT is choose structure ps_control_path or batch, flush
173
+ * FTS_ALSPS_SUPPORT = 1, is batch, flush
174
+ * FTS_ALSPS_SUPPORT = 0, NULL
175
+ */
176
+#define FTS_OPEN_DATA_HAL_SUPPORT 1
177
+
178
+#if !FTS_ALSPS_SUPPORT
179
+#include <hwmsen_dev.h>
180
+#endif
181
+
182
+/*****************************************************************************
183
+* Static variables
184
+*****************************************************************************/
185
+
186
+/*****************************************************************************
187
+* Global variable or extern global variabls/functions
188
+*****************************************************************************/
189
+
190
+/*****************************************************************************
191
+* Static function prototypes
192
+*****************************************************************************/
193
+
194
+#if FTS_ALSPS_SUPPORT
195
+/* if use this typ of enable , Gsensor should report inputEvent(x, y, z ,stats, div) to HAL */
196
+static int ps_open_report_data(int open)
197
+{
198
+ /* should queue work to report event if is_report_input_direct=true */
199
+ return 0;
200
+}
201
+
202
+/* if use this type of enable , Psensor only enabled but not report inputEvent to HAL */
203
+static int ps_enable_nodata(int en)
204
+{
205
+ int ret = 0;
206
+ FTS_DEBUG("[PROXIMITY]SENSOR_ENABLE value = %d", en);
207
+ /* Enable proximity */
208
+ ret = fts_proximity_enable(fts_proximity_data, en);
209
+ return ret;
210
+}
211
+
212
+static int ps_set_delay(u64 ns)
213
+{
214
+ return 0;
215
+}
216
+
217
+#if FTS_OPEN_DATA_HAL_SUPPORT
218
+static int ps_batch(int flag, int64_t sampling_period_ns, int64_t max_batch_report_ns)
219
+{
220
+ return 0;
221
+}
222
+
223
+static int ps_flush(void)
224
+{
225
+ return 0;
226
+}
227
+#endif
228
+
229
+static int ps_get_data(int *value, int *status)
230
+{
231
+ *value = (int)fts_proximity_data.host_state;
232
+ FTS_DEBUG("proximity status = %d\n", *value);
233
+ *status = SENSOR_STATUS_ACCURACY_MEDIUM;
234
+ return 0;
235
+}
236
+
237
+static int ps_local_init(void)
238
+{
239
+ int err = 0;
240
+ struct ps_control_path ps_ctl = { 0 };
241
+ struct ps_data_path ps_data = { 0 };
242
+
243
+ ps_ctl.is_use_common_factory = false;
244
+ ps_ctl.open_report_data = ps_open_report_data;
245
+ ps_ctl.enable_nodata = ps_enable_nodata;
246
+ ps_ctl.set_delay = ps_set_delay;
247
+#if FTS_OPEN_DATA_HAL_SUPPORT
248
+ ps_ctl.batch = ps_batch;
249
+ ps_ctl.flush = ps_flush;
250
+#endif
251
+ ps_ctl.is_report_input_direct = false;
252
+ ps_ctl.is_support_batch = false;
253
+
254
+ err = ps_register_control_path(&ps_ctl);
255
+ if (err) {
256
+ FTS_ERROR("register fail = %d\n", err);
257
+ }
258
+ ps_data.get_data = ps_get_data;
259
+ ps_data.vender_div = 100;
260
+ err = ps_register_data_path(&ps_data);
261
+ if (err) {
262
+ FTS_ERROR("tregister fail = %d\n", err);
263
+ }
264
+
265
+ return err;
266
+}
267
+int ps_local_uninit(void)
268
+{
269
+ return 0;
270
+}
271
+
272
+struct alsps_init_info ps_init_info = {
273
+ .name = "fts_ts",
274
+ .init = ps_local_init,
275
+ .uninit = ps_local_uninit,
276
+};
277
+
278
+#else
279
+
280
+static int mtk_ps_operate(void *self, uint32_t command, void *buff_in,
281
+ int size_in, void *buff_out, int size_out, int *actualout)
282
+{
283
+ int err = 0;
284
+ int value;
285
+ struct hwm_sensor_data *sensor_data;
286
+ struct fts_proximity *proximity_data = &fts_proximity_data;
287
+
288
+ if (!proximity_data || !proximity_data->ts_data) {
289
+ FTS_ERROR("proximity_data/ts_data" is null);
290
+ return -EINVAL;
291
+ }
292
+
293
+ FTS_DEBUG("[PROXIMITY]COMMAND = %d", command);
294
+ switch (command) {
295
+ case SENSOR_DELAY:
296
+ if ((buff_in == NULL) || (size_in < sizeof(int))) {
297
+ FTS_ERROR("[PROXIMITY]Set delay parameter error!");
298
+ err = -EINVAL;
299
+ }
300
+ break;
301
+
302
+ case SENSOR_ENABLE:
303
+ if ((buff_in == NULL) || (size_in < sizeof(int))) {
304
+ FTS_ERROR("[PROXIMITY]Enable sensor parameter error!");
305
+ err = -EINVAL;
306
+ } else {
307
+ value = *(int *)buff_in;
308
+ FTS_DEBUG("[PROXIMITY]SENSOR_ENABLE value = %d", value);
309
+ /* Enable proximity */
310
+ err = fts_proximity_enable(proximity_data, value);
311
+ }
312
+ break;
313
+
314
+ case SENSOR_GET_DATA:
315
+ if ((buff_out == NULL) || (size_out < sizeof(struct hwm_sensor_data))) {
316
+ FTS_ERROR("[PROXIMITY]get sensor data parameter error!");
317
+ err = -EINVAL;
318
+ } else {
319
+ sensor_data = (struct hwm_sensor_data *)buff_out;
320
+ sensor_data->values[0] = (int)proximity_data->host_state;
321
+ FTS_DEBUG("sensor_data->values[0] = %d", sensor_data->values[0]);
322
+ sensor_data->value_divide = 1;
323
+ sensor_data->status = SENSOR_STATUS_ACCURACY_MEDIUM;
324
+ }
325
+ break;
326
+ default:
327
+ FTS_ERROR("[PROXIMITY]ps has no operate function:%d!", command);
328
+ err = -EPERM;
329
+ break;
330
+ }
331
+
332
+ return err;
333
+}
334
+#endif
335
+
336
+
337
+static int mtk_proximity_report(struct fts_proximity *proximity_data)
338
+{
339
+ int ret = 0;
340
+ int proximity_state = PROXIMITY_HOST_STATE_DEFAULT;
341
+#if !FTS_ALSPS_SUPPORT
342
+ struct hwm_sensor_data sensor_data;
343
+#endif
344
+
345
+ if (proximity_data->tp_val == PROXIMITY_TP_VAL_NEAR) {
346
+ /* close. need lcd off */
347
+ proximity_state = PROXIMITY_HOST_STATE_NEAR;
348
+ } else if (proximity_data->tp_val == PROXIMITY_TP_VAL_FAR) {
349
+ /* far away */
350
+ proximity_state = PROXIMITY_HOST_STATE_FAR;
351
+ } else if (proximity_data->tp_val == PROXIMITY_TP_VAL_ERROR) {
352
+ /* error, need report far away */
353
+ proximity_state = PROXIMITY_HOST_STATE_FAR;
354
+ }
355
+
356
+ if (proximity_state != proximity_data->host_state) {
357
+ FTS_INFO("report proximity state:%s", proximity_state ? "AWAY" : "NEAR");
358
+ proximity_data->host_state = proximity_state;
359
+#if FTS_ALSPS_SUPPORT
360
+ ret = ps_report_interrupt_data(proximity_state);
361
+#else
362
+ sensor_data.values[0] = proximity_state;
363
+ sensor_data.value_divide = 1;
364
+ sensor_data.status = SENSOR_STATUS_ACCURACY_MEDIUM;
365
+ ret = hwmsen_get_interrupt_data(ID_PROXIMITY, &sensor_data);
366
+ if (ret) {
367
+ FTS_ERROR("[PROXIMITY] Call hwmsen_get_interrupt_data failed, ret=%d", ret);
368
+ return ret;
369
+ }
370
+#endif
371
+ return FTS_RETVAL_IGNORE_TOUCHES;
372
+ }
373
+
374
+ return 0;
375
+}
376
+
377
+static int mtk_proximity_init(struct fts_proximity *proximity_data)
378
+{
379
+#if !FTS_ALSPS_SUPPORT
380
+ int err = 0;
381
+ struct hwmsen_object obj_ps;
382
+#endif
383
+
384
+ FTS_FUNC_ENTER();
385
+#if FTS_ALSPS_SUPPORT
386
+ alsps_driver_add(&ps_init_info);
387
+#else
388
+ obj_ps.polling = 0; /* interrupt mode */
389
+ obj_ps.sensor_operate = mtk_ps_operate;
390
+ err = hwmsen_attach(ID_PROXIMITY, &obj_ps);
391
+ if (err)
392
+ FTS_ERROR("[PROXIMITY]fts proximity attach fail = %d!", err);
393
+ else
394
+ FTS_INFO("[PROXIMITY]fts proximity attach ok = %d\n", err);
395
+#endif
396
+
397
+ FTS_FUNC_EXIT();
398
+ return 0;
399
+}
400
+
401
+struct fts_proximity_ops mtk_proximity_ops = {
402
+ .init = mtk_proximity_init,
403
+ .report = mtk_proximity_report,
404
+};
405
+#endif
406
+
407
+#if (PROXIMITY_SOLUTION == PROXIMITY_SOLUTION_QCOM)
408
+#include <linux/sensors.h>
409
+
410
+struct qcom_proximity {
411
+ struct fts_proximity *proximity_data;
412
+ struct sensors_classdev ps_cdev;
413
+};
414
+
415
+static struct qcom_proximity qcom_proximity_data;
416
+
417
+static struct sensors_classdev __maybe_unused qcom_proximity_cdev = {
418
+ .name = "fts-proximity",
419
+ .vendor = "FocalTech",
420
+ .version = 1,
421
+ .handle = SENSORS_PROXIMITY_HANDLE,
422
+ .type = SENSOR_TYPE_PROXIMITY,
423
+ .max_range = "5.0",
424
+ .resolution = "5.0",
425
+ .sensor_power = "0.1",
426
+ .min_delay = 0,
427
+ .fifo_reserved_event_count = 0,
428
+ .fifo_max_event_count = 0,
429
+ .enabled = 0,
430
+ .delay_msec = 200,
431
+ .sensors_enable = NULL,
432
+ .sensors_poll_delay = NULL,
433
+};
434
+
435
+static int qcom_proximity_enable(struct sensors_classdev *sensors_cdev, unsigned int enable)
436
+{
437
+ struct qcom_proximity *qps = container_of(sensors_cdev, struct qcom_proximity, ps_cdev);
438
+ if (qps && qps->proximity_data) {
439
+ fts_proximity_enable(qps->proximity_data, enable);
440
+ }
441
+ return enable;
442
+}
443
+
444
+static int qcom_proximity_report(struct fts_proximity *proximity_data)
445
+{
446
+ int proximity_state = PROXIMITY_HOST_STATE_DEFAULT;
447
+
448
+ if (!proximity_data || !proximity_data->proximity_input_dev) {
449
+ FTS_ERROR("proximity/input is null");
450
+ return -EINVAL;
451
+ }
452
+
453
+ if (proximity_data->tp_val == PROXIMITY_TP_VAL_NEAR) {
454
+ /* close. need lcd off */
455
+ proximity_state = PROXIMITY_HOST_STATE_NEAR;
456
+ } else if (proximity_data->tp_val == PROXIMITY_TP_VAL_FAR) {
457
+ /* far away */
458
+ proximity_state = PROXIMITY_HOST_STATE_FAR;
459
+ } else if (proximity_data->tp_val == PROXIMITY_TP_VAL_ERROR) {
460
+ /* error, need report far away */
461
+ proximity_state = PROXIMITY_HOST_STATE_FAR;
462
+ }
463
+
464
+ if (proximity_state != proximity_data->host_state) {
465
+ FTS_INFO("report proximity state:%s", proximity_state ? "AWAY" : "NEAR");
466
+ proximity_data->host_state = proximity_state;
467
+ input_report_abs(proximity_data->proximity_input_dev, ABS_DISTANCE,
468
+ (proximity_state == PROXIMITY_HOST_STATE_NEAR) ? 0 : 1;
469
+ input_sync(proximity_data->proximity_input_dev);
470
+ return FTS_RETVAL_IGNORE_TOUCHES;
471
+ }
472
+
473
+ return 0;
474
+}
475
+
476
+static int qcom_proximity_init(struct fts_proximity *proximity_data)
477
+{
478
+ int ret = 0;
479
+ struct qcom_proximity *qps = &qcom_proximity_data;
480
+ FTS_FUNC_ENTER();
481
+ if (proximity_data && proximity_data->ts_data && proximity_data->ts_data->dev) {
482
+ memset(qps, 0, sizeof(struct qcom_proximity));
483
+ qps->proximity_data = proximity_data;
484
+ qps->ps_cdev = qcom_proximity_cdev;
485
+ qps->ps_cdev.sensors_enable = qcom_proximity_enable;
486
+ ret = sensors_classdev_register(proximity_data->ts_data->dev, &qps->ps_cdev);
487
+ if (ret) FTS_ERROR("sensors_classdev_register failed,ret=%d", ret);
488
+ } else {
489
+ FTS_ERROR("proximity/ts/device is null");
490
+ ret = -EINVAL;
491
+ }
492
+ FTS_FUNC_EXIT();
493
+ return ret;
494
+}
495
+
496
+static int qcom_proximity_exit(struct fts_proximity *proximity_data)
497
+{
498
+ FTS_FUNC_ENTER();
499
+ sensors_classdev_unregister(qcom_proximity_data.ps_cdev);
500
+ FTS_FUNC_EXIT();
501
+ return 0;
502
+}
503
+
504
+struct fts_proximity_ops qcom_proximity_ops = {
505
+ .init = qcom_proximity_init,
506
+ .exit = qcom_proximity_exit,
507
+ .report = qcom_proximity_report,
508
+};
509
+#endif // #if (PROXIMITY_SOLUTION == PROXIMITY_SOLUTION_QCOM)
510
+
511
+
512
+#if (PROXIMITY_SOLUTION == PROXIMITY_SOLUTION_SAMPLE_1)
513
+static int sample_1_proximity_report(struct fts_proximity *proximity_data)
514
+{
515
+ u8 clear_status_value = 0xFF;
516
+ int proximity_state = PROXIMITY_HOST_STATE_DEFAULT;
517
+
518
+ if (!proximity_data || !proximity_data->proximity_input_dev) {
519
+ FTS_ERROR("proximity/input is null");
520
+ return -EINVAL;
521
+ }
522
+
523
+ if ((proximity_data->tp_val > 0x00) && (proximity_data->tp_val < 0x04)) {
524
+ /* close. need lcd off */
525
+ proximity_state = PROXIMITY_HOST_STATE_NEAR;
526
+ clear_status_value = 1;
527
+ } else if (proximity_data->tp_val == 0x00) {
528
+ /* far away */
529
+ proximity_state = PROXIMITY_HOST_STATE_FAR;
530
+ clear_status_value = 0;
531
+ } else {
532
+ /* error, need report far away */
533
+ proximity_state = PROXIMITY_HOST_STATE_FAR;
534
+ clear_status_value = 0xEE;
535
+ }
536
+
537
+ if (proximity_data->tp_val != proximity_data->tp_val_last) {
538
+ FTS_DEBUG("tp proximity status:%x->%x", proximity_data->tp_val_last, proximity_data->tp_val);
539
+ tpd_notifier_call_chain(proximity_data->host_state, NULL);
540
+ fts_write_reg(FTS_REG_PSENSOR_CLEAR_STATUS, clear_status_value);
541
+ }
542
+
543
+ if (proximity_state != proximity_data->host_state) {
544
+ FTS_INFO("report proximity state:%s", proximity_state ? "AWAY" : "NEAR");
545
+ proximity_data->host_state = proximity_state;
546
+ return FTS_RETVAL_IGNORE_TOUCHES;
547
+ }
548
+
549
+ return 0;
550
+}
551
+
552
+static struct fts_proximity_ops sample_1_proximity_ops = {
553
+ .report = sample_1_proximity_report,
554
+};
555
+#endif // #if (PROXIMITY_SOLUTION == PROXIMITY_SOLUTION_SAMPLE_1)
556
+
557
+
558
+#if (PROXIMITY_SOLUTION == PROXIMITY_SOLUTION_SAMPLE)
559
+static int sample_proximity_report(struct fts_proximity *proximity_data)
560
+{
561
+ int proximity_state = PROXIMITY_HOST_STATE_DEFAULT;
562
+ if (!proximity_data || !proximity_data->proximity_input_dev) {
563
+ FTS_ERROR("proximity/input is null");
564
+ return -EINVAL;
565
+ }
566
+
567
+ if (proximity_data->tp_val == PROXIMITY_TP_VAL_NEAR) {
568
+ /* close. need lcd off */
569
+ proximity_state = PROXIMITY_HOST_STATE_NEAR;
570
+ } else if (proximity_data->tp_val == PROXIMITY_TP_VAL_FAR) {
571
+ /* far away */
572
+ proximity_state = PROXIMITY_HOST_STATE_FAR;
573
+ } else if (proximity_data->tp_val == PROXIMITY_TP_VAL_ERROR) {
574
+ /* error, need report far away */
575
+ proximity_state = PROXIMITY_HOST_STATE_FAR;
576
+ }
577
+
578
+ if (proximity_data->ts_data->log_level >= 3) {
579
+ FTS_DEBUG("tp proximity status, now:%x,before:%x", proximity_data->tp_val, proximity_data->tp_val_last);
580
+ FTS_DEBUG("proximity state, now:%x,before:%d", proximity_state, proximity_data->host_state);
581
+ }
582
+ if (proximity_state != proximity_data->host_state) {
583
+ FTS_INFO("report proximity state:%s", proximity_state ? "AWAY" : "NEAR");
584
+ proximity_data->host_state = proximity_state;
585
+ /* TODO: Report proximity state to host */
586
+
587
+
588
+ return FTS_RETVAL_IGNORE_TOUCHES;
589
+ }
590
+
591
+ return 0;
592
+}
593
+
594
+static int sample_proximity_init(struct fts_proximity *proximity_data)
595
+{
596
+ FTS_FUNC_ENTER();
597
+ FTS_FUNC_EXIT();
598
+ return 0;
599
+}
600
+
601
+static int sample_proximity_exit(struct fts_proximity *proximity_data)
602
+{
603
+ FTS_FUNC_ENTER();
604
+ FTS_FUNC_EXIT();
605
+ return 0;
606
+}
607
+
608
+static struct fts_proximity_ops sample_proximity_ops = {
609
+ .init = sample_proximity_init,
610
+ .exit = sample_proximity_exit,
611
+ .report = sample_proximity_report,
612
+};
613
+#endif // #if (PROXIMITY_SOLUTION == PROXIMITY_SOLUTION_SAMPLE)
614
+
615
+
616
+static ssize_t fts_proximity_show(struct device *dev, struct device_attribute *attr, char *buf)
617
+{
618
+ int count = 0;
619
+ u8 val = 0;
620
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
621
+ struct fts_proximity *proximity_data = &fts_proximity_data;
622
+
623
+ if (proximity_data->proximity_input_dev) {
624
+ mutex_lock(&proximity_data->proximity_input_dev->mutex);
625
+ fts_read_reg(FTS_REG_PSENSOR_ENABLE, &val);
626
+ count = snprintf(buf, PAGE_SIZE, "Proximity Mode:%s\n", ts_data->proximity_mode ? "On" : "Off");
627
+ count += snprintf(buf + count, PAGE_SIZE, "Reg(0xB0)=%d\n", val);
628
+ mutex_unlock(&proximity_data->proximity_input_dev->mutex);
629
+ }
630
+
631
+ return count;
632
+}
633
+
634
+static ssize_t fts_proximity_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
635
+{
636
+ struct fts_ts_data *ts_data = dev_get_drvdata(dev);
637
+ struct fts_proximity *proximity_data = &fts_proximity_data;
638
+
639
+ if (FTS_SYSFS_ECHO_ON(buf)) {
640
+ if (ts_data->suspended) {
641
+ FTS_INFO("In suspend,not allowed to enable proximity mode");
642
+ } else {
643
+ FTS_DEBUG("enable proximity");
644
+ fts_proximity_enable(proximity_data, ENABLE);
645
+ }
646
+ } else if (FTS_SYSFS_ECHO_OFF(buf)) {
647
+ FTS_DEBUG("disable proximity");
648
+ fts_proximity_enable(proximity_data, DISABLE);
649
+ }
650
+
651
+ return count;
652
+}
653
+
654
+/* sysfs node of proximity_mode, maybe not used */
655
+static DEVICE_ATTR(fts_proximity_mode, S_IRUGO | S_IWUSR, fts_proximity_show, fts_proximity_store);
656
+static struct attribute *fts_proximity_mode_attrs[] = { &dev_attr_fts_proximity_mode.attr, NULL, };
657
+static struct attribute_group fts_proximity_group = {.attrs = fts_proximity_mode_attrs,};
658
+
659
+
660
+static fts_proximity_input_init(struct fts_proximity *proximity_data)
661
+{
662
+ int ret = 0;
663
+ struct input_dev *proximity_input_dev;
664
+
665
+ FTS_FUNC_ENTER();
666
+ if (!proximity_data || !proximity_data->ts_data || !proximity_data->ts_data->dev) {
667
+ FTS_ERROR("proximity_data/ts_data/device is null");
668
+ return -EINVAL;
669
+ }
670
+
671
+ proximity_input_dev = input_allocate_device();
672
+ if (!proximity_input_dev) {
673
+ FTS_ERROR("Failed to allocate memory for input_proximity device");
674
+ return -ENOMEM;
675
+ }
676
+
677
+ proximity_input_dev->dev.parent = proximity_data->ts_data->dev;
678
+ proximity_input_dev->name = "proximity";
679
+ __set_bit(EV_ABS, proximity_input_dev->evbit);
680
+ input_set_abs_params(proximity_input_dev, ABS_DISTANCE, 0, 1, 0, 0);
681
+ ret = input_register_device(proximity_input_dev);
682
+ if (ret) {
683
+ FTS_ERROR("proximity input device registration failed");
684
+ input_free_device(proximity_input_dev);
685
+ proximity_input_dev = NULL;
686
+ return ret;
687
+ }
688
+
689
+ proximity_data->proximity_input_dev = proximity_input_dev;
690
+ FTS_FUNC_EXIT();
691
+ return 0;
692
+}
693
+
694
+int fts_proximity_recovery(struct fts_ts_data *ts_data)
695
+{
696
+ if (ts_data->proximity_mode) {
697
+ fts_proximity_set_reg(ENABLE);
698
+ }
699
+ return 0;
700
+}
701
+
702
+/*****************************************************************************
703
+* Name: fts_proximity_readdata
704
+* Brief: read proximity value from TP, check whether tp is near or far away,
705
+* and report the state to host if need.
706
+*
707
+* Input: ts_data
708
+* Output:
709
+* Return: return negative code if error occurs,return 0 or 1 if success.
710
+* return 0 if continue report finger touches.
711
+* return 1(FTS_RETVAL_IGNORE_TOUCHES) if you want to ingore this
712
+* finger reporting, As default, the following situation will report 1:
713
+* a.proximity state changed
714
+* b.System in suspend state
715
+*****************************************************************************/
716
+int fts_proximity_readdata(struct fts_ts_data *ts_data)
717
+{
718
+ int ret = 0;
719
+ struct fts_proximity *proximity_data = &fts_proximity_data;
720
+ u8 psensor_status = 0xFF;
721
+ u8 psensor_enable = 0xFF;
722
+
723
+ ret = fts_read_reg(FTS_REG_PSENSOR_ENABLE, &psensor_enable);
724
+ if (psensor_enable != ENABLE) {
725
+ FTS_DEBUG("proximity not enable in FW, don't process proximity");
726
+ return 0;
727
+ }
728
+
729
+ ret = fts_read_reg(FTS_REG_PSENSOR_STATUS, &psensor_status);
730
+ if (ret < 0) {
731
+ FTS_ERROR("read proximity value failed,ret=%d", ret);
732
+ proximity_data->tp_val = PROXIMITY_TP_VAL_ERROR;
733
+ } else {
734
+ if (ts_data->log_level >= 3)
735
+ FTS_INFO("read proximity status:0x%x", psensor_status);
736
+ else if (proximity_data->tp_val != psensor_status)
737
+ FTS_INFO("read proximity status:0x%x[%x]", psensor_status, proximity_data->tp_val);
738
+ proximity_data->tp_val = psensor_status;
739
+ }
740
+
741
+ if (proximity_data->ops->report) {
742
+ ret = proximity_data->ops->report(proximity_data);
743
+ }
744
+
745
+ proximity_data->tp_val_last = proximity_data->tp_val;
746
+ if (ts_data->suspended) ret = FTS_RETVAL_IGNORE_TOUCHES;
747
+ return ret;
748
+}
749
+
750
+int fts_proximity_suspend(struct fts_ts_data *ts_data)
751
+{
752
+ if (enable_irq_wake(ts_data->irq)) {
753
+ FTS_ERROR("enable_irq_wake(irq:%d) fail", ts_data->irq);
754
+ }
755
+ FTS_INFO("proximity mode in suspend.");
756
+ return 0;
757
+}
758
+
759
+int fts_proximity_resume(struct fts_ts_data *ts_data)
760
+{
761
+ if (disable_irq_wake(ts_data->irq)) {
762
+ FTS_ERROR("disable_irq_wake(irq:%d) fail", ts_data->irq);
763
+ }
764
+ fts_proximity_recovery(ts_data);
765
+ return 0;
766
+}
767
+
768
+int fts_proximity_init(struct fts_ts_data *ts_data)
769
+{
770
+ int ret = 0;
771
+ struct fts_proximity *proximity_data = &fts_proximity_data;
772
+
773
+ FTS_FUNC_ENTER();
774
+ memset((u8 *)proximity_data, 0, sizeof(struct fts_proximity));
775
+ proximity_data->ts_data = ts_data;
776
+ proximity_data->tp_val = PROXIMITY_TP_VAL_DEFAULT;
777
+ proximity_data->tp_val_last = PROXIMITY_TP_VAL_DEFAULT;
778
+ proximity_data->host_state = PROXIMITY_HOST_STATE_DEFAULT;
779
+
780
+ /* TODO: initialize following platform implementation */
781
+#if (PROXIMITY_SOLUTION == PROXIMITY_SOLUTION_SAMPLE)
782
+ proximity_data->ops = &sample_proximity_ops;
783
+#elif (PROXIMITY_SOLUTION == PROXIMITY_SOLUTION_QCOM)
784
+ proximity_data->ops = &qcom_proximity_ops;
785
+#elif (PROXIMITY_SOLUTION == PROXIMITY_SOLUTION_MTK)
786
+ proximity_data->ops = &mtk_proximity_ops;
787
+#elif (PROXIMITY_SOLUTION == PROXIMITY_SOLUTION_SAMPLE_1)
788
+ proximity_data->ops = &sample_1_proximity_ops;
789
+#endif
790
+
791
+ ret = fts_proximity_input_init(proximity_data);
792
+ if (ret) {
793
+ FTS_ERROR("proximity input init failed");
794
+ return ret;
795
+ }
796
+
797
+ ret = sysfs_create_group(&ts_data->dev->kobj, &fts_proximity_group);
798
+ if (ret) {
799
+ FTS_ERROR("proximity sys node create failed");
800
+ sysfs_remove_group(&ts_data->dev->kobj, &fts_proximity_group);
801
+ }
802
+
803
+ if (proximity_data->ops && proximity_data->ops->init) {
804
+ ret = proximity_data->ops->init(proximity_data);
805
+ if (ret) FTS_ERROR("proximity init failed,ret=%d", ret);
806
+ }
807
+ FTS_FUNC_EXIT();
808
+ return ret;
809
+}
810
+
811
+int fts_proximity_exit(struct fts_ts_data *ts_data)
812
+{
813
+ int ret = 0;
814
+ struct fts_proximity *proximity_data = &fts_proximity_data;
815
+ FTS_FUNC_ENTER();
816
+ sysfs_remove_group(&ts_data->dev->kobj, &fts_proximity_group);
817
+ input_unregister_device(proximity_data->proximity_input_dev);
818
+ if (proximity_data->ops && proximity_data->ops->exit) {
819
+ ret = proximity_data->ops->exit(proximity_data);
820
+ if (ret) FTS_ERROR("proximity exit failed,ret=%d", ret);
821
+ }
822
+ FTS_FUNC_EXIT();
823
+ return ret;
824
+}
825
+#endif /* FTS_PSENSOR_EN */
826
+
827
+
longan/kernel/linux-4.9/drivers/video/fbdev/sunxi/disp2/disp/Makefile
....@@ -29,3 +29,5 @@
2929 lcd/bp101wx1-206.o lcd/m133x56-105.o lcd/m133x56-105-two.o lcd/k101im2qa04.o lcd/k101im2byl02l.o \
3030 conver_chips/lt8911ex.o lcd/K101_IM2BYL02_L_800X1280.o lcd/mipi_8_800x1280.o lcd/mipi_10_800x1280.o
3131 disp-objs += $(obj_low)
32
+
33
+disp-objs += lcd/mipi_5_720x1280.o
longan/kernel/linux-4.9/drivers/video/fbdev/sunxi/disp2/disp/lcd/mipi_5_720x1280.c
....@@ -0,0 +1,392 @@
1
+/* drivers/video/sunxi/disp2/disp/lcd/k101im2qa04.c
2
+ *
3
+ * Copyright (c) 2017 Allwinnertech Co., Ltd.
4
+ * Author: zhengxiaobin <zhengxiaobin@allwinnertech.com>
5
+ *
6
+ * This program is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License version 2 as
8
+ * published by the Free Software Foundation.
9
+*/
10
+#include "mipi_5_720x1280.h"
11
+
12
+static void lcd_power_on(u32 sel);
13
+static void lcd_power_off(u32 sel);
14
+static void lcd_bl_open(u32 sel);
15
+static void lcd_bl_close(u32 sel);
16
+
17
+static void lcd_panel_init1(u32 sel);
18
+static void lcd_panel_init2(u32 sel);
19
+static void lcd_panel_exit(u32 sel);
20
+
21
+#define panel_reset(sel, val) sunxi_lcd_gpio_set_value(sel, 0, val)
22
+
23
+static void lcd_cfg_panel_info(struct panel_extend_para *info)
24
+{
25
+ u32 i = 0, j = 0;
26
+ u32 items;
27
+ u8 lcd_gamma_tbl[][2] = {
28
+ {0, 0},
29
+ {15, 15},
30
+ {30, 30},
31
+ {45, 45},
32
+ {60, 60},
33
+ {75, 75},
34
+ {90, 90},
35
+ {105, 105},
36
+ {120, 120},
37
+ {135, 135},
38
+ {150, 150},
39
+ {165, 165},
40
+ {180, 180},
41
+ {195, 195},
42
+ {210, 210},
43
+ {225, 225},
44
+ {240, 240},
45
+ {255, 255},
46
+ };
47
+
48
+ u32 lcd_cmap_tbl[2][3][4] = {
49
+ {
50
+ {LCD_CMAP_G0, LCD_CMAP_B1, LCD_CMAP_G2, LCD_CMAP_B3},
51
+ {LCD_CMAP_B0, LCD_CMAP_R1, LCD_CMAP_B2, LCD_CMAP_R3},
52
+ {LCD_CMAP_R0, LCD_CMAP_G1, LCD_CMAP_R2, LCD_CMAP_G3},
53
+ },
54
+ {
55
+ {LCD_CMAP_B3, LCD_CMAP_G2, LCD_CMAP_B1, LCD_CMAP_G0},
56
+ {LCD_CMAP_R3, LCD_CMAP_B2, LCD_CMAP_R1, LCD_CMAP_B0},
57
+ {LCD_CMAP_G3, LCD_CMAP_R2, LCD_CMAP_G1, LCD_CMAP_R0},
58
+ },
59
+ };
60
+
61
+ items = sizeof(lcd_gamma_tbl) / 2;
62
+ for (i = 0; i < items - 1; i++) {
63
+ u32 num = lcd_gamma_tbl[i+1][0] - lcd_gamma_tbl[i][0];
64
+
65
+ for (j = 0; j < num; j++) {
66
+ u32 value = 0;
67
+
68
+ value = lcd_gamma_tbl[i][1] +
69
+ ((lcd_gamma_tbl[i+1][1] - lcd_gamma_tbl[i][1])
70
+ * j) / num;
71
+ info->lcd_gamma_tbl[lcd_gamma_tbl[i][0] + j] =
72
+ (value<<16)
73
+ + (value<<8) + value;
74
+ }
75
+ }
76
+ info->lcd_gamma_tbl[255] = (lcd_gamma_tbl[items-1][1]<<16) +
77
+ (lcd_gamma_tbl[items-1][1]<<8)
78
+ + lcd_gamma_tbl[items-1][1];
79
+
80
+ memcpy(info->lcd_cmap_tbl, lcd_cmap_tbl, sizeof(lcd_cmap_tbl));
81
+
82
+}
83
+
84
+static s32 lcd_open_flow(u32 sel)
85
+{
86
+ LCD_OPEN_FUNC(sel, lcd_power_on, 50);
87
+ LCD_OPEN_FUNC(sel, lcd_panel_init1, 50);
88
+ LCD_OPEN_FUNC(sel, lcd_panel_init2, 50);
89
+ LCD_OPEN_FUNC(sel, sunxi_lcd_tcon_enable, 100);
90
+ LCD_OPEN_FUNC(sel, lcd_bl_open, 0);
91
+
92
+ return 0;
93
+}
94
+
95
+static s32 lcd_close_flow(u32 sel)
96
+{
97
+ LCD_CLOSE_FUNC(sel, lcd_bl_close, 0);
98
+ LCD_CLOSE_FUNC(sel, lcd_panel_exit, 1);
99
+ LCD_CLOSE_FUNC(sel, sunxi_lcd_tcon_disable, 10);
100
+ LCD_CLOSE_FUNC(sel, lcd_power_off, 0);
101
+
102
+ return 0;
103
+}
104
+
105
+static void lcd_power_on(u32 sel)
106
+{
107
+
108
+
109
+ panel_reset(sel, 0);
110
+ sunxi_lcd_power_enable(sel, 0);
111
+ sunxi_lcd_pin_cfg(sel, 1);
112
+ //sunxi_lcd_power_enable(sel, 1);
113
+ sunxi_lcd_delay_ms(50);
114
+ panel_reset(sel, 1);
115
+ sunxi_lcd_delay_ms(10);
116
+ panel_reset(sel, 0);
117
+ sunxi_lcd_delay_ms(20);
118
+ panel_reset(sel, 1);
119
+ sunxi_lcd_delay_ms(120);
120
+}
121
+
122
+static void lcd_power_off(u32 sel)
123
+{
124
+ panel_reset(sel, 0);
125
+ sunxi_lcd_delay_ms(1);
126
+ sunxi_lcd_power_disable(sel, 1);
127
+ sunxi_lcd_delay_ms(1);
128
+ sunxi_lcd_power_disable(sel, 0);
129
+ sunxi_lcd_pin_cfg(sel, 0);
130
+}
131
+
132
+static void lcd_bl_open(u32 sel)
133
+{
134
+ sunxi_lcd_pwm_enable(sel);
135
+ sunxi_lcd_backlight_enable(sel);
136
+}
137
+
138
+static void lcd_bl_close(u32 sel)
139
+{
140
+ sunxi_lcd_backlight_disable(sel);
141
+ sunxi_lcd_pwm_disable(sel);
142
+}
143
+
144
+#define ROWS 171
145
+#define COLS 44
146
+
147
+u8 data[ROWS][COLS] = {
148
+ // CMD2 ENABLE
149
+ {0x15, 0x00, 0x02, 0x00, 0x00},
150
+ {0x39, 0x00, 0x04, 0xFF, 0x87, 0x56, 0x01},
151
+ {0x15, 0x00, 0x02, 0x00, 0x80},
152
+ {0x39, 0x00, 0x03, 0xFF, 0x87, 0x56},
153
+ // Panel Resolution 720x1280
154
+ {0x15, 0x00, 0x02, 0x00, 0xA1},
155
+ {0x39, 0x00, 0x07, 0xB3, 0x02, 0xD0, 0x05, 0x00, 0x20, 0xFC},
156
+ // TCON
157
+ {0x15, 0x00, 0x02, 0x00, 0x80},
158
+ {0x39, 0x00, 0x07, 0xC0, 0x00, 0xF6, 0x00, 0x10, 0x00, 0x24},
159
+ {0x15, 0x00, 0x02, 0x00, 0x90},
160
+ {0x39, 0x00, 0x07, 0xC0, 0x00, 0xF6, 0x00, 0x10, 0x00, 0x24},
161
+ {0x15, 0x00, 0x02, 0x00, 0xA0},
162
+ {0x39, 0x00, 0x07, 0xC0, 0x02, 0x14, 0x00, 0x10, 0x00, 0x24},
163
+ {0x15, 0x00, 0x02, 0x00, 0xB0},
164
+ {0x39, 0x00, 0x07, 0xC0, 0x00, 0xF6, 0x00, 0x10, 0x00, 0x24},
165
+ {0x15, 0x00, 0x02, 0x00, 0xC1},
166
+ {0x39, 0x00, 0x09, 0xC0, 0x01, 0x27, 0x00, 0xEA, 0x00, 0xC5, 0x01, 0x5F},
167
+ {0x15, 0x00, 0x02, 0x00, 0xD7},
168
+ {0x39, 0x00, 0x07, 0xC0, 0x00, 0xC5, 0x00, 0x10, 0x00, 0x24},
169
+ {0x15, 0x00, 0x02, 0x00, 0xA3},
170
+ {0x39, 0x00, 0x07, 0xC1, 0x00, 0x20, 0x00, 0x20, 0x00, 0x02},
171
+ {0x15, 0x00, 0x02, 0x00, 0x80},
172
+ {0x39, 0x00, 0x11, 0xCE, 0x01, 0x81, 0x09, 0x13, 0x00, 0x78, 0x00, 0x78, 0x00, 0x50, 0x00, 0x50, 0x00, 0x78, 0x00, 0x78},
173
+ {0x15, 0x00, 0x02, 0x00, 0x90},
174
+ {0x39, 0x00, 0x10, 0xCE, 0x00, 0x8E, 0x0E, 0xB6, 0x00, 0x8E, 0x80, 0x09, 0x13, 0x00, 0x04, 0x00, 0x1C, 0x1F, 0x16},
175
+ {0x15, 0x00, 0x02, 0x00, 0xA0},
176
+ {0x39, 0x00, 0x04, 0xCE, 0x20, 0x00, 0x00},
177
+ {0x15, 0x00, 0x02, 0x00, 0xB0},
178
+ {0x39, 0x00, 0x04, 0xCE, 0x22, 0x00, 0x00},
179
+ {0x15, 0x00, 0x02, 0x00, 0xD1},
180
+ {0x39, 0x00, 0x08, 0xCE, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00},
181
+ {0x15, 0x00, 0x02, 0x00, 0xE1},
182
+ {0x39, 0x00, 0x0C, 0xCE, 0x08, 0x02, 0x4D, 0x02, 0x4D, 0x02, 0x4D, 0x00, 0x00, 0x00, 0x00},
183
+ {0x15, 0x00, 0x02, 0x00, 0xF1},
184
+ {0x39, 0x00, 0x0A, 0xCE, 0x0C, 0x06, 0x0A, 0x00, 0xE9, 0x00, 0xE9, 0x00, 0xF8},
185
+ {0x15, 0x00, 0x02, 0x00, 0xB0},
186
+ {0x39, 0x00, 0x05, 0xCF, 0x00, 0x00, 0x6E, 0x72},
187
+ {0x15, 0x00, 0x02, 0x00, 0xB5},
188
+ {0x39, 0x00, 0x05, 0xCF, 0x02, 0x02, 0x94, 0x98},
189
+ {0x15, 0x00, 0x02, 0x00, 0xC0},
190
+ {0x39, 0x00, 0x05, 0xCF, 0x04, 0x04, 0xD8, 0xDC},
191
+ {0x15, 0x00, 0x02, 0x00, 0xC5},
192
+ {0x39, 0x00, 0x05, 0xCF, 0x00, 0x00, 0x08, 0x0C},
193
+ // Scan Mode
194
+ {0x15, 0x00, 0x02, 0x00, 0xE8},
195
+ {0x15, 0x00, 0x02, 0xC0, 0x40},
196
+ // VST1&VST2
197
+ {0x15, 0x00, 0x02, 0x00, 0x80},
198
+ {0x39, 0x00, 0x09, 0xC2, 0x84, 0x00, 0x05, 0x89, 0x83, 0x00, 0x05, 0x89},
199
+ // CKV1-3
200
+ {0x15, 0x00, 0x02, 0x00, 0xA0},
201
+ {0x39, 0x00, 0x10, 0xC2, 0x82, 0x04, 0x00, 0x05, 0x89, 0x81, 0x04, 0x00, 0x05, 0x89, 0x00, 0x04, 0x00, 0x05, 0x89},
202
+ // CKV4-6
203
+ {0x15, 0x00, 0x02, 0x00, 0xB0},
204
+ {0x39, 0x00, 0x10, 0xC2, 0x01, 0x04, 0x00, 0x05, 0x89, 0x02, 0x04, 0x00, 0x05, 0x89, 0x03, 0x04, 0x00, 0x05, 0x89},
205
+ // CKV7-8
206
+ {0x15, 0x00, 0x02, 0x00, 0xC0},
207
+ {0x39, 0x00, 0x0B, 0xC2, 0x04, 0x04, 0x00, 0x05, 0x89, 0x05, 0x04, 0x00, 0x05, 0x89},
208
+ {0x15, 0x00, 0x02, 0x00, 0xE0},
209
+ {0x39, 0x00, 0x05, 0xC2, 0x77, 0x77, 0x77, 0x77},
210
+ {0x15, 0x00, 0x02, 0x00, 0xC0},
211
+ {0x39, 0x00, 0x05, 0xC3, 0x99, 0x99, 0x99, 0x99},
212
+ {0x15, 0x00, 0x02, 0x00, 0x80},
213
+ {0x39, 0x00, 0x11, 0xCB, 0x00, 0xC5, 0x00, 0x00, 0x05, 0x05, 0x00, 0x05, 0x0A, 0x05, 0xC5, 0x00, 0x05, 0x05, 0x00, 0xC0},
214
+ {0x15, 0x00, 0x02, 0x00, 0x90},
215
+ {0x39, 0x00, 0x11, 0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
216
+ {0x15, 0x00, 0x02, 0x00, 0xA0},
217
+ {0x39, 0x00, 0x05, 0xCB, 0x00, 0x00, 0x00, 0x00},
218
+ {0x15, 0x00, 0x02, 0x00, 0xB0},
219
+ {0x39, 0x00, 0x05, 0xCB, 0x10, 0x51, 0x94, 0x50},
220
+ {0x15, 0x00, 0x02, 0x00, 0xC0},
221
+ {0x39, 0x00, 0x05, 0xCB, 0x10, 0x51, 0x94, 0x50},
222
+ {0x15, 0x00, 0x02, 0x00, 0x80},
223
+ {0x39, 0x00, 0x11, 0xCC, 0x2D, 0x2D, 0x2D, 0x2D, 0x07, 0x09, 0x0B, 0x0D, 0x25, 0x25, 0x03, 0x2D, 0x22, 0x2D, 0x24, 0x2D},
224
+ {0x15, 0x00, 0x02, 0x00, 0x90},
225
+ {0x39, 0x00, 0x09, 0xCC, 0x29, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x26},
226
+ {0x15, 0x00, 0x02, 0x00, 0x80},
227
+ {0x39, 0x00, 0x11, 0xCD, 0x2D, 0x2D, 0x2D, 0x2D, 0x06, 0x08, 0x0A, 0x0C, 0x25, 0x00, 0x02, 0x2D, 0x22, 0x2D, 0x24, 0x2D},
228
+ {0x15, 0x00, 0x02, 0x00, 0x90},
229
+ {0x39, 0x00, 0x09, 0xCD, 0x29, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x26},
230
+ {0x15, 0x00, 0x02, 0x00, 0xA0},
231
+ {0x39, 0x00, 0x11, 0xCC, 0x2D, 0x2D, 0x2D, 0x2D, 0x08, 0x06, 0x0C, 0x0A, 0x25, 0x25, 0x02, 0x2D, 0x24, 0x2D, 0x23, 0x2D},
232
+ {0x15, 0x00, 0x02, 0x00, 0xB0},
233
+ {0x39, 0x00, 0x09, 0xCC, 0x29, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x26},
234
+ {0x15, 0x00, 0x02, 0x00, 0xA0},
235
+ {0x39, 0x00, 0x11, 0xCD, 0x2D, 0x2D, 0x2D, 0x2D, 0x09, 0x07, 0x0D, 0x0B, 0x25, 0x00, 0x03, 0x2D, 0x24, 0x2D, 0x23, 0x2D},
236
+ {0x15, 0x00, 0x02, 0x00, 0xB0},
237
+ {0x39, 0x00, 0x09, 0xCD, 0x29, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x26},
238
+ {0x15, 0x00, 0x02, 0x00, 0x80},
239
+ {0x15, 0x00, 0x02, 0xA7, 0x13},
240
+ {0x15, 0x00, 0x02, 0x00, 0x82},
241
+ {0x39, 0x00, 0x03, 0xA7, 0x22, 0x02},
242
+ {0x15, 0x00, 0x02, 0x00, 0x85},
243
+ {0x15, 0x00, 0x02, 0xC4, 0x1C},
244
+ {0x15, 0x00, 0x02, 0x00, 0xA0},
245
+ {0x39, 0x00, 0x04, 0xC4, 0x8D, 0xD8, 0x8D},
246
+ {0x15, 0x00, 0x02, 0x00, 0x93},
247
+ {0x15, 0x00, 0x02, 0xC5, 0x37},
248
+ {0x15, 0x00, 0x02, 0x00, 0x97},
249
+ {0x15, 0x00, 0x02, 0xC5, 0x37},
250
+ {0x15, 0x00, 0x02, 0x00, 0xB6},
251
+ {0x39, 0x00, 0x03, 0xC5, 0x2D, 0x2D},
252
+ {0x15, 0x00, 0x02, 0x00, 0x9A},
253
+ {0x15, 0x00, 0x02, 0xC5, 0x19},
254
+ {0x15, 0x00, 0x02, 0x00, 0x9C},
255
+ {0x15, 0x00, 0x02, 0xC5, 0x19},
256
+ {0x15, 0x00, 0x02, 0x00, 0x97},
257
+ {0x15, 0x00, 0x02, 0xC4, 0x01},
258
+ {0x15, 0x00, 0x02, 0x00, 0x9B},
259
+ {0x15, 0x00, 0x02, 0xF5, 0x4B},
260
+ {0x15, 0x00, 0x02, 0x00, 0x93},
261
+ {0x39, 0x00, 0x03, 0xF5, 0x00, 0x00},
262
+ {0x15, 0x00, 0x02, 0x00, 0x9D},
263
+ {0x15, 0x00, 0x02, 0xF5, 0x49},
264
+ {0x15, 0x00, 0x02, 0x00, 0x82},
265
+ {0x39, 0x00, 0x03, 0xF5, 0x00, 0x00},
266
+ {0x15, 0x00, 0x02, 0x00, 0x8C},
267
+ {0x39, 0x00, 0x04, 0xC3, 0x00, 0x00, 0x00},
268
+ {0x15, 0x00, 0x02, 0x00, 0x84},
269
+ {0x39, 0x00, 0x03, 0xC5, 0x28, 0x28},
270
+ {0x15, 0x00, 0x02, 0x00, 0xA4},
271
+ {0x15, 0x00, 0x02, 0xD7, 0x00},
272
+ {0x15, 0x00, 0x02, 0x00, 0x80},
273
+ {0x39, 0x00, 0x03, 0xF5, 0x59, 0x59},
274
+ {0x15, 0x00, 0x02, 0x00, 0x84},
275
+ {0x39, 0x00, 0x04, 0xF5, 0x59, 0x59, 0x59},
276
+ {0x15, 0x00, 0x02, 0x00, 0x96},
277
+ {0x15, 0x00, 0x02, 0xF5, 0x59},
278
+ {0x15, 0x00, 0x02, 0x00, 0xA6},
279
+ {0x15, 0x00, 0x02, 0xF5, 0x59},
280
+ {0x15, 0x00, 0x02, 0x00, 0xCA},
281
+ {0x15, 0x00, 0x02, 0xC0, 0x80},
282
+ {0x15, 0x00, 0x02, 0x00, 0xB1},
283
+ {0x15, 0x00, 0x02, 0xF5, 0x1F},
284
+ {0x15, 0x00, 0x02, 0x00, 0x00},
285
+ {0x39, 0x00, 0x03, 0xD8, 0x29, 0x2D},
286
+ {0x15, 0x00, 0x02, 0x00, 0x86},
287
+ {0x39, 0x00, 0x07, 0xC0, 0x01, 0x04, 0x01, 0x01, 0x22, 0x03},
288
+ {0x15, 0x00, 0x02, 0x00, 0x96},
289
+ {0x39, 0x00, 0x07, 0xC0, 0x01, 0x04, 0x01, 0x01, 0x1B, 0x03},
290
+ {0x15, 0x00, 0x02, 0x00, 0xA6},
291
+ {0x39, 0x00, 0x07, 0xC0, 0x01, 0x04, 0x01, 0x01, 0x3E, 0x03},
292
+ {0x15, 0x00, 0x02, 0x00, 0xE9},
293
+ {0x39, 0x00, 0x07, 0xC0, 0x01, 0x04, 0x01, 0x01, 0x1B, 0x03},
294
+ {0x15, 0x00, 0x02, 0x00, 0xA3},
295
+ {0x39, 0x00, 0x07, 0xCE, 0x01, 0x04, 0x01, 0x01, 0x1B, 0x03},
296
+ {0x15, 0x00, 0x02, 0x00, 0xB3},
297
+ {0x39, 0x00, 0x07, 0xCE, 0x01, 0x04, 0x01, 0x01, 0x1B, 0x03},
298
+ // gamma2.2
299
+ {0x15, 0x00, 0x02, 0x00, 0x00},
300
+ {0x39, 0x00, 0x29, 0xE1, 0x05, 0x06, 0x09, 0x10, 0x69, 0x1A, 0x22, 0x28, 0x33, 0x98, 0x3A, 0x41, 0x47, 0x4C, 0xE5, 0x51, 0x59, 0x60, 0x67, 0x05, 0x6E, 0x75, 0x7C, 0x85, 0x08, 0x8F, 0x94, 0x9B, 0xA2, 0x22, 0xAB, 0xB6, 0xC4, 0xCE, 0x9E, 0xDA, 0xEA, 0xF7, 0xFF, 0x7B},
301
+ {0x15, 0x00, 0x02, 0x00, 0x00},
302
+ {0x39, 0x00, 0x29, 0xE2, 0x05, 0x06, 0x09, 0x10, 0x69, 0x1A, 0x22, 0x28, 0x33, 0x98, 0x3A, 0x41, 0x47, 0x4C, 0xE5, 0x51, 0x59, 0x60, 0x67, 0x05, 0x6E, 0x75, 0x7C, 0x85, 0x08, 0x8F, 0x94, 0x9B, 0xA2, 0x22, 0xAB, 0xB6, 0xC4, 0xCE, 0x9E, 0xDA, 0xEA, 0xF7, 0xFF, 0x7B},
303
+ {0x15, 0x00, 0x02, 0x00, 0x00},
304
+ {0x39, 0x00, 0x29, 0xE3, 0x05, 0x06, 0x09, 0x10, 0x69, 0x1A, 0x22, 0x28, 0x33, 0x98, 0x3A, 0x41, 0x47, 0x4C, 0xE5, 0x51, 0x59, 0x60, 0x67, 0x05, 0x6E, 0x75, 0x7C, 0x85, 0x08, 0x8F, 0x94, 0x9B, 0xA2, 0x22, 0xAB, 0xB6, 0xC4, 0xCE, 0x9E, 0xDA, 0xEA, 0xF7, 0xFF, 0x7B},
305
+ {0x15, 0x00, 0x02, 0x00, 0x00},
306
+ {0x39, 0x00, 0x29, 0xE4, 0x05, 0x06, 0x09, 0x10, 0x69, 0x1A, 0x22, 0x28, 0x33, 0x98, 0x3A, 0x41, 0x47, 0x4C, 0xE5, 0x51, 0x59, 0x60, 0x67, 0x05, 0x6E, 0x75, 0x7C, 0x85, 0x08, 0x8F, 0x94, 0x9B, 0xA2, 0x22, 0xAB, 0xB6, 0xC4, 0xCE, 0x9E, 0xDA, 0xEA, 0xF7, 0xFF, 0x7B},
307
+ {0x15, 0x00, 0x02, 0x00, 0x00},
308
+ {0x39, 0x00, 0x29, 0xE5, 0x05, 0x06, 0x09, 0x10, 0x69, 0x1A, 0x22, 0x28, 0x33, 0x98, 0x3A, 0x41, 0x47, 0x4C, 0xE5, 0x51, 0x59, 0x60, 0x67, 0x05, 0x6E, 0x75, 0x7C, 0x85, 0x08, 0x8F, 0x94, 0x9B, 0xA2, 0x22, 0xAB, 0xB6, 0xC4, 0xCE, 0x9E, 0xDA, 0xEA, 0xF7, 0xFF, 0x7B},
309
+ {0x15, 0x00, 0x02, 0x00, 0x00},
310
+ {0x39, 0x00, 0x29, 0xE6, 0x05, 0x06, 0x09, 0x10, 0x69, 0x1A, 0x22, 0x28, 0x33, 0x98, 0x3A, 0x41, 0x47, 0x4C, 0xE5, 0x51, 0x59, 0x60, 0x67, 0x05, 0x6E, 0x75, 0x7C, 0x85, 0x08, 0x8F, 0x94, 0x9B, 0xA2, 0x22, 0xAB, 0xB6, 0xC4, 0xCE, 0x9E, 0xDA, 0xEA, 0xF7, 0xFF, 0x7B},
311
+ // EN GND 4 frame
312
+ {0x15, 0x00, 0x02, 0x00, 0xCC},
313
+ {0x15, 0x00, 0x02, 0xC0, 0x13},
314
+ // LVD detect Voltage
315
+ {0x15, 0x00, 0x02, 0x00, 0x82},
316
+ {0x15, 0x00, 0x02, 0xC5, 0x35},
317
+ {0x15, 0x00, 0x02, 0x00, 0x94},
318
+ {0x39, 0x00, 0x04, 0xC5, 0x02, 0x01, 0x01},
319
+ {0x15, 0x00, 0x02, 0x00, 0x98},
320
+ {0x39, 0x00, 0x03, 0xC5, 0x25, 0x01},
321
+ {0x15, 0x00, 0x02, 0x00, 0x9B},
322
+ {0x15, 0x00, 0x02, 0xC5, 0x21},
323
+ {0x15, 0x00, 0x02, 0x00, 0x9D},
324
+ {0x15, 0x00, 0x02, 0xC5, 0x25},
325
+ // Write ID
326
+ {0x15, 0x00, 0x02, 0x00, 0xD0},
327
+ {0x15, 0x00, 0x02, 0xD0, 0x56},
328
+ //LCD initial code End
329
+ {0x05, 0x78, 0x01, 0x11},
330
+ {0x05, 0x00, 0x01, 0x29},
331
+ {0x15, 0x00, 0x02, 0x35, 0x00}
332
+};
333
+
334
+
335
+static void lcd_panel_init1(u32 sel)
336
+{
337
+ int i;
338
+ u8 command;
339
+ u8 *para;
340
+ u32 para_num;
341
+ u8 *tmp;
342
+ int j;
343
+ printk(KERN_ERR"--kernel!! mipi 720x1280 init\n");
344
+ sunxi_lcd_dsi_clk_enable(sel);
345
+ sunxi_lcd_delay_ms(5);
346
+ for(i = 0; i < ROWS; i++) {
347
+ tmp = data[i];
348
+ if (tmp[0] == 0x05) {
349
+ sunxi_lcd_dsi_dcs_write_0para(sel, tmp[3]);
350
+ } else {
351
+ command = tmp[3];
352
+ para_num = tmp[2] - 1;
353
+ para = tmp + 4;
354
+ sunxi_lcd_dsi_dcs_write(sel, command, para, para_num);
355
+ }
356
+ if (tmp[1] != 0x0)
357
+ sunxi_lcd_delay_ms(tmp[1]);
358
+ }
359
+
360
+}
361
+
362
+static void lcd_panel_init2(u32 sel)
363
+{
364
+}
365
+
366
+
367
+static void lcd_panel_exit(u32 sel)
368
+{
369
+ sunxi_lcd_dsi_dcs_write_0para(sel, 0x28);
370
+ sunxi_lcd_delay_ms(1);
371
+ sunxi_lcd_dsi_dcs_write_0para(sel, 0x10);
372
+ sunxi_lcd_delay_ms(1);
373
+}
374
+
375
+/*sel: 0:lcd0; 1:lcd1*/
376
+static s32 lcd_user_defined_func(u32 sel, u32 para1, u32 para2, u32 para3)
377
+{
378
+ return 0;
379
+}
380
+
381
+__lcd_panel_t mipi_5_720x1280_panel = {
382
+ /* panel driver name, must mach the name of
383
+ * lcd_drv_name in sys_config.fex
384
+ */
385
+ .name = "mipi_5_720x1280",
386
+ .func = {
387
+ .cfg_panel_info = lcd_cfg_panel_info,
388
+ .cfg_open_flow = lcd_open_flow,
389
+ .cfg_close_flow = lcd_close_flow,
390
+ .lcd_user_defined_func = lcd_user_defined_func,
391
+ },
392
+};
longan/kernel/linux-4.9/drivers/video/fbdev/sunxi/disp2/disp/lcd/mipi_5_720x1280.h
....@@ -0,0 +1,23 @@
1
+/* drivers/video/sunxi/disp2/disp/lcd/k101im2qa04.h
2
+ *
3
+ * Copyright (c) 2017 Allwinnertech Co., Ltd.
4
+ * Author: zhengxiaobin <zhengxiaobin@allwinnertech.com>
5
+ *
6
+ * k101im2qa04 panel driver
7
+ *
8
+ * This program is free software; you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License version 2 as
10
+ * published by the Free Software Foundation.
11
+*/
12
+
13
+#ifndef _MIPI_5_720X1280_H
14
+#define _MIPI_5_720X1280_H
15
+
16
+#include "panels.h"
17
+
18
+typedef struct __lcd_panel __lcd_panel_t;
19
+
20
+extern struct __lcd_panel mipi_5_720x1280_panel;
21
+extern s32 bsp_disp_get_panel_info(u32 screen_id, struct disp_panel_para *info);
22
+
23
+#endif /*End of file*/
longan/kernel/linux-4.9/drivers/video/fbdev/sunxi/disp2/disp/lcd/panels.c
....@@ -41,6 +41,7 @@
4141 &K101_IM2BYL02_L_800X1280_mipi_panel,
4242 &mipi_8_800x1280_panel,
4343 &mipi_10_800x1280_panel,
44
+ &mipi_5_720x1280_panel,
4445 NULL,
4546 };
4647
longan/kernel/linux-4.9/drivers/video/fbdev/sunxi/disp2/disp/lcd/panels.h
....@@ -100,4 +100,5 @@
100100 extern struct __lcd_panel K101_IM2BYL02_L_800X1280_mipi_panel;
101101 extern struct __lcd_panel mipi_8_800x1280_panel;
102102 extern struct __lcd_panel mipi_10_800x1280_panel;
103
+extern struct __lcd_panel mipi_5_720x1280_panel;
103104 #endif