18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2011-2015 Synaptics Incorporated 48c2ecf20Sopenharmony_ci * Copyright (c) 2011 Unixphere 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/kernel.h> 88c2ecf20Sopenharmony_ci#include <linux/delay.h> 98c2ecf20Sopenharmony_ci#include <linux/device.h> 108c2ecf20Sopenharmony_ci#include <linux/input.h> 118c2ecf20Sopenharmony_ci#include <linux/input/mt.h> 128c2ecf20Sopenharmony_ci#include <linux/rmi.h> 138c2ecf20Sopenharmony_ci#include <linux/slab.h> 148c2ecf20Sopenharmony_ci#include <linux/of.h> 158c2ecf20Sopenharmony_ci#include "rmi_driver.h" 168c2ecf20Sopenharmony_ci#include "rmi_2d_sensor.h" 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define F11_MAX_NUM_OF_FINGERS 10 198c2ecf20Sopenharmony_ci#define F11_MAX_NUM_OF_TOUCH_SHAPES 16 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define FINGER_STATE_MASK 0x03 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#define F11_CTRL_SENSOR_MAX_X_POS_OFFSET 6 248c2ecf20Sopenharmony_ci#define F11_CTRL_SENSOR_MAX_Y_POS_OFFSET 8 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#define DEFAULT_XY_MAX 9999 278c2ecf20Sopenharmony_ci#define DEFAULT_MAX_ABS_MT_PRESSURE 255 288c2ecf20Sopenharmony_ci#define DEFAULT_MAX_ABS_MT_TOUCH 15 298c2ecf20Sopenharmony_ci#define DEFAULT_MAX_ABS_MT_ORIENTATION 1 308c2ecf20Sopenharmony_ci#define DEFAULT_MIN_ABS_MT_TRACKING_ID 1 318c2ecf20Sopenharmony_ci#define DEFAULT_MAX_ABS_MT_TRACKING_ID 10 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci/** A note about RMI4 F11 register structure. 348c2ecf20Sopenharmony_ci * 358c2ecf20Sopenharmony_ci * The properties for 368c2ecf20Sopenharmony_ci * a given sensor are described by its query registers. The number of query 378c2ecf20Sopenharmony_ci * registers and the layout of their contents are described by the F11 device 388c2ecf20Sopenharmony_ci * queries as well as the sensor query information. 398c2ecf20Sopenharmony_ci * 408c2ecf20Sopenharmony_ci * Similarly, each sensor has control registers that govern its behavior. The 418c2ecf20Sopenharmony_ci * size and layout of the control registers for a given sensor can be determined 428c2ecf20Sopenharmony_ci * by parsing that sensors query registers. 438c2ecf20Sopenharmony_ci * 448c2ecf20Sopenharmony_ci * And in a likewise fashion, each sensor has data registers where it reports 458c2ecf20Sopenharmony_ci * its touch data and other interesting stuff. The size and layout of a 468c2ecf20Sopenharmony_ci * sensors data registers must be determined by parsing its query registers. 478c2ecf20Sopenharmony_ci * 488c2ecf20Sopenharmony_ci * The short story is that we need to read and parse a lot of query 498c2ecf20Sopenharmony_ci * registers in order to determine the attributes of a sensor. Then 508c2ecf20Sopenharmony_ci * we need to use that data to compute the size of the control and data 518c2ecf20Sopenharmony_ci * registers for sensor. 528c2ecf20Sopenharmony_ci * 538c2ecf20Sopenharmony_ci * The end result is that we have a number of structs that aren't used to 548c2ecf20Sopenharmony_ci * directly generate the input events, but their size, location and contents 558c2ecf20Sopenharmony_ci * are critical to determining where the data we are interested in lives. 568c2ecf20Sopenharmony_ci * 578c2ecf20Sopenharmony_ci * At this time, the driver does not yet comprehend all possible F11 588c2ecf20Sopenharmony_ci * configuration options, but it should be sufficient to cover 99% of RMI4 F11 598c2ecf20Sopenharmony_ci * devices currently in the field. 608c2ecf20Sopenharmony_ci */ 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci/* maximum ABS_MT_POSITION displacement (in mm) */ 638c2ecf20Sopenharmony_ci#define DMAX 10 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci/** 668c2ecf20Sopenharmony_ci * @rezero - writing this to the F11 command register will cause the sensor to 678c2ecf20Sopenharmony_ci * calibrate to the current capacitive state. 688c2ecf20Sopenharmony_ci */ 698c2ecf20Sopenharmony_ci#define RMI_F11_REZERO 0x01 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci#define RMI_F11_HAS_QUERY9 (1 << 3) 728c2ecf20Sopenharmony_ci#define RMI_F11_HAS_QUERY11 (1 << 4) 738c2ecf20Sopenharmony_ci#define RMI_F11_HAS_QUERY12 (1 << 5) 748c2ecf20Sopenharmony_ci#define RMI_F11_HAS_QUERY27 (1 << 6) 758c2ecf20Sopenharmony_ci#define RMI_F11_HAS_QUERY28 (1 << 7) 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci/** Defs for Query 1 */ 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci#define RMI_F11_NR_FINGERS_MASK 0x07 808c2ecf20Sopenharmony_ci#define RMI_F11_HAS_REL (1 << 3) 818c2ecf20Sopenharmony_ci#define RMI_F11_HAS_ABS (1 << 4) 828c2ecf20Sopenharmony_ci#define RMI_F11_HAS_GESTURES (1 << 5) 838c2ecf20Sopenharmony_ci#define RMI_F11_HAS_SENSITIVITY_ADJ (1 << 6) 848c2ecf20Sopenharmony_ci#define RMI_F11_CONFIGURABLE (1 << 7) 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci/** Defs for Query 2, 3, and 4. */ 878c2ecf20Sopenharmony_ci#define RMI_F11_NR_ELECTRODES_MASK 0x7F 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci/** Defs for Query 5 */ 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci#define RMI_F11_ABS_DATA_SIZE_MASK 0x03 928c2ecf20Sopenharmony_ci#define RMI_F11_HAS_ANCHORED_FINGER (1 << 2) 938c2ecf20Sopenharmony_ci#define RMI_F11_HAS_ADJ_HYST (1 << 3) 948c2ecf20Sopenharmony_ci#define RMI_F11_HAS_DRIBBLE (1 << 4) 958c2ecf20Sopenharmony_ci#define RMI_F11_HAS_BENDING_CORRECTION (1 << 5) 968c2ecf20Sopenharmony_ci#define RMI_F11_HAS_LARGE_OBJECT_SUPPRESSION (1 << 6) 978c2ecf20Sopenharmony_ci#define RMI_F11_HAS_JITTER_FILTER (1 << 7) 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci/** Defs for Query 7 */ 1008c2ecf20Sopenharmony_ci#define RMI_F11_HAS_SINGLE_TAP (1 << 0) 1018c2ecf20Sopenharmony_ci#define RMI_F11_HAS_TAP_AND_HOLD (1 << 1) 1028c2ecf20Sopenharmony_ci#define RMI_F11_HAS_DOUBLE_TAP (1 << 2) 1038c2ecf20Sopenharmony_ci#define RMI_F11_HAS_EARLY_TAP (1 << 3) 1048c2ecf20Sopenharmony_ci#define RMI_F11_HAS_FLICK (1 << 4) 1058c2ecf20Sopenharmony_ci#define RMI_F11_HAS_PRESS (1 << 5) 1068c2ecf20Sopenharmony_ci#define RMI_F11_HAS_PINCH (1 << 6) 1078c2ecf20Sopenharmony_ci#define RMI_F11_HAS_CHIRAL (1 << 7) 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci/** Defs for Query 8 */ 1108c2ecf20Sopenharmony_ci#define RMI_F11_HAS_PALM_DET (1 << 0) 1118c2ecf20Sopenharmony_ci#define RMI_F11_HAS_ROTATE (1 << 1) 1128c2ecf20Sopenharmony_ci#define RMI_F11_HAS_TOUCH_SHAPES (1 << 2) 1138c2ecf20Sopenharmony_ci#define RMI_F11_HAS_SCROLL_ZONES (1 << 3) 1148c2ecf20Sopenharmony_ci#define RMI_F11_HAS_INDIVIDUAL_SCROLL_ZONES (1 << 4) 1158c2ecf20Sopenharmony_ci#define RMI_F11_HAS_MF_SCROLL (1 << 5) 1168c2ecf20Sopenharmony_ci#define RMI_F11_HAS_MF_EDGE_MOTION (1 << 6) 1178c2ecf20Sopenharmony_ci#define RMI_F11_HAS_MF_SCROLL_INERTIA (1 << 7) 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci/** Defs for Query 9. */ 1208c2ecf20Sopenharmony_ci#define RMI_F11_HAS_PEN (1 << 0) 1218c2ecf20Sopenharmony_ci#define RMI_F11_HAS_PROXIMITY (1 << 1) 1228c2ecf20Sopenharmony_ci#define RMI_F11_HAS_PALM_DET_SENSITIVITY (1 << 2) 1238c2ecf20Sopenharmony_ci#define RMI_F11_HAS_SUPPRESS_ON_PALM_DETECT (1 << 3) 1248c2ecf20Sopenharmony_ci#define RMI_F11_HAS_TWO_PEN_THRESHOLDS (1 << 4) 1258c2ecf20Sopenharmony_ci#define RMI_F11_HAS_CONTACT_GEOMETRY (1 << 5) 1268c2ecf20Sopenharmony_ci#define RMI_F11_HAS_PEN_HOVER_DISCRIMINATION (1 << 6) 1278c2ecf20Sopenharmony_ci#define RMI_F11_HAS_PEN_FILTERS (1 << 7) 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci/** Defs for Query 10. */ 1308c2ecf20Sopenharmony_ci#define RMI_F11_NR_TOUCH_SHAPES_MASK 0x1F 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci/** Defs for Query 11 */ 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci#define RMI_F11_HAS_Z_TUNING (1 << 0) 1358c2ecf20Sopenharmony_ci#define RMI_F11_HAS_ALGORITHM_SELECTION (1 << 1) 1368c2ecf20Sopenharmony_ci#define RMI_F11_HAS_W_TUNING (1 << 2) 1378c2ecf20Sopenharmony_ci#define RMI_F11_HAS_PITCH_INFO (1 << 3) 1388c2ecf20Sopenharmony_ci#define RMI_F11_HAS_FINGER_SIZE (1 << 4) 1398c2ecf20Sopenharmony_ci#define RMI_F11_HAS_SEGMENTATION_AGGRESSIVENESS (1 << 5) 1408c2ecf20Sopenharmony_ci#define RMI_F11_HAS_XY_CLIP (1 << 6) 1418c2ecf20Sopenharmony_ci#define RMI_F11_HAS_DRUMMING_FILTER (1 << 7) 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci/** Defs for Query 12. */ 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci#define RMI_F11_HAS_GAPLESS_FINGER (1 << 0) 1468c2ecf20Sopenharmony_ci#define RMI_F11_HAS_GAPLESS_FINGER_TUNING (1 << 1) 1478c2ecf20Sopenharmony_ci#define RMI_F11_HAS_8BIT_W (1 << 2) 1488c2ecf20Sopenharmony_ci#define RMI_F11_HAS_ADJUSTABLE_MAPPING (1 << 3) 1498c2ecf20Sopenharmony_ci#define RMI_F11_HAS_INFO2 (1 << 4) 1508c2ecf20Sopenharmony_ci#define RMI_F11_HAS_PHYSICAL_PROPS (1 << 5) 1518c2ecf20Sopenharmony_ci#define RMI_F11_HAS_FINGER_LIMIT (1 << 6) 1528c2ecf20Sopenharmony_ci#define RMI_F11_HAS_LINEAR_COEFF (1 << 7) 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci/** Defs for Query 13. */ 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci#define RMI_F11_JITTER_WINDOW_MASK 0x1F 1578c2ecf20Sopenharmony_ci#define RMI_F11_JITTER_FILTER_MASK 0x60 1588c2ecf20Sopenharmony_ci#define RMI_F11_JITTER_FILTER_SHIFT 5 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci/** Defs for Query 14. */ 1618c2ecf20Sopenharmony_ci#define RMI_F11_LIGHT_CONTROL_MASK 0x03 1628c2ecf20Sopenharmony_ci#define RMI_F11_IS_CLEAR (1 << 2) 1638c2ecf20Sopenharmony_ci#define RMI_F11_CLICKPAD_PROPS_MASK 0x18 1648c2ecf20Sopenharmony_ci#define RMI_F11_CLICKPAD_PROPS_SHIFT 3 1658c2ecf20Sopenharmony_ci#define RMI_F11_MOUSE_BUTTONS_MASK 0x60 1668c2ecf20Sopenharmony_ci#define RMI_F11_MOUSE_BUTTONS_SHIFT 5 1678c2ecf20Sopenharmony_ci#define RMI_F11_HAS_ADVANCED_GESTURES (1 << 7) 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci#define RMI_F11_QUERY_SIZE 4 1708c2ecf20Sopenharmony_ci#define RMI_F11_QUERY_GESTURE_SIZE 2 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci#define F11_LIGHT_CTL_NONE 0x00 1738c2ecf20Sopenharmony_ci#define F11_LUXPAD 0x01 1748c2ecf20Sopenharmony_ci#define F11_DUAL_MODE 0x02 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci#define F11_NOT_CLICKPAD 0x00 1778c2ecf20Sopenharmony_ci#define F11_HINGED_CLICKPAD 0x01 1788c2ecf20Sopenharmony_ci#define F11_UNIFORM_CLICKPAD 0x02 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci/** 1818c2ecf20Sopenharmony_ci * Query registers 1 through 4 are always present. 1828c2ecf20Sopenharmony_ci * 1838c2ecf20Sopenharmony_ci * @nr_fingers - describes the maximum number of fingers the 2-D sensor 1848c2ecf20Sopenharmony_ci * supports. 1858c2ecf20Sopenharmony_ci * @has_rel - the sensor supports relative motion reporting. 1868c2ecf20Sopenharmony_ci * @has_abs - the sensor supports absolute poition reporting. 1878c2ecf20Sopenharmony_ci * @has_gestures - the sensor supports gesture reporting. 1888c2ecf20Sopenharmony_ci * @has_sensitivity_adjust - the sensor supports a global sensitivity 1898c2ecf20Sopenharmony_ci * adjustment. 1908c2ecf20Sopenharmony_ci * @configurable - the sensor supports various configuration options. 1918c2ecf20Sopenharmony_ci * @num_of_x_electrodes - the maximum number of electrodes the 2-D sensor 1928c2ecf20Sopenharmony_ci * supports on the X axis. 1938c2ecf20Sopenharmony_ci * @num_of_y_electrodes - the maximum number of electrodes the 2-D sensor 1948c2ecf20Sopenharmony_ci * supports on the Y axis. 1958c2ecf20Sopenharmony_ci * @max_electrodes - the total number of X and Y electrodes that may be 1968c2ecf20Sopenharmony_ci * configured. 1978c2ecf20Sopenharmony_ci * 1988c2ecf20Sopenharmony_ci * Query 5 is present if the has_abs bit is set. 1998c2ecf20Sopenharmony_ci * 2008c2ecf20Sopenharmony_ci * @abs_data_size - describes the format of data reported by the absolute 2018c2ecf20Sopenharmony_ci * data source. Only one format (the kind used here) is supported at this 2028c2ecf20Sopenharmony_ci * time. 2038c2ecf20Sopenharmony_ci * @has_anchored_finger - then the sensor supports the high-precision second 2048c2ecf20Sopenharmony_ci * finger tracking provided by the manual tracking and motion sensitivity 2058c2ecf20Sopenharmony_ci * options. 2068c2ecf20Sopenharmony_ci * @has_adjust_hyst - the difference between the finger release threshold and 2078c2ecf20Sopenharmony_ci * the touch threshold. 2088c2ecf20Sopenharmony_ci * @has_dribble - the sensor supports the generation of dribble interrupts, 2098c2ecf20Sopenharmony_ci * which may be enabled or disabled with the dribble control bit. 2108c2ecf20Sopenharmony_ci * @has_bending_correction - Bending related data registers 28 and 36, and 2118c2ecf20Sopenharmony_ci * control register 52..57 are present. 2128c2ecf20Sopenharmony_ci * @has_large_object_suppression - control register 58 and data register 28 2138c2ecf20Sopenharmony_ci * exist. 2148c2ecf20Sopenharmony_ci * @has_jitter_filter - query 13 and control 73..76 exist. 2158c2ecf20Sopenharmony_ci * 2168c2ecf20Sopenharmony_ci * Gesture information queries 7 and 8 are present if has_gestures bit is set. 2178c2ecf20Sopenharmony_ci * 2188c2ecf20Sopenharmony_ci * @has_single_tap - a basic single-tap gesture is supported. 2198c2ecf20Sopenharmony_ci * @has_tap_n_hold - tap-and-hold gesture is supported. 2208c2ecf20Sopenharmony_ci * @has_double_tap - double-tap gesture is supported. 2218c2ecf20Sopenharmony_ci * @has_early_tap - early tap is supported and reported as soon as the finger 2228c2ecf20Sopenharmony_ci * lifts for any tap event that could be interpreted as either a single tap 2238c2ecf20Sopenharmony_ci * or as the first tap of a double-tap or tap-and-hold gesture. 2248c2ecf20Sopenharmony_ci * @has_flick - flick detection is supported. 2258c2ecf20Sopenharmony_ci * @has_press - press gesture reporting is supported. 2268c2ecf20Sopenharmony_ci * @has_pinch - pinch gesture detection is supported. 2278c2ecf20Sopenharmony_ci * @has_palm_det - the 2-D sensor notifies the host whenever a large conductive 2288c2ecf20Sopenharmony_ci * object such as a palm or a cheek touches the 2-D sensor. 2298c2ecf20Sopenharmony_ci * @has_rotate - rotation gesture detection is supported. 2308c2ecf20Sopenharmony_ci * @has_touch_shapes - TouchShapes are supported. A TouchShape is a fixed 2318c2ecf20Sopenharmony_ci * rectangular area on the sensor that behaves like a capacitive button. 2328c2ecf20Sopenharmony_ci * @has_scroll_zones - scrolling areas near the sensor edges are supported. 2338c2ecf20Sopenharmony_ci * @has_individual_scroll_zones - if 1, then 4 scroll zones are supported; 2348c2ecf20Sopenharmony_ci * if 0, then only two are supported. 2358c2ecf20Sopenharmony_ci * @has_mf_scroll - the multifinger_scrolling bit will be set when 2368c2ecf20Sopenharmony_ci * more than one finger is involved in a scrolling action. 2378c2ecf20Sopenharmony_ci * 2388c2ecf20Sopenharmony_ci * Convenience for checking bytes in the gesture info registers. This is done 2398c2ecf20Sopenharmony_ci * often enough that we put it here to declutter the conditionals 2408c2ecf20Sopenharmony_ci * 2418c2ecf20Sopenharmony_ci * @query7_nonzero - true if none of the query 7 bits are set 2428c2ecf20Sopenharmony_ci * @query8_nonzero - true if none of the query 8 bits are set 2438c2ecf20Sopenharmony_ci * 2448c2ecf20Sopenharmony_ci * Query 9 is present if the has_query9 is set. 2458c2ecf20Sopenharmony_ci * 2468c2ecf20Sopenharmony_ci * @has_pen - detection of a stylus is supported and registers F11_2D_Ctrl20 2478c2ecf20Sopenharmony_ci * and F11_2D_Ctrl21 exist. 2488c2ecf20Sopenharmony_ci * @has_proximity - detection of fingers near the sensor is supported and 2498c2ecf20Sopenharmony_ci * registers F11_2D_Ctrl22 through F11_2D_Ctrl26 exist. 2508c2ecf20Sopenharmony_ci * @has_palm_det_sensitivity - the sensor supports the palm detect sensitivity 2518c2ecf20Sopenharmony_ci * feature and register F11_2D_Ctrl27 exists. 2528c2ecf20Sopenharmony_ci * @has_two_pen_thresholds - is has_pen is also set, then F11_2D_Ctrl35 exists. 2538c2ecf20Sopenharmony_ci * @has_contact_geometry - the sensor supports the use of contact geometry to 2548c2ecf20Sopenharmony_ci * map absolute X and Y target positions and registers F11_2D_Data18 2558c2ecf20Sopenharmony_ci * through F11_2D_Data27 exist. 2568c2ecf20Sopenharmony_ci * 2578c2ecf20Sopenharmony_ci * Touch shape info (query 10) is present if has_touch_shapes is set. 2588c2ecf20Sopenharmony_ci * 2598c2ecf20Sopenharmony_ci * @nr_touch_shapes - the total number of touch shapes supported. 2608c2ecf20Sopenharmony_ci * 2618c2ecf20Sopenharmony_ci * Query 11 is present if the has_query11 bit is set in query 0. 2628c2ecf20Sopenharmony_ci * 2638c2ecf20Sopenharmony_ci * @has_z_tuning - if set, the sensor supports Z tuning and registers 2648c2ecf20Sopenharmony_ci * F11_2D_Ctrl29 through F11_2D_Ctrl33 exist. 2658c2ecf20Sopenharmony_ci * @has_algorithm_selection - controls choice of noise suppression algorithm 2668c2ecf20Sopenharmony_ci * @has_w_tuning - the sensor supports Wx and Wy scaling and registers 2678c2ecf20Sopenharmony_ci * F11_2D_Ctrl36 through F11_2D_Ctrl39 exist. 2688c2ecf20Sopenharmony_ci * @has_pitch_info - the X and Y pitches of the sensor electrodes can be 2698c2ecf20Sopenharmony_ci * configured and registers F11_2D_Ctrl40 and F11_2D_Ctrl41 exist. 2708c2ecf20Sopenharmony_ci * @has_finger_size - the default finger width settings for the 2718c2ecf20Sopenharmony_ci * sensor can be configured and registers F11_2D_Ctrl42 through F11_2D_Ctrl44 2728c2ecf20Sopenharmony_ci * exist. 2738c2ecf20Sopenharmony_ci * @has_segmentation_aggressiveness - the sensor’s ability to distinguish 2748c2ecf20Sopenharmony_ci * multiple objects close together can be configured and register F11_2D_Ctrl45 2758c2ecf20Sopenharmony_ci * exists. 2768c2ecf20Sopenharmony_ci * @has_XY_clip - the inactive outside borders of the sensor can be 2778c2ecf20Sopenharmony_ci * configured and registers F11_2D_Ctrl46 through F11_2D_Ctrl49 exist. 2788c2ecf20Sopenharmony_ci * @has_drumming_filter - the sensor can be configured to distinguish 2798c2ecf20Sopenharmony_ci * between a fast flick and a quick drumming movement and registers 2808c2ecf20Sopenharmony_ci * F11_2D_Ctrl50 and F11_2D_Ctrl51 exist. 2818c2ecf20Sopenharmony_ci * 2828c2ecf20Sopenharmony_ci * Query 12 is present if hasQuery12 bit is set. 2838c2ecf20Sopenharmony_ci * 2848c2ecf20Sopenharmony_ci * @has_gapless_finger - control registers relating to gapless finger are 2858c2ecf20Sopenharmony_ci * present. 2868c2ecf20Sopenharmony_ci * @has_gapless_finger_tuning - additional control and data registers relating 2878c2ecf20Sopenharmony_ci * to gapless finger are present. 2888c2ecf20Sopenharmony_ci * @has_8bit_w - larger W value reporting is supported. 2898c2ecf20Sopenharmony_ci * @has_adjustable_mapping - TBD 2908c2ecf20Sopenharmony_ci * @has_info2 - the general info query14 is present 2918c2ecf20Sopenharmony_ci * @has_physical_props - additional queries describing the physical properties 2928c2ecf20Sopenharmony_ci * of the sensor are present. 2938c2ecf20Sopenharmony_ci * @has_finger_limit - indicates that F11 Ctrl 80 exists. 2948c2ecf20Sopenharmony_ci * @has_linear_coeff - indicates that F11 Ctrl 81 exists. 2958c2ecf20Sopenharmony_ci * 2968c2ecf20Sopenharmony_ci * Query 13 is present if Query 5's has_jitter_filter bit is set. 2978c2ecf20Sopenharmony_ci * @jitter_window_size - used by Design Studio 4. 2988c2ecf20Sopenharmony_ci * @jitter_filter_type - used by Design Studio 4. 2998c2ecf20Sopenharmony_ci * 3008c2ecf20Sopenharmony_ci * Query 14 is present if query 12's has_general_info2 flag is set. 3018c2ecf20Sopenharmony_ci * 3028c2ecf20Sopenharmony_ci * @light_control - Indicates what light/led control features are present, if 3038c2ecf20Sopenharmony_ci * any. 3048c2ecf20Sopenharmony_ci * @is_clear - if set, this is a clear sensor (indicating direct pointing 3058c2ecf20Sopenharmony_ci * application), otherwise it's opaque (indicating indirect pointing). 3068c2ecf20Sopenharmony_ci * @clickpad_props - specifies if this is a clickpad, and if so what sort of 3078c2ecf20Sopenharmony_ci * mechanism it uses 3088c2ecf20Sopenharmony_ci * @mouse_buttons - specifies the number of mouse buttons present (if any). 3098c2ecf20Sopenharmony_ci * @has_advanced_gestures - advanced driver gestures are supported. 3108c2ecf20Sopenharmony_ci */ 3118c2ecf20Sopenharmony_cistruct f11_2d_sensor_queries { 3128c2ecf20Sopenharmony_ci /* query1 */ 3138c2ecf20Sopenharmony_ci u8 nr_fingers; 3148c2ecf20Sopenharmony_ci bool has_rel; 3158c2ecf20Sopenharmony_ci bool has_abs; 3168c2ecf20Sopenharmony_ci bool has_gestures; 3178c2ecf20Sopenharmony_ci bool has_sensitivity_adjust; 3188c2ecf20Sopenharmony_ci bool configurable; 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci /* query2 */ 3218c2ecf20Sopenharmony_ci u8 nr_x_electrodes; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci /* query3 */ 3248c2ecf20Sopenharmony_ci u8 nr_y_electrodes; 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci /* query4 */ 3278c2ecf20Sopenharmony_ci u8 max_electrodes; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci /* query5 */ 3308c2ecf20Sopenharmony_ci u8 abs_data_size; 3318c2ecf20Sopenharmony_ci bool has_anchored_finger; 3328c2ecf20Sopenharmony_ci bool has_adj_hyst; 3338c2ecf20Sopenharmony_ci bool has_dribble; 3348c2ecf20Sopenharmony_ci bool has_bending_correction; 3358c2ecf20Sopenharmony_ci bool has_large_object_suppression; 3368c2ecf20Sopenharmony_ci bool has_jitter_filter; 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci u8 f11_2d_query6; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci /* query 7 */ 3418c2ecf20Sopenharmony_ci bool has_single_tap; 3428c2ecf20Sopenharmony_ci bool has_tap_n_hold; 3438c2ecf20Sopenharmony_ci bool has_double_tap; 3448c2ecf20Sopenharmony_ci bool has_early_tap; 3458c2ecf20Sopenharmony_ci bool has_flick; 3468c2ecf20Sopenharmony_ci bool has_press; 3478c2ecf20Sopenharmony_ci bool has_pinch; 3488c2ecf20Sopenharmony_ci bool has_chiral; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci bool query7_nonzero; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci /* query 8 */ 3538c2ecf20Sopenharmony_ci bool has_palm_det; 3548c2ecf20Sopenharmony_ci bool has_rotate; 3558c2ecf20Sopenharmony_ci bool has_touch_shapes; 3568c2ecf20Sopenharmony_ci bool has_scroll_zones; 3578c2ecf20Sopenharmony_ci bool has_individual_scroll_zones; 3588c2ecf20Sopenharmony_ci bool has_mf_scroll; 3598c2ecf20Sopenharmony_ci bool has_mf_edge_motion; 3608c2ecf20Sopenharmony_ci bool has_mf_scroll_inertia; 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci bool query8_nonzero; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci /* Query 9 */ 3658c2ecf20Sopenharmony_ci bool has_pen; 3668c2ecf20Sopenharmony_ci bool has_proximity; 3678c2ecf20Sopenharmony_ci bool has_palm_det_sensitivity; 3688c2ecf20Sopenharmony_ci bool has_suppress_on_palm_detect; 3698c2ecf20Sopenharmony_ci bool has_two_pen_thresholds; 3708c2ecf20Sopenharmony_ci bool has_contact_geometry; 3718c2ecf20Sopenharmony_ci bool has_pen_hover_discrimination; 3728c2ecf20Sopenharmony_ci bool has_pen_filters; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci /* Query 10 */ 3758c2ecf20Sopenharmony_ci u8 nr_touch_shapes; 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci /* Query 11. */ 3788c2ecf20Sopenharmony_ci bool has_z_tuning; 3798c2ecf20Sopenharmony_ci bool has_algorithm_selection; 3808c2ecf20Sopenharmony_ci bool has_w_tuning; 3818c2ecf20Sopenharmony_ci bool has_pitch_info; 3828c2ecf20Sopenharmony_ci bool has_finger_size; 3838c2ecf20Sopenharmony_ci bool has_segmentation_aggressiveness; 3848c2ecf20Sopenharmony_ci bool has_XY_clip; 3858c2ecf20Sopenharmony_ci bool has_drumming_filter; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci /* Query 12 */ 3888c2ecf20Sopenharmony_ci bool has_gapless_finger; 3898c2ecf20Sopenharmony_ci bool has_gapless_finger_tuning; 3908c2ecf20Sopenharmony_ci bool has_8bit_w; 3918c2ecf20Sopenharmony_ci bool has_adjustable_mapping; 3928c2ecf20Sopenharmony_ci bool has_info2; 3938c2ecf20Sopenharmony_ci bool has_physical_props; 3948c2ecf20Sopenharmony_ci bool has_finger_limit; 3958c2ecf20Sopenharmony_ci bool has_linear_coeff_2; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci /* Query 13 */ 3988c2ecf20Sopenharmony_ci u8 jitter_window_size; 3998c2ecf20Sopenharmony_ci u8 jitter_filter_type; 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci /* Query 14 */ 4028c2ecf20Sopenharmony_ci u8 light_control; 4038c2ecf20Sopenharmony_ci bool is_clear; 4048c2ecf20Sopenharmony_ci u8 clickpad_props; 4058c2ecf20Sopenharmony_ci u8 mouse_buttons; 4068c2ecf20Sopenharmony_ci bool has_advanced_gestures; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci /* Query 15 - 18 */ 4098c2ecf20Sopenharmony_ci u16 x_sensor_size_mm; 4108c2ecf20Sopenharmony_ci u16 y_sensor_size_mm; 4118c2ecf20Sopenharmony_ci}; 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci/* Defs for Ctrl0. */ 4148c2ecf20Sopenharmony_ci#define RMI_F11_REPORT_MODE_MASK 0x07 4158c2ecf20Sopenharmony_ci#define RMI_F11_REPORT_MODE_CONTINUOUS (0 << 0) 4168c2ecf20Sopenharmony_ci#define RMI_F11_REPORT_MODE_REDUCED (1 << 0) 4178c2ecf20Sopenharmony_ci#define RMI_F11_REPORT_MODE_FS_CHANGE (2 << 0) 4188c2ecf20Sopenharmony_ci#define RMI_F11_REPORT_MODE_FP_CHANGE (3 << 0) 4198c2ecf20Sopenharmony_ci#define RMI_F11_ABS_POS_FILT (1 << 3) 4208c2ecf20Sopenharmony_ci#define RMI_F11_REL_POS_FILT (1 << 4) 4218c2ecf20Sopenharmony_ci#define RMI_F11_REL_BALLISTICS (1 << 5) 4228c2ecf20Sopenharmony_ci#define RMI_F11_DRIBBLE (1 << 6) 4238c2ecf20Sopenharmony_ci#define RMI_F11_REPORT_BEYOND_CLIP (1 << 7) 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci/* Defs for Ctrl1. */ 4268c2ecf20Sopenharmony_ci#define RMI_F11_PALM_DETECT_THRESH_MASK 0x0F 4278c2ecf20Sopenharmony_ci#define RMI_F11_MOTION_SENSITIVITY_MASK 0x30 4288c2ecf20Sopenharmony_ci#define RMI_F11_MANUAL_TRACKING (1 << 6) 4298c2ecf20Sopenharmony_ci#define RMI_F11_MANUAL_TRACKED_FINGER (1 << 7) 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci#define RMI_F11_DELTA_X_THRESHOLD 2 4328c2ecf20Sopenharmony_ci#define RMI_F11_DELTA_Y_THRESHOLD 3 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci#define RMI_F11_CTRL_REG_COUNT 12 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_cistruct f11_2d_ctrl { 4378c2ecf20Sopenharmony_ci u8 ctrl0_11[RMI_F11_CTRL_REG_COUNT]; 4388c2ecf20Sopenharmony_ci u16 ctrl0_11_address; 4398c2ecf20Sopenharmony_ci}; 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci#define RMI_F11_ABS_BYTES 5 4428c2ecf20Sopenharmony_ci#define RMI_F11_REL_BYTES 2 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci/* Defs for Data 8 */ 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci#define RMI_F11_SINGLE_TAP (1 << 0) 4478c2ecf20Sopenharmony_ci#define RMI_F11_TAP_AND_HOLD (1 << 1) 4488c2ecf20Sopenharmony_ci#define RMI_F11_DOUBLE_TAP (1 << 2) 4498c2ecf20Sopenharmony_ci#define RMI_F11_EARLY_TAP (1 << 3) 4508c2ecf20Sopenharmony_ci#define RMI_F11_FLICK (1 << 4) 4518c2ecf20Sopenharmony_ci#define RMI_F11_PRESS (1 << 5) 4528c2ecf20Sopenharmony_ci#define RMI_F11_PINCH (1 << 6) 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci/* Defs for Data 9 */ 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci#define RMI_F11_PALM_DETECT (1 << 0) 4578c2ecf20Sopenharmony_ci#define RMI_F11_ROTATE (1 << 1) 4588c2ecf20Sopenharmony_ci#define RMI_F11_SHAPE (1 << 2) 4598c2ecf20Sopenharmony_ci#define RMI_F11_SCROLLZONE (1 << 3) 4608c2ecf20Sopenharmony_ci#define RMI_F11_GESTURE_FINGER_COUNT_MASK 0x70 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci/** Handy pointers into our data buffer. 4638c2ecf20Sopenharmony_ci * 4648c2ecf20Sopenharmony_ci * @f_state - start of finger state registers. 4658c2ecf20Sopenharmony_ci * @abs_pos - start of absolute position registers (if present). 4668c2ecf20Sopenharmony_ci * @rel_pos - start of relative data registers (if present). 4678c2ecf20Sopenharmony_ci * @gest_1 - gesture flags (if present). 4688c2ecf20Sopenharmony_ci * @gest_2 - gesture flags & finger count (if present). 4698c2ecf20Sopenharmony_ci * @pinch - pinch motion register (if present). 4708c2ecf20Sopenharmony_ci * @flick - flick distance X & Y, flick time (if present). 4718c2ecf20Sopenharmony_ci * @rotate - rotate motion and finger separation. 4728c2ecf20Sopenharmony_ci * @multi_scroll - chiral deltas for X and Y (if present). 4738c2ecf20Sopenharmony_ci * @scroll_zones - scroll deltas for 4 regions (if present). 4748c2ecf20Sopenharmony_ci */ 4758c2ecf20Sopenharmony_cistruct f11_2d_data { 4768c2ecf20Sopenharmony_ci u8 *f_state; 4778c2ecf20Sopenharmony_ci u8 *abs_pos; 4788c2ecf20Sopenharmony_ci s8 *rel_pos; 4798c2ecf20Sopenharmony_ci u8 *gest_1; 4808c2ecf20Sopenharmony_ci u8 *gest_2; 4818c2ecf20Sopenharmony_ci s8 *pinch; 4828c2ecf20Sopenharmony_ci u8 *flick; 4838c2ecf20Sopenharmony_ci u8 *rotate; 4848c2ecf20Sopenharmony_ci u8 *shapes; 4858c2ecf20Sopenharmony_ci s8 *multi_scroll; 4868c2ecf20Sopenharmony_ci s8 *scroll_zones; 4878c2ecf20Sopenharmony_ci}; 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci/** Data pertaining to F11 in general. For per-sensor data, see struct 4908c2ecf20Sopenharmony_ci * f11_2d_sensor. 4918c2ecf20Sopenharmony_ci * 4928c2ecf20Sopenharmony_ci * @dev_query - F11 device specific query registers. 4938c2ecf20Sopenharmony_ci * @dev_controls - F11 device specific control registers. 4948c2ecf20Sopenharmony_ci * @dev_controls_mutex - lock for the control registers. 4958c2ecf20Sopenharmony_ci * @rezero_wait_ms - if nonzero, upon resume we will wait this many 4968c2ecf20Sopenharmony_ci * milliseconds before rezeroing the sensor(s). This is useful in systems with 4978c2ecf20Sopenharmony_ci * poor electrical behavior on resume, where the initial calibration of the 4988c2ecf20Sopenharmony_ci * sensor(s) coming out of sleep state may be bogus. 4998c2ecf20Sopenharmony_ci * @sensors - per sensor data structures. 5008c2ecf20Sopenharmony_ci */ 5018c2ecf20Sopenharmony_cistruct f11_data { 5028c2ecf20Sopenharmony_ci bool has_query9; 5038c2ecf20Sopenharmony_ci bool has_query11; 5048c2ecf20Sopenharmony_ci bool has_query12; 5058c2ecf20Sopenharmony_ci bool has_query27; 5068c2ecf20Sopenharmony_ci bool has_query28; 5078c2ecf20Sopenharmony_ci bool has_acm; 5088c2ecf20Sopenharmony_ci struct f11_2d_ctrl dev_controls; 5098c2ecf20Sopenharmony_ci struct mutex dev_controls_mutex; 5108c2ecf20Sopenharmony_ci u16 rezero_wait_ms; 5118c2ecf20Sopenharmony_ci struct rmi_2d_sensor sensor; 5128c2ecf20Sopenharmony_ci struct f11_2d_sensor_queries sens_query; 5138c2ecf20Sopenharmony_ci struct f11_2d_data data; 5148c2ecf20Sopenharmony_ci struct rmi_2d_sensor_platform_data sensor_pdata; 5158c2ecf20Sopenharmony_ci unsigned long *abs_mask; 5168c2ecf20Sopenharmony_ci unsigned long *rel_mask; 5178c2ecf20Sopenharmony_ci}; 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_cienum f11_finger_state { 5208c2ecf20Sopenharmony_ci F11_NO_FINGER = 0x00, 5218c2ecf20Sopenharmony_ci F11_PRESENT = 0x01, 5228c2ecf20Sopenharmony_ci F11_INACCURATE = 0x02, 5238c2ecf20Sopenharmony_ci F11_RESERVED = 0x03 5248c2ecf20Sopenharmony_ci}; 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_cistatic void rmi_f11_rel_pos_report(struct f11_data *f11, u8 n_finger) 5278c2ecf20Sopenharmony_ci{ 5288c2ecf20Sopenharmony_ci struct rmi_2d_sensor *sensor = &f11->sensor; 5298c2ecf20Sopenharmony_ci struct f11_2d_data *data = &f11->data; 5308c2ecf20Sopenharmony_ci s8 x, y; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci x = data->rel_pos[n_finger * RMI_F11_REL_BYTES]; 5338c2ecf20Sopenharmony_ci y = data->rel_pos[n_finger * RMI_F11_REL_BYTES + 1]; 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci rmi_2d_sensor_rel_report(sensor, x, y); 5368c2ecf20Sopenharmony_ci} 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_cistatic void rmi_f11_abs_pos_process(struct f11_data *f11, 5398c2ecf20Sopenharmony_ci struct rmi_2d_sensor *sensor, 5408c2ecf20Sopenharmony_ci struct rmi_2d_sensor_abs_object *obj, 5418c2ecf20Sopenharmony_ci enum f11_finger_state finger_state, 5428c2ecf20Sopenharmony_ci u8 n_finger) 5438c2ecf20Sopenharmony_ci{ 5448c2ecf20Sopenharmony_ci struct f11_2d_data *data = &f11->data; 5458c2ecf20Sopenharmony_ci u8 *pos_data = &data->abs_pos[n_finger * RMI_F11_ABS_BYTES]; 5468c2ecf20Sopenharmony_ci int tool_type = MT_TOOL_FINGER; 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci switch (finger_state) { 5498c2ecf20Sopenharmony_ci case F11_PRESENT: 5508c2ecf20Sopenharmony_ci obj->type = RMI_2D_OBJECT_FINGER; 5518c2ecf20Sopenharmony_ci break; 5528c2ecf20Sopenharmony_ci default: 5538c2ecf20Sopenharmony_ci obj->type = RMI_2D_OBJECT_NONE; 5548c2ecf20Sopenharmony_ci } 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci obj->mt_tool = tool_type; 5578c2ecf20Sopenharmony_ci obj->x = (pos_data[0] << 4) | (pos_data[2] & 0x0F); 5588c2ecf20Sopenharmony_ci obj->y = (pos_data[1] << 4) | (pos_data[2] >> 4); 5598c2ecf20Sopenharmony_ci obj->z = pos_data[4]; 5608c2ecf20Sopenharmony_ci obj->wx = pos_data[3] & 0x0f; 5618c2ecf20Sopenharmony_ci obj->wy = pos_data[3] >> 4; 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci rmi_2d_sensor_abs_process(sensor, obj, n_finger); 5648c2ecf20Sopenharmony_ci} 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_cistatic inline u8 rmi_f11_parse_finger_state(const u8 *f_state, u8 n_finger) 5678c2ecf20Sopenharmony_ci{ 5688c2ecf20Sopenharmony_ci return (f_state[n_finger / 4] >> (2 * (n_finger % 4))) & 5698c2ecf20Sopenharmony_ci FINGER_STATE_MASK; 5708c2ecf20Sopenharmony_ci} 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_cistatic void rmi_f11_finger_handler(struct f11_data *f11, 5738c2ecf20Sopenharmony_ci struct rmi_2d_sensor *sensor, int size) 5748c2ecf20Sopenharmony_ci{ 5758c2ecf20Sopenharmony_ci const u8 *f_state = f11->data.f_state; 5768c2ecf20Sopenharmony_ci u8 finger_state; 5778c2ecf20Sopenharmony_ci u8 i; 5788c2ecf20Sopenharmony_ci int abs_fingers; 5798c2ecf20Sopenharmony_ci int rel_fingers; 5808c2ecf20Sopenharmony_ci int abs_size = sensor->nbr_fingers * RMI_F11_ABS_BYTES; 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci if (sensor->report_abs) { 5838c2ecf20Sopenharmony_ci if (abs_size > size) 5848c2ecf20Sopenharmony_ci abs_fingers = size / RMI_F11_ABS_BYTES; 5858c2ecf20Sopenharmony_ci else 5868c2ecf20Sopenharmony_ci abs_fingers = sensor->nbr_fingers; 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci for (i = 0; i < abs_fingers; i++) { 5898c2ecf20Sopenharmony_ci /* Possible of having 4 fingers per f_state register */ 5908c2ecf20Sopenharmony_ci finger_state = rmi_f11_parse_finger_state(f_state, i); 5918c2ecf20Sopenharmony_ci if (finger_state == F11_RESERVED) { 5928c2ecf20Sopenharmony_ci pr_err("Invalid finger state[%d]: 0x%02x", i, 5938c2ecf20Sopenharmony_ci finger_state); 5948c2ecf20Sopenharmony_ci continue; 5958c2ecf20Sopenharmony_ci } 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci rmi_f11_abs_pos_process(f11, sensor, &sensor->objs[i], 5988c2ecf20Sopenharmony_ci finger_state, i); 5998c2ecf20Sopenharmony_ci } 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci /* 6028c2ecf20Sopenharmony_ci * the absolute part is made in 2 parts to allow the kernel 6038c2ecf20Sopenharmony_ci * tracking to take place. 6048c2ecf20Sopenharmony_ci */ 6058c2ecf20Sopenharmony_ci if (sensor->kernel_tracking) 6068c2ecf20Sopenharmony_ci input_mt_assign_slots(sensor->input, 6078c2ecf20Sopenharmony_ci sensor->tracking_slots, 6088c2ecf20Sopenharmony_ci sensor->tracking_pos, 6098c2ecf20Sopenharmony_ci sensor->nbr_fingers, 6108c2ecf20Sopenharmony_ci sensor->dmax); 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci for (i = 0; i < abs_fingers; i++) { 6138c2ecf20Sopenharmony_ci finger_state = rmi_f11_parse_finger_state(f_state, i); 6148c2ecf20Sopenharmony_ci if (finger_state == F11_RESERVED) 6158c2ecf20Sopenharmony_ci /* no need to send twice the error */ 6168c2ecf20Sopenharmony_ci continue; 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci rmi_2d_sensor_abs_report(sensor, &sensor->objs[i], i); 6198c2ecf20Sopenharmony_ci } 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci input_mt_sync_frame(sensor->input); 6228c2ecf20Sopenharmony_ci } else if (sensor->report_rel) { 6238c2ecf20Sopenharmony_ci if ((abs_size + sensor->nbr_fingers * RMI_F11_REL_BYTES) > size) 6248c2ecf20Sopenharmony_ci rel_fingers = (size - abs_size) / RMI_F11_REL_BYTES; 6258c2ecf20Sopenharmony_ci else 6268c2ecf20Sopenharmony_ci rel_fingers = sensor->nbr_fingers; 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci for (i = 0; i < rel_fingers; i++) 6298c2ecf20Sopenharmony_ci rmi_f11_rel_pos_report(f11, i); 6308c2ecf20Sopenharmony_ci } 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci} 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_cistatic int f11_2d_construct_data(struct f11_data *f11) 6358c2ecf20Sopenharmony_ci{ 6368c2ecf20Sopenharmony_ci struct rmi_2d_sensor *sensor = &f11->sensor; 6378c2ecf20Sopenharmony_ci struct f11_2d_sensor_queries *query = &f11->sens_query; 6388c2ecf20Sopenharmony_ci struct f11_2d_data *data = &f11->data; 6398c2ecf20Sopenharmony_ci int i; 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci sensor->nbr_fingers = (query->nr_fingers == 5 ? 10 : 6428c2ecf20Sopenharmony_ci query->nr_fingers + 1); 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci sensor->pkt_size = DIV_ROUND_UP(sensor->nbr_fingers, 4); 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci if (query->has_abs) { 6478c2ecf20Sopenharmony_ci sensor->pkt_size += (sensor->nbr_fingers * 5); 6488c2ecf20Sopenharmony_ci sensor->attn_size = sensor->pkt_size; 6498c2ecf20Sopenharmony_ci } 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci if (query->has_rel) 6528c2ecf20Sopenharmony_ci sensor->pkt_size += (sensor->nbr_fingers * 2); 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci /* Check if F11_2D_Query7 is non-zero */ 6558c2ecf20Sopenharmony_ci if (query->query7_nonzero) 6568c2ecf20Sopenharmony_ci sensor->pkt_size += sizeof(u8); 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci /* Check if F11_2D_Query7 or F11_2D_Query8 is non-zero */ 6598c2ecf20Sopenharmony_ci if (query->query7_nonzero || query->query8_nonzero) 6608c2ecf20Sopenharmony_ci sensor->pkt_size += sizeof(u8); 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci if (query->has_pinch || query->has_flick || query->has_rotate) { 6638c2ecf20Sopenharmony_ci sensor->pkt_size += 3; 6648c2ecf20Sopenharmony_ci if (!query->has_flick) 6658c2ecf20Sopenharmony_ci sensor->pkt_size--; 6668c2ecf20Sopenharmony_ci if (!query->has_rotate) 6678c2ecf20Sopenharmony_ci sensor->pkt_size--; 6688c2ecf20Sopenharmony_ci } 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci if (query->has_touch_shapes) 6718c2ecf20Sopenharmony_ci sensor->pkt_size += 6728c2ecf20Sopenharmony_ci DIV_ROUND_UP(query->nr_touch_shapes + 1, 8); 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci sensor->data_pkt = devm_kzalloc(&sensor->fn->dev, sensor->pkt_size, 6758c2ecf20Sopenharmony_ci GFP_KERNEL); 6768c2ecf20Sopenharmony_ci if (!sensor->data_pkt) 6778c2ecf20Sopenharmony_ci return -ENOMEM; 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci data->f_state = sensor->data_pkt; 6808c2ecf20Sopenharmony_ci i = DIV_ROUND_UP(sensor->nbr_fingers, 4); 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci if (query->has_abs) { 6838c2ecf20Sopenharmony_ci data->abs_pos = &sensor->data_pkt[i]; 6848c2ecf20Sopenharmony_ci i += (sensor->nbr_fingers * RMI_F11_ABS_BYTES); 6858c2ecf20Sopenharmony_ci } 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_ci if (query->has_rel) { 6888c2ecf20Sopenharmony_ci data->rel_pos = &sensor->data_pkt[i]; 6898c2ecf20Sopenharmony_ci i += (sensor->nbr_fingers * RMI_F11_REL_BYTES); 6908c2ecf20Sopenharmony_ci } 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci if (query->query7_nonzero) { 6938c2ecf20Sopenharmony_ci data->gest_1 = &sensor->data_pkt[i]; 6948c2ecf20Sopenharmony_ci i++; 6958c2ecf20Sopenharmony_ci } 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci if (query->query7_nonzero || query->query8_nonzero) { 6988c2ecf20Sopenharmony_ci data->gest_2 = &sensor->data_pkt[i]; 6998c2ecf20Sopenharmony_ci i++; 7008c2ecf20Sopenharmony_ci } 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci if (query->has_pinch) { 7038c2ecf20Sopenharmony_ci data->pinch = &sensor->data_pkt[i]; 7048c2ecf20Sopenharmony_ci i++; 7058c2ecf20Sopenharmony_ci } 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci if (query->has_flick) { 7088c2ecf20Sopenharmony_ci if (query->has_pinch) { 7098c2ecf20Sopenharmony_ci data->flick = data->pinch; 7108c2ecf20Sopenharmony_ci i += 2; 7118c2ecf20Sopenharmony_ci } else { 7128c2ecf20Sopenharmony_ci data->flick = &sensor->data_pkt[i]; 7138c2ecf20Sopenharmony_ci i += 3; 7148c2ecf20Sopenharmony_ci } 7158c2ecf20Sopenharmony_ci } 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci if (query->has_rotate) { 7188c2ecf20Sopenharmony_ci if (query->has_flick) { 7198c2ecf20Sopenharmony_ci data->rotate = data->flick + 1; 7208c2ecf20Sopenharmony_ci } else { 7218c2ecf20Sopenharmony_ci data->rotate = &sensor->data_pkt[i]; 7228c2ecf20Sopenharmony_ci i += 2; 7238c2ecf20Sopenharmony_ci } 7248c2ecf20Sopenharmony_ci } 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci if (query->has_touch_shapes) 7278c2ecf20Sopenharmony_ci data->shapes = &sensor->data_pkt[i]; 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci return 0; 7308c2ecf20Sopenharmony_ci} 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_cistatic int f11_read_control_regs(struct rmi_function *fn, 7338c2ecf20Sopenharmony_ci struct f11_2d_ctrl *ctrl, u16 ctrl_base_addr) { 7348c2ecf20Sopenharmony_ci struct rmi_device *rmi_dev = fn->rmi_dev; 7358c2ecf20Sopenharmony_ci int error = 0; 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci ctrl->ctrl0_11_address = ctrl_base_addr; 7388c2ecf20Sopenharmony_ci error = rmi_read_block(rmi_dev, ctrl_base_addr, ctrl->ctrl0_11, 7398c2ecf20Sopenharmony_ci RMI_F11_CTRL_REG_COUNT); 7408c2ecf20Sopenharmony_ci if (error < 0) { 7418c2ecf20Sopenharmony_ci dev_err(&fn->dev, "Failed to read ctrl0, code: %d.\n", error); 7428c2ecf20Sopenharmony_ci return error; 7438c2ecf20Sopenharmony_ci } 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci return 0; 7468c2ecf20Sopenharmony_ci} 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_cistatic int f11_write_control_regs(struct rmi_function *fn, 7498c2ecf20Sopenharmony_ci struct f11_2d_sensor_queries *query, 7508c2ecf20Sopenharmony_ci struct f11_2d_ctrl *ctrl, 7518c2ecf20Sopenharmony_ci u16 ctrl_base_addr) 7528c2ecf20Sopenharmony_ci{ 7538c2ecf20Sopenharmony_ci struct rmi_device *rmi_dev = fn->rmi_dev; 7548c2ecf20Sopenharmony_ci int error; 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci error = rmi_write_block(rmi_dev, ctrl_base_addr, ctrl->ctrl0_11, 7578c2ecf20Sopenharmony_ci RMI_F11_CTRL_REG_COUNT); 7588c2ecf20Sopenharmony_ci if (error < 0) 7598c2ecf20Sopenharmony_ci return error; 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci return 0; 7628c2ecf20Sopenharmony_ci} 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_cistatic int rmi_f11_get_query_parameters(struct rmi_device *rmi_dev, 7658c2ecf20Sopenharmony_ci struct f11_data *f11, 7668c2ecf20Sopenharmony_ci struct f11_2d_sensor_queries *sensor_query, 7678c2ecf20Sopenharmony_ci u16 query_base_addr) 7688c2ecf20Sopenharmony_ci{ 7698c2ecf20Sopenharmony_ci int query_size; 7708c2ecf20Sopenharmony_ci int rc; 7718c2ecf20Sopenharmony_ci u8 query_buf[RMI_F11_QUERY_SIZE]; 7728c2ecf20Sopenharmony_ci bool has_query36 = false; 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci rc = rmi_read_block(rmi_dev, query_base_addr, query_buf, 7758c2ecf20Sopenharmony_ci RMI_F11_QUERY_SIZE); 7768c2ecf20Sopenharmony_ci if (rc < 0) 7778c2ecf20Sopenharmony_ci return rc; 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci sensor_query->nr_fingers = query_buf[0] & RMI_F11_NR_FINGERS_MASK; 7808c2ecf20Sopenharmony_ci sensor_query->has_rel = !!(query_buf[0] & RMI_F11_HAS_REL); 7818c2ecf20Sopenharmony_ci sensor_query->has_abs = !!(query_buf[0] & RMI_F11_HAS_ABS); 7828c2ecf20Sopenharmony_ci sensor_query->has_gestures = !!(query_buf[0] & RMI_F11_HAS_GESTURES); 7838c2ecf20Sopenharmony_ci sensor_query->has_sensitivity_adjust = 7848c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_SENSITIVITY_ADJ); 7858c2ecf20Sopenharmony_ci sensor_query->configurable = !!(query_buf[0] & RMI_F11_CONFIGURABLE); 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci sensor_query->nr_x_electrodes = 7888c2ecf20Sopenharmony_ci query_buf[1] & RMI_F11_NR_ELECTRODES_MASK; 7898c2ecf20Sopenharmony_ci sensor_query->nr_y_electrodes = 7908c2ecf20Sopenharmony_ci query_buf[2] & RMI_F11_NR_ELECTRODES_MASK; 7918c2ecf20Sopenharmony_ci sensor_query->max_electrodes = 7928c2ecf20Sopenharmony_ci query_buf[3] & RMI_F11_NR_ELECTRODES_MASK; 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_ci query_size = RMI_F11_QUERY_SIZE; 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci if (sensor_query->has_abs) { 7978c2ecf20Sopenharmony_ci rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf); 7988c2ecf20Sopenharmony_ci if (rc < 0) 7998c2ecf20Sopenharmony_ci return rc; 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci sensor_query->abs_data_size = 8028c2ecf20Sopenharmony_ci query_buf[0] & RMI_F11_ABS_DATA_SIZE_MASK; 8038c2ecf20Sopenharmony_ci sensor_query->has_anchored_finger = 8048c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_ANCHORED_FINGER); 8058c2ecf20Sopenharmony_ci sensor_query->has_adj_hyst = 8068c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_ADJ_HYST); 8078c2ecf20Sopenharmony_ci sensor_query->has_dribble = 8088c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_DRIBBLE); 8098c2ecf20Sopenharmony_ci sensor_query->has_bending_correction = 8108c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_BENDING_CORRECTION); 8118c2ecf20Sopenharmony_ci sensor_query->has_large_object_suppression = 8128c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_LARGE_OBJECT_SUPPRESSION); 8138c2ecf20Sopenharmony_ci sensor_query->has_jitter_filter = 8148c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_JITTER_FILTER); 8158c2ecf20Sopenharmony_ci query_size++; 8168c2ecf20Sopenharmony_ci } 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci if (sensor_query->has_rel) { 8198c2ecf20Sopenharmony_ci rc = rmi_read(rmi_dev, query_base_addr + query_size, 8208c2ecf20Sopenharmony_ci &sensor_query->f11_2d_query6); 8218c2ecf20Sopenharmony_ci if (rc < 0) 8228c2ecf20Sopenharmony_ci return rc; 8238c2ecf20Sopenharmony_ci query_size++; 8248c2ecf20Sopenharmony_ci } 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci if (sensor_query->has_gestures) { 8278c2ecf20Sopenharmony_ci rc = rmi_read_block(rmi_dev, query_base_addr + query_size, 8288c2ecf20Sopenharmony_ci query_buf, RMI_F11_QUERY_GESTURE_SIZE); 8298c2ecf20Sopenharmony_ci if (rc < 0) 8308c2ecf20Sopenharmony_ci return rc; 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci sensor_query->has_single_tap = 8338c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_SINGLE_TAP); 8348c2ecf20Sopenharmony_ci sensor_query->has_tap_n_hold = 8358c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_TAP_AND_HOLD); 8368c2ecf20Sopenharmony_ci sensor_query->has_double_tap = 8378c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_DOUBLE_TAP); 8388c2ecf20Sopenharmony_ci sensor_query->has_early_tap = 8398c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_EARLY_TAP); 8408c2ecf20Sopenharmony_ci sensor_query->has_flick = 8418c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_FLICK); 8428c2ecf20Sopenharmony_ci sensor_query->has_press = 8438c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_PRESS); 8448c2ecf20Sopenharmony_ci sensor_query->has_pinch = 8458c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_PINCH); 8468c2ecf20Sopenharmony_ci sensor_query->has_chiral = 8478c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_CHIRAL); 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci /* query 8 */ 8508c2ecf20Sopenharmony_ci sensor_query->has_palm_det = 8518c2ecf20Sopenharmony_ci !!(query_buf[1] & RMI_F11_HAS_PALM_DET); 8528c2ecf20Sopenharmony_ci sensor_query->has_rotate = 8538c2ecf20Sopenharmony_ci !!(query_buf[1] & RMI_F11_HAS_ROTATE); 8548c2ecf20Sopenharmony_ci sensor_query->has_touch_shapes = 8558c2ecf20Sopenharmony_ci !!(query_buf[1] & RMI_F11_HAS_TOUCH_SHAPES); 8568c2ecf20Sopenharmony_ci sensor_query->has_scroll_zones = 8578c2ecf20Sopenharmony_ci !!(query_buf[1] & RMI_F11_HAS_SCROLL_ZONES); 8588c2ecf20Sopenharmony_ci sensor_query->has_individual_scroll_zones = 8598c2ecf20Sopenharmony_ci !!(query_buf[1] & RMI_F11_HAS_INDIVIDUAL_SCROLL_ZONES); 8608c2ecf20Sopenharmony_ci sensor_query->has_mf_scroll = 8618c2ecf20Sopenharmony_ci !!(query_buf[1] & RMI_F11_HAS_MF_SCROLL); 8628c2ecf20Sopenharmony_ci sensor_query->has_mf_edge_motion = 8638c2ecf20Sopenharmony_ci !!(query_buf[1] & RMI_F11_HAS_MF_EDGE_MOTION); 8648c2ecf20Sopenharmony_ci sensor_query->has_mf_scroll_inertia = 8658c2ecf20Sopenharmony_ci !!(query_buf[1] & RMI_F11_HAS_MF_SCROLL_INERTIA); 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_ci sensor_query->query7_nonzero = !!(query_buf[0]); 8688c2ecf20Sopenharmony_ci sensor_query->query8_nonzero = !!(query_buf[1]); 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ci query_size += 2; 8718c2ecf20Sopenharmony_ci } 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci if (f11->has_query9) { 8748c2ecf20Sopenharmony_ci rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf); 8758c2ecf20Sopenharmony_ci if (rc < 0) 8768c2ecf20Sopenharmony_ci return rc; 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci sensor_query->has_pen = 8798c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_PEN); 8808c2ecf20Sopenharmony_ci sensor_query->has_proximity = 8818c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_PROXIMITY); 8828c2ecf20Sopenharmony_ci sensor_query->has_palm_det_sensitivity = 8838c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_PALM_DET_SENSITIVITY); 8848c2ecf20Sopenharmony_ci sensor_query->has_suppress_on_palm_detect = 8858c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_SUPPRESS_ON_PALM_DETECT); 8868c2ecf20Sopenharmony_ci sensor_query->has_two_pen_thresholds = 8878c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_TWO_PEN_THRESHOLDS); 8888c2ecf20Sopenharmony_ci sensor_query->has_contact_geometry = 8898c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_CONTACT_GEOMETRY); 8908c2ecf20Sopenharmony_ci sensor_query->has_pen_hover_discrimination = 8918c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_PEN_HOVER_DISCRIMINATION); 8928c2ecf20Sopenharmony_ci sensor_query->has_pen_filters = 8938c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_PEN_FILTERS); 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci query_size++; 8968c2ecf20Sopenharmony_ci } 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci if (sensor_query->has_touch_shapes) { 8998c2ecf20Sopenharmony_ci rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf); 9008c2ecf20Sopenharmony_ci if (rc < 0) 9018c2ecf20Sopenharmony_ci return rc; 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ci sensor_query->nr_touch_shapes = query_buf[0] & 9048c2ecf20Sopenharmony_ci RMI_F11_NR_TOUCH_SHAPES_MASK; 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_ci query_size++; 9078c2ecf20Sopenharmony_ci } 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci if (f11->has_query11) { 9108c2ecf20Sopenharmony_ci rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf); 9118c2ecf20Sopenharmony_ci if (rc < 0) 9128c2ecf20Sopenharmony_ci return rc; 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci sensor_query->has_z_tuning = 9158c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_Z_TUNING); 9168c2ecf20Sopenharmony_ci sensor_query->has_algorithm_selection = 9178c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_ALGORITHM_SELECTION); 9188c2ecf20Sopenharmony_ci sensor_query->has_w_tuning = 9198c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_W_TUNING); 9208c2ecf20Sopenharmony_ci sensor_query->has_pitch_info = 9218c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_PITCH_INFO); 9228c2ecf20Sopenharmony_ci sensor_query->has_finger_size = 9238c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_FINGER_SIZE); 9248c2ecf20Sopenharmony_ci sensor_query->has_segmentation_aggressiveness = 9258c2ecf20Sopenharmony_ci !!(query_buf[0] & 9268c2ecf20Sopenharmony_ci RMI_F11_HAS_SEGMENTATION_AGGRESSIVENESS); 9278c2ecf20Sopenharmony_ci sensor_query->has_XY_clip = 9288c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_XY_CLIP); 9298c2ecf20Sopenharmony_ci sensor_query->has_drumming_filter = 9308c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_DRUMMING_FILTER); 9318c2ecf20Sopenharmony_ci 9328c2ecf20Sopenharmony_ci query_size++; 9338c2ecf20Sopenharmony_ci } 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_ci if (f11->has_query12) { 9368c2ecf20Sopenharmony_ci rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf); 9378c2ecf20Sopenharmony_ci if (rc < 0) 9388c2ecf20Sopenharmony_ci return rc; 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_ci sensor_query->has_gapless_finger = 9418c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_GAPLESS_FINGER); 9428c2ecf20Sopenharmony_ci sensor_query->has_gapless_finger_tuning = 9438c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_GAPLESS_FINGER_TUNING); 9448c2ecf20Sopenharmony_ci sensor_query->has_8bit_w = 9458c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_8BIT_W); 9468c2ecf20Sopenharmony_ci sensor_query->has_adjustable_mapping = 9478c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_ADJUSTABLE_MAPPING); 9488c2ecf20Sopenharmony_ci sensor_query->has_info2 = 9498c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_INFO2); 9508c2ecf20Sopenharmony_ci sensor_query->has_physical_props = 9518c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_PHYSICAL_PROPS); 9528c2ecf20Sopenharmony_ci sensor_query->has_finger_limit = 9538c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_FINGER_LIMIT); 9548c2ecf20Sopenharmony_ci sensor_query->has_linear_coeff_2 = 9558c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_LINEAR_COEFF); 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci query_size++; 9588c2ecf20Sopenharmony_ci } 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci if (sensor_query->has_jitter_filter) { 9618c2ecf20Sopenharmony_ci rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf); 9628c2ecf20Sopenharmony_ci if (rc < 0) 9638c2ecf20Sopenharmony_ci return rc; 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci sensor_query->jitter_window_size = query_buf[0] & 9668c2ecf20Sopenharmony_ci RMI_F11_JITTER_WINDOW_MASK; 9678c2ecf20Sopenharmony_ci sensor_query->jitter_filter_type = (query_buf[0] & 9688c2ecf20Sopenharmony_ci RMI_F11_JITTER_FILTER_MASK) >> 9698c2ecf20Sopenharmony_ci RMI_F11_JITTER_FILTER_SHIFT; 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_ci query_size++; 9728c2ecf20Sopenharmony_ci } 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci if (sensor_query->has_info2) { 9758c2ecf20Sopenharmony_ci rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf); 9768c2ecf20Sopenharmony_ci if (rc < 0) 9778c2ecf20Sopenharmony_ci return rc; 9788c2ecf20Sopenharmony_ci 9798c2ecf20Sopenharmony_ci sensor_query->light_control = 9808c2ecf20Sopenharmony_ci query_buf[0] & RMI_F11_LIGHT_CONTROL_MASK; 9818c2ecf20Sopenharmony_ci sensor_query->is_clear = 9828c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_IS_CLEAR); 9838c2ecf20Sopenharmony_ci sensor_query->clickpad_props = 9848c2ecf20Sopenharmony_ci (query_buf[0] & RMI_F11_CLICKPAD_PROPS_MASK) >> 9858c2ecf20Sopenharmony_ci RMI_F11_CLICKPAD_PROPS_SHIFT; 9868c2ecf20Sopenharmony_ci sensor_query->mouse_buttons = 9878c2ecf20Sopenharmony_ci (query_buf[0] & RMI_F11_MOUSE_BUTTONS_MASK) >> 9888c2ecf20Sopenharmony_ci RMI_F11_MOUSE_BUTTONS_SHIFT; 9898c2ecf20Sopenharmony_ci sensor_query->has_advanced_gestures = 9908c2ecf20Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_ADVANCED_GESTURES); 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci query_size++; 9938c2ecf20Sopenharmony_ci } 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ci if (sensor_query->has_physical_props) { 9968c2ecf20Sopenharmony_ci rc = rmi_read_block(rmi_dev, query_base_addr 9978c2ecf20Sopenharmony_ci + query_size, query_buf, 4); 9988c2ecf20Sopenharmony_ci if (rc < 0) 9998c2ecf20Sopenharmony_ci return rc; 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci sensor_query->x_sensor_size_mm = 10028c2ecf20Sopenharmony_ci (query_buf[0] | (query_buf[1] << 8)) / 10; 10038c2ecf20Sopenharmony_ci sensor_query->y_sensor_size_mm = 10048c2ecf20Sopenharmony_ci (query_buf[2] | (query_buf[3] << 8)) / 10; 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_ci /* 10078c2ecf20Sopenharmony_ci * query 15 - 18 contain the size of the sensor 10088c2ecf20Sopenharmony_ci * and query 19 - 26 contain bezel dimensions 10098c2ecf20Sopenharmony_ci */ 10108c2ecf20Sopenharmony_ci query_size += 12; 10118c2ecf20Sopenharmony_ci } 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci if (f11->has_query27) 10148c2ecf20Sopenharmony_ci ++query_size; 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci if (f11->has_query28) { 10178c2ecf20Sopenharmony_ci rc = rmi_read(rmi_dev, query_base_addr + query_size, 10188c2ecf20Sopenharmony_ci query_buf); 10198c2ecf20Sopenharmony_ci if (rc < 0) 10208c2ecf20Sopenharmony_ci return rc; 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_ci has_query36 = !!(query_buf[0] & BIT(6)); 10238c2ecf20Sopenharmony_ci } 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci if (has_query36) { 10268c2ecf20Sopenharmony_ci query_size += 2; 10278c2ecf20Sopenharmony_ci rc = rmi_read(rmi_dev, query_base_addr + query_size, 10288c2ecf20Sopenharmony_ci query_buf); 10298c2ecf20Sopenharmony_ci if (rc < 0) 10308c2ecf20Sopenharmony_ci return rc; 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_ci if (!!(query_buf[0] & BIT(5))) 10338c2ecf20Sopenharmony_ci f11->has_acm = true; 10348c2ecf20Sopenharmony_ci } 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci return query_size; 10378c2ecf20Sopenharmony_ci} 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_cistatic int rmi_f11_initialize(struct rmi_function *fn) 10408c2ecf20Sopenharmony_ci{ 10418c2ecf20Sopenharmony_ci struct rmi_device *rmi_dev = fn->rmi_dev; 10428c2ecf20Sopenharmony_ci struct f11_data *f11; 10438c2ecf20Sopenharmony_ci struct f11_2d_ctrl *ctrl; 10448c2ecf20Sopenharmony_ci u8 query_offset; 10458c2ecf20Sopenharmony_ci u16 query_base_addr; 10468c2ecf20Sopenharmony_ci u16 control_base_addr; 10478c2ecf20Sopenharmony_ci u16 max_x_pos, max_y_pos; 10488c2ecf20Sopenharmony_ci int rc; 10498c2ecf20Sopenharmony_ci const struct rmi_device_platform_data *pdata = 10508c2ecf20Sopenharmony_ci rmi_get_platform_data(rmi_dev); 10518c2ecf20Sopenharmony_ci struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev); 10528c2ecf20Sopenharmony_ci struct rmi_2d_sensor *sensor; 10538c2ecf20Sopenharmony_ci u8 buf; 10548c2ecf20Sopenharmony_ci int mask_size; 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_ci rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Initializing F11 values.\n"); 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci mask_size = BITS_TO_LONGS(drvdata->irq_count) * sizeof(unsigned long); 10598c2ecf20Sopenharmony_ci 10608c2ecf20Sopenharmony_ci /* 10618c2ecf20Sopenharmony_ci ** init instance data, fill in values and create any sysfs files 10628c2ecf20Sopenharmony_ci */ 10638c2ecf20Sopenharmony_ci f11 = devm_kzalloc(&fn->dev, sizeof(struct f11_data) + mask_size * 2, 10648c2ecf20Sopenharmony_ci GFP_KERNEL); 10658c2ecf20Sopenharmony_ci if (!f11) 10668c2ecf20Sopenharmony_ci return -ENOMEM; 10678c2ecf20Sopenharmony_ci 10688c2ecf20Sopenharmony_ci if (fn->dev.of_node) { 10698c2ecf20Sopenharmony_ci rc = rmi_2d_sensor_of_probe(&fn->dev, &f11->sensor_pdata); 10708c2ecf20Sopenharmony_ci if (rc) 10718c2ecf20Sopenharmony_ci return rc; 10728c2ecf20Sopenharmony_ci } else { 10738c2ecf20Sopenharmony_ci f11->sensor_pdata = pdata->sensor_pdata; 10748c2ecf20Sopenharmony_ci } 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci f11->rezero_wait_ms = f11->sensor_pdata.rezero_wait; 10778c2ecf20Sopenharmony_ci 10788c2ecf20Sopenharmony_ci f11->abs_mask = (unsigned long *)((char *)f11 10798c2ecf20Sopenharmony_ci + sizeof(struct f11_data)); 10808c2ecf20Sopenharmony_ci f11->rel_mask = (unsigned long *)((char *)f11 10818c2ecf20Sopenharmony_ci + sizeof(struct f11_data) + mask_size); 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci set_bit(fn->irq_pos, f11->abs_mask); 10848c2ecf20Sopenharmony_ci set_bit(fn->irq_pos + 1, f11->rel_mask); 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_ci query_base_addr = fn->fd.query_base_addr; 10878c2ecf20Sopenharmony_ci control_base_addr = fn->fd.control_base_addr; 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci rc = rmi_read(rmi_dev, query_base_addr, &buf); 10908c2ecf20Sopenharmony_ci if (rc < 0) 10918c2ecf20Sopenharmony_ci return rc; 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci f11->has_query9 = !!(buf & RMI_F11_HAS_QUERY9); 10948c2ecf20Sopenharmony_ci f11->has_query11 = !!(buf & RMI_F11_HAS_QUERY11); 10958c2ecf20Sopenharmony_ci f11->has_query12 = !!(buf & RMI_F11_HAS_QUERY12); 10968c2ecf20Sopenharmony_ci f11->has_query27 = !!(buf & RMI_F11_HAS_QUERY27); 10978c2ecf20Sopenharmony_ci f11->has_query28 = !!(buf & RMI_F11_HAS_QUERY28); 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_ci query_offset = (query_base_addr + 1); 11008c2ecf20Sopenharmony_ci sensor = &f11->sensor; 11018c2ecf20Sopenharmony_ci sensor->fn = fn; 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_ci rc = rmi_f11_get_query_parameters(rmi_dev, f11, 11048c2ecf20Sopenharmony_ci &f11->sens_query, query_offset); 11058c2ecf20Sopenharmony_ci if (rc < 0) 11068c2ecf20Sopenharmony_ci return rc; 11078c2ecf20Sopenharmony_ci query_offset += rc; 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci rc = f11_read_control_regs(fn, &f11->dev_controls, 11108c2ecf20Sopenharmony_ci control_base_addr); 11118c2ecf20Sopenharmony_ci if (rc < 0) { 11128c2ecf20Sopenharmony_ci dev_err(&fn->dev, 11138c2ecf20Sopenharmony_ci "Failed to read F11 control params.\n"); 11148c2ecf20Sopenharmony_ci return rc; 11158c2ecf20Sopenharmony_ci } 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_ci if (f11->sens_query.has_info2) { 11188c2ecf20Sopenharmony_ci if (f11->sens_query.is_clear) 11198c2ecf20Sopenharmony_ci f11->sensor.sensor_type = rmi_sensor_touchscreen; 11208c2ecf20Sopenharmony_ci else 11218c2ecf20Sopenharmony_ci f11->sensor.sensor_type = rmi_sensor_touchpad; 11228c2ecf20Sopenharmony_ci } 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_ci sensor->report_abs = f11->sens_query.has_abs; 11258c2ecf20Sopenharmony_ci 11268c2ecf20Sopenharmony_ci sensor->axis_align = 11278c2ecf20Sopenharmony_ci f11->sensor_pdata.axis_align; 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_ci sensor->topbuttonpad = f11->sensor_pdata.topbuttonpad; 11308c2ecf20Sopenharmony_ci sensor->kernel_tracking = f11->sensor_pdata.kernel_tracking; 11318c2ecf20Sopenharmony_ci sensor->dmax = f11->sensor_pdata.dmax; 11328c2ecf20Sopenharmony_ci sensor->dribble = f11->sensor_pdata.dribble; 11338c2ecf20Sopenharmony_ci sensor->palm_detect = f11->sensor_pdata.palm_detect; 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_ci if (f11->sens_query.has_physical_props) { 11368c2ecf20Sopenharmony_ci sensor->x_mm = f11->sens_query.x_sensor_size_mm; 11378c2ecf20Sopenharmony_ci sensor->y_mm = f11->sens_query.y_sensor_size_mm; 11388c2ecf20Sopenharmony_ci } else { 11398c2ecf20Sopenharmony_ci sensor->x_mm = f11->sensor_pdata.x_mm; 11408c2ecf20Sopenharmony_ci sensor->y_mm = f11->sensor_pdata.y_mm; 11418c2ecf20Sopenharmony_ci } 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci if (sensor->sensor_type == rmi_sensor_default) 11448c2ecf20Sopenharmony_ci sensor->sensor_type = 11458c2ecf20Sopenharmony_ci f11->sensor_pdata.sensor_type; 11468c2ecf20Sopenharmony_ci 11478c2ecf20Sopenharmony_ci sensor->report_abs = sensor->report_abs 11488c2ecf20Sopenharmony_ci && !(f11->sensor_pdata.disable_report_mask 11498c2ecf20Sopenharmony_ci & RMI_F11_DISABLE_ABS_REPORT); 11508c2ecf20Sopenharmony_ci 11518c2ecf20Sopenharmony_ci if (!sensor->report_abs) 11528c2ecf20Sopenharmony_ci /* 11538c2ecf20Sopenharmony_ci * If device doesn't have abs or if it has been disables 11548c2ecf20Sopenharmony_ci * fallback to reporting rel data. 11558c2ecf20Sopenharmony_ci */ 11568c2ecf20Sopenharmony_ci sensor->report_rel = f11->sens_query.has_rel; 11578c2ecf20Sopenharmony_ci 11588c2ecf20Sopenharmony_ci rc = rmi_read_block(rmi_dev, 11598c2ecf20Sopenharmony_ci control_base_addr + F11_CTRL_SENSOR_MAX_X_POS_OFFSET, 11608c2ecf20Sopenharmony_ci (u8 *)&max_x_pos, sizeof(max_x_pos)); 11618c2ecf20Sopenharmony_ci if (rc < 0) 11628c2ecf20Sopenharmony_ci return rc; 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_ci rc = rmi_read_block(rmi_dev, 11658c2ecf20Sopenharmony_ci control_base_addr + F11_CTRL_SENSOR_MAX_Y_POS_OFFSET, 11668c2ecf20Sopenharmony_ci (u8 *)&max_y_pos, sizeof(max_y_pos)); 11678c2ecf20Sopenharmony_ci if (rc < 0) 11688c2ecf20Sopenharmony_ci return rc; 11698c2ecf20Sopenharmony_ci 11708c2ecf20Sopenharmony_ci sensor->max_x = max_x_pos; 11718c2ecf20Sopenharmony_ci sensor->max_y = max_y_pos; 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ci rc = f11_2d_construct_data(f11); 11748c2ecf20Sopenharmony_ci if (rc < 0) 11758c2ecf20Sopenharmony_ci return rc; 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci if (f11->has_acm) 11788c2ecf20Sopenharmony_ci f11->sensor.attn_size += f11->sensor.nbr_fingers * 2; 11798c2ecf20Sopenharmony_ci 11808c2ecf20Sopenharmony_ci /* allocate the in-kernel tracking buffers */ 11818c2ecf20Sopenharmony_ci sensor->tracking_pos = devm_kcalloc(&fn->dev, 11828c2ecf20Sopenharmony_ci sensor->nbr_fingers, sizeof(struct input_mt_pos), 11838c2ecf20Sopenharmony_ci GFP_KERNEL); 11848c2ecf20Sopenharmony_ci sensor->tracking_slots = devm_kcalloc(&fn->dev, 11858c2ecf20Sopenharmony_ci sensor->nbr_fingers, sizeof(int), GFP_KERNEL); 11868c2ecf20Sopenharmony_ci sensor->objs = devm_kcalloc(&fn->dev, 11878c2ecf20Sopenharmony_ci sensor->nbr_fingers, 11888c2ecf20Sopenharmony_ci sizeof(struct rmi_2d_sensor_abs_object), 11898c2ecf20Sopenharmony_ci GFP_KERNEL); 11908c2ecf20Sopenharmony_ci if (!sensor->tracking_pos || !sensor->tracking_slots || !sensor->objs) 11918c2ecf20Sopenharmony_ci return -ENOMEM; 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci ctrl = &f11->dev_controls; 11948c2ecf20Sopenharmony_ci if (sensor->axis_align.delta_x_threshold) 11958c2ecf20Sopenharmony_ci ctrl->ctrl0_11[RMI_F11_DELTA_X_THRESHOLD] = 11968c2ecf20Sopenharmony_ci sensor->axis_align.delta_x_threshold; 11978c2ecf20Sopenharmony_ci 11988c2ecf20Sopenharmony_ci if (sensor->axis_align.delta_y_threshold) 11998c2ecf20Sopenharmony_ci ctrl->ctrl0_11[RMI_F11_DELTA_Y_THRESHOLD] = 12008c2ecf20Sopenharmony_ci sensor->axis_align.delta_y_threshold; 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_ci /* 12038c2ecf20Sopenharmony_ci * If distance threshold values are set, switch to reduced reporting 12048c2ecf20Sopenharmony_ci * mode so they actually get used by the controller. 12058c2ecf20Sopenharmony_ci */ 12068c2ecf20Sopenharmony_ci if (sensor->axis_align.delta_x_threshold || 12078c2ecf20Sopenharmony_ci sensor->axis_align.delta_y_threshold) { 12088c2ecf20Sopenharmony_ci ctrl->ctrl0_11[0] &= ~RMI_F11_REPORT_MODE_MASK; 12098c2ecf20Sopenharmony_ci ctrl->ctrl0_11[0] |= RMI_F11_REPORT_MODE_REDUCED; 12108c2ecf20Sopenharmony_ci } 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci if (f11->sens_query.has_dribble) { 12138c2ecf20Sopenharmony_ci switch (sensor->dribble) { 12148c2ecf20Sopenharmony_ci case RMI_REG_STATE_OFF: 12158c2ecf20Sopenharmony_ci ctrl->ctrl0_11[0] &= ~BIT(6); 12168c2ecf20Sopenharmony_ci break; 12178c2ecf20Sopenharmony_ci case RMI_REG_STATE_ON: 12188c2ecf20Sopenharmony_ci ctrl->ctrl0_11[0] |= BIT(6); 12198c2ecf20Sopenharmony_ci break; 12208c2ecf20Sopenharmony_ci case RMI_REG_STATE_DEFAULT: 12218c2ecf20Sopenharmony_ci default: 12228c2ecf20Sopenharmony_ci break; 12238c2ecf20Sopenharmony_ci } 12248c2ecf20Sopenharmony_ci } 12258c2ecf20Sopenharmony_ci 12268c2ecf20Sopenharmony_ci if (f11->sens_query.has_palm_det) { 12278c2ecf20Sopenharmony_ci switch (sensor->palm_detect) { 12288c2ecf20Sopenharmony_ci case RMI_REG_STATE_OFF: 12298c2ecf20Sopenharmony_ci ctrl->ctrl0_11[11] &= ~BIT(0); 12308c2ecf20Sopenharmony_ci break; 12318c2ecf20Sopenharmony_ci case RMI_REG_STATE_ON: 12328c2ecf20Sopenharmony_ci ctrl->ctrl0_11[11] |= BIT(0); 12338c2ecf20Sopenharmony_ci break; 12348c2ecf20Sopenharmony_ci case RMI_REG_STATE_DEFAULT: 12358c2ecf20Sopenharmony_ci default: 12368c2ecf20Sopenharmony_ci break; 12378c2ecf20Sopenharmony_ci } 12388c2ecf20Sopenharmony_ci } 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_ci rc = f11_write_control_regs(fn, &f11->sens_query, 12418c2ecf20Sopenharmony_ci &f11->dev_controls, fn->fd.control_base_addr); 12428c2ecf20Sopenharmony_ci if (rc) 12438c2ecf20Sopenharmony_ci dev_warn(&fn->dev, "Failed to write control registers\n"); 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_ci mutex_init(&f11->dev_controls_mutex); 12468c2ecf20Sopenharmony_ci 12478c2ecf20Sopenharmony_ci dev_set_drvdata(&fn->dev, f11); 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ci return 0; 12508c2ecf20Sopenharmony_ci} 12518c2ecf20Sopenharmony_ci 12528c2ecf20Sopenharmony_cistatic int rmi_f11_config(struct rmi_function *fn) 12538c2ecf20Sopenharmony_ci{ 12548c2ecf20Sopenharmony_ci struct f11_data *f11 = dev_get_drvdata(&fn->dev); 12558c2ecf20Sopenharmony_ci struct rmi_driver *drv = fn->rmi_dev->driver; 12568c2ecf20Sopenharmony_ci struct rmi_2d_sensor *sensor = &f11->sensor; 12578c2ecf20Sopenharmony_ci int rc; 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_ci if (!sensor->report_abs) 12608c2ecf20Sopenharmony_ci drv->clear_irq_bits(fn->rmi_dev, f11->abs_mask); 12618c2ecf20Sopenharmony_ci else 12628c2ecf20Sopenharmony_ci drv->set_irq_bits(fn->rmi_dev, f11->abs_mask); 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_ci if (!sensor->report_rel) 12658c2ecf20Sopenharmony_ci drv->clear_irq_bits(fn->rmi_dev, f11->rel_mask); 12668c2ecf20Sopenharmony_ci else 12678c2ecf20Sopenharmony_ci drv->set_irq_bits(fn->rmi_dev, f11->rel_mask); 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci rc = f11_write_control_regs(fn, &f11->sens_query, 12708c2ecf20Sopenharmony_ci &f11->dev_controls, fn->fd.query_base_addr); 12718c2ecf20Sopenharmony_ci if (rc < 0) 12728c2ecf20Sopenharmony_ci return rc; 12738c2ecf20Sopenharmony_ci 12748c2ecf20Sopenharmony_ci return 0; 12758c2ecf20Sopenharmony_ci} 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_cistatic irqreturn_t rmi_f11_attention(int irq, void *ctx) 12788c2ecf20Sopenharmony_ci{ 12798c2ecf20Sopenharmony_ci struct rmi_function *fn = ctx; 12808c2ecf20Sopenharmony_ci struct rmi_device *rmi_dev = fn->rmi_dev; 12818c2ecf20Sopenharmony_ci struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev); 12828c2ecf20Sopenharmony_ci struct f11_data *f11 = dev_get_drvdata(&fn->dev); 12838c2ecf20Sopenharmony_ci u16 data_base_addr = fn->fd.data_base_addr; 12848c2ecf20Sopenharmony_ci int error; 12858c2ecf20Sopenharmony_ci int valid_bytes = f11->sensor.pkt_size; 12868c2ecf20Sopenharmony_ci 12878c2ecf20Sopenharmony_ci if (drvdata->attn_data.data) { 12888c2ecf20Sopenharmony_ci /* 12898c2ecf20Sopenharmony_ci * The valid data in the attention report is less then 12908c2ecf20Sopenharmony_ci * expected. Only process the complete fingers. 12918c2ecf20Sopenharmony_ci */ 12928c2ecf20Sopenharmony_ci if (f11->sensor.attn_size > drvdata->attn_data.size) 12938c2ecf20Sopenharmony_ci valid_bytes = drvdata->attn_data.size; 12948c2ecf20Sopenharmony_ci else 12958c2ecf20Sopenharmony_ci valid_bytes = f11->sensor.attn_size; 12968c2ecf20Sopenharmony_ci memcpy(f11->sensor.data_pkt, drvdata->attn_data.data, 12978c2ecf20Sopenharmony_ci valid_bytes); 12988c2ecf20Sopenharmony_ci drvdata->attn_data.data += valid_bytes; 12998c2ecf20Sopenharmony_ci drvdata->attn_data.size -= valid_bytes; 13008c2ecf20Sopenharmony_ci } else { 13018c2ecf20Sopenharmony_ci error = rmi_read_block(rmi_dev, 13028c2ecf20Sopenharmony_ci data_base_addr, f11->sensor.data_pkt, 13038c2ecf20Sopenharmony_ci f11->sensor.pkt_size); 13048c2ecf20Sopenharmony_ci if (error < 0) 13058c2ecf20Sopenharmony_ci return IRQ_RETVAL(error); 13068c2ecf20Sopenharmony_ci } 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci rmi_f11_finger_handler(f11, &f11->sensor, valid_bytes); 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_ci return IRQ_HANDLED; 13118c2ecf20Sopenharmony_ci} 13128c2ecf20Sopenharmony_ci 13138c2ecf20Sopenharmony_cistatic int rmi_f11_resume(struct rmi_function *fn) 13148c2ecf20Sopenharmony_ci{ 13158c2ecf20Sopenharmony_ci struct f11_data *f11 = dev_get_drvdata(&fn->dev); 13168c2ecf20Sopenharmony_ci int error; 13178c2ecf20Sopenharmony_ci 13188c2ecf20Sopenharmony_ci rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Resuming...\n"); 13198c2ecf20Sopenharmony_ci if (!f11->rezero_wait_ms) 13208c2ecf20Sopenharmony_ci return 0; 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci mdelay(f11->rezero_wait_ms); 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_ci error = rmi_write(fn->rmi_dev, fn->fd.command_base_addr, 13258c2ecf20Sopenharmony_ci RMI_F11_REZERO); 13268c2ecf20Sopenharmony_ci if (error) { 13278c2ecf20Sopenharmony_ci dev_err(&fn->dev, 13288c2ecf20Sopenharmony_ci "%s: failed to issue rezero command, error = %d.", 13298c2ecf20Sopenharmony_ci __func__, error); 13308c2ecf20Sopenharmony_ci return error; 13318c2ecf20Sopenharmony_ci } 13328c2ecf20Sopenharmony_ci 13338c2ecf20Sopenharmony_ci return 0; 13348c2ecf20Sopenharmony_ci} 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_cistatic int rmi_f11_probe(struct rmi_function *fn) 13378c2ecf20Sopenharmony_ci{ 13388c2ecf20Sopenharmony_ci int error; 13398c2ecf20Sopenharmony_ci struct f11_data *f11; 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_ci error = rmi_f11_initialize(fn); 13428c2ecf20Sopenharmony_ci if (error) 13438c2ecf20Sopenharmony_ci return error; 13448c2ecf20Sopenharmony_ci 13458c2ecf20Sopenharmony_ci f11 = dev_get_drvdata(&fn->dev); 13468c2ecf20Sopenharmony_ci error = rmi_2d_sensor_configure_input(fn, &f11->sensor); 13478c2ecf20Sopenharmony_ci if (error) 13488c2ecf20Sopenharmony_ci return error; 13498c2ecf20Sopenharmony_ci 13508c2ecf20Sopenharmony_ci return 0; 13518c2ecf20Sopenharmony_ci} 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_cistruct rmi_function_handler rmi_f11_handler = { 13548c2ecf20Sopenharmony_ci .driver = { 13558c2ecf20Sopenharmony_ci .name = "rmi4_f11", 13568c2ecf20Sopenharmony_ci }, 13578c2ecf20Sopenharmony_ci .func = 0x11, 13588c2ecf20Sopenharmony_ci .probe = rmi_f11_probe, 13598c2ecf20Sopenharmony_ci .config = rmi_f11_config, 13608c2ecf20Sopenharmony_ci .attention = rmi_f11_attention, 13618c2ecf20Sopenharmony_ci .resume = rmi_f11_resume, 13628c2ecf20Sopenharmony_ci}; 1363