162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2011-2015 Synaptics Incorporated 462306a36Sopenharmony_ci * Copyright (c) 2011 Unixphere 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/kernel.h> 862306a36Sopenharmony_ci#include <linux/delay.h> 962306a36Sopenharmony_ci#include <linux/device.h> 1062306a36Sopenharmony_ci#include <linux/input.h> 1162306a36Sopenharmony_ci#include <linux/input/mt.h> 1262306a36Sopenharmony_ci#include <linux/rmi.h> 1362306a36Sopenharmony_ci#include <linux/slab.h> 1462306a36Sopenharmony_ci#include <linux/of.h> 1562306a36Sopenharmony_ci#include "rmi_driver.h" 1662306a36Sopenharmony_ci#include "rmi_2d_sensor.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define F11_MAX_NUM_OF_FINGERS 10 1962306a36Sopenharmony_ci#define F11_MAX_NUM_OF_TOUCH_SHAPES 16 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define FINGER_STATE_MASK 0x03 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define F11_CTRL_SENSOR_MAX_X_POS_OFFSET 6 2462306a36Sopenharmony_ci#define F11_CTRL_SENSOR_MAX_Y_POS_OFFSET 8 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define DEFAULT_XY_MAX 9999 2762306a36Sopenharmony_ci#define DEFAULT_MAX_ABS_MT_PRESSURE 255 2862306a36Sopenharmony_ci#define DEFAULT_MAX_ABS_MT_TOUCH 15 2962306a36Sopenharmony_ci#define DEFAULT_MAX_ABS_MT_ORIENTATION 1 3062306a36Sopenharmony_ci#define DEFAULT_MIN_ABS_MT_TRACKING_ID 1 3162306a36Sopenharmony_ci#define DEFAULT_MAX_ABS_MT_TRACKING_ID 10 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci/* 3462306a36Sopenharmony_ci * A note about RMI4 F11 register structure. 3562306a36Sopenharmony_ci * 3662306a36Sopenharmony_ci * The properties for a given sensor are described by its query registers. The 3762306a36Sopenharmony_ci * number of query registers and the layout of their contents are described by 3862306a36Sopenharmony_ci * the F11 device queries as well as the sensor query information. 3962306a36Sopenharmony_ci * 4062306a36Sopenharmony_ci * Similarly, each sensor has control registers that govern its behavior. The 4162306a36Sopenharmony_ci * size and layout of the control registers for a given sensor can be determined 4262306a36Sopenharmony_ci * by parsing that sensors query registers. 4362306a36Sopenharmony_ci * 4462306a36Sopenharmony_ci * And in a likewise fashion, each sensor has data registers where it reports 4562306a36Sopenharmony_ci * its touch data and other interesting stuff. The size and layout of a 4662306a36Sopenharmony_ci * sensors data registers must be determined by parsing its query registers. 4762306a36Sopenharmony_ci * 4862306a36Sopenharmony_ci * The short story is that we need to read and parse a lot of query 4962306a36Sopenharmony_ci * registers in order to determine the attributes of a sensor. Then 5062306a36Sopenharmony_ci * we need to use that data to compute the size of the control and data 5162306a36Sopenharmony_ci * registers for sensor. 5262306a36Sopenharmony_ci * 5362306a36Sopenharmony_ci * The end result is that we have a number of structs that aren't used to 5462306a36Sopenharmony_ci * directly generate the input events, but their size, location and contents 5562306a36Sopenharmony_ci * are critical to determining where the data we are interested in lives. 5662306a36Sopenharmony_ci * 5762306a36Sopenharmony_ci * At this time, the driver does not yet comprehend all possible F11 5862306a36Sopenharmony_ci * configuration options, but it should be sufficient to cover 99% of RMI4 F11 5962306a36Sopenharmony_ci * devices currently in the field. 6062306a36Sopenharmony_ci */ 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci/* maximum ABS_MT_POSITION displacement (in mm) */ 6362306a36Sopenharmony_ci#define DMAX 10 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci/* 6662306a36Sopenharmony_ci * Writing this to the F11 command register will cause the sensor to 6762306a36Sopenharmony_ci * calibrate to the current capacitive state. 6862306a36Sopenharmony_ci */ 6962306a36Sopenharmony_ci#define RMI_F11_REZERO 0x01 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci#define RMI_F11_HAS_QUERY9 (1 << 3) 7262306a36Sopenharmony_ci#define RMI_F11_HAS_QUERY11 (1 << 4) 7362306a36Sopenharmony_ci#define RMI_F11_HAS_QUERY12 (1 << 5) 7462306a36Sopenharmony_ci#define RMI_F11_HAS_QUERY27 (1 << 6) 7562306a36Sopenharmony_ci#define RMI_F11_HAS_QUERY28 (1 << 7) 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci/** Defs for Query 1 */ 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci#define RMI_F11_NR_FINGERS_MASK 0x07 8062306a36Sopenharmony_ci#define RMI_F11_HAS_REL (1 << 3) 8162306a36Sopenharmony_ci#define RMI_F11_HAS_ABS (1 << 4) 8262306a36Sopenharmony_ci#define RMI_F11_HAS_GESTURES (1 << 5) 8362306a36Sopenharmony_ci#define RMI_F11_HAS_SENSITIVITY_ADJ (1 << 6) 8462306a36Sopenharmony_ci#define RMI_F11_CONFIGURABLE (1 << 7) 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci/** Defs for Query 2, 3, and 4. */ 8762306a36Sopenharmony_ci#define RMI_F11_NR_ELECTRODES_MASK 0x7F 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci/** Defs for Query 5 */ 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci#define RMI_F11_ABS_DATA_SIZE_MASK 0x03 9262306a36Sopenharmony_ci#define RMI_F11_HAS_ANCHORED_FINGER (1 << 2) 9362306a36Sopenharmony_ci#define RMI_F11_HAS_ADJ_HYST (1 << 3) 9462306a36Sopenharmony_ci#define RMI_F11_HAS_DRIBBLE (1 << 4) 9562306a36Sopenharmony_ci#define RMI_F11_HAS_BENDING_CORRECTION (1 << 5) 9662306a36Sopenharmony_ci#define RMI_F11_HAS_LARGE_OBJECT_SUPPRESSION (1 << 6) 9762306a36Sopenharmony_ci#define RMI_F11_HAS_JITTER_FILTER (1 << 7) 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci/** Defs for Query 7 */ 10062306a36Sopenharmony_ci#define RMI_F11_HAS_SINGLE_TAP (1 << 0) 10162306a36Sopenharmony_ci#define RMI_F11_HAS_TAP_AND_HOLD (1 << 1) 10262306a36Sopenharmony_ci#define RMI_F11_HAS_DOUBLE_TAP (1 << 2) 10362306a36Sopenharmony_ci#define RMI_F11_HAS_EARLY_TAP (1 << 3) 10462306a36Sopenharmony_ci#define RMI_F11_HAS_FLICK (1 << 4) 10562306a36Sopenharmony_ci#define RMI_F11_HAS_PRESS (1 << 5) 10662306a36Sopenharmony_ci#define RMI_F11_HAS_PINCH (1 << 6) 10762306a36Sopenharmony_ci#define RMI_F11_HAS_CHIRAL (1 << 7) 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci/** Defs for Query 8 */ 11062306a36Sopenharmony_ci#define RMI_F11_HAS_PALM_DET (1 << 0) 11162306a36Sopenharmony_ci#define RMI_F11_HAS_ROTATE (1 << 1) 11262306a36Sopenharmony_ci#define RMI_F11_HAS_TOUCH_SHAPES (1 << 2) 11362306a36Sopenharmony_ci#define RMI_F11_HAS_SCROLL_ZONES (1 << 3) 11462306a36Sopenharmony_ci#define RMI_F11_HAS_INDIVIDUAL_SCROLL_ZONES (1 << 4) 11562306a36Sopenharmony_ci#define RMI_F11_HAS_MF_SCROLL (1 << 5) 11662306a36Sopenharmony_ci#define RMI_F11_HAS_MF_EDGE_MOTION (1 << 6) 11762306a36Sopenharmony_ci#define RMI_F11_HAS_MF_SCROLL_INERTIA (1 << 7) 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci/** Defs for Query 9. */ 12062306a36Sopenharmony_ci#define RMI_F11_HAS_PEN (1 << 0) 12162306a36Sopenharmony_ci#define RMI_F11_HAS_PROXIMITY (1 << 1) 12262306a36Sopenharmony_ci#define RMI_F11_HAS_PALM_DET_SENSITIVITY (1 << 2) 12362306a36Sopenharmony_ci#define RMI_F11_HAS_SUPPRESS_ON_PALM_DETECT (1 << 3) 12462306a36Sopenharmony_ci#define RMI_F11_HAS_TWO_PEN_THRESHOLDS (1 << 4) 12562306a36Sopenharmony_ci#define RMI_F11_HAS_CONTACT_GEOMETRY (1 << 5) 12662306a36Sopenharmony_ci#define RMI_F11_HAS_PEN_HOVER_DISCRIMINATION (1 << 6) 12762306a36Sopenharmony_ci#define RMI_F11_HAS_PEN_FILTERS (1 << 7) 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci/** Defs for Query 10. */ 13062306a36Sopenharmony_ci#define RMI_F11_NR_TOUCH_SHAPES_MASK 0x1F 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci/** Defs for Query 11 */ 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci#define RMI_F11_HAS_Z_TUNING (1 << 0) 13562306a36Sopenharmony_ci#define RMI_F11_HAS_ALGORITHM_SELECTION (1 << 1) 13662306a36Sopenharmony_ci#define RMI_F11_HAS_W_TUNING (1 << 2) 13762306a36Sopenharmony_ci#define RMI_F11_HAS_PITCH_INFO (1 << 3) 13862306a36Sopenharmony_ci#define RMI_F11_HAS_FINGER_SIZE (1 << 4) 13962306a36Sopenharmony_ci#define RMI_F11_HAS_SEGMENTATION_AGGRESSIVENESS (1 << 5) 14062306a36Sopenharmony_ci#define RMI_F11_HAS_XY_CLIP (1 << 6) 14162306a36Sopenharmony_ci#define RMI_F11_HAS_DRUMMING_FILTER (1 << 7) 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci/** Defs for Query 12. */ 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci#define RMI_F11_HAS_GAPLESS_FINGER (1 << 0) 14662306a36Sopenharmony_ci#define RMI_F11_HAS_GAPLESS_FINGER_TUNING (1 << 1) 14762306a36Sopenharmony_ci#define RMI_F11_HAS_8BIT_W (1 << 2) 14862306a36Sopenharmony_ci#define RMI_F11_HAS_ADJUSTABLE_MAPPING (1 << 3) 14962306a36Sopenharmony_ci#define RMI_F11_HAS_INFO2 (1 << 4) 15062306a36Sopenharmony_ci#define RMI_F11_HAS_PHYSICAL_PROPS (1 << 5) 15162306a36Sopenharmony_ci#define RMI_F11_HAS_FINGER_LIMIT (1 << 6) 15262306a36Sopenharmony_ci#define RMI_F11_HAS_LINEAR_COEFF (1 << 7) 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci/** Defs for Query 13. */ 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci#define RMI_F11_JITTER_WINDOW_MASK 0x1F 15762306a36Sopenharmony_ci#define RMI_F11_JITTER_FILTER_MASK 0x60 15862306a36Sopenharmony_ci#define RMI_F11_JITTER_FILTER_SHIFT 5 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci/** Defs for Query 14. */ 16162306a36Sopenharmony_ci#define RMI_F11_LIGHT_CONTROL_MASK 0x03 16262306a36Sopenharmony_ci#define RMI_F11_IS_CLEAR (1 << 2) 16362306a36Sopenharmony_ci#define RMI_F11_CLICKPAD_PROPS_MASK 0x18 16462306a36Sopenharmony_ci#define RMI_F11_CLICKPAD_PROPS_SHIFT 3 16562306a36Sopenharmony_ci#define RMI_F11_MOUSE_BUTTONS_MASK 0x60 16662306a36Sopenharmony_ci#define RMI_F11_MOUSE_BUTTONS_SHIFT 5 16762306a36Sopenharmony_ci#define RMI_F11_HAS_ADVANCED_GESTURES (1 << 7) 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci#define RMI_F11_QUERY_SIZE 4 17062306a36Sopenharmony_ci#define RMI_F11_QUERY_GESTURE_SIZE 2 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci#define F11_LIGHT_CTL_NONE 0x00 17362306a36Sopenharmony_ci#define F11_LUXPAD 0x01 17462306a36Sopenharmony_ci#define F11_DUAL_MODE 0x02 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci#define F11_NOT_CLICKPAD 0x00 17762306a36Sopenharmony_ci#define F11_HINGED_CLICKPAD 0x01 17862306a36Sopenharmony_ci#define F11_UNIFORM_CLICKPAD 0x02 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci/** 18162306a36Sopenharmony_ci * struct f11_2d_sensor_queries - describes sensor capabilities 18262306a36Sopenharmony_ci * 18362306a36Sopenharmony_ci * Query registers 1 through 4 are always present. 18462306a36Sopenharmony_ci * 18562306a36Sopenharmony_ci * @nr_fingers: describes the maximum number of fingers the 2-D sensor 18662306a36Sopenharmony_ci * supports. 18762306a36Sopenharmony_ci * @has_rel: the sensor supports relative motion reporting. 18862306a36Sopenharmony_ci * @has_abs: the sensor supports absolute poition reporting. 18962306a36Sopenharmony_ci * @has_gestures: the sensor supports gesture reporting. 19062306a36Sopenharmony_ci * @has_sensitivity_adjust: the sensor supports a global sensitivity 19162306a36Sopenharmony_ci * adjustment. 19262306a36Sopenharmony_ci * @configurable: the sensor supports various configuration options. 19362306a36Sopenharmony_ci * @nr_x_electrodes: the maximum number of electrodes the 2-D sensor 19462306a36Sopenharmony_ci * supports on the X axis. 19562306a36Sopenharmony_ci * @nr_y_electrodes: the maximum number of electrodes the 2-D sensor 19662306a36Sopenharmony_ci * supports on the Y axis. 19762306a36Sopenharmony_ci * @max_electrodes: the total number of X and Y electrodes that may be 19862306a36Sopenharmony_ci * configured. 19962306a36Sopenharmony_ci * 20062306a36Sopenharmony_ci * Query 5 is present if the has_abs bit is set. 20162306a36Sopenharmony_ci * 20262306a36Sopenharmony_ci * @abs_data_size: describes the format of data reported by the absolute 20362306a36Sopenharmony_ci * data source. Only one format (the kind used here) is supported at this 20462306a36Sopenharmony_ci * time. 20562306a36Sopenharmony_ci * @has_anchored_finger: then the sensor supports the high-precision second 20662306a36Sopenharmony_ci * finger tracking provided by the manual tracking and motion sensitivity 20762306a36Sopenharmony_ci * options. 20862306a36Sopenharmony_ci * @has_adj_hyst: the difference between the finger release threshold and 20962306a36Sopenharmony_ci * the touch threshold. 21062306a36Sopenharmony_ci * @has_dribble: the sensor supports the generation of dribble interrupts, 21162306a36Sopenharmony_ci * which may be enabled or disabled with the dribble control bit. 21262306a36Sopenharmony_ci * @has_bending_correction: Bending related data registers 28 and 36, and 21362306a36Sopenharmony_ci * control register 52..57 are present. 21462306a36Sopenharmony_ci * @has_large_object_suppression: control register 58 and data register 28 21562306a36Sopenharmony_ci * exist. 21662306a36Sopenharmony_ci * @has_jitter_filter: query 13 and control 73..76 exist. 21762306a36Sopenharmony_ci * 21862306a36Sopenharmony_ci * Query 6 is present if the has_rel it is set. 21962306a36Sopenharmony_ci * 22062306a36Sopenharmony_ci * @f11_2d_query6: this register is reserved. 22162306a36Sopenharmony_ci * 22262306a36Sopenharmony_ci * Gesture information queries 7 and 8 are present if has_gestures bit is set. 22362306a36Sopenharmony_ci * 22462306a36Sopenharmony_ci * @has_single_tap: a basic single-tap gesture is supported. 22562306a36Sopenharmony_ci * @has_tap_n_hold: tap-and-hold gesture is supported. 22662306a36Sopenharmony_ci * @has_double_tap: double-tap gesture is supported. 22762306a36Sopenharmony_ci * @has_early_tap: early tap is supported and reported as soon as the finger 22862306a36Sopenharmony_ci * lifts for any tap event that could be interpreted as either a single 22962306a36Sopenharmony_ci * tap or as the first tap of a double-tap or tap-and-hold gesture. 23062306a36Sopenharmony_ci * @has_flick: flick detection is supported. 23162306a36Sopenharmony_ci * @has_press: press gesture reporting is supported. 23262306a36Sopenharmony_ci * @has_pinch: pinch gesture detection is supported. 23362306a36Sopenharmony_ci * @has_chiral: chiral (circular) scrolling gesture detection is supported. 23462306a36Sopenharmony_ci * @has_palm_det: the 2-D sensor notifies the host whenever a large conductive 23562306a36Sopenharmony_ci * object such as a palm or a cheek touches the 2-D sensor. 23662306a36Sopenharmony_ci * @has_rotate: rotation gesture detection is supported. 23762306a36Sopenharmony_ci * @has_touch_shapes: TouchShapes are supported. A TouchShape is a fixed 23862306a36Sopenharmony_ci * rectangular area on the sensor that behaves like a capacitive button. 23962306a36Sopenharmony_ci * @has_scroll_zones: scrolling areas near the sensor edges are supported. 24062306a36Sopenharmony_ci * @has_individual_scroll_zones: if 1, then 4 scroll zones are supported; 24162306a36Sopenharmony_ci * if 0, then only two are supported. 24262306a36Sopenharmony_ci * @has_mf_scroll: the multifinger_scrolling bit will be set when 24362306a36Sopenharmony_ci * more than one finger is involved in a scrolling action. 24462306a36Sopenharmony_ci * @has_mf_edge_motion: indicates whether multi-finger edge motion gesture 24562306a36Sopenharmony_ci * is supported. 24662306a36Sopenharmony_ci * @has_mf_scroll_inertia: indicates whether multi-finger scroll inertia 24762306a36Sopenharmony_ci * feature is supported. 24862306a36Sopenharmony_ci * 24962306a36Sopenharmony_ci * Convenience for checking bytes in the gesture info registers. This is done 25062306a36Sopenharmony_ci * often enough that we put it here to declutter the conditionals 25162306a36Sopenharmony_ci * 25262306a36Sopenharmony_ci * @query7_nonzero: true if none of the query 7 bits are set 25362306a36Sopenharmony_ci * @query8_nonzero: true if none of the query 8 bits are set 25462306a36Sopenharmony_ci * 25562306a36Sopenharmony_ci * Query 9 is present if the has_query9 is set. 25662306a36Sopenharmony_ci * 25762306a36Sopenharmony_ci * @has_pen: detection of a stylus is supported and registers F11_2D_Ctrl20 25862306a36Sopenharmony_ci * and F11_2D_Ctrl21 exist. 25962306a36Sopenharmony_ci * @has_proximity: detection of fingers near the sensor is supported and 26062306a36Sopenharmony_ci * registers F11_2D_Ctrl22 through F11_2D_Ctrl26 exist. 26162306a36Sopenharmony_ci * @has_palm_det_sensitivity: the sensor supports the palm detect sensitivity 26262306a36Sopenharmony_ci * feature and register F11_2D_Ctrl27 exists. 26362306a36Sopenharmony_ci * @has_suppress_on_palm_detect: the device supports the large object detect 26462306a36Sopenharmony_ci * suppression feature and register F11_2D_Ctrl27 exists. 26562306a36Sopenharmony_ci * @has_two_pen_thresholds: if has_pen is also set, then F11_2D_Ctrl35 exists. 26662306a36Sopenharmony_ci * @has_contact_geometry: the sensor supports the use of contact geometry to 26762306a36Sopenharmony_ci * map absolute X and Y target positions and registers F11_2D_Data18 26862306a36Sopenharmony_ci * through F11_2D_Data27 exist. 26962306a36Sopenharmony_ci * @has_pen_hover_discrimination: if has_pen is also set, then registers 27062306a36Sopenharmony_ci * F11_2D_Data29 through F11_2D_Data31, F11_2D_Ctrl68.*, F11_2D_Ctrl69 27162306a36Sopenharmony_ci * and F11_2D_Ctrl72 exist. 27262306a36Sopenharmony_ci * @has_pen_filters: if has_pen is also set, then registers F11_2D_Ctrl70 and 27362306a36Sopenharmony_ci * F11_2D_Ctrl71 exist. 27462306a36Sopenharmony_ci * 27562306a36Sopenharmony_ci * Touch shape info (query 10) is present if has_touch_shapes is set. 27662306a36Sopenharmony_ci * 27762306a36Sopenharmony_ci * @nr_touch_shapes: the total number of touch shapes supported. 27862306a36Sopenharmony_ci * 27962306a36Sopenharmony_ci * Query 11 is present if the has_query11 bit is set in query 0. 28062306a36Sopenharmony_ci * 28162306a36Sopenharmony_ci * @has_z_tuning: if set, the sensor supports Z tuning and registers 28262306a36Sopenharmony_ci * F11_2D_Ctrl29 through F11_2D_Ctrl33 exist. 28362306a36Sopenharmony_ci * @has_algorithm_selection: controls choice of noise suppression algorithm 28462306a36Sopenharmony_ci * @has_w_tuning: the sensor supports Wx and Wy scaling and registers 28562306a36Sopenharmony_ci * F11_2D_Ctrl36 through F11_2D_Ctrl39 exist. 28662306a36Sopenharmony_ci * @has_pitch_info: the X and Y pitches of the sensor electrodes can be 28762306a36Sopenharmony_ci * configured and registers F11_2D_Ctrl40 and F11_2D_Ctrl41 exist. 28862306a36Sopenharmony_ci * @has_finger_size: the default finger width settings for the sensor 28962306a36Sopenharmony_ci * can be configured and registers F11_2D_Ctrl42 through F11_2D_Ctrl44 29062306a36Sopenharmony_ci * exist. 29162306a36Sopenharmony_ci * @has_segmentation_aggressiveness: the sensor’s ability to distinguish 29262306a36Sopenharmony_ci * multiple objects close together can be configured and register 29362306a36Sopenharmony_ci * F11_2D_Ctrl45 exists. 29462306a36Sopenharmony_ci * @has_XY_clip: the inactive outside borders of the sensor can be 29562306a36Sopenharmony_ci * configured and registers F11_2D_Ctrl46 through F11_2D_Ctrl49 exist. 29662306a36Sopenharmony_ci * @has_drumming_filter: the sensor can be configured to distinguish 29762306a36Sopenharmony_ci * between a fast flick and a quick drumming movement and registers 29862306a36Sopenharmony_ci * F11_2D_Ctrl50 and F11_2D_Ctrl51 exist. 29962306a36Sopenharmony_ci * 30062306a36Sopenharmony_ci * Query 12 is present if hasQuery12 bit is set. 30162306a36Sopenharmony_ci * 30262306a36Sopenharmony_ci * @has_gapless_finger: control registers relating to gapless finger are 30362306a36Sopenharmony_ci * present. 30462306a36Sopenharmony_ci * @has_gapless_finger_tuning: additional control and data registers relating 30562306a36Sopenharmony_ci * to gapless finger are present. 30662306a36Sopenharmony_ci * @has_8bit_w: larger W value reporting is supported. 30762306a36Sopenharmony_ci * @has_adjustable_mapping: TBD 30862306a36Sopenharmony_ci * @has_info2: the general info query14 is present 30962306a36Sopenharmony_ci * @has_physical_props: additional queries describing the physical properties 31062306a36Sopenharmony_ci * of the sensor are present. 31162306a36Sopenharmony_ci * @has_finger_limit: indicates that F11 Ctrl 80 exists. 31262306a36Sopenharmony_ci * @has_linear_coeff_2: indicates that F11 Ctrl 81 exists. 31362306a36Sopenharmony_ci * 31462306a36Sopenharmony_ci * Query 13 is present if Query 5's has_jitter_filter bit is set. 31562306a36Sopenharmony_ci * 31662306a36Sopenharmony_ci * @jitter_window_size: used by Design Studio 4. 31762306a36Sopenharmony_ci * @jitter_filter_type: used by Design Studio 4. 31862306a36Sopenharmony_ci * 31962306a36Sopenharmony_ci * Query 14 is present if query 12's has_general_info2 flag is set. 32062306a36Sopenharmony_ci * 32162306a36Sopenharmony_ci * @light_control: Indicates what light/led control features are present, 32262306a36Sopenharmony_ci * if any. 32362306a36Sopenharmony_ci * @is_clear: if set, this is a clear sensor (indicating direct pointing 32462306a36Sopenharmony_ci * application), otherwise it's opaque (indicating indirect pointing). 32562306a36Sopenharmony_ci * @clickpad_props: specifies if this is a clickpad, and if so what sort of 32662306a36Sopenharmony_ci * mechanism it uses 32762306a36Sopenharmony_ci * @mouse_buttons: specifies the number of mouse buttons present (if any). 32862306a36Sopenharmony_ci * @has_advanced_gestures: advanced driver gestures are supported. 32962306a36Sopenharmony_ci * 33062306a36Sopenharmony_ci * @x_sensor_size_mm: size of the sensor in millimeters on the X axis. 33162306a36Sopenharmony_ci * @y_sensor_size_mm: size of the sensor in millimeters on the Y axis. 33262306a36Sopenharmony_ci */ 33362306a36Sopenharmony_cistruct f11_2d_sensor_queries { 33462306a36Sopenharmony_ci /* query1 */ 33562306a36Sopenharmony_ci u8 nr_fingers; 33662306a36Sopenharmony_ci bool has_rel; 33762306a36Sopenharmony_ci bool has_abs; 33862306a36Sopenharmony_ci bool has_gestures; 33962306a36Sopenharmony_ci bool has_sensitivity_adjust; 34062306a36Sopenharmony_ci bool configurable; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci /* query2 */ 34362306a36Sopenharmony_ci u8 nr_x_electrodes; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci /* query3 */ 34662306a36Sopenharmony_ci u8 nr_y_electrodes; 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci /* query4 */ 34962306a36Sopenharmony_ci u8 max_electrodes; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci /* query5 */ 35262306a36Sopenharmony_ci u8 abs_data_size; 35362306a36Sopenharmony_ci bool has_anchored_finger; 35462306a36Sopenharmony_ci bool has_adj_hyst; 35562306a36Sopenharmony_ci bool has_dribble; 35662306a36Sopenharmony_ci bool has_bending_correction; 35762306a36Sopenharmony_ci bool has_large_object_suppression; 35862306a36Sopenharmony_ci bool has_jitter_filter; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci u8 f11_2d_query6; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci /* query 7 */ 36362306a36Sopenharmony_ci bool has_single_tap; 36462306a36Sopenharmony_ci bool has_tap_n_hold; 36562306a36Sopenharmony_ci bool has_double_tap; 36662306a36Sopenharmony_ci bool has_early_tap; 36762306a36Sopenharmony_ci bool has_flick; 36862306a36Sopenharmony_ci bool has_press; 36962306a36Sopenharmony_ci bool has_pinch; 37062306a36Sopenharmony_ci bool has_chiral; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci bool query7_nonzero; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci /* query 8 */ 37562306a36Sopenharmony_ci bool has_palm_det; 37662306a36Sopenharmony_ci bool has_rotate; 37762306a36Sopenharmony_ci bool has_touch_shapes; 37862306a36Sopenharmony_ci bool has_scroll_zones; 37962306a36Sopenharmony_ci bool has_individual_scroll_zones; 38062306a36Sopenharmony_ci bool has_mf_scroll; 38162306a36Sopenharmony_ci bool has_mf_edge_motion; 38262306a36Sopenharmony_ci bool has_mf_scroll_inertia; 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci bool query8_nonzero; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci /* Query 9 */ 38762306a36Sopenharmony_ci bool has_pen; 38862306a36Sopenharmony_ci bool has_proximity; 38962306a36Sopenharmony_ci bool has_palm_det_sensitivity; 39062306a36Sopenharmony_ci bool has_suppress_on_palm_detect; 39162306a36Sopenharmony_ci bool has_two_pen_thresholds; 39262306a36Sopenharmony_ci bool has_contact_geometry; 39362306a36Sopenharmony_ci bool has_pen_hover_discrimination; 39462306a36Sopenharmony_ci bool has_pen_filters; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci /* Query 10 */ 39762306a36Sopenharmony_ci u8 nr_touch_shapes; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci /* Query 11. */ 40062306a36Sopenharmony_ci bool has_z_tuning; 40162306a36Sopenharmony_ci bool has_algorithm_selection; 40262306a36Sopenharmony_ci bool has_w_tuning; 40362306a36Sopenharmony_ci bool has_pitch_info; 40462306a36Sopenharmony_ci bool has_finger_size; 40562306a36Sopenharmony_ci bool has_segmentation_aggressiveness; 40662306a36Sopenharmony_ci bool has_XY_clip; 40762306a36Sopenharmony_ci bool has_drumming_filter; 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci /* Query 12 */ 41062306a36Sopenharmony_ci bool has_gapless_finger; 41162306a36Sopenharmony_ci bool has_gapless_finger_tuning; 41262306a36Sopenharmony_ci bool has_8bit_w; 41362306a36Sopenharmony_ci bool has_adjustable_mapping; 41462306a36Sopenharmony_ci bool has_info2; 41562306a36Sopenharmony_ci bool has_physical_props; 41662306a36Sopenharmony_ci bool has_finger_limit; 41762306a36Sopenharmony_ci bool has_linear_coeff_2; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci /* Query 13 */ 42062306a36Sopenharmony_ci u8 jitter_window_size; 42162306a36Sopenharmony_ci u8 jitter_filter_type; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci /* Query 14 */ 42462306a36Sopenharmony_ci u8 light_control; 42562306a36Sopenharmony_ci bool is_clear; 42662306a36Sopenharmony_ci u8 clickpad_props; 42762306a36Sopenharmony_ci u8 mouse_buttons; 42862306a36Sopenharmony_ci bool has_advanced_gestures; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci /* Query 15 - 18 */ 43162306a36Sopenharmony_ci u16 x_sensor_size_mm; 43262306a36Sopenharmony_ci u16 y_sensor_size_mm; 43362306a36Sopenharmony_ci}; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci/* Defs for Ctrl0. */ 43662306a36Sopenharmony_ci#define RMI_F11_REPORT_MODE_MASK 0x07 43762306a36Sopenharmony_ci#define RMI_F11_REPORT_MODE_CONTINUOUS (0 << 0) 43862306a36Sopenharmony_ci#define RMI_F11_REPORT_MODE_REDUCED (1 << 0) 43962306a36Sopenharmony_ci#define RMI_F11_REPORT_MODE_FS_CHANGE (2 << 0) 44062306a36Sopenharmony_ci#define RMI_F11_REPORT_MODE_FP_CHANGE (3 << 0) 44162306a36Sopenharmony_ci#define RMI_F11_ABS_POS_FILT (1 << 3) 44262306a36Sopenharmony_ci#define RMI_F11_REL_POS_FILT (1 << 4) 44362306a36Sopenharmony_ci#define RMI_F11_REL_BALLISTICS (1 << 5) 44462306a36Sopenharmony_ci#define RMI_F11_DRIBBLE (1 << 6) 44562306a36Sopenharmony_ci#define RMI_F11_REPORT_BEYOND_CLIP (1 << 7) 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci/* Defs for Ctrl1. */ 44862306a36Sopenharmony_ci#define RMI_F11_PALM_DETECT_THRESH_MASK 0x0F 44962306a36Sopenharmony_ci#define RMI_F11_MOTION_SENSITIVITY_MASK 0x30 45062306a36Sopenharmony_ci#define RMI_F11_MANUAL_TRACKING (1 << 6) 45162306a36Sopenharmony_ci#define RMI_F11_MANUAL_TRACKED_FINGER (1 << 7) 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci#define RMI_F11_DELTA_X_THRESHOLD 2 45462306a36Sopenharmony_ci#define RMI_F11_DELTA_Y_THRESHOLD 3 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci#define RMI_F11_CTRL_REG_COUNT 12 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_cistruct f11_2d_ctrl { 45962306a36Sopenharmony_ci u8 ctrl0_11[RMI_F11_CTRL_REG_COUNT]; 46062306a36Sopenharmony_ci u16 ctrl0_11_address; 46162306a36Sopenharmony_ci}; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci#define RMI_F11_ABS_BYTES 5 46462306a36Sopenharmony_ci#define RMI_F11_REL_BYTES 2 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci/* Defs for Data 8 */ 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci#define RMI_F11_SINGLE_TAP (1 << 0) 46962306a36Sopenharmony_ci#define RMI_F11_TAP_AND_HOLD (1 << 1) 47062306a36Sopenharmony_ci#define RMI_F11_DOUBLE_TAP (1 << 2) 47162306a36Sopenharmony_ci#define RMI_F11_EARLY_TAP (1 << 3) 47262306a36Sopenharmony_ci#define RMI_F11_FLICK (1 << 4) 47362306a36Sopenharmony_ci#define RMI_F11_PRESS (1 << 5) 47462306a36Sopenharmony_ci#define RMI_F11_PINCH (1 << 6) 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci/* Defs for Data 9 */ 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci#define RMI_F11_PALM_DETECT (1 << 0) 47962306a36Sopenharmony_ci#define RMI_F11_ROTATE (1 << 1) 48062306a36Sopenharmony_ci#define RMI_F11_SHAPE (1 << 2) 48162306a36Sopenharmony_ci#define RMI_F11_SCROLLZONE (1 << 3) 48262306a36Sopenharmony_ci#define RMI_F11_GESTURE_FINGER_COUNT_MASK 0x70 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci/** Handy pointers into our data buffer. 48562306a36Sopenharmony_ci * 48662306a36Sopenharmony_ci * @f_state - start of finger state registers. 48762306a36Sopenharmony_ci * @abs_pos - start of absolute position registers (if present). 48862306a36Sopenharmony_ci * @rel_pos - start of relative data registers (if present). 48962306a36Sopenharmony_ci * @gest_1 - gesture flags (if present). 49062306a36Sopenharmony_ci * @gest_2 - gesture flags & finger count (if present). 49162306a36Sopenharmony_ci * @pinch - pinch motion register (if present). 49262306a36Sopenharmony_ci * @flick - flick distance X & Y, flick time (if present). 49362306a36Sopenharmony_ci * @rotate - rotate motion and finger separation. 49462306a36Sopenharmony_ci * @multi_scroll - chiral deltas for X and Y (if present). 49562306a36Sopenharmony_ci * @scroll_zones - scroll deltas for 4 regions (if present). 49662306a36Sopenharmony_ci */ 49762306a36Sopenharmony_cistruct f11_2d_data { 49862306a36Sopenharmony_ci u8 *f_state; 49962306a36Sopenharmony_ci u8 *abs_pos; 50062306a36Sopenharmony_ci s8 *rel_pos; 50162306a36Sopenharmony_ci u8 *gest_1; 50262306a36Sopenharmony_ci u8 *gest_2; 50362306a36Sopenharmony_ci s8 *pinch; 50462306a36Sopenharmony_ci u8 *flick; 50562306a36Sopenharmony_ci u8 *rotate; 50662306a36Sopenharmony_ci u8 *shapes; 50762306a36Sopenharmony_ci s8 *multi_scroll; 50862306a36Sopenharmony_ci s8 *scroll_zones; 50962306a36Sopenharmony_ci}; 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci/** Data pertaining to F11 in general. For per-sensor data, see struct 51262306a36Sopenharmony_ci * f11_2d_sensor. 51362306a36Sopenharmony_ci * 51462306a36Sopenharmony_ci * @dev_query - F11 device specific query registers. 51562306a36Sopenharmony_ci * @dev_controls - F11 device specific control registers. 51662306a36Sopenharmony_ci * @dev_controls_mutex - lock for the control registers. 51762306a36Sopenharmony_ci * @rezero_wait_ms - if nonzero, upon resume we will wait this many 51862306a36Sopenharmony_ci * milliseconds before rezeroing the sensor(s). This is useful in systems with 51962306a36Sopenharmony_ci * poor electrical behavior on resume, where the initial calibration of the 52062306a36Sopenharmony_ci * sensor(s) coming out of sleep state may be bogus. 52162306a36Sopenharmony_ci * @sensors - per sensor data structures. 52262306a36Sopenharmony_ci */ 52362306a36Sopenharmony_cistruct f11_data { 52462306a36Sopenharmony_ci bool has_query9; 52562306a36Sopenharmony_ci bool has_query11; 52662306a36Sopenharmony_ci bool has_query12; 52762306a36Sopenharmony_ci bool has_query27; 52862306a36Sopenharmony_ci bool has_query28; 52962306a36Sopenharmony_ci bool has_acm; 53062306a36Sopenharmony_ci struct f11_2d_ctrl dev_controls; 53162306a36Sopenharmony_ci struct mutex dev_controls_mutex; 53262306a36Sopenharmony_ci u16 rezero_wait_ms; 53362306a36Sopenharmony_ci struct rmi_2d_sensor sensor; 53462306a36Sopenharmony_ci struct f11_2d_sensor_queries sens_query; 53562306a36Sopenharmony_ci struct f11_2d_data data; 53662306a36Sopenharmony_ci struct rmi_2d_sensor_platform_data sensor_pdata; 53762306a36Sopenharmony_ci unsigned long *abs_mask; 53862306a36Sopenharmony_ci unsigned long *rel_mask; 53962306a36Sopenharmony_ci}; 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_cienum f11_finger_state { 54262306a36Sopenharmony_ci F11_NO_FINGER = 0x00, 54362306a36Sopenharmony_ci F11_PRESENT = 0x01, 54462306a36Sopenharmony_ci F11_INACCURATE = 0x02, 54562306a36Sopenharmony_ci F11_RESERVED = 0x03 54662306a36Sopenharmony_ci}; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_cistatic void rmi_f11_rel_pos_report(struct f11_data *f11, u8 n_finger) 54962306a36Sopenharmony_ci{ 55062306a36Sopenharmony_ci struct rmi_2d_sensor *sensor = &f11->sensor; 55162306a36Sopenharmony_ci struct f11_2d_data *data = &f11->data; 55262306a36Sopenharmony_ci s8 x, y; 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci x = data->rel_pos[n_finger * RMI_F11_REL_BYTES]; 55562306a36Sopenharmony_ci y = data->rel_pos[n_finger * RMI_F11_REL_BYTES + 1]; 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci rmi_2d_sensor_rel_report(sensor, x, y); 55862306a36Sopenharmony_ci} 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_cistatic void rmi_f11_abs_pos_process(struct f11_data *f11, 56162306a36Sopenharmony_ci struct rmi_2d_sensor *sensor, 56262306a36Sopenharmony_ci struct rmi_2d_sensor_abs_object *obj, 56362306a36Sopenharmony_ci enum f11_finger_state finger_state, 56462306a36Sopenharmony_ci u8 n_finger) 56562306a36Sopenharmony_ci{ 56662306a36Sopenharmony_ci struct f11_2d_data *data = &f11->data; 56762306a36Sopenharmony_ci u8 *pos_data = &data->abs_pos[n_finger * RMI_F11_ABS_BYTES]; 56862306a36Sopenharmony_ci int tool_type = MT_TOOL_FINGER; 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci switch (finger_state) { 57162306a36Sopenharmony_ci case F11_PRESENT: 57262306a36Sopenharmony_ci obj->type = RMI_2D_OBJECT_FINGER; 57362306a36Sopenharmony_ci break; 57462306a36Sopenharmony_ci default: 57562306a36Sopenharmony_ci obj->type = RMI_2D_OBJECT_NONE; 57662306a36Sopenharmony_ci } 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci obj->mt_tool = tool_type; 57962306a36Sopenharmony_ci obj->x = (pos_data[0] << 4) | (pos_data[2] & 0x0F); 58062306a36Sopenharmony_ci obj->y = (pos_data[1] << 4) | (pos_data[2] >> 4); 58162306a36Sopenharmony_ci obj->z = pos_data[4]; 58262306a36Sopenharmony_ci obj->wx = pos_data[3] & 0x0f; 58362306a36Sopenharmony_ci obj->wy = pos_data[3] >> 4; 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci rmi_2d_sensor_abs_process(sensor, obj, n_finger); 58662306a36Sopenharmony_ci} 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_cistatic inline u8 rmi_f11_parse_finger_state(const u8 *f_state, u8 n_finger) 58962306a36Sopenharmony_ci{ 59062306a36Sopenharmony_ci return (f_state[n_finger / 4] >> (2 * (n_finger % 4))) & 59162306a36Sopenharmony_ci FINGER_STATE_MASK; 59262306a36Sopenharmony_ci} 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_cistatic void rmi_f11_finger_handler(struct f11_data *f11, 59562306a36Sopenharmony_ci struct rmi_2d_sensor *sensor, int size) 59662306a36Sopenharmony_ci{ 59762306a36Sopenharmony_ci const u8 *f_state = f11->data.f_state; 59862306a36Sopenharmony_ci u8 finger_state; 59962306a36Sopenharmony_ci u8 i; 60062306a36Sopenharmony_ci int abs_fingers; 60162306a36Sopenharmony_ci int rel_fingers; 60262306a36Sopenharmony_ci int abs_size = sensor->nbr_fingers * RMI_F11_ABS_BYTES; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci if (sensor->report_abs) { 60562306a36Sopenharmony_ci if (abs_size > size) 60662306a36Sopenharmony_ci abs_fingers = size / RMI_F11_ABS_BYTES; 60762306a36Sopenharmony_ci else 60862306a36Sopenharmony_ci abs_fingers = sensor->nbr_fingers; 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci for (i = 0; i < abs_fingers; i++) { 61162306a36Sopenharmony_ci /* Possible of having 4 fingers per f_state register */ 61262306a36Sopenharmony_ci finger_state = rmi_f11_parse_finger_state(f_state, i); 61362306a36Sopenharmony_ci if (finger_state == F11_RESERVED) { 61462306a36Sopenharmony_ci pr_err("Invalid finger state[%d]: 0x%02x", i, 61562306a36Sopenharmony_ci finger_state); 61662306a36Sopenharmony_ci continue; 61762306a36Sopenharmony_ci } 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci rmi_f11_abs_pos_process(f11, sensor, &sensor->objs[i], 62062306a36Sopenharmony_ci finger_state, i); 62162306a36Sopenharmony_ci } 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci /* 62462306a36Sopenharmony_ci * the absolute part is made in 2 parts to allow the kernel 62562306a36Sopenharmony_ci * tracking to take place. 62662306a36Sopenharmony_ci */ 62762306a36Sopenharmony_ci if (sensor->kernel_tracking) 62862306a36Sopenharmony_ci input_mt_assign_slots(sensor->input, 62962306a36Sopenharmony_ci sensor->tracking_slots, 63062306a36Sopenharmony_ci sensor->tracking_pos, 63162306a36Sopenharmony_ci sensor->nbr_fingers, 63262306a36Sopenharmony_ci sensor->dmax); 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci for (i = 0; i < abs_fingers; i++) { 63562306a36Sopenharmony_ci finger_state = rmi_f11_parse_finger_state(f_state, i); 63662306a36Sopenharmony_ci if (finger_state == F11_RESERVED) 63762306a36Sopenharmony_ci /* no need to send twice the error */ 63862306a36Sopenharmony_ci continue; 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci rmi_2d_sensor_abs_report(sensor, &sensor->objs[i], i); 64162306a36Sopenharmony_ci } 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci input_mt_sync_frame(sensor->input); 64462306a36Sopenharmony_ci } else if (sensor->report_rel) { 64562306a36Sopenharmony_ci if ((abs_size + sensor->nbr_fingers * RMI_F11_REL_BYTES) > size) 64662306a36Sopenharmony_ci rel_fingers = (size - abs_size) / RMI_F11_REL_BYTES; 64762306a36Sopenharmony_ci else 64862306a36Sopenharmony_ci rel_fingers = sensor->nbr_fingers; 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci for (i = 0; i < rel_fingers; i++) 65162306a36Sopenharmony_ci rmi_f11_rel_pos_report(f11, i); 65262306a36Sopenharmony_ci } 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci} 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_cistatic int f11_2d_construct_data(struct f11_data *f11) 65762306a36Sopenharmony_ci{ 65862306a36Sopenharmony_ci struct rmi_2d_sensor *sensor = &f11->sensor; 65962306a36Sopenharmony_ci struct f11_2d_sensor_queries *query = &f11->sens_query; 66062306a36Sopenharmony_ci struct f11_2d_data *data = &f11->data; 66162306a36Sopenharmony_ci int i; 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci sensor->nbr_fingers = (query->nr_fingers == 5 ? 10 : 66462306a36Sopenharmony_ci query->nr_fingers + 1); 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci sensor->pkt_size = DIV_ROUND_UP(sensor->nbr_fingers, 4); 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci if (query->has_abs) { 66962306a36Sopenharmony_ci sensor->pkt_size += (sensor->nbr_fingers * 5); 67062306a36Sopenharmony_ci sensor->attn_size = sensor->pkt_size; 67162306a36Sopenharmony_ci } 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci if (query->has_rel) 67462306a36Sopenharmony_ci sensor->pkt_size += (sensor->nbr_fingers * 2); 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci /* Check if F11_2D_Query7 is non-zero */ 67762306a36Sopenharmony_ci if (query->query7_nonzero) 67862306a36Sopenharmony_ci sensor->pkt_size += sizeof(u8); 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci /* Check if F11_2D_Query7 or F11_2D_Query8 is non-zero */ 68162306a36Sopenharmony_ci if (query->query7_nonzero || query->query8_nonzero) 68262306a36Sopenharmony_ci sensor->pkt_size += sizeof(u8); 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci if (query->has_pinch || query->has_flick || query->has_rotate) { 68562306a36Sopenharmony_ci sensor->pkt_size += 3; 68662306a36Sopenharmony_ci if (!query->has_flick) 68762306a36Sopenharmony_ci sensor->pkt_size--; 68862306a36Sopenharmony_ci if (!query->has_rotate) 68962306a36Sopenharmony_ci sensor->pkt_size--; 69062306a36Sopenharmony_ci } 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci if (query->has_touch_shapes) 69362306a36Sopenharmony_ci sensor->pkt_size += 69462306a36Sopenharmony_ci DIV_ROUND_UP(query->nr_touch_shapes + 1, 8); 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci sensor->data_pkt = devm_kzalloc(&sensor->fn->dev, sensor->pkt_size, 69762306a36Sopenharmony_ci GFP_KERNEL); 69862306a36Sopenharmony_ci if (!sensor->data_pkt) 69962306a36Sopenharmony_ci return -ENOMEM; 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci data->f_state = sensor->data_pkt; 70262306a36Sopenharmony_ci i = DIV_ROUND_UP(sensor->nbr_fingers, 4); 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci if (query->has_abs) { 70562306a36Sopenharmony_ci data->abs_pos = &sensor->data_pkt[i]; 70662306a36Sopenharmony_ci i += (sensor->nbr_fingers * RMI_F11_ABS_BYTES); 70762306a36Sopenharmony_ci } 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci if (query->has_rel) { 71062306a36Sopenharmony_ci data->rel_pos = &sensor->data_pkt[i]; 71162306a36Sopenharmony_ci i += (sensor->nbr_fingers * RMI_F11_REL_BYTES); 71262306a36Sopenharmony_ci } 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci if (query->query7_nonzero) { 71562306a36Sopenharmony_ci data->gest_1 = &sensor->data_pkt[i]; 71662306a36Sopenharmony_ci i++; 71762306a36Sopenharmony_ci } 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci if (query->query7_nonzero || query->query8_nonzero) { 72062306a36Sopenharmony_ci data->gest_2 = &sensor->data_pkt[i]; 72162306a36Sopenharmony_ci i++; 72262306a36Sopenharmony_ci } 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci if (query->has_pinch) { 72562306a36Sopenharmony_ci data->pinch = &sensor->data_pkt[i]; 72662306a36Sopenharmony_ci i++; 72762306a36Sopenharmony_ci } 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci if (query->has_flick) { 73062306a36Sopenharmony_ci if (query->has_pinch) { 73162306a36Sopenharmony_ci data->flick = data->pinch; 73262306a36Sopenharmony_ci i += 2; 73362306a36Sopenharmony_ci } else { 73462306a36Sopenharmony_ci data->flick = &sensor->data_pkt[i]; 73562306a36Sopenharmony_ci i += 3; 73662306a36Sopenharmony_ci } 73762306a36Sopenharmony_ci } 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci if (query->has_rotate) { 74062306a36Sopenharmony_ci if (query->has_flick) { 74162306a36Sopenharmony_ci data->rotate = data->flick + 1; 74262306a36Sopenharmony_ci } else { 74362306a36Sopenharmony_ci data->rotate = &sensor->data_pkt[i]; 74462306a36Sopenharmony_ci i += 2; 74562306a36Sopenharmony_ci } 74662306a36Sopenharmony_ci } 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci if (query->has_touch_shapes) 74962306a36Sopenharmony_ci data->shapes = &sensor->data_pkt[i]; 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci return 0; 75262306a36Sopenharmony_ci} 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_cistatic int f11_read_control_regs(struct rmi_function *fn, 75562306a36Sopenharmony_ci struct f11_2d_ctrl *ctrl, u16 ctrl_base_addr) { 75662306a36Sopenharmony_ci struct rmi_device *rmi_dev = fn->rmi_dev; 75762306a36Sopenharmony_ci int error = 0; 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci ctrl->ctrl0_11_address = ctrl_base_addr; 76062306a36Sopenharmony_ci error = rmi_read_block(rmi_dev, ctrl_base_addr, ctrl->ctrl0_11, 76162306a36Sopenharmony_ci RMI_F11_CTRL_REG_COUNT); 76262306a36Sopenharmony_ci if (error < 0) { 76362306a36Sopenharmony_ci dev_err(&fn->dev, "Failed to read ctrl0, code: %d.\n", error); 76462306a36Sopenharmony_ci return error; 76562306a36Sopenharmony_ci } 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci return 0; 76862306a36Sopenharmony_ci} 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_cistatic int f11_write_control_regs(struct rmi_function *fn, 77162306a36Sopenharmony_ci struct f11_2d_sensor_queries *query, 77262306a36Sopenharmony_ci struct f11_2d_ctrl *ctrl, 77362306a36Sopenharmony_ci u16 ctrl_base_addr) 77462306a36Sopenharmony_ci{ 77562306a36Sopenharmony_ci struct rmi_device *rmi_dev = fn->rmi_dev; 77662306a36Sopenharmony_ci int error; 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci error = rmi_write_block(rmi_dev, ctrl_base_addr, ctrl->ctrl0_11, 77962306a36Sopenharmony_ci RMI_F11_CTRL_REG_COUNT); 78062306a36Sopenharmony_ci if (error < 0) 78162306a36Sopenharmony_ci return error; 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ci return 0; 78462306a36Sopenharmony_ci} 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_cistatic int rmi_f11_get_query_parameters(struct rmi_device *rmi_dev, 78762306a36Sopenharmony_ci struct f11_data *f11, 78862306a36Sopenharmony_ci struct f11_2d_sensor_queries *sensor_query, 78962306a36Sopenharmony_ci u16 query_base_addr) 79062306a36Sopenharmony_ci{ 79162306a36Sopenharmony_ci int query_size; 79262306a36Sopenharmony_ci int rc; 79362306a36Sopenharmony_ci u8 query_buf[RMI_F11_QUERY_SIZE]; 79462306a36Sopenharmony_ci bool has_query36 = false; 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci rc = rmi_read_block(rmi_dev, query_base_addr, query_buf, 79762306a36Sopenharmony_ci RMI_F11_QUERY_SIZE); 79862306a36Sopenharmony_ci if (rc < 0) 79962306a36Sopenharmony_ci return rc; 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci sensor_query->nr_fingers = query_buf[0] & RMI_F11_NR_FINGERS_MASK; 80262306a36Sopenharmony_ci sensor_query->has_rel = !!(query_buf[0] & RMI_F11_HAS_REL); 80362306a36Sopenharmony_ci sensor_query->has_abs = !!(query_buf[0] & RMI_F11_HAS_ABS); 80462306a36Sopenharmony_ci sensor_query->has_gestures = !!(query_buf[0] & RMI_F11_HAS_GESTURES); 80562306a36Sopenharmony_ci sensor_query->has_sensitivity_adjust = 80662306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_SENSITIVITY_ADJ); 80762306a36Sopenharmony_ci sensor_query->configurable = !!(query_buf[0] & RMI_F11_CONFIGURABLE); 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci sensor_query->nr_x_electrodes = 81062306a36Sopenharmony_ci query_buf[1] & RMI_F11_NR_ELECTRODES_MASK; 81162306a36Sopenharmony_ci sensor_query->nr_y_electrodes = 81262306a36Sopenharmony_ci query_buf[2] & RMI_F11_NR_ELECTRODES_MASK; 81362306a36Sopenharmony_ci sensor_query->max_electrodes = 81462306a36Sopenharmony_ci query_buf[3] & RMI_F11_NR_ELECTRODES_MASK; 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci query_size = RMI_F11_QUERY_SIZE; 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci if (sensor_query->has_abs) { 81962306a36Sopenharmony_ci rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf); 82062306a36Sopenharmony_ci if (rc < 0) 82162306a36Sopenharmony_ci return rc; 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci sensor_query->abs_data_size = 82462306a36Sopenharmony_ci query_buf[0] & RMI_F11_ABS_DATA_SIZE_MASK; 82562306a36Sopenharmony_ci sensor_query->has_anchored_finger = 82662306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_ANCHORED_FINGER); 82762306a36Sopenharmony_ci sensor_query->has_adj_hyst = 82862306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_ADJ_HYST); 82962306a36Sopenharmony_ci sensor_query->has_dribble = 83062306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_DRIBBLE); 83162306a36Sopenharmony_ci sensor_query->has_bending_correction = 83262306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_BENDING_CORRECTION); 83362306a36Sopenharmony_ci sensor_query->has_large_object_suppression = 83462306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_LARGE_OBJECT_SUPPRESSION); 83562306a36Sopenharmony_ci sensor_query->has_jitter_filter = 83662306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_JITTER_FILTER); 83762306a36Sopenharmony_ci query_size++; 83862306a36Sopenharmony_ci } 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci if (sensor_query->has_rel) { 84162306a36Sopenharmony_ci rc = rmi_read(rmi_dev, query_base_addr + query_size, 84262306a36Sopenharmony_ci &sensor_query->f11_2d_query6); 84362306a36Sopenharmony_ci if (rc < 0) 84462306a36Sopenharmony_ci return rc; 84562306a36Sopenharmony_ci query_size++; 84662306a36Sopenharmony_ci } 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci if (sensor_query->has_gestures) { 84962306a36Sopenharmony_ci rc = rmi_read_block(rmi_dev, query_base_addr + query_size, 85062306a36Sopenharmony_ci query_buf, RMI_F11_QUERY_GESTURE_SIZE); 85162306a36Sopenharmony_ci if (rc < 0) 85262306a36Sopenharmony_ci return rc; 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci sensor_query->has_single_tap = 85562306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_SINGLE_TAP); 85662306a36Sopenharmony_ci sensor_query->has_tap_n_hold = 85762306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_TAP_AND_HOLD); 85862306a36Sopenharmony_ci sensor_query->has_double_tap = 85962306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_DOUBLE_TAP); 86062306a36Sopenharmony_ci sensor_query->has_early_tap = 86162306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_EARLY_TAP); 86262306a36Sopenharmony_ci sensor_query->has_flick = 86362306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_FLICK); 86462306a36Sopenharmony_ci sensor_query->has_press = 86562306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_PRESS); 86662306a36Sopenharmony_ci sensor_query->has_pinch = 86762306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_PINCH); 86862306a36Sopenharmony_ci sensor_query->has_chiral = 86962306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_CHIRAL); 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_ci /* query 8 */ 87262306a36Sopenharmony_ci sensor_query->has_palm_det = 87362306a36Sopenharmony_ci !!(query_buf[1] & RMI_F11_HAS_PALM_DET); 87462306a36Sopenharmony_ci sensor_query->has_rotate = 87562306a36Sopenharmony_ci !!(query_buf[1] & RMI_F11_HAS_ROTATE); 87662306a36Sopenharmony_ci sensor_query->has_touch_shapes = 87762306a36Sopenharmony_ci !!(query_buf[1] & RMI_F11_HAS_TOUCH_SHAPES); 87862306a36Sopenharmony_ci sensor_query->has_scroll_zones = 87962306a36Sopenharmony_ci !!(query_buf[1] & RMI_F11_HAS_SCROLL_ZONES); 88062306a36Sopenharmony_ci sensor_query->has_individual_scroll_zones = 88162306a36Sopenharmony_ci !!(query_buf[1] & RMI_F11_HAS_INDIVIDUAL_SCROLL_ZONES); 88262306a36Sopenharmony_ci sensor_query->has_mf_scroll = 88362306a36Sopenharmony_ci !!(query_buf[1] & RMI_F11_HAS_MF_SCROLL); 88462306a36Sopenharmony_ci sensor_query->has_mf_edge_motion = 88562306a36Sopenharmony_ci !!(query_buf[1] & RMI_F11_HAS_MF_EDGE_MOTION); 88662306a36Sopenharmony_ci sensor_query->has_mf_scroll_inertia = 88762306a36Sopenharmony_ci !!(query_buf[1] & RMI_F11_HAS_MF_SCROLL_INERTIA); 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_ci sensor_query->query7_nonzero = !!(query_buf[0]); 89062306a36Sopenharmony_ci sensor_query->query8_nonzero = !!(query_buf[1]); 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci query_size += 2; 89362306a36Sopenharmony_ci } 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci if (f11->has_query9) { 89662306a36Sopenharmony_ci rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf); 89762306a36Sopenharmony_ci if (rc < 0) 89862306a36Sopenharmony_ci return rc; 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci sensor_query->has_pen = 90162306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_PEN); 90262306a36Sopenharmony_ci sensor_query->has_proximity = 90362306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_PROXIMITY); 90462306a36Sopenharmony_ci sensor_query->has_palm_det_sensitivity = 90562306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_PALM_DET_SENSITIVITY); 90662306a36Sopenharmony_ci sensor_query->has_suppress_on_palm_detect = 90762306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_SUPPRESS_ON_PALM_DETECT); 90862306a36Sopenharmony_ci sensor_query->has_two_pen_thresholds = 90962306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_TWO_PEN_THRESHOLDS); 91062306a36Sopenharmony_ci sensor_query->has_contact_geometry = 91162306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_CONTACT_GEOMETRY); 91262306a36Sopenharmony_ci sensor_query->has_pen_hover_discrimination = 91362306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_PEN_HOVER_DISCRIMINATION); 91462306a36Sopenharmony_ci sensor_query->has_pen_filters = 91562306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_PEN_FILTERS); 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_ci query_size++; 91862306a36Sopenharmony_ci } 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci if (sensor_query->has_touch_shapes) { 92162306a36Sopenharmony_ci rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf); 92262306a36Sopenharmony_ci if (rc < 0) 92362306a36Sopenharmony_ci return rc; 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci sensor_query->nr_touch_shapes = query_buf[0] & 92662306a36Sopenharmony_ci RMI_F11_NR_TOUCH_SHAPES_MASK; 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci query_size++; 92962306a36Sopenharmony_ci } 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci if (f11->has_query11) { 93262306a36Sopenharmony_ci rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf); 93362306a36Sopenharmony_ci if (rc < 0) 93462306a36Sopenharmony_ci return rc; 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci sensor_query->has_z_tuning = 93762306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_Z_TUNING); 93862306a36Sopenharmony_ci sensor_query->has_algorithm_selection = 93962306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_ALGORITHM_SELECTION); 94062306a36Sopenharmony_ci sensor_query->has_w_tuning = 94162306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_W_TUNING); 94262306a36Sopenharmony_ci sensor_query->has_pitch_info = 94362306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_PITCH_INFO); 94462306a36Sopenharmony_ci sensor_query->has_finger_size = 94562306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_FINGER_SIZE); 94662306a36Sopenharmony_ci sensor_query->has_segmentation_aggressiveness = 94762306a36Sopenharmony_ci !!(query_buf[0] & 94862306a36Sopenharmony_ci RMI_F11_HAS_SEGMENTATION_AGGRESSIVENESS); 94962306a36Sopenharmony_ci sensor_query->has_XY_clip = 95062306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_XY_CLIP); 95162306a36Sopenharmony_ci sensor_query->has_drumming_filter = 95262306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_DRUMMING_FILTER); 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_ci query_size++; 95562306a36Sopenharmony_ci } 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_ci if (f11->has_query12) { 95862306a36Sopenharmony_ci rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf); 95962306a36Sopenharmony_ci if (rc < 0) 96062306a36Sopenharmony_ci return rc; 96162306a36Sopenharmony_ci 96262306a36Sopenharmony_ci sensor_query->has_gapless_finger = 96362306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_GAPLESS_FINGER); 96462306a36Sopenharmony_ci sensor_query->has_gapless_finger_tuning = 96562306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_GAPLESS_FINGER_TUNING); 96662306a36Sopenharmony_ci sensor_query->has_8bit_w = 96762306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_8BIT_W); 96862306a36Sopenharmony_ci sensor_query->has_adjustable_mapping = 96962306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_ADJUSTABLE_MAPPING); 97062306a36Sopenharmony_ci sensor_query->has_info2 = 97162306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_INFO2); 97262306a36Sopenharmony_ci sensor_query->has_physical_props = 97362306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_PHYSICAL_PROPS); 97462306a36Sopenharmony_ci sensor_query->has_finger_limit = 97562306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_FINGER_LIMIT); 97662306a36Sopenharmony_ci sensor_query->has_linear_coeff_2 = 97762306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_LINEAR_COEFF); 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci query_size++; 98062306a36Sopenharmony_ci } 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci if (sensor_query->has_jitter_filter) { 98362306a36Sopenharmony_ci rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf); 98462306a36Sopenharmony_ci if (rc < 0) 98562306a36Sopenharmony_ci return rc; 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci sensor_query->jitter_window_size = query_buf[0] & 98862306a36Sopenharmony_ci RMI_F11_JITTER_WINDOW_MASK; 98962306a36Sopenharmony_ci sensor_query->jitter_filter_type = (query_buf[0] & 99062306a36Sopenharmony_ci RMI_F11_JITTER_FILTER_MASK) >> 99162306a36Sopenharmony_ci RMI_F11_JITTER_FILTER_SHIFT; 99262306a36Sopenharmony_ci 99362306a36Sopenharmony_ci query_size++; 99462306a36Sopenharmony_ci } 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci if (sensor_query->has_info2) { 99762306a36Sopenharmony_ci rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf); 99862306a36Sopenharmony_ci if (rc < 0) 99962306a36Sopenharmony_ci return rc; 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci sensor_query->light_control = 100262306a36Sopenharmony_ci query_buf[0] & RMI_F11_LIGHT_CONTROL_MASK; 100362306a36Sopenharmony_ci sensor_query->is_clear = 100462306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_IS_CLEAR); 100562306a36Sopenharmony_ci sensor_query->clickpad_props = 100662306a36Sopenharmony_ci (query_buf[0] & RMI_F11_CLICKPAD_PROPS_MASK) >> 100762306a36Sopenharmony_ci RMI_F11_CLICKPAD_PROPS_SHIFT; 100862306a36Sopenharmony_ci sensor_query->mouse_buttons = 100962306a36Sopenharmony_ci (query_buf[0] & RMI_F11_MOUSE_BUTTONS_MASK) >> 101062306a36Sopenharmony_ci RMI_F11_MOUSE_BUTTONS_SHIFT; 101162306a36Sopenharmony_ci sensor_query->has_advanced_gestures = 101262306a36Sopenharmony_ci !!(query_buf[0] & RMI_F11_HAS_ADVANCED_GESTURES); 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci query_size++; 101562306a36Sopenharmony_ci } 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci if (sensor_query->has_physical_props) { 101862306a36Sopenharmony_ci rc = rmi_read_block(rmi_dev, query_base_addr 101962306a36Sopenharmony_ci + query_size, query_buf, 4); 102062306a36Sopenharmony_ci if (rc < 0) 102162306a36Sopenharmony_ci return rc; 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci sensor_query->x_sensor_size_mm = 102462306a36Sopenharmony_ci (query_buf[0] | (query_buf[1] << 8)) / 10; 102562306a36Sopenharmony_ci sensor_query->y_sensor_size_mm = 102662306a36Sopenharmony_ci (query_buf[2] | (query_buf[3] << 8)) / 10; 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci /* 102962306a36Sopenharmony_ci * query 15 - 18 contain the size of the sensor 103062306a36Sopenharmony_ci * and query 19 - 26 contain bezel dimensions 103162306a36Sopenharmony_ci */ 103262306a36Sopenharmony_ci query_size += 12; 103362306a36Sopenharmony_ci } 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci if (f11->has_query27) 103662306a36Sopenharmony_ci ++query_size; 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ci if (f11->has_query28) { 103962306a36Sopenharmony_ci rc = rmi_read(rmi_dev, query_base_addr + query_size, 104062306a36Sopenharmony_ci query_buf); 104162306a36Sopenharmony_ci if (rc < 0) 104262306a36Sopenharmony_ci return rc; 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci has_query36 = !!(query_buf[0] & BIT(6)); 104562306a36Sopenharmony_ci } 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci if (has_query36) { 104862306a36Sopenharmony_ci query_size += 2; 104962306a36Sopenharmony_ci rc = rmi_read(rmi_dev, query_base_addr + query_size, 105062306a36Sopenharmony_ci query_buf); 105162306a36Sopenharmony_ci if (rc < 0) 105262306a36Sopenharmony_ci return rc; 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_ci if (!!(query_buf[0] & BIT(5))) 105562306a36Sopenharmony_ci f11->has_acm = true; 105662306a36Sopenharmony_ci } 105762306a36Sopenharmony_ci 105862306a36Sopenharmony_ci return query_size; 105962306a36Sopenharmony_ci} 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_cistatic int rmi_f11_initialize(struct rmi_function *fn) 106262306a36Sopenharmony_ci{ 106362306a36Sopenharmony_ci struct rmi_device *rmi_dev = fn->rmi_dev; 106462306a36Sopenharmony_ci struct f11_data *f11; 106562306a36Sopenharmony_ci struct f11_2d_ctrl *ctrl; 106662306a36Sopenharmony_ci u8 query_offset; 106762306a36Sopenharmony_ci u16 query_base_addr; 106862306a36Sopenharmony_ci u16 control_base_addr; 106962306a36Sopenharmony_ci u16 max_x_pos, max_y_pos; 107062306a36Sopenharmony_ci int rc; 107162306a36Sopenharmony_ci const struct rmi_device_platform_data *pdata = 107262306a36Sopenharmony_ci rmi_get_platform_data(rmi_dev); 107362306a36Sopenharmony_ci struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev); 107462306a36Sopenharmony_ci struct rmi_2d_sensor *sensor; 107562306a36Sopenharmony_ci u8 buf; 107662306a36Sopenharmony_ci int mask_size; 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Initializing F11 values.\n"); 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_ci mask_size = BITS_TO_LONGS(drvdata->irq_count) * sizeof(unsigned long); 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci /* 108362306a36Sopenharmony_ci ** init instance data, fill in values and create any sysfs files 108462306a36Sopenharmony_ci */ 108562306a36Sopenharmony_ci f11 = devm_kzalloc(&fn->dev, sizeof(struct f11_data) + mask_size * 2, 108662306a36Sopenharmony_ci GFP_KERNEL); 108762306a36Sopenharmony_ci if (!f11) 108862306a36Sopenharmony_ci return -ENOMEM; 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci if (fn->dev.of_node) { 109162306a36Sopenharmony_ci rc = rmi_2d_sensor_of_probe(&fn->dev, &f11->sensor_pdata); 109262306a36Sopenharmony_ci if (rc) 109362306a36Sopenharmony_ci return rc; 109462306a36Sopenharmony_ci } else { 109562306a36Sopenharmony_ci f11->sensor_pdata = pdata->sensor_pdata; 109662306a36Sopenharmony_ci } 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_ci f11->rezero_wait_ms = f11->sensor_pdata.rezero_wait; 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci f11->abs_mask = (unsigned long *)((char *)f11 110162306a36Sopenharmony_ci + sizeof(struct f11_data)); 110262306a36Sopenharmony_ci f11->rel_mask = (unsigned long *)((char *)f11 110362306a36Sopenharmony_ci + sizeof(struct f11_data) + mask_size); 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ci set_bit(fn->irq_pos, f11->abs_mask); 110662306a36Sopenharmony_ci set_bit(fn->irq_pos + 1, f11->rel_mask); 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci query_base_addr = fn->fd.query_base_addr; 110962306a36Sopenharmony_ci control_base_addr = fn->fd.control_base_addr; 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ci rc = rmi_read(rmi_dev, query_base_addr, &buf); 111262306a36Sopenharmony_ci if (rc < 0) 111362306a36Sopenharmony_ci return rc; 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_ci f11->has_query9 = !!(buf & RMI_F11_HAS_QUERY9); 111662306a36Sopenharmony_ci f11->has_query11 = !!(buf & RMI_F11_HAS_QUERY11); 111762306a36Sopenharmony_ci f11->has_query12 = !!(buf & RMI_F11_HAS_QUERY12); 111862306a36Sopenharmony_ci f11->has_query27 = !!(buf & RMI_F11_HAS_QUERY27); 111962306a36Sopenharmony_ci f11->has_query28 = !!(buf & RMI_F11_HAS_QUERY28); 112062306a36Sopenharmony_ci 112162306a36Sopenharmony_ci query_offset = (query_base_addr + 1); 112262306a36Sopenharmony_ci sensor = &f11->sensor; 112362306a36Sopenharmony_ci sensor->fn = fn; 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_ci rc = rmi_f11_get_query_parameters(rmi_dev, f11, 112662306a36Sopenharmony_ci &f11->sens_query, query_offset); 112762306a36Sopenharmony_ci if (rc < 0) 112862306a36Sopenharmony_ci return rc; 112962306a36Sopenharmony_ci query_offset += rc; 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_ci rc = f11_read_control_regs(fn, &f11->dev_controls, 113262306a36Sopenharmony_ci control_base_addr); 113362306a36Sopenharmony_ci if (rc < 0) { 113462306a36Sopenharmony_ci dev_err(&fn->dev, 113562306a36Sopenharmony_ci "Failed to read F11 control params.\n"); 113662306a36Sopenharmony_ci return rc; 113762306a36Sopenharmony_ci } 113862306a36Sopenharmony_ci 113962306a36Sopenharmony_ci if (f11->sens_query.has_info2) { 114062306a36Sopenharmony_ci if (f11->sens_query.is_clear) 114162306a36Sopenharmony_ci f11->sensor.sensor_type = rmi_sensor_touchscreen; 114262306a36Sopenharmony_ci else 114362306a36Sopenharmony_ci f11->sensor.sensor_type = rmi_sensor_touchpad; 114462306a36Sopenharmony_ci } 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci sensor->report_abs = f11->sens_query.has_abs; 114762306a36Sopenharmony_ci 114862306a36Sopenharmony_ci sensor->axis_align = 114962306a36Sopenharmony_ci f11->sensor_pdata.axis_align; 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_ci sensor->topbuttonpad = f11->sensor_pdata.topbuttonpad; 115262306a36Sopenharmony_ci sensor->kernel_tracking = f11->sensor_pdata.kernel_tracking; 115362306a36Sopenharmony_ci sensor->dmax = f11->sensor_pdata.dmax; 115462306a36Sopenharmony_ci sensor->dribble = f11->sensor_pdata.dribble; 115562306a36Sopenharmony_ci sensor->palm_detect = f11->sensor_pdata.palm_detect; 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_ci if (f11->sens_query.has_physical_props) { 115862306a36Sopenharmony_ci sensor->x_mm = f11->sens_query.x_sensor_size_mm; 115962306a36Sopenharmony_ci sensor->y_mm = f11->sens_query.y_sensor_size_mm; 116062306a36Sopenharmony_ci } else { 116162306a36Sopenharmony_ci sensor->x_mm = f11->sensor_pdata.x_mm; 116262306a36Sopenharmony_ci sensor->y_mm = f11->sensor_pdata.y_mm; 116362306a36Sopenharmony_ci } 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_ci if (sensor->sensor_type == rmi_sensor_default) 116662306a36Sopenharmony_ci sensor->sensor_type = 116762306a36Sopenharmony_ci f11->sensor_pdata.sensor_type; 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci sensor->report_abs = sensor->report_abs 117062306a36Sopenharmony_ci && !(f11->sensor_pdata.disable_report_mask 117162306a36Sopenharmony_ci & RMI_F11_DISABLE_ABS_REPORT); 117262306a36Sopenharmony_ci 117362306a36Sopenharmony_ci if (!sensor->report_abs) 117462306a36Sopenharmony_ci /* 117562306a36Sopenharmony_ci * If device doesn't have abs or if it has been disables 117662306a36Sopenharmony_ci * fallback to reporting rel data. 117762306a36Sopenharmony_ci */ 117862306a36Sopenharmony_ci sensor->report_rel = f11->sens_query.has_rel; 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_ci rc = rmi_read_block(rmi_dev, 118162306a36Sopenharmony_ci control_base_addr + F11_CTRL_SENSOR_MAX_X_POS_OFFSET, 118262306a36Sopenharmony_ci (u8 *)&max_x_pos, sizeof(max_x_pos)); 118362306a36Sopenharmony_ci if (rc < 0) 118462306a36Sopenharmony_ci return rc; 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_ci rc = rmi_read_block(rmi_dev, 118762306a36Sopenharmony_ci control_base_addr + F11_CTRL_SENSOR_MAX_Y_POS_OFFSET, 118862306a36Sopenharmony_ci (u8 *)&max_y_pos, sizeof(max_y_pos)); 118962306a36Sopenharmony_ci if (rc < 0) 119062306a36Sopenharmony_ci return rc; 119162306a36Sopenharmony_ci 119262306a36Sopenharmony_ci sensor->max_x = max_x_pos; 119362306a36Sopenharmony_ci sensor->max_y = max_y_pos; 119462306a36Sopenharmony_ci 119562306a36Sopenharmony_ci rc = f11_2d_construct_data(f11); 119662306a36Sopenharmony_ci if (rc < 0) 119762306a36Sopenharmony_ci return rc; 119862306a36Sopenharmony_ci 119962306a36Sopenharmony_ci if (f11->has_acm) 120062306a36Sopenharmony_ci f11->sensor.attn_size += f11->sensor.nbr_fingers * 2; 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_ci /* allocate the in-kernel tracking buffers */ 120362306a36Sopenharmony_ci sensor->tracking_pos = devm_kcalloc(&fn->dev, 120462306a36Sopenharmony_ci sensor->nbr_fingers, sizeof(struct input_mt_pos), 120562306a36Sopenharmony_ci GFP_KERNEL); 120662306a36Sopenharmony_ci sensor->tracking_slots = devm_kcalloc(&fn->dev, 120762306a36Sopenharmony_ci sensor->nbr_fingers, sizeof(int), GFP_KERNEL); 120862306a36Sopenharmony_ci sensor->objs = devm_kcalloc(&fn->dev, 120962306a36Sopenharmony_ci sensor->nbr_fingers, 121062306a36Sopenharmony_ci sizeof(struct rmi_2d_sensor_abs_object), 121162306a36Sopenharmony_ci GFP_KERNEL); 121262306a36Sopenharmony_ci if (!sensor->tracking_pos || !sensor->tracking_slots || !sensor->objs) 121362306a36Sopenharmony_ci return -ENOMEM; 121462306a36Sopenharmony_ci 121562306a36Sopenharmony_ci ctrl = &f11->dev_controls; 121662306a36Sopenharmony_ci if (sensor->axis_align.delta_x_threshold) 121762306a36Sopenharmony_ci ctrl->ctrl0_11[RMI_F11_DELTA_X_THRESHOLD] = 121862306a36Sopenharmony_ci sensor->axis_align.delta_x_threshold; 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci if (sensor->axis_align.delta_y_threshold) 122162306a36Sopenharmony_ci ctrl->ctrl0_11[RMI_F11_DELTA_Y_THRESHOLD] = 122262306a36Sopenharmony_ci sensor->axis_align.delta_y_threshold; 122362306a36Sopenharmony_ci 122462306a36Sopenharmony_ci /* 122562306a36Sopenharmony_ci * If distance threshold values are set, switch to reduced reporting 122662306a36Sopenharmony_ci * mode so they actually get used by the controller. 122762306a36Sopenharmony_ci */ 122862306a36Sopenharmony_ci if (sensor->axis_align.delta_x_threshold || 122962306a36Sopenharmony_ci sensor->axis_align.delta_y_threshold) { 123062306a36Sopenharmony_ci ctrl->ctrl0_11[0] &= ~RMI_F11_REPORT_MODE_MASK; 123162306a36Sopenharmony_ci ctrl->ctrl0_11[0] |= RMI_F11_REPORT_MODE_REDUCED; 123262306a36Sopenharmony_ci } 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ci if (f11->sens_query.has_dribble) { 123562306a36Sopenharmony_ci switch (sensor->dribble) { 123662306a36Sopenharmony_ci case RMI_REG_STATE_OFF: 123762306a36Sopenharmony_ci ctrl->ctrl0_11[0] &= ~BIT(6); 123862306a36Sopenharmony_ci break; 123962306a36Sopenharmony_ci case RMI_REG_STATE_ON: 124062306a36Sopenharmony_ci ctrl->ctrl0_11[0] |= BIT(6); 124162306a36Sopenharmony_ci break; 124262306a36Sopenharmony_ci case RMI_REG_STATE_DEFAULT: 124362306a36Sopenharmony_ci default: 124462306a36Sopenharmony_ci break; 124562306a36Sopenharmony_ci } 124662306a36Sopenharmony_ci } 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_ci if (f11->sens_query.has_palm_det) { 124962306a36Sopenharmony_ci switch (sensor->palm_detect) { 125062306a36Sopenharmony_ci case RMI_REG_STATE_OFF: 125162306a36Sopenharmony_ci ctrl->ctrl0_11[11] &= ~BIT(0); 125262306a36Sopenharmony_ci break; 125362306a36Sopenharmony_ci case RMI_REG_STATE_ON: 125462306a36Sopenharmony_ci ctrl->ctrl0_11[11] |= BIT(0); 125562306a36Sopenharmony_ci break; 125662306a36Sopenharmony_ci case RMI_REG_STATE_DEFAULT: 125762306a36Sopenharmony_ci default: 125862306a36Sopenharmony_ci break; 125962306a36Sopenharmony_ci } 126062306a36Sopenharmony_ci } 126162306a36Sopenharmony_ci 126262306a36Sopenharmony_ci rc = f11_write_control_regs(fn, &f11->sens_query, 126362306a36Sopenharmony_ci &f11->dev_controls, fn->fd.control_base_addr); 126462306a36Sopenharmony_ci if (rc) 126562306a36Sopenharmony_ci dev_warn(&fn->dev, "Failed to write control registers\n"); 126662306a36Sopenharmony_ci 126762306a36Sopenharmony_ci mutex_init(&f11->dev_controls_mutex); 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_ci dev_set_drvdata(&fn->dev, f11); 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_ci return 0; 127262306a36Sopenharmony_ci} 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_cistatic int rmi_f11_config(struct rmi_function *fn) 127562306a36Sopenharmony_ci{ 127662306a36Sopenharmony_ci struct f11_data *f11 = dev_get_drvdata(&fn->dev); 127762306a36Sopenharmony_ci struct rmi_driver *drv = fn->rmi_dev->driver; 127862306a36Sopenharmony_ci struct rmi_2d_sensor *sensor = &f11->sensor; 127962306a36Sopenharmony_ci int rc; 128062306a36Sopenharmony_ci 128162306a36Sopenharmony_ci if (!sensor->report_abs) 128262306a36Sopenharmony_ci drv->clear_irq_bits(fn->rmi_dev, f11->abs_mask); 128362306a36Sopenharmony_ci else 128462306a36Sopenharmony_ci drv->set_irq_bits(fn->rmi_dev, f11->abs_mask); 128562306a36Sopenharmony_ci 128662306a36Sopenharmony_ci if (!sensor->report_rel) 128762306a36Sopenharmony_ci drv->clear_irq_bits(fn->rmi_dev, f11->rel_mask); 128862306a36Sopenharmony_ci else 128962306a36Sopenharmony_ci drv->set_irq_bits(fn->rmi_dev, f11->rel_mask); 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ci rc = f11_write_control_regs(fn, &f11->sens_query, 129262306a36Sopenharmony_ci &f11->dev_controls, fn->fd.query_base_addr); 129362306a36Sopenharmony_ci if (rc < 0) 129462306a36Sopenharmony_ci return rc; 129562306a36Sopenharmony_ci 129662306a36Sopenharmony_ci return 0; 129762306a36Sopenharmony_ci} 129862306a36Sopenharmony_ci 129962306a36Sopenharmony_cistatic irqreturn_t rmi_f11_attention(int irq, void *ctx) 130062306a36Sopenharmony_ci{ 130162306a36Sopenharmony_ci struct rmi_function *fn = ctx; 130262306a36Sopenharmony_ci struct rmi_device *rmi_dev = fn->rmi_dev; 130362306a36Sopenharmony_ci struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev); 130462306a36Sopenharmony_ci struct f11_data *f11 = dev_get_drvdata(&fn->dev); 130562306a36Sopenharmony_ci u16 data_base_addr = fn->fd.data_base_addr; 130662306a36Sopenharmony_ci int error; 130762306a36Sopenharmony_ci int valid_bytes = f11->sensor.pkt_size; 130862306a36Sopenharmony_ci 130962306a36Sopenharmony_ci if (drvdata->attn_data.data) { 131062306a36Sopenharmony_ci /* 131162306a36Sopenharmony_ci * The valid data in the attention report is less then 131262306a36Sopenharmony_ci * expected. Only process the complete fingers. 131362306a36Sopenharmony_ci */ 131462306a36Sopenharmony_ci if (f11->sensor.attn_size > drvdata->attn_data.size) 131562306a36Sopenharmony_ci valid_bytes = drvdata->attn_data.size; 131662306a36Sopenharmony_ci else 131762306a36Sopenharmony_ci valid_bytes = f11->sensor.attn_size; 131862306a36Sopenharmony_ci memcpy(f11->sensor.data_pkt, drvdata->attn_data.data, 131962306a36Sopenharmony_ci valid_bytes); 132062306a36Sopenharmony_ci drvdata->attn_data.data += valid_bytes; 132162306a36Sopenharmony_ci drvdata->attn_data.size -= valid_bytes; 132262306a36Sopenharmony_ci } else { 132362306a36Sopenharmony_ci error = rmi_read_block(rmi_dev, 132462306a36Sopenharmony_ci data_base_addr, f11->sensor.data_pkt, 132562306a36Sopenharmony_ci f11->sensor.pkt_size); 132662306a36Sopenharmony_ci if (error < 0) 132762306a36Sopenharmony_ci return IRQ_RETVAL(error); 132862306a36Sopenharmony_ci } 132962306a36Sopenharmony_ci 133062306a36Sopenharmony_ci rmi_f11_finger_handler(f11, &f11->sensor, valid_bytes); 133162306a36Sopenharmony_ci 133262306a36Sopenharmony_ci return IRQ_HANDLED; 133362306a36Sopenharmony_ci} 133462306a36Sopenharmony_ci 133562306a36Sopenharmony_cistatic int rmi_f11_resume(struct rmi_function *fn) 133662306a36Sopenharmony_ci{ 133762306a36Sopenharmony_ci struct f11_data *f11 = dev_get_drvdata(&fn->dev); 133862306a36Sopenharmony_ci int error; 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_ci rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Resuming...\n"); 134162306a36Sopenharmony_ci if (!f11->rezero_wait_ms) 134262306a36Sopenharmony_ci return 0; 134362306a36Sopenharmony_ci 134462306a36Sopenharmony_ci mdelay(f11->rezero_wait_ms); 134562306a36Sopenharmony_ci 134662306a36Sopenharmony_ci error = rmi_write(fn->rmi_dev, fn->fd.command_base_addr, 134762306a36Sopenharmony_ci RMI_F11_REZERO); 134862306a36Sopenharmony_ci if (error) { 134962306a36Sopenharmony_ci dev_err(&fn->dev, 135062306a36Sopenharmony_ci "%s: failed to issue rezero command, error = %d.", 135162306a36Sopenharmony_ci __func__, error); 135262306a36Sopenharmony_ci return error; 135362306a36Sopenharmony_ci } 135462306a36Sopenharmony_ci 135562306a36Sopenharmony_ci return 0; 135662306a36Sopenharmony_ci} 135762306a36Sopenharmony_ci 135862306a36Sopenharmony_cistatic int rmi_f11_probe(struct rmi_function *fn) 135962306a36Sopenharmony_ci{ 136062306a36Sopenharmony_ci int error; 136162306a36Sopenharmony_ci struct f11_data *f11; 136262306a36Sopenharmony_ci 136362306a36Sopenharmony_ci error = rmi_f11_initialize(fn); 136462306a36Sopenharmony_ci if (error) 136562306a36Sopenharmony_ci return error; 136662306a36Sopenharmony_ci 136762306a36Sopenharmony_ci f11 = dev_get_drvdata(&fn->dev); 136862306a36Sopenharmony_ci error = rmi_2d_sensor_configure_input(fn, &f11->sensor); 136962306a36Sopenharmony_ci if (error) 137062306a36Sopenharmony_ci return error; 137162306a36Sopenharmony_ci 137262306a36Sopenharmony_ci return 0; 137362306a36Sopenharmony_ci} 137462306a36Sopenharmony_ci 137562306a36Sopenharmony_cistruct rmi_function_handler rmi_f11_handler = { 137662306a36Sopenharmony_ci .driver = { 137762306a36Sopenharmony_ci .name = "rmi4_f11", 137862306a36Sopenharmony_ci }, 137962306a36Sopenharmony_ci .func = 0x11, 138062306a36Sopenharmony_ci .probe = rmi_f11_probe, 138162306a36Sopenharmony_ci .config = rmi_f11_config, 138262306a36Sopenharmony_ci .attention = rmi_f11_attention, 138362306a36Sopenharmony_ci .resume = rmi_f11_resume, 138462306a36Sopenharmony_ci}; 1385