feat(mipi): add 5' mipi & touchscreen config
1. add 5' mipi config
2. add FT8756M touchscreen config
8 files modified
21 files added
.. | .. |
---|
53 | 53 | disp-$(CONFIG_LCD_SUPPORT_K101_IM2BYL02_L_800X1280) += lcd/K101_IM2BYL02_L_800X1280.o |
---|
54 | 54 | disp-y += lcd/mipi_8_800x1280.o |
---|
55 | 55 | disp-y += lcd/mipi_10_800x1280.o |
---|
| 56 | +disp-y += lcd/mipi_5_720x1280.o |
---|
56 | 57 | |
---|
57 | 58 | ifeq ($(CONFIG_MACH_SUN8IW6),y) |
---|
58 | 59 | export MIPI_DSI_IP_VERSION := 28 |
---|
.. | .. |
---|
| 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 | +}; |
---|
.. | .. |
---|
| 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*/ |
---|
.. | .. |
---|
138 | 138 | &mipi_8_800x1280_panel, |
---|
139 | 139 | &mipi_10_800x1280_panel, |
---|
140 | 140 | /* add new panel below */ |
---|
141 | | - |
---|
| 141 | + &mipi_5_720x1280_panel, |
---|
142 | 142 | NULL, |
---|
143 | 143 | }; |
---|
144 | 144 | |
---|
.. | .. |
---|
239 | 239 | |
---|
240 | 240 | extern __lcd_panel_t mipi_8_800x1280_panel; |
---|
241 | 241 | extern __lcd_panel_t mipi_10_800x1280_panel; |
---|
| 242 | +extern __lcd_panel_t mipi_5_720x1280_panel; |
---|
242 | 243 | |
---|
243 | 244 | #endif |
---|
.. | .. |
---|
443 | 443 | |
---|
444 | 444 | pmu_chg_ic_temp = <0>; |
---|
445 | 445 | pmu_battery_rdc= <93>; |
---|
446 | | - pmu_battery_cap = <5067>; |
---|
| 446 | + pmu_battery_cap = <5000>; |
---|
447 | 447 | pmu_runtime_chgcur = <1000>; |
---|
448 | 448 | pmu_suspend_chgcur = <2000>; |
---|
449 | 449 | pmu_shutdown_chgcur = <2000>; |
---|
450 | 450 | pmu_init_chgvol = <4200>; |
---|
451 | 451 | pmu_battery_warning_level1 = <15>; |
---|
452 | 452 | pmu_battery_warning_level2 = <0>; |
---|
453 | | - pmu_chgled_func = <0>; |
---|
| 453 | + pmu_chgled_func = <1>; |
---|
454 | 454 | pmu_chgled_type = <0>; |
---|
455 | 455 | ocv_coulumb_100 = <1>; |
---|
456 | 456 | pmu_bat_para1 = <0>; |
---|
.. | .. |
---|
476 | 476 | pmu_bat_para21 = <75>; |
---|
477 | 477 | pmu_bat_para22 = <80>; |
---|
478 | 478 | 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>; |
---|
485 | 485 | pmu_bat_para30 = <100>; |
---|
486 | 486 | pmu_bat_para31 = <100>; |
---|
487 | 487 | pmu_bat_para32 = <100>; |
---|
.. | .. |
---|
1465 | 1465 | |
---|
1466 | 1466 | |
---|
1467 | 1467 | //#include "lcd-lvds-21-1920-1080.dtsi" |
---|
1468 | | -#include "lcd-lvds-7-1024-600.dtsi" |
---|
| 1468 | +//#include "lcd-lvds-7-1024-600.dtsi" |
---|
1469 | 1469 | //#include "lcd-mipi-10-800-1280.dtsi" |
---|
1470 | 1470 | //#include "lcd-mipi-8-800-1280.dtsi" |
---|
| 1471 | +#include "lcd-mipi-5-720-1280.dtsi" |
---|
.. | .. |
---|
| 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 = <®_dc1sw>; |
---|
| 84 | + eldo3-supply = <®_eldo3>; |
---|
| 85 | + dldo2-supply = <®_dldo2>; |
---|
| 86 | + dcdc1-supply = <®_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 | +}; |
---|
.. | .. |
---|
97 | 97 | obj-$(CONFIG_TOUCHSCREEN_FTS_TS) += focaltech_touch/ |
---|
98 | 98 | obj-$(CONFIG_INPUT_TOUCHSCREEN) += gt9xxnew/ |
---|
99 | 99 | obj-$(CONFIG_INPUT_TOUCHSCREEN) += gt9xx/ |
---|
| 100 | +obj-y += focaltech_touch_ft8756/ |
---|
.. | .. |
---|
| 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. |
---|
.. | .. |
---|
| 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
|
---|
.. | .. |
---|
| 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__ */
|
---|
.. | .. |
---|
| 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_ */
|
---|
.. | .. |
---|
| 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, ®val);
|
---|
| 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 | +}
|
---|
.. | .. |
---|
| 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__ */
|
---|
.. | .. |
---|
| 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(®_addr, 1, ®_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, ®_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 | +} |
---|
.. | .. |
---|
| 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(®, 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 | +} |
---|
.. | .. |
---|
| 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, ®_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, ®_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, ®_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, ®_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, ®_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 | +} |
---|
.. | .. |
---|
| 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, ®_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, ®_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 | +}
|
---|
.. | .. |
---|
| 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
|
---|
.. | .. |
---|
| 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 | +}; |
---|
.. | .. |
---|
| 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 | +}
|
---|
.. | .. |
---|
| 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"); |
---|
.. | .. |
---|
| 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 | +} |
---|
.. | .. |
---|
| 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, ®val); |
---|
| 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 | + |
---|
.. | .. |
---|
29 | 29 | lcd/bp101wx1-206.o lcd/m133x56-105.o lcd/m133x56-105-two.o lcd/k101im2qa04.o lcd/k101im2byl02l.o \ |
---|
30 | 30 | conver_chips/lt8911ex.o lcd/K101_IM2BYL02_L_800X1280.o lcd/mipi_8_800x1280.o lcd/mipi_10_800x1280.o |
---|
31 | 31 | disp-objs += $(obj_low) |
---|
| 32 | + |
---|
| 33 | +disp-objs += lcd/mipi_5_720x1280.o |
---|
.. | .. |
---|
| 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 | +}; |
---|
.. | .. |
---|
| 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*/ |
---|
.. | .. |
---|
41 | 41 | &K101_IM2BYL02_L_800X1280_mipi_panel, |
---|
42 | 42 | &mipi_8_800x1280_panel, |
---|
43 | 43 | &mipi_10_800x1280_panel, |
---|
| 44 | + &mipi_5_720x1280_panel, |
---|
44 | 45 | NULL, |
---|
45 | 46 | }; |
---|
46 | 47 | |
---|
.. | .. |
---|
100 | 100 | extern struct __lcd_panel K101_IM2BYL02_L_800X1280_mipi_panel; |
---|
101 | 101 | extern struct __lcd_panel mipi_8_800x1280_panel; |
---|
102 | 102 | extern struct __lcd_panel mipi_10_800x1280_panel; |
---|
| 103 | +extern struct __lcd_panel mipi_5_720x1280_panel; |
---|
103 | 104 | #endif |
---|