xref: /openbmc/linux/drivers/input/rmi4/rmi_f55.c (revision 6adba43f)
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 f55_data *f55;
42 	int error;
43 
44 	f55 = dev_get_drvdata(&fn->dev);
45 
46 	error = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr,
47 			       &f55->qry, sizeof(f55->qry));
48 	if (error) {
49 		dev_err(&fn->dev, "%s: Failed to query F55 properties\n",
50 			__func__);
51 		return error;
52 	}
53 
54 	f55->num_rx_electrodes = f55->qry[F55_NUM_RX_OFFSET];
55 	f55->num_tx_electrodes = f55->qry[F55_NUM_TX_OFFSET];
56 
57 	f55->cfg_num_rx_electrodes = f55->num_rx_electrodes;
58 	f55->cfg_num_tx_electrodes = f55->num_rx_electrodes;
59 
60 	if (f55->qry[F55_PHYS_CHAR_OFFSET] & F55_CAP_SENSOR_ASSIGN) {
61 		int i, total;
62 		u8 buf[256];
63 
64 		/*
65 		 * Calculate the number of enabled receive and transmit
66 		 * electrodes by reading F55:Ctrl1 (sensor receiver assignment)
67 		 * and F55:Ctrl2 (sensor transmitter assignment). The number of
68 		 * enabled electrodes is the sum of all field entries with a
69 		 * value other than 0xff.
70 		 */
71 		error = rmi_read_block(fn->rmi_dev,
72 				       fn->fd.control_base_addr + 1,
73 				       buf, f55->num_rx_electrodes);
74 		if (!error) {
75 			total = 0;
76 			for (i = 0; i < f55->num_rx_electrodes; i++) {
77 				if (buf[i] != 0xff)
78 					total++;
79 			}
80 			f55->cfg_num_rx_electrodes = total;
81 		}
82 
83 		error = rmi_read_block(fn->rmi_dev,
84 				       fn->fd.control_base_addr + 2,
85 				       buf, f55->num_tx_electrodes);
86 		if (!error) {
87 			total = 0;
88 			for (i = 0; i < f55->num_tx_electrodes; i++) {
89 				if (buf[i] != 0xff)
90 					total++;
91 			}
92 			f55->cfg_num_tx_electrodes = total;
93 		}
94 	}
95 
96 	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "F55 num_rx_electrodes: %d (raw %d)\n",
97 		f55->cfg_num_rx_electrodes, f55->num_rx_electrodes);
98 	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "F55 num_tx_electrodes: %d (raw %d)\n",
99 		f55->cfg_num_tx_electrodes, f55->num_tx_electrodes);
100 
101 	return 0;
102 }
103 
104 static int rmi_f55_probe(struct rmi_function *fn)
105 {
106 	struct f55_data *f55;
107 
108 	f55 = devm_kzalloc(&fn->dev, sizeof(struct f55_data), GFP_KERNEL);
109 	if (!f55)
110 		return -ENOMEM;
111 
112 	f55->fn = fn;
113 	dev_set_drvdata(&fn->dev, f55);
114 
115 	return rmi_f55_detect(fn);
116 }
117 
118 struct rmi_function_handler rmi_f55_handler = {
119 	.driver = {
120 		.name = F55_NAME,
121 	},
122 	.func = 0x55,
123 	.probe = rmi_f55_probe,
124 };
125