162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2012-2016 Synaptics Incorporated
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci#include <linux/input.h>
662306a36Sopenharmony_ci#include <linux/input/mt.h>
762306a36Sopenharmony_ci#include <linux/rmi.h>
862306a36Sopenharmony_ci#include "rmi_driver.h"
962306a36Sopenharmony_ci#include "rmi_2d_sensor.h"
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_cienum rmi_f12_object_type {
1262306a36Sopenharmony_ci	RMI_F12_OBJECT_NONE			= 0x00,
1362306a36Sopenharmony_ci	RMI_F12_OBJECT_FINGER			= 0x01,
1462306a36Sopenharmony_ci	RMI_F12_OBJECT_STYLUS			= 0x02,
1562306a36Sopenharmony_ci	RMI_F12_OBJECT_PALM			= 0x03,
1662306a36Sopenharmony_ci	RMI_F12_OBJECT_UNCLASSIFIED		= 0x04,
1762306a36Sopenharmony_ci	RMI_F12_OBJECT_GLOVED_FINGER		= 0x06,
1862306a36Sopenharmony_ci	RMI_F12_OBJECT_NARROW_OBJECT		= 0x07,
1962306a36Sopenharmony_ci	RMI_F12_OBJECT_HAND_EDGE		= 0x08,
2062306a36Sopenharmony_ci	RMI_F12_OBJECT_COVER			= 0x0A,
2162306a36Sopenharmony_ci	RMI_F12_OBJECT_STYLUS_2			= 0x0B,
2262306a36Sopenharmony_ci	RMI_F12_OBJECT_ERASER			= 0x0C,
2362306a36Sopenharmony_ci	RMI_F12_OBJECT_SMALL_OBJECT		= 0x0D,
2462306a36Sopenharmony_ci};
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#define F12_DATA1_BYTES_PER_OBJ			8
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cistruct f12_data {
2962306a36Sopenharmony_ci	struct rmi_2d_sensor sensor;
3062306a36Sopenharmony_ci	struct rmi_2d_sensor_platform_data sensor_pdata;
3162306a36Sopenharmony_ci	bool has_dribble;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	u16 data_addr;
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	struct rmi_register_descriptor query_reg_desc;
3662306a36Sopenharmony_ci	struct rmi_register_descriptor control_reg_desc;
3762306a36Sopenharmony_ci	struct rmi_register_descriptor data_reg_desc;
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	/* F12 Data1 describes sensed objects */
4062306a36Sopenharmony_ci	const struct rmi_register_desc_item *data1;
4162306a36Sopenharmony_ci	u16 data1_offset;
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	/* F12 Data5 describes finger ACM */
4462306a36Sopenharmony_ci	const struct rmi_register_desc_item *data5;
4562306a36Sopenharmony_ci	u16 data5_offset;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	/* F12 Data5 describes Pen */
4862306a36Sopenharmony_ci	const struct rmi_register_desc_item *data6;
4962306a36Sopenharmony_ci	u16 data6_offset;
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	/* F12 Data9 reports relative data */
5362306a36Sopenharmony_ci	const struct rmi_register_desc_item *data9;
5462306a36Sopenharmony_ci	u16 data9_offset;
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	const struct rmi_register_desc_item *data15;
5762306a36Sopenharmony_ci	u16 data15_offset;
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	unsigned long *abs_mask;
6062306a36Sopenharmony_ci	unsigned long *rel_mask;
6162306a36Sopenharmony_ci};
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistatic int rmi_f12_read_sensor_tuning(struct f12_data *f12)
6462306a36Sopenharmony_ci{
6562306a36Sopenharmony_ci	const struct rmi_register_desc_item *item;
6662306a36Sopenharmony_ci	struct rmi_2d_sensor *sensor = &f12->sensor;
6762306a36Sopenharmony_ci	struct rmi_function *fn = sensor->fn;
6862306a36Sopenharmony_ci	struct rmi_device *rmi_dev = fn->rmi_dev;
6962306a36Sopenharmony_ci	int ret;
7062306a36Sopenharmony_ci	int offset;
7162306a36Sopenharmony_ci	u8 buf[15];
7262306a36Sopenharmony_ci	int pitch_x = 0;
7362306a36Sopenharmony_ci	int pitch_y = 0;
7462306a36Sopenharmony_ci	int rx_receivers = 0;
7562306a36Sopenharmony_ci	int tx_receivers = 0;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->control_reg_desc, 8);
7862306a36Sopenharmony_ci	if (!item) {
7962306a36Sopenharmony_ci		dev_err(&fn->dev,
8062306a36Sopenharmony_ci			"F12 does not have the sensor tuning control register\n");
8162306a36Sopenharmony_ci		return -ENODEV;
8262306a36Sopenharmony_ci	}
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	offset = rmi_register_desc_calc_reg_offset(&f12->control_reg_desc, 8);
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	if (item->reg_size > sizeof(buf)) {
8762306a36Sopenharmony_ci		dev_err(&fn->dev,
8862306a36Sopenharmony_ci			"F12 control8 should be no bigger than %zd bytes, not: %ld\n",
8962306a36Sopenharmony_ci			sizeof(buf), item->reg_size);
9062306a36Sopenharmony_ci		return -ENODEV;
9162306a36Sopenharmony_ci	}
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	ret = rmi_read_block(rmi_dev, fn->fd.control_base_addr + offset, buf,
9462306a36Sopenharmony_ci				item->reg_size);
9562306a36Sopenharmony_ci	if (ret)
9662306a36Sopenharmony_ci		return ret;
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	offset = 0;
9962306a36Sopenharmony_ci	if (rmi_register_desc_has_subpacket(item, 0)) {
10062306a36Sopenharmony_ci		sensor->max_x = (buf[offset + 1] << 8) | buf[offset];
10162306a36Sopenharmony_ci		sensor->max_y = (buf[offset + 3] << 8) | buf[offset + 2];
10262306a36Sopenharmony_ci		offset += 4;
10362306a36Sopenharmony_ci	}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: max_x: %d max_y: %d\n", __func__,
10662306a36Sopenharmony_ci		sensor->max_x, sensor->max_y);
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	if (rmi_register_desc_has_subpacket(item, 1)) {
10962306a36Sopenharmony_ci		pitch_x = (buf[offset + 1] << 8) | buf[offset];
11062306a36Sopenharmony_ci		pitch_y	= (buf[offset + 3] << 8) | buf[offset + 2];
11162306a36Sopenharmony_ci		offset += 4;
11262306a36Sopenharmony_ci	}
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	if (rmi_register_desc_has_subpacket(item, 2)) {
11562306a36Sopenharmony_ci		/* Units 1/128 sensor pitch */
11662306a36Sopenharmony_ci		rmi_dbg(RMI_DEBUG_FN, &fn->dev,
11762306a36Sopenharmony_ci			"%s: Inactive Border xlo:%d xhi:%d ylo:%d yhi:%d\n",
11862306a36Sopenharmony_ci			__func__,
11962306a36Sopenharmony_ci			buf[offset], buf[offset + 1],
12062306a36Sopenharmony_ci			buf[offset + 2], buf[offset + 3]);
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci		offset += 4;
12362306a36Sopenharmony_ci	}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	if (rmi_register_desc_has_subpacket(item, 3)) {
12662306a36Sopenharmony_ci		rx_receivers = buf[offset];
12762306a36Sopenharmony_ci		tx_receivers = buf[offset + 1];
12862306a36Sopenharmony_ci		offset += 2;
12962306a36Sopenharmony_ci	}
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	/* Skip over sensor flags */
13262306a36Sopenharmony_ci	if (rmi_register_desc_has_subpacket(item, 4))
13362306a36Sopenharmony_ci		offset += 1;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	sensor->x_mm = (pitch_x * rx_receivers) >> 12;
13662306a36Sopenharmony_ci	sensor->y_mm = (pitch_y * tx_receivers) >> 12;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: x_mm: %d y_mm: %d\n", __func__,
13962306a36Sopenharmony_ci		sensor->x_mm, sensor->y_mm);
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	return 0;
14262306a36Sopenharmony_ci}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_cistatic void rmi_f12_process_objects(struct f12_data *f12, u8 *data1, int size)
14562306a36Sopenharmony_ci{
14662306a36Sopenharmony_ci	int i;
14762306a36Sopenharmony_ci	struct rmi_2d_sensor *sensor = &f12->sensor;
14862306a36Sopenharmony_ci	int objects = f12->data1->num_subpackets;
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	if ((f12->data1->num_subpackets * F12_DATA1_BYTES_PER_OBJ) > size)
15162306a36Sopenharmony_ci		objects = size / F12_DATA1_BYTES_PER_OBJ;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	for (i = 0; i < objects; i++) {
15462306a36Sopenharmony_ci		struct rmi_2d_sensor_abs_object *obj = &sensor->objs[i];
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci		obj->type = RMI_2D_OBJECT_NONE;
15762306a36Sopenharmony_ci		obj->mt_tool = MT_TOOL_FINGER;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci		switch (data1[0]) {
16062306a36Sopenharmony_ci		case RMI_F12_OBJECT_FINGER:
16162306a36Sopenharmony_ci			obj->type = RMI_2D_OBJECT_FINGER;
16262306a36Sopenharmony_ci			break;
16362306a36Sopenharmony_ci		case RMI_F12_OBJECT_STYLUS:
16462306a36Sopenharmony_ci			obj->type = RMI_2D_OBJECT_STYLUS;
16562306a36Sopenharmony_ci			obj->mt_tool = MT_TOOL_PEN;
16662306a36Sopenharmony_ci			break;
16762306a36Sopenharmony_ci		case RMI_F12_OBJECT_PALM:
16862306a36Sopenharmony_ci			obj->type = RMI_2D_OBJECT_PALM;
16962306a36Sopenharmony_ci			obj->mt_tool = MT_TOOL_PALM;
17062306a36Sopenharmony_ci			break;
17162306a36Sopenharmony_ci		case RMI_F12_OBJECT_UNCLASSIFIED:
17262306a36Sopenharmony_ci			obj->type = RMI_2D_OBJECT_UNCLASSIFIED;
17362306a36Sopenharmony_ci			break;
17462306a36Sopenharmony_ci		}
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci		obj->x = (data1[2] << 8) | data1[1];
17762306a36Sopenharmony_ci		obj->y = (data1[4] << 8) | data1[3];
17862306a36Sopenharmony_ci		obj->z = data1[5];
17962306a36Sopenharmony_ci		obj->wx = data1[6];
18062306a36Sopenharmony_ci		obj->wy = data1[7];
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci		rmi_2d_sensor_abs_process(sensor, obj, i);
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci		data1 += F12_DATA1_BYTES_PER_OBJ;
18562306a36Sopenharmony_ci	}
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	if (sensor->kernel_tracking)
18862306a36Sopenharmony_ci		input_mt_assign_slots(sensor->input,
18962306a36Sopenharmony_ci				      sensor->tracking_slots,
19062306a36Sopenharmony_ci				      sensor->tracking_pos,
19162306a36Sopenharmony_ci				      sensor->nbr_fingers,
19262306a36Sopenharmony_ci				      sensor->dmax);
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	for (i = 0; i < objects; i++)
19562306a36Sopenharmony_ci		rmi_2d_sensor_abs_report(sensor, &sensor->objs[i], i);
19662306a36Sopenharmony_ci}
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_cistatic irqreturn_t rmi_f12_attention(int irq, void *ctx)
19962306a36Sopenharmony_ci{
20062306a36Sopenharmony_ci	int retval;
20162306a36Sopenharmony_ci	struct rmi_function *fn = ctx;
20262306a36Sopenharmony_ci	struct rmi_device *rmi_dev = fn->rmi_dev;
20362306a36Sopenharmony_ci	struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
20462306a36Sopenharmony_ci	struct f12_data *f12 = dev_get_drvdata(&fn->dev);
20562306a36Sopenharmony_ci	struct rmi_2d_sensor *sensor = &f12->sensor;
20662306a36Sopenharmony_ci	int valid_bytes = sensor->pkt_size;
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	if (drvdata->attn_data.data) {
20962306a36Sopenharmony_ci		if (sensor->attn_size > drvdata->attn_data.size)
21062306a36Sopenharmony_ci			valid_bytes = drvdata->attn_data.size;
21162306a36Sopenharmony_ci		else
21262306a36Sopenharmony_ci			valid_bytes = sensor->attn_size;
21362306a36Sopenharmony_ci		memcpy(sensor->data_pkt, drvdata->attn_data.data,
21462306a36Sopenharmony_ci			valid_bytes);
21562306a36Sopenharmony_ci		drvdata->attn_data.data += valid_bytes;
21662306a36Sopenharmony_ci		drvdata->attn_data.size -= valid_bytes;
21762306a36Sopenharmony_ci	} else {
21862306a36Sopenharmony_ci		retval = rmi_read_block(rmi_dev, f12->data_addr,
21962306a36Sopenharmony_ci					sensor->data_pkt, sensor->pkt_size);
22062306a36Sopenharmony_ci		if (retval < 0) {
22162306a36Sopenharmony_ci			dev_err(&fn->dev, "Failed to read object data. Code: %d.\n",
22262306a36Sopenharmony_ci				retval);
22362306a36Sopenharmony_ci			return IRQ_RETVAL(retval);
22462306a36Sopenharmony_ci		}
22562306a36Sopenharmony_ci	}
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	if (f12->data1)
22862306a36Sopenharmony_ci		rmi_f12_process_objects(f12,
22962306a36Sopenharmony_ci			&sensor->data_pkt[f12->data1_offset], valid_bytes);
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	input_mt_sync_frame(sensor->input);
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	return IRQ_HANDLED;
23462306a36Sopenharmony_ci}
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_cistatic int rmi_f12_write_control_regs(struct rmi_function *fn)
23762306a36Sopenharmony_ci{
23862306a36Sopenharmony_ci	int ret;
23962306a36Sopenharmony_ci	const struct rmi_register_desc_item *item;
24062306a36Sopenharmony_ci	struct rmi_device *rmi_dev = fn->rmi_dev;
24162306a36Sopenharmony_ci	struct f12_data *f12 = dev_get_drvdata(&fn->dev);
24262306a36Sopenharmony_ci	int control_size;
24362306a36Sopenharmony_ci	char buf[3];
24462306a36Sopenharmony_ci	u16 control_offset = 0;
24562306a36Sopenharmony_ci	u8 subpacket_offset = 0;
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	if (f12->has_dribble
24862306a36Sopenharmony_ci	    && (f12->sensor.dribble != RMI_REG_STATE_DEFAULT)) {
24962306a36Sopenharmony_ci		item = rmi_get_register_desc_item(&f12->control_reg_desc, 20);
25062306a36Sopenharmony_ci		if (item) {
25162306a36Sopenharmony_ci			control_offset = rmi_register_desc_calc_reg_offset(
25262306a36Sopenharmony_ci						&f12->control_reg_desc, 20);
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci			/*
25562306a36Sopenharmony_ci			 * The byte containing the EnableDribble bit will be
25662306a36Sopenharmony_ci			 * in either byte 0 or byte 2 of control 20. Depending
25762306a36Sopenharmony_ci			 * on the existence of subpacket 0. If control 20 is
25862306a36Sopenharmony_ci			 * larger then 3 bytes, just read the first 3.
25962306a36Sopenharmony_ci			 */
26062306a36Sopenharmony_ci			control_size = min(item->reg_size, 3UL);
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci			ret = rmi_read_block(rmi_dev, fn->fd.control_base_addr
26362306a36Sopenharmony_ci					+ control_offset, buf, control_size);
26462306a36Sopenharmony_ci			if (ret)
26562306a36Sopenharmony_ci				return ret;
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci			if (rmi_register_desc_has_subpacket(item, 0))
26862306a36Sopenharmony_ci				subpacket_offset += 1;
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci			switch (f12->sensor.dribble) {
27162306a36Sopenharmony_ci			case RMI_REG_STATE_OFF:
27262306a36Sopenharmony_ci				buf[subpacket_offset] &= ~BIT(2);
27362306a36Sopenharmony_ci				break;
27462306a36Sopenharmony_ci			case RMI_REG_STATE_ON:
27562306a36Sopenharmony_ci				buf[subpacket_offset] |= BIT(2);
27662306a36Sopenharmony_ci				break;
27762306a36Sopenharmony_ci			case RMI_REG_STATE_DEFAULT:
27862306a36Sopenharmony_ci			default:
27962306a36Sopenharmony_ci				break;
28062306a36Sopenharmony_ci			}
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci			ret = rmi_write_block(rmi_dev,
28362306a36Sopenharmony_ci				fn->fd.control_base_addr + control_offset,
28462306a36Sopenharmony_ci				buf, control_size);
28562306a36Sopenharmony_ci			if (ret)
28662306a36Sopenharmony_ci				return ret;
28762306a36Sopenharmony_ci		}
28862306a36Sopenharmony_ci	}
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	return 0;
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci}
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_cistatic int rmi_f12_config(struct rmi_function *fn)
29562306a36Sopenharmony_ci{
29662306a36Sopenharmony_ci	struct rmi_driver *drv = fn->rmi_dev->driver;
29762306a36Sopenharmony_ci	struct f12_data *f12 = dev_get_drvdata(&fn->dev);
29862306a36Sopenharmony_ci	struct rmi_2d_sensor *sensor;
29962306a36Sopenharmony_ci	int ret;
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	sensor = &f12->sensor;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	if (!sensor->report_abs)
30462306a36Sopenharmony_ci		drv->clear_irq_bits(fn->rmi_dev, f12->abs_mask);
30562306a36Sopenharmony_ci	else
30662306a36Sopenharmony_ci		drv->set_irq_bits(fn->rmi_dev, f12->abs_mask);
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	drv->clear_irq_bits(fn->rmi_dev, f12->rel_mask);
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci	ret = rmi_f12_write_control_regs(fn);
31162306a36Sopenharmony_ci	if (ret)
31262306a36Sopenharmony_ci		dev_warn(&fn->dev,
31362306a36Sopenharmony_ci			"Failed to write F12 control registers: %d\n", ret);
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	return 0;
31662306a36Sopenharmony_ci}
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_cistatic int rmi_f12_probe(struct rmi_function *fn)
31962306a36Sopenharmony_ci{
32062306a36Sopenharmony_ci	struct f12_data *f12;
32162306a36Sopenharmony_ci	int ret;
32262306a36Sopenharmony_ci	struct rmi_device *rmi_dev = fn->rmi_dev;
32362306a36Sopenharmony_ci	char buf;
32462306a36Sopenharmony_ci	u16 query_addr = fn->fd.query_base_addr;
32562306a36Sopenharmony_ci	const struct rmi_register_desc_item *item;
32662306a36Sopenharmony_ci	struct rmi_2d_sensor *sensor;
32762306a36Sopenharmony_ci	struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
32862306a36Sopenharmony_ci	struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
32962306a36Sopenharmony_ci	u16 data_offset = 0;
33062306a36Sopenharmony_ci	int mask_size;
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s\n", __func__);
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	mask_size = BITS_TO_LONGS(drvdata->irq_count) * sizeof(unsigned long);
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	ret = rmi_read(fn->rmi_dev, query_addr, &buf);
33762306a36Sopenharmony_ci	if (ret < 0) {
33862306a36Sopenharmony_ci		dev_err(&fn->dev, "Failed to read general info register: %d\n",
33962306a36Sopenharmony_ci			ret);
34062306a36Sopenharmony_ci		return -ENODEV;
34162306a36Sopenharmony_ci	}
34262306a36Sopenharmony_ci	++query_addr;
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	if (!(buf & BIT(0))) {
34562306a36Sopenharmony_ci		dev_err(&fn->dev,
34662306a36Sopenharmony_ci			"Behavior of F12 without register descriptors is undefined.\n");
34762306a36Sopenharmony_ci		return -ENODEV;
34862306a36Sopenharmony_ci	}
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	f12 = devm_kzalloc(&fn->dev, sizeof(struct f12_data) + mask_size * 2,
35162306a36Sopenharmony_ci			GFP_KERNEL);
35262306a36Sopenharmony_ci	if (!f12)
35362306a36Sopenharmony_ci		return -ENOMEM;
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	f12->abs_mask = (unsigned long *)((char *)f12
35662306a36Sopenharmony_ci			+ sizeof(struct f12_data));
35762306a36Sopenharmony_ci	f12->rel_mask = (unsigned long *)((char *)f12
35862306a36Sopenharmony_ci			+ sizeof(struct f12_data) + mask_size);
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	set_bit(fn->irq_pos, f12->abs_mask);
36162306a36Sopenharmony_ci	set_bit(fn->irq_pos + 1, f12->rel_mask);
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	f12->has_dribble = !!(buf & BIT(3));
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci	if (fn->dev.of_node) {
36662306a36Sopenharmony_ci		ret = rmi_2d_sensor_of_probe(&fn->dev, &f12->sensor_pdata);
36762306a36Sopenharmony_ci		if (ret)
36862306a36Sopenharmony_ci			return ret;
36962306a36Sopenharmony_ci	} else {
37062306a36Sopenharmony_ci		f12->sensor_pdata = pdata->sensor_pdata;
37162306a36Sopenharmony_ci	}
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci	ret = rmi_read_register_desc(rmi_dev, query_addr,
37462306a36Sopenharmony_ci					&f12->query_reg_desc);
37562306a36Sopenharmony_ci	if (ret) {
37662306a36Sopenharmony_ci		dev_err(&fn->dev,
37762306a36Sopenharmony_ci			"Failed to read the Query Register Descriptor: %d\n",
37862306a36Sopenharmony_ci			ret);
37962306a36Sopenharmony_ci		return ret;
38062306a36Sopenharmony_ci	}
38162306a36Sopenharmony_ci	query_addr += 3;
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	ret = rmi_read_register_desc(rmi_dev, query_addr,
38462306a36Sopenharmony_ci						&f12->control_reg_desc);
38562306a36Sopenharmony_ci	if (ret) {
38662306a36Sopenharmony_ci		dev_err(&fn->dev,
38762306a36Sopenharmony_ci			"Failed to read the Control Register Descriptor: %d\n",
38862306a36Sopenharmony_ci			ret);
38962306a36Sopenharmony_ci		return ret;
39062306a36Sopenharmony_ci	}
39162306a36Sopenharmony_ci	query_addr += 3;
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	ret = rmi_read_register_desc(rmi_dev, query_addr,
39462306a36Sopenharmony_ci						&f12->data_reg_desc);
39562306a36Sopenharmony_ci	if (ret) {
39662306a36Sopenharmony_ci		dev_err(&fn->dev,
39762306a36Sopenharmony_ci			"Failed to read the Data Register Descriptor: %d\n",
39862306a36Sopenharmony_ci			ret);
39962306a36Sopenharmony_ci		return ret;
40062306a36Sopenharmony_ci	}
40162306a36Sopenharmony_ci	query_addr += 3;
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci	sensor = &f12->sensor;
40462306a36Sopenharmony_ci	sensor->fn = fn;
40562306a36Sopenharmony_ci	f12->data_addr = fn->fd.data_base_addr;
40662306a36Sopenharmony_ci	sensor->pkt_size = rmi_register_desc_calc_size(&f12->data_reg_desc);
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci	sensor->axis_align =
40962306a36Sopenharmony_ci		f12->sensor_pdata.axis_align;
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci	sensor->x_mm = f12->sensor_pdata.x_mm;
41262306a36Sopenharmony_ci	sensor->y_mm = f12->sensor_pdata.y_mm;
41362306a36Sopenharmony_ci	sensor->dribble = f12->sensor_pdata.dribble;
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	if (sensor->sensor_type == rmi_sensor_default)
41662306a36Sopenharmony_ci		sensor->sensor_type =
41762306a36Sopenharmony_ci			f12->sensor_pdata.sensor_type;
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: data packet size: %d\n", __func__,
42062306a36Sopenharmony_ci		sensor->pkt_size);
42162306a36Sopenharmony_ci	sensor->data_pkt = devm_kzalloc(&fn->dev, sensor->pkt_size, GFP_KERNEL);
42262306a36Sopenharmony_ci	if (!sensor->data_pkt)
42362306a36Sopenharmony_ci		return -ENOMEM;
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	dev_set_drvdata(&fn->dev, f12);
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci	ret = rmi_f12_read_sensor_tuning(f12);
42862306a36Sopenharmony_ci	if (ret)
42962306a36Sopenharmony_ci		return ret;
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	/*
43262306a36Sopenharmony_ci	 * Figure out what data is contained in the data registers. HID devices
43362306a36Sopenharmony_ci	 * may have registers defined, but their data is not reported in the
43462306a36Sopenharmony_ci	 * HID attention report. Registers which are not reported in the HID
43562306a36Sopenharmony_ci	 * attention report check to see if the device is receiving data from
43662306a36Sopenharmony_ci	 * HID attention reports.
43762306a36Sopenharmony_ci	 */
43862306a36Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 0);
43962306a36Sopenharmony_ci	if (item && !drvdata->attn_data.data)
44062306a36Sopenharmony_ci		data_offset += item->reg_size;
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 1);
44362306a36Sopenharmony_ci	if (item) {
44462306a36Sopenharmony_ci		f12->data1 = item;
44562306a36Sopenharmony_ci		f12->data1_offset = data_offset;
44662306a36Sopenharmony_ci		data_offset += item->reg_size;
44762306a36Sopenharmony_ci		sensor->nbr_fingers = item->num_subpackets;
44862306a36Sopenharmony_ci		sensor->report_abs = 1;
44962306a36Sopenharmony_ci		sensor->attn_size += item->reg_size;
45062306a36Sopenharmony_ci	}
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 2);
45362306a36Sopenharmony_ci	if (item && !drvdata->attn_data.data)
45462306a36Sopenharmony_ci		data_offset += item->reg_size;
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 3);
45762306a36Sopenharmony_ci	if (item && !drvdata->attn_data.data)
45862306a36Sopenharmony_ci		data_offset += item->reg_size;
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 4);
46162306a36Sopenharmony_ci	if (item && !drvdata->attn_data.data)
46262306a36Sopenharmony_ci		data_offset += item->reg_size;
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 5);
46562306a36Sopenharmony_ci	if (item) {
46662306a36Sopenharmony_ci		f12->data5 = item;
46762306a36Sopenharmony_ci		f12->data5_offset = data_offset;
46862306a36Sopenharmony_ci		data_offset += item->reg_size;
46962306a36Sopenharmony_ci		sensor->attn_size += item->reg_size;
47062306a36Sopenharmony_ci	}
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 6);
47362306a36Sopenharmony_ci	if (item && !drvdata->attn_data.data) {
47462306a36Sopenharmony_ci		f12->data6 = item;
47562306a36Sopenharmony_ci		f12->data6_offset = data_offset;
47662306a36Sopenharmony_ci		data_offset += item->reg_size;
47762306a36Sopenharmony_ci	}
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 7);
48062306a36Sopenharmony_ci	if (item && !drvdata->attn_data.data)
48162306a36Sopenharmony_ci		data_offset += item->reg_size;
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 8);
48462306a36Sopenharmony_ci	if (item && !drvdata->attn_data.data)
48562306a36Sopenharmony_ci		data_offset += item->reg_size;
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 9);
48862306a36Sopenharmony_ci	if (item && !drvdata->attn_data.data) {
48962306a36Sopenharmony_ci		f12->data9 = item;
49062306a36Sopenharmony_ci		f12->data9_offset = data_offset;
49162306a36Sopenharmony_ci		data_offset += item->reg_size;
49262306a36Sopenharmony_ci		if (!sensor->report_abs)
49362306a36Sopenharmony_ci			sensor->report_rel = 1;
49462306a36Sopenharmony_ci	}
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 10);
49762306a36Sopenharmony_ci	if (item && !drvdata->attn_data.data)
49862306a36Sopenharmony_ci		data_offset += item->reg_size;
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 11);
50162306a36Sopenharmony_ci	if (item && !drvdata->attn_data.data)
50262306a36Sopenharmony_ci		data_offset += item->reg_size;
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 12);
50562306a36Sopenharmony_ci	if (item && !drvdata->attn_data.data)
50662306a36Sopenharmony_ci		data_offset += item->reg_size;
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 13);
50962306a36Sopenharmony_ci	if (item && !drvdata->attn_data.data)
51062306a36Sopenharmony_ci		data_offset += item->reg_size;
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 14);
51362306a36Sopenharmony_ci	if (item && !drvdata->attn_data.data)
51462306a36Sopenharmony_ci		data_offset += item->reg_size;
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci	item = rmi_get_register_desc_item(&f12->data_reg_desc, 15);
51762306a36Sopenharmony_ci	if (item && !drvdata->attn_data.data) {
51862306a36Sopenharmony_ci		f12->data15 = item;
51962306a36Sopenharmony_ci		f12->data15_offset = data_offset;
52062306a36Sopenharmony_ci		data_offset += item->reg_size;
52162306a36Sopenharmony_ci	}
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	/* allocate the in-kernel tracking buffers */
52462306a36Sopenharmony_ci	sensor->tracking_pos = devm_kcalloc(&fn->dev,
52562306a36Sopenharmony_ci			sensor->nbr_fingers, sizeof(struct input_mt_pos),
52662306a36Sopenharmony_ci			GFP_KERNEL);
52762306a36Sopenharmony_ci	sensor->tracking_slots = devm_kcalloc(&fn->dev,
52862306a36Sopenharmony_ci			sensor->nbr_fingers, sizeof(int), GFP_KERNEL);
52962306a36Sopenharmony_ci	sensor->objs = devm_kcalloc(&fn->dev,
53062306a36Sopenharmony_ci			sensor->nbr_fingers,
53162306a36Sopenharmony_ci			sizeof(struct rmi_2d_sensor_abs_object),
53262306a36Sopenharmony_ci			GFP_KERNEL);
53362306a36Sopenharmony_ci	if (!sensor->tracking_pos || !sensor->tracking_slots || !sensor->objs)
53462306a36Sopenharmony_ci		return -ENOMEM;
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	ret = rmi_2d_sensor_configure_input(fn, sensor);
53762306a36Sopenharmony_ci	if (ret)
53862306a36Sopenharmony_ci		return ret;
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci	return 0;
54162306a36Sopenharmony_ci}
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_cistruct rmi_function_handler rmi_f12_handler = {
54462306a36Sopenharmony_ci	.driver = {
54562306a36Sopenharmony_ci		.name = "rmi4_f12",
54662306a36Sopenharmony_ci	},
54762306a36Sopenharmony_ci	.func = 0x12,
54862306a36Sopenharmony_ci	.probe = rmi_f12_probe,
54962306a36Sopenharmony_ci	.config = rmi_f12_config,
55062306a36Sopenharmony_ci	.attention = rmi_f12_attention,
55162306a36Sopenharmony_ci};
552