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