1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2012-2015 Synaptics Incorporated
4  * Copyright (C) 2016 Zodiac Inflight Innovations
5  */
6 
7 #include <linux/bitops.h>
8 #include <linux/kernel.h>
9 #include <linux/rmi.h>
10 #include <linux/slab.h>
11 #include "rmi_driver.h"
12 
13 #define F55_NAME		"rmi4_f55"
14 
15 /* F55 data offsets */
16 #define F55_NUM_RX_OFFSET	0
17 #define F55_NUM_TX_OFFSET	1
18 #define F55_PHYS_CHAR_OFFSET	2
19 
20 /* Only read required query registers */
21 #define F55_QUERY_LEN		3
22 
23 /* F55 capabilities */
24 #define F55_CAP_SENSOR_ASSIGN	BIT(0)
25 
26 struct f55_data {
27 	struct rmi_function *fn;
28 
29 	u8 qry[F55_QUERY_LEN];
30 	u8 num_rx_electrodes;
31 	u8 cfg_num_rx_electrodes;
32 	u8 num_tx_electrodes;
33 	u8 cfg_num_tx_electrodes;
34 };
35 
rmi_f55_detect(struct rmi_function * fn)36 static int rmi_f55_detect(struct rmi_function *fn)
37 {
38 	struct rmi_device *rmi_dev = fn->rmi_dev;
39 	struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev);
40 	struct f55_data *f55;
41 	int error;
42 
43 	f55 = dev_get_drvdata(&fn->dev);
44 
45 	error = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr,
46 			       &f55->qry, sizeof(f55->qry));
47 	if (error) {
48 		dev_err(&fn->dev, "%s: Failed to query F55 properties\n",
49 			__func__);
50 		return error;
51 	}
52 
53 	f55->num_rx_electrodes = f55->qry[F55_NUM_RX_OFFSET];
54 	f55->num_tx_electrodes = f55->qry[F55_NUM_TX_OFFSET];
55 
56 	f55->cfg_num_rx_electrodes = f55->num_rx_electrodes;
57 	f55->cfg_num_tx_electrodes = f55->num_rx_electrodes;
58 
59 	drv_data->num_rx_electrodes = f55->cfg_num_rx_electrodes;
60 	drv_data->num_tx_electrodes = f55->cfg_num_rx_electrodes;
61 
62 	if (f55->qry[F55_PHYS_CHAR_OFFSET] & F55_CAP_SENSOR_ASSIGN) {
63 		int i, total;
64 		u8 buf[256];
65 
66 		/*
67 		 * Calculate the number of enabled receive and transmit
68 		 * electrodes by reading F55:Ctrl1 (sensor receiver assignment)
69 		 * and F55:Ctrl2 (sensor transmitter assignment). The number of
70 		 * enabled electrodes is the sum of all field entries with a
71 		 * value other than 0xff.
72 		 */
73 		error = rmi_read_block(fn->rmi_dev,
74 				       fn->fd.control_base_addr + 1,
75 				       buf, f55->num_rx_electrodes);
76 		if (!error) {
77 			total = 0;
78 			for (i = 0; i < f55->num_rx_electrodes; i++) {
79 				if (buf[i] != 0xff)
80 					total++;
81 			}
82 			f55->cfg_num_rx_electrodes = total;
83 			drv_data->num_rx_electrodes = total;
84 		}
85 
86 		error = rmi_read_block(fn->rmi_dev,
87 				       fn->fd.control_base_addr + 2,
88 				       buf, f55->num_tx_electrodes);
89 		if (!error) {
90 			total = 0;
91 			for (i = 0; i < f55->num_tx_electrodes; i++) {
92 				if (buf[i] != 0xff)
93 					total++;
94 			}
95 			f55->cfg_num_tx_electrodes = total;
96 			drv_data->num_tx_electrodes = total;
97 		}
98 	}
99 
100 	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "F55 num_rx_electrodes: %d (raw %d)\n",
101 		f55->cfg_num_rx_electrodes, f55->num_rx_electrodes);
102 	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "F55 num_tx_electrodes: %d (raw %d)\n",
103 		f55->cfg_num_tx_electrodes, f55->num_tx_electrodes);
104 
105 	return 0;
106 }
107 
rmi_f55_probe(struct rmi_function * fn)108 static int rmi_f55_probe(struct rmi_function *fn)
109 {
110 	struct f55_data *f55;
111 
112 	f55 = devm_kzalloc(&fn->dev, sizeof(struct f55_data), GFP_KERNEL);
113 	if (!f55)
114 		return -ENOMEM;
115 
116 	f55->fn = fn;
117 	dev_set_drvdata(&fn->dev, f55);
118 
119 	return rmi_f55_detect(fn);
120 }
121 
122 struct rmi_function_handler rmi_f55_handler = {
123 	.driver = {
124 		.name = F55_NAME,
125 	},
126 	.func = 0x55,
127 	.probe = rmi_f55_probe,
128 };
129