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 | |
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(dev: &rmi_dev->dev); |
40 | struct f55_data *f55; |
41 | int error; |
42 | |
43 | f55 = dev_get_drvdata(dev: &fn->dev); |
44 | |
45 | error = rmi_read_block(d: fn->rmi_dev, addr: fn->fd.query_base_addr, |
46 | buf: &f55->qry, len: 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(d: fn->rmi_dev, |
74 | addr: fn->fd.control_base_addr + 1, |
75 | buf, len: 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(d: fn->rmi_dev, |
87 | addr: fn->fd.control_base_addr + 2, |
88 | buf, len: 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, dev: &fn->dev, fmt: "F55 num_rx_electrodes: %d (raw %d)\n" , |
101 | f55->cfg_num_rx_electrodes, f55->num_rx_electrodes); |
102 | rmi_dbg(RMI_DEBUG_FN, dev: &fn->dev, fmt: "F55 num_tx_electrodes: %d (raw %d)\n" , |
103 | f55->cfg_num_tx_electrodes, f55->num_tx_electrodes); |
104 | |
105 | return 0; |
106 | } |
107 | |
108 | static int rmi_f55_probe(struct rmi_function *fn) |
109 | { |
110 | struct f55_data *f55; |
111 | |
112 | f55 = devm_kzalloc(dev: &fn->dev, size: sizeof(struct f55_data), GFP_KERNEL); |
113 | if (!f55) |
114 | return -ENOMEM; |
115 | |
116 | f55->fn = fn; |
117 | dev_set_drvdata(dev: &fn->dev, data: 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 | |