9e0c721ac5381adf0573312682350a7cfad69b3a
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / hdmi / rockchip-hdmiv1 / rockchip_hdmiv1_hw.c
1 #include <linux/delay.h>
2 #include <linux/io.h>
3 #include <linux/interrupt.h>
4 #include <linux/of_irq.h>
5 #include "rockchip_hdmiv1.h"
6 #include "rockchip_hdmiv1_hw.h"
7 #include "rockchip_hdmiv1_hdcp.h"
8
9 static inline void delay100us(void)
10 {
11         usleep_range(99, 100);
12 }
13
14 static void rockchip_hdmiv1_av_mute(struct hdmi *hdmi_drv, bool enable)
15 {
16         struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
17
18         if (enable) {
19                 hdmi_msk_reg(hdmi_dev, AV_MUTE,
20                              m_AVMUTE_CLEAR | m_AVMUTE_ENABLE,
21                              v_AVMUTE_CLEAR(0) | v_AVMUTE_ENABLE(1));
22         } else {
23                 hdmi_msk_reg(hdmi_dev, AV_MUTE,
24                              m_AVMUTE_CLEAR | m_AVMUTE_ENABLE,
25                              v_AVMUTE_CLEAR(1) | v_AVMUTE_ENABLE(0));
26         }
27         hdmi_msk_reg(hdmi_dev, PACKET_SEND_AUTO,
28                      m_PACKET_GCP_EN, v_PACKET_GCP_EN(1));
29 }
30
31 static void rockchip_hdmiv1_sys_power(struct hdmi *hdmi_drv, bool enable)
32 {
33         struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
34
35         if (enable)
36                 hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_POWER, v_PWR_ON);
37         else
38                 hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_POWER, v_PWR_OFF);
39 }
40
41 static void rockchip_hdmiv1_set_pwr_mode(struct hdmi *hdmi_drv, int mode)
42 {
43         struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
44
45         if (hdmi_dev->pwr_mode == mode)
46                 return;
47
48         dev_info(hdmi_drv->dev, "%s change pwr_mode %d --> %d\n", __func__,
49                  hdmi_dev->pwr_mode, mode);
50
51         switch (mode) {
52         case NORMAL:
53                 dev_info(hdmi_drv->dev,
54                          "%s change pwr_mode NORMAL\n",
55                          __func__);
56                 rockchip_hdmiv1_sys_power(hdmi_drv, false);
57                 if (hdmi_dev->soctype == HDMI_SOC_RK3036) {
58                         hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x6f);
59                         hdmi_writel(hdmi_dev, PHY_DRIVER, 0xbb);
60                 } else if (hdmi_dev->soctype == HDMI_SOC_RK312X) {
61                         hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x5f);
62                         hdmi_writel(hdmi_dev, PHY_DRIVER, 0xaa);
63                 }
64
65                 hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x15);
66                 hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x14);
67                 hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x10);
68                 hdmi_writel(hdmi_dev, PHY_CHG_PWR, 0x0f);
69                 hdmi_writel(hdmi_dev, 0xce, 0x00);
70                 hdmi_writel(hdmi_dev, 0xce, 0x01);
71                 rockchip_hdmiv1_sys_power(hdmi_drv, true);
72                 break;
73         case LOWER_PWR:
74                 dev_info(hdmi_drv->dev,
75                          "%s change pwr_mode LOWER_PWR\n",
76                          __func__);
77                 rockchip_hdmiv1_sys_power(hdmi_drv, false);
78                 hdmi_writel(hdmi_dev, PHY_DRIVER, 0x00);
79                 hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x00);
80                 hdmi_writel(hdmi_dev, PHY_CHG_PWR, 0x00);
81                 hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x17);
82                 break;
83         default:
84                 dev_info(hdmi_drv->dev, "unkown rk3036 hdmi pwr mode %d\n",
85                          mode);
86         }
87
88         hdmi_dev->pwr_mode = mode;
89 }
90
91 int rockchip_hdmiv1_detect_hotplug(struct hdmi *hdmi_drv)
92 {
93         int value = 0;
94         struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
95
96         hdmi_readl(hdmi_dev, HDMI_STATUS, &value);
97         value &= m_HOTPLUG;
98         if (value == m_HOTPLUG)
99                 return HDMI_HPD_ACTIVED;
100         else if (value)
101                 return HDMI_HPD_INSERT;
102         else
103                 return HDMI_HPD_REMOVED;
104 }
105
106 int rockchip_hdmiv1_insert(struct hdmi *hdmi_drv)
107 {
108         rockchip_hdmiv1_set_pwr_mode(hdmi_drv, NORMAL);
109         return 0;
110 }
111
112
113 int rockchip_hdmiv1_read_edid(struct hdmi *hdmi_drv, int block, u8 *buf)
114 {
115         u32 c = 0;
116         u8 segment = 0;
117         u8 offset = 0;
118         int ret = -1;
119         int i, j;
120         int ddc_bus_freq;
121         int trytime;
122         int checksum = 0;
123         struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
124
125         if (block % 2)
126                 offset = HDMI_EDID_BLOCK_SIZE;
127
128         if (block / 2)
129                 segment = 1;
130         ddc_bus_freq = (hdmi_dev->hclk_rate >> 2) / HDMI_SCL_RATE;
131         hdmi_writel(hdmi_dev, DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
132         hdmi_writel(hdmi_dev, DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
133
134         dev_info(hdmi_drv->dev,
135                  "EDID DATA (Segment = %d Block = %d Offset = %d):\n",
136                  (int)segment, (int)block, (int)offset);
137         disable_irq(hdmi_dev->irq);
138
139         /* Enable edid interrupt */
140         hdmi_writel(hdmi_dev, INTERRUPT_MASK1, m_INT_EDID_READY);
141
142         for (trytime = 0; trytime < 10; trytime++) {
143                 checksum = 0;
144                 hdmi_writel(hdmi_dev, INTERRUPT_STATUS1, 0x04);
145
146                 /* Set edid fifo first addr */
147                 hdmi_writel(hdmi_dev, EDID_FIFO_OFFSET, 0x00);
148
149                 /* Set edid word address 0x00/0x80 */
150                 hdmi_writel(hdmi_dev, EDID_WORD_ADDR, offset);
151
152                 /* Set edid segment pointer */
153                 hdmi_writel(hdmi_dev, EDID_SEGMENT_POINTER, segment);
154
155                 for (i = 0; i < 200; i++) {
156                         /* Wait edid interrupt */
157                         usleep_range(900, 1000);
158                         c = 0x00;
159                         hdmi_readl(hdmi_dev, INTERRUPT_STATUS1, &c);
160
161                         if (c & m_INT_EDID_READY)
162                                 break;
163                 }
164
165                 if (c & m_INT_EDID_READY) {
166                         for (j = 0; j < HDMI_EDID_BLOCK_SIZE; j++) {
167                                 c = 0;
168                                 hdmi_readl(hdmi_dev, 0x50, &c);
169                                 buf[j] = c;
170                                 checksum += c;
171 #ifdef HDMI_DEBUG
172                                 if (j % 16 == 0)
173                                         printk("\n>>>0x%02x: ", j);
174                                 printk("0x%02x ", c);
175 #endif
176                         }
177
178                         if ((checksum & 0xff) == 0) {
179                                 ret = 0;
180                                 dev_info(hdmi_drv->dev,
181                                          "[%s] edid read sucess\n", __func__);
182                                 break;
183                         }
184                 }
185         }
186         /*close edid irq*/
187         hdmi_writel(hdmi_dev, INTERRUPT_MASK1, 0);
188         /* clear EDID interrupt reg */
189         hdmi_writel(hdmi_dev, INTERRUPT_STATUS1,
190                     m_INT_EDID_READY);
191
192         enable_irq(hdmi_dev->irq);
193
194         return ret;
195 }
196
197 static const char coeff_csc[][24] = {
198         /*YUV2RGB:601 SD mode(Y[16:235],UV[16:240],RGB[0:255]):
199             R = 1.164*Y +1.596*V - 204
200             G = 1.164*Y - 0.391*U - 0.813*V + 154
201             B = 1.164*Y + 2.018*U - 258*/
202         {
203         0x04, 0xa7, 0x00, 0x00, 0x06, 0x62, 0x02, 0xcc,
204         0x04, 0xa7, 0x11, 0x90, 0x13, 0x40, 0x00, 0x9a,
205         0x04, 0xa7, 0x08, 0x12, 0x00, 0x00, 0x03, 0x02},
206
207         /*YUV2RGB:601 SD mode(YUV[0:255],RGB[0:255]):
208             R = Y + 1.402*V - 248
209             G = Y - 0.344*U - 0.714*V + 135
210             B = Y + 1.772*U - 227*/
211         {
212         0x04, 0x00, 0x00, 0x00, 0x05, 0x9b, 0x02, 0xf8,
213         0x04, 0x00, 0x11, 0x60, 0x12, 0xdb, 0x00, 0x87,
214         0x04, 0x00, 0x07, 0x16, 0x00, 0x00, 0x02, 0xe3},
215         /*YUV2RGB:709 HD mode(Y[16:235],UV[16:240],RGB[0:255]):
216             R = 1.164*Y +1.793*V - 248
217             G = 1.164*Y - 0.213*U - 0.534*V + 77
218             B = 1.164*Y + 2.115*U - 289*/
219         {
220         0x04, 0xa7, 0x00, 0x00, 0x07, 0x2c, 0x02, 0xf8,
221         0x04, 0xa7, 0x10, 0xda, 0x12, 0x22, 0x00, 0x4d,
222         0x04, 0xa7, 0x08, 0x74, 0x00, 0x00, 0x03, 0x21},
223         /*RGB2YUV:601 SD mode:
224             Cb = -0.291G  - 0.148R + 0.439B + 128
225             Y   = 0.504G   + 0.257R + 0.098B + 16
226             Cr  = -0.368G + 0.439R - 0.071B + 128*/
227         {
228         /*0x11, 0x78, 0x01, 0xc1, 0x10, 0x48, 0x00, 0x80,
229         0x02, 0x04, 0x01, 0x07, 0x00, 0x64, 0x00, 0x10,
230         0x11, 0x29, 0x10, 0x97, 0x01, 0xc1, 0x00, 0x80*/
231
232         /*0x11,0x4b,0x01,0x8a,0x10,0x3f,0x00,0x80,
233         0x01,0xbb,0x00,0xe2,0x00,0x56,0x00,0x1d,
234         0x11,0x05,0x10,0x85,0x01,0x8a,0x00,0x80*/
235
236         0x11, 0x5f, 0x01, 0x82, 0x10, 0x23, 0x00, 0x80,
237         0x02, 0x1c, 0x00, 0xa1, 0x00, 0x36, 0x00, 0x1e,
238         0x11, 0x29, 0x10, 0x59, 0x01, 0x82, 0x00, 0x80
239         },
240
241         /*RGB2YUV:709 HD mode:
242             Cb = - 0.338G - 0.101R +  0.439B + 128
243             Y  =    0.614G + 0.183R +  0.062B + 16
244             Cr = - 0.399G + 0.439R  -  0.040B + 128*/
245         {
246         0x11, 0x98, 0x01, 0xc1, 0x10, 0x28, 0x00, 0x80,
247         0x02, 0x74, 0x00, 0xbb, 0x00, 0x3f, 0x00, 0x10,
248         0x11, 0x5a, 0x10, 0x67, 0x01, 0xc1, 0x00, 0x80
249         },
250         /*RGB[0:255]2RGB[16:235]:
251         R' = R x (235-16)/255 + 16;
252         G' = G x (235-16)/255 + 16;
253         B' = B x (235-16)/255 + 16;*/
254         {
255         0x00, 0x00, 0x03, 0x6F, 0x00, 0x00, 0x00, 0x10,
256         0x03, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
257         0x00, 0x00, 0x00, 0x00, 0x03, 0x6F, 0x00, 0x10},
258 };
259
260 static int rockchip_hdmiv1_video_csc(struct hdmi *hdmi_drv,
261                                      struct hdmi_video *vpara)
262 {
263         int value, i, csc_mode, c0_c2_change, auto_csc, csc_enable;
264         const char *coeff = NULL;
265         struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
266
267         /* Enable or disalbe color space convert */
268         dev_info(hdmi_drv->dev, "[%s] input_color=%d,output_color=%d\n",
269                  __func__, vpara->color_input, vpara->color_output);
270         if (vpara->color_input == vpara->color_output) {
271                 if ((vpara->color_input >= HDMI_COLOR_YCBCR444) ||
272                     (vpara->color_input == HDMI_COLOR_RGB_0_255)) {
273                         value = v_SOF_DISABLE | v_COLOR_DEPTH_NOT_INDICATED(1);
274                         hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
275                         hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
276                                      m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_SWAP,
277                                      v_VIDEO_AUTO_CSC(AUTO_CSC_DISABLE) |
278                                      v_VIDEO_C0_C2_SWAP(C0_C2_CHANGE_DISABLE));
279                         return 0;
280                 } else if (vpara->color_input == HDMI_COLOR_RGB_16_235) {
281                         csc_mode = CSC_RGB_0_255_TO_RGB_16_235_8BIT;
282                         auto_csc = AUTO_CSC_DISABLE;
283                         c0_c2_change = C0_C2_CHANGE_DISABLE;
284                         csc_enable = v_CSC_ENABLE;
285                 }
286         }
287
288         switch (vpara->vic) {
289         case HDMI_720X480I_60HZ_4_3:
290         case HDMI_720X576I_50HZ_4_3:
291         case HDMI_720X480P_60HZ_4_3:
292         case HDMI_720X576P_50HZ_4_3:
293         case HDMI_720X480I_60HZ_16_9:
294         case HDMI_720X576I_50HZ_16_9:
295         case HDMI_720X480P_60HZ_16_9:
296         case HDMI_720X576P_50HZ_16_9:
297                 if (((vpara->color_input == HDMI_COLOR_RGB_0_255) ||
298                      (vpara->color_input == HDMI_COLOR_RGB_16_235)) &&
299                     vpara->color_output >= HDMI_COLOR_YCBCR444) {
300                         csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT;
301                         auto_csc = AUTO_CSC_DISABLE;
302                         c0_c2_change = C0_C2_CHANGE_DISABLE;
303                         csc_enable = v_CSC_ENABLE;
304                 } else if (vpara->color_input >= HDMI_COLOR_YCBCR444 &&
305                            ((vpara->color_output == HDMI_COLOR_RGB_0_255) ||
306                            (vpara->color_output == HDMI_COLOR_RGB_16_235))) {
307 #ifdef AUTO_DEFINE_CSC
308                         csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
309                         auto_csc = AUTO_CSC_ENABLE;
310                         c0_c2_change = C0_C2_CHANGE_DISABLE;
311                         csc_enable = v_CSC_DISABLE;
312 #else
313                         csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
314                         auto_csc = AUTO_CSC_DISABLE;
315                         c0_c2_change = C0_C2_CHANGE_ENABLE;
316                         csc_enable = v_CSC_ENABLE;
317 #endif
318                 }
319                 break;
320         default:
321                 if (((vpara->color_input == HDMI_COLOR_RGB_0_255) ||
322                      (vpara->color_input == HDMI_COLOR_RGB_16_235)) &&
323                     vpara->color_output >= HDMI_COLOR_YCBCR444) {
324                         csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT;
325                         auto_csc = AUTO_CSC_DISABLE;
326                         c0_c2_change = C0_C2_CHANGE_DISABLE;
327                         csc_enable = v_CSC_ENABLE;
328                 } else if (vpara->color_input >= HDMI_COLOR_YCBCR444 &&
329                            ((vpara->color_output == HDMI_COLOR_RGB_0_255) ||
330                            (vpara->color_output == HDMI_COLOR_RGB_16_235))) {
331 #ifdef AUTO_DEFINE_CSC
332                         csc_mode = CSC_ITU709_16_235_TO_RGB_0_255_8BIT;
333                         auto_csc = AUTO_CSC_ENABLE;
334                         c0_c2_change = C0_C2_CHANGE_DISABLE;
335                         csc_enable = v_CSC_DISABLE;
336 #else
337                         /*CSC_ITU709_16_235_TO_RGB_0_255_8BIT;*/
338                         csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
339                         auto_csc = AUTO_CSC_DISABLE;
340                         c0_c2_change = C0_C2_CHANGE_ENABLE;
341                         csc_enable = v_CSC_ENABLE;
342 #endif
343                 }
344                 break;
345         }
346
347         coeff = coeff_csc[csc_mode];
348         for (i = 0; i < 24; i++)
349                 hdmi_writel(hdmi_dev, VIDEO_CSC_COEF+i, coeff[i]);
350
351         value = v_SOF_DISABLE | csc_enable | v_COLOR_DEPTH_NOT_INDICATED(1);
352         hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
353         hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
354                      m_VIDEO_AUTO_CSC |
355                      m_VIDEO_C0_C2_SWAP,
356                      v_VIDEO_AUTO_CSC(auto_csc) |
357                      v_VIDEO_C0_C2_SWAP(c0_c2_change));
358
359 #if 0
360         if (vpara->input_color != vpara->output_color) {
361                 if (vpara->input_color == VIDEO_INPUT_COLOR_RGB) {/*rgb2yuv*/
362                         coeff = coeff_csc[3];
363                         for (i = 0; i < 24; i++)
364                                 hdmi_writel(hdmi_dev,
365                                             VIDEO_CSC_COEF+i, coeff[i]);
366
367                         value = v_SOF_DISABLE | v_CSC_ENABLE;
368                         hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
369                         hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
370                                      m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_EXCHANGE,
371                                      v_VIDEO_AUTO_CSC(0) |
372                                      v_VIDEO_C0_C2_EXCHANGE(1));
373                 } else {/*yuv2rgb*/
374 #ifdef AUTO_DEFINE_CSC
375                         value = v_SOF_DISABLE | v_CSC_DISABLE;
376                         hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
377                         hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
378                                      m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_EXCHANGE,
379                                      v_VIDEO_AUTO_CSC(1) |
380                                      v_VIDEO_C0_C2_EXCHANGE(1));
381 #else
382                         if (hdmi_drv->lcdc->cur_screen->mode.xres <= 576) {
383                                 /*x <= 576,REC-601*/
384                                 coeff = coeff_csc[0];
385                                 pr_info("xres<=576,xres=%d\n",
386                                         hdmi_drv->lcdc->cur_screen->mode.xres);
387                         } else/*x > 576,REC-709*/{
388                                 coeff = coeff_csc[2];
389                                 pr_info("xres>576,xres=%d\n",
390                                         hdmi_drv->lcdc->cur_screen->mode.xres);
391                         }
392                         for (i = 0; i < 24; i++)
393                                 hdmi_writel(hdmi_dev,
394                                             VIDEO_CSC_COEF+i, coeff[i]);
395
396                         value = v_SOF_DISABLE | v_CSC_ENABLE;
397                         hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
398                         hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
399                                      m_VIDEO_AUTO_CSC |
400                                      m_VIDEO_C0_C2_EXCHANGE,
401                                      v_VIDEO_AUTO_CSC(0) |
402                                      v_VIDEO_C0_C2_EXCHANGE(0));
403 #endif
404                 }
405         } else {
406                 if (vpara->input_color == VIDEO_INPUT_COLOR_RGB) {
407                         /*rgb[0:255]->rbg[16:235]*/
408                         coeff = coeff_csc[5];
409                         for (i = 0; i < 24; i++)
410                                 hdmi_writel(hdmi_dev,
411                                             VIDEO_CSC_COEF+i, coeff[i]);
412
413                         value = v_SOF_DISABLE | v_CSC_ENABLE;
414                         hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
415                         hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
416                                      m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_EXCHANGE,
417                                      v_VIDEO_AUTO_CSC(0) |
418                                      v_VIDEO_C0_C2_EXCHANGE(1));
419                 } else {
420                         value = v_SOF_DISABLE;
421                         hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
422                         hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
423                                      m_VIDEO_AUTO_CSC |
424                                      m_VIDEO_C0_C2_EXCHANGE,
425                                      v_VIDEO_AUTO_CSC(0) |
426                                      v_VIDEO_C0_C2_EXCHANGE(1));
427                 }
428         }
429 #endif
430         return 0;
431 }
432
433 static int rockchip_hdmiv1_config_vsi(struct hdmi *hdmi,
434                                       unsigned char vic_3d,
435                                       unsigned char format)
436 {
437         struct hdmi_dev *hdmi_dev = hdmi->property->priv;
438         char info[SIZE_VSI_INFOFRAME];
439         int i;
440
441         DBG("[%s] vic_3d %d format %d.\n", __func__, vic_3d, format);
442         memset(info, 0, SIZE_VSI_INFOFRAME);
443         hdmi_msk_reg(hdmi_dev, PACKET_SEND_AUTO,
444                      m_PACKET_VSI_EN, v_PACKET_VSI_EN(0));
445         hdmi_writel(hdmi_dev, CONTROL_PACKET_BUF_INDEX, INFOFRAME_VSI);
446         /* Header Bytes */
447         info[0] = 0x81;
448         info[1] = 0x01;
449         /* PB1 - PB3 contain the 24bit IEEE Registration Identifier */
450         info[4] = 0x03;
451         info[5] = 0x0c;
452         info[6] = 0x00;
453         /* PB4 - HDMI_Video_Format into bits 7:5 */
454         info[7] = format << 5;
455         /* PB5 - Depending on the video format, this byte will contain either
456            the HDMI_VIC code in buts 7:0, OR the 3D_Structure in bits 7:4. */
457         switch (format) {
458         case HDMI_VIDEO_FORMAT_4KX2K:
459                 /* This is a 2x4K mode, set the HDMI_VIC in buts 7:0.  Values
460                    are from HDMI 1.4 Spec, 8.2.3.1 (Table 8-13). */
461                 info[2] = 0x06 - 1;
462                 info[8] = vic_3d;
463                 info[9] = 0;
464                 break;
465         case HDMI_VIDEO_FORMAT_3D:
466                 /* This is a 3D mode, set the 3D_Structure in buts 7:4
467                    Bits 3:0 are reseved so set to 0.  Values are from HDMI 1.4
468                    Spec, Appendix H (Table H-2). */
469                 info[8] = vic_3d << 4;
470                 /* Add the Extended data field when the 3D format is
471                    Side-by-Side(Half). See Spec Table H-3 for details. */
472                 if ((info[8] >> 4) == HDMI_3D_SIDE_BY_SIDE_HALF) {
473                         info[2] = 0x06;
474                         info[9] = 0x00;
475                 } else {
476                         info[2] = 0x06 - 1;
477                 }
478                 break;
479         default:
480                 info[2] = 0x06 - 2;
481                 info[8] = 0;
482                 info[9] = 0;
483                 break;
484         }
485         info[3] = info[0] + info[1] + info[2];
486         /* Calculate InfoFrame ChecKsum */
487         for (i = 4; i < SIZE_VSI_INFOFRAME; i++)
488                 info[3] += info[i];
489         info[3] = 0x100 - info[3];
490
491         for (i = 0; i < SIZE_VSI_INFOFRAME; i++)
492                 hdmi_writel(hdmi_dev, CONTROL_PACKET_ADDR + i, info[i]);
493         hdmi_msk_reg(hdmi_dev, PACKET_SEND_AUTO,
494                      m_PACKET_VSI_EN, v_PACKET_VSI_EN(1));
495         return 0;
496 }
497
498 static void rockchip_hdmiv1_config_avi(struct hdmi *hdmi_drv,
499                                        unsigned char vic,
500                                        unsigned char output_color)
501 {
502         int i;
503         int avi_color_mode;
504         char info[SIZE_AVI_INFOFRAME];
505         struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
506
507         memset(info, 0, SIZE_AVI_INFOFRAME);
508         hdmi_writel(hdmi_dev, CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI);
509         info[0] = 0x82;
510         info[1] = 0x02;
511         info[2] = 0x0D;
512         info[3] = info[0] + info[1] + info[2];
513
514         if ((output_color == HDMI_COLOR_RGB_0_255) ||
515             (output_color == HDMI_COLOR_RGB_16_235))
516                 avi_color_mode = AVI_COLOR_MODE_RGB;
517         else if (output_color == HDMI_COLOR_YCBCR444)
518                 avi_color_mode = AVI_COLOR_MODE_YCBCR444;
519         else if (output_color == HDMI_COLOR_YCBCR422)
520                 avi_color_mode = AVI_COLOR_MODE_YCBCR422;
521
522         info[4] = (avi_color_mode << 5);
523         info[5] =
524             (AVI_COLORIMETRY_NO_DATA << 6) |
525             (AVI_CODED_FRAME_ASPECT_NO_DATA << 4) |
526             ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME;
527         info[6] = 0;
528         info[7] = vic;
529         if ((vic == HDMI_720X480I_60HZ_4_3) ||
530             (vic == HDMI_720X576I_50HZ_4_3) ||
531             (vic == HDMI_720X480I_60HZ_16_9) ||
532             (vic == HDMI_720X480I_60HZ_16_9))
533                 info[8] = 1;
534         else
535                 info[8] = 0;
536
537         /* Calculate AVI InfoFrame ChecKsum */
538         for (i = 4; i < SIZE_AVI_INFOFRAME; i++)
539                 info[3] += info[i];
540
541         info[3] = 0x100 - info[3];
542
543         for (i = 0; i < SIZE_AVI_INFOFRAME; i++)
544                 hdmi_writel(hdmi_dev, CONTROL_PACKET_ADDR + i, info[i]);
545 }
546
547 static int rockchip_hdmiv1_config_video(struct hdmi *hdmi_drv,
548                                         struct hdmi_video *vpara)
549 {
550         struct fb_videomode *mode;
551         struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
552         int value;
553
554         dev_dbg(hdmi_drv->dev, "[%s]\n", __func__);
555
556         if (vpara == NULL) {
557                 dev_err(hdmi_drv->dev, "[%s] input parameter error\n",
558                         __func__);
559                 return -1;
560         }
561
562         if (hdmi_dev->soctype == HDMI_SOC_RK3036) {
563                 /*rk3036 vop only can output rgb fmt*/
564                 vpara->color_input = HDMI_COLOR_RGB_0_255;
565         } else if (hdmi_dev->soctype == HDMI_SOC_RK312X) {
566                 /* rk3128 vop can output yuv444 fmt */
567                 /*if (vpara->input_color == VIDEO_INPUT_COLOR_YCBCR444)
568                         vpara->output_color = VIDEO_OUTPUT_YCBCR444;
569                 else
570                         vpara->output_color = VIDEO_OUTPUT_RGB444;*/
571         }
572
573         mode = (struct fb_videomode *)hdmi_vic_to_videomode(vpara->vic);
574         if (mode == NULL) {
575                 dev_err(hdmi_drv->dev, "[%s] not found vic %d\n", __func__,
576                         vpara->vic);
577                 return -ENOENT;
578         }
579         hdmi_dev->tmdsclk = mode->pixclock;
580         if (hdmi_drv->uboot)
581                 return 0;
582         /* Disable video and audio output */
583         hdmi_msk_reg(hdmi_dev, AV_MUTE,
584                      m_AUDIO_MUTE | m_VIDEO_BLACK,
585                      v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
586
587         /* Input video mode is SDR RGB24bit,
588            Data enable signal from external */
589         hdmi_writel(hdmi_dev, VIDEO_CONTRL1,
590                     v_VIDEO_INPUT_FORMAT(VIDEO_INPUT_SDR_RGB444) |
591                     v_DE_EXTERNAL);
592
593         value = v_VIDEO_INPUT_BITS(VIDEO_INPUT_8BITS);
594         if (vpara->color_output <= HDMI_COLOR_RGB_16_235)
595                 value |= v_VIDEO_OUTPUT_COLOR(0);
596         else
597                 value |= v_VIDEO_OUTPUT_COLOR((vpara->color_output - 2) & 0x3);
598         if (vpara->color_input <= HDMI_COLOR_RGB_16_235)
599                 value |= v_VIDEO_INPUT_CSP(0);
600         else
601                 value |= v_VIDEO_INPUT_CSP((vpara->color_input - 2) & 0x1);
602
603         hdmi_writel(hdmi_dev, VIDEO_CONTRL2, value);
604         /* Set HDMI Mode */
605         hdmi_writel(hdmi_dev, HDCP_CTRL, v_HDMI_DVI(vpara->sink_hdmi));
606
607         /* Enable or disalbe color space convert */
608         rockchip_hdmiv1_video_csc(hdmi_drv, vpara);
609
610         /* Set ext video timing */
611         if (mode->vmode || mode->pixclock <= 27000000) {
612                 hdmi_writel(hdmi_dev, VIDEO_TIMING_CTL, 0);
613         } else {
614                 value = v_EXTERANL_VIDEO(1) | v_INETLACE(mode->vmode);
615                 if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
616                         value |= v_HSYNC_POLARITY(1);
617                 if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
618                         value |= v_VSYNC_POLARITY(1);
619                 hdmi_writel(hdmi_dev, VIDEO_TIMING_CTL, value);
620
621                 value = mode->left_margin +
622                         mode->xres + mode->right_margin +
623                         mode->hsync_len;
624                 hdmi_writel(hdmi_dev, VIDEO_EXT_HTOTAL_L, value & 0xFF);
625                 hdmi_writel(hdmi_dev, VIDEO_EXT_HTOTAL_H, (value >> 8) & 0xFF);
626
627                 value = mode->left_margin +
628                         mode->right_margin +
629                         mode->hsync_len;
630                 hdmi_writel(hdmi_dev, VIDEO_EXT_HBLANK_L, value & 0xFF);
631                 hdmi_writel(hdmi_dev, VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);
632
633                 value = mode->left_margin + mode->hsync_len;
634                 hdmi_writel(hdmi_dev, VIDEO_EXT_HDELAY_L, value & 0xFF);
635                 hdmi_writel(hdmi_dev, VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);
636
637                 value = mode->hsync_len;
638                 hdmi_writel(hdmi_dev, VIDEO_EXT_HDURATION_L,
639                             value & 0xFF);
640                 hdmi_writel(hdmi_dev, VIDEO_EXT_HDURATION_H,
641                             (value >> 8) & 0xFF);
642
643                 value = mode->upper_margin + mode->yres + mode->lower_margin +
644                     mode->vsync_len;
645                 hdmi_writel(hdmi_dev, VIDEO_EXT_VTOTAL_L, value & 0xFF);
646                 hdmi_writel(hdmi_dev, VIDEO_EXT_VTOTAL_H, (value >> 8) & 0xFF);
647
648                 value = mode->upper_margin +
649                         mode->vsync_len +
650                         mode->lower_margin;
651                 hdmi_writel(hdmi_dev, VIDEO_EXT_VBLANK, value & 0xFF);
652
653                 if (vpara->vic == HDMI_720X480P_60HZ_4_3 ||
654                     vpara->vic == HDMI_720X480P_60HZ_16_9)
655                         value = 42;
656                 else
657                         value = mode->upper_margin + mode->vsync_len;
658
659                 hdmi_writel(hdmi_dev, VIDEO_EXT_VDELAY, value & 0xFF);
660
661                 value = mode->vsync_len;
662                 hdmi_writel(hdmi_dev, VIDEO_EXT_VDURATION, value & 0xFF);
663         }
664         if (vpara->sink_hdmi == OUTPUT_HDMI) {
665                 rockchip_hdmiv1_config_avi(hdmi_drv, vpara->vic,
666                                            vpara->color_output);
667                 if (vpara->format_3d != HDMI_3D_NONE) {
668                         rockchip_hdmiv1_config_vsi(hdmi_drv,
669                                                    vpara->format_3d,
670                                                    HDMI_VIDEO_FORMAT_3D);
671                 } else if ((vpara->vic > 92 && vpara->vic < 96) ||
672                          (vpara->vic == 98)) {
673                         vpara->vic = (vpara->vic == 98) ?
674                                      4 : (96 - vpara->vic);
675                         rockchip_hdmiv1_config_vsi(hdmi_drv,
676                                                    vpara->vic,
677                                                    HDMI_VIDEO_FORMAT_4KX2K);
678                 } else {
679                         rockchip_hdmiv1_config_vsi(hdmi_drv,
680                                                    vpara->vic,
681                                                    HDMI_VIDEO_FORMAT_NORMAL);
682                 }
683                 dev_info(hdmi_drv->dev,
684                          "[%s] sucess output HDMI.\n", __func__);
685         } else {
686                 dev_info(hdmi_drv->dev,
687                          "[%s] sucess output DVI.\n", __func__);
688         }
689
690         /* rk3028a */
691         hdmi_writel(hdmi_dev, PHY_PRE_DIV_RATIO, 0x1e);
692         hdmi_writel(hdmi_dev, PHY_FEEDBACK_DIV_RATIO_LOW, 0x2c);
693         hdmi_writel(hdmi_dev, PHY_FEEDBACK_DIV_RATIO_HIGH, 0x01);
694
695         return 0;
696 }
697
698 static void rockchip_hdmiv1_config_aai(struct hdmi *hdmi_drv)
699 {
700         int i;
701         char info[SIZE_AUDIO_INFOFRAME];
702         struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
703
704         memset(info, 0, SIZE_AUDIO_INFOFRAME);
705
706         info[0] = 0x84;
707         info[1] = 0x01;
708         info[2] = 0x0A;
709
710         info[3] = info[0] + info[1] + info[2];
711         for (i = 4; i < SIZE_AUDIO_INFOFRAME; i++)
712                 info[3] += info[i];
713
714         info[3] = 0x100 - info[3];
715
716         hdmi_writel(hdmi_dev, CONTROL_PACKET_BUF_INDEX, INFOFRAME_AAI);
717         for (i = 0; i < SIZE_AUDIO_INFOFRAME; i++)
718                 hdmi_writel(hdmi_dev, CONTROL_PACKET_ADDR + i, info[i]);
719 }
720
721 static int rockchip_hdmiv1_config_audio(struct hdmi *hdmi_drv,
722                                         struct hdmi_audio *audio)
723 {
724         int rate, N, channel, mclk_fs;
725         struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
726
727         if (audio->channel < 3)
728                 channel = I2S_CHANNEL_1_2;
729         else if (audio->channel < 5)
730                 channel = I2S_CHANNEL_3_4;
731         else if (audio->channel < 7)
732                 channel = I2S_CHANNEL_5_6;
733         else
734                 channel = I2S_CHANNEL_7_8;
735
736         switch (audio->rate) {
737         case HDMI_AUDIO_FS_32000:
738                 rate = AUDIO_32K;
739                 N = N_32K;
740                 mclk_fs = MCLK_384FS;
741                 break;
742         case HDMI_AUDIO_FS_44100:
743                 rate = AUDIO_441K;
744                 N = N_441K;
745                 mclk_fs = MCLK_256FS;
746                 break;
747         case HDMI_AUDIO_FS_48000:
748                 rate = AUDIO_48K;
749                 N = N_48K;
750                 mclk_fs = MCLK_256FS;
751                 break;
752         case HDMI_AUDIO_FS_88200:
753                 rate = AUDIO_882K;
754                 N = N_882K;
755                 mclk_fs = MCLK_128FS;
756                 break;
757         case HDMI_AUDIO_FS_96000:
758                 rate = AUDIO_96K;
759                 N = N_96K;
760                 mclk_fs = MCLK_128FS;
761                 break;
762         case HDMI_AUDIO_FS_176400:
763                 rate = AUDIO_1764K;
764                 N = N_1764K;
765                 mclk_fs = MCLK_128FS;
766                 break;
767         case HDMI_AUDIO_FS_192000:
768                 rate = AUDIO_192K;
769                 N = N_192K;
770                 mclk_fs = MCLK_128FS;
771                 break;
772         default:
773                 dev_err(hdmi_drv->dev,
774                         "[%s] not support such sample rate %d\n",
775                         __func__, audio->rate);
776                 return -ENOENT;
777         }
778
779         /* set_audio source I2S */
780         if (hdmi_dev->audiosrc == HDMI_AUDIO_SRC_IIS) {
781                 hdmi_writel(hdmi_dev, AUDIO_CTRL1, 0x00);
782                 hdmi_writel(hdmi_dev, AUDIO_SAMPLE_RATE, rate);
783                 hdmi_writel(hdmi_dev, AUDIO_I2S_MODE,
784                             v_I2S_MODE(I2S_STANDARD) |
785                             v_I2S_CHANNEL(channel));
786                 hdmi_writel(hdmi_dev, AUDIO_I2S_MAP, 0x00);
787                 /* no swap */
788                 hdmi_writel(hdmi_dev, AUDIO_I2S_SWAPS_SPDIF, 0);
789         } else {
790                 hdmi_writel(hdmi_dev, AUDIO_CTRL1, 0x08);
791                 /* no swap */
792                 hdmi_writel(hdmi_dev, AUDIO_I2S_SWAPS_SPDIF, 0);
793         }
794
795         /* Set N value */
796         hdmi_writel(hdmi_dev, AUDIO_N_H, (N >> 16) & 0x0F);
797         hdmi_writel(hdmi_dev, AUDIO_N_M, (N >> 8) & 0xFF);
798         hdmi_writel(hdmi_dev, AUDIO_N_L, N & 0xFF);
799         rockchip_hdmiv1_config_aai(hdmi_drv);
800
801         return 0;
802 }
803
804 int rockchip_hdmiv1_control_output(struct hdmi *hdmi_drv, int enable)
805 {
806         int mutestatus = 0;
807         struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
808
809         if (hdmi_drv->uboot) {
810                 hdmi_drv->uboot = 0;
811                 return 0;
812         }
813
814         if (enable == HDMI_AV_UNMUTE) {
815                 if (hdmi_dev->pwr_mode == LOWER_PWR)
816                         rockchip_hdmiv1_set_pwr_mode(hdmi_drv, NORMAL);
817
818                 rockchip_hdmiv1_sys_power(hdmi_drv, true);
819                 rockchip_hdmiv1_sys_power(hdmi_drv, false);
820                 delay100us();
821                 rockchip_hdmiv1_sys_power(hdmi_drv, true);
822                 hdmi_writel(hdmi_dev, 0xce, 0x00);
823                 delay100us();
824                 hdmi_writel(hdmi_dev, 0xce, 0x01);
825
826                 hdmi_readl(hdmi_dev, AV_MUTE, &mutestatus);
827                 if (mutestatus && (m_AUDIO_MUTE | m_VIDEO_BLACK)) {
828                         hdmi_msk_reg(hdmi_dev, AV_MUTE,
829                                      m_AUDIO_MUTE | m_VIDEO_BLACK,
830                                      v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
831                 }
832                 rockchip_hdmiv1_av_mute(hdmi_drv, 0);
833         } else {
834                 hdmi_msk_reg(hdmi_dev, AV_MUTE,
835                              m_AUDIO_MUTE | m_VIDEO_BLACK,
836                              v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
837                 rockchip_hdmiv1_av_mute(hdmi_drv, 1);
838                 msleep(100);
839                 rockchip_hdmiv1_set_pwr_mode(hdmi_drv, LOWER_PWR);
840         }
841         return 0;
842 }
843
844 int rockchip_hdmiv1_removed(struct hdmi *hdmi_drv)
845 {
846         dev_info(hdmi_drv->dev, "Removed.\n");
847         if (hdmi_drv->ops->hdcp_power_off_cb)
848                 hdmi_drv->ops->hdcp_power_off_cb();
849
850         rockchip_hdmiv1_control_output(hdmi_drv, -1);
851         rockchip_hdmiv1_set_pwr_mode(hdmi_drv, LOWER_PWR);
852
853         return HDMI_ERROR_SUCESS;
854 }
855
856 static int rockchip_hdmiv1_enable(struct hdmi *hdmi_drv)
857 {
858         struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
859
860         if (!hdmi_dev->enable)
861                 hdmi_dev->enable = 1;
862         hdmi_submit_work(hdmi_drv, HDMI_HPD_CHANGE, 10, NULL);
863         return 0;
864 }
865
866 static int rockchip_hdmiv1_disable(struct hdmi *hdmi_drv)
867 {
868         struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
869
870         if (hdmi_dev->enable)
871                 hdmi_dev->enable = 0;
872
873         return 0;
874 }
875
876 void rockchip_hdmiv1_irq(struct hdmi *hdmi_drv)
877 {
878         u32 interrupt = 0;
879         struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
880
881         hdmi_readl(hdmi_dev, INTERRUPT_STATUS1, &interrupt);
882         if (interrupt) {
883                 hdmi_writel(hdmi_dev, INTERRUPT_STATUS1, interrupt);
884                 dev_info(hdmi_drv->dev, "Clear edid irq.\n");
885         }
886
887         hdmi_readl(hdmi_dev, HDMI_STATUS, &interrupt);
888         if (interrupt)
889                 hdmi_writel(hdmi_dev, HDMI_STATUS, interrupt);
890         if (interrupt & m_INT_HOTPLUG)
891                 hdmi_submit_work(hdmi_drv, HDMI_HPD_CHANGE, 20, NULL);
892
893         if (hdmi_drv->ops->hdcp_irq_cb)
894                 hdmi_drv->ops->hdcp_irq_cb(0);
895         if (hdmi_drv->property->feature & SUPPORT_CEC)
896                 rockchip_hdmiv1_cec_isr(hdmi_dev);
897 }
898
899 static void rockchip_hdmiv1_reset(struct hdmi *hdmi_drv)
900 {
901         u32 val = 0;
902         u32 msk = 0;
903         struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
904
905         hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_RST_DIGITAL, v_NOT_RST_DIGITAL);
906         delay100us();
907         hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_RST_ANALOG, v_NOT_RST_ANALOG);
908         delay100us();
909         msk = m_REG_CLK_INV | m_REG_CLK_SOURCE | m_POWER | m_INT_POL;
910         val = v_REG_CLK_INV | v_REG_CLK_SOURCE_SYS | v_PWR_ON | v_INT_POL_HIGH;
911         hdmi_msk_reg(hdmi_dev, SYS_CTRL, msk, val);
912
913         rockchip_hdmiv1_set_pwr_mode(hdmi_drv, LOWER_PWR);
914 }
915
916 void rockchip_hdmiv1_dev_init_ops(struct hdmi_ops *ops)
917 {
918         if (ops) {
919                 ops->disable = rockchip_hdmiv1_disable;
920                 ops->enable = rockchip_hdmiv1_enable;
921                 ops->remove = rockchip_hdmiv1_removed;
922                 ops->setmute = rockchip_hdmiv1_control_output;
923                 ops->setvideo = rockchip_hdmiv1_config_video;
924                 ops->setaudio = rockchip_hdmiv1_config_audio;
925                 ops->getstatus = rockchip_hdmiv1_detect_hotplug;
926                 ops->getedid = rockchip_hdmiv1_read_edid;
927                 ops->insert     = rockchip_hdmiv1_insert;
928                 ops->setvsi = rockchip_hdmiv1_config_vsi;
929         }
930 }
931
932 int rockchip_hdmiv1_initial(struct hdmi *hdmi_drv)
933 {
934         int rc = HDMI_ERROR_SUCESS;
935         struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
936
937         hdmi_dev->pwr_mode = NORMAL;
938
939         if (!hdmi_drv->uboot) {
940                 rockchip_hdmiv1_reset_pclk();
941                 rockchip_hdmiv1_reset(hdmi_drv);
942         } else if (hdmi_drv->ops->getstatus(hdmi_drv) == HDMI_HPD_REMOVED) {
943                 rockchip_hdmiv1_removed(hdmi_drv);
944                 hdmi_drv->lcdc->uboot_logo = 0;
945                 hdmi_drv->uboot = 0;
946         }
947         if (hdmi_drv->property->feature & SUPPORT_CEC)
948                 rockchip_hdmiv1_cec_init(hdmi_drv);
949         if (hdmi_drv->property->feature & SUPPORT_HDCP)
950                 rockchip_hdmiv1_hdcp_init(hdmi_drv);
951         return rc;
952 }