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