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 <drm/display/drm_hdmi_cec_helper.h>
16
17#include "adv7511.h"
18
19static const u8 ADV7511_REG_CEC_RX_FRAME_HDR[] = {
20 ADV7511_REG_CEC_RX1_FRAME_HDR,
21 ADV7511_REG_CEC_RX2_FRAME_HDR,
22 ADV7511_REG_CEC_RX3_FRAME_HDR,
23};
24
25static const u8 ADV7511_REG_CEC_RX_FRAME_LEN[] = {
26 ADV7511_REG_CEC_RX1_FRAME_LEN,
27 ADV7511_REG_CEC_RX2_FRAME_LEN,
28 ADV7511_REG_CEC_RX3_FRAME_LEN,
29};
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 ADV7511_INT1_CEC_RX_READY2 | ADV7511_INT1_CEC_RX_READY3)
35
36static void adv_cec_tx_raw_status(struct adv7511 *adv7511, u8 tx_raw_status)
37{
38 unsigned int offset = adv7511->info->reg_cec_offset;
39 unsigned int val;
40
41 if (regmap_read(map: adv7511->regmap_cec,
42 ADV7511_REG_CEC_TX_ENABLE + offset, val: &val))
43 return;
44
45 if ((val & 0x01) == 0)
46 return;
47
48 if (tx_raw_status & ADV7511_INT1_CEC_TX_ARBIT_LOST) {
49 drm_connector_hdmi_cec_transmit_attempt_done(connector: adv7511->cec_connector,
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(map: adv7511->regmap_cec,
66 ADV7511_REG_CEC_TX_LOW_DRV_CNT + offset, val: &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 drm_connector_hdmi_cec_transmit_done(connector: adv7511->cec_connector, status,
78 arb_lost_cnt: 0, nack_cnt, low_drive_cnt,
79 error_cnt: err_cnt);
80 return;
81 }
82 if (tx_raw_status & ADV7511_INT1_CEC_TX_READY) {
83 drm_connector_hdmi_cec_transmit_attempt_done(connector: adv7511->cec_connector,
84 CEC_TX_STATUS_OK);
85 return;
86 }
87}
88
89static void adv7511_cec_rx(struct adv7511 *adv7511, int rx_buf)
90{
91 unsigned int offset = adv7511->info->reg_cec_offset;
92 struct cec_msg msg = {};
93 unsigned int len;
94 unsigned int val;
95 u8 i;
96
97 if (regmap_read(map: adv7511->regmap_cec,
98 reg: ADV7511_REG_CEC_RX_FRAME_LEN[rx_buf] + offset, val: &len))
99 return;
100
101 msg.len = len & 0x1f;
102
103 if (msg.len > 16)
104 msg.len = 16;
105
106 if (!msg.len)
107 return;
108
109 for (i = 0; i < msg.len; i++) {
110 regmap_read(map: adv7511->regmap_cec,
111 reg: i + ADV7511_REG_CEC_RX_FRAME_HDR[rx_buf] + offset,
112 val: &val);
113 msg.msg[i] = val;
114 }
115
116 /* Toggle RX Ready Clear bit to re-enable this RX buffer */
117 regmap_update_bits(map: adv7511->regmap_cec,
118 ADV7511_REG_CEC_RX_BUFFERS + offset, BIT(rx_buf),
119 BIT(rx_buf));
120 regmap_update_bits(map: adv7511->regmap_cec,
121 ADV7511_REG_CEC_RX_BUFFERS + offset, BIT(rx_buf), val: 0);
122
123 drm_connector_hdmi_cec_received_msg(connector: adv7511->cec_connector, msg: &msg);
124}
125
126int adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1)
127{
128 unsigned int offset = adv7511->info->reg_cec_offset;
129 const u32 irq_tx_mask = ADV7511_INT1_CEC_TX_READY |
130 ADV7511_INT1_CEC_TX_ARBIT_LOST |
131 ADV7511_INT1_CEC_TX_RETRY_TIMEOUT;
132 const u32 irq_rx_mask = ADV7511_INT1_CEC_RX_READY1 |
133 ADV7511_INT1_CEC_RX_READY2 |
134 ADV7511_INT1_CEC_RX_READY3;
135 unsigned int rx_status;
136 int rx_order[3] = { -1, -1, -1 };
137 int i;
138 int irq_status = IRQ_NONE;
139
140 if (irq1 & irq_tx_mask) {
141 adv_cec_tx_raw_status(adv7511, tx_raw_status: irq1);
142 irq_status = IRQ_HANDLED;
143 }
144
145 if (!(irq1 & irq_rx_mask))
146 return irq_status;
147
148 if (regmap_read(map: adv7511->regmap_cec,
149 ADV7511_REG_CEC_RX_STATUS + offset, val: &rx_status))
150 return irq_status;
151
152 /*
153 * ADV7511_REG_CEC_RX_STATUS[5:0] contains the reception order of RX
154 * buffers 0, 1, and 2 in bits [1:0], [3:2], and [5:4] respectively.
155 * The values are to be interpreted as follows:
156 *
157 * 0 = buffer unused
158 * 1 = buffer contains oldest received frame (if applicable)
159 * 2 = buffer contains second oldest received frame (if applicable)
160 * 3 = buffer contains third oldest received frame (if applicable)
161 *
162 * Fill rx_order with the sequence of RX buffer indices to
163 * read from in order, where -1 indicates that there are no
164 * more buffers to process.
165 */
166 for (i = 0; i < 3; i++) {
167 unsigned int timestamp = (rx_status >> (2 * i)) & 0x3;
168
169 if (timestamp)
170 rx_order[timestamp - 1] = i;
171 }
172
173 /* Read CEC RX buffers in the appropriate order as prescribed above */
174 for (i = 0; i < 3; i++) {
175 int rx_buf = rx_order[i];
176
177 if (rx_buf < 0)
178 break;
179
180 adv7511_cec_rx(adv7511, rx_buf);
181 }
182
183 return IRQ_HANDLED;
184}
185
186int adv7511_cec_enable(struct drm_bridge *bridge, bool enable)
187{
188 struct adv7511 *adv7511 = bridge_to_adv7511(bridge);
189 unsigned int offset = adv7511->info->reg_cec_offset;
190
191 if (adv7511->i2c_cec == NULL)
192 return -EIO;
193
194 if (!adv7511->cec_enabled_adap && enable) {
195 /* power up cec section */
196 regmap_update_bits(map: adv7511->regmap_cec,
197 ADV7511_REG_CEC_CLK_DIV + offset,
198 mask: 0x03, val: 0x01);
199 /* non-legacy mode and clear all rx buffers */
200 regmap_write(map: adv7511->regmap_cec,
201 ADV7511_REG_CEC_RX_BUFFERS + offset, val: 0x0f);
202 regmap_write(map: adv7511->regmap_cec,
203 ADV7511_REG_CEC_RX_BUFFERS + offset, val: 0x08);
204 /* initially disable tx */
205 regmap_update_bits(map: adv7511->regmap_cec,
206 ADV7511_REG_CEC_TX_ENABLE + offset, mask: 1, val: 0);
207 /* enabled irqs: */
208 /* tx: ready */
209 /* tx: arbitration lost */
210 /* tx: retry timeout */
211 /* rx: ready 1-3 */
212 regmap_update_bits(map: adv7511->regmap,
213 ADV7511_REG_INT_ENABLE(1), mask: 0x3f,
214 ADV7511_INT1_CEC_MASK);
215 } else if (adv7511->cec_enabled_adap && !enable) {
216 regmap_update_bits(map: adv7511->regmap,
217 ADV7511_REG_INT_ENABLE(1), mask: 0x3f, val: 0);
218 /* disable address mask 1-3 */
219 regmap_update_bits(map: adv7511->regmap_cec,
220 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
221 mask: 0x70, val: 0x00);
222 /* power down cec section */
223 regmap_update_bits(map: adv7511->regmap_cec,
224 ADV7511_REG_CEC_CLK_DIV + offset,
225 mask: 0x03, val: 0x00);
226 adv7511->cec_valid_addrs = 0;
227 }
228 adv7511->cec_enabled_adap = enable;
229 return 0;
230}
231
232int adv7511_cec_log_addr(struct drm_bridge *bridge, u8 addr)
233{
234 struct adv7511 *adv7511 = bridge_to_adv7511(bridge);
235 unsigned int offset = adv7511->info->reg_cec_offset;
236 unsigned int i, free_idx = ADV7511_MAX_ADDRS;
237
238 if (!adv7511->cec_enabled_adap)
239 return addr == CEC_LOG_ADDR_INVALID ? 0 : -EIO;
240
241 if (addr == CEC_LOG_ADDR_INVALID) {
242 regmap_update_bits(map: adv7511->regmap_cec,
243 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
244 mask: 0x70, val: 0);
245 adv7511->cec_valid_addrs = 0;
246 return 0;
247 }
248
249 for (i = 0; i < ADV7511_MAX_ADDRS; i++) {
250 bool is_valid = adv7511->cec_valid_addrs & (1 << i);
251
252 if (free_idx == ADV7511_MAX_ADDRS && !is_valid)
253 free_idx = i;
254 if (is_valid && adv7511->cec_addr[i] == addr)
255 return 0;
256 }
257 if (i == ADV7511_MAX_ADDRS) {
258 i = free_idx;
259 if (i == ADV7511_MAX_ADDRS)
260 return -ENXIO;
261 }
262 adv7511->cec_addr[i] = addr;
263 adv7511->cec_valid_addrs |= 1 << i;
264
265 switch (i) {
266 case 0:
267 /* enable address mask 0 */
268 regmap_update_bits(map: adv7511->regmap_cec,
269 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
270 mask: 0x10, val: 0x10);
271 /* set address for mask 0 */
272 regmap_update_bits(map: adv7511->regmap_cec,
273 ADV7511_REG_CEC_LOG_ADDR_0_1 + offset,
274 mask: 0x0f, val: addr);
275 break;
276 case 1:
277 /* enable address mask 1 */
278 regmap_update_bits(map: adv7511->regmap_cec,
279 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
280 mask: 0x20, val: 0x20);
281 /* set address for mask 1 */
282 regmap_update_bits(map: adv7511->regmap_cec,
283 ADV7511_REG_CEC_LOG_ADDR_0_1 + offset,
284 mask: 0xf0, val: addr << 4);
285 break;
286 case 2:
287 /* enable address mask 2 */
288 regmap_update_bits(map: adv7511->regmap_cec,
289 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
290 mask: 0x40, val: 0x40);
291 /* set address for mask 1 */
292 regmap_update_bits(map: adv7511->regmap_cec,
293 ADV7511_REG_CEC_LOG_ADDR_2 + offset,
294 mask: 0x0f, val: addr);
295 break;
296 }
297 return 0;
298}
299
300int adv7511_cec_transmit(struct drm_bridge *bridge, u8 attempts,
301 u32 signal_free_time, struct cec_msg *msg)
302{
303 struct adv7511 *adv7511 = bridge_to_adv7511(bridge);
304 unsigned int offset = adv7511->info->reg_cec_offset;
305 u8 len = msg->len;
306 unsigned int i;
307
308 /*
309 * The number of retries is the number of attempts - 1, but retry
310 * at least once. It's not clear if a value of 0 is allowed, so
311 * let's do at least one retry.
312 */
313 regmap_update_bits(map: adv7511->regmap_cec,
314 ADV7511_REG_CEC_TX_RETRY + offset,
315 mask: 0x70, max(1, attempts - 1) << 4);
316
317 /* blocking, clear cec tx irq status */
318 regmap_update_bits(map: adv7511->regmap, ADV7511_REG_INT(1), mask: 0x38, val: 0x38);
319
320 /* write data */
321 for (i = 0; i < len; i++)
322 regmap_write(map: adv7511->regmap_cec,
323 reg: i + ADV7511_REG_CEC_TX_FRAME_HDR + offset,
324 val: msg->msg[i]);
325
326 /* set length (data + header) */
327 regmap_write(map: adv7511->regmap_cec,
328 ADV7511_REG_CEC_TX_FRAME_LEN + offset, val: len);
329 /* start transmit, enable tx */
330 regmap_write(map: adv7511->regmap_cec,
331 ADV7511_REG_CEC_TX_ENABLE + offset, val: 0x01);
332 return 0;
333}
334
335static int adv7511_cec_parse_dt(struct device *dev, struct adv7511 *adv7511)
336{
337 adv7511->cec_clk = devm_clk_get(dev, id: "cec");
338 if (IS_ERR(ptr: adv7511->cec_clk)) {
339 int ret = PTR_ERR(ptr: adv7511->cec_clk);
340
341 adv7511->cec_clk = NULL;
342 return ret;
343 }
344 clk_prepare_enable(clk: adv7511->cec_clk);
345 adv7511->cec_clk_freq = clk_get_rate(clk: adv7511->cec_clk);
346 return 0;
347}
348
349int adv7511_cec_init(struct drm_bridge *bridge,
350 struct drm_connector *connector)
351{
352 struct adv7511 *adv7511 = bridge_to_adv7511(bridge);
353 struct device *dev = &adv7511->i2c_main->dev;
354 unsigned int offset = adv7511->info->reg_cec_offset;
355 int ret = adv7511_cec_parse_dt(dev, adv7511);
356
357 if (ret)
358 goto err_cec_parse_dt;
359
360 adv7511->cec_connector = connector;
361
362 regmap_write(map: adv7511->regmap, ADV7511_REG_CEC_CTRL, val: 0);
363 /* cec soft reset */
364 regmap_write(map: adv7511->regmap_cec,
365 ADV7511_REG_CEC_SOFT_RESET + offset, val: 0x01);
366 regmap_write(map: adv7511->regmap_cec,
367 ADV7511_REG_CEC_SOFT_RESET + offset, val: 0x00);
368
369 /* non-legacy mode - use all three RX buffers */
370 regmap_write(map: adv7511->regmap_cec,
371 ADV7511_REG_CEC_RX_BUFFERS + offset, val: 0x08);
372
373 regmap_write(map: adv7511->regmap_cec,
374 ADV7511_REG_CEC_CLK_DIV + offset,
375 val: ((adv7511->cec_clk_freq / 750000) - 1) << 2);
376
377 return 0;
378
379err_cec_parse_dt:
380 regmap_write(map: adv7511->regmap, ADV7511_REG_CEC_CTRL,
381 ADV7511_CEC_CTRL_POWER_DOWN);
382 return ret == -EPROBE_DEFER ? ret : 0;
383}
384

source code of linux/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c