Loading...
Note: File does not exist in v3.1.
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
122int 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 int irq_status = IRQ_NONE;
135
136 if (irq1 & irq_tx_mask) {
137 adv_cec_tx_raw_status(adv7511, irq1);
138 irq_status = IRQ_HANDLED;
139 }
140
141 if (!(irq1 & irq_rx_mask))
142 return irq_status;
143
144 if (regmap_read(adv7511->regmap_cec,
145 ADV7511_REG_CEC_RX_STATUS + offset, &rx_status))
146 return irq_status;
147
148 /*
149 * ADV7511_REG_CEC_RX_STATUS[5:0] contains the reception order of RX
150 * buffers 0, 1, and 2 in bits [1:0], [3:2], and [5:4] respectively.
151 * The values are to be interpreted as follows:
152 *
153 * 0 = buffer unused
154 * 1 = buffer contains oldest received frame (if applicable)
155 * 2 = buffer contains second oldest received frame (if applicable)
156 * 3 = buffer contains third oldest received frame (if applicable)
157 *
158 * Fill rx_order with the sequence of RX buffer indices to
159 * read from in order, where -1 indicates that there are no
160 * more buffers to process.
161 */
162 for (i = 0; i < 3; i++) {
163 unsigned int timestamp = (rx_status >> (2 * i)) & 0x3;
164
165 if (timestamp)
166 rx_order[timestamp - 1] = i;
167 }
168
169 /* Read CEC RX buffers in the appropriate order as prescribed above */
170 for (i = 0; i < 3; i++) {
171 int rx_buf = rx_order[i];
172
173 if (rx_buf < 0)
174 break;
175
176 adv7511_cec_rx(adv7511, rx_buf);
177 }
178
179 return IRQ_HANDLED;
180}
181
182static int adv7511_cec_adap_enable(struct cec_adapter *adap, bool enable)
183{
184 struct adv7511 *adv7511 = cec_get_drvdata(adap);
185 unsigned int offset = adv7511->info->reg_cec_offset;
186
187 if (adv7511->i2c_cec == NULL)
188 return -EIO;
189
190 if (!adv7511->cec_enabled_adap && enable) {
191 /* power up cec section */
192 regmap_update_bits(adv7511->regmap_cec,
193 ADV7511_REG_CEC_CLK_DIV + offset,
194 0x03, 0x01);
195 /* non-legacy mode and clear all rx buffers */
196 regmap_write(adv7511->regmap_cec,
197 ADV7511_REG_CEC_RX_BUFFERS + offset, 0x0f);
198 regmap_write(adv7511->regmap_cec,
199 ADV7511_REG_CEC_RX_BUFFERS + offset, 0x08);
200 /* initially disable tx */
201 regmap_update_bits(adv7511->regmap_cec,
202 ADV7511_REG_CEC_TX_ENABLE + offset, 1, 0);
203 /* enabled irqs: */
204 /* tx: ready */
205 /* tx: arbitration lost */
206 /* tx: retry timeout */
207 /* rx: ready 1-3 */
208 regmap_update_bits(adv7511->regmap,
209 ADV7511_REG_INT_ENABLE(1), 0x3f,
210 ADV7511_INT1_CEC_MASK);
211 } else if (adv7511->cec_enabled_adap && !enable) {
212 regmap_update_bits(adv7511->regmap,
213 ADV7511_REG_INT_ENABLE(1), 0x3f, 0);
214 /* disable address mask 1-3 */
215 regmap_update_bits(adv7511->regmap_cec,
216 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
217 0x70, 0x00);
218 /* power down cec section */
219 regmap_update_bits(adv7511->regmap_cec,
220 ADV7511_REG_CEC_CLK_DIV + offset,
221 0x03, 0x00);
222 adv7511->cec_valid_addrs = 0;
223 }
224 adv7511->cec_enabled_adap = enable;
225 return 0;
226}
227
228static int adv7511_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
229{
230 struct adv7511 *adv7511 = cec_get_drvdata(adap);
231 unsigned int offset = adv7511->info->reg_cec_offset;
232 unsigned int i, free_idx = ADV7511_MAX_ADDRS;
233
234 if (!adv7511->cec_enabled_adap)
235 return addr == CEC_LOG_ADDR_INVALID ? 0 : -EIO;
236
237 if (addr == CEC_LOG_ADDR_INVALID) {
238 regmap_update_bits(adv7511->regmap_cec,
239 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
240 0x70, 0);
241 adv7511->cec_valid_addrs = 0;
242 return 0;
243 }
244
245 for (i = 0; i < ADV7511_MAX_ADDRS; i++) {
246 bool is_valid = adv7511->cec_valid_addrs & (1 << i);
247
248 if (free_idx == ADV7511_MAX_ADDRS && !is_valid)
249 free_idx = i;
250 if (is_valid && adv7511->cec_addr[i] == addr)
251 return 0;
252 }
253 if (i == ADV7511_MAX_ADDRS) {
254 i = free_idx;
255 if (i == ADV7511_MAX_ADDRS)
256 return -ENXIO;
257 }
258 adv7511->cec_addr[i] = addr;
259 adv7511->cec_valid_addrs |= 1 << i;
260
261 switch (i) {
262 case 0:
263 /* enable address mask 0 */
264 regmap_update_bits(adv7511->regmap_cec,
265 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
266 0x10, 0x10);
267 /* set address for mask 0 */
268 regmap_update_bits(adv7511->regmap_cec,
269 ADV7511_REG_CEC_LOG_ADDR_0_1 + offset,
270 0x0f, addr);
271 break;
272 case 1:
273 /* enable address mask 1 */
274 regmap_update_bits(adv7511->regmap_cec,
275 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
276 0x20, 0x20);
277 /* set address for mask 1 */
278 regmap_update_bits(adv7511->regmap_cec,
279 ADV7511_REG_CEC_LOG_ADDR_0_1 + offset,
280 0xf0, addr << 4);
281 break;
282 case 2:
283 /* enable address mask 2 */
284 regmap_update_bits(adv7511->regmap_cec,
285 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
286 0x40, 0x40);
287 /* set address for mask 1 */
288 regmap_update_bits(adv7511->regmap_cec,
289 ADV7511_REG_CEC_LOG_ADDR_2 + offset,
290 0x0f, addr);
291 break;
292 }
293 return 0;
294}
295
296static int adv7511_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
297 u32 signal_free_time, struct cec_msg *msg)
298{
299 struct adv7511 *adv7511 = cec_get_drvdata(adap);
300 unsigned int offset = adv7511->info->reg_cec_offset;
301 u8 len = msg->len;
302 unsigned int i;
303
304 /*
305 * The number of retries is the number of attempts - 1, but retry
306 * at least once. It's not clear if a value of 0 is allowed, so
307 * let's do at least one retry.
308 */
309 regmap_update_bits(adv7511->regmap_cec,
310 ADV7511_REG_CEC_TX_RETRY + offset,
311 0x70, max(1, attempts - 1) << 4);
312
313 /* blocking, clear cec tx irq status */
314 regmap_update_bits(adv7511->regmap, ADV7511_REG_INT(1), 0x38, 0x38);
315
316 /* write data */
317 for (i = 0; i < len; i++)
318 regmap_write(adv7511->regmap_cec,
319 i + ADV7511_REG_CEC_TX_FRAME_HDR + offset,
320 msg->msg[i]);
321
322 /* set length (data + header) */
323 regmap_write(adv7511->regmap_cec,
324 ADV7511_REG_CEC_TX_FRAME_LEN + offset, len);
325 /* start transmit, enable tx */
326 regmap_write(adv7511->regmap_cec,
327 ADV7511_REG_CEC_TX_ENABLE + offset, 0x01);
328 return 0;
329}
330
331static const struct cec_adap_ops adv7511_cec_adap_ops = {
332 .adap_enable = adv7511_cec_adap_enable,
333 .adap_log_addr = adv7511_cec_adap_log_addr,
334 .adap_transmit = adv7511_cec_adap_transmit,
335};
336
337static int adv7511_cec_parse_dt(struct device *dev, struct adv7511 *adv7511)
338{
339 adv7511->cec_clk = devm_clk_get(dev, "cec");
340 if (IS_ERR(adv7511->cec_clk)) {
341 int ret = PTR_ERR(adv7511->cec_clk);
342
343 adv7511->cec_clk = NULL;
344 return ret;
345 }
346 clk_prepare_enable(adv7511->cec_clk);
347 adv7511->cec_clk_freq = clk_get_rate(adv7511->cec_clk);
348 return 0;
349}
350
351int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
352{
353 unsigned int offset = adv7511->info->reg_cec_offset;
354 int ret = adv7511_cec_parse_dt(dev, adv7511);
355
356 if (ret)
357 goto err_cec_parse_dt;
358
359 adv7511->cec_adap = cec_allocate_adapter(&adv7511_cec_adap_ops,
360 adv7511, dev_name(dev), CEC_CAP_DEFAULTS, ADV7511_MAX_ADDRS);
361 if (IS_ERR(adv7511->cec_adap)) {
362 ret = PTR_ERR(adv7511->cec_adap);
363 goto err_cec_alloc;
364 }
365
366 regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL, 0);
367 /* cec soft reset */
368 regmap_write(adv7511->regmap_cec,
369 ADV7511_REG_CEC_SOFT_RESET + offset, 0x01);
370 regmap_write(adv7511->regmap_cec,
371 ADV7511_REG_CEC_SOFT_RESET + offset, 0x00);
372
373 /* non-legacy mode - use all three RX buffers */
374 regmap_write(adv7511->regmap_cec,
375 ADV7511_REG_CEC_RX_BUFFERS + offset, 0x08);
376
377 regmap_write(adv7511->regmap_cec,
378 ADV7511_REG_CEC_CLK_DIV + offset,
379 ((adv7511->cec_clk_freq / 750000) - 1) << 2);
380
381 ret = cec_register_adapter(adv7511->cec_adap, dev);
382 if (ret)
383 goto err_cec_register;
384 return 0;
385
386err_cec_register:
387 cec_delete_adapter(adv7511->cec_adap);
388 adv7511->cec_adap = NULL;
389err_cec_alloc:
390 dev_info(dev, "Initializing CEC failed with error %d, disabling CEC\n",
391 ret);
392err_cec_parse_dt:
393 regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL,
394 ADV7511_CEC_CTRL_POWER_DOWN);
395 return ret == -EPROBE_DEFER ? ret : 0;
396}