Andrew Duggan | ff8f837 | 2016-03-10 15:47:28 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2011-2015 Synaptics Incorporated |
| 3 | * Copyright (c) 2011 Unixphere |
| 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of the GNU General Public License version 2 as published by |
| 7 | * the Free Software Foundation. |
| 8 | */ |
| 9 | |
| 10 | #include <linux/kernel.h> |
| 11 | #include <linux/delay.h> |
| 12 | #include <linux/device.h> |
| 13 | #include <linux/input.h> |
| 14 | #include <linux/input/mt.h> |
| 15 | #include <linux/kconfig.h> |
| 16 | #include <linux/rmi.h> |
| 17 | #include <linux/slab.h> |
| 18 | #include <linux/of.h> |
| 19 | #include "rmi_driver.h" |
| 20 | #include "rmi_2d_sensor.h" |
| 21 | |
| 22 | #define F11_MAX_NUM_OF_FINGERS 10 |
| 23 | #define F11_MAX_NUM_OF_TOUCH_SHAPES 16 |
| 24 | |
| 25 | #define FINGER_STATE_MASK 0x03 |
| 26 | |
| 27 | #define F11_CTRL_SENSOR_MAX_X_POS_OFFSET 6 |
| 28 | #define F11_CTRL_SENSOR_MAX_Y_POS_OFFSET 8 |
| 29 | |
| 30 | #define DEFAULT_XY_MAX 9999 |
| 31 | #define DEFAULT_MAX_ABS_MT_PRESSURE 255 |
| 32 | #define DEFAULT_MAX_ABS_MT_TOUCH 15 |
| 33 | #define DEFAULT_MAX_ABS_MT_ORIENTATION 1 |
| 34 | #define DEFAULT_MIN_ABS_MT_TRACKING_ID 1 |
| 35 | #define DEFAULT_MAX_ABS_MT_TRACKING_ID 10 |
| 36 | |
| 37 | /** A note about RMI4 F11 register structure. |
| 38 | * |
| 39 | * The properties for |
| 40 | * a given sensor are described by its query registers. The number of query |
| 41 | * registers and the layout of their contents are described by the F11 device |
| 42 | * queries as well as the sensor query information. |
| 43 | * |
| 44 | * Similarly, each sensor has control registers that govern its behavior. The |
| 45 | * size and layout of the control registers for a given sensor can be determined |
| 46 | * by parsing that sensors query registers. |
| 47 | * |
| 48 | * And in a likewise fashion, each sensor has data registers where it reports |
| 49 | * its touch data and other interesting stuff. The size and layout of a |
| 50 | * sensors data registers must be determined by parsing its query registers. |
| 51 | * |
| 52 | * The short story is that we need to read and parse a lot of query |
| 53 | * registers in order to determine the attributes of a sensor. Then |
| 54 | * we need to use that data to compute the size of the control and data |
| 55 | * registers for sensor. |
| 56 | * |
| 57 | * The end result is that we have a number of structs that aren't used to |
| 58 | * directly generate the input events, but their size, location and contents |
| 59 | * are critical to determining where the data we are interested in lives. |
| 60 | * |
| 61 | * At this time, the driver does not yet comprehend all possible F11 |
| 62 | * configuration options, but it should be sufficient to cover 99% of RMI4 F11 |
| 63 | * devices currently in the field. |
| 64 | */ |
| 65 | |
| 66 | /* maximum ABS_MT_POSITION displacement (in mm) */ |
| 67 | #define DMAX 10 |
| 68 | |
| 69 | /** |
| 70 | * @rezero - writing this to the F11 command register will cause the sensor to |
| 71 | * calibrate to the current capacitive state. |
| 72 | */ |
| 73 | #define RMI_F11_REZERO 0x01 |
| 74 | |
| 75 | #define RMI_F11_HAS_QUERY9 (1 << 3) |
| 76 | #define RMI_F11_HAS_QUERY11 (1 << 4) |
| 77 | #define RMI_F11_HAS_QUERY12 (1 << 5) |
| 78 | #define RMI_F11_HAS_QUERY27 (1 << 6) |
| 79 | #define RMI_F11_HAS_QUERY28 (1 << 7) |
| 80 | |
| 81 | /** Defs for Query 1 */ |
| 82 | |
| 83 | #define RMI_F11_NR_FINGERS_MASK 0x07 |
| 84 | #define RMI_F11_HAS_REL (1 << 3) |
| 85 | #define RMI_F11_HAS_ABS (1 << 4) |
| 86 | #define RMI_F11_HAS_GESTURES (1 << 5) |
| 87 | #define RMI_F11_HAS_SENSITIVITY_ADJ (1 << 6) |
| 88 | #define RMI_F11_CONFIGURABLE (1 << 7) |
| 89 | |
| 90 | /** Defs for Query 2, 3, and 4. */ |
| 91 | #define RMI_F11_NR_ELECTRODES_MASK 0x7F |
| 92 | |
| 93 | /** Defs for Query 5 */ |
| 94 | |
| 95 | #define RMI_F11_ABS_DATA_SIZE_MASK 0x03 |
| 96 | #define RMI_F11_HAS_ANCHORED_FINGER (1 << 2) |
| 97 | #define RMI_F11_HAS_ADJ_HYST (1 << 3) |
| 98 | #define RMI_F11_HAS_DRIBBLE (1 << 4) |
| 99 | #define RMI_F11_HAS_BENDING_CORRECTION (1 << 5) |
| 100 | #define RMI_F11_HAS_LARGE_OBJECT_SUPPRESSION (1 << 6) |
| 101 | #define RMI_F11_HAS_JITTER_FILTER (1 << 7) |
| 102 | |
| 103 | /** Defs for Query 7 */ |
| 104 | #define RMI_F11_HAS_SINGLE_TAP (1 << 0) |
| 105 | #define RMI_F11_HAS_TAP_AND_HOLD (1 << 1) |
| 106 | #define RMI_F11_HAS_DOUBLE_TAP (1 << 2) |
| 107 | #define RMI_F11_HAS_EARLY_TAP (1 << 3) |
| 108 | #define RMI_F11_HAS_FLICK (1 << 4) |
| 109 | #define RMI_F11_HAS_PRESS (1 << 5) |
| 110 | #define RMI_F11_HAS_PINCH (1 << 6) |
| 111 | #define RMI_F11_HAS_CHIRAL (1 << 7) |
| 112 | |
| 113 | /** Defs for Query 8 */ |
| 114 | #define RMI_F11_HAS_PALM_DET (1 << 0) |
| 115 | #define RMI_F11_HAS_ROTATE (1 << 1) |
| 116 | #define RMI_F11_HAS_TOUCH_SHAPES (1 << 2) |
| 117 | #define RMI_F11_HAS_SCROLL_ZONES (1 << 3) |
| 118 | #define RMI_F11_HAS_INDIVIDUAL_SCROLL_ZONES (1 << 4) |
| 119 | #define RMI_F11_HAS_MF_SCROLL (1 << 5) |
| 120 | #define RMI_F11_HAS_MF_EDGE_MOTION (1 << 6) |
| 121 | #define RMI_F11_HAS_MF_SCROLL_INERTIA (1 << 7) |
| 122 | |
| 123 | /** Defs for Query 9. */ |
| 124 | #define RMI_F11_HAS_PEN (1 << 0) |
| 125 | #define RMI_F11_HAS_PROXIMITY (1 << 1) |
| 126 | #define RMI_F11_HAS_PALM_DET_SENSITIVITY (1 << 2) |
| 127 | #define RMI_F11_HAS_SUPPRESS_ON_PALM_DETECT (1 << 3) |
| 128 | #define RMI_F11_HAS_TWO_PEN_THRESHOLDS (1 << 4) |
| 129 | #define RMI_F11_HAS_CONTACT_GEOMETRY (1 << 5) |
| 130 | #define RMI_F11_HAS_PEN_HOVER_DISCRIMINATION (1 << 6) |
| 131 | #define RMI_F11_HAS_PEN_FILTERS (1 << 7) |
| 132 | |
| 133 | /** Defs for Query 10. */ |
| 134 | #define RMI_F11_NR_TOUCH_SHAPES_MASK 0x1F |
| 135 | |
| 136 | /** Defs for Query 11 */ |
| 137 | |
| 138 | #define RMI_F11_HAS_Z_TUNING (1 << 0) |
| 139 | #define RMI_F11_HAS_ALGORITHM_SELECTION (1 << 1) |
| 140 | #define RMI_F11_HAS_W_TUNING (1 << 2) |
| 141 | #define RMI_F11_HAS_PITCH_INFO (1 << 3) |
| 142 | #define RMI_F11_HAS_FINGER_SIZE (1 << 4) |
| 143 | #define RMI_F11_HAS_SEGMENTATION_AGGRESSIVENESS (1 << 5) |
| 144 | #define RMI_F11_HAS_XY_CLIP (1 << 6) |
| 145 | #define RMI_F11_HAS_DRUMMING_FILTER (1 << 7) |
| 146 | |
| 147 | /** Defs for Query 12. */ |
| 148 | |
| 149 | #define RMI_F11_HAS_GAPLESS_FINGER (1 << 0) |
| 150 | #define RMI_F11_HAS_GAPLESS_FINGER_TUNING (1 << 1) |
| 151 | #define RMI_F11_HAS_8BIT_W (1 << 2) |
| 152 | #define RMI_F11_HAS_ADJUSTABLE_MAPPING (1 << 3) |
| 153 | #define RMI_F11_HAS_INFO2 (1 << 4) |
| 154 | #define RMI_F11_HAS_PHYSICAL_PROPS (1 << 5) |
| 155 | #define RMI_F11_HAS_FINGER_LIMIT (1 << 6) |
| 156 | #define RMI_F11_HAS_LINEAR_COEFF (1 << 7) |
| 157 | |
| 158 | /** Defs for Query 13. */ |
| 159 | |
| 160 | #define RMI_F11_JITTER_WINDOW_MASK 0x1F |
| 161 | #define RMI_F11_JITTER_FILTER_MASK 0x60 |
| 162 | #define RMI_F11_JITTER_FILTER_SHIFT 5 |
| 163 | |
| 164 | /** Defs for Query 14. */ |
| 165 | #define RMI_F11_LIGHT_CONTROL_MASK 0x03 |
| 166 | #define RMI_F11_IS_CLEAR (1 << 2) |
| 167 | #define RMI_F11_CLICKPAD_PROPS_MASK 0x18 |
| 168 | #define RMI_F11_CLICKPAD_PROPS_SHIFT 3 |
| 169 | #define RMI_F11_MOUSE_BUTTONS_MASK 0x60 |
| 170 | #define RMI_F11_MOUSE_BUTTONS_SHIFT 5 |
| 171 | #define RMI_F11_HAS_ADVANCED_GESTURES (1 << 7) |
| 172 | |
| 173 | #define RMI_F11_QUERY_SIZE 4 |
| 174 | #define RMI_F11_QUERY_GESTURE_SIZE 2 |
| 175 | |
| 176 | #define F11_LIGHT_CTL_NONE 0x00 |
| 177 | #define F11_LUXPAD 0x01 |
| 178 | #define F11_DUAL_MODE 0x02 |
| 179 | |
| 180 | #define F11_NOT_CLICKPAD 0x00 |
| 181 | #define F11_HINGED_CLICKPAD 0x01 |
| 182 | #define F11_UNIFORM_CLICKPAD 0x02 |
| 183 | |
| 184 | /** |
| 185 | * Query registers 1 through 4 are always present. |
| 186 | * |
| 187 | * @nr_fingers - describes the maximum number of fingers the 2-D sensor |
| 188 | * supports. |
| 189 | * @has_rel - the sensor supports relative motion reporting. |
| 190 | * @has_abs - the sensor supports absolute poition reporting. |
| 191 | * @has_gestures - the sensor supports gesture reporting. |
| 192 | * @has_sensitivity_adjust - the sensor supports a global sensitivity |
| 193 | * adjustment. |
| 194 | * @configurable - the sensor supports various configuration options. |
| 195 | * @num_of_x_electrodes - the maximum number of electrodes the 2-D sensor |
| 196 | * supports on the X axis. |
| 197 | * @num_of_y_electrodes - the maximum number of electrodes the 2-D sensor |
| 198 | * supports on the Y axis. |
| 199 | * @max_electrodes - the total number of X and Y electrodes that may be |
| 200 | * configured. |
| 201 | * |
| 202 | * Query 5 is present if the has_abs bit is set. |
| 203 | * |
| 204 | * @abs_data_size - describes the format of data reported by the absolute |
| 205 | * data source. Only one format (the kind used here) is supported at this |
| 206 | * time. |
| 207 | * @has_anchored_finger - then the sensor supports the high-precision second |
| 208 | * finger tracking provided by the manual tracking and motion sensitivity |
| 209 | * options. |
| 210 | * @has_adjust_hyst - the difference between the finger release threshold and |
| 211 | * the touch threshold. |
| 212 | * @has_dribble - the sensor supports the generation of dribble interrupts, |
| 213 | * which may be enabled or disabled with the dribble control bit. |
| 214 | * @has_bending_correction - Bending related data registers 28 and 36, and |
| 215 | * control register 52..57 are present. |
| 216 | * @has_large_object_suppression - control register 58 and data register 28 |
| 217 | * exist. |
| 218 | * @has_jitter_filter - query 13 and control 73..76 exist. |
| 219 | * |
| 220 | * Gesture information queries 7 and 8 are present if has_gestures bit is set. |
| 221 | * |
| 222 | * @has_single_tap - a basic single-tap gesture is supported. |
| 223 | * @has_tap_n_hold - tap-and-hold gesture is supported. |
| 224 | * @has_double_tap - double-tap gesture is supported. |
| 225 | * @has_early_tap - early tap is supported and reported as soon as the finger |
| 226 | * lifts for any tap event that could be interpreted as either a single tap |
| 227 | * or as the first tap of a double-tap or tap-and-hold gesture. |
| 228 | * @has_flick - flick detection is supported. |
| 229 | * @has_press - press gesture reporting is supported. |
| 230 | * @has_pinch - pinch gesture detection is supported. |
| 231 | * @has_palm_det - the 2-D sensor notifies the host whenever a large conductive |
| 232 | * object such as a palm or a cheek touches the 2-D sensor. |
| 233 | * @has_rotate - rotation gesture detection is supported. |
| 234 | * @has_touch_shapes - TouchShapes are supported. A TouchShape is a fixed |
| 235 | * rectangular area on the sensor that behaves like a capacitive button. |
| 236 | * @has_scroll_zones - scrolling areas near the sensor edges are supported. |
| 237 | * @has_individual_scroll_zones - if 1, then 4 scroll zones are supported; |
| 238 | * if 0, then only two are supported. |
| 239 | * @has_mf_scroll - the multifinger_scrolling bit will be set when |
| 240 | * more than one finger is involved in a scrolling action. |
| 241 | * |
| 242 | * Convenience for checking bytes in the gesture info registers. This is done |
| 243 | * often enough that we put it here to declutter the conditionals |
| 244 | * |
| 245 | * @query7_nonzero - true if none of the query 7 bits are set |
| 246 | * @query8_nonzero - true if none of the query 8 bits are set |
| 247 | * |
| 248 | * Query 9 is present if the has_query9 is set. |
| 249 | * |
| 250 | * @has_pen - detection of a stylus is supported and registers F11_2D_Ctrl20 |
| 251 | * and F11_2D_Ctrl21 exist. |
| 252 | * @has_proximity - detection of fingers near the sensor is supported and |
| 253 | * registers F11_2D_Ctrl22 through F11_2D_Ctrl26 exist. |
| 254 | * @has_palm_det_sensitivity - the sensor supports the palm detect sensitivity |
| 255 | * feature and register F11_2D_Ctrl27 exists. |
| 256 | * @has_two_pen_thresholds - is has_pen is also set, then F11_2D_Ctrl35 exists. |
| 257 | * @has_contact_geometry - the sensor supports the use of contact geometry to |
| 258 | * map absolute X and Y target positions and registers F11_2D_Data18 |
| 259 | * through F11_2D_Data27 exist. |
| 260 | * |
| 261 | * Touch shape info (query 10) is present if has_touch_shapes is set. |
| 262 | * |
| 263 | * @nr_touch_shapes - the total number of touch shapes supported. |
| 264 | * |
| 265 | * Query 11 is present if the has_query11 bit is set in query 0. |
| 266 | * |
| 267 | * @has_z_tuning - if set, the sensor supports Z tuning and registers |
| 268 | * F11_2D_Ctrl29 through F11_2D_Ctrl33 exist. |
| 269 | * @has_algorithm_selection - controls choice of noise suppression algorithm |
| 270 | * @has_w_tuning - the sensor supports Wx and Wy scaling and registers |
| 271 | * F11_2D_Ctrl36 through F11_2D_Ctrl39 exist. |
| 272 | * @has_pitch_info - the X and Y pitches of the sensor electrodes can be |
| 273 | * configured and registers F11_2D_Ctrl40 and F11_2D_Ctrl41 exist. |
| 274 | * @has_finger_size - the default finger width settings for the |
| 275 | * sensor can be configured and registers F11_2D_Ctrl42 through F11_2D_Ctrl44 |
| 276 | * exist. |
| 277 | * @has_segmentation_aggressiveness - the sensor’s ability to distinguish |
| 278 | * multiple objects close together can be configured and register F11_2D_Ctrl45 |
| 279 | * exists. |
| 280 | * @has_XY_clip - the inactive outside borders of the sensor can be |
| 281 | * configured and registers F11_2D_Ctrl46 through F11_2D_Ctrl49 exist. |
| 282 | * @has_drumming_filter - the sensor can be configured to distinguish |
| 283 | * between a fast flick and a quick drumming movement and registers |
| 284 | * F11_2D_Ctrl50 and F11_2D_Ctrl51 exist. |
| 285 | * |
| 286 | * Query 12 is present if hasQuery12 bit is set. |
| 287 | * |
| 288 | * @has_gapless_finger - control registers relating to gapless finger are |
| 289 | * present. |
| 290 | * @has_gapless_finger_tuning - additional control and data registers relating |
| 291 | * to gapless finger are present. |
| 292 | * @has_8bit_w - larger W value reporting is supported. |
| 293 | * @has_adjustable_mapping - TBD |
| 294 | * @has_info2 - the general info query14 is present |
| 295 | * @has_physical_props - additional queries describing the physical properties |
| 296 | * of the sensor are present. |
| 297 | * @has_finger_limit - indicates that F11 Ctrl 80 exists. |
| 298 | * @has_linear_coeff - indicates that F11 Ctrl 81 exists. |
| 299 | * |
| 300 | * Query 13 is present if Query 5's has_jitter_filter bit is set. |
| 301 | * @jitter_window_size - used by Design Studio 4. |
| 302 | * @jitter_filter_type - used by Design Studio 4. |
| 303 | * |
| 304 | * Query 14 is present if query 12's has_general_info2 flag is set. |
| 305 | * |
| 306 | * @light_control - Indicates what light/led control features are present, if |
| 307 | * any. |
| 308 | * @is_clear - if set, this is a clear sensor (indicating direct pointing |
| 309 | * application), otherwise it's opaque (indicating indirect pointing). |
| 310 | * @clickpad_props - specifies if this is a clickpad, and if so what sort of |
| 311 | * mechanism it uses |
| 312 | * @mouse_buttons - specifies the number of mouse buttons present (if any). |
| 313 | * @has_advanced_gestures - advanced driver gestures are supported. |
| 314 | */ |
| 315 | struct f11_2d_sensor_queries { |
| 316 | /* query1 */ |
| 317 | u8 nr_fingers; |
| 318 | bool has_rel; |
| 319 | bool has_abs; |
| 320 | bool has_gestures; |
| 321 | bool has_sensitivity_adjust; |
| 322 | bool configurable; |
| 323 | |
| 324 | /* query2 */ |
| 325 | u8 nr_x_electrodes; |
| 326 | |
| 327 | /* query3 */ |
| 328 | u8 nr_y_electrodes; |
| 329 | |
| 330 | /* query4 */ |
| 331 | u8 max_electrodes; |
| 332 | |
| 333 | /* query5 */ |
| 334 | u8 abs_data_size; |
| 335 | bool has_anchored_finger; |
| 336 | bool has_adj_hyst; |
| 337 | bool has_dribble; |
| 338 | bool has_bending_correction; |
| 339 | bool has_large_object_suppression; |
| 340 | bool has_jitter_filter; |
| 341 | |
| 342 | u8 f11_2d_query6; |
| 343 | |
| 344 | /* query 7 */ |
| 345 | bool has_single_tap; |
| 346 | bool has_tap_n_hold; |
| 347 | bool has_double_tap; |
| 348 | bool has_early_tap; |
| 349 | bool has_flick; |
| 350 | bool has_press; |
| 351 | bool has_pinch; |
| 352 | bool has_chiral; |
| 353 | |
| 354 | bool query7_nonzero; |
| 355 | |
| 356 | /* query 8 */ |
| 357 | bool has_palm_det; |
| 358 | bool has_rotate; |
| 359 | bool has_touch_shapes; |
| 360 | bool has_scroll_zones; |
| 361 | bool has_individual_scroll_zones; |
| 362 | bool has_mf_scroll; |
| 363 | bool has_mf_edge_motion; |
| 364 | bool has_mf_scroll_inertia; |
| 365 | |
| 366 | bool query8_nonzero; |
| 367 | |
| 368 | /* Query 9 */ |
| 369 | bool has_pen; |
| 370 | bool has_proximity; |
| 371 | bool has_palm_det_sensitivity; |
| 372 | bool has_suppress_on_palm_detect; |
| 373 | bool has_two_pen_thresholds; |
| 374 | bool has_contact_geometry; |
| 375 | bool has_pen_hover_discrimination; |
| 376 | bool has_pen_filters; |
| 377 | |
| 378 | /* Query 10 */ |
| 379 | u8 nr_touch_shapes; |
| 380 | |
| 381 | /* Query 11. */ |
| 382 | bool has_z_tuning; |
| 383 | bool has_algorithm_selection; |
| 384 | bool has_w_tuning; |
| 385 | bool has_pitch_info; |
| 386 | bool has_finger_size; |
| 387 | bool has_segmentation_aggressiveness; |
| 388 | bool has_XY_clip; |
| 389 | bool has_drumming_filter; |
| 390 | |
| 391 | /* Query 12 */ |
| 392 | bool has_gapless_finger; |
| 393 | bool has_gapless_finger_tuning; |
| 394 | bool has_8bit_w; |
| 395 | bool has_adjustable_mapping; |
| 396 | bool has_info2; |
| 397 | bool has_physical_props; |
| 398 | bool has_finger_limit; |
| 399 | bool has_linear_coeff_2; |
| 400 | |
| 401 | /* Query 13 */ |
| 402 | u8 jitter_window_size; |
| 403 | u8 jitter_filter_type; |
| 404 | |
| 405 | /* Query 14 */ |
| 406 | u8 light_control; |
| 407 | bool is_clear; |
| 408 | u8 clickpad_props; |
| 409 | u8 mouse_buttons; |
| 410 | bool has_advanced_gestures; |
| 411 | |
| 412 | /* Query 15 - 18 */ |
| 413 | u16 x_sensor_size_mm; |
| 414 | u16 y_sensor_size_mm; |
| 415 | }; |
| 416 | |
| 417 | /* Defs for Ctrl0. */ |
| 418 | #define RMI_F11_REPORT_MODE_MASK 0x07 |
| 419 | #define RMI_F11_ABS_POS_FILT (1 << 3) |
| 420 | #define RMI_F11_REL_POS_FILT (1 << 4) |
| 421 | #define RMI_F11_REL_BALLISTICS (1 << 5) |
| 422 | #define RMI_F11_DRIBBLE (1 << 6) |
| 423 | #define RMI_F11_REPORT_BEYOND_CLIP (1 << 7) |
| 424 | |
| 425 | /* Defs for Ctrl1. */ |
| 426 | #define RMI_F11_PALM_DETECT_THRESH_MASK 0x0F |
| 427 | #define RMI_F11_MOTION_SENSITIVITY_MASK 0x30 |
| 428 | #define RMI_F11_MANUAL_TRACKING (1 << 6) |
| 429 | #define RMI_F11_MANUAL_TRACKED_FINGER (1 << 7) |
| 430 | |
| 431 | #define RMI_F11_DELTA_X_THRESHOLD 2 |
| 432 | #define RMI_F11_DELTA_Y_THRESHOLD 3 |
| 433 | |
| 434 | #define RMI_F11_CTRL_REG_COUNT 12 |
| 435 | |
| 436 | struct f11_2d_ctrl { |
| 437 | u8 ctrl0_11[RMI_F11_CTRL_REG_COUNT]; |
| 438 | u16 ctrl0_11_address; |
| 439 | }; |
| 440 | |
| 441 | #define RMI_F11_ABS_BYTES 5 |
| 442 | #define RMI_F11_REL_BYTES 2 |
| 443 | |
| 444 | /* Defs for Data 8 */ |
| 445 | |
| 446 | #define RMI_F11_SINGLE_TAP (1 << 0) |
| 447 | #define RMI_F11_TAP_AND_HOLD (1 << 1) |
| 448 | #define RMI_F11_DOUBLE_TAP (1 << 2) |
| 449 | #define RMI_F11_EARLY_TAP (1 << 3) |
| 450 | #define RMI_F11_FLICK (1 << 4) |
| 451 | #define RMI_F11_PRESS (1 << 5) |
| 452 | #define RMI_F11_PINCH (1 << 6) |
| 453 | |
| 454 | /* Defs for Data 9 */ |
| 455 | |
| 456 | #define RMI_F11_PALM_DETECT (1 << 0) |
| 457 | #define RMI_F11_ROTATE (1 << 1) |
| 458 | #define RMI_F11_SHAPE (1 << 2) |
| 459 | #define RMI_F11_SCROLLZONE (1 << 3) |
| 460 | #define RMI_F11_GESTURE_FINGER_COUNT_MASK 0x70 |
| 461 | |
| 462 | /** Handy pointers into our data buffer. |
| 463 | * |
| 464 | * @f_state - start of finger state registers. |
| 465 | * @abs_pos - start of absolute position registers (if present). |
| 466 | * @rel_pos - start of relative data registers (if present). |
| 467 | * @gest_1 - gesture flags (if present). |
| 468 | * @gest_2 - gesture flags & finger count (if present). |
| 469 | * @pinch - pinch motion register (if present). |
| 470 | * @flick - flick distance X & Y, flick time (if present). |
| 471 | * @rotate - rotate motion and finger separation. |
| 472 | * @multi_scroll - chiral deltas for X and Y (if present). |
| 473 | * @scroll_zones - scroll deltas for 4 regions (if present). |
| 474 | */ |
| 475 | struct f11_2d_data { |
| 476 | u8 *f_state; |
| 477 | u8 *abs_pos; |
| 478 | s8 *rel_pos; |
| 479 | u8 *gest_1; |
| 480 | u8 *gest_2; |
| 481 | s8 *pinch; |
| 482 | u8 *flick; |
| 483 | u8 *rotate; |
| 484 | u8 *shapes; |
| 485 | s8 *multi_scroll; |
| 486 | s8 *scroll_zones; |
| 487 | }; |
| 488 | |
| 489 | /** Data pertaining to F11 in general. For per-sensor data, see struct |
| 490 | * f11_2d_sensor. |
| 491 | * |
| 492 | * @dev_query - F11 device specific query registers. |
| 493 | * @dev_controls - F11 device specific control registers. |
| 494 | * @dev_controls_mutex - lock for the control registers. |
| 495 | * @rezero_wait_ms - if nonzero, upon resume we will wait this many |
| 496 | * milliseconds before rezeroing the sensor(s). This is useful in systems with |
| 497 | * poor electrical behavior on resume, where the initial calibration of the |
| 498 | * sensor(s) coming out of sleep state may be bogus. |
| 499 | * @sensors - per sensor data structures. |
| 500 | */ |
| 501 | struct f11_data { |
| 502 | bool has_query9; |
| 503 | bool has_query11; |
| 504 | bool has_query12; |
| 505 | bool has_query27; |
| 506 | bool has_query28; |
| 507 | bool has_acm; |
| 508 | struct f11_2d_ctrl dev_controls; |
| 509 | struct mutex dev_controls_mutex; |
| 510 | u16 rezero_wait_ms; |
| 511 | struct rmi_2d_sensor sensor; |
| 512 | struct f11_2d_sensor_queries sens_query; |
| 513 | struct f11_2d_data data; |
| 514 | struct rmi_2d_sensor_platform_data sensor_pdata; |
| 515 | unsigned long *abs_mask; |
| 516 | unsigned long *rel_mask; |
| 517 | unsigned long *result_bits; |
| 518 | }; |
| 519 | |
| 520 | enum f11_finger_state { |
| 521 | F11_NO_FINGER = 0x00, |
| 522 | F11_PRESENT = 0x01, |
| 523 | F11_INACCURATE = 0x02, |
| 524 | F11_RESERVED = 0x03 |
| 525 | }; |
| 526 | |
| 527 | static void rmi_f11_rel_pos_report(struct f11_data *f11, u8 n_finger) |
| 528 | { |
| 529 | struct rmi_2d_sensor *sensor = &f11->sensor; |
| 530 | struct f11_2d_data *data = &f11->data; |
| 531 | s8 x, y; |
| 532 | |
Andrew Duggan | 345ded8 | 2016-07-14 09:38:59 -0700 | [diff] [blame] | 533 | x = data->rel_pos[n_finger * RMI_F11_REL_BYTES]; |
| 534 | y = data->rel_pos[n_finger * RMI_F11_REL_BYTES + 1]; |
Andrew Duggan | ff8f837 | 2016-03-10 15:47:28 -0800 | [diff] [blame] | 535 | |
| 536 | rmi_2d_sensor_rel_report(sensor, x, y); |
| 537 | } |
| 538 | |
| 539 | static void rmi_f11_abs_pos_process(struct f11_data *f11, |
| 540 | struct rmi_2d_sensor *sensor, |
| 541 | struct rmi_2d_sensor_abs_object *obj, |
| 542 | enum f11_finger_state finger_state, |
| 543 | u8 n_finger) |
| 544 | { |
| 545 | struct f11_2d_data *data = &f11->data; |
| 546 | u8 *pos_data = &data->abs_pos[n_finger * RMI_F11_ABS_BYTES]; |
| 547 | int tool_type = MT_TOOL_FINGER; |
| 548 | |
| 549 | switch (finger_state) { |
| 550 | case F11_PRESENT: |
| 551 | obj->type = RMI_2D_OBJECT_FINGER; |
| 552 | break; |
| 553 | default: |
| 554 | obj->type = RMI_2D_OBJECT_NONE; |
| 555 | } |
| 556 | |
| 557 | obj->mt_tool = tool_type; |
| 558 | obj->x = (pos_data[0] << 4) | (pos_data[2] & 0x0F); |
| 559 | obj->y = (pos_data[1] << 4) | (pos_data[2] >> 4); |
| 560 | obj->z = pos_data[4]; |
| 561 | obj->wx = pos_data[3] & 0x0f; |
| 562 | obj->wy = pos_data[3] >> 4; |
| 563 | |
| 564 | rmi_2d_sensor_abs_process(sensor, obj, n_finger); |
| 565 | } |
| 566 | |
| 567 | static inline u8 rmi_f11_parse_finger_state(const u8 *f_state, u8 n_finger) |
| 568 | { |
| 569 | return (f_state[n_finger / 4] >> (2 * (n_finger % 4))) & |
| 570 | FINGER_STATE_MASK; |
| 571 | } |
| 572 | |
| 573 | static void rmi_f11_finger_handler(struct f11_data *f11, |
| 574 | struct rmi_2d_sensor *sensor, |
Andrew Duggan | 6d0dbea | 2016-11-08 16:46:20 -0800 | [diff] [blame] | 575 | unsigned long *irq_bits, int num_irq_regs, |
| 576 | int size) |
Andrew Duggan | ff8f837 | 2016-03-10 15:47:28 -0800 | [diff] [blame] | 577 | { |
| 578 | const u8 *f_state = f11->data.f_state; |
| 579 | u8 finger_state; |
| 580 | u8 i; |
Andrew Duggan | 6d0dbea | 2016-11-08 16:46:20 -0800 | [diff] [blame] | 581 | int abs_fingers; |
| 582 | int rel_fingers; |
| 583 | int abs_size = sensor->nbr_fingers * RMI_F11_ABS_BYTES; |
Andrew Duggan | ff8f837 | 2016-03-10 15:47:28 -0800 | [diff] [blame] | 584 | |
| 585 | int abs_bits = bitmap_and(f11->result_bits, irq_bits, f11->abs_mask, |
| 586 | num_irq_regs * 8); |
| 587 | int rel_bits = bitmap_and(f11->result_bits, irq_bits, f11->rel_mask, |
| 588 | num_irq_regs * 8); |
| 589 | |
Andrew Duggan | 6d0dbea | 2016-11-08 16:46:20 -0800 | [diff] [blame] | 590 | if (abs_bits) { |
| 591 | if (abs_size > size) |
| 592 | abs_fingers = size / RMI_F11_ABS_BYTES; |
| 593 | else |
| 594 | abs_fingers = sensor->nbr_fingers; |
Andrew Duggan | ff8f837 | 2016-03-10 15:47:28 -0800 | [diff] [blame] | 595 | |
Andrew Duggan | 6d0dbea | 2016-11-08 16:46:20 -0800 | [diff] [blame] | 596 | for (i = 0; i < abs_fingers; i++) { |
| 597 | /* Possible of having 4 fingers per f_state register */ |
| 598 | finger_state = rmi_f11_parse_finger_state(f_state, i); |
| 599 | if (finger_state == F11_RESERVED) { |
| 600 | pr_err("Invalid finger state[%d]: 0x%02x", i, |
| 601 | finger_state); |
| 602 | continue; |
| 603 | } |
| 604 | |
Andrew Duggan | ff8f837 | 2016-03-10 15:47:28 -0800 | [diff] [blame] | 605 | rmi_f11_abs_pos_process(f11, sensor, &sensor->objs[i], |
| 606 | finger_state, i); |
Andrew Duggan | 6d0dbea | 2016-11-08 16:46:20 -0800 | [diff] [blame] | 607 | } |
| 608 | } |
Andrew Duggan | ff8f837 | 2016-03-10 15:47:28 -0800 | [diff] [blame] | 609 | |
Andrew Duggan | 6d0dbea | 2016-11-08 16:46:20 -0800 | [diff] [blame] | 610 | if (rel_bits) { |
| 611 | if ((abs_size + sensor->nbr_fingers * RMI_F11_REL_BYTES) > size) |
| 612 | rel_fingers = (size - abs_size) / RMI_F11_REL_BYTES; |
| 613 | else |
| 614 | rel_fingers = sensor->nbr_fingers; |
| 615 | |
| 616 | for (i = 0; i < rel_fingers; i++) |
Andrew Duggan | ff8f837 | 2016-03-10 15:47:28 -0800 | [diff] [blame] | 617 | rmi_f11_rel_pos_report(f11, i); |
| 618 | } |
| 619 | |
| 620 | if (abs_bits) { |
| 621 | /* |
| 622 | * the absolute part is made in 2 parts to allow the kernel |
| 623 | * tracking to take place. |
| 624 | */ |
| 625 | if (sensor->kernel_tracking) |
| 626 | input_mt_assign_slots(sensor->input, |
| 627 | sensor->tracking_slots, |
| 628 | sensor->tracking_pos, |
| 629 | sensor->nbr_fingers, |
| 630 | sensor->dmax); |
| 631 | |
Andrew Duggan | 6d0dbea | 2016-11-08 16:46:20 -0800 | [diff] [blame] | 632 | for (i = 0; i < abs_fingers; i++) { |
Andrew Duggan | ff8f837 | 2016-03-10 15:47:28 -0800 | [diff] [blame] | 633 | finger_state = rmi_f11_parse_finger_state(f_state, i); |
| 634 | if (finger_state == F11_RESERVED) |
| 635 | /* no need to send twice the error */ |
| 636 | continue; |
| 637 | |
| 638 | rmi_2d_sensor_abs_report(sensor, &sensor->objs[i], i); |
| 639 | } |
| 640 | |
| 641 | input_mt_sync_frame(sensor->input); |
| 642 | } |
| 643 | } |
| 644 | |
| 645 | static int f11_2d_construct_data(struct f11_data *f11) |
| 646 | { |
| 647 | struct rmi_2d_sensor *sensor = &f11->sensor; |
| 648 | struct f11_2d_sensor_queries *query = &f11->sens_query; |
| 649 | struct f11_2d_data *data = &f11->data; |
| 650 | int i; |
| 651 | |
| 652 | sensor->nbr_fingers = (query->nr_fingers == 5 ? 10 : |
| 653 | query->nr_fingers + 1); |
| 654 | |
| 655 | sensor->pkt_size = DIV_ROUND_UP(sensor->nbr_fingers, 4); |
| 656 | |
| 657 | if (query->has_abs) { |
| 658 | sensor->pkt_size += (sensor->nbr_fingers * 5); |
| 659 | sensor->attn_size = sensor->pkt_size; |
| 660 | } |
| 661 | |
| 662 | if (query->has_rel) |
| 663 | sensor->pkt_size += (sensor->nbr_fingers * 2); |
| 664 | |
| 665 | /* Check if F11_2D_Query7 is non-zero */ |
| 666 | if (query->query7_nonzero) |
| 667 | sensor->pkt_size += sizeof(u8); |
| 668 | |
| 669 | /* Check if F11_2D_Query7 or F11_2D_Query8 is non-zero */ |
| 670 | if (query->query7_nonzero || query->query8_nonzero) |
| 671 | sensor->pkt_size += sizeof(u8); |
| 672 | |
| 673 | if (query->has_pinch || query->has_flick || query->has_rotate) { |
| 674 | sensor->pkt_size += 3; |
| 675 | if (!query->has_flick) |
| 676 | sensor->pkt_size--; |
| 677 | if (!query->has_rotate) |
| 678 | sensor->pkt_size--; |
| 679 | } |
| 680 | |
| 681 | if (query->has_touch_shapes) |
| 682 | sensor->pkt_size += |
| 683 | DIV_ROUND_UP(query->nr_touch_shapes + 1, 8); |
| 684 | |
| 685 | sensor->data_pkt = devm_kzalloc(&sensor->fn->dev, sensor->pkt_size, |
| 686 | GFP_KERNEL); |
| 687 | if (!sensor->data_pkt) |
| 688 | return -ENOMEM; |
| 689 | |
| 690 | data->f_state = sensor->data_pkt; |
| 691 | i = DIV_ROUND_UP(sensor->nbr_fingers, 4); |
| 692 | |
| 693 | if (query->has_abs) { |
| 694 | data->abs_pos = &sensor->data_pkt[i]; |
| 695 | i += (sensor->nbr_fingers * RMI_F11_ABS_BYTES); |
| 696 | } |
| 697 | |
| 698 | if (query->has_rel) { |
| 699 | data->rel_pos = &sensor->data_pkt[i]; |
| 700 | i += (sensor->nbr_fingers * RMI_F11_REL_BYTES); |
| 701 | } |
| 702 | |
| 703 | if (query->query7_nonzero) { |
| 704 | data->gest_1 = &sensor->data_pkt[i]; |
| 705 | i++; |
| 706 | } |
| 707 | |
| 708 | if (query->query7_nonzero || query->query8_nonzero) { |
| 709 | data->gest_2 = &sensor->data_pkt[i]; |
| 710 | i++; |
| 711 | } |
| 712 | |
| 713 | if (query->has_pinch) { |
| 714 | data->pinch = &sensor->data_pkt[i]; |
| 715 | i++; |
| 716 | } |
| 717 | |
| 718 | if (query->has_flick) { |
| 719 | if (query->has_pinch) { |
| 720 | data->flick = data->pinch; |
| 721 | i += 2; |
| 722 | } else { |
| 723 | data->flick = &sensor->data_pkt[i]; |
| 724 | i += 3; |
| 725 | } |
| 726 | } |
| 727 | |
| 728 | if (query->has_rotate) { |
| 729 | if (query->has_flick) { |
| 730 | data->rotate = data->flick + 1; |
| 731 | } else { |
| 732 | data->rotate = &sensor->data_pkt[i]; |
| 733 | i += 2; |
| 734 | } |
| 735 | } |
| 736 | |
| 737 | if (query->has_touch_shapes) |
| 738 | data->shapes = &sensor->data_pkt[i]; |
| 739 | |
| 740 | return 0; |
| 741 | } |
| 742 | |
| 743 | static int f11_read_control_regs(struct rmi_function *fn, |
| 744 | struct f11_2d_ctrl *ctrl, u16 ctrl_base_addr) { |
| 745 | struct rmi_device *rmi_dev = fn->rmi_dev; |
| 746 | int error = 0; |
| 747 | |
| 748 | ctrl->ctrl0_11_address = ctrl_base_addr; |
| 749 | error = rmi_read_block(rmi_dev, ctrl_base_addr, ctrl->ctrl0_11, |
| 750 | RMI_F11_CTRL_REG_COUNT); |
| 751 | if (error < 0) { |
| 752 | dev_err(&fn->dev, "Failed to read ctrl0, code: %d.\n", error); |
| 753 | return error; |
| 754 | } |
| 755 | |
| 756 | return 0; |
| 757 | } |
| 758 | |
| 759 | static int f11_write_control_regs(struct rmi_function *fn, |
| 760 | struct f11_2d_sensor_queries *query, |
| 761 | struct f11_2d_ctrl *ctrl, |
| 762 | u16 ctrl_base_addr) |
| 763 | { |
| 764 | struct rmi_device *rmi_dev = fn->rmi_dev; |
| 765 | int error; |
| 766 | |
| 767 | error = rmi_write_block(rmi_dev, ctrl_base_addr, ctrl->ctrl0_11, |
| 768 | RMI_F11_CTRL_REG_COUNT); |
| 769 | if (error < 0) |
| 770 | return error; |
| 771 | |
| 772 | return 0; |
| 773 | } |
| 774 | |
| 775 | static int rmi_f11_get_query_parameters(struct rmi_device *rmi_dev, |
| 776 | struct f11_data *f11, |
| 777 | struct f11_2d_sensor_queries *sensor_query, |
| 778 | u16 query_base_addr) |
| 779 | { |
| 780 | int query_size; |
| 781 | int rc; |
| 782 | u8 query_buf[RMI_F11_QUERY_SIZE]; |
| 783 | bool has_query36 = false; |
| 784 | |
| 785 | rc = rmi_read_block(rmi_dev, query_base_addr, query_buf, |
| 786 | RMI_F11_QUERY_SIZE); |
| 787 | if (rc < 0) |
| 788 | return rc; |
| 789 | |
| 790 | sensor_query->nr_fingers = query_buf[0] & RMI_F11_NR_FINGERS_MASK; |
| 791 | sensor_query->has_rel = !!(query_buf[0] & RMI_F11_HAS_REL); |
| 792 | sensor_query->has_abs = !!(query_buf[0] & RMI_F11_HAS_ABS); |
| 793 | sensor_query->has_gestures = !!(query_buf[0] & RMI_F11_HAS_GESTURES); |
| 794 | sensor_query->has_sensitivity_adjust = |
Dan Carpenter | 24672bd | 2016-03-15 16:45:07 -0700 | [diff] [blame] | 795 | !!(query_buf[0] & RMI_F11_HAS_SENSITIVITY_ADJ); |
Andrew Duggan | ff8f837 | 2016-03-10 15:47:28 -0800 | [diff] [blame] | 796 | sensor_query->configurable = !!(query_buf[0] & RMI_F11_CONFIGURABLE); |
| 797 | |
| 798 | sensor_query->nr_x_electrodes = |
| 799 | query_buf[1] & RMI_F11_NR_ELECTRODES_MASK; |
| 800 | sensor_query->nr_y_electrodes = |
| 801 | query_buf[2] & RMI_F11_NR_ELECTRODES_MASK; |
| 802 | sensor_query->max_electrodes = |
| 803 | query_buf[3] & RMI_F11_NR_ELECTRODES_MASK; |
| 804 | |
| 805 | query_size = RMI_F11_QUERY_SIZE; |
| 806 | |
| 807 | if (sensor_query->has_abs) { |
| 808 | rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf); |
| 809 | if (rc < 0) |
| 810 | return rc; |
| 811 | |
| 812 | sensor_query->abs_data_size = |
| 813 | query_buf[0] & RMI_F11_ABS_DATA_SIZE_MASK; |
| 814 | sensor_query->has_anchored_finger = |
| 815 | !!(query_buf[0] & RMI_F11_HAS_ANCHORED_FINGER); |
| 816 | sensor_query->has_adj_hyst = |
| 817 | !!(query_buf[0] & RMI_F11_HAS_ADJ_HYST); |
| 818 | sensor_query->has_dribble = |
| 819 | !!(query_buf[0] & RMI_F11_HAS_DRIBBLE); |
| 820 | sensor_query->has_bending_correction = |
| 821 | !!(query_buf[0] & RMI_F11_HAS_BENDING_CORRECTION); |
| 822 | sensor_query->has_large_object_suppression = |
Dan Carpenter | 24672bd | 2016-03-15 16:45:07 -0700 | [diff] [blame] | 823 | !!(query_buf[0] & RMI_F11_HAS_LARGE_OBJECT_SUPPRESSION); |
Andrew Duggan | ff8f837 | 2016-03-10 15:47:28 -0800 | [diff] [blame] | 824 | sensor_query->has_jitter_filter = |
| 825 | !!(query_buf[0] & RMI_F11_HAS_JITTER_FILTER); |
| 826 | query_size++; |
| 827 | } |
| 828 | |
| 829 | if (sensor_query->has_rel) { |
| 830 | rc = rmi_read(rmi_dev, query_base_addr + query_size, |
| 831 | &sensor_query->f11_2d_query6); |
| 832 | if (rc < 0) |
| 833 | return rc; |
| 834 | query_size++; |
| 835 | } |
| 836 | |
| 837 | if (sensor_query->has_gestures) { |
| 838 | rc = rmi_read_block(rmi_dev, query_base_addr + query_size, |
| 839 | query_buf, RMI_F11_QUERY_GESTURE_SIZE); |
| 840 | if (rc < 0) |
| 841 | return rc; |
| 842 | |
| 843 | sensor_query->has_single_tap = |
| 844 | !!(query_buf[0] & RMI_F11_HAS_SINGLE_TAP); |
| 845 | sensor_query->has_tap_n_hold = |
| 846 | !!(query_buf[0] & RMI_F11_HAS_TAP_AND_HOLD); |
| 847 | sensor_query->has_double_tap = |
| 848 | !!(query_buf[0] & RMI_F11_HAS_DOUBLE_TAP); |
| 849 | sensor_query->has_early_tap = |
| 850 | !!(query_buf[0] & RMI_F11_HAS_EARLY_TAP); |
| 851 | sensor_query->has_flick = |
| 852 | !!(query_buf[0] & RMI_F11_HAS_FLICK); |
| 853 | sensor_query->has_press = |
| 854 | !!(query_buf[0] & RMI_F11_HAS_PRESS); |
| 855 | sensor_query->has_pinch = |
| 856 | !!(query_buf[0] & RMI_F11_HAS_PINCH); |
| 857 | sensor_query->has_chiral = |
| 858 | !!(query_buf[0] & RMI_F11_HAS_CHIRAL); |
| 859 | |
| 860 | /* query 8 */ |
| 861 | sensor_query->has_palm_det = |
| 862 | !!(query_buf[1] & RMI_F11_HAS_PALM_DET); |
| 863 | sensor_query->has_rotate = |
| 864 | !!(query_buf[1] & RMI_F11_HAS_ROTATE); |
| 865 | sensor_query->has_touch_shapes = |
| 866 | !!(query_buf[1] & RMI_F11_HAS_TOUCH_SHAPES); |
| 867 | sensor_query->has_scroll_zones = |
| 868 | !!(query_buf[1] & RMI_F11_HAS_SCROLL_ZONES); |
| 869 | sensor_query->has_individual_scroll_zones = |
| 870 | !!(query_buf[1] & RMI_F11_HAS_INDIVIDUAL_SCROLL_ZONES); |
| 871 | sensor_query->has_mf_scroll = |
| 872 | !!(query_buf[1] & RMI_F11_HAS_MF_SCROLL); |
| 873 | sensor_query->has_mf_edge_motion = |
| 874 | !!(query_buf[1] & RMI_F11_HAS_MF_EDGE_MOTION); |
| 875 | sensor_query->has_mf_scroll_inertia = |
| 876 | !!(query_buf[1] & RMI_F11_HAS_MF_SCROLL_INERTIA); |
| 877 | |
| 878 | sensor_query->query7_nonzero = !!(query_buf[0]); |
| 879 | sensor_query->query8_nonzero = !!(query_buf[1]); |
| 880 | |
| 881 | query_size += 2; |
| 882 | } |
| 883 | |
| 884 | if (f11->has_query9) { |
| 885 | rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf); |
| 886 | if (rc < 0) |
| 887 | return rc; |
| 888 | |
| 889 | sensor_query->has_pen = |
| 890 | !!(query_buf[0] & RMI_F11_HAS_PEN); |
| 891 | sensor_query->has_proximity = |
| 892 | !!(query_buf[0] & RMI_F11_HAS_PROXIMITY); |
| 893 | sensor_query->has_palm_det_sensitivity = |
| 894 | !!(query_buf[0] & RMI_F11_HAS_PALM_DET_SENSITIVITY); |
| 895 | sensor_query->has_suppress_on_palm_detect = |
| 896 | !!(query_buf[0] & RMI_F11_HAS_SUPPRESS_ON_PALM_DETECT); |
| 897 | sensor_query->has_two_pen_thresholds = |
| 898 | !!(query_buf[0] & RMI_F11_HAS_TWO_PEN_THRESHOLDS); |
| 899 | sensor_query->has_contact_geometry = |
| 900 | !!(query_buf[0] & RMI_F11_HAS_CONTACT_GEOMETRY); |
| 901 | sensor_query->has_pen_hover_discrimination = |
| 902 | !!(query_buf[0] & RMI_F11_HAS_PEN_HOVER_DISCRIMINATION); |
| 903 | sensor_query->has_pen_filters = |
| 904 | !!(query_buf[0] & RMI_F11_HAS_PEN_FILTERS); |
| 905 | |
| 906 | query_size++; |
| 907 | } |
| 908 | |
| 909 | if (sensor_query->has_touch_shapes) { |
| 910 | rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf); |
| 911 | if (rc < 0) |
| 912 | return rc; |
| 913 | |
| 914 | sensor_query->nr_touch_shapes = query_buf[0] & |
| 915 | RMI_F11_NR_TOUCH_SHAPES_MASK; |
| 916 | |
| 917 | query_size++; |
| 918 | } |
| 919 | |
| 920 | if (f11->has_query11) { |
| 921 | rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf); |
| 922 | if (rc < 0) |
| 923 | return rc; |
| 924 | |
| 925 | sensor_query->has_z_tuning = |
| 926 | !!(query_buf[0] & RMI_F11_HAS_Z_TUNING); |
| 927 | sensor_query->has_algorithm_selection = |
| 928 | !!(query_buf[0] & RMI_F11_HAS_ALGORITHM_SELECTION); |
| 929 | sensor_query->has_w_tuning = |
| 930 | !!(query_buf[0] & RMI_F11_HAS_W_TUNING); |
| 931 | sensor_query->has_pitch_info = |
| 932 | !!(query_buf[0] & RMI_F11_HAS_PITCH_INFO); |
| 933 | sensor_query->has_finger_size = |
| 934 | !!(query_buf[0] & RMI_F11_HAS_FINGER_SIZE); |
| 935 | sensor_query->has_segmentation_aggressiveness = |
| 936 | !!(query_buf[0] & |
| 937 | RMI_F11_HAS_SEGMENTATION_AGGRESSIVENESS); |
| 938 | sensor_query->has_XY_clip = |
| 939 | !!(query_buf[0] & RMI_F11_HAS_XY_CLIP); |
| 940 | sensor_query->has_drumming_filter = |
| 941 | !!(query_buf[0] & RMI_F11_HAS_DRUMMING_FILTER); |
| 942 | |
| 943 | query_size++; |
| 944 | } |
| 945 | |
| 946 | if (f11->has_query12) { |
| 947 | rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf); |
| 948 | if (rc < 0) |
| 949 | return rc; |
| 950 | |
| 951 | sensor_query->has_gapless_finger = |
| 952 | !!(query_buf[0] & RMI_F11_HAS_GAPLESS_FINGER); |
| 953 | sensor_query->has_gapless_finger_tuning = |
| 954 | !!(query_buf[0] & RMI_F11_HAS_GAPLESS_FINGER_TUNING); |
| 955 | sensor_query->has_8bit_w = |
| 956 | !!(query_buf[0] & RMI_F11_HAS_8BIT_W); |
| 957 | sensor_query->has_adjustable_mapping = |
| 958 | !!(query_buf[0] & RMI_F11_HAS_ADJUSTABLE_MAPPING); |
| 959 | sensor_query->has_info2 = |
| 960 | !!(query_buf[0] & RMI_F11_HAS_INFO2); |
| 961 | sensor_query->has_physical_props = |
| 962 | !!(query_buf[0] & RMI_F11_HAS_PHYSICAL_PROPS); |
| 963 | sensor_query->has_finger_limit = |
| 964 | !!(query_buf[0] & RMI_F11_HAS_FINGER_LIMIT); |
| 965 | sensor_query->has_linear_coeff_2 = |
| 966 | !!(query_buf[0] & RMI_F11_HAS_LINEAR_COEFF); |
| 967 | |
| 968 | query_size++; |
| 969 | } |
| 970 | |
| 971 | if (sensor_query->has_jitter_filter) { |
| 972 | rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf); |
| 973 | if (rc < 0) |
| 974 | return rc; |
| 975 | |
| 976 | sensor_query->jitter_window_size = query_buf[0] & |
| 977 | RMI_F11_JITTER_WINDOW_MASK; |
| 978 | sensor_query->jitter_filter_type = (query_buf[0] & |
| 979 | RMI_F11_JITTER_FILTER_MASK) >> |
| 980 | RMI_F11_JITTER_FILTER_SHIFT; |
| 981 | |
| 982 | query_size++; |
| 983 | } |
| 984 | |
| 985 | if (sensor_query->has_info2) { |
| 986 | rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf); |
| 987 | if (rc < 0) |
| 988 | return rc; |
| 989 | |
| 990 | sensor_query->light_control = |
| 991 | query_buf[0] & RMI_F11_LIGHT_CONTROL_MASK; |
| 992 | sensor_query->is_clear = |
| 993 | !!(query_buf[0] & RMI_F11_IS_CLEAR); |
| 994 | sensor_query->clickpad_props = |
| 995 | (query_buf[0] & RMI_F11_CLICKPAD_PROPS_MASK) >> |
| 996 | RMI_F11_CLICKPAD_PROPS_SHIFT; |
| 997 | sensor_query->mouse_buttons = |
| 998 | (query_buf[0] & RMI_F11_MOUSE_BUTTONS_MASK) >> |
| 999 | RMI_F11_MOUSE_BUTTONS_SHIFT; |
| 1000 | sensor_query->has_advanced_gestures = |
| 1001 | !!(query_buf[0] & RMI_F11_HAS_ADVANCED_GESTURES); |
| 1002 | |
| 1003 | query_size++; |
| 1004 | } |
| 1005 | |
| 1006 | if (sensor_query->has_physical_props) { |
| 1007 | rc = rmi_read_block(rmi_dev, query_base_addr |
| 1008 | + query_size, query_buf, 4); |
| 1009 | if (rc < 0) |
| 1010 | return rc; |
| 1011 | |
| 1012 | sensor_query->x_sensor_size_mm = |
| 1013 | (query_buf[0] | (query_buf[1] << 8)) / 10; |
| 1014 | sensor_query->y_sensor_size_mm = |
| 1015 | (query_buf[2] | (query_buf[3] << 8)) / 10; |
| 1016 | |
| 1017 | /* |
| 1018 | * query 15 - 18 contain the size of the sensor |
| 1019 | * and query 19 - 26 contain bezel dimensions |
| 1020 | */ |
| 1021 | query_size += 12; |
| 1022 | } |
| 1023 | |
| 1024 | if (f11->has_query27) |
| 1025 | ++query_size; |
| 1026 | |
| 1027 | if (f11->has_query28) { |
| 1028 | rc = rmi_read(rmi_dev, query_base_addr + query_size, |
| 1029 | query_buf); |
| 1030 | if (rc < 0) |
| 1031 | return rc; |
| 1032 | |
| 1033 | has_query36 = !!(query_buf[0] & BIT(6)); |
| 1034 | } |
| 1035 | |
| 1036 | if (has_query36) { |
| 1037 | query_size += 2; |
| 1038 | rc = rmi_read(rmi_dev, query_base_addr + query_size, |
| 1039 | query_buf); |
| 1040 | if (rc < 0) |
| 1041 | return rc; |
| 1042 | |
| 1043 | if (!!(query_buf[0] & BIT(5))) |
| 1044 | f11->has_acm = true; |
| 1045 | } |
| 1046 | |
| 1047 | return query_size; |
| 1048 | } |
| 1049 | |
| 1050 | static int rmi_f11_initialize(struct rmi_function *fn) |
| 1051 | { |
| 1052 | struct rmi_device *rmi_dev = fn->rmi_dev; |
| 1053 | struct f11_data *f11; |
| 1054 | struct f11_2d_ctrl *ctrl; |
| 1055 | u8 query_offset; |
| 1056 | u16 query_base_addr; |
| 1057 | u16 control_base_addr; |
| 1058 | u16 max_x_pos, max_y_pos; |
| 1059 | int rc; |
| 1060 | const struct rmi_device_platform_data *pdata = |
| 1061 | rmi_get_platform_data(rmi_dev); |
| 1062 | struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev); |
| 1063 | struct rmi_2d_sensor *sensor; |
| 1064 | u8 buf; |
| 1065 | int mask_size; |
| 1066 | |
| 1067 | rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Initializing F11 values.\n"); |
| 1068 | |
| 1069 | mask_size = BITS_TO_LONGS(drvdata->irq_count) * sizeof(unsigned long); |
| 1070 | |
| 1071 | /* |
| 1072 | ** init instance data, fill in values and create any sysfs files |
| 1073 | */ |
| 1074 | f11 = devm_kzalloc(&fn->dev, sizeof(struct f11_data) + mask_size * 3, |
| 1075 | GFP_KERNEL); |
| 1076 | if (!f11) |
| 1077 | return -ENOMEM; |
| 1078 | |
Andrew Duggan | aaa2798 | 2016-03-10 15:48:32 -0800 | [diff] [blame] | 1079 | if (fn->dev.of_node) { |
| 1080 | rc = rmi_2d_sensor_of_probe(&fn->dev, &f11->sensor_pdata); |
| 1081 | if (rc) |
| 1082 | return rc; |
Benjamin Tissoires | 0a135b8 | 2016-11-30 17:01:50 -0800 | [diff] [blame^] | 1083 | } else { |
| 1084 | f11->sensor_pdata = pdata->sensor_pdata; |
Andrew Duggan | aaa2798 | 2016-03-10 15:48:32 -0800 | [diff] [blame] | 1085 | } |
Andrew Duggan | ff8f837 | 2016-03-10 15:47:28 -0800 | [diff] [blame] | 1086 | |
| 1087 | f11->rezero_wait_ms = f11->sensor_pdata.rezero_wait; |
| 1088 | |
| 1089 | f11->abs_mask = (unsigned long *)((char *)f11 |
| 1090 | + sizeof(struct f11_data)); |
| 1091 | f11->rel_mask = (unsigned long *)((char *)f11 |
| 1092 | + sizeof(struct f11_data) + mask_size); |
| 1093 | f11->result_bits = (unsigned long *)((char *)f11 |
| 1094 | + sizeof(struct f11_data) + mask_size * 2); |
| 1095 | |
| 1096 | set_bit(fn->irq_pos, f11->abs_mask); |
| 1097 | set_bit(fn->irq_pos + 1, f11->rel_mask); |
| 1098 | |
| 1099 | query_base_addr = fn->fd.query_base_addr; |
| 1100 | control_base_addr = fn->fd.control_base_addr; |
| 1101 | |
| 1102 | rc = rmi_read(rmi_dev, query_base_addr, &buf); |
| 1103 | if (rc < 0) |
| 1104 | return rc; |
| 1105 | |
| 1106 | f11->has_query9 = !!(buf & RMI_F11_HAS_QUERY9); |
| 1107 | f11->has_query11 = !!(buf & RMI_F11_HAS_QUERY11); |
| 1108 | f11->has_query12 = !!(buf & RMI_F11_HAS_QUERY12); |
| 1109 | f11->has_query27 = !!(buf & RMI_F11_HAS_QUERY27); |
| 1110 | f11->has_query28 = !!(buf & RMI_F11_HAS_QUERY28); |
| 1111 | |
| 1112 | query_offset = (query_base_addr + 1); |
| 1113 | sensor = &f11->sensor; |
| 1114 | sensor->fn = fn; |
| 1115 | |
| 1116 | rc = rmi_f11_get_query_parameters(rmi_dev, f11, |
| 1117 | &f11->sens_query, query_offset); |
| 1118 | if (rc < 0) |
| 1119 | return rc; |
| 1120 | query_offset += rc; |
| 1121 | |
| 1122 | rc = f11_read_control_regs(fn, &f11->dev_controls, |
| 1123 | control_base_addr); |
| 1124 | if (rc < 0) { |
| 1125 | dev_err(&fn->dev, |
| 1126 | "Failed to read F11 control params.\n"); |
| 1127 | return rc; |
| 1128 | } |
| 1129 | |
| 1130 | if (f11->sens_query.has_info2) { |
| 1131 | if (f11->sens_query.is_clear) |
| 1132 | f11->sensor.sensor_type = rmi_sensor_touchscreen; |
| 1133 | else |
| 1134 | f11->sensor.sensor_type = rmi_sensor_touchpad; |
| 1135 | } |
| 1136 | |
| 1137 | sensor->report_abs = f11->sens_query.has_abs; |
| 1138 | |
| 1139 | sensor->axis_align = |
| 1140 | f11->sensor_pdata.axis_align; |
| 1141 | |
| 1142 | sensor->topbuttonpad = f11->sensor_pdata.topbuttonpad; |
| 1143 | sensor->kernel_tracking = f11->sensor_pdata.kernel_tracking; |
| 1144 | sensor->dmax = f11->sensor_pdata.dmax; |
Andrew Duggan | 2775e52 | 2016-11-08 16:48:48 -0800 | [diff] [blame] | 1145 | sensor->dribble = f11->sensor_pdata.dribble; |
| 1146 | sensor->palm_detect = f11->sensor_pdata.palm_detect; |
Andrew Duggan | ff8f837 | 2016-03-10 15:47:28 -0800 | [diff] [blame] | 1147 | |
| 1148 | if (f11->sens_query.has_physical_props) { |
| 1149 | sensor->x_mm = f11->sens_query.x_sensor_size_mm; |
| 1150 | sensor->y_mm = f11->sens_query.y_sensor_size_mm; |
| 1151 | } else { |
| 1152 | sensor->x_mm = f11->sensor_pdata.x_mm; |
| 1153 | sensor->y_mm = f11->sensor_pdata.y_mm; |
| 1154 | } |
| 1155 | |
| 1156 | if (sensor->sensor_type == rmi_sensor_default) |
| 1157 | sensor->sensor_type = |
| 1158 | f11->sensor_pdata.sensor_type; |
| 1159 | |
| 1160 | sensor->report_abs = sensor->report_abs |
| 1161 | && !(f11->sensor_pdata.disable_report_mask |
| 1162 | & RMI_F11_DISABLE_ABS_REPORT); |
| 1163 | |
| 1164 | if (!sensor->report_abs) |
| 1165 | /* |
| 1166 | * If device doesn't have abs or if it has been disables |
| 1167 | * fallback to reporting rel data. |
| 1168 | */ |
| 1169 | sensor->report_rel = f11->sens_query.has_rel; |
| 1170 | |
| 1171 | rc = rmi_read_block(rmi_dev, |
| 1172 | control_base_addr + F11_CTRL_SENSOR_MAX_X_POS_OFFSET, |
| 1173 | (u8 *)&max_x_pos, sizeof(max_x_pos)); |
| 1174 | if (rc < 0) |
| 1175 | return rc; |
| 1176 | |
| 1177 | rc = rmi_read_block(rmi_dev, |
| 1178 | control_base_addr + F11_CTRL_SENSOR_MAX_Y_POS_OFFSET, |
| 1179 | (u8 *)&max_y_pos, sizeof(max_y_pos)); |
| 1180 | if (rc < 0) |
| 1181 | return rc; |
| 1182 | |
| 1183 | sensor->max_x = max_x_pos; |
| 1184 | sensor->max_y = max_y_pos; |
| 1185 | |
| 1186 | rc = f11_2d_construct_data(f11); |
| 1187 | if (rc < 0) |
| 1188 | return rc; |
| 1189 | |
| 1190 | if (f11->has_acm) |
| 1191 | f11->sensor.attn_size += f11->sensor.nbr_fingers * 2; |
| 1192 | |
| 1193 | /* allocate the in-kernel tracking buffers */ |
| 1194 | sensor->tracking_pos = devm_kzalloc(&fn->dev, |
| 1195 | sizeof(struct input_mt_pos) * sensor->nbr_fingers, |
| 1196 | GFP_KERNEL); |
| 1197 | sensor->tracking_slots = devm_kzalloc(&fn->dev, |
| 1198 | sizeof(int) * sensor->nbr_fingers, GFP_KERNEL); |
| 1199 | sensor->objs = devm_kzalloc(&fn->dev, |
| 1200 | sizeof(struct rmi_2d_sensor_abs_object) |
| 1201 | * sensor->nbr_fingers, GFP_KERNEL); |
| 1202 | if (!sensor->tracking_pos || !sensor->tracking_slots || !sensor->objs) |
| 1203 | return -ENOMEM; |
| 1204 | |
| 1205 | ctrl = &f11->dev_controls; |
| 1206 | if (sensor->axis_align.delta_x_threshold) |
| 1207 | ctrl->ctrl0_11[RMI_F11_DELTA_X_THRESHOLD] = |
| 1208 | sensor->axis_align.delta_x_threshold; |
| 1209 | |
| 1210 | if (sensor->axis_align.delta_y_threshold) |
| 1211 | ctrl->ctrl0_11[RMI_F11_DELTA_Y_THRESHOLD] = |
| 1212 | sensor->axis_align.delta_y_threshold; |
| 1213 | |
Andrew Duggan | 2775e52 | 2016-11-08 16:48:48 -0800 | [diff] [blame] | 1214 | if (f11->sens_query.has_dribble) { |
| 1215 | switch (sensor->dribble) { |
| 1216 | case RMI_REG_STATE_OFF: |
| 1217 | ctrl->ctrl0_11[0] &= ~BIT(6); |
| 1218 | break; |
| 1219 | case RMI_REG_STATE_ON: |
| 1220 | ctrl->ctrl0_11[0] |= BIT(6); |
| 1221 | break; |
| 1222 | case RMI_REG_STATE_DEFAULT: |
| 1223 | default: |
| 1224 | break; |
| 1225 | } |
| 1226 | } |
Andrew Duggan | ff8f837 | 2016-03-10 15:47:28 -0800 | [diff] [blame] | 1227 | |
Andrew Duggan | 2775e52 | 2016-11-08 16:48:48 -0800 | [diff] [blame] | 1228 | if (f11->sens_query.has_palm_det) { |
| 1229 | switch (sensor->palm_detect) { |
| 1230 | case RMI_REG_STATE_OFF: |
| 1231 | ctrl->ctrl0_11[11] &= ~BIT(0); |
| 1232 | break; |
| 1233 | case RMI_REG_STATE_ON: |
| 1234 | ctrl->ctrl0_11[11] |= BIT(0); |
| 1235 | break; |
| 1236 | case RMI_REG_STATE_DEFAULT: |
| 1237 | default: |
| 1238 | break; |
| 1239 | } |
| 1240 | } |
Andrew Duggan | ff8f837 | 2016-03-10 15:47:28 -0800 | [diff] [blame] | 1241 | |
| 1242 | rc = f11_write_control_regs(fn, &f11->sens_query, |
| 1243 | &f11->dev_controls, fn->fd.query_base_addr); |
| 1244 | if (rc) |
| 1245 | dev_warn(&fn->dev, "Failed to write control registers\n"); |
| 1246 | |
| 1247 | mutex_init(&f11->dev_controls_mutex); |
| 1248 | |
| 1249 | dev_set_drvdata(&fn->dev, f11); |
| 1250 | |
| 1251 | return 0; |
| 1252 | } |
| 1253 | |
| 1254 | static int rmi_f11_config(struct rmi_function *fn) |
| 1255 | { |
| 1256 | struct f11_data *f11 = dev_get_drvdata(&fn->dev); |
| 1257 | struct rmi_driver *drv = fn->rmi_dev->driver; |
| 1258 | struct rmi_2d_sensor *sensor = &f11->sensor; |
| 1259 | int rc; |
| 1260 | |
| 1261 | if (!sensor->report_abs) |
| 1262 | drv->clear_irq_bits(fn->rmi_dev, f11->abs_mask); |
| 1263 | else |
| 1264 | drv->set_irq_bits(fn->rmi_dev, f11->abs_mask); |
| 1265 | |
| 1266 | if (!sensor->report_rel) |
| 1267 | drv->clear_irq_bits(fn->rmi_dev, f11->rel_mask); |
| 1268 | else |
| 1269 | drv->set_irq_bits(fn->rmi_dev, f11->rel_mask); |
| 1270 | |
| 1271 | rc = f11_write_control_regs(fn, &f11->sens_query, |
| 1272 | &f11->dev_controls, fn->fd.query_base_addr); |
| 1273 | if (rc < 0) |
| 1274 | return rc; |
| 1275 | |
| 1276 | return 0; |
| 1277 | } |
| 1278 | |
| 1279 | static int rmi_f11_attention(struct rmi_function *fn, unsigned long *irq_bits) |
| 1280 | { |
| 1281 | struct rmi_device *rmi_dev = fn->rmi_dev; |
| 1282 | struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev); |
| 1283 | struct f11_data *f11 = dev_get_drvdata(&fn->dev); |
| 1284 | u16 data_base_addr = fn->fd.data_base_addr; |
Andrew Duggan | ff8f837 | 2016-03-10 15:47:28 -0800 | [diff] [blame] | 1285 | int error; |
Andrew Duggan | 6d0dbea | 2016-11-08 16:46:20 -0800 | [diff] [blame] | 1286 | int valid_bytes = f11->sensor.pkt_size; |
Andrew Duggan | ff8f837 | 2016-03-10 15:47:28 -0800 | [diff] [blame] | 1287 | |
| 1288 | if (rmi_dev->xport->attn_data) { |
Andrew Duggan | 6d0dbea | 2016-11-08 16:46:20 -0800 | [diff] [blame] | 1289 | /* |
| 1290 | * The valid data in the attention report is less then |
| 1291 | * expected. Only process the complete fingers. |
| 1292 | */ |
| 1293 | if (f11->sensor.attn_size > rmi_dev->xport->attn_size) |
| 1294 | valid_bytes = rmi_dev->xport->attn_size; |
| 1295 | else |
| 1296 | valid_bytes = f11->sensor.attn_size; |
Andrew Duggan | ff8f837 | 2016-03-10 15:47:28 -0800 | [diff] [blame] | 1297 | memcpy(f11->sensor.data_pkt, rmi_dev->xport->attn_data, |
Andrew Duggan | 6d0dbea | 2016-11-08 16:46:20 -0800 | [diff] [blame] | 1298 | valid_bytes); |
Andrew Duggan | ff8f837 | 2016-03-10 15:47:28 -0800 | [diff] [blame] | 1299 | rmi_dev->xport->attn_data += f11->sensor.attn_size; |
| 1300 | rmi_dev->xport->attn_size -= f11->sensor.attn_size; |
| 1301 | } else { |
| 1302 | error = rmi_read_block(rmi_dev, |
Andrew Duggan | 546ae10 | 2016-07-14 09:38:04 -0700 | [diff] [blame] | 1303 | data_base_addr, f11->sensor.data_pkt, |
Andrew Duggan | ff8f837 | 2016-03-10 15:47:28 -0800 | [diff] [blame] | 1304 | f11->sensor.pkt_size); |
| 1305 | if (error < 0) |
| 1306 | return error; |
| 1307 | } |
| 1308 | |
| 1309 | rmi_f11_finger_handler(f11, &f11->sensor, irq_bits, |
Andrew Duggan | 6d0dbea | 2016-11-08 16:46:20 -0800 | [diff] [blame] | 1310 | drvdata->num_of_irq_regs, valid_bytes); |
Andrew Duggan | ff8f837 | 2016-03-10 15:47:28 -0800 | [diff] [blame] | 1311 | |
| 1312 | return 0; |
| 1313 | } |
| 1314 | |
| 1315 | static int rmi_f11_resume(struct rmi_function *fn) |
| 1316 | { |
| 1317 | struct f11_data *f11 = dev_get_drvdata(&fn->dev); |
| 1318 | int error; |
| 1319 | |
| 1320 | rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Resuming...\n"); |
| 1321 | if (!f11->rezero_wait_ms) |
| 1322 | return 0; |
| 1323 | |
| 1324 | mdelay(f11->rezero_wait_ms); |
| 1325 | |
| 1326 | error = rmi_write(fn->rmi_dev, fn->fd.command_base_addr, |
| 1327 | RMI_F11_REZERO); |
| 1328 | if (error) { |
| 1329 | dev_err(&fn->dev, |
| 1330 | "%s: failed to issue rezero command, error = %d.", |
| 1331 | __func__, error); |
| 1332 | return error; |
| 1333 | } |
| 1334 | |
| 1335 | return 0; |
| 1336 | } |
| 1337 | |
| 1338 | static int rmi_f11_probe(struct rmi_function *fn) |
| 1339 | { |
| 1340 | int error; |
| 1341 | struct f11_data *f11; |
| 1342 | |
| 1343 | error = rmi_f11_initialize(fn); |
| 1344 | if (error) |
| 1345 | return error; |
| 1346 | |
| 1347 | f11 = dev_get_drvdata(&fn->dev); |
| 1348 | error = rmi_2d_sensor_configure_input(fn, &f11->sensor); |
| 1349 | if (error) |
| 1350 | return error; |
| 1351 | |
| 1352 | return 0; |
| 1353 | } |
| 1354 | |
| 1355 | struct rmi_function_handler rmi_f11_handler = { |
| 1356 | .driver = { |
| 1357 | .name = "rmi4_f11", |
| 1358 | }, |
| 1359 | .func = 0x11, |
| 1360 | .probe = rmi_f11_probe, |
| 1361 | .config = rmi_f11_config, |
| 1362 | .attention = rmi_f11_attention, |
| 1363 | .resume = rmi_f11_resume, |
| 1364 | }; |