2 * adv7511_cec.c - Analog Devices ADV7511/33 cec driver
4 * Copyright 2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
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.
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
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>
27 #include <media/cec.h>
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)
35 static void adv_cec_tx_raw_status(struct adv7511
*adv7511
, u8 tx_raw_status
)
37 unsigned int offset
= adv7511
->type
== ADV7533
?
38 ADV7533_REG_CEC_OFFSET
: 0;
41 if (regmap_read(adv7511
->regmap_cec
,
42 ADV7511_REG_CEC_TX_ENABLE
+ offset
, &val
))
45 if ((val
& 0x01) == 0)
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
);
53 if (tx_raw_status
& ADV7511_INT1_CEC_TX_RETRY_TIMEOUT
) {
61 * We set this status bit since this hardware performs
64 status
= CEC_TX_STATUS_MAX_RETRIES
;
65 if (regmap_read(adv7511
->regmap_cec
,
66 ADV7511_REG_CEC_TX_LOW_DRV_CNT
+ offset
, &cnt
)) {
68 status
|= CEC_TX_STATUS_ERROR
;
72 status
|= CEC_TX_STATUS_NACK
;
73 low_drive_cnt
= cnt
>> 4;
75 status
|= CEC_TX_STATUS_LOW_DRIVE
;
77 cec_transmit_done(adv7511
->cec_adap
, status
,
78 0, nack_cnt
, low_drive_cnt
, err_cnt
);
81 if (tx_raw_status
& ADV7511_INT1_CEC_TX_READY
) {
82 cec_transmit_attempt_done(adv7511
->cec_adap
, CEC_TX_STATUS_OK
);
87 void adv7511_cec_irq_process(struct adv7511
*adv7511
, unsigned int irq1
)
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
= {};
99 if (irq1
& irq_tx_mask
)
100 adv_cec_tx_raw_status(adv7511
, irq1
);
102 if (!(irq1
& ADV7511_INT1_CEC_RX_READY1
))
105 if (regmap_read(adv7511
->regmap_cec
,
106 ADV7511_REG_CEC_RX_FRAME_LEN
+ offset
, &len
))
109 msg
.len
= len
& 0x1f;
117 for (i
= 0; i
< msg
.len
; i
++) {
118 regmap_read(adv7511
->regmap_cec
,
119 i
+ ADV7511_REG_CEC_RX_FRAME_HDR
+ offset
, &val
);
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
);
131 static int adv7511_cec_adap_enable(struct cec_adapter
*adap
, bool enable
)
133 struct adv7511
*adv7511
= cec_get_drvdata(adap
);
134 unsigned int offset
= adv7511
->type
== ADV7533
?
135 ADV7533_REG_CEC_OFFSET
: 0;
137 if (adv7511
->i2c_cec
== NULL
)
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
,
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);
155 /* tx: arbitration lost */
156 /* tx: retry timeout */
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
,
168 /* power down cec section */
169 regmap_update_bits(adv7511
->regmap_cec
,
170 ADV7511_REG_CEC_CLK_DIV
+ offset
,
172 adv7511
->cec_valid_addrs
= 0;
174 adv7511
->cec_enabled_adap
= enable
;
178 static int adv7511_cec_adap_log_addr(struct cec_adapter
*adap
, u8 addr
)
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
;
185 if (!adv7511
->cec_enabled_adap
)
186 return addr
== CEC_LOG_ADDR_INVALID
? 0 : -EIO
;
188 if (addr
== CEC_LOG_ADDR_INVALID
) {
189 regmap_update_bits(adv7511
->regmap_cec
,
190 ADV7511_REG_CEC_LOG_ADDR_MASK
+ offset
,
192 adv7511
->cec_valid_addrs
= 0;
196 for (i
= 0; i
< ADV7511_MAX_ADDRS
; i
++) {
197 bool is_valid
= adv7511
->cec_valid_addrs
& (1 << i
);
199 if (free_idx
== ADV7511_MAX_ADDRS
&& !is_valid
)
201 if (is_valid
&& adv7511
->cec_addr
[i
] == addr
)
204 if (i
== ADV7511_MAX_ADDRS
) {
206 if (i
== ADV7511_MAX_ADDRS
)
209 adv7511
->cec_addr
[i
] = addr
;
210 adv7511
->cec_valid_addrs
|= 1 << i
;
214 /* enable address mask 0 */
215 regmap_update_bits(adv7511
->regmap_cec
,
216 ADV7511_REG_CEC_LOG_ADDR_MASK
+ offset
,
218 /* set address for mask 0 */
219 regmap_update_bits(adv7511
->regmap_cec
,
220 ADV7511_REG_CEC_LOG_ADDR_0_1
+ offset
,
224 /* enable address mask 1 */
225 regmap_update_bits(adv7511
->regmap_cec
,
226 ADV7511_REG_CEC_LOG_ADDR_MASK
+ offset
,
228 /* set address for mask 1 */
229 regmap_update_bits(adv7511
->regmap_cec
,
230 ADV7511_REG_CEC_LOG_ADDR_0_1
+ offset
,
234 /* enable address mask 2 */
235 regmap_update_bits(adv7511
->regmap_cec
,
236 ADV7511_REG_CEC_LOG_ADDR_MASK
+ offset
,
238 /* set address for mask 1 */
239 regmap_update_bits(adv7511
->regmap_cec
,
240 ADV7511_REG_CEC_LOG_ADDR_2
+ offset
,
247 static int adv7511_cec_adap_transmit(struct cec_adapter
*adap
, u8 attempts
,
248 u32 signal_free_time
, struct cec_msg
*msg
)
250 struct adv7511
*adv7511
= cec_get_drvdata(adap
);
251 unsigned int offset
= adv7511
->type
== ADV7533
?
252 ADV7533_REG_CEC_OFFSET
: 0;
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.
261 regmap_update_bits(adv7511
->regmap_cec
,
262 ADV7511_REG_CEC_TX_RETRY
+ offset
,
263 0x70, max(1, attempts
- 1) << 4);
265 /* blocking, clear cec tx irq status */
266 regmap_update_bits(adv7511
->regmap
, ADV7511_REG_INT(1), 0x38, 0x38);
269 for (i
= 0; i
< len
; i
++)
270 regmap_write(adv7511
->regmap_cec
,
271 i
+ ADV7511_REG_CEC_TX_FRAME_HDR
+ offset
,
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);
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
,
289 static int adv7511_cec_parse_dt(struct device
*dev
, struct adv7511
*adv7511
)
291 adv7511
->cec_clk
= devm_clk_get(dev
, "cec");
292 if (IS_ERR(adv7511
->cec_clk
)) {
293 int ret
= PTR_ERR(adv7511
->cec_clk
);
295 adv7511
->cec_clk
= NULL
;
298 clk_prepare_enable(adv7511
->cec_clk
);
299 adv7511
->cec_clk_freq
= clk_get_rate(adv7511
->cec_clk
);
303 int adv7511_cec_init(struct device
*dev
, struct adv7511
*adv7511
)
305 unsigned int offset
= adv7511
->type
== ADV7533
?
306 ADV7533_REG_CEC_OFFSET
: 0;
307 int ret
= adv7511_cec_parse_dt(dev
, adv7511
);
310 goto err_cec_parse_dt
;
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
);
319 regmap_write(adv7511
->regmap
, ADV7511_REG_CEC_CTRL
+ offset
, 0);
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);
327 regmap_write(adv7511
->regmap_cec
,
328 ADV7511_REG_CEC_RX_BUFFERS
+ offset
, 0x00);
330 regmap_write(adv7511
->regmap_cec
,
331 ADV7511_REG_CEC_CLK_DIV
+ offset
,
332 ((adv7511
->cec_clk_freq
/ 750000) - 1) << 2);
334 ret
= cec_register_adapter(adv7511
->cec_adap
, dev
);
336 goto err_cec_register
;
340 cec_delete_adapter(adv7511
->cec_adap
);
341 adv7511
->cec_adap
= NULL
;
343 dev_info(dev
, "Initializing CEC failed with error %d, disabling CEC\n",
346 regmap_write(adv7511
->regmap
, ADV7511_REG_CEC_CTRL
+ offset
,
347 ADV7511_CEC_CTRL_POWER_DOWN
);
348 return ret
== -EPROBE_DEFER
? ret
: 0;