xref: /linux/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
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 
17 static 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 
23 static 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 
34 static 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 
85 static 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 
122 int 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 
182 static 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 
228 static 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 
296 static 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 
331 static 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 
337 static 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 
351 int 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 
386 err_cec_register:
387 	cec_delete_adapter(adv7511->cec_adap);
388 	adv7511->cec_adap = NULL;
389 err_cec_alloc:
390 	dev_info(dev, "Initializing CEC failed with error %d, disabling CEC\n",
391 		 ret);
392 err_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 }
397