1 #include <linux/delay.h>
2 #include "../rockchip-hdmi-cec.h"
3 #include "rockchip_hdmiv2.h"
4 #include "rockchip_hdmiv2_hw.h"
6 /* static wait_queue_head_t wait;*/
8 void rockchip_hdmiv2_cec_isr(struct hdmi_dev *hdmi_dev, char cec_int)
10 CECDBG("%s cec 0x%x\n", __func__, cec_int);
12 rockchip_hdmi_cec_submit_work(EVENT_RX_FRAME, 0, NULL);
14 CECDBG("send frame success\n");
17 static int rockchip_hdmiv2_cec_readframe(struct hdmi *hdmi,
18 struct cec_framedata *frame)
20 struct hdmi_dev *hdmi_dev = hdmi->property->priv;
22 char *data = (char *)frame;
24 if (((hdmi_dev->clk_on & HDMI_PCLK_ON) == 0) || !frame)
26 count = hdmi_readl(hdmi_dev, CEC_RX_CNT);
27 CECDBG("%s count %d\n", __func__, count);
28 for (i = 0; i < count; i++) {
29 data[i] = hdmi_readl(hdmi_dev, CEC_RX_DATA0 + i);
30 CECDBG("%02x\n", data[i]);
32 frame->argcount = count - 2;
33 hdmi_writel(hdmi_dev, CEC_LOCK, 0x0);
37 void rockchip_hdmiv2_cec_setcecla(struct hdmi *hdmi, int ceclgaddr)
39 struct hdmi_dev *hdmi_dev = hdmi->property->priv;
42 if ((hdmi_dev->clk_on & HDMI_PCLK_ON) == 0)
44 if (ceclgaddr < 0 || ceclgaddr > 16)
47 hdmi_writel(hdmi_dev, CEC_ADDR_L, val & 0xff);
48 hdmi_writel(hdmi_dev, CEC_ADDR_H, val >> 8);
51 static int rockchip_hdmiv2_cec_sendframe(struct hdmi *hdmi,
52 struct cec_framedata *frame)
54 struct hdmi_dev *hdmi_dev = hdmi->property->priv;
57 if ((hdmi_dev->clk_on & HDMI_PCLK_ON) == 0)
59 CECDBG("TX srcdestaddr %02x opcode %02x ",
60 frame->srcdestaddr, frame->opcode);
61 if (frame->argcount) {
63 for (i = 0; i < frame->argcount; i++)
64 CECDBG("%02x ", frame->args[i]);
67 if ((frame->srcdestaddr & 0x0f) == ((frame->srcdestaddr >> 4) & 0x0f)) {
68 /*it is a ping command*/
69 hdmi_writel(hdmi_dev, CEC_TX_DATA0, frame->srcdestaddr);
70 hdmi_writel(hdmi_dev, CEC_TX_CNT, 1);
72 hdmi_writel(hdmi_dev, CEC_TX_DATA0, frame->srcdestaddr);
73 hdmi_writel(hdmi_dev, CEC_TX_DATA0 + 1, frame->opcode);
74 for (i = 0; i < frame->argcount; i++)
76 CEC_TX_DATA0 + 2 + i, frame->args[i]);
77 hdmi_writel(hdmi_dev, CEC_TX_CNT, frame->argcount + 2);
80 hdmi_msk_reg(hdmi_dev, CEC_CTRL, m_CEC_SEND, v_CEC_SEND(1));
82 /* time = 2.4(ms)*(1 + 16)(head + param)*11(bit)*/
83 /*11bit = start bit(4.5ms) + data bit(2.4ms) */
85 usleep_range(900, 1000);
86 interrupt = hdmi_readl(hdmi_dev, IH_CEC_STAT0);
87 if (interrupt & (m_ERR_INITIATOR | m_ARB_LOST |
89 hdmi_writel(hdmi_dev, IH_CEC_STAT0,
90 interrupt & (m_ERR_INITIATOR |
91 m_ARB_LOST | m_NACK | m_DONE));
95 CECDBG("%s interrupt 0x%02x\n", __func__, interrupt);
96 if (interrupt & m_DONE)
97 return CEC_SEND_SUCCESS;
98 else if (interrupt & m_NACK)
101 return CEC_SEND_BUSY;
104 void rockchip_hdmiv2_cec_init(struct hdmi *hdmi)
106 struct hdmi_dev *hdmi_dev = hdmi->property->priv;
109 rockchip_hdmi_cec_init(hdmi,
110 rockchip_hdmiv2_cec_sendframe,
111 rockchip_hdmiv2_cec_readframe,
112 rockchip_hdmiv2_cec_setcecla);
114 /* init_waitqueue_head(&wait); */
117 * Enable sending all message even if sink refuse
118 * message broadcasted by us.
120 if (hdmi_dev->grf_base)
121 regmap_write(hdmi_dev->grf_base,
122 hdmi_dev->grf_reg_offset,
123 (1 << hdmi_dev->grf_reg_shift) |
124 (1 << (hdmi_dev->grf_reg_shift + 16)));
125 hdmi_writel(hdmi_dev, IH_MUTE_CEC_STAT0, m_ERR_INITIATOR |
126 m_ARB_LOST | m_NACK | m_DONE);
127 CECDBG("%s", __func__);