GNU Linux-libre 4.14.290-gnu1
[releases.git] / drivers / input / rmi4 / rmi_f55.c
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 };