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