18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (c) 2012-2016 Synaptics Incorporated
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci#include <linux/input.h>
68c2ecf20Sopenharmony_ci#include <linux/input/mt.h>
78c2ecf20Sopenharmony_ci#include <linux/rmi.h>
88c2ecf20Sopenharmony_ci#include "rmi_driver.h"
98c2ecf20Sopenharmony_ci#include "rmi_2d_sensor.h"
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_cienum rmi_f12_object_type {
128c2ecf20Sopenharmony_ci	RMI_F12_OBJECT_NONE			= 0x00,
138c2ecf20Sopenharmony_ci	RMI_F12_OBJECT_FINGER			= 0x01,
148c2ecf20Sopenharmony_ci	RMI_F12_OBJECT_STYLUS			= 0x02,
158c2ecf20Sopenharmony_ci	RMI_F12_OBJECT_PALM			= 0x03,
168c2ecf20Sopenharmony_ci	RMI_F12_OBJECT_UNCLASSIFIED		= 0x04,
178c2ecf20Sopenharmony_ci	RMI_F12_OBJECT_GLOVED_FINGER		= 0x06,
188c2ecf20Sopenharmony_ci	RMI_F12_OBJECT_NARROW_OBJECT		= 0x07,
198c2ecf20Sopenharmony_ci	RMI_F12_OBJECT_HAND_EDGE		= 0x08,
208c2ecf20Sopenharmony_ci	RMI_F12_OBJECT_COVER			= 0x0A,
218c2ecf20Sopenharmony_ci	RMI_F12_OBJECT_STYLUS_2			= 0x0B,
228c2ecf20Sopenharmony_ci	RMI_F12_OBJECT_ERASER			= 0x0C,
238c2ecf20Sopenharmony_ci	RMI_F12_OBJECT_SMALL_OBJECT		= 0x0D,
248c2ecf20Sopenharmony_ci};
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#define F12_DATA1_BYTES_PER_OBJ			8
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_cistruct f12_data {
298c2ecf20Sopenharmony_ci	struct rmi_2d_sensor sensor;
308c2ecf20Sopenharmony_ci	struct rmi_2d_sensor_platform_data sensor_pdata;
318c2ecf20Sopenharmony_ci	bool has_dribble;
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	u16 data_addr;
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	struct rmi_register_descriptor query_reg_desc;
368c2ecf20Sopenharmony_ci	struct rmi_register_descriptor control_reg_desc;
378c2ecf20Sopenharmony_ci	struct rmi_register_descriptor data_reg_desc;
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	/* F12 Data1 describes sensed objects */
408c2ecf20Sopenharmony_ci	const struct rmi_register_desc_item *data1;
418c2ecf20Sopenharmony_ci	u16 data1_offset;
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	/* F12 Data5 describes finger ACM */
448c2ecf20Sopenharmony_ci	const struct rmi_register_desc_item *data5;
458c2ecf20Sopenharmony_ci	u16 data5_offset;
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	/* F12 Data5 describes Pen */
488c2ecf20Sopenharmony_ci	const struct rmi_register_desc_item *data6;
498c2ecf20Sopenharmony_ci	u16 data6_offset;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	/* F12 Data9 reports relative data */
538c2ecf20Sopenharmony_ci	const struct rmi_register_desc_item *data9;
548c2ecf20Sopenharmony_ci	u16 data9_offset;
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	const struct rmi_register_desc_item *data15;
578c2ecf20Sopenharmony_ci	u16 data15_offset;
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	unsigned long *abs_mask;
608c2ecf20Sopenharmony_ci	unsigned long *rel_mask;
618c2ecf20Sopenharmony_ci};
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cistatic int rmi_f12_read_sensor_tuning(struct f12_data *f12)
648c2ecf20Sopenharmony_ci{
658c2ecf20Sopenharmony_ci	const struct rmi_register_desc_item *item;
668c2ecf20Sopenharmony_ci	struct rmi_2d_sensor *sensor = &f12->sensor;
678c2ecf20Sopenharmony_ci	struct rmi_function *fn = sensor->fn;
688c2ecf20Sopenharmony_ci	struct rmi_device *rmi_dev = fn->rmi_dev;
698c2ecf20Sopenharmony_ci	int ret;
708c2ecf20Sopenharmony_ci	int offset;
718c2ecf20Sopenharmony_ci	u8 buf[15];
728c2ecf20Sopenharmony_ci	int pitch_x = 0;
738c2ecf20Sopenharmony_ci	int pitch_y = 0;
748c2ecf20Sopenharmony_ci	int rx_receivers = 0;
758c2ecf20Sopenharmony_ci	int tx_receivers = 0;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->control_reg_desc, 8);
788c2ecf20Sopenharmony_ci	if (!item) {
798c2ecf20Sopenharmony_ci		dev_err(&fn->dev,
808c2ecf20Sopenharmony_ci			"F12 does not have the sensor tuning control register\n");
818c2ecf20Sopenharmony_ci		return -ENODEV;
828c2ecf20Sopenharmony_ci	}
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	offset = rmi_register_desc_calc_reg_offset(&f12->control_reg_desc, 8);
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	if (item->reg_size > sizeof(buf)) {
878c2ecf20Sopenharmony_ci		dev_err(&fn->dev,
888c2ecf20Sopenharmony_ci			"F12 control8 should be no bigger than %zd bytes, not: %ld\n",
898c2ecf20Sopenharmony_ci			sizeof(buf), item->reg_size);
908c2ecf20Sopenharmony_ci		return -ENODEV;
918c2ecf20Sopenharmony_ci	}
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	ret = rmi_read_block(rmi_dev, fn->fd.control_base_addr + offset, buf,
948c2ecf20Sopenharmony_ci				item->reg_size);
958c2ecf20Sopenharmony_ci	if (ret)
968c2ecf20Sopenharmony_ci		return ret;
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	offset = 0;
998c2ecf20Sopenharmony_ci	if (rmi_register_desc_has_subpacket(item, 0)) {
1008c2ecf20Sopenharmony_ci		sensor->max_x = (buf[offset + 1] << 8) | buf[offset];
1018c2ecf20Sopenharmony_ci		sensor->max_y = (buf[offset + 3] << 8) | buf[offset + 2];
1028c2ecf20Sopenharmony_ci		offset += 4;
1038c2ecf20Sopenharmony_ci	}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: max_x: %d max_y: %d\n", __func__,
1068c2ecf20Sopenharmony_ci		sensor->max_x, sensor->max_y);
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	if (rmi_register_desc_has_subpacket(item, 1)) {
1098c2ecf20Sopenharmony_ci		pitch_x = (buf[offset + 1] << 8) | buf[offset];
1108c2ecf20Sopenharmony_ci		pitch_y	= (buf[offset + 3] << 8) | buf[offset + 2];
1118c2ecf20Sopenharmony_ci		offset += 4;
1128c2ecf20Sopenharmony_ci	}
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	if (rmi_register_desc_has_subpacket(item, 2)) {
1158c2ecf20Sopenharmony_ci		/* Units 1/128 sensor pitch */
1168c2ecf20Sopenharmony_ci		rmi_dbg(RMI_DEBUG_FN, &fn->dev,
1178c2ecf20Sopenharmony_ci			"%s: Inactive Border xlo:%d xhi:%d ylo:%d yhi:%d\n",
1188c2ecf20Sopenharmony_ci			__func__,
1198c2ecf20Sopenharmony_ci			buf[offset], buf[offset + 1],
1208c2ecf20Sopenharmony_ci			buf[offset + 2], buf[offset + 3]);
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci		offset += 4;
1238c2ecf20Sopenharmony_ci	}
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	if (rmi_register_desc_has_subpacket(item, 3)) {
1268c2ecf20Sopenharmony_ci		rx_receivers = buf[offset];
1278c2ecf20Sopenharmony_ci		tx_receivers = buf[offset + 1];
1288c2ecf20Sopenharmony_ci		offset += 2;
1298c2ecf20Sopenharmony_ci	}
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	/* Skip over sensor flags */
1328c2ecf20Sopenharmony_ci	if (rmi_register_desc_has_subpacket(item, 4))
1338c2ecf20Sopenharmony_ci		offset += 1;
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	sensor->x_mm = (pitch_x * rx_receivers) >> 12;
1368c2ecf20Sopenharmony_ci	sensor->y_mm = (pitch_y * tx_receivers) >> 12;
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: x_mm: %d y_mm: %d\n", __func__,
1398c2ecf20Sopenharmony_ci		sensor->x_mm, sensor->y_mm);
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	return 0;
1428c2ecf20Sopenharmony_ci}
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_cistatic void rmi_f12_process_objects(struct f12_data *f12, u8 *data1, int size)
1458c2ecf20Sopenharmony_ci{
1468c2ecf20Sopenharmony_ci	int i;
1478c2ecf20Sopenharmony_ci	struct rmi_2d_sensor *sensor = &f12->sensor;
1488c2ecf20Sopenharmony_ci	int objects = f12->data1->num_subpackets;
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	if ((f12->data1->num_subpackets * F12_DATA1_BYTES_PER_OBJ) > size)
1518c2ecf20Sopenharmony_ci		objects = size / F12_DATA1_BYTES_PER_OBJ;
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci	for (i = 0; i < objects; i++) {
1548c2ecf20Sopenharmony_ci		struct rmi_2d_sensor_abs_object *obj = &sensor->objs[i];
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci		obj->type = RMI_2D_OBJECT_NONE;
1578c2ecf20Sopenharmony_ci		obj->mt_tool = MT_TOOL_FINGER;
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci		switch (data1[0]) {
1608c2ecf20Sopenharmony_ci		case RMI_F12_OBJECT_FINGER:
1618c2ecf20Sopenharmony_ci			obj->type = RMI_2D_OBJECT_FINGER;
1628c2ecf20Sopenharmony_ci			break;
1638c2ecf20Sopenharmony_ci		case RMI_F12_OBJECT_STYLUS:
1648c2ecf20Sopenharmony_ci			obj->type = RMI_2D_OBJECT_STYLUS;
1658c2ecf20Sopenharmony_ci			obj->mt_tool = MT_TOOL_PEN;
1668c2ecf20Sopenharmony_ci			break;
1678c2ecf20Sopenharmony_ci		case RMI_F12_OBJECT_PALM:
1688c2ecf20Sopenharmony_ci			obj->type = RMI_2D_OBJECT_PALM;
1698c2ecf20Sopenharmony_ci			obj->mt_tool = MT_TOOL_PALM;
1708c2ecf20Sopenharmony_ci			break;
1718c2ecf20Sopenharmony_ci		case RMI_F12_OBJECT_UNCLASSIFIED:
1728c2ecf20Sopenharmony_ci			obj->type = RMI_2D_OBJECT_UNCLASSIFIED;
1738c2ecf20Sopenharmony_ci			break;
1748c2ecf20Sopenharmony_ci		}
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci		obj->x = (data1[2] << 8) | data1[1];
1778c2ecf20Sopenharmony_ci		obj->y = (data1[4] << 8) | data1[3];
1788c2ecf20Sopenharmony_ci		obj->z = data1[5];
1798c2ecf20Sopenharmony_ci		obj->wx = data1[6];
1808c2ecf20Sopenharmony_ci		obj->wy = data1[7];
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci		rmi_2d_sensor_abs_process(sensor, obj, i);
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci		data1 += F12_DATA1_BYTES_PER_OBJ;
1858c2ecf20Sopenharmony_ci	}
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	if (sensor->kernel_tracking)
1888c2ecf20Sopenharmony_ci		input_mt_assign_slots(sensor->input,
1898c2ecf20Sopenharmony_ci				      sensor->tracking_slots,
1908c2ecf20Sopenharmony_ci				      sensor->tracking_pos,
1918c2ecf20Sopenharmony_ci				      sensor->nbr_fingers,
1928c2ecf20Sopenharmony_ci				      sensor->dmax);
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci	for (i = 0; i < objects; i++)
1958c2ecf20Sopenharmony_ci		rmi_2d_sensor_abs_report(sensor, &sensor->objs[i], i);
1968c2ecf20Sopenharmony_ci}
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_cistatic irqreturn_t rmi_f12_attention(int irq, void *ctx)
1998c2ecf20Sopenharmony_ci{
2008c2ecf20Sopenharmony_ci	int retval;
2018c2ecf20Sopenharmony_ci	struct rmi_function *fn = ctx;
2028c2ecf20Sopenharmony_ci	struct rmi_device *rmi_dev = fn->rmi_dev;
2038c2ecf20Sopenharmony_ci	struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
2048c2ecf20Sopenharmony_ci	struct f12_data *f12 = dev_get_drvdata(&fn->dev);
2058c2ecf20Sopenharmony_ci	struct rmi_2d_sensor *sensor = &f12->sensor;
2068c2ecf20Sopenharmony_ci	int valid_bytes = sensor->pkt_size;
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	if (drvdata->attn_data.data) {
2098c2ecf20Sopenharmony_ci		if (sensor->attn_size > drvdata->attn_data.size)
2108c2ecf20Sopenharmony_ci			valid_bytes = drvdata->attn_data.size;
2118c2ecf20Sopenharmony_ci		else
2128c2ecf20Sopenharmony_ci			valid_bytes = sensor->attn_size;
2138c2ecf20Sopenharmony_ci		memcpy(sensor->data_pkt, drvdata->attn_data.data,
2148c2ecf20Sopenharmony_ci			valid_bytes);
2158c2ecf20Sopenharmony_ci		drvdata->attn_data.data += valid_bytes;
2168c2ecf20Sopenharmony_ci		drvdata->attn_data.size -= valid_bytes;
2178c2ecf20Sopenharmony_ci	} else {
2188c2ecf20Sopenharmony_ci		retval = rmi_read_block(rmi_dev, f12->data_addr,
2198c2ecf20Sopenharmony_ci					sensor->data_pkt, sensor->pkt_size);
2208c2ecf20Sopenharmony_ci		if (retval < 0) {
2218c2ecf20Sopenharmony_ci			dev_err(&fn->dev, "Failed to read object data. Code: %d.\n",
2228c2ecf20Sopenharmony_ci				retval);
2238c2ecf20Sopenharmony_ci			return IRQ_RETVAL(retval);
2248c2ecf20Sopenharmony_ci		}
2258c2ecf20Sopenharmony_ci	}
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	if (f12->data1)
2288c2ecf20Sopenharmony_ci		rmi_f12_process_objects(f12,
2298c2ecf20Sopenharmony_ci			&sensor->data_pkt[f12->data1_offset], valid_bytes);
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	input_mt_sync_frame(sensor->input);
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
2348c2ecf20Sopenharmony_ci}
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_cistatic int rmi_f12_write_control_regs(struct rmi_function *fn)
2378c2ecf20Sopenharmony_ci{
2388c2ecf20Sopenharmony_ci	int ret;
2398c2ecf20Sopenharmony_ci	const struct rmi_register_desc_item *item;
2408c2ecf20Sopenharmony_ci	struct rmi_device *rmi_dev = fn->rmi_dev;
2418c2ecf20Sopenharmony_ci	struct f12_data *f12 = dev_get_drvdata(&fn->dev);
2428c2ecf20Sopenharmony_ci	int control_size;
2438c2ecf20Sopenharmony_ci	char buf[3];
2448c2ecf20Sopenharmony_ci	u16 control_offset = 0;
2458c2ecf20Sopenharmony_ci	u8 subpacket_offset = 0;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	if (f12->has_dribble
2488c2ecf20Sopenharmony_ci	    && (f12->sensor.dribble != RMI_REG_STATE_DEFAULT)) {
2498c2ecf20Sopenharmony_ci		item = rmi_get_register_desc_item(&f12->control_reg_desc, 20);
2508c2ecf20Sopenharmony_ci		if (item) {
2518c2ecf20Sopenharmony_ci			control_offset = rmi_register_desc_calc_reg_offset(
2528c2ecf20Sopenharmony_ci						&f12->control_reg_desc, 20);
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci			/*
2558c2ecf20Sopenharmony_ci			 * The byte containing the EnableDribble bit will be
2568c2ecf20Sopenharmony_ci			 * in either byte 0 or byte 2 of control 20. Depending
2578c2ecf20Sopenharmony_ci			 * on the existence of subpacket 0. If control 20 is
2588c2ecf20Sopenharmony_ci			 * larger then 3 bytes, just read the first 3.
2598c2ecf20Sopenharmony_ci			 */
2608c2ecf20Sopenharmony_ci			control_size = min(item->reg_size, 3UL);
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci			ret = rmi_read_block(rmi_dev, fn->fd.control_base_addr
2638c2ecf20Sopenharmony_ci					+ control_offset, buf, control_size);
2648c2ecf20Sopenharmony_ci			if (ret)
2658c2ecf20Sopenharmony_ci				return ret;
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci			if (rmi_register_desc_has_subpacket(item, 0))
2688c2ecf20Sopenharmony_ci				subpacket_offset += 1;
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci			switch (f12->sensor.dribble) {
2718c2ecf20Sopenharmony_ci			case RMI_REG_STATE_OFF:
2728c2ecf20Sopenharmony_ci				buf[subpacket_offset] &= ~BIT(2);
2738c2ecf20Sopenharmony_ci				break;
2748c2ecf20Sopenharmony_ci			case RMI_REG_STATE_ON:
2758c2ecf20Sopenharmony_ci				buf[subpacket_offset] |= BIT(2);
2768c2ecf20Sopenharmony_ci				break;
2778c2ecf20Sopenharmony_ci			case RMI_REG_STATE_DEFAULT:
2788c2ecf20Sopenharmony_ci			default:
2798c2ecf20Sopenharmony_ci				break;
2808c2ecf20Sopenharmony_ci			}
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci			ret = rmi_write_block(rmi_dev,
2838c2ecf20Sopenharmony_ci				fn->fd.control_base_addr + control_offset,
2848c2ecf20Sopenharmony_ci				buf, control_size);
2858c2ecf20Sopenharmony_ci			if (ret)
2868c2ecf20Sopenharmony_ci				return ret;
2878c2ecf20Sopenharmony_ci		}
2888c2ecf20Sopenharmony_ci	}
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	return 0;
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci}
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_cistatic int rmi_f12_config(struct rmi_function *fn)
2958c2ecf20Sopenharmony_ci{
2968c2ecf20Sopenharmony_ci	struct rmi_driver *drv = fn->rmi_dev->driver;
2978c2ecf20Sopenharmony_ci	struct f12_data *f12 = dev_get_drvdata(&fn->dev);
2988c2ecf20Sopenharmony_ci	struct rmi_2d_sensor *sensor;
2998c2ecf20Sopenharmony_ci	int ret;
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci	sensor = &f12->sensor;
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	if (!sensor->report_abs)
3048c2ecf20Sopenharmony_ci		drv->clear_irq_bits(fn->rmi_dev, f12->abs_mask);
3058c2ecf20Sopenharmony_ci	else
3068c2ecf20Sopenharmony_ci		drv->set_irq_bits(fn->rmi_dev, f12->abs_mask);
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	drv->clear_irq_bits(fn->rmi_dev, f12->rel_mask);
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	ret = rmi_f12_write_control_regs(fn);
3118c2ecf20Sopenharmony_ci	if (ret)
3128c2ecf20Sopenharmony_ci		dev_warn(&fn->dev,
3138c2ecf20Sopenharmony_ci			"Failed to write F12 control registers: %d\n", ret);
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	return 0;
3168c2ecf20Sopenharmony_ci}
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_cistatic int rmi_f12_probe(struct rmi_function *fn)
3198c2ecf20Sopenharmony_ci{
3208c2ecf20Sopenharmony_ci	struct f12_data *f12;
3218c2ecf20Sopenharmony_ci	int ret;
3228c2ecf20Sopenharmony_ci	struct rmi_device *rmi_dev = fn->rmi_dev;
3238c2ecf20Sopenharmony_ci	char buf;
3248c2ecf20Sopenharmony_ci	u16 query_addr = fn->fd.query_base_addr;
3258c2ecf20Sopenharmony_ci	const struct rmi_register_desc_item *item;
3268c2ecf20Sopenharmony_ci	struct rmi_2d_sensor *sensor;
3278c2ecf20Sopenharmony_ci	struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
3288c2ecf20Sopenharmony_ci	struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
3298c2ecf20Sopenharmony_ci	u16 data_offset = 0;
3308c2ecf20Sopenharmony_ci	int mask_size;
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s\n", __func__);
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	mask_size = BITS_TO_LONGS(drvdata->irq_count) * sizeof(unsigned long);
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	ret = rmi_read(fn->rmi_dev, query_addr, &buf);
3378c2ecf20Sopenharmony_ci	if (ret < 0) {
3388c2ecf20Sopenharmony_ci		dev_err(&fn->dev, "Failed to read general info register: %d\n",
3398c2ecf20Sopenharmony_ci			ret);
3408c2ecf20Sopenharmony_ci		return -ENODEV;
3418c2ecf20Sopenharmony_ci	}
3428c2ecf20Sopenharmony_ci	++query_addr;
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci	if (!(buf & BIT(0))) {
3458c2ecf20Sopenharmony_ci		dev_err(&fn->dev,
3468c2ecf20Sopenharmony_ci			"Behavior of F12 without register descriptors is undefined.\n");
3478c2ecf20Sopenharmony_ci		return -ENODEV;
3488c2ecf20Sopenharmony_ci	}
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	f12 = devm_kzalloc(&fn->dev, sizeof(struct f12_data) + mask_size * 2,
3518c2ecf20Sopenharmony_ci			GFP_KERNEL);
3528c2ecf20Sopenharmony_ci	if (!f12)
3538c2ecf20Sopenharmony_ci		return -ENOMEM;
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci	f12->abs_mask = (unsigned long *)((char *)f12
3568c2ecf20Sopenharmony_ci			+ sizeof(struct f12_data));
3578c2ecf20Sopenharmony_ci	f12->rel_mask = (unsigned long *)((char *)f12
3588c2ecf20Sopenharmony_ci			+ sizeof(struct f12_data) + mask_size);
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	set_bit(fn->irq_pos, f12->abs_mask);
3618c2ecf20Sopenharmony_ci	set_bit(fn->irq_pos + 1, f12->rel_mask);
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci	f12->has_dribble = !!(buf & BIT(3));
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	if (fn->dev.of_node) {
3668c2ecf20Sopenharmony_ci		ret = rmi_2d_sensor_of_probe(&fn->dev, &f12->sensor_pdata);
3678c2ecf20Sopenharmony_ci		if (ret)
3688c2ecf20Sopenharmony_ci			return ret;
3698c2ecf20Sopenharmony_ci	} else {
3708c2ecf20Sopenharmony_ci		f12->sensor_pdata = pdata->sensor_pdata;
3718c2ecf20Sopenharmony_ci	}
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci	ret = rmi_read_register_desc(rmi_dev, query_addr,
3748c2ecf20Sopenharmony_ci					&f12->query_reg_desc);
3758c2ecf20Sopenharmony_ci	if (ret) {
3768c2ecf20Sopenharmony_ci		dev_err(&fn->dev,
3778c2ecf20Sopenharmony_ci			"Failed to read the Query Register Descriptor: %d\n",
3788c2ecf20Sopenharmony_ci			ret);
3798c2ecf20Sopenharmony_ci		return ret;
3808c2ecf20Sopenharmony_ci	}
3818c2ecf20Sopenharmony_ci	query_addr += 3;
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	ret = rmi_read_register_desc(rmi_dev, query_addr,
3848c2ecf20Sopenharmony_ci						&f12->control_reg_desc);
3858c2ecf20Sopenharmony_ci	if (ret) {
3868c2ecf20Sopenharmony_ci		dev_err(&fn->dev,
3878c2ecf20Sopenharmony_ci			"Failed to read the Control Register Descriptor: %d\n",
3888c2ecf20Sopenharmony_ci			ret);
3898c2ecf20Sopenharmony_ci		return ret;
3908c2ecf20Sopenharmony_ci	}
3918c2ecf20Sopenharmony_ci	query_addr += 3;
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	ret = rmi_read_register_desc(rmi_dev, query_addr,
3948c2ecf20Sopenharmony_ci						&f12->data_reg_desc);
3958c2ecf20Sopenharmony_ci	if (ret) {
3968c2ecf20Sopenharmony_ci		dev_err(&fn->dev,
3978c2ecf20Sopenharmony_ci			"Failed to read the Data Register Descriptor: %d\n",
3988c2ecf20Sopenharmony_ci			ret);
3998c2ecf20Sopenharmony_ci		return ret;
4008c2ecf20Sopenharmony_ci	}
4018c2ecf20Sopenharmony_ci	query_addr += 3;
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci	sensor = &f12->sensor;
4048c2ecf20Sopenharmony_ci	sensor->fn = fn;
4058c2ecf20Sopenharmony_ci	f12->data_addr = fn->fd.data_base_addr;
4068c2ecf20Sopenharmony_ci	sensor->pkt_size = rmi_register_desc_calc_size(&f12->data_reg_desc);
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci	sensor->axis_align =
4098c2ecf20Sopenharmony_ci		f12->sensor_pdata.axis_align;
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	sensor->x_mm = f12->sensor_pdata.x_mm;
4128c2ecf20Sopenharmony_ci	sensor->y_mm = f12->sensor_pdata.y_mm;
4138c2ecf20Sopenharmony_ci	sensor->dribble = f12->sensor_pdata.dribble;
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	if (sensor->sensor_type == rmi_sensor_default)
4168c2ecf20Sopenharmony_ci		sensor->sensor_type =
4178c2ecf20Sopenharmony_ci			f12->sensor_pdata.sensor_type;
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: data packet size: %d\n", __func__,
4208c2ecf20Sopenharmony_ci		sensor->pkt_size);
4218c2ecf20Sopenharmony_ci	sensor->data_pkt = devm_kzalloc(&fn->dev, sensor->pkt_size, GFP_KERNEL);
4228c2ecf20Sopenharmony_ci	if (!sensor->data_pkt)
4238c2ecf20Sopenharmony_ci		return -ENOMEM;
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	dev_set_drvdata(&fn->dev, f12);
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci	ret = rmi_f12_read_sensor_tuning(f12);
4288c2ecf20Sopenharmony_ci	if (ret)
4298c2ecf20Sopenharmony_ci		return ret;
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	/*
4328c2ecf20Sopenharmony_ci	 * Figure out what data is contained in the data registers. HID devices
4338c2ecf20Sopenharmony_ci	 * may have registers defined, but their data is not reported in the
4348c2ecf20Sopenharmony_ci	 * HID attention report. Registers which are not reported in the HID
4358c2ecf20Sopenharmony_ci	 * attention report check to see if the device is receiving data from
4368c2ecf20Sopenharmony_ci	 * HID attention reports.
4378c2ecf20Sopenharmony_ci	 */
4388c2ecf20Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 0);
4398c2ecf20Sopenharmony_ci	if (item && !drvdata->attn_data.data)
4408c2ecf20Sopenharmony_ci		data_offset += item->reg_size;
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 1);
4438c2ecf20Sopenharmony_ci	if (item) {
4448c2ecf20Sopenharmony_ci		f12->data1 = item;
4458c2ecf20Sopenharmony_ci		f12->data1_offset = data_offset;
4468c2ecf20Sopenharmony_ci		data_offset += item->reg_size;
4478c2ecf20Sopenharmony_ci		sensor->nbr_fingers = item->num_subpackets;
4488c2ecf20Sopenharmony_ci		sensor->report_abs = 1;
4498c2ecf20Sopenharmony_ci		sensor->attn_size += item->reg_size;
4508c2ecf20Sopenharmony_ci	}
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 2);
4538c2ecf20Sopenharmony_ci	if (item && !drvdata->attn_data.data)
4548c2ecf20Sopenharmony_ci		data_offset += item->reg_size;
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 3);
4578c2ecf20Sopenharmony_ci	if (item && !drvdata->attn_data.data)
4588c2ecf20Sopenharmony_ci		data_offset += item->reg_size;
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 4);
4618c2ecf20Sopenharmony_ci	if (item && !drvdata->attn_data.data)
4628c2ecf20Sopenharmony_ci		data_offset += item->reg_size;
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 5);
4658c2ecf20Sopenharmony_ci	if (item) {
4668c2ecf20Sopenharmony_ci		f12->data5 = item;
4678c2ecf20Sopenharmony_ci		f12->data5_offset = data_offset;
4688c2ecf20Sopenharmony_ci		data_offset += item->reg_size;
4698c2ecf20Sopenharmony_ci		sensor->attn_size += item->reg_size;
4708c2ecf20Sopenharmony_ci	}
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 6);
4738c2ecf20Sopenharmony_ci	if (item && !drvdata->attn_data.data) {
4748c2ecf20Sopenharmony_ci		f12->data6 = item;
4758c2ecf20Sopenharmony_ci		f12->data6_offset = data_offset;
4768c2ecf20Sopenharmony_ci		data_offset += item->reg_size;
4778c2ecf20Sopenharmony_ci	}
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 7);
4808c2ecf20Sopenharmony_ci	if (item && !drvdata->attn_data.data)
4818c2ecf20Sopenharmony_ci		data_offset += item->reg_size;
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 8);
4848c2ecf20Sopenharmony_ci	if (item && !drvdata->attn_data.data)
4858c2ecf20Sopenharmony_ci		data_offset += item->reg_size;
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 9);
4888c2ecf20Sopenharmony_ci	if (item && !drvdata->attn_data.data) {
4898c2ecf20Sopenharmony_ci		f12->data9 = item;
4908c2ecf20Sopenharmony_ci		f12->data9_offset = data_offset;
4918c2ecf20Sopenharmony_ci		data_offset += item->reg_size;
4928c2ecf20Sopenharmony_ci		if (!sensor->report_abs)
4938c2ecf20Sopenharmony_ci			sensor->report_rel = 1;
4948c2ecf20Sopenharmony_ci	}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 10);
4978c2ecf20Sopenharmony_ci	if (item && !drvdata->attn_data.data)
4988c2ecf20Sopenharmony_ci		data_offset += item->reg_size;
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 11);
5018c2ecf20Sopenharmony_ci	if (item && !drvdata->attn_data.data)
5028c2ecf20Sopenharmony_ci		data_offset += item->reg_size;
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 12);
5058c2ecf20Sopenharmony_ci	if (item && !drvdata->attn_data.data)
5068c2ecf20Sopenharmony_ci		data_offset += item->reg_size;
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 13);
5098c2ecf20Sopenharmony_ci	if (item && !drvdata->attn_data.data)
5108c2ecf20Sopenharmony_ci		data_offset += item->reg_size;
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 14);
5138c2ecf20Sopenharmony_ci	if (item && !drvdata->attn_data.data)
5148c2ecf20Sopenharmony_ci		data_offset += item->reg_size;
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 15);
5178c2ecf20Sopenharmony_ci	if (item && !drvdata->attn_data.data) {
5188c2ecf20Sopenharmony_ci		f12->data15 = item;
5198c2ecf20Sopenharmony_ci		f12->data15_offset = data_offset;
5208c2ecf20Sopenharmony_ci		data_offset += item->reg_size;
5218c2ecf20Sopenharmony_ci	}
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ci	/* allocate the in-kernel tracking buffers */
5248c2ecf20Sopenharmony_ci	sensor->tracking_pos = devm_kcalloc(&fn->dev,
5258c2ecf20Sopenharmony_ci			sensor->nbr_fingers, sizeof(struct input_mt_pos),
5268c2ecf20Sopenharmony_ci			GFP_KERNEL);
5278c2ecf20Sopenharmony_ci	sensor->tracking_slots = devm_kcalloc(&fn->dev,
5288c2ecf20Sopenharmony_ci			sensor->nbr_fingers, sizeof(int), GFP_KERNEL);
5298c2ecf20Sopenharmony_ci	sensor->objs = devm_kcalloc(&fn->dev,
5308c2ecf20Sopenharmony_ci			sensor->nbr_fingers,
5318c2ecf20Sopenharmony_ci			sizeof(struct rmi_2d_sensor_abs_object),
5328c2ecf20Sopenharmony_ci			GFP_KERNEL);
5338c2ecf20Sopenharmony_ci	if (!sensor->tracking_pos || !sensor->tracking_slots || !sensor->objs)
5348c2ecf20Sopenharmony_ci		return -ENOMEM;
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	ret = rmi_2d_sensor_configure_input(fn, sensor);
5378c2ecf20Sopenharmony_ci	if (ret)
5388c2ecf20Sopenharmony_ci		return ret;
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	return 0;
5418c2ecf20Sopenharmony_ci}
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_cistruct rmi_function_handler rmi_f12_handler = {
5448c2ecf20Sopenharmony_ci	.driver = {
5458c2ecf20Sopenharmony_ci		.name = "rmi4_f12",
5468c2ecf20Sopenharmony_ci	},
5478c2ecf20Sopenharmony_ci	.func = 0x12,
5488c2ecf20Sopenharmony_ci	.probe = rmi_f12_probe,
5498c2ecf20Sopenharmony_ci	.config = rmi_f12_config,
5508c2ecf20Sopenharmony_ci	.attention = rmi_f12_attention,
5518c2ecf20Sopenharmony_ci};
552