Linux Audio

Check our new training course

Loading...
v6.13.7
  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}
v5.9
 
  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}