hdmi: update driver to v2.0:
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / hdmi / rockchip-hdmi-lcdc.c
1 #include "rockchip-hdmi.h"
2
3 static const struct hdmi_video_timing hdmi_mode[] = {
4 /*              name                    refresh xres    yres    pixclock        h_bp    h_fp    v_bp    v_fp    h_pw    v_pw                    polariry                        PorI    flag            vic             2ndvic          pixelrepeat     interface */
5
6         { {     "720x480i@60Hz",        60,     720,    480,    27000000,       57,     19,     15,     4,      62,     3,                      0,                              1,      0       },      6,      HDMI_720X480I_60HZ_16_9,        2,      OUT_P888},
7         { {     "720x576i@50Hz",        50,     720,    576,    27000000,       69,     12,     19,     2,      63,     3,                      0,                              1,      0       },      21,     HDMI_720X576I_50HZ_16_9,        2,      OUT_P888},
8         { {     "720x480p@60Hz",        60,     720,    480,    27000000,       60,     16,     30,     9,      62,     6,                      0,                              0,      0       },      2,      HDMI_720X480P_60HZ_16_9,        1,      OUT_P888},
9         { {     "720x576p@50Hz",        50,     720,    576,    27000000,       68,     12,     39,     5,      64,     5,                      0,                              0,      0       },      17,     HDMI_720X576P_50HZ_16_9,        1,      OUT_P888},
10         { {     "1280x720p@24Hz",       24,     1280,   720,    59400000,       220,    1760,   20,     5,      40,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      0       },      60,     HDMI_1280X720P_24HZ_4_3,        1,      OUT_P888},
11         { {     "1280x720p@25Hz",       25,     1280,   720,    74250000,       220,    2420,   20,     5,      40,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      0       },      61,     HDMI_1280X720P_25HZ_4_3,        1,      OUT_P888},
12         { {     "1280x720p@30Hz",       30,     1280,   720,    74250000,       220,    1760,   20,     5,      40,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      0       },      62,     HDMI_1280X720P_30HZ_4_3,        1,      OUT_P888},
13         { {     "1280x720p@50Hz",       50,     1280,   720,    74250000,       220,    440,    20,     5,      40,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      0       },      19,     HDMI_1280X720P_50HZ_4_3,        1,      OUT_P888},
14         { {     "1280x720p@60Hz",       60,     1280,   720,    74250000,       220,    110,    20,     5,      40,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      0       },      4,      HDMI_1280X720P_60HZ_4_3,        1,      OUT_P888},
15         { {     "1920x1080i@50Hz",      50,     1920,   1080,   74250000,       148,    528,    15,     2,      44,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   1,      0       },      20,     0,                              1,      OUT_P888},
16         { {     "1920x1080i@60Hz",      60,     1920,   1080,   74250000,       148,    88,     15,     2,      44,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   1,      0       },      5,      0,                              1,      OUT_P888},
17         { {     "1920x1080p@24Hz",      24,     1920,   1080,   74250000,       148,    638,    36,     4,      44,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      0       },      32,     HDMI_1920X1080P_24HZ_4_3,       1,      OUT_P888},
18         { {     "1920x1080p@25Hz",      25,     1920,   1080,   74250000,       148,    528,    36,     4,      44,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      0       },      33,     HDMI_1920X1080P_25HZ_4_3,       1,      OUT_P888},
19         { {     "1920x1080p@30Hz",      30,     1920,   1080,   74250000,       148,    88,     36,     4,      44,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      0       },      34,     HDMI_1920X1080P_30HZ_4_3,       1,      OUT_P888},
20         { {     "1920x1080p@50Hz",      50,     1920,   1080,   148500000,      148,    528,    36,     4,      44,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      0       },      31,     HDMI_1920X1080P_50HZ_4_3,       1,      OUT_P888},
21         { {     "1920x1080p@60Hz",      60,     1920,   1080,   148500000,      148,    88,     36,     4,      44,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      0       },      16,     HDMI_1920X1080P_60HZ_4_3,       1,      OUT_P888},
22         { {     "3840x2160p@24Hz",      24,     3840,   2160,   297000000,      296,    1276,   72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      0       },      93,     HDMI_3840X2160P_24HZ_4_3,       1,      OUT_P888},
23         { {     "3840x2160p@25Hz",      25,     3840,   2160,   297000000,      296,    1056,   72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      0       },      94,     HDMI_3840X2160P_25HZ_4_3,       1,      OUT_P888},
24         { {     "3840x2160p@30Hz",      30,     3840,   2160,   297000000,      296,    176,    72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      0       },      95,     HDMI_3840X2160P_30HZ_4_3,       1,      OUT_P888},
25         { {     "4096x2160p@24Hz",      24,     4096,   2160,   297000000,      296,    1020,   72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      0       },      98,     0,                              1,      OUT_P888},
26         { {     "4096x2160p@25Hz",      25,     4096,   2160,   297000000,      128,    968,    72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      0       },      99,     0,                              1,      OUT_P888},
27         { {     "4096x2160p@30Hz",      30,     4096,   2160,   297000000,      128,    88,     72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      0       },      100,    0,                              1,      OUT_P888},
28         { {     "3840x2160p@50Hz",      50,     3840,   2160,   594000000,      296,    1056,   72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      0       },      96,     HDMI_3840X2160P_50HZ_4_3,       1,      OUT_P888},
29         { {     "3840x2160p@60Hz",      60,     3840,   2160,   594000000,      296,    176,    72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      0       },      97,     HDMI_3840X2160P_60HZ_4_3,       1,      OUT_P888},
30         { {     "4096x2160p@50Hz",      50,     4096,   2160,   594000000,      128,    968,    72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      0       },      101,    0,                              1,      OUT_P888},
31         { {     "4096x2160p@60Hz",      60,     4096,   2160,   594000000,      128,    88,     72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      0       },      102,    0,                              1,      OUT_P888},
32 };
33
34 static int hdmi_set_info(struct rk_screen *screen, struct hdmi *hdmi)
35 {
36         int i;
37         struct fb_videomode *mode;
38
39         if (screen == NULL || hdmi == NULL)
40                 return HDMI_ERROR_FALSE;
41
42         if (hdmi->vic == 0)
43                 hdmi->vic = HDMI_VIDEO_DEFAULT_MODE;
44
45         for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
46                 if (hdmi_mode[i].vic == (hdmi->vic & HDMI_VIC_MASK) ||
47                     hdmi_mode[i].vic_2nd == (hdmi->vic & HDMI_VIC_MASK))
48                         break;
49         }
50         if (i == ARRAY_SIZE(hdmi_mode))
51                 return HDMI_ERROR_FALSE;
52
53         memset(screen, 0, sizeof(struct rk_screen));
54
55         /* screen type & face */
56         screen->type = SCREEN_HDMI;
57         screen->color_mode = COLOR_YCBCR;
58         if (hdmi->vic & HDMI_VIDEO_YUV420)
59                 screen->face = OUT_YUV_420;
60         else
61                 screen->face = hdmi_mode[i].interface;
62         screen->pixelrepeat = hdmi_mode[i].pixelrepeat - 1;
63         mode = (struct fb_videomode *)&(hdmi_mode[i].mode);
64
65         screen->mode = *mode;
66
67         /* Pin polarity */
68         #ifdef CONFIG_HDMI_RK616
69         screen->pin_hsync = 0;
70         screen->pin_vsync = 0;
71         #else
72         if (FB_SYNC_HOR_HIGH_ACT & mode->sync)
73                 screen->pin_hsync = 1;
74         else
75                 screen->pin_hsync = 0;
76         if (FB_SYNC_VERT_HIGH_ACT & mode->sync)
77                 screen->pin_vsync = 1;
78         else
79                 screen->pin_vsync = 0;
80         #endif
81         screen->pin_den = 0;
82         screen->pin_dclk = 1;
83
84         /* Swap rule */
85         if (hdmi->soctype == HDMI_SOC_RK3368 &&
86             screen->color_mode == COLOR_YCBCR &&
87             screen->face == OUT_P888)
88                 screen->swap_rb = 1;
89         else
90                 screen->swap_rb = 0;
91         screen->swap_rg = 0;
92         screen->swap_gb = 0;
93         screen->swap_delta = 0;
94         screen->swap_dumy = 0;
95
96         /* Operation function*/
97         screen->init = NULL;
98         screen->standby = NULL;
99
100         screen->overscan.left = hdmi->xscale;
101         screen->overscan.top = hdmi->yscale;
102         screen->overscan.right = hdmi->xscale;
103         screen->overscan.bottom = hdmi->yscale;
104         return 0;
105 }
106
107 /**
108  * hdmi_find_best_mode: find the video mode nearest to input vic
109  * @hdmi:
110  * @vic: input vic
111  *
112  * NOTES:
113  * If vic is zero, return the high resolution video mode vic.
114  */
115 int hdmi_find_best_mode(struct hdmi *hdmi, int vic)
116 {
117         struct list_head *pos, *head = &hdmi->edid.modelist;
118         struct display_modelist *modelist;
119         int found = 0;
120 /*      pr_info("%s vic %d\n", __FUNCTION__, vic); */
121         if (vic) {
122                 list_for_each(pos, head) {
123                         modelist =
124                                 list_entry(pos,
125                                            struct display_modelist, list);
126                         if (modelist->vic == vic) {
127                                 found = 1;
128                                 break;
129                         }
130                 }
131         }
132         if ((vic == 0 || found == 0) && head->next != head) {
133                 /* If parse edid error, we select default mode; */
134                 if (hdmi->edid.specs == NULL ||
135                     hdmi->edid.specs->modedb_len == 0)
136                         return HDMI_VIDEO_DEFAULT_MODE;
137                         /*modelist = list_entry(head->prev,
138                                         struct display_modelist, list);*/
139                 else
140                         modelist = list_entry(head->next,
141                                               struct display_modelist, list);
142         }
143
144         if (modelist != NULL)
145                 return modelist->vic;
146         else
147                 return 0;
148 }
149 /**
150  * hdmi_set_lcdc: switch lcdc mode to required video mode
151  * @hdmi:
152  *
153  * NOTES:
154  *
155  */
156 int hdmi_set_lcdc(struct hdmi *hdmi)
157 {
158         int rc = 0;
159         struct rk_screen screen;
160
161         if (hdmi->autoset)
162                 hdmi->vic = hdmi_find_best_mode(hdmi, 0);
163         else
164         hdmi->vic = hdmi_find_best_mode(hdmi, hdmi->vic);
165
166         if (hdmi->vic == 0)
167                 hdmi->vic = HDMI_VIDEO_DEFAULT_MODE;
168
169         rc = hdmi_set_info(&screen, hdmi);
170
171         if (rc == 0)
172                 rk_fb_switch_screen(&screen, 1, hdmi->lcdc->id);
173
174         return rc;
175 }
176
177 /**
178  * hdmi_videomode_compare - compare 2 videomodes
179  * @mode1: first videomode
180  * @mode2: second videomode
181  *
182  * RETURNS:
183  * 1 if mode1 > mode2, 0 if mode1 = mode2, -1 mode1 < mode2
184  */
185 static int hdmi_videomode_compare(const struct fb_videomode *mode1,
186                                   const struct fb_videomode *mode2)
187 {
188         if (mode1->xres > mode2->xres)
189                 return 1;
190
191         if (mode1->xres == mode2->xres) {
192                 if (mode1->yres > mode2->yres)
193                         return 1;
194                 if (mode1->yres == mode2->yres) {
195                         if (mode1->vmode < mode2->vmode)
196                                 return 1;
197                         if (mode1->pixclock > mode2->pixclock)
198                                 return 1;
199                         if (mode1->pixclock == mode2->pixclock) {
200                                 if (mode1->refresh > mode2->refresh)
201                                         return 1;
202                                 if (mode1->refresh == mode2->refresh) {
203                                         if (mode2->flag > mode1->flag)
204                                                 return 1;
205                                         if (mode2->flag < mode1->flag)
206                                                 return -1;
207                                         if (mode2->vmode > mode1->vmode)
208                                                 return 1;
209                                         if (mode2->vmode == mode1->vmode)
210                                                 return 0;
211                                 }
212                         }
213                 }
214         }
215         return -1;
216 }
217
218 /**
219  * hdmi_add_vic - add entry to modelist according vic
220  * @vic: vic to be added
221  * @head: struct list_head of modelist
222  *
223  * NOTES:
224  * Will only add unmatched mode entries
225  */
226 int hdmi_add_vic(int vic, struct list_head *head)
227 {
228         struct list_head *pos;
229         struct display_modelist *modelist;
230         int found = 0, v;
231
232 /*      DBG("%s vic %d", __FUNCTION__, vic); */
233         if (vic == 0)
234                 return -1;
235
236         list_for_each(pos, head) {
237                 modelist = list_entry(pos, struct display_modelist, list);
238                 v = modelist->vic;
239                 if (v == vic) {
240                         found = 1;
241                         break;
242                 }
243         }
244         if (!found) {
245                 modelist = kmalloc(sizeof(*modelist),
246                                    GFP_KERNEL);
247
248                 if (!modelist)
249                         return -ENOMEM;
250                 memset(modelist, 0, sizeof(struct display_modelist));
251                 modelist->vic = vic;
252                 list_add_tail(&modelist->list, head);
253         }
254         return 0;
255 }
256
257 /**
258  * hdmi_add_videomode: adds videomode entry to modelist
259  * @mode: videomode to be added
260  * @head: struct list_head of modelist
261  *
262  * NOTES:
263  * Will only add unmatched mode entries
264  */
265 static int hdmi_add_videomode(const struct fb_videomode *mode,
266                               struct list_head *head)
267 {
268         struct list_head *pos;
269         struct display_modelist *modelist, *modelist_new;
270         struct fb_videomode *m;
271         int i, found = 0;
272
273         for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
274                 m = (struct fb_videomode *)&(hdmi_mode[i].mode);
275                 if (fb_mode_is_equal(m, mode)) {
276                         found = 1;
277                         break;
278                 }
279         }
280
281         if (found) {
282                 list_for_each(pos, head) {
283                         modelist = list_entry(pos,
284                                               struct display_modelist, list);
285                         m = &modelist->mode;
286                         if (fb_mode_is_equal(m, mode))
287                                 return 0;
288                         else if (hdmi_videomode_compare(m, mode) == -1)
289                                 break;
290                 }
291
292                 modelist_new = kmalloc(sizeof(*modelist_new), GFP_KERNEL);
293                 if (!modelist_new)
294                         return -ENOMEM;
295                 memset(modelist_new, 0, sizeof(struct display_modelist));
296                 modelist_new->mode = hdmi_mode[i].mode;
297                 modelist_new->vic = hdmi_mode[i].vic;
298                 list_add_tail(&modelist_new->list, pos);
299         }
300
301         return 0;
302 }
303
304 /**
305  * hdmi_show_sink_info: show hdmi sink device infomation
306  * @hdmi: handle of hdmi
307  */
308 static void hdmi_show_sink_info(struct hdmi *hdmi)
309 {
310         struct list_head *pos, *head = &hdmi->edid.modelist;
311         struct display_modelist *modelist;
312         struct fb_videomode *m;
313         int i;
314         struct hdmi_audio *audio;
315
316         pr_info("******** Show Sink Info ********\n");
317         pr_info("Max tmds clk is %u\n", hdmi->edid.maxtmdsclock);
318         if (hdmi->edid.hf_vsdb_version)
319                 pr_info("Support HFVSDB\n");
320         if (hdmi->edid.scdc_present)
321                 pr_info("Support SCDC\n");
322         pr_info("Support video mode:\n");
323         list_for_each(pos, head) {
324                 modelist = list_entry(pos, struct display_modelist, list);
325                 m = &modelist->mode;
326                 if (m->flag)
327                         pr_info("       %s(YCbCr420)\n", m->name);
328                 else
329                         pr_info("       %s\n", m->name);
330         }
331         pr_info("Support video color mode:\n");
332         pr_info("       RGB\n");
333         if (hdmi->edid.ycbcr420)
334                 pr_info("       YCbCr420\n");
335         if (hdmi->edid.ycbcr422)
336                 pr_info("       YCbCr422\n");
337         if (hdmi->edid.ycbcr444)
338                 pr_info("       YCbCr444\n");
339         pr_info("Support video color depth:\n");
340         pr_info("       24bit\n");
341         if (hdmi->edid.deepcolor & HDMI_DEEP_COLOR_30BITS)
342                 pr_info("       30bit\n");
343         if (hdmi->edid.deepcolor & HDMI_DEEP_COLOR_36BITS)
344                 pr_info("       36bit\n");
345         if (hdmi->edid.deepcolor & HDMI_DEEP_COLOR_48BITS)
346                 pr_info("       48bit\n");
347
348         pr_info("Support audio type:\n");
349         for (i = 0; i < hdmi->edid.audio_num; i++) {
350                 audio = &(hdmi->edid.audio[i]);
351                 switch (audio->type) {
352                 case HDMI_AUDIO_LPCM:
353                         pr_info("       LPCM\n");
354                         break;
355                 case HDMI_AUDIO_AC3:
356                         pr_info("       AC3\n");
357                         break;
358                 case HDMI_AUDIO_MPEG1:
359                         pr_info("       MPEG1\n");
360                         break;
361                 case HDMI_AUDIO_MP3:
362                         pr_info("       MP3\n");
363                         break;
364                 case HDMI_AUDIO_MPEG2:
365                         pr_info("       MPEG2\n");
366                         break;
367                 case HDMI_AUDIO_AAC_LC:
368                         pr_info("S      AAC\n");
369                         break;
370                 case HDMI_AUDIO_DTS:
371                         pr_info("       DTS\n");
372                         break;
373                 case HDMI_AUDIO_ATARC:
374                         pr_info("       ATARC\n");
375                         break;
376                 case HDMI_AUDIO_DSD:
377                         pr_info("       DSD\n");
378                         break;
379                 case HDMI_AUDIO_E_AC3:
380                         pr_info("       E-AC3\n");
381                         break;
382                 case HDMI_AUDIO_DTS_HD:
383                         pr_info("       DTS-HD\n");
384                         break;
385                 case HDMI_AUDIO_MLP:
386                         pr_info("       MLP\n");
387                         break;
388                 case HDMI_AUDIO_DST:
389                         pr_info("       DST\n");
390                         break;
391                 case HDMI_AUDIO_WMA_PRO:
392                         pr_info("       WMP-PRO\n");
393                         break;
394                 default:
395                         pr_info("       Unkown\n");
396                         break;
397                 }
398                 pr_info("Support max audio channel is %d\n", audio->channel);
399                 pr_info("Support audio sample rate:\n");
400                 if (audio->rate & HDMI_AUDIO_FS_32000)
401                         pr_info("       32000\n");
402                 if (audio->rate & HDMI_AUDIO_FS_44100)
403                         pr_info("       44100\n");
404                 if (audio->rate & HDMI_AUDIO_FS_48000)
405                         pr_info("       48000\n");
406                 if (audio->rate & HDMI_AUDIO_FS_88200)
407                         pr_info("       88200\n");
408                 if (audio->rate & HDMI_AUDIO_FS_96000)
409                         pr_info("       96000\n");
410                 if (audio->rate & HDMI_AUDIO_FS_176400)
411                         pr_info("       176400\n");
412                 if (audio->rate & HDMI_AUDIO_FS_192000)
413                         pr_info("       192000\n");
414                 pr_info("Support audio word lenght:\n");
415                 if (audio->rate & HDMI_AUDIO_WORD_LENGTH_16bit)
416                         pr_info("       16bit\n");
417                 if (audio->rate & HDMI_AUDIO_WORD_LENGTH_20bit)
418                         pr_info("       20bit\n");
419                 if (audio->rate & HDMI_AUDIO_WORD_LENGTH_24bit)
420                         pr_info("       24bit\n");
421                 pr_info("\n");
422         }
423         pr_info("******** Show Sink Info ********\n");
424 }
425
426 /**
427  * hdmi_sort_modelist: sort modelist of edid
428  * @edid: edid to be sort
429  */
430 static void hdmi_sort_modelist(struct hdmi_edid *edid, int feature)
431 {
432         struct list_head *pos, *pos_new;
433         struct list_head head_new, *head = &edid->modelist;
434         struct display_modelist *modelist, *modelist_new, *modelist_n;
435         struct fb_videomode *m, *m_new;
436         int i, compare, vic;
437
438         INIT_LIST_HEAD(&head_new);
439         list_for_each(pos, head) {
440                 modelist = list_entry(pos, struct display_modelist, list);
441                 /*pr_info("%s vic %d\n", __function__, modelist->vic);*/
442                 for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
443                         vic = modelist->vic & HDMI_VIC_MASK;
444                         if (vic == hdmi_mode[i].vic ||
445                             vic == hdmi_mode[i].vic_2nd) {
446                                 if ((feature & SUPPORT_TMDS_600M) == 0 &&
447                                     !(modelist->vic & HDMI_VIDEO_YUV420) &&
448                                     hdmi_mode[i].mode.pixclock > 340000000 &&
449                                     edid->maxtmdsclock < 340000000)
450                                         continue;
451                                 if ((feature & SUPPORT_4K) == 0 &&
452                                     hdmi_mode[i].mode.xres >= 3840)
453                                         continue;
454                                 if ((feature & SUPPORT_4K_4096) == 0 &&
455                                     hdmi_mode[i].mode.xres == 4096)
456                                         continue;
457                                 if ((modelist->vic & HDMI_VIDEO_YUV420) &&
458                                     (feature & SUPPORT_YUV420) == 0)
459                                         continue;
460                                 if ((feature & SUPPORT_1080I) == 0 &&
461                                     hdmi_mode[i].mode.xres == 1920 &&
462                                     hdmi_mode[i].mode.vmode ==
463                                     FB_VMODE_INTERLACED)
464                                         continue;
465                                 if ((feature & SUPPORT_480I_576I) == 0 &&
466                                     hdmi_mode[i].mode.xres == 720 &&
467                                     hdmi_mode[i].mode.vmode ==
468                                     FB_VMODE_INTERLACED)
469                                         continue;
470                                 vic = modelist->vic;
471                                 modelist->vic = hdmi_mode[i].vic;
472                                 modelist->mode = hdmi_mode[i].mode;
473                                 if (vic & HDMI_VIDEO_YUV420) {
474                                         modelist->vic |= HDMI_VIDEO_YUV420;
475                                         modelist->mode.flag = 1;
476                                 }
477                                 compare = 1;
478                                 m = (struct fb_videomode *)&(modelist->mode);
479                                 list_for_each(pos_new, &head_new) {
480                                         modelist_new =
481                                         list_entry(pos_new,
482                                                    struct display_modelist,
483                                                    list);
484                                         m_new = &modelist_new->mode;
485                                         compare =
486                                         hdmi_videomode_compare(m, m_new);
487                                         if (compare != -1)
488                                                 break;
489                                 }
490                                 if (compare != 0) {
491                                         modelist_n =
492                                                 kmalloc(sizeof(*modelist_n),
493                                                         GFP_KERNEL);
494                                         if (!modelist_n)
495                                                 return;
496                                         *modelist_n = *modelist;
497                                         list_add_tail(&modelist_n->list,
498                                                       pos_new);
499                                 }
500                                 break;
501                         }
502                 }
503         }
504         fb_destroy_modelist(head);
505
506         edid->modelist = head_new;
507         edid->modelist.prev->next = &edid->modelist;
508 }
509
510 /**
511  * hdmi_ouputmode_select - select hdmi transmitter output mode: hdmi or dvi?
512  * @hdmi: handle of hdmi
513  * @edid_ok: get EDID data success or not, HDMI_ERROR_SUCESS means success.
514  */
515 int hdmi_ouputmode_select(struct hdmi *hdmi, int edid_ok)
516 {
517         struct list_head *head = &hdmi->edid.modelist;
518         struct fb_monspecs *specs = hdmi->edid.specs;
519         struct fb_videomode *modedb = NULL, *mode = NULL;
520         int i, pixclock;
521
522         if (edid_ok != HDMI_ERROR_SUCESS) {
523                 dev_err(hdmi->dev, "warning: EDID error, assume sink as HDMI !!!!");
524                 hdmi->edid.sink_hdmi = 1;
525                 hdmi->edid.baseaudio_support = 1;
526                 hdmi->edid.ycbcr444 = 0;
527                 hdmi->edid.ycbcr422 = 0;
528         }
529
530         if (head->next == head) {
531                 dev_info(hdmi->dev,
532                          "warning: no CEA video mode parsed from EDID !!!!\n");
533                 /* If EDID get error, list all system supported mode.
534                    If output mode is set to DVI and EDID is ok, check
535                    the output timing.
536                 */
537                 if (hdmi->edid.sink_hdmi == 0 && specs && specs->modedb_len) {
538                         /* Get max resolution timing */
539                         modedb = &specs->modedb[0];
540                         for (i = 0; i < specs->modedb_len; i++) {
541                                 if (specs->modedb[i].xres > modedb->xres)
542                                         modedb = &specs->modedb[i];
543                                 else if (specs->modedb[i].xres ==
544                                          modedb->xres &&
545                                          specs->modedb[i].yres > modedb->yres)
546                                         modedb = &specs->modedb[i];
547                         }
548                         /* For some monitor, the max pixclock read from EDID
549                            is smaller than the clock of max resolution mode
550                            supported. We fix it. */
551                         pixclock = PICOS2KHZ(modedb->pixclock);
552                         pixclock /= 250;
553                         pixclock *= 250;
554                         pixclock *= 1000;
555                         if (pixclock == 148250000)
556                                 pixclock = 148500000;
557                         if (pixclock > specs->dclkmax)
558                                 specs->dclkmax = pixclock;
559                 }
560
561                 for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
562                         mode = (struct fb_videomode *)&(hdmi_mode[i].mode);
563                         if (modedb) {
564                                 if ((mode->pixclock < specs->dclkmin) ||
565                                     (mode->pixclock > specs->dclkmax) ||
566                                     (mode->refresh < specs->vfmin) ||
567                                     (mode->refresh > specs->vfmax) ||
568                                     (mode->xres > modedb->xres) ||
569                                     (mode->yres > modedb->yres))
570                                         continue;
571                         } else {
572                                 if (!(hdmi->property->feature & SUPPORT_4K) &&
573                                     mode->xres >= 3840)
574                                         continue;
575                                 else if (mode->pixclock > 340000000)
576                                         continue;
577                         }
578                         hdmi_add_videomode(mode, head);
579                 }
580         } else {
581                 hdmi_sort_modelist(&hdmi->edid, hdmi->property->feature);
582         }
583         hdmi_show_sink_info(hdmi);
584
585         return HDMI_ERROR_SUCESS;
586 }
587
588 /**
589  * hdmi_videomode_to_vic: transverse video mode to vic
590  * @vmode: videomode to transverse
591  *
592  */
593 int hdmi_videomode_to_vic(struct fb_videomode *vmode)
594 {
595         struct fb_videomode *mode;
596         unsigned char vic = 0;
597         int i = 0;
598
599         for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
600                 mode = (struct fb_videomode *)&(hdmi_mode[i].mode);
601                 if (vmode->vmode == mode->vmode &&
602                     vmode->refresh == mode->refresh &&
603                     vmode->xres == mode->xres &&
604                     vmode->yres == mode->yres &&
605                     vmode->left_margin == mode->left_margin &&
606                     vmode->right_margin == mode->right_margin &&
607                     vmode->upper_margin == mode->upper_margin &&
608                     vmode->lower_margin == mode->lower_margin &&
609                     vmode->hsync_len == mode->hsync_len &&
610                     vmode->vsync_len == mode->vsync_len) {
611                         vic = hdmi_mode[i].vic;
612                         break;
613                 }
614         }
615         return vic;
616 }
617
618 /**
619  * hdmi_vic2timing: transverse vic mode to video timing
620  * @vmode: vic to transverse
621  *
622  */
623 const struct hdmi_video_timing *hdmi_vic2timing(int vic)
624 {
625         int i;
626
627         if (vic == 0)
628                 return NULL;
629
630         for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
631                 if (hdmi_mode[i].vic == vic || hdmi_mode[i].vic_2nd == vic)
632                         return &(hdmi_mode[i]);
633         }
634         return NULL;
635 }
636
637 /**
638  * hdmi_vic_to_videomode: transverse vic mode to video mode
639  * @vmode: vic to transverse
640  *
641  */
642 const struct fb_videomode *hdmi_vic_to_videomode(int vic)
643 {
644         int i;
645
646         if (vic == 0)
647                 return NULL;
648
649         for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
650                 if (hdmi_mode[i].vic == (vic & HDMI_VIC_MASK) ||
651                     hdmi_mode[i].vic_2nd == (vic & HDMI_VIC_MASK))
652                         return &hdmi_mode[i].mode;
653         }
654         return NULL;
655 }
656
657 /**
658  * hdmi_init_modelist: initial hdmi mode list
659  * @hdmi:
660  *
661  * NOTES:
662  *
663  */
664 void hdmi_init_modelist(struct hdmi *hdmi)
665 {
666         int i, feature;
667         struct list_head *head = &hdmi->edid.modelist;
668
669         feature = hdmi->property->feature;
670         INIT_LIST_HEAD(&hdmi->edid.modelist);
671         for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
672                 if ((feature & SUPPORT_TMDS_600M) == 0 &&
673                     hdmi_mode[i].mode.pixclock > 340000000)
674                         continue;
675                 if ((feature & SUPPORT_4K) == 0 &&
676                     hdmi_mode[i].mode.xres >= 3840)
677                         continue;
678                 if ((feature & SUPPORT_4K_4096) == 0 &&
679                     hdmi_mode[i].mode.xres == 4096)
680                         continue;
681                 if ((feature & SUPPORT_1080I) == 0 &&
682                     hdmi_mode[i].mode.xres == 1920 &&
683                     hdmi_mode[i].mode.vmode == FB_VMODE_INTERLACED)
684                         continue;
685                 if ((feature & SUPPORT_480I_576I) == 0 &&
686                     hdmi_mode[i].mode.xres == 720 &&
687                     hdmi_mode[i].mode.vmode == FB_VMODE_INTERLACED)
688                         continue;
689                 hdmi_add_videomode(&(hdmi_mode[i].mode), head);
690         }
691 }