1.rockchip:screen: add color-mode node in screen timing and add prop at lcd-xxx.dtsi
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / hdmi / rk_hdmi_lcdc.c
1 #include <linux/console.h>
2 #include<linux/rk_fb.h>
3 #include "rk_hdmi.h"
4
5 #define OUT_TYPE                SCREEN_HDMI
6 #define OUT_FACE                OUT_P888
7 #define DCLK_POL                1
8 #define SWAP_RB                 0
9 #define LCD_ACLK                800000000
10
11 struct hdmi *m_hdmi_drv;
12
13 static const struct fb_videomode hdmi_mode[] = {
14         /*      name            refresh xres    yres    pixclock                h_bp    h_fp    v_bp    v_fp    h_pw    v_pw                    polariry                        PorI    flag(used for vic) */
15 /*
16         {"640x480p@60Hz",       60,     640,    480,    25175000,       48,     16,     33,     10,     96,     2,                      0,                              0,      1 },
17 */
18         {"720x480i@60Hz",       60,     720,    480,    27000000,       57,     19,   15,     4,        62,     3,                      0,                              1,      6 },
19         {"720x576i@50Hz",       50,     720,    576,    27000000,       69,     12,     19,     2,      63,     3,                      0,                              1,      21},
20         {"720x480p@60Hz",       60,     720,    480,    27000000,       60,     16,     30,     9,      62,     6,                      0,                              0,      2 },
21         {"720x576p@50Hz",       50,     720,    576,    27000000,       68,     12,     39,     5,      64,     5,                      0,                              0,      17},
22 /*
23         {"1280x720p@24Hz",      24,     1280,   720,    59400000,       220,    1760,   20,     5,      40,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      60},
24         {"1280x720p@25Hz",      25,     1280,   720,    74250000,       220,    2420,   20,     5,      40,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      61},
25         {"1280x720p@30Hz",      30,     1280,   720,    74250000,       220,    1760,   20,     5,      40,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      62},
26 */
27         {"1280x720p@50Hz",      50,     1280,   720,    74250000,       220,    440,    20,     5,      40,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      19},
28         {"1280x720p@60Hz",      60,     1280,   720,    74250000,       220,    110,    20,     5,      40,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      4 },
29 /*
30         {"1920x1080p@24Hz",     24,     1920,   1080,   74250000,       148,    638,    36,     4,      44,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      32},
31         {"1920x1080p@25Hz",     25,     1920,   1080,   74250000,       148,    528,    36,     4,      44,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      33},
32         {"1920x1080p@30Hz",     30,     1920,   1080,   74250000,       148,    88,     36,     4,      44,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      34},
33         {"1920x1080i@50Hz_2",   50,     1920,   1080,   72000000,       184,    32,     57,     23,     168,    5,      FB_SYNC_HOR_HIGH_ACT,                           1,      39},
34 */
35         {"1920x1080i@50Hz",     50,     1920,   1080,   74250000,       148,    528,    15,     2,      44,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   1,      20},
36         {"1920x1080i@60Hz",     60,     1920,   1080,   74250000,       148,    88,     15,     2,      44,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   1,      5 },
37         {"1920x1080p@50Hz",     50,     1920,   1080,   148500000,      148,    528,    36,     4,      44,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      31},
38         {"1920x1080p@60Hz",     60,     1920,   1080,   148500000,      148,    88,     36,     4,      44,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      16},
39 /*
40         {"1440x288p@50Hz",      50,     720,    480,    27000000,       138,    24,     19,     2,      126,    3,                      0,                              0,      23},
41         {"2880x576i@50Hz",      50,     1440,   240,    54000000,       276,    48,     19,     2,      252,    3,                      0,                              1,      25},
42         {"2880x288p@50Hz",      50,     2880,   480,    54000000,       276,    48,     19,     3,      252,    3,                      0,                              0,      27},
43         {"1440x576p@50Hz",      50,     2880,   480,    54000000,       136,    24,     39,     5,      128,    5,                      0,                              0,      29},
44         {"2880x576p@50Hz",      50,     1920,   1080,   108000000,      272,    48,     39,     5,      256,    5,                      0,                              0,      37},
45         {"1440x240p@60Hz",      60,     1440,   240,    27000000,       114,    38,     15,     4,      124,    3,                      0,                              0,      8 },
46         {"2880x480i@60Hz",      60,     2880,   480,    54000000,       228,    76,     15,     4,      248,    3,                      0,                              1,      10},
47         {"2880x480p@60Hz",      60,     2880,   480,    54000000,       228,    76,     15,     4,      248,    3,                      0,                              0,      12},
48         {"1440x480p@60Hz",      60,     1440,   480,    54000000,       120,    32,     30,     9,      124,    6,                      0,                              0,      14},
49         {"2880x480p@60Hz",      60,     2880,   480,    54000000,       240,    64,     30,     9,      248,    6,                      0,                              0,      35},
50
51         {"1920x1080i@100Hz",    100,    1920,   1080,   148500000,      148,    528,    15,     2,      44,     5,                      1,                              1,      40},
52         {"1280x720p@100Hz",     100,    1280,   720,    148500000,      220,    440,    20,     5,      40,     5,                      1,                              0,      41},
53         {"720x576p@100Hz",      100,    720,    576,    54000000,       68,     12,     39,     5,      64,     5,                      0,                              0,      42},
54         {"1440x576i@100Hz",     100,    1440,   576,    54000000,       138,    24,     19,     2,      12,     3,                      0,                              1,      44},
55         {"1920x1080p@100Hz",    100,    1920,   1080,   297000000,      148,    528,    36,     4,      44,     5,                      1,                              0,      64},
56
57         {"1920x1080i@120Hz",    120,    1920,   1080,   148500000,      148,    88,     15,     2,      44,     5,                      1,                              1,      46},
58         {"1280x720p@120Hz",     120,    1280,   720,    148500000,      220,    110,    20,     5,      40,     5,                      1,                              0,      47},
59         {"720x480p@120Hz",      120,    720,    480,    54000000,       60,     16,     30,     9,      62,     6,                      0,                              0,      48},
60         {"1440x480i@120Hz",     120,    1440,   480,    54000000,       114,    38,     15,     4,      12,     3,                      0,                              1,      50},
61         {"1920x1080p@120Hz",    120,    1920,   1080,   297000000,      148,    88,     36,     4,      44,     5,                      1,                              0,      63},
62
63         {"720x576p@200Hz",      200,    720,    576,    108000000,      68,     12,     39,     5,      64,     5,                      0,                              0,      52},
64         {"1440x576i@200Hz",     200,    1920,   1080,   108000000,      138,    24,     19,     2,      12,     3,                      0,                              1,      54},
65
66         {"720x480p@240Hz",      240,    720,    480,    108000000,      60,     16,     30,     9,      62,     6,                      0,                              0,      56},
67         {"1440x480i@240Hz",     240,    1440,   480,    108000000,      114,    38,     15,     4,      12,     3,                      0,                              1,      58},
68 */
69         {"3840x2160p@24Hz",     24,     3840,   2160,   297000000,      296,    1276,   72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      93},
70         {"3840x2160p@25Hz",     25,     3840,   2160,   297000000,      296,    1056,   72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      94},
71         {"3840x2160p@30Hz",     30,     3840,   2160,   297000000,      296,    176,    72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      95},
72         {"3840x2160p@50Hz",     50,     3840,   2160,   594000000,      296,    1056,   72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      96},
73         {"3840x2160p@60Hz",     60,     3840,   2160,   594000000,      296,    176,    72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      97},
74         {"4096x2160p@24Hz",     24,     4096,   2160,   297000000,      296,    1020,   72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      98},
75         {"4096x2160p@25Hz",     25,     4096,   2160,   297000000,      128,    968,    72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      99},
76         {"4096x2160p@30Hz",     30,     4096,   2160,   297000000,      128,    88,     72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      100},
77         {"4096x2160p@50Hz",     50,     4096,   2160,   594000000,      128,    968,    72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      101},
78         {"4096x2160p@60Hz",     60,     4096,   2160,   594000000,      128,    88,     72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      102},
79
80 };
81
82 void hdmi_init_lcdc(struct rk_screen *screen, struct rk29lcd_info *lcd_info)
83 {
84         hdmi_set_info(screen, HDMI_VIDEO_DEFAULT_MODE);
85 }
86
87 int hdmi_set_info(struct rk_screen *screen, unsigned int vic)
88 {
89         int i;
90
91         if (screen == NULL)
92                 return -1;
93
94         if (vic == 0)
95                 vic = HDMI_VIDEO_DEFAULT_MODE;
96
97         for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
98                 if (hdmi_mode[i].flag == vic)
99                         break;
100         }
101         if (i == ARRAY_SIZE(hdmi_mode))
102                 return -1;
103
104         memset(screen, 0, sizeof(struct rk_screen));
105
106         /* screen type & face */
107         screen->type = OUT_TYPE;
108         screen->face = OUT_FACE;
109         screen->color_mode = COLOR_YCBCR;
110
111         /* Screen size */
112         screen->mode.xres = hdmi_mode[i].xres;
113         screen->mode.yres = hdmi_mode[i].yres;
114
115         /* Timing */
116         screen->mode.pixclock = hdmi_mode[i].pixclock;
117         screen->mode.refresh = hdmi_mode[i].refresh;
118         /* screen->lcdc_aclk = LCD_ACLK; */
119         screen->mode.left_margin = hdmi_mode[i].left_margin;
120         screen->mode.right_margin = hdmi_mode[i].right_margin;
121         screen->mode.hsync_len = hdmi_mode[i].hsync_len;
122         screen->mode.upper_margin = hdmi_mode[i].upper_margin;
123         screen->mode.lower_margin = hdmi_mode[i].lower_margin;
124         screen->mode.vsync_len = hdmi_mode[i].vsync_len;
125         screen->mode.vmode = hdmi_mode[i].vmode;
126         screen->hdmi_resolution = hdmi_mode[i].flag;
127         if ((screen->hdmi_resolution == HDMI_720X480I_60HZ_VIC) ||
128                 (screen->hdmi_resolution == HDMI_720X576I_50HZ_VIC))
129                 screen->pixelrepeat = 1;
130
131         /* Pin polarity */
132 #if defined(CONFIG_HDMI_RK616) && !defined(CONFIG_ARCH_RK3026)
133         screen->pin_hsync = 0;
134         screen->pin_vsync = 0;
135 #else
136         screen->pin_hsync = 0;
137         if (FB_SYNC_HOR_HIGH_ACT & hdmi_mode[i].sync)
138                 screen->pin_hsync = 1;
139         else
140                 screen->pin_hsync = 0;
141         if (FB_SYNC_VERT_HIGH_ACT & hdmi_mode[i].sync)
142                 screen->pin_vsync = 1;
143         else
144                 screen->pin_vsync = 0;
145 #endif
146         screen->pin_den = 0;
147         screen->pin_dclk = DCLK_POL;
148
149         /* Swap rule */
150         screen->swap_rb = SWAP_RB;
151         screen->swap_rg = 0;
152         screen->swap_gb = 0;
153         screen->swap_delta = 0;
154         screen->swap_dumy = 0;
155
156         /* Operation function */
157         screen->init = NULL;
158         screen->standby = NULL;
159
160         /* Init Default Overscan Value:
161          * TODO modify the value according to your need adjust value
162          */
163         switch (vic) {
164         case 16:                /* 1080p-60Hz */
165                 screen->overscan.left = 97;
166                 screen->overscan.top = 97;
167                 screen->overscan.right = 97;
168                 screen->overscan.bottom = 97;
169                 break;
170         default:
171                 screen->overscan.left = 96;
172                 screen->overscan.top = 96;
173                 screen->overscan.right = 96;
174                 screen->overscan.bottom = 96;
175                 break;
176         }
177
178         return 0;
179 }
180
181 #ifdef HDMI_DEBUG
182 static void hdmi_show_sink_info(struct hdmi *hdmi)
183 {
184         struct list_head *pos, *head = &hdmi->edid.modelist;
185         struct fb_modelist *modelist;
186         struct fb_videomode *m;
187         int i;
188         struct hdmi_audio *audio;
189
190         hdmi_dbg(hdmi->dev, "******** Show Sink Info ********\n");
191         hdmi_dbg(hdmi->dev, "Support video mode:\n");
192         list_for_each(pos, head) {
193                 modelist = list_entry(pos, struct fb_modelist, list);
194                 m = &modelist->mode;
195                 hdmi_dbg(hdmi->dev, "   %s.\n", m->name);
196         }
197
198         for (i = 0; i < hdmi->edid.audio_num; i++) {
199                 audio = &(hdmi->edid.audio[i]);
200                 switch (audio->type) {
201                 case HDMI_AUDIO_LPCM:
202                         hdmi_dbg(hdmi->dev, "Support audio type: LPCM\n");
203                         break;
204                 case HDMI_AUDIO_AC3:
205                         hdmi_dbg(hdmi->dev, "Support audio type: AC3\n");
206                         break;
207                 case HDMI_AUDIO_MPEG1:
208                         hdmi_dbg(hdmi->dev, "Support audio type: MPEG1\n");
209                         break;
210                 case HDMI_AUDIO_MP3:
211                         hdmi_dbg(hdmi->dev, "Support audio type: MP3\n");
212                         break;
213                 case HDMI_AUDIO_MPEG2:
214                         hdmi_dbg(hdmi->dev, "Support audio type: MPEG2\n");
215                         break;
216                 case HDMI_AUDIO_AAC_LC:
217                         hdmi_dbg(hdmi->dev, "Support audio type: AAC\n");
218                         break;
219                 case HDMI_AUDIO_DTS:
220                         hdmi_dbg(hdmi->dev, "Support audio type: DTS\n");
221                         break;
222                 case HDMI_AUDIO_ATARC:
223                         hdmi_dbg(hdmi->dev, "Support audio type: ATARC\n");
224                         break;
225                 case HDMI_AUDIO_DSD:
226                         hdmi_dbg(hdmi->dev, "Support audio type: DSD\n");
227                         break;
228                 case HDMI_AUDIO_E_AC3:
229                         hdmi_dbg(hdmi->dev, "Support audio type: E-AC3\n");
230                         break;
231                 case HDMI_AUDIO_DTS_HD:
232                         hdmi_dbg(hdmi->dev, "Support audio type: DTS-HD\n");
233                         break;
234                 case HDMI_AUDIO_MLP:
235                         hdmi_dbg(hdmi->dev, "Support audio type: MLP\n");
236                         break;
237                 case HDMI_AUDIO_DST:
238                         hdmi_dbg(hdmi->dev, "Support audio type: DST\n");
239                         break;
240                 case HDMI_AUDIO_WMA_PRO:
241                         hdmi_dbg(hdmi->dev, "Support audio type: WMP-PRO\n");
242                         break;
243                 default:
244                         hdmi_dbg(hdmi->dev, "Support audio type: Unkown\n");
245                         break;
246                 }
247
248                 hdmi_dbg(hdmi->dev, "Support audio sample rate:\n");
249                 if (audio->rate & HDMI_AUDIO_FS_32000)
250                         hdmi_dbg(hdmi->dev, "   32000\n");
251                 if (audio->rate & HDMI_AUDIO_FS_44100)
252                         hdmi_dbg(hdmi->dev, "   44100\n");
253                 if (audio->rate & HDMI_AUDIO_FS_48000)
254                         hdmi_dbg(hdmi->dev, "   48000\n");
255                 if (audio->rate & HDMI_AUDIO_FS_88200)
256                         hdmi_dbg(hdmi->dev, "   88200\n");
257                 if (audio->rate & HDMI_AUDIO_FS_96000)
258                         hdmi_dbg(hdmi->dev, "   96000\n");
259                 if (audio->rate & HDMI_AUDIO_FS_176400)
260                         hdmi_dbg(hdmi->dev, "   176400\n");
261                 if (audio->rate & HDMI_AUDIO_FS_192000)
262                         hdmi_dbg(hdmi->dev, "   192000\n");
263
264                 hdmi_dbg(hdmi->dev, "Support audio word lenght:\n");
265                 if (audio->rate & HDMI_AUDIO_WORD_LENGTH_16bit)
266                         hdmi_dbg(hdmi->dev, "   16bit\n");
267                 if (audio->rate & HDMI_AUDIO_WORD_LENGTH_20bit)
268                         hdmi_dbg(hdmi->dev, "   20bit\n");
269                 if (audio->rate & HDMI_AUDIO_WORD_LENGTH_24bit)
270                         hdmi_dbg(hdmi->dev, "   24bit\n");
271         }
272         hdmi_dbg(hdmi->dev, "******** Show Sink Info ********\n");
273 }
274 #endif
275
276 /**
277  * hdmi_ouputmode_select - select hdmi transmitter output mode: hdmi or dvi?
278  * @hdmi: handle of hdmi
279  * @edid_ok: get EDID data success or not, HDMI_ERROR_SUCESS means success.
280  */
281 int hdmi_ouputmode_select(struct hdmi *hdmi, int edid_ok)
282 {
283         struct list_head *head = &hdmi->edid.modelist;
284         struct fb_monspecs *specs = hdmi->edid.specs;
285         struct fb_videomode *modedb = NULL;
286         int i, pixclock;
287
288         if (edid_ok != HDMI_ERROR_SUCESS) {
289                 dev_err(hdmi->dev,
290                         "warning: EDID error, assume sink as HDMI and asume minitor support audio output!!!!");
291                 hdmi->edid.sink_hdmi = 1;
292                 /* if edid error,asume monitor support audio output */
293                 hdmi->edid.base_audio_support = 1;
294         }
295
296         if (edid_ok != HDMI_ERROR_SUCESS) {
297                 hdmi->edid.ycbcr444 = 0;
298                 hdmi->edid.ycbcr422 = 0;
299                 hdmi->autoconfig = HDMI_DISABLE;
300         }
301         if (head->next == head) {
302                 dev_info(hdmi->dev,
303                          "warning: no CEA video mode parsed from EDID !!!!");
304                 /* If EDID get error, list all system supported mode.
305                  * If output mode is set to DVI and EDID is ok, check
306                  * the output timing.
307                  */
308
309                 if (hdmi->edid.sink_hdmi == 0 && specs && specs->modedb_len) {
310                         /* Get max resolution timing */
311                         modedb = &specs->modedb[0];
312                         for (i = 0; i < specs->modedb_len; i++) {
313                                 if (specs->modedb[i].xres > modedb->xres)
314                                         modedb = &specs->modedb[i];
315                                 else if (specs->modedb[i].yres > modedb->yres)
316                                         modedb = &specs->modedb[i];
317                         }
318                         /* For some monitor, the max pixclock read from EDID
319                          * is smaller than the clock of
320                          * max resolution mode supported.
321                          */
322                         pixclock = PICOS2KHZ(modedb->pixclock);
323                         pixclock /= 250;
324                         pixclock *= 250;
325                         pixclock *= 1000;
326                         if (pixclock == 148250000)
327                                 pixclock = 148500000;
328                         if (pixclock > specs->dclkmax)
329                                 specs->dclkmax = pixclock;
330                 }
331
332                 for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
333                         if (modedb) {
334                                 if ((hdmi_mode[i].pixclock < specs->dclkmin) ||
335                                     (hdmi_mode[i].pixclock > specs->dclkmax) ||
336                                     (hdmi_mode[i].refresh < specs->vfmin) ||
337                                     (hdmi_mode[i].refresh > specs->vfmax) ||
338                                     (hdmi_mode[i].xres > modedb->xres) ||
339                                     (hdmi_mode[i].yres > modedb->yres))
340                                         continue;
341                         }
342                         hdmi_add_videomode(&hdmi_mode[i], head);
343                 }
344         }
345 #ifdef HDMI_DEBUG
346         hdmi_show_sink_info(hdmi);
347 #endif
348         return HDMI_ERROR_SUCESS;
349 }
350
351 /**
352  * hdmi_videomode_compare - compare 2 videomodes
353  * @mode1: first videomode
354  * @mode2: second videomode
355  *
356  * RETURNS:
357  * 1 if mode1 > mode2, 0 if mode1 = mode2, -1 mode1 < mode2
358  */
359 static int hdmi_videomode_compare(const struct fb_videomode *mode1,
360                                   const struct fb_videomode *mode2)
361 {
362         if (mode1->xres > mode2->xres)
363                 return 1;
364         else if (mode1->xres == mode2->xres) {
365                 if (mode1->yres > mode2->yres)
366                         return 1;
367                 else if (mode1->yres == mode2->yres) {
368                         if (mode1->pixclock > mode2->pixclock)
369                                 return 1;
370                         else if (mode1->pixclock == mode2->pixclock) {
371                                 if (mode1->refresh > mode2->refresh)
372                                         return 1;
373                                 else if (mode1->refresh == mode2->refresh)
374                                         return 0;
375                         }
376                 }
377         }
378         return -1;
379 }
380
381 /**
382  * hdmi_add_videomode: adds videomode entry to modelist
383  * @mode: videomode to add
384  * @head: struct list_head of modelist
385  *
386  * NOTES:
387  * Will only add unmatched mode entries
388  */
389 int hdmi_add_videomode(const struct fb_videomode *mode, struct list_head *head)
390 {
391         struct list_head *pos;
392         struct fb_modelist *modelist, *modelist_new;
393         struct fb_videomode *m;
394         int i, found = 0;
395
396         for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
397                 m = (struct fb_videomode *)&hdmi_mode[i];
398                 if (fb_mode_is_equal(m, mode)) {
399                         found = 1;
400                         break;
401                 }
402         }
403
404         if (found) {
405                 list_for_each(pos, head) {
406                         modelist = list_entry(pos, struct fb_modelist, list);
407                         m = &modelist->mode;
408                         if (fb_mode_is_equal(m, mode)) {
409                                 /* m == mode */
410                                 return 0;
411                         } else {
412                                 if (hdmi_videomode_compare(m, mode) == -1)
413                                         break;
414                         }
415                 }
416
417                 modelist_new = kmalloc(sizeof(struct fb_modelist), GFP_KERNEL);
418                 if (!modelist_new)
419                         return -ENOMEM;
420                 modelist_new->mode = hdmi_mode[i];
421                 list_add_tail(&modelist_new->list, pos);
422         }
423
424         return 0;
425 }
426
427 /**
428  * hdmi_videomode_to_vic: transverse video mode to vic
429  * @vmode: videomode to transverse
430  *
431  */
432 int hdmi_videomode_to_vic(struct fb_videomode *vmode)
433 {
434         unsigned char vic = 0;
435         int i = 0;
436
437         for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
438                 if (vmode->vmode == hdmi_mode[i].vmode &&
439                     vmode->refresh == hdmi_mode[i].refresh &&
440                     vmode->xres == hdmi_mode[i].xres &&
441                     vmode->left_margin == hdmi_mode[i].left_margin &&
442                     vmode->right_margin == hdmi_mode[i].right_margin &&
443                     vmode->upper_margin == hdmi_mode[i].upper_margin &&
444                     vmode->lower_margin == hdmi_mode[i].lower_margin &&
445                     vmode->hsync_len == hdmi_mode[i].hsync_len &&
446                     vmode->vsync_len == hdmi_mode[i].vsync_len) {
447                         /*if ((vmode->vmode == FB_VMODE_NONINTERLACED
448                              && vmode->yres == hdmi_mode[i].yres)
449                             || (vmode->vmode == FB_VMODE_INTERLACED
450                                 && vmode->yres == hdmi_mode[i].yres / 2))*/
451                         {
452                                 vic = hdmi_mode[i].flag;
453                                 break;
454                         }
455                 }
456         }
457         return vic;
458 }
459
460 /**
461  * hdmi_vic_to_videomode: transverse vic mode to video mode
462  * @vmode: vic to transverse
463  *
464  */
465 const struct fb_videomode *hdmi_vic_to_videomode(int vic)
466 {
467         int i;
468
469         if (vic == 0)
470                 return NULL;
471
472         for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
473                 if (hdmi_mode[i].flag == vic)
474                         return &hdmi_mode[i];
475         }
476         return NULL;
477 }
478
479 /**
480  * hdmi_find_best_mode: find the video mode nearest to input vic
481  * @hdmi:
482  * @vic: input vic
483  *
484  * NOTES:
485  * If vic is zero, return the high resolution video mode vic.
486  */
487 int hdmi_find_best_mode(struct hdmi *hdmi, int vic)
488 {
489         struct list_head *pos, *head = &hdmi->edid.modelist;
490         struct fb_modelist *modelist;
491         struct fb_videomode *m = NULL;
492         int found = 0;
493
494         if (vic) {
495                 list_for_each(pos, head) {
496                         modelist = list_entry(pos, struct fb_modelist, list);
497                         m = &modelist->mode;
498                         if (m->flag == vic) {
499                                 found = 1;
500                                 break;
501                         }
502                 }
503         }
504         if ((vic == 0 || found == 0) && head->next != head) {
505                 modelist = list_entry(head->next, struct fb_modelist, list);
506                 m = &modelist->mode;
507         }
508         if (m != NULL)
509                 return m->flag;
510         else
511                 return 0;
512 }
513
514 const char *hdmi_get_video_mode_name(unsigned char vic)
515 {
516         int i;
517
518         for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
519                 if (vic == hdmi_mode[i].flag)
520                         break;
521         }
522         if (i == ARRAY_SIZE(hdmi_mode))
523                 return NULL;
524         else
525                 return hdmi_mode[i].name;
526 }
527
528 /**
529  * hdmi_switch_fb: switch lcdc mode to required video mode
530  * @hdmi:
531  * @type:
532  *
533  * NOTES:
534  *
535  */
536 int hdmi_switch_fb(struct hdmi *hdmi, int vic)
537 {
538         int rc = 0;
539         struct rk_screen *screen;
540
541         screen = kzalloc(sizeof(struct rk_screen), GFP_KERNEL);
542         if (screen == NULL)
543                 return -1;
544
545         if (hdmi->vic == 0)
546                 hdmi->vic = HDMI_VIDEO_DEFAULT_MODE;
547
548         rc = hdmi_set_info(screen, hdmi->vic);
549
550         if (rc == 0) {
551                 if (hdmi->set_vif)      /* turn off vif for jettab */
552                         hdmi->set_vif(hdmi, screen, 0);
553                 rk_fb_switch_screen(screen, 1, hdmi->lcdc->id);
554                 rk_fb_disp_scale(hdmi->xscale, hdmi->yscale, hdmi->lcdc->id);
555                 if (hdmi->set_vif)
556                         hdmi->set_vif(hdmi, screen, 1);
557
558         }
559
560         kfree(screen);
561
562         return rc;
563 }
564
565 /**
566  * hdmi_init_video_para: init video_para variable
567  *
568  * NOTES:
569  *This parameters should be modified according to need by user
570  */
571 int hdmi_init_video_para(struct hdmi *hdmi_drv, struct hdmi_video_para *video)
572 {
573         struct rk_lcdc_driver *lcdc_drv = NULL;
574
575         if (unlikely(hdmi_drv == NULL))
576                 return -1;
577
578         lcdc_drv = hdmi_drv->lcdc;
579         if (unlikely(lcdc_drv == NULL))
580                 return -1;
581
582         memset(video, 0, sizeof(struct hdmi_video_para));
583
584         video->vic = hdmi_drv->vic;
585         video->input_mode = VIDEO_INPUT_RGB_YCBCR_444;
586         if (lcdc_drv->output_color == COLOR_RGB)
587                 video->input_color = VIDEO_INPUT_COLOR_RGB;
588         else
589                 video->input_color = VIDEO_INPUT_COLOR_YCBCR444;
590
591         video->output_mode = hdmi_drv->edid.sink_hdmi;
592         video->format_3d = 0;   /* TODO modify according to EDID if need */
593         video->pixel_repet = 0;
594         /* 0:IT Video Format  1:CE Video Format
595          * TODO modify according to EDID
596          */
597         video->color_limit_range = 1;
598
599 #ifdef SOURCE_ABOVE_10BIT
600         if (hdmi_drv->edid.deepcolor & HDMI_COLOR_DEPTH_16BIT)
601                 video->color_depth = HDMI_COLOR_DEPTH_16BIT;
602         else if (hdmi_drv->edid.deepcolor & HDMI_COLOR_DEPTH_12BIT)
603                 video->color_depth = HDMI_COLOR_DEPTH_12BIT;
604         else
605 #endif
606         if (hdmi_drv->edid.deepcolor & HDMI_COLOR_DEPTH_10BIT)
607                 video->color_depth = HDMI_COLOR_DEPTH_10BIT;
608         else
609                 video->color_depth = HDMI_COLOR_DEPTH_8BIT;
610
611         if (hdmi_drv->edid.ycbcr444)
612                 video->output_color = VIDEO_OUTPUT_YCBCR444;
613         else if (hdmi_drv->edid.ycbcr422)
614                 video->output_color = VIDEO_OUTPUT_YCBCR422;
615         else
616                 video->output_color = VIDEO_OUTPUT_RGB444;
617
618         /*For DVI, output RGB */
619         if (hdmi_drv->edid.sink_hdmi == 0)
620                 video->output_color = VIDEO_OUTPUT_RGB444;
621
622         return 0;
623 }
624
625 /**
626  * hdmi_drv_register: init hdmi_drv variable
627  *
628  * NOTES:
629  *
630  */
631 int hdmi_drv_register(struct hdmi *hdmi_drv)
632 {
633         m_hdmi_drv = hdmi_drv;
634         return 0;
635 }
636
637 /**
638  * hdmi_get_status: get hdmi hotplug status
639  *
640  * NOTES:
641  *
642  */
643 int hdmi_get_hotplug(void)
644 {
645         if (m_hdmi_drv)
646                 return m_hdmi_drv->hotplug;
647         else
648                 return HDMI_HPD_REMOVED;
649 }