Commit | Line | Data |
---|---|---|
d2912cb1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
6adba43f GR |
2 | /* |
3 | * Copyright (c) 2012-2015 Synaptics Incorporated | |
4 | * Copyright (C) 2016 Zodiac Inflight Innovations | |
6adba43f GR |
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 | { | |
c762cc68 GR |
38 | struct rmi_device *rmi_dev = fn->rmi_dev; |
39 | struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev); | |
6adba43f GR |
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 | ||
c762cc68 GR |
59 | drv_data->num_rx_electrodes = f55->cfg_num_rx_electrodes; |
60 | drv_data->num_tx_electrodes = f55->cfg_num_rx_electrodes; | |
61 | ||
6adba43f GR |
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; | |
c762cc68 | 83 | drv_data->num_rx_electrodes = total; |
6adba43f GR |
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; | |
c762cc68 | 96 | drv_data->num_tx_electrodes = total; |
6adba43f GR |
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 | ||
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 | }; |