Loading...
1/*
2 * adv7511_cec.c - Analog Devices ADV7511/33 cec driver
3 *
4 * Copyright 2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5 *
6 * This program is free software; you may redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
14 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
15 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17 * SOFTWARE.
18 *
19 */
20
21#include <linux/device.h>
22#include <linux/module.h>
23#include <linux/of_device.h>
24#include <linux/slab.h>
25#include <linux/clk.h>
26
27#include <media/cec.h>
28
29#include "adv7511.h"
30
31#define ADV7511_INT1_CEC_MASK \
32 (ADV7511_INT1_CEC_TX_READY | ADV7511_INT1_CEC_TX_ARBIT_LOST | \
33 ADV7511_INT1_CEC_TX_RETRY_TIMEOUT | ADV7511_INT1_CEC_RX_READY1)
34
35static void adv_cec_tx_raw_status(struct adv7511 *adv7511, u8 tx_raw_status)
36{
37 unsigned int offset = adv7511->type == ADV7533 ?
38 ADV7533_REG_CEC_OFFSET : 0;
39 unsigned int val;
40
41 if (regmap_read(adv7511->regmap_cec,
42 ADV7511_REG_CEC_TX_ENABLE + offset, &val))
43 return;
44
45 if ((val & 0x01) == 0)
46 return;
47
48 if (tx_raw_status & ADV7511_INT1_CEC_TX_ARBIT_LOST) {
49 cec_transmit_attempt_done(adv7511->cec_adap,
50 CEC_TX_STATUS_ARB_LOST);
51 return;
52 }
53 if (tx_raw_status & ADV7511_INT1_CEC_TX_RETRY_TIMEOUT) {
54 u8 status;
55 u8 err_cnt = 0;
56 u8 nack_cnt = 0;
57 u8 low_drive_cnt = 0;
58 unsigned int cnt;
59
60 /*
61 * We set this status bit since this hardware performs
62 * retransmissions.
63 */
64 status = CEC_TX_STATUS_MAX_RETRIES;
65 if (regmap_read(adv7511->regmap_cec,
66 ADV7511_REG_CEC_TX_LOW_DRV_CNT + offset, &cnt)) {
67 err_cnt = 1;
68 status |= CEC_TX_STATUS_ERROR;
69 } else {
70 nack_cnt = cnt & 0xf;
71 if (nack_cnt)
72 status |= CEC_TX_STATUS_NACK;
73 low_drive_cnt = cnt >> 4;
74 if (low_drive_cnt)
75 status |= CEC_TX_STATUS_LOW_DRIVE;
76 }
77 cec_transmit_done(adv7511->cec_adap, status,
78 0, nack_cnt, low_drive_cnt, err_cnt);
79 return;
80 }
81 if (tx_raw_status & ADV7511_INT1_CEC_TX_READY) {
82 cec_transmit_attempt_done(adv7511->cec_adap, CEC_TX_STATUS_OK);
83 return;
84 }
85}
86
87void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1)
88{
89 unsigned int offset = adv7511->type == ADV7533 ?
90 ADV7533_REG_CEC_OFFSET : 0;
91 const u32 irq_tx_mask = ADV7511_INT1_CEC_TX_READY |
92 ADV7511_INT1_CEC_TX_ARBIT_LOST |
93 ADV7511_INT1_CEC_TX_RETRY_TIMEOUT;
94 struct cec_msg msg = {};
95 unsigned int len;
96 unsigned int val;
97 u8 i;
98
99 if (irq1 & irq_tx_mask)
100 adv_cec_tx_raw_status(adv7511, irq1);
101
102 if (!(irq1 & ADV7511_INT1_CEC_RX_READY1))
103 return;
104
105 if (regmap_read(adv7511->regmap_cec,
106 ADV7511_REG_CEC_RX_FRAME_LEN + offset, &len))
107 return;
108
109 msg.len = len & 0x1f;
110
111 if (msg.len > 16)
112 msg.len = 16;
113
114 if (!msg.len)
115 return;
116
117 for (i = 0; i < msg.len; i++) {
118 regmap_read(adv7511->regmap_cec,
119 i + ADV7511_REG_CEC_RX_FRAME_HDR + offset, &val);
120 msg.msg[i] = val;
121 }
122
123 /* toggle to re-enable rx 1 */
124 regmap_write(adv7511->regmap_cec,
125 ADV7511_REG_CEC_RX_BUFFERS + offset, 1);
126 regmap_write(adv7511->regmap_cec,
127 ADV7511_REG_CEC_RX_BUFFERS + offset, 0);
128 cec_received_msg(adv7511->cec_adap, &msg);
129}
130
131static int adv7511_cec_adap_enable(struct cec_adapter *adap, bool enable)
132{
133 struct adv7511 *adv7511 = cec_get_drvdata(adap);
134 unsigned int offset = adv7511->type == ADV7533 ?
135 ADV7533_REG_CEC_OFFSET : 0;
136
137 if (adv7511->i2c_cec == NULL)
138 return -EIO;
139
140 if (!adv7511->cec_enabled_adap && enable) {
141 /* power up cec section */
142 regmap_update_bits(adv7511->regmap_cec,
143 ADV7511_REG_CEC_CLK_DIV + offset,
144 0x03, 0x01);
145 /* legacy mode and clear all rx buffers */
146 regmap_write(adv7511->regmap_cec,
147 ADV7511_REG_CEC_RX_BUFFERS + offset, 0x07);
148 regmap_write(adv7511->regmap_cec,
149 ADV7511_REG_CEC_RX_BUFFERS + offset, 0);
150 /* initially disable tx */
151 regmap_update_bits(adv7511->regmap_cec,
152 ADV7511_REG_CEC_TX_ENABLE + offset, 1, 0);
153 /* enabled irqs: */
154 /* tx: ready */
155 /* tx: arbitration lost */
156 /* tx: retry timeout */
157 /* rx: ready 1 */
158 regmap_update_bits(adv7511->regmap,
159 ADV7511_REG_INT_ENABLE(1), 0x3f,
160 ADV7511_INT1_CEC_MASK);
161 } else if (adv7511->cec_enabled_adap && !enable) {
162 regmap_update_bits(adv7511->regmap,
163 ADV7511_REG_INT_ENABLE(1), 0x3f, 0);
164 /* disable address mask 1-3 */
165 regmap_update_bits(adv7511->regmap_cec,
166 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
167 0x70, 0x00);
168 /* power down cec section */
169 regmap_update_bits(adv7511->regmap_cec,
170 ADV7511_REG_CEC_CLK_DIV + offset,
171 0x03, 0x00);
172 adv7511->cec_valid_addrs = 0;
173 }
174 adv7511->cec_enabled_adap = enable;
175 return 0;
176}
177
178static int adv7511_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
179{
180 struct adv7511 *adv7511 = cec_get_drvdata(adap);
181 unsigned int offset = adv7511->type == ADV7533 ?
182 ADV7533_REG_CEC_OFFSET : 0;
183 unsigned int i, free_idx = ADV7511_MAX_ADDRS;
184
185 if (!adv7511->cec_enabled_adap)
186 return addr == CEC_LOG_ADDR_INVALID ? 0 : -EIO;
187
188 if (addr == CEC_LOG_ADDR_INVALID) {
189 regmap_update_bits(adv7511->regmap_cec,
190 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
191 0x70, 0);
192 adv7511->cec_valid_addrs = 0;
193 return 0;
194 }
195
196 for (i = 0; i < ADV7511_MAX_ADDRS; i++) {
197 bool is_valid = adv7511->cec_valid_addrs & (1 << i);
198
199 if (free_idx == ADV7511_MAX_ADDRS && !is_valid)
200 free_idx = i;
201 if (is_valid && adv7511->cec_addr[i] == addr)
202 return 0;
203 }
204 if (i == ADV7511_MAX_ADDRS) {
205 i = free_idx;
206 if (i == ADV7511_MAX_ADDRS)
207 return -ENXIO;
208 }
209 adv7511->cec_addr[i] = addr;
210 adv7511->cec_valid_addrs |= 1 << i;
211
212 switch (i) {
213 case 0:
214 /* enable address mask 0 */
215 regmap_update_bits(adv7511->regmap_cec,
216 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
217 0x10, 0x10);
218 /* set address for mask 0 */
219 regmap_update_bits(adv7511->regmap_cec,
220 ADV7511_REG_CEC_LOG_ADDR_0_1 + offset,
221 0x0f, addr);
222 break;
223 case 1:
224 /* enable address mask 1 */
225 regmap_update_bits(adv7511->regmap_cec,
226 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
227 0x20, 0x20);
228 /* set address for mask 1 */
229 regmap_update_bits(adv7511->regmap_cec,
230 ADV7511_REG_CEC_LOG_ADDR_0_1 + offset,
231 0xf0, addr << 4);
232 break;
233 case 2:
234 /* enable address mask 2 */
235 regmap_update_bits(adv7511->regmap_cec,
236 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
237 0x40, 0x40);
238 /* set address for mask 1 */
239 regmap_update_bits(adv7511->regmap_cec,
240 ADV7511_REG_CEC_LOG_ADDR_2 + offset,
241 0x0f, addr);
242 break;
243 }
244 return 0;
245}
246
247static int adv7511_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
248 u32 signal_free_time, struct cec_msg *msg)
249{
250 struct adv7511 *adv7511 = cec_get_drvdata(adap);
251 unsigned int offset = adv7511->type == ADV7533 ?
252 ADV7533_REG_CEC_OFFSET : 0;
253 u8 len = msg->len;
254 unsigned int i;
255
256 /*
257 * The number of retries is the number of attempts - 1, but retry
258 * at least once. It's not clear if a value of 0 is allowed, so
259 * let's do at least one retry.
260 */
261 regmap_update_bits(adv7511->regmap_cec,
262 ADV7511_REG_CEC_TX_RETRY + offset,
263 0x70, max(1, attempts - 1) << 4);
264
265 /* blocking, clear cec tx irq status */
266 regmap_update_bits(adv7511->regmap, ADV7511_REG_INT(1), 0x38, 0x38);
267
268 /* write data */
269 for (i = 0; i < len; i++)
270 regmap_write(adv7511->regmap_cec,
271 i + ADV7511_REG_CEC_TX_FRAME_HDR + offset,
272 msg->msg[i]);
273
274 /* set length (data + header) */
275 regmap_write(adv7511->regmap_cec,
276 ADV7511_REG_CEC_TX_FRAME_LEN + offset, len);
277 /* start transmit, enable tx */
278 regmap_write(adv7511->regmap_cec,
279 ADV7511_REG_CEC_TX_ENABLE + offset, 0x01);
280 return 0;
281}
282
283static const struct cec_adap_ops adv7511_cec_adap_ops = {
284 .adap_enable = adv7511_cec_adap_enable,
285 .adap_log_addr = adv7511_cec_adap_log_addr,
286 .adap_transmit = adv7511_cec_adap_transmit,
287};
288
289static int adv7511_cec_parse_dt(struct device *dev, struct adv7511 *adv7511)
290{
291 adv7511->cec_clk = devm_clk_get(dev, "cec");
292 if (IS_ERR(adv7511->cec_clk)) {
293 int ret = PTR_ERR(adv7511->cec_clk);
294
295 adv7511->cec_clk = NULL;
296 return ret;
297 }
298 clk_prepare_enable(adv7511->cec_clk);
299 adv7511->cec_clk_freq = clk_get_rate(adv7511->cec_clk);
300 return 0;
301}
302
303int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
304{
305 unsigned int offset = adv7511->type == ADV7533 ?
306 ADV7533_REG_CEC_OFFSET : 0;
307 int ret = adv7511_cec_parse_dt(dev, adv7511);
308
309 if (ret)
310 goto err_cec_parse_dt;
311
312 adv7511->cec_adap = cec_allocate_adapter(&adv7511_cec_adap_ops,
313 adv7511, dev_name(dev), CEC_CAP_DEFAULTS, ADV7511_MAX_ADDRS);
314 if (IS_ERR(adv7511->cec_adap)) {
315 ret = PTR_ERR(adv7511->cec_adap);
316 goto err_cec_alloc;
317 }
318
319 regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset, 0);
320 /* cec soft reset */
321 regmap_write(adv7511->regmap_cec,
322 ADV7511_REG_CEC_SOFT_RESET + offset, 0x01);
323 regmap_write(adv7511->regmap_cec,
324 ADV7511_REG_CEC_SOFT_RESET + offset, 0x00);
325
326 /* legacy mode */
327 regmap_write(adv7511->regmap_cec,
328 ADV7511_REG_CEC_RX_BUFFERS + offset, 0x00);
329
330 regmap_write(adv7511->regmap_cec,
331 ADV7511_REG_CEC_CLK_DIV + offset,
332 ((adv7511->cec_clk_freq / 750000) - 1) << 2);
333
334 ret = cec_register_adapter(adv7511->cec_adap, dev);
335 if (ret)
336 goto err_cec_register;
337 return 0;
338
339err_cec_register:
340 cec_delete_adapter(adv7511->cec_adap);
341 adv7511->cec_adap = NULL;
342err_cec_alloc:
343 dev_info(dev, "Initializing CEC failed with error %d, disabling CEC\n",
344 ret);
345err_cec_parse_dt:
346 regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset,
347 ADV7511_CEC_CTRL_POWER_DOWN);
348 return ret == -EPROBE_DEFER ? ret : 0;
349}
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * adv7511_cec.c - Analog Devices ADV7511/33 cec driver
4 *
5 * Copyright 2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
6 */
7
8#include <linux/device.h>
9#include <linux/module.h>
10#include <linux/slab.h>
11#include <linux/clk.h>
12
13#include <media/cec.h>
14
15#include "adv7511.h"
16
17static const u8 ADV7511_REG_CEC_RX_FRAME_HDR[] = {
18 ADV7511_REG_CEC_RX1_FRAME_HDR,
19 ADV7511_REG_CEC_RX2_FRAME_HDR,
20 ADV7511_REG_CEC_RX3_FRAME_HDR,
21};
22
23static const u8 ADV7511_REG_CEC_RX_FRAME_LEN[] = {
24 ADV7511_REG_CEC_RX1_FRAME_LEN,
25 ADV7511_REG_CEC_RX2_FRAME_LEN,
26 ADV7511_REG_CEC_RX3_FRAME_LEN,
27};
28
29#define ADV7511_INT1_CEC_MASK \
30 (ADV7511_INT1_CEC_TX_READY | ADV7511_INT1_CEC_TX_ARBIT_LOST | \
31 ADV7511_INT1_CEC_TX_RETRY_TIMEOUT | ADV7511_INT1_CEC_RX_READY1 | \
32 ADV7511_INT1_CEC_RX_READY2 | ADV7511_INT1_CEC_RX_READY3)
33
34static void adv_cec_tx_raw_status(struct adv7511 *adv7511, u8 tx_raw_status)
35{
36 unsigned int offset = adv7511->info->reg_cec_offset;
37 unsigned int val;
38
39 if (regmap_read(adv7511->regmap_cec,
40 ADV7511_REG_CEC_TX_ENABLE + offset, &val))
41 return;
42
43 if ((val & 0x01) == 0)
44 return;
45
46 if (tx_raw_status & ADV7511_INT1_CEC_TX_ARBIT_LOST) {
47 cec_transmit_attempt_done(adv7511->cec_adap,
48 CEC_TX_STATUS_ARB_LOST);
49 return;
50 }
51 if (tx_raw_status & ADV7511_INT1_CEC_TX_RETRY_TIMEOUT) {
52 u8 status;
53 u8 err_cnt = 0;
54 u8 nack_cnt = 0;
55 u8 low_drive_cnt = 0;
56 unsigned int cnt;
57
58 /*
59 * We set this status bit since this hardware performs
60 * retransmissions.
61 */
62 status = CEC_TX_STATUS_MAX_RETRIES;
63 if (regmap_read(adv7511->regmap_cec,
64 ADV7511_REG_CEC_TX_LOW_DRV_CNT + offset, &cnt)) {
65 err_cnt = 1;
66 status |= CEC_TX_STATUS_ERROR;
67 } else {
68 nack_cnt = cnt & 0xf;
69 if (nack_cnt)
70 status |= CEC_TX_STATUS_NACK;
71 low_drive_cnt = cnt >> 4;
72 if (low_drive_cnt)
73 status |= CEC_TX_STATUS_LOW_DRIVE;
74 }
75 cec_transmit_done(adv7511->cec_adap, status,
76 0, nack_cnt, low_drive_cnt, err_cnt);
77 return;
78 }
79 if (tx_raw_status & ADV7511_INT1_CEC_TX_READY) {
80 cec_transmit_attempt_done(adv7511->cec_adap, CEC_TX_STATUS_OK);
81 return;
82 }
83}
84
85static void adv7511_cec_rx(struct adv7511 *adv7511, int rx_buf)
86{
87 unsigned int offset = adv7511->info->reg_cec_offset;
88 struct cec_msg msg = {};
89 unsigned int len;
90 unsigned int val;
91 u8 i;
92
93 if (regmap_read(adv7511->regmap_cec,
94 ADV7511_REG_CEC_RX_FRAME_LEN[rx_buf] + offset, &len))
95 return;
96
97 msg.len = len & 0x1f;
98
99 if (msg.len > 16)
100 msg.len = 16;
101
102 if (!msg.len)
103 return;
104
105 for (i = 0; i < msg.len; i++) {
106 regmap_read(adv7511->regmap_cec,
107 i + ADV7511_REG_CEC_RX_FRAME_HDR[rx_buf] + offset,
108 &val);
109 msg.msg[i] = val;
110 }
111
112 /* Toggle RX Ready Clear bit to re-enable this RX buffer */
113 regmap_update_bits(adv7511->regmap_cec,
114 ADV7511_REG_CEC_RX_BUFFERS + offset, BIT(rx_buf),
115 BIT(rx_buf));
116 regmap_update_bits(adv7511->regmap_cec,
117 ADV7511_REG_CEC_RX_BUFFERS + offset, BIT(rx_buf), 0);
118
119 cec_received_msg(adv7511->cec_adap, &msg);
120}
121
122void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1)
123{
124 unsigned int offset = adv7511->info->reg_cec_offset;
125 const u32 irq_tx_mask = ADV7511_INT1_CEC_TX_READY |
126 ADV7511_INT1_CEC_TX_ARBIT_LOST |
127 ADV7511_INT1_CEC_TX_RETRY_TIMEOUT;
128 const u32 irq_rx_mask = ADV7511_INT1_CEC_RX_READY1 |
129 ADV7511_INT1_CEC_RX_READY2 |
130 ADV7511_INT1_CEC_RX_READY3;
131 unsigned int rx_status;
132 int rx_order[3] = { -1, -1, -1 };
133 int i;
134
135 if (irq1 & irq_tx_mask)
136 adv_cec_tx_raw_status(adv7511, irq1);
137
138 if (!(irq1 & irq_rx_mask))
139 return;
140
141 if (regmap_read(adv7511->regmap_cec,
142 ADV7511_REG_CEC_RX_STATUS + offset, &rx_status))
143 return;
144
145 /*
146 * ADV7511_REG_CEC_RX_STATUS[5:0] contains the reception order of RX
147 * buffers 0, 1, and 2 in bits [1:0], [3:2], and [5:4] respectively.
148 * The values are to be interpreted as follows:
149 *
150 * 0 = buffer unused
151 * 1 = buffer contains oldest received frame (if applicable)
152 * 2 = buffer contains second oldest received frame (if applicable)
153 * 3 = buffer contains third oldest received frame (if applicable)
154 *
155 * Fill rx_order with the sequence of RX buffer indices to
156 * read from in order, where -1 indicates that there are no
157 * more buffers to process.
158 */
159 for (i = 0; i < 3; i++) {
160 unsigned int timestamp = (rx_status >> (2 * i)) & 0x3;
161
162 if (timestamp)
163 rx_order[timestamp - 1] = i;
164 }
165
166 /* Read CEC RX buffers in the appropriate order as prescribed above */
167 for (i = 0; i < 3; i++) {
168 int rx_buf = rx_order[i];
169
170 if (rx_buf < 0)
171 break;
172
173 adv7511_cec_rx(adv7511, rx_buf);
174 }
175}
176
177static int adv7511_cec_adap_enable(struct cec_adapter *adap, bool enable)
178{
179 struct adv7511 *adv7511 = cec_get_drvdata(adap);
180 unsigned int offset = adv7511->info->reg_cec_offset;
181
182 if (adv7511->i2c_cec == NULL)
183 return -EIO;
184
185 if (!adv7511->cec_enabled_adap && enable) {
186 /* power up cec section */
187 regmap_update_bits(adv7511->regmap_cec,
188 ADV7511_REG_CEC_CLK_DIV + offset,
189 0x03, 0x01);
190 /* non-legacy mode and clear all rx buffers */
191 regmap_write(adv7511->regmap_cec,
192 ADV7511_REG_CEC_RX_BUFFERS + offset, 0x0f);
193 regmap_write(adv7511->regmap_cec,
194 ADV7511_REG_CEC_RX_BUFFERS + offset, 0x08);
195 /* initially disable tx */
196 regmap_update_bits(adv7511->regmap_cec,
197 ADV7511_REG_CEC_TX_ENABLE + offset, 1, 0);
198 /* enabled irqs: */
199 /* tx: ready */
200 /* tx: arbitration lost */
201 /* tx: retry timeout */
202 /* rx: ready 1-3 */
203 regmap_update_bits(adv7511->regmap,
204 ADV7511_REG_INT_ENABLE(1), 0x3f,
205 ADV7511_INT1_CEC_MASK);
206 } else if (adv7511->cec_enabled_adap && !enable) {
207 regmap_update_bits(adv7511->regmap,
208 ADV7511_REG_INT_ENABLE(1), 0x3f, 0);
209 /* disable address mask 1-3 */
210 regmap_update_bits(adv7511->regmap_cec,
211 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
212 0x70, 0x00);
213 /* power down cec section */
214 regmap_update_bits(adv7511->regmap_cec,
215 ADV7511_REG_CEC_CLK_DIV + offset,
216 0x03, 0x00);
217 adv7511->cec_valid_addrs = 0;
218 }
219 adv7511->cec_enabled_adap = enable;
220 return 0;
221}
222
223static int adv7511_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
224{
225 struct adv7511 *adv7511 = cec_get_drvdata(adap);
226 unsigned int offset = adv7511->info->reg_cec_offset;
227 unsigned int i, free_idx = ADV7511_MAX_ADDRS;
228
229 if (!adv7511->cec_enabled_adap)
230 return addr == CEC_LOG_ADDR_INVALID ? 0 : -EIO;
231
232 if (addr == CEC_LOG_ADDR_INVALID) {
233 regmap_update_bits(adv7511->regmap_cec,
234 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
235 0x70, 0);
236 adv7511->cec_valid_addrs = 0;
237 return 0;
238 }
239
240 for (i = 0; i < ADV7511_MAX_ADDRS; i++) {
241 bool is_valid = adv7511->cec_valid_addrs & (1 << i);
242
243 if (free_idx == ADV7511_MAX_ADDRS && !is_valid)
244 free_idx = i;
245 if (is_valid && adv7511->cec_addr[i] == addr)
246 return 0;
247 }
248 if (i == ADV7511_MAX_ADDRS) {
249 i = free_idx;
250 if (i == ADV7511_MAX_ADDRS)
251 return -ENXIO;
252 }
253 adv7511->cec_addr[i] = addr;
254 adv7511->cec_valid_addrs |= 1 << i;
255
256 switch (i) {
257 case 0:
258 /* enable address mask 0 */
259 regmap_update_bits(adv7511->regmap_cec,
260 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
261 0x10, 0x10);
262 /* set address for mask 0 */
263 regmap_update_bits(adv7511->regmap_cec,
264 ADV7511_REG_CEC_LOG_ADDR_0_1 + offset,
265 0x0f, addr);
266 break;
267 case 1:
268 /* enable address mask 1 */
269 regmap_update_bits(adv7511->regmap_cec,
270 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
271 0x20, 0x20);
272 /* set address for mask 1 */
273 regmap_update_bits(adv7511->regmap_cec,
274 ADV7511_REG_CEC_LOG_ADDR_0_1 + offset,
275 0xf0, addr << 4);
276 break;
277 case 2:
278 /* enable address mask 2 */
279 regmap_update_bits(adv7511->regmap_cec,
280 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
281 0x40, 0x40);
282 /* set address for mask 1 */
283 regmap_update_bits(adv7511->regmap_cec,
284 ADV7511_REG_CEC_LOG_ADDR_2 + offset,
285 0x0f, addr);
286 break;
287 }
288 return 0;
289}
290
291static int adv7511_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
292 u32 signal_free_time, struct cec_msg *msg)
293{
294 struct adv7511 *adv7511 = cec_get_drvdata(adap);
295 unsigned int offset = adv7511->info->reg_cec_offset;
296 u8 len = msg->len;
297 unsigned int i;
298
299 /*
300 * The number of retries is the number of attempts - 1, but retry
301 * at least once. It's not clear if a value of 0 is allowed, so
302 * let's do at least one retry.
303 */
304 regmap_update_bits(adv7511->regmap_cec,
305 ADV7511_REG_CEC_TX_RETRY + offset,
306 0x70, max(1, attempts - 1) << 4);
307
308 /* blocking, clear cec tx irq status */
309 regmap_update_bits(adv7511->regmap, ADV7511_REG_INT(1), 0x38, 0x38);
310
311 /* write data */
312 for (i = 0; i < len; i++)
313 regmap_write(adv7511->regmap_cec,
314 i + ADV7511_REG_CEC_TX_FRAME_HDR + offset,
315 msg->msg[i]);
316
317 /* set length (data + header) */
318 regmap_write(adv7511->regmap_cec,
319 ADV7511_REG_CEC_TX_FRAME_LEN + offset, len);
320 /* start transmit, enable tx */
321 regmap_write(adv7511->regmap_cec,
322 ADV7511_REG_CEC_TX_ENABLE + offset, 0x01);
323 return 0;
324}
325
326static const struct cec_adap_ops adv7511_cec_adap_ops = {
327 .adap_enable = adv7511_cec_adap_enable,
328 .adap_log_addr = adv7511_cec_adap_log_addr,
329 .adap_transmit = adv7511_cec_adap_transmit,
330};
331
332static int adv7511_cec_parse_dt(struct device *dev, struct adv7511 *adv7511)
333{
334 adv7511->cec_clk = devm_clk_get(dev, "cec");
335 if (IS_ERR(adv7511->cec_clk)) {
336 int ret = PTR_ERR(adv7511->cec_clk);
337
338 adv7511->cec_clk = NULL;
339 return ret;
340 }
341 clk_prepare_enable(adv7511->cec_clk);
342 adv7511->cec_clk_freq = clk_get_rate(adv7511->cec_clk);
343 return 0;
344}
345
346int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
347{
348 unsigned int offset = adv7511->info->reg_cec_offset;
349 int ret = adv7511_cec_parse_dt(dev, adv7511);
350
351 if (ret)
352 goto err_cec_parse_dt;
353
354 adv7511->cec_adap = cec_allocate_adapter(&adv7511_cec_adap_ops,
355 adv7511, dev_name(dev), CEC_CAP_DEFAULTS, ADV7511_MAX_ADDRS);
356 if (IS_ERR(adv7511->cec_adap)) {
357 ret = PTR_ERR(adv7511->cec_adap);
358 goto err_cec_alloc;
359 }
360
361 regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL, 0);
362 /* cec soft reset */
363 regmap_write(adv7511->regmap_cec,
364 ADV7511_REG_CEC_SOFT_RESET + offset, 0x01);
365 regmap_write(adv7511->regmap_cec,
366 ADV7511_REG_CEC_SOFT_RESET + offset, 0x00);
367
368 /* non-legacy mode - use all three RX buffers */
369 regmap_write(adv7511->regmap_cec,
370 ADV7511_REG_CEC_RX_BUFFERS + offset, 0x08);
371
372 regmap_write(adv7511->regmap_cec,
373 ADV7511_REG_CEC_CLK_DIV + offset,
374 ((adv7511->cec_clk_freq / 750000) - 1) << 2);
375
376 ret = cec_register_adapter(adv7511->cec_adap, dev);
377 if (ret)
378 goto err_cec_register;
379 return 0;
380
381err_cec_register:
382 cec_delete_adapter(adv7511->cec_adap);
383 adv7511->cec_adap = NULL;
384err_cec_alloc:
385 dev_info(dev, "Initializing CEC failed with error %d, disabling CEC\n",
386 ret);
387err_cec_parse_dt:
388 regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL,
389 ADV7511_CEC_CTRL_POWER_DOWN);
390 return ret == -EPROBE_DEFER ? ret : 0;
391}