1*b94b7353SCai Huoqing // SPDX-License-Identifier: GPL-2.0-only
28d7f934dSHans Verkuil /*
38d7f934dSHans Verkuil * HDMI CEC
48d7f934dSHans Verkuil *
58d7f934dSHans Verkuil * Based on the CEC code from hdmi_ti_4xxx_ip.c from Android.
68d7f934dSHans Verkuil *
71b409fdaSAlexander A. Klimov * Copyright (C) 2010-2011 Texas Instruments Incorporated - https://www.ti.com/
88d7f934dSHans Verkuil * Authors: Yong Zhi
98d7f934dSHans Verkuil * Mythri pk <mythripk@ti.com>
108d7f934dSHans Verkuil *
118d7f934dSHans Verkuil * Heavily modified to use the linux CEC framework:
128d7f934dSHans Verkuil *
138d7f934dSHans Verkuil * Copyright 2016-2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
148d7f934dSHans Verkuil */
158d7f934dSHans Verkuil
168d7f934dSHans Verkuil #include <linux/kernel.h>
178d7f934dSHans Verkuil #include <linux/err.h>
188d7f934dSHans Verkuil #include <linux/io.h>
198d7f934dSHans Verkuil #include <linux/platform_device.h>
208d7f934dSHans Verkuil #include <linux/slab.h>
218d7f934dSHans Verkuil
228d7f934dSHans Verkuil #include "dss.h"
238d7f934dSHans Verkuil #include "hdmi.h"
248d7f934dSHans Verkuil #include "hdmi4_core.h"
258d7f934dSHans Verkuil #include "hdmi4_cec.h"
268d7f934dSHans Verkuil
278d7f934dSHans Verkuil /* HDMI CEC */
288d7f934dSHans Verkuil #define HDMI_CEC_DEV_ID 0x900
298d7f934dSHans Verkuil #define HDMI_CEC_SPEC 0x904
308d7f934dSHans Verkuil
318d7f934dSHans Verkuil /* Not really a debug register, more a low-level control register */
328d7f934dSHans Verkuil #define HDMI_CEC_DBG_3 0x91C
338d7f934dSHans Verkuil #define HDMI_CEC_TX_INIT 0x920
348d7f934dSHans Verkuil #define HDMI_CEC_TX_DEST 0x924
358d7f934dSHans Verkuil #define HDMI_CEC_SETUP 0x938
368d7f934dSHans Verkuil #define HDMI_CEC_TX_COMMAND 0x93C
378d7f934dSHans Verkuil #define HDMI_CEC_TX_OPERAND 0x940
388d7f934dSHans Verkuil #define HDMI_CEC_TRANSMIT_DATA 0x97C
398d7f934dSHans Verkuil #define HDMI_CEC_CA_7_0 0x988
408d7f934dSHans Verkuil #define HDMI_CEC_CA_15_8 0x98C
418d7f934dSHans Verkuil #define HDMI_CEC_INT_STATUS_0 0x998
428d7f934dSHans Verkuil #define HDMI_CEC_INT_STATUS_1 0x99C
438d7f934dSHans Verkuil #define HDMI_CEC_INT_ENABLE_0 0x990
448d7f934dSHans Verkuil #define HDMI_CEC_INT_ENABLE_1 0x994
458d7f934dSHans Verkuil #define HDMI_CEC_RX_CONTROL 0x9B0
468d7f934dSHans Verkuil #define HDMI_CEC_RX_COUNT 0x9B4
478d7f934dSHans Verkuil #define HDMI_CEC_RX_CMD_HEADER 0x9B8
488d7f934dSHans Verkuil #define HDMI_CEC_RX_COMMAND 0x9BC
498d7f934dSHans Verkuil #define HDMI_CEC_RX_OPERAND 0x9C0
508d7f934dSHans Verkuil
518d7f934dSHans Verkuil #define HDMI_CEC_TX_FIFO_INT_MASK 0x64
528d7f934dSHans Verkuil #define HDMI_CEC_RETRANSMIT_CNT_INT_MASK 0x2
538d7f934dSHans Verkuil
548d7f934dSHans Verkuil #define HDMI_CORE_CEC_RETRY 200
558d7f934dSHans Verkuil
hdmi_cec_received_msg(struct hdmi_core_data * core)568d7f934dSHans Verkuil static void hdmi_cec_received_msg(struct hdmi_core_data *core)
578d7f934dSHans Verkuil {
588d7f934dSHans Verkuil u32 cnt = hdmi_read_reg(core->base, HDMI_CEC_RX_COUNT) & 0xff;
598d7f934dSHans Verkuil
608d7f934dSHans Verkuil /* While there are CEC frames in the FIFO */
618d7f934dSHans Verkuil while (cnt & 0x70) {
628d7f934dSHans Verkuil /* and the frame doesn't have an error */
638d7f934dSHans Verkuil if (!(cnt & 0x80)) {
648d7f934dSHans Verkuil struct cec_msg msg = {};
658d7f934dSHans Verkuil unsigned int i;
668d7f934dSHans Verkuil
678d7f934dSHans Verkuil /* then read the message */
688d7f934dSHans Verkuil msg.len = cnt & 0xf;
69df29c9dbSHans Verkuil if (msg.len > CEC_MAX_MSG_SIZE - 2)
70df29c9dbSHans Verkuil msg.len = CEC_MAX_MSG_SIZE - 2;
718d7f934dSHans Verkuil msg.msg[0] = hdmi_read_reg(core->base,
728d7f934dSHans Verkuil HDMI_CEC_RX_CMD_HEADER);
738d7f934dSHans Verkuil msg.msg[1] = hdmi_read_reg(core->base,
748d7f934dSHans Verkuil HDMI_CEC_RX_COMMAND);
758d7f934dSHans Verkuil for (i = 0; i < msg.len; i++) {
768d7f934dSHans Verkuil unsigned int reg = HDMI_CEC_RX_OPERAND + i * 4;
778d7f934dSHans Verkuil
788d7f934dSHans Verkuil msg.msg[2 + i] =
798d7f934dSHans Verkuil hdmi_read_reg(core->base, reg);
808d7f934dSHans Verkuil }
818d7f934dSHans Verkuil msg.len += 2;
828d7f934dSHans Verkuil cec_received_msg(core->adap, &msg);
838d7f934dSHans Verkuil }
848d7f934dSHans Verkuil /* Clear the current frame from the FIFO */
858d7f934dSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_RX_CONTROL, 1);
868d7f934dSHans Verkuil /* Wait until the current frame is cleared */
878d7f934dSHans Verkuil while (hdmi_read_reg(core->base, HDMI_CEC_RX_CONTROL) & 1)
888d7f934dSHans Verkuil udelay(1);
898d7f934dSHans Verkuil /*
908d7f934dSHans Verkuil * Re-read the count register and loop to see if there are
918d7f934dSHans Verkuil * more messages in the FIFO.
928d7f934dSHans Verkuil */
938d7f934dSHans Verkuil cnt = hdmi_read_reg(core->base, HDMI_CEC_RX_COUNT) & 0xff;
948d7f934dSHans Verkuil }
958d7f934dSHans Verkuil }
968d7f934dSHans Verkuil
hdmi4_cec_irq(struct hdmi_core_data * core)978d7f934dSHans Verkuil void hdmi4_cec_irq(struct hdmi_core_data *core)
988d7f934dSHans Verkuil {
998d7f934dSHans Verkuil u32 stat0 = hdmi_read_reg(core->base, HDMI_CEC_INT_STATUS_0);
1008d7f934dSHans Verkuil u32 stat1 = hdmi_read_reg(core->base, HDMI_CEC_INT_STATUS_1);
1018d7f934dSHans Verkuil
1028d7f934dSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_0, stat0);
1038d7f934dSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_1, stat1);
1048d7f934dSHans Verkuil
105df29c9dbSHans Verkuil if (stat0 & 0x20) {
106df29c9dbSHans Verkuil cec_transmit_done(core->adap, CEC_TX_STATUS_OK,
107df29c9dbSHans Verkuil 0, 0, 0, 0);
1088d7f934dSHans Verkuil REG_FLD_MOD(core->base, HDMI_CEC_DBG_3, 0x1, 7, 7);
109df29c9dbSHans Verkuil } else if (stat1 & 0x02) {
1108d7f934dSHans Verkuil u32 dbg3 = hdmi_read_reg(core->base, HDMI_CEC_DBG_3);
1118d7f934dSHans Verkuil
1128d7f934dSHans Verkuil cec_transmit_done(core->adap,
1138d7f934dSHans Verkuil CEC_TX_STATUS_NACK |
1148d7f934dSHans Verkuil CEC_TX_STATUS_MAX_RETRIES,
1158d7f934dSHans Verkuil 0, (dbg3 >> 4) & 7, 0, 0);
116df29c9dbSHans Verkuil REG_FLD_MOD(core->base, HDMI_CEC_DBG_3, 0x1, 7, 7);
1178d7f934dSHans Verkuil }
1188d7f934dSHans Verkuil if (stat0 & 0x02)
1198d7f934dSHans Verkuil hdmi_cec_received_msg(core);
1208d7f934dSHans Verkuil }
1218d7f934dSHans Verkuil
hdmi_cec_clear_tx_fifo(struct cec_adapter * adap)1228d7f934dSHans Verkuil static bool hdmi_cec_clear_tx_fifo(struct cec_adapter *adap)
1238d7f934dSHans Verkuil {
1248d7f934dSHans Verkuil struct hdmi_core_data *core = cec_get_drvdata(adap);
1258d7f934dSHans Verkuil int retry = HDMI_CORE_CEC_RETRY;
1268d7f934dSHans Verkuil int temp;
1278d7f934dSHans Verkuil
1288d7f934dSHans Verkuil REG_FLD_MOD(core->base, HDMI_CEC_DBG_3, 0x1, 7, 7);
1298d7f934dSHans Verkuil while (retry) {
1308d7f934dSHans Verkuil temp = hdmi_read_reg(core->base, HDMI_CEC_DBG_3);
1318d7f934dSHans Verkuil if (FLD_GET(temp, 7, 7) == 0)
1328d7f934dSHans Verkuil break;
1338d7f934dSHans Verkuil retry--;
1348d7f934dSHans Verkuil }
1358d7f934dSHans Verkuil return retry != 0;
1368d7f934dSHans Verkuil }
1378d7f934dSHans Verkuil
hdmi_cec_clear_rx_fifo(struct cec_adapter * adap)1388d7f934dSHans Verkuil static bool hdmi_cec_clear_rx_fifo(struct cec_adapter *adap)
1398d7f934dSHans Verkuil {
1408d7f934dSHans Verkuil struct hdmi_core_data *core = cec_get_drvdata(adap);
1418d7f934dSHans Verkuil int retry = HDMI_CORE_CEC_RETRY;
1428d7f934dSHans Verkuil int temp;
1438d7f934dSHans Verkuil
1448d7f934dSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_RX_CONTROL, 0x3);
1458d7f934dSHans Verkuil retry = HDMI_CORE_CEC_RETRY;
1468d7f934dSHans Verkuil while (retry) {
1478d7f934dSHans Verkuil temp = hdmi_read_reg(core->base, HDMI_CEC_RX_CONTROL);
1488d7f934dSHans Verkuil if (FLD_GET(temp, 1, 0) == 0)
1498d7f934dSHans Verkuil break;
1508d7f934dSHans Verkuil retry--;
1518d7f934dSHans Verkuil }
1528d7f934dSHans Verkuil return retry != 0;
1538d7f934dSHans Verkuil }
1548d7f934dSHans Verkuil
hdmi_cec_adap_enable(struct cec_adapter * adap,bool enable)1558d7f934dSHans Verkuil static int hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
1568d7f934dSHans Verkuil {
1578d7f934dSHans Verkuil struct hdmi_core_data *core = cec_get_drvdata(adap);
1588d7f934dSHans Verkuil int temp, err;
1598d7f934dSHans Verkuil
1608d7f934dSHans Verkuil if (!enable) {
1618d7f934dSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_INT_ENABLE_0, 0);
1628d7f934dSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_INT_ENABLE_1, 0);
1638d7f934dSHans Verkuil REG_FLD_MOD(core->base, HDMI_CORE_SYS_INTR_UNMASK4, 0, 3, 3);
1648d7f934dSHans Verkuil hdmi_wp_clear_irqenable(core->wp, HDMI_IRQ_CORE);
1658d7f934dSHans Verkuil hdmi_wp_set_irqstatus(core->wp, HDMI_IRQ_CORE);
16636a1da15STony Lindgren REG_FLD_MOD(core->wp->base, HDMI_WP_CLK, 0, 5, 0);
167ac767456SLaurent Pinchart hdmi4_core_disable(core);
1688d7f934dSHans Verkuil return 0;
1698d7f934dSHans Verkuil }
170ac767456SLaurent Pinchart err = hdmi4_core_enable(core);
1718d7f934dSHans Verkuil if (err)
1728d7f934dSHans Verkuil return err;
1738d7f934dSHans Verkuil
17436a1da15STony Lindgren /*
17536a1da15STony Lindgren * Initialize CEC clock divider: CEC needs 2MHz clock hence
17636a1da15STony Lindgren * set the divider to 24 to get 48/24=2MHz clock
17736a1da15STony Lindgren */
17836a1da15STony Lindgren REG_FLD_MOD(core->wp->base, HDMI_WP_CLK, 0x18, 5, 0);
17936a1da15STony Lindgren
1808d7f934dSHans Verkuil /* Clear TX FIFO */
1818d7f934dSHans Verkuil if (!hdmi_cec_clear_tx_fifo(adap)) {
1828d7f934dSHans Verkuil pr_err("cec-%s: could not clear TX FIFO\n", adap->name);
18336a1da15STony Lindgren err = -EIO;
18436a1da15STony Lindgren goto err_disable_clk;
1858d7f934dSHans Verkuil }
1868d7f934dSHans Verkuil
1878d7f934dSHans Verkuil /* Clear RX FIFO */
1888d7f934dSHans Verkuil if (!hdmi_cec_clear_rx_fifo(adap)) {
1898d7f934dSHans Verkuil pr_err("cec-%s: could not clear RX FIFO\n", adap->name);
19036a1da15STony Lindgren err = -EIO;
19136a1da15STony Lindgren goto err_disable_clk;
1928d7f934dSHans Verkuil }
1938d7f934dSHans Verkuil
1948d7f934dSHans Verkuil /* Clear CEC interrupts */
1958d7f934dSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_1,
1968d7f934dSHans Verkuil hdmi_read_reg(core->base, HDMI_CEC_INT_STATUS_1));
1978d7f934dSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_0,
1988d7f934dSHans Verkuil hdmi_read_reg(core->base, HDMI_CEC_INT_STATUS_0));
1998d7f934dSHans Verkuil
2008d7f934dSHans Verkuil /* Enable HDMI core interrupts */
2018d7f934dSHans Verkuil hdmi_wp_set_irqenable(core->wp, HDMI_IRQ_CORE);
2028d7f934dSHans Verkuil /* Unmask CEC interrupt */
2038d7f934dSHans Verkuil REG_FLD_MOD(core->base, HDMI_CORE_SYS_INTR_UNMASK4, 0x1, 3, 3);
2048d7f934dSHans Verkuil /*
2058d7f934dSHans Verkuil * Enable CEC interrupts:
2068d7f934dSHans Verkuil * Transmit Buffer Full/Empty Change event
2078d7f934dSHans Verkuil * Receiver FIFO Not Empty event
2088d7f934dSHans Verkuil */
209df29c9dbSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_INT_ENABLE_0, 0x22);
2108d7f934dSHans Verkuil /*
2118d7f934dSHans Verkuil * Enable CEC interrupts:
2128d7f934dSHans Verkuil * Frame Retransmit Count Exceeded event
2138d7f934dSHans Verkuil */
214df29c9dbSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_INT_ENABLE_1, 0x02);
2158d7f934dSHans Verkuil
2168d7f934dSHans Verkuil /* cec calibration enable (self clearing) */
2178d7f934dSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_SETUP, 0x03);
2188d7f934dSHans Verkuil msleep(20);
2198d7f934dSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_SETUP, 0x04);
2208d7f934dSHans Verkuil
2218d7f934dSHans Verkuil temp = hdmi_read_reg(core->base, HDMI_CEC_SETUP);
2228d7f934dSHans Verkuil if (FLD_GET(temp, 4, 4) != 0) {
2238d7f934dSHans Verkuil temp = FLD_MOD(temp, 0, 4, 4);
2248d7f934dSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_SETUP, temp);
2258d7f934dSHans Verkuil
2268d7f934dSHans Verkuil /*
2278d7f934dSHans Verkuil * If we enabled CEC in middle of a CEC message on the bus,
2288d7f934dSHans Verkuil * we could have start bit irregularity and/or short
2298d7f934dSHans Verkuil * pulse event. Clear them now.
2308d7f934dSHans Verkuil */
2318d7f934dSHans Verkuil temp = hdmi_read_reg(core->base, HDMI_CEC_INT_STATUS_1);
2328d7f934dSHans Verkuil temp = FLD_MOD(0x0, 0x5, 2, 0);
2338d7f934dSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_1, temp);
2348d7f934dSHans Verkuil }
2358d7f934dSHans Verkuil return 0;
23636a1da15STony Lindgren
23736a1da15STony Lindgren err_disable_clk:
23836a1da15STony Lindgren REG_FLD_MOD(core->wp->base, HDMI_WP_CLK, 0, 5, 0);
23936a1da15STony Lindgren hdmi4_core_disable(core);
24036a1da15STony Lindgren
24136a1da15STony Lindgren return err;
2428d7f934dSHans Verkuil }
2438d7f934dSHans Verkuil
hdmi_cec_adap_log_addr(struct cec_adapter * adap,u8 log_addr)2448d7f934dSHans Verkuil static int hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
2458d7f934dSHans Verkuil {
2468d7f934dSHans Verkuil struct hdmi_core_data *core = cec_get_drvdata(adap);
2478d7f934dSHans Verkuil u32 v;
2488d7f934dSHans Verkuil
2498d7f934dSHans Verkuil if (log_addr == CEC_LOG_ADDR_INVALID) {
2508d7f934dSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_CA_7_0, 0);
2518d7f934dSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_CA_15_8, 0);
2528d7f934dSHans Verkuil return 0;
2538d7f934dSHans Verkuil }
2548d7f934dSHans Verkuil if (log_addr <= 7) {
2558d7f934dSHans Verkuil v = hdmi_read_reg(core->base, HDMI_CEC_CA_7_0);
2568d7f934dSHans Verkuil v |= 1 << log_addr;
2578d7f934dSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_CA_7_0, v);
2588d7f934dSHans Verkuil } else {
2598d7f934dSHans Verkuil v = hdmi_read_reg(core->base, HDMI_CEC_CA_15_8);
2608d7f934dSHans Verkuil v |= 1 << (log_addr - 8);
2618d7f934dSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_CA_15_8, v);
2628d7f934dSHans Verkuil }
2638d7f934dSHans Verkuil return 0;
2648d7f934dSHans Verkuil }
2658d7f934dSHans Verkuil
hdmi_cec_adap_transmit(struct cec_adapter * adap,u8 attempts,u32 signal_free_time,struct cec_msg * msg)2668d7f934dSHans Verkuil static int hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
2678d7f934dSHans Verkuil u32 signal_free_time, struct cec_msg *msg)
2688d7f934dSHans Verkuil {
2698d7f934dSHans Verkuil struct hdmi_core_data *core = cec_get_drvdata(adap);
2708d7f934dSHans Verkuil int temp;
2718d7f934dSHans Verkuil u32 i;
2728d7f934dSHans Verkuil
2738d7f934dSHans Verkuil /* Clear TX FIFO */
2748d7f934dSHans Verkuil if (!hdmi_cec_clear_tx_fifo(adap)) {
2758d7f934dSHans Verkuil pr_err("cec-%s: could not clear TX FIFO for transmit\n",
2768d7f934dSHans Verkuil adap->name);
2778d7f934dSHans Verkuil return -EIO;
2788d7f934dSHans Verkuil }
2798d7f934dSHans Verkuil
2808d7f934dSHans Verkuil /* Clear TX interrupts */
2818d7f934dSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_0,
2828d7f934dSHans Verkuil HDMI_CEC_TX_FIFO_INT_MASK);
2838d7f934dSHans Verkuil
2848d7f934dSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_1,
2858d7f934dSHans Verkuil HDMI_CEC_RETRANSMIT_CNT_INT_MASK);
2868d7f934dSHans Verkuil
2878d7f934dSHans Verkuil /* Set the retry count */
2888d7f934dSHans Verkuil REG_FLD_MOD(core->base, HDMI_CEC_DBG_3, attempts - 1, 6, 4);
2898d7f934dSHans Verkuil
2908d7f934dSHans Verkuil /* Set the initiator addresses */
2918d7f934dSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_TX_INIT, cec_msg_initiator(msg));
2928d7f934dSHans Verkuil
2938d7f934dSHans Verkuil /* Set destination id */
2948d7f934dSHans Verkuil temp = cec_msg_destination(msg);
2958d7f934dSHans Verkuil if (msg->len == 1)
2968d7f934dSHans Verkuil temp |= 0x80;
2978d7f934dSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_TX_DEST, temp);
2988d7f934dSHans Verkuil if (msg->len == 1)
2998d7f934dSHans Verkuil return 0;
3008d7f934dSHans Verkuil
3018d7f934dSHans Verkuil /* Setup command and arguments for the command */
3028d7f934dSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_TX_COMMAND, msg->msg[1]);
3038d7f934dSHans Verkuil
3048d7f934dSHans Verkuil for (i = 0; i < msg->len - 2; i++)
3058d7f934dSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_TX_OPERAND + i * 4,
3068d7f934dSHans Verkuil msg->msg[2 + i]);
3078d7f934dSHans Verkuil
3088d7f934dSHans Verkuil /* Operand count */
3098d7f934dSHans Verkuil hdmi_write_reg(core->base, HDMI_CEC_TRANSMIT_DATA,
3108d7f934dSHans Verkuil (msg->len - 2) | 0x10);
3118d7f934dSHans Verkuil return 0;
3128d7f934dSHans Verkuil }
3138d7f934dSHans Verkuil
3148d7f934dSHans Verkuil static const struct cec_adap_ops hdmi_cec_adap_ops = {
3158d7f934dSHans Verkuil .adap_enable = hdmi_cec_adap_enable,
3168d7f934dSHans Verkuil .adap_log_addr = hdmi_cec_adap_log_addr,
3178d7f934dSHans Verkuil .adap_transmit = hdmi_cec_adap_transmit,
3188d7f934dSHans Verkuil };
3198d7f934dSHans Verkuil
hdmi4_cec_set_phys_addr(struct hdmi_core_data * core,u16 pa)3208d7f934dSHans Verkuil void hdmi4_cec_set_phys_addr(struct hdmi_core_data *core, u16 pa)
3218d7f934dSHans Verkuil {
3228d7f934dSHans Verkuil cec_s_phys_addr(core->adap, pa, false);
3238d7f934dSHans Verkuil }
3248d7f934dSHans Verkuil
hdmi4_cec_init(struct platform_device * pdev,struct hdmi_core_data * core,struct hdmi_wp_data * wp)3258d7f934dSHans Verkuil int hdmi4_cec_init(struct platform_device *pdev, struct hdmi_core_data *core,
3268d7f934dSHans Verkuil struct hdmi_wp_data *wp)
3278d7f934dSHans Verkuil {
3288d7f934dSHans Verkuil const u32 caps = CEC_CAP_TRANSMIT | CEC_CAP_LOG_ADDRS |
3298d7f934dSHans Verkuil CEC_CAP_PASSTHROUGH | CEC_CAP_RC;
330bc2aba90SDan Carpenter int ret;
3318d7f934dSHans Verkuil
3328d7f934dSHans Verkuil core->adap = cec_allocate_adapter(&hdmi_cec_adap_ops, core,
3338d7f934dSHans Verkuil "omap4", caps, CEC_MAX_LOG_ADDRS);
3348d7f934dSHans Verkuil ret = PTR_ERR_OR_ZERO(core->adap);
3358d7f934dSHans Verkuil if (ret < 0)
3368d7f934dSHans Verkuil return ret;
3378d7f934dSHans Verkuil core->wp = wp;
3388d7f934dSHans Verkuil
33936a1da15STony Lindgren /* Disable clock initially, hdmi_cec_adap_enable() manages it */
34036a1da15STony Lindgren REG_FLD_MOD(core->wp->base, HDMI_WP_CLK, 0, 5, 0);
3418d7f934dSHans Verkuil
3428d7f934dSHans Verkuil ret = cec_register_adapter(core->adap, &pdev->dev);
3438d7f934dSHans Verkuil if (ret < 0) {
3448d7f934dSHans Verkuil cec_delete_adapter(core->adap);
3458d7f934dSHans Verkuil return ret;
3468d7f934dSHans Verkuil }
3478d7f934dSHans Verkuil return 0;
3488d7f934dSHans Verkuil }
3498d7f934dSHans Verkuil
hdmi4_cec_uninit(struct hdmi_core_data * core)3508d7f934dSHans Verkuil void hdmi4_cec_uninit(struct hdmi_core_data *core)
3518d7f934dSHans Verkuil {
3528d7f934dSHans Verkuil cec_unregister_adapter(core->adap);
3538d7f934dSHans Verkuil }
354