1 // SPDX-License-Identifier: GPL-2.0-only
3 * adv7511_cec.c - Analog Devices ADV7511/33 cec driver
5 * Copyright 2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
8 #include <linux/device.h>
9 #include <linux/module.h>
10 #include <linux/of_device.h>
11 #include <linux/slab.h>
12 #include <linux/clk.h>
14 #include <media/cec.h>
18 #define ADV7511_INT1_CEC_MASK \
19 (ADV7511_INT1_CEC_TX_READY | ADV7511_INT1_CEC_TX_ARBIT_LOST | \
20 ADV7511_INT1_CEC_TX_RETRY_TIMEOUT | ADV7511_INT1_CEC_RX_READY1 | \
21 ADV7511_INT1_CEC_RX_READY2 | ADV7511_INT1_CEC_RX_READY3)
23 static void adv_cec_tx_raw_status(struct adv7511 *adv7511, u8 tx_raw_status)
25 unsigned int offset = adv7511->reg_cec_offset;
28 if (regmap_read(adv7511->regmap_cec,
29 ADV7511_REG_CEC_TX_ENABLE + offset, &val))
32 if ((val & 0x01) == 0)
35 if (tx_raw_status & ADV7511_INT1_CEC_TX_ARBIT_LOST) {
36 cec_transmit_attempt_done(adv7511->cec_adap,
37 CEC_TX_STATUS_ARB_LOST);
40 if (tx_raw_status & ADV7511_INT1_CEC_TX_RETRY_TIMEOUT) {
48 * We set this status bit since this hardware performs
51 status = CEC_TX_STATUS_MAX_RETRIES;
52 if (regmap_read(adv7511->regmap_cec,
53 ADV7511_REG_CEC_TX_LOW_DRV_CNT + offset, &cnt)) {
55 status |= CEC_TX_STATUS_ERROR;
59 status |= CEC_TX_STATUS_NACK;
60 low_drive_cnt = cnt >> 4;
62 status |= CEC_TX_STATUS_LOW_DRIVE;
64 cec_transmit_done(adv7511->cec_adap, status,
65 0, nack_cnt, low_drive_cnt, err_cnt);
68 if (tx_raw_status & ADV7511_INT1_CEC_TX_READY) {
69 cec_transmit_attempt_done(adv7511->cec_adap, CEC_TX_STATUS_OK);
74 static void adv7511_cec_rx(struct adv7511 *adv7511, int rx_buf)
76 unsigned int offset = adv7511->reg_cec_offset;
77 struct cec_msg msg = {};
82 if (regmap_read(adv7511->regmap_cec,
83 ADV7511_REG_CEC_RX_FRAME_LEN[rx_buf] + offset, &len))
94 for (i = 0; i < msg.len; i++) {
95 regmap_read(adv7511->regmap_cec,
96 i + ADV7511_REG_CEC_RX_FRAME_HDR[rx_buf] + offset,
101 /* Toggle RX Ready Clear bit to re-enable this RX buffer */
102 regmap_update_bits(adv7511->regmap_cec,
103 ADV7511_REG_CEC_RX_BUFFERS + offset, BIT(rx_buf),
105 regmap_update_bits(adv7511->regmap_cec,
106 ADV7511_REG_CEC_RX_BUFFERS + offset, BIT(rx_buf), 0);
108 cec_received_msg(adv7511->cec_adap, &msg);
111 void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1)
113 unsigned int offset = adv7511->reg_cec_offset;
114 const u32 irq_tx_mask = ADV7511_INT1_CEC_TX_READY |
115 ADV7511_INT1_CEC_TX_ARBIT_LOST |
116 ADV7511_INT1_CEC_TX_RETRY_TIMEOUT;
117 const u32 irq_rx_mask = ADV7511_INT1_CEC_RX_READY1 |
118 ADV7511_INT1_CEC_RX_READY2 |
119 ADV7511_INT1_CEC_RX_READY3;
120 unsigned int rx_status;
121 int rx_order[3] = { -1, -1, -1 };
124 if (irq1 & irq_tx_mask)
125 adv_cec_tx_raw_status(adv7511, irq1);
127 if (!(irq1 & irq_rx_mask))
130 if (regmap_read(adv7511->regmap_cec,
131 ADV7511_REG_CEC_RX_STATUS + offset, &rx_status))
135 * ADV7511_REG_CEC_RX_STATUS[5:0] contains the reception order of RX
136 * buffers 0, 1, and 2 in bits [1:0], [3:2], and [5:4] respectively.
137 * The values are to be interpreted as follows:
140 * 1 = buffer contains oldest received frame (if applicable)
141 * 2 = buffer contains second oldest received frame (if applicable)
142 * 3 = buffer contains third oldest received frame (if applicable)
144 * Fill rx_order with the sequence of RX buffer indices to
145 * read from in order, where -1 indicates that there are no
146 * more buffers to process.
148 for (i = 0; i < 3; i++) {
149 unsigned int timestamp = (rx_status >> (2 * i)) & 0x3;
152 rx_order[timestamp - 1] = i;
155 /* Read CEC RX buffers in the appropriate order as prescribed above */
156 for (i = 0; i < 3; i++) {
157 int rx_buf = rx_order[i];
162 adv7511_cec_rx(adv7511, rx_buf);
166 static int adv7511_cec_adap_enable(struct cec_adapter *adap, bool enable)
168 struct adv7511 *adv7511 = cec_get_drvdata(adap);
169 unsigned int offset = adv7511->reg_cec_offset;
171 if (adv7511->i2c_cec == NULL)
174 if (!adv7511->cec_enabled_adap && enable) {
175 /* power up cec section */
176 regmap_update_bits(adv7511->regmap_cec,
177 ADV7511_REG_CEC_CLK_DIV + offset,
179 /* non-legacy mode and clear all rx buffers */
180 regmap_write(adv7511->regmap_cec,
181 ADV7511_REG_CEC_RX_BUFFERS + offset, 0x0f);
182 regmap_write(adv7511->regmap_cec,
183 ADV7511_REG_CEC_RX_BUFFERS + offset, 0x08);
184 /* initially disable tx */
185 regmap_update_bits(adv7511->regmap_cec,
186 ADV7511_REG_CEC_TX_ENABLE + offset, 1, 0);
189 /* tx: arbitration lost */
190 /* tx: retry timeout */
192 regmap_update_bits(adv7511->regmap,
193 ADV7511_REG_INT_ENABLE(1), 0x3f,
194 ADV7511_INT1_CEC_MASK);
195 } else if (adv7511->cec_enabled_adap && !enable) {
196 regmap_update_bits(adv7511->regmap,
197 ADV7511_REG_INT_ENABLE(1), 0x3f, 0);
198 /* disable address mask 1-3 */
199 regmap_update_bits(adv7511->regmap_cec,
200 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
202 /* power down cec section */
203 regmap_update_bits(adv7511->regmap_cec,
204 ADV7511_REG_CEC_CLK_DIV + offset,
206 adv7511->cec_valid_addrs = 0;
208 adv7511->cec_enabled_adap = enable;
212 static int adv7511_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
214 struct adv7511 *adv7511 = cec_get_drvdata(adap);
215 unsigned int offset = adv7511->reg_cec_offset;
216 unsigned int i, free_idx = ADV7511_MAX_ADDRS;
218 if (!adv7511->cec_enabled_adap)
219 return addr == CEC_LOG_ADDR_INVALID ? 0 : -EIO;
221 if (addr == CEC_LOG_ADDR_INVALID) {
222 regmap_update_bits(adv7511->regmap_cec,
223 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
225 adv7511->cec_valid_addrs = 0;
229 for (i = 0; i < ADV7511_MAX_ADDRS; i++) {
230 bool is_valid = adv7511->cec_valid_addrs & (1 << i);
232 if (free_idx == ADV7511_MAX_ADDRS && !is_valid)
234 if (is_valid && adv7511->cec_addr[i] == addr)
237 if (i == ADV7511_MAX_ADDRS) {
239 if (i == ADV7511_MAX_ADDRS)
242 adv7511->cec_addr[i] = addr;
243 adv7511->cec_valid_addrs |= 1 << i;
247 /* enable address mask 0 */
248 regmap_update_bits(adv7511->regmap_cec,
249 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
251 /* set address for mask 0 */
252 regmap_update_bits(adv7511->regmap_cec,
253 ADV7511_REG_CEC_LOG_ADDR_0_1 + offset,
257 /* enable address mask 1 */
258 regmap_update_bits(adv7511->regmap_cec,
259 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
261 /* set address for mask 1 */
262 regmap_update_bits(adv7511->regmap_cec,
263 ADV7511_REG_CEC_LOG_ADDR_0_1 + offset,
267 /* enable address mask 2 */
268 regmap_update_bits(adv7511->regmap_cec,
269 ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
271 /* set address for mask 1 */
272 regmap_update_bits(adv7511->regmap_cec,
273 ADV7511_REG_CEC_LOG_ADDR_2 + offset,
280 static int adv7511_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
281 u32 signal_free_time, struct cec_msg *msg)
283 struct adv7511 *adv7511 = cec_get_drvdata(adap);
284 unsigned int offset = adv7511->reg_cec_offset;
289 * The number of retries is the number of attempts - 1, but retry
290 * at least once. It's not clear if a value of 0 is allowed, so
291 * let's do at least one retry.
293 regmap_update_bits(adv7511->regmap_cec,
294 ADV7511_REG_CEC_TX_RETRY + offset,
295 0x70, max(1, attempts - 1) << 4);
297 /* blocking, clear cec tx irq status */
298 regmap_update_bits(adv7511->regmap, ADV7511_REG_INT(1), 0x38, 0x38);
301 for (i = 0; i < len; i++)
302 regmap_write(adv7511->regmap_cec,
303 i + ADV7511_REG_CEC_TX_FRAME_HDR + offset,
306 /* set length (data + header) */
307 regmap_write(adv7511->regmap_cec,
308 ADV7511_REG_CEC_TX_FRAME_LEN + offset, len);
309 /* start transmit, enable tx */
310 regmap_write(adv7511->regmap_cec,
311 ADV7511_REG_CEC_TX_ENABLE + offset, 0x01);
315 static const struct cec_adap_ops adv7511_cec_adap_ops = {
316 .adap_enable = adv7511_cec_adap_enable,
317 .adap_log_addr = adv7511_cec_adap_log_addr,
318 .adap_transmit = adv7511_cec_adap_transmit,
321 static int adv7511_cec_parse_dt(struct device *dev, struct adv7511 *adv7511)
323 adv7511->cec_clk = devm_clk_get(dev, "cec");
324 if (IS_ERR(adv7511->cec_clk)) {
325 int ret = PTR_ERR(adv7511->cec_clk);
327 adv7511->cec_clk = NULL;
330 clk_prepare_enable(adv7511->cec_clk);
331 adv7511->cec_clk_freq = clk_get_rate(adv7511->cec_clk);
335 int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
337 unsigned int offset = adv7511->reg_cec_offset;
338 int ret = adv7511_cec_parse_dt(dev, adv7511);
341 goto err_cec_parse_dt;
343 adv7511->cec_adap = cec_allocate_adapter(&adv7511_cec_adap_ops,
344 adv7511, dev_name(dev), CEC_CAP_DEFAULTS, ADV7511_MAX_ADDRS);
345 if (IS_ERR(adv7511->cec_adap)) {
346 ret = PTR_ERR(adv7511->cec_adap);
350 regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset, 0);
352 regmap_write(adv7511->regmap_cec,
353 ADV7511_REG_CEC_SOFT_RESET + offset, 0x01);
354 regmap_write(adv7511->regmap_cec,
355 ADV7511_REG_CEC_SOFT_RESET + offset, 0x00);
357 /* non-legacy mode - use all three RX buffers */
358 regmap_write(adv7511->regmap_cec,
359 ADV7511_REG_CEC_RX_BUFFERS + offset, 0x08);
361 regmap_write(adv7511->regmap_cec,
362 ADV7511_REG_CEC_CLK_DIV + offset,
363 ((adv7511->cec_clk_freq / 750000) - 1) << 2);
365 ret = cec_register_adapter(adv7511->cec_adap, dev);
367 goto err_cec_register;
371 cec_delete_adapter(adv7511->cec_adap);
372 adv7511->cec_adap = NULL;
374 dev_info(dev, "Initializing CEC failed with error %d, disabling CEC\n",
377 regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset,
378 ADV7511_CEC_CTRL_POWER_DOWN);
379 return ret == -EPROBE_DEFER ? ret : 0;