• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
adv_cec_tx_raw_status(struct adv7511 * adv7511,u8 tx_raw_status)35 static 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 
adv7511_cec_irq_process(struct adv7511 * adv7511,unsigned int irq1)87 void 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 
adv7511_cec_adap_enable(struct cec_adapter * adap,bool enable)131 static 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 
adv7511_cec_adap_log_addr(struct cec_adapter * adap,u8 addr)178 static 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 
adv7511_cec_adap_transmit(struct cec_adapter * adap,u8 attempts,u32 signal_free_time,struct cec_msg * msg)247 static 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 
283 static 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 
adv7511_cec_parse_dt(struct device * dev,struct adv7511 * adv7511)289 static 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 
adv7511_cec_init(struct device * dev,struct adv7511 * adv7511)303 int 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, 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 
339 err_cec_register:
340 	cec_delete_adapter(adv7511->cec_adap);
341 	adv7511->cec_adap = NULL;
342 err_cec_alloc:
343 	dev_info(dev, "Initializing CEC failed with error %d, disabling CEC\n",
344 		 ret);
345 err_cec_parse_dt:
346 	regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL,
347 		     ADV7511_CEC_CTRL_POWER_DOWN);
348 	return ret == -EPROBE_DEFER ? ret : 0;
349 }
350