hdmi:cec: Define cec send frame return value.
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / hdmi / rockchip-hdmiv1 / rockchip_hdmiv1_cec.c
1 #include "rockchip_hdmiv1.h"
2 #include "rockchip_hdmiv1_hw.h"
3 #include "../rockchip-hdmi-cec.h"
4
5 struct cec_t {
6         wait_queue_head_t wait;
7         int busfree;
8         int tx_done;
9 };
10
11 static int init = 1;
12 static struct cec_t cec;
13
14 static int rockchip_hdmiv1_cec_read_frame(struct hdmi *hdmi,
15                                           struct cec_framedata *frame)
16 {
17         int i, length, val;
18         char *data = (char *)frame;
19         struct hdmi_dev *hdmi_dev = hdmi->property->priv;
20
21         if (frame == NULL)
22                 return -1;
23
24         hdmi_readl(hdmi_dev, CEC_RX_LENGTH, &length);
25         hdmi_writel(hdmi_dev, CEC_RX_OFFSET, 0);
26
27         CECDBG("CEC: %s length is %d\n", __func__, length);
28         for (i = 0; i < length; i++) {
29                 hdmi_readl(hdmi_dev, CEC_DATA, &val);
30                 data[i] = val;
31                 pr_info("%02x\n", data[i]);
32         }
33         return 0;
34 }
35
36 static int rockchip_hdmiv1_cec_send_frame(struct hdmi *hdmi,
37                                           struct cec_framedata *frame)
38 {
39         int i;
40         struct hdmi_dev *hdmi_dev = hdmi->property->priv;
41
42         CECDBG("CEC: TX srcdestaddr %x opcode %x ",
43                frame->srcdestaddr, frame->opcode);
44         if (frame->argcount) {
45                 DBG("args:");
46                 for (i = 0; i < frame->argcount; i++)
47                         DBG("%02x ", frame->args[i]);
48         }
49         CECDBG("\n");
50
51         hdmi_writel(hdmi_dev, CEC_TX_OFFSET, 0);
52         hdmi_writel(hdmi_dev, CEC_DATA, frame->srcdestaddr);
53         hdmi_writel(hdmi_dev, CEC_DATA, frame->opcode);
54
55         for (i = 0; i < frame->argcount; i++)
56                 hdmi_writel(hdmi_dev, CEC_DATA, frame->args[i]);
57
58         hdmi_writel(hdmi_dev, CEC_TX_LENGTH, frame->argcount + 2);
59
60         /*Wait for bus free*/
61         cec.busfree = 1;
62         hdmi_writel(hdmi_dev, CEC_CTRL, m_BUSFREETIME_ENABLE);
63         CECDBG("start wait bus free\n");
64         if (wait_event_interruptible_timeout(cec.wait,
65                                              cec.busfree == 0,
66                                              msecs_to_jiffies(17)))
67                 return CEC_SEND_BUSY;
68
69         CECDBG("end wait bus free,start tx,busfree=%d\n", cec.busfree);
70         /*Start TX*/
71         cec.tx_done = 0;
72         hdmi_writel(hdmi_dev, CEC_CTRL, m_BUSFREETIME_ENABLE|m_START_TX);
73         if (wait_event_interruptible_timeout(cec.wait,
74                                              cec.tx_done != 0,
75                                              msecs_to_jiffies(100)))
76                 hdmi_writel(hdmi_dev, CEC_CTRL, 0);
77         CECDBG("end tx,tx_done=%d\n", cec.tx_done);
78
79         if (cec.tx_done == 1) {
80                 cec.tx_done = 0;
81                 return CEC_SEND_SUCCESS;
82         } else {
83                 return CEC_SEND_NACK;
84         }
85 }
86
87 void rockchip_hdmiv1_cec_setcecla(struct hdmi *hdmi, int ceclgaddr)
88 {
89         struct hdmi_dev *hdmi_dev = hdmi->property->priv;
90
91         /*for(i = 0; i < 3; i++) {
92                 if(Cec_Ping(la_player[i]) == 1) {
93                         cec.address_logic = la_player[i];
94                         break;
95                 }
96         }
97         if(i == 3)
98                 return -1;
99         //Broadcast our physical address.
100         GPIO_CecSendMessage(CECOP_GET_MENU_LANGUAGE,CEC_LOGADDR_TV);
101         msleep(100);*/
102         CECDBG("CEC: %s\n", __func__);
103         hdmi_writel(hdmi_dev, CEC_LOGICADDR, ceclgaddr);
104 }
105
106 void rockchip_hdmiv1_cec_isr(struct hdmi_dev *hdmi_dev)
107 {
108         int tx_isr = 0, rx_isr = 0;
109
110         hdmi_readl(hdmi_dev, CEC_TX_INT, &tx_isr);
111         hdmi_readl(hdmi_dev, CEC_RX_INT, &rx_isr);
112
113         CECDBG("CEC: rockchip_hdmiv1_cec_isr:tx_isr %02x  rx_isr %02x\n\n",
114                tx_isr, rx_isr);
115
116         hdmi_writel(hdmi_dev, CEC_TX_INT, tx_isr);
117         hdmi_writel(hdmi_dev, CEC_RX_INT, rx_isr);
118
119         if (tx_isr & m_TX_BUSNOTFREE) {
120                 cec.busfree = 0;
121                 CECDBG("CEC: m_TX_BUSNOTFREE,busfree=%d\n", cec.busfree);
122         } else if (tx_isr & m_TX_DONE) {
123                 cec.tx_done = 1;
124                 CECDBG("CEC: m_TX_DONE,busfree=%d\n", cec.tx_done);
125         } else {
126                 cec.tx_done = -1;
127                 CECDBG("CEC: else:busfree=%d\n", cec.tx_done);
128         }
129
130         wake_up_interruptible_all(&cec.wait);
131         if (rx_isr & m_RX_DONE)
132                 rockchip_hdmi_cec_submit_work(EVENT_RX_FRAME, 0, NULL);
133 }
134
135 void rockchip_hdmiv1_cec_init(struct hdmi *hdmi)
136 {
137         struct hdmi_dev *hdmi_dev = hdmi->property->priv;
138
139         if (init) {
140                 /*Fref = Fsys / ((register 0xd4 + 1)*(register 0xd5 + 1))*/
141                 /*Fref = 0.5M, Fsys = 74.25M*/
142                 hdmi_writel(hdmi_dev, CEC_CLK_H, 11);
143                 hdmi_writel(hdmi_dev, CEC_CLK_L, 11);
144
145                 /*Set bus free time to 16.8ms*/
146                 hdmi_writel(hdmi_dev, CEC_BUSFREETIME_L, 0xd0);
147                 hdmi_writel(hdmi_dev, CEC_BUSFREETIME_H, 0x20);
148
149                 /*Enable TX/RX INT*/
150                 hdmi_writel(hdmi_dev, CEC_TX_INT, 0xFF);
151                 hdmi_writel(hdmi_dev, CEC_RX_INT, 0xFF);
152
153                 CECDBG(KERN_ERR "CEC: rockchip_hdmiv1_cec_init sucess\n");
154                 rockchip_hdmi_cec_init(hdmi,
155                                        rockchip_hdmiv1_cec_send_frame,
156                                        rockchip_hdmiv1_cec_read_frame,
157                                        rockchip_hdmiv1_cec_setcecla);
158                 init = 0;
159                 init_waitqueue_head(&cec.wait);
160         }
161         CECDBG("%s", __func__);
162 }
163