2 * Tegra CEC implementation
4 * The original 3.10 CEC driver using a custom API:
6 * Copyright (c) 2012-2015, NVIDIA CORPORATION. All rights reserved.
8 * Conversion to the CEC framework and to the mainline kernel:
10 * Copyright 2016-2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms and conditions of the GNU General Public License,
14 * version 2, as published by the Free Software Foundation.
16 * This program is distributed in the hope it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include <linux/module.h>
26 #include <linux/kernel.h>
27 #include <linux/err.h>
28 #include <linux/errno.h>
29 #include <linux/interrupt.h>
30 #include <linux/slab.h>
32 #include <linux/clk.h>
33 #include <linux/delay.h>
36 #include <linux/of_platform.h>
37 #include <linux/platform_device.h>
38 #include <linux/clk/tegra.h>
40 #include <media/cec-notifier.h>
42 #include "tegra_cec.h"
44 #define TEGRA_CEC_NAME "tegra-cec"
47 struct cec_adapter
*adap
;
50 void __iomem
*cec_base
;
51 struct cec_notifier
*notifier
;
56 u8 rx_buf
[CEC_MAX_MSG_SIZE
];
58 u32 tx_buf
[CEC_MAX_MSG_SIZE
];
63 static inline u32
cec_read(struct tegra_cec
*cec
, u32 reg
)
65 return readl(cec
->cec_base
+ reg
);
68 static inline void cec_write(struct tegra_cec
*cec
, u32 reg
, u32 val
)
70 writel(val
, cec
->cec_base
+ reg
);
73 static void tegra_cec_error_recovery(struct tegra_cec
*cec
)
77 hw_ctrl
= cec_read(cec
, TEGRA_CEC_HW_CONTROL
);
78 cec_write(cec
, TEGRA_CEC_HW_CONTROL
, 0);
79 cec_write(cec
, TEGRA_CEC_INT_STAT
, 0xffffffff);
80 cec_write(cec
, TEGRA_CEC_HW_CONTROL
, hw_ctrl
);
83 static irqreturn_t
tegra_cec_irq_thread_handler(int irq
, void *data
)
85 struct device
*dev
= data
;
86 struct tegra_cec
*cec
= dev_get_drvdata(dev
);
89 cec_transmit_attempt_done(cec
->adap
, cec
->tx_status
);
93 struct cec_msg msg
= {};
95 msg
.len
= cec
->rx_buf_cnt
;
96 memcpy(msg
.msg
, cec
->rx_buf
, msg
.len
);
97 cec_received_msg(cec
->adap
, &msg
);
104 static irqreturn_t
tegra_cec_irq_handler(int irq
, void *data
)
106 struct device
*dev
= data
;
107 struct tegra_cec
*cec
= dev_get_drvdata(dev
);
110 status
= cec_read(cec
, TEGRA_CEC_INT_STAT
);
111 mask
= cec_read(cec
, TEGRA_CEC_INT_MASK
);
118 if (status
& TEGRA_CEC_INT_STAT_TX_REGISTER_UNDERRUN
) {
119 dev_err(dev
, "TX underrun, interrupt timing issue!\n");
121 tegra_cec_error_recovery(cec
);
122 cec_write(cec
, TEGRA_CEC_INT_MASK
,
123 mask
& ~TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY
);
126 cec
->tx_status
= CEC_TX_STATUS_ERROR
;
127 return IRQ_WAKE_THREAD
;
130 if ((status
& TEGRA_CEC_INT_STAT_TX_ARBITRATION_FAILED
) ||
131 (status
& TEGRA_CEC_INT_STAT_TX_BUS_ANOMALY_DETECTED
)) {
132 tegra_cec_error_recovery(cec
);
133 cec_write(cec
, TEGRA_CEC_INT_MASK
,
134 mask
& ~TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY
);
137 if (status
& TEGRA_CEC_INT_STAT_TX_BUS_ANOMALY_DETECTED
)
138 cec
->tx_status
= CEC_TX_STATUS_LOW_DRIVE
;
140 cec
->tx_status
= CEC_TX_STATUS_ARB_LOST
;
141 return IRQ_WAKE_THREAD
;
144 if (status
& TEGRA_CEC_INT_STAT_TX_FRAME_TRANSMITTED
) {
145 cec_write(cec
, TEGRA_CEC_INT_STAT
,
146 TEGRA_CEC_INT_STAT_TX_FRAME_TRANSMITTED
);
148 if (status
& TEGRA_CEC_INT_STAT_TX_FRAME_OR_BLOCK_NAKD
) {
149 tegra_cec_error_recovery(cec
);
152 cec
->tx_status
= CEC_TX_STATUS_NACK
;
155 cec
->tx_status
= CEC_TX_STATUS_OK
;
157 return IRQ_WAKE_THREAD
;
160 if (status
& TEGRA_CEC_INT_STAT_TX_FRAME_OR_BLOCK_NAKD
)
161 dev_warn(dev
, "TX NAKed on the fly!\n");
163 if (status
& TEGRA_CEC_INT_STAT_TX_REGISTER_EMPTY
) {
164 if (cec
->tx_buf_cur
== cec
->tx_buf_cnt
) {
165 cec_write(cec
, TEGRA_CEC_INT_MASK
,
166 mask
& ~TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY
);
168 cec_write(cec
, TEGRA_CEC_TX_REGISTER
,
169 cec
->tx_buf
[cec
->tx_buf_cur
++]);
170 cec_write(cec
, TEGRA_CEC_INT_STAT
,
171 TEGRA_CEC_INT_STAT_TX_REGISTER_EMPTY
);
175 if (status
& (TEGRA_CEC_INT_STAT_RX_REGISTER_OVERRUN
|
176 TEGRA_CEC_INT_STAT_RX_BUS_ANOMALY_DETECTED
|
177 TEGRA_CEC_INT_STAT_RX_START_BIT_DETECTED
|
178 TEGRA_CEC_INT_STAT_RX_BUS_ERROR_DETECTED
)) {
179 cec_write(cec
, TEGRA_CEC_INT_STAT
,
180 (TEGRA_CEC_INT_STAT_RX_REGISTER_OVERRUN
|
181 TEGRA_CEC_INT_STAT_RX_BUS_ANOMALY_DETECTED
|
182 TEGRA_CEC_INT_STAT_RX_START_BIT_DETECTED
|
183 TEGRA_CEC_INT_STAT_RX_BUS_ERROR_DETECTED
));
184 } else if (status
& TEGRA_CEC_INT_STAT_RX_REGISTER_FULL
) {
187 cec_write(cec
, TEGRA_CEC_INT_STAT
,
188 TEGRA_CEC_INT_STAT_RX_REGISTER_FULL
);
189 v
= cec_read(cec
, TEGRA_CEC_RX_REGISTER
);
190 if (cec
->rx_buf_cnt
< CEC_MAX_MSG_SIZE
)
191 cec
->rx_buf
[cec
->rx_buf_cnt
++] = v
& 0xff;
192 if (v
& TEGRA_CEC_RX_REGISTER_EOM
) {
194 return IRQ_WAKE_THREAD
;
201 static int tegra_cec_adap_enable(struct cec_adapter
*adap
, bool enable
)
203 struct tegra_cec
*cec
= adap
->priv
;
209 cec_write(cec
, TEGRA_CEC_HW_CONTROL
, 0);
210 cec_write(cec
, TEGRA_CEC_INT_MASK
, 0);
211 cec_write(cec
, TEGRA_CEC_INT_STAT
, 0xffffffff);
212 cec_write(cec
, TEGRA_CEC_SW_CONTROL
, 0);
217 cec_write(cec
, TEGRA_CEC_INPUT_FILTER
, (1U << 31) | 0x20);
219 cec_write(cec
, TEGRA_CEC_RX_TIMING_0
,
220 (0x7a << TEGRA_CEC_RX_TIM0_START_BIT_MAX_LO_TIME_SHIFT
) |
221 (0x6d << TEGRA_CEC_RX_TIM0_START_BIT_MIN_LO_TIME_SHIFT
) |
222 (0x93 << TEGRA_CEC_RX_TIM0_START_BIT_MAX_DURATION_SHIFT
) |
223 (0x86 << TEGRA_CEC_RX_TIM0_START_BIT_MIN_DURATION_SHIFT
));
225 cec_write(cec
, TEGRA_CEC_RX_TIMING_1
,
226 (0x35 << TEGRA_CEC_RX_TIM1_DATA_BIT_MAX_LO_TIME_SHIFT
) |
227 (0x21 << TEGRA_CEC_RX_TIM1_DATA_BIT_SAMPLE_TIME_SHIFT
) |
228 (0x56 << TEGRA_CEC_RX_TIM1_DATA_BIT_MAX_DURATION_SHIFT
) |
229 (0x40 << TEGRA_CEC_RX_TIM1_DATA_BIT_MIN_DURATION_SHIFT
));
231 cec_write(cec
, TEGRA_CEC_RX_TIMING_2
,
232 (0x50 << TEGRA_CEC_RX_TIM2_END_OF_BLOCK_TIME_SHIFT
));
234 cec_write(cec
, TEGRA_CEC_TX_TIMING_0
,
235 (0x74 << TEGRA_CEC_TX_TIM0_START_BIT_LO_TIME_SHIFT
) |
236 (0x8d << TEGRA_CEC_TX_TIM0_START_BIT_DURATION_SHIFT
) |
237 (0x08 << TEGRA_CEC_TX_TIM0_BUS_XITION_TIME_SHIFT
) |
238 (0x71 << TEGRA_CEC_TX_TIM0_BUS_ERROR_LO_TIME_SHIFT
));
240 cec_write(cec
, TEGRA_CEC_TX_TIMING_1
,
241 (0x2f << TEGRA_CEC_TX_TIM1_LO_DATA_BIT_LO_TIME_SHIFT
) |
242 (0x13 << TEGRA_CEC_TX_TIM1_HI_DATA_BIT_LO_TIME_SHIFT
) |
243 (0x4b << TEGRA_CEC_TX_TIM1_DATA_BIT_DURATION_SHIFT
) |
244 (0x21 << TEGRA_CEC_TX_TIM1_ACK_NAK_BIT_SAMPLE_TIME_SHIFT
));
246 cec_write(cec
, TEGRA_CEC_TX_TIMING_2
,
247 (0x07 << TEGRA_CEC_TX_TIM2_BUS_IDLE_TIME_ADDITIONAL_FRAME_SHIFT
) |
248 (0x05 << TEGRA_CEC_TX_TIM2_BUS_IDLE_TIME_NEW_FRAME_SHIFT
) |
249 (0x03 << TEGRA_CEC_TX_TIM2_BUS_IDLE_TIME_RETRY_FRAME_SHIFT
));
251 cec_write(cec
, TEGRA_CEC_INT_MASK
,
252 TEGRA_CEC_INT_MASK_TX_REGISTER_UNDERRUN
|
253 TEGRA_CEC_INT_MASK_TX_FRAME_OR_BLOCK_NAKD
|
254 TEGRA_CEC_INT_MASK_TX_ARBITRATION_FAILED
|
255 TEGRA_CEC_INT_MASK_TX_BUS_ANOMALY_DETECTED
|
256 TEGRA_CEC_INT_MASK_TX_FRAME_TRANSMITTED
|
257 TEGRA_CEC_INT_MASK_RX_REGISTER_FULL
|
258 TEGRA_CEC_INT_MASK_RX_REGISTER_OVERRUN
);
260 cec_write(cec
, TEGRA_CEC_HW_CONTROL
, TEGRA_CEC_HWCTRL_TX_RX_MODE
);
264 static int tegra_cec_adap_log_addr(struct cec_adapter
*adap
, u8 logical_addr
)
266 struct tegra_cec
*cec
= adap
->priv
;
267 u32 state
= cec_read(cec
, TEGRA_CEC_HW_CONTROL
);
269 if (logical_addr
== CEC_LOG_ADDR_INVALID
)
270 state
&= ~TEGRA_CEC_HWCTRL_RX_LADDR_MASK
;
272 state
|= TEGRA_CEC_HWCTRL_RX_LADDR((1 << logical_addr
));
274 cec_write(cec
, TEGRA_CEC_HW_CONTROL
, state
);
278 static int tegra_cec_adap_monitor_all_enable(struct cec_adapter
*adap
,
281 struct tegra_cec
*cec
= adap
->priv
;
282 u32 reg
= cec_read(cec
, TEGRA_CEC_HW_CONTROL
);
285 reg
|= TEGRA_CEC_HWCTRL_RX_SNOOP
;
287 reg
&= ~TEGRA_CEC_HWCTRL_RX_SNOOP
;
288 cec_write(cec
, TEGRA_CEC_HW_CONTROL
, reg
);
292 static int tegra_cec_adap_transmit(struct cec_adapter
*adap
, u8 attempts
,
293 u32 signal_free_time_ms
, struct cec_msg
*msg
)
295 bool retry_xfer
= signal_free_time_ms
== CEC_SIGNAL_FREE_TIME_RETRY
;
296 struct tegra_cec
*cec
= adap
->priv
;
301 if (cec_msg_is_broadcast(msg
))
302 mode
= TEGRA_CEC_TX_REG_BCAST
;
305 cec
->tx_buf_cnt
= msg
->len
;
307 for (i
= 0; i
< msg
->len
; i
++) {
308 cec
->tx_buf
[i
] = mode
| msg
->msg
[i
];
310 cec
->tx_buf
[i
] |= TEGRA_CEC_TX_REG_START_BIT
;
311 if (i
== msg
->len
- 1)
312 cec
->tx_buf
[i
] |= TEGRA_CEC_TX_REG_EOM
;
313 if (i
== 0 && retry_xfer
)
314 cec
->tx_buf
[i
] |= TEGRA_CEC_TX_REG_RETRY
;
317 mask
= cec_read(cec
, TEGRA_CEC_INT_MASK
);
318 cec_write(cec
, TEGRA_CEC_INT_MASK
,
319 mask
| TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY
);
324 static const struct cec_adap_ops tegra_cec_ops
= {
325 .adap_enable
= tegra_cec_adap_enable
,
326 .adap_log_addr
= tegra_cec_adap_log_addr
,
327 .adap_transmit
= tegra_cec_adap_transmit
,
328 .adap_monitor_all_enable
= tegra_cec_adap_monitor_all_enable
,
331 static int tegra_cec_probe(struct platform_device
*pdev
)
333 struct platform_device
*hdmi_dev
;
334 struct device_node
*np
;
335 struct tegra_cec
*cec
;
336 struct resource
*res
;
339 np
= of_parse_phandle(pdev
->dev
.of_node
, "hdmi-phandle", 0);
342 dev_err(&pdev
->dev
, "Failed to find hdmi node in device tree\n");
345 hdmi_dev
= of_find_device_by_node(np
);
346 if (hdmi_dev
== NULL
)
347 return -EPROBE_DEFER
;
349 cec
= devm_kzalloc(&pdev
->dev
, sizeof(struct tegra_cec
), GFP_KERNEL
);
354 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
358 "Unable to allocate resources for device\n");
362 if (!devm_request_mem_region(&pdev
->dev
, res
->start
, resource_size(res
),
365 "Unable to request mem region for device\n");
369 cec
->tegra_cec_irq
= platform_get_irq(pdev
, 0);
371 if (cec
->tegra_cec_irq
<= 0)
374 cec
->cec_base
= devm_ioremap_nocache(&pdev
->dev
, res
->start
,
377 if (!cec
->cec_base
) {
378 dev_err(&pdev
->dev
, "Unable to grab IOs for device\n");
382 cec
->clk
= devm_clk_get(&pdev
->dev
, "cec");
384 if (IS_ERR_OR_NULL(cec
->clk
)) {
385 dev_err(&pdev
->dev
, "Can't get clock for CEC\n");
389 clk_prepare_enable(cec
->clk
);
391 /* set context info. */
392 cec
->dev
= &pdev
->dev
;
394 platform_set_drvdata(pdev
, cec
);
396 ret
= devm_request_threaded_irq(&pdev
->dev
, cec
->tegra_cec_irq
,
397 tegra_cec_irq_handler
, tegra_cec_irq_thread_handler
,
398 0, "cec_irq", &pdev
->dev
);
402 "Unable to request interrupt for device\n");
406 cec
->notifier
= cec_notifier_get(&hdmi_dev
->dev
);
407 if (!cec
->notifier
) {
412 cec
->adap
= cec_allocate_adapter(&tegra_cec_ops
, cec
, TEGRA_CEC_NAME
,
413 CEC_CAP_DEFAULTS
| CEC_CAP_MONITOR_ALL
,
415 if (IS_ERR(cec
->adap
)) {
417 dev_err(&pdev
->dev
, "Couldn't create cec adapter\n");
420 ret
= cec_register_adapter(cec
->adap
, &pdev
->dev
);
422 dev_err(&pdev
->dev
, "Couldn't register device\n");
426 cec_register_cec_notifier(cec
->adap
, cec
->notifier
);
432 cec_notifier_put(cec
->notifier
);
433 cec_delete_adapter(cec
->adap
);
435 clk_disable_unprepare(cec
->clk
);
439 static int tegra_cec_remove(struct platform_device
*pdev
)
441 struct tegra_cec
*cec
= platform_get_drvdata(pdev
);
443 clk_disable_unprepare(cec
->clk
);
445 cec_unregister_adapter(cec
->adap
);
446 cec_notifier_put(cec
->notifier
);
452 static int tegra_cec_suspend(struct platform_device
*pdev
, pm_message_t state
)
454 struct tegra_cec
*cec
= platform_get_drvdata(pdev
);
456 clk_disable_unprepare(cec
->clk
);
458 dev_notice(&pdev
->dev
, "suspended\n");
462 static int tegra_cec_resume(struct platform_device
*pdev
)
464 struct tegra_cec
*cec
= platform_get_drvdata(pdev
);
466 dev_notice(&pdev
->dev
, "Resuming\n");
468 clk_prepare_enable(cec
->clk
);
474 static const struct of_device_id tegra_cec_of_match
[] = {
475 { .compatible
= "nvidia,tegra114-cec", },
476 { .compatible
= "nvidia,tegra124-cec", },
477 { .compatible
= "nvidia,tegra210-cec", },
481 static struct platform_driver tegra_cec_driver
= {
483 .name
= TEGRA_CEC_NAME
,
484 .of_match_table
= of_match_ptr(tegra_cec_of_match
),
486 .probe
= tegra_cec_probe
,
487 .remove
= tegra_cec_remove
,
490 .suspend
= tegra_cec_suspend
,
491 .resume
= tegra_cec_resume
,
495 module_platform_driver(tegra_cec_driver
);
497 MODULE_DESCRIPTION("Tegra HDMI CEC driver");
498 MODULE_AUTHOR("NVIDIA CORPORATION");
499 MODULE_AUTHOR("Cisco Systems, Inc. and/or its affiliates");
500 MODULE_LICENSE("GPL v2");