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