Merge tag 'lsk-v3.10-15.05-android' into develop-3.10
[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         if (head_new.next == &head_new) {
512                 pr_info("There is no available video mode in EDID.\n");
513                 INIT_LIST_HEAD(&edid->modelist);
514         } else {
515                 edid->modelist = head_new;
516                 edid->modelist.prev->next = &edid->modelist;
517                 edid->modelist.next->prev = &edid->modelist;
518         }
519 }
520
521 /**
522  * hdmi_ouputmode_select - select hdmi transmitter output mode: hdmi or dvi?
523  * @hdmi: handle of hdmi
524  * @edid_ok: get EDID data success or not, HDMI_ERROR_SUCESS means success.
525  */
526 int hdmi_ouputmode_select(struct hdmi *hdmi, int edid_ok)
527 {
528         struct list_head *head = &hdmi->edid.modelist;
529         struct fb_monspecs *specs = hdmi->edid.specs;
530         struct fb_videomode *modedb = NULL, *mode = NULL;
531         int i, pixclock, feature = hdmi->property->feature;
532
533         if (edid_ok != HDMI_ERROR_SUCESS) {
534                 dev_err(hdmi->dev, "warning: EDID error, assume sink as HDMI !!!!");
535                 hdmi->edid.status = -1;
536                 hdmi->edid.sink_hdmi = 1;
537                 hdmi->edid.baseaudio_support = 1;
538                 hdmi->edid.ycbcr444 = 0;
539                 hdmi->edid.ycbcr422 = 0;
540         }
541
542         if (head->next == head) {
543                 dev_info(hdmi->dev,
544                          "warning: no CEA video mode parsed from EDID !!!!\n");
545                 /* If EDID get error, list all system supported mode.
546                    If output mode is set to DVI and EDID is ok, check
547                    the output timing.
548                 */
549                 if (hdmi->edid.sink_hdmi == 0 && specs && specs->modedb_len) {
550                         /* Get max resolution timing */
551                         modedb = &specs->modedb[0];
552                         for (i = 0; i < specs->modedb_len; i++) {
553                                 if (specs->modedb[i].xres > modedb->xres)
554                                         modedb = &specs->modedb[i];
555                                 else if (specs->modedb[i].xres ==
556                                          modedb->xres &&
557                                          specs->modedb[i].yres > modedb->yres)
558                                         modedb = &specs->modedb[i];
559                         }
560                         /* For some monitor, the max pixclock read from EDID
561                            is smaller than the clock of max resolution mode
562                            supported. We fix it. */
563                         pixclock = PICOS2KHZ(modedb->pixclock);
564                         pixclock /= 250;
565                         pixclock *= 250;
566                         pixclock *= 1000;
567                         if (pixclock == 148250000)
568                                 pixclock = 148500000;
569                         if (pixclock > specs->dclkmax)
570                                 specs->dclkmax = pixclock;
571                 }
572
573                 for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
574                         mode = (struct fb_videomode *)&(hdmi_mode[i].mode);
575                         if (modedb) {
576                                 if ((mode->pixclock < specs->dclkmin) ||
577                                     (mode->pixclock > specs->dclkmax) ||
578                                     (mode->refresh < specs->vfmin) ||
579                                     (mode->refresh > specs->vfmax) ||
580                                     (mode->xres > modedb->xres) ||
581                                     (mode->yres > modedb->yres))
582                                         continue;
583                         } else {
584                                 /* If there is no valid information in EDID,
585                                    just list common hdmi foramt. */
586                                 if (mode->xres > 3840 ||
587                                     mode->refresh < 50 ||
588                                     mode->vmode == FB_VMODE_INTERLACED)
589                                         continue;
590                         }
591                         if ((feature & SUPPORT_TMDS_600M) == 0 &&
592                             mode->pixclock > 340000000)
593                                 continue;
594                         if ((feature & SUPPORT_4K) == 0 &&
595                             mode->xres >= 3840)
596                                 continue;
597                         if ((feature & SUPPORT_4K_4096) == 0 &&
598                             mode->xres == 4096)
599                                 continue;
600                         if ((feature & SUPPORT_1080I) == 0 &&
601                             mode->xres == 1920 &&
602                             mode->vmode == FB_VMODE_INTERLACED)
603                                 continue;
604                         if ((feature & SUPPORT_480I_576I) == 0 &&
605                             mode->xres == 720 &&
606                             mode->vmode == FB_VMODE_INTERLACED)
607                                 continue;
608                         hdmi_add_videomode(mode, head);
609                 }
610         } else {
611                 /* There are some video mode is not defined in EDID extend
612                    block, so we need to check first block data.*/
613                 if (specs && specs->modedb_len) {
614                         for (i = 0; i < specs->modedb_len; i++) {
615                                 modedb = &specs->modedb[0];
616                                 pixclock = hdmi_videomode_to_vic(modedb);
617                                 if (pixclock)
618                                         hdmi_add_vic(pixclock, head);
619                         }
620                 }
621                 hdmi_sort_modelist(&hdmi->edid, hdmi->property->feature);
622         }
623         hdmi_show_sink_info(hdmi);
624
625         return HDMI_ERROR_SUCESS;
626 }
627
628 /**
629  * hdmi_videomode_to_vic: transverse video mode to vic
630  * @vmode: videomode to transverse
631  *
632  */
633 int hdmi_videomode_to_vic(struct fb_videomode *vmode)
634 {
635         struct fb_videomode *mode;
636         unsigned char vic = 0;
637         int i = 0;
638
639         for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
640                 mode = (struct fb_videomode *)&(hdmi_mode[i].mode);
641                 if (vmode->vmode == mode->vmode &&
642                     vmode->refresh == mode->refresh &&
643                     vmode->xres == mode->xres &&
644                     vmode->yres == mode->yres &&
645                     vmode->left_margin == mode->left_margin &&
646                     vmode->right_margin == mode->right_margin &&
647                     vmode->upper_margin == mode->upper_margin &&
648                     vmode->lower_margin == mode->lower_margin &&
649                     vmode->hsync_len == mode->hsync_len &&
650                     vmode->vsync_len == mode->vsync_len) {
651                         vic = hdmi_mode[i].vic;
652                         break;
653                 }
654         }
655         return vic;
656 }
657
658 /**
659  * hdmi_vic2timing: transverse vic mode to video timing
660  * @vmode: vic to transverse
661  *
662  */
663 const struct hdmi_video_timing *hdmi_vic2timing(int vic)
664 {
665         int i;
666
667         if (vic == 0)
668                 return NULL;
669
670         for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
671                 if (hdmi_mode[i].vic == vic || hdmi_mode[i].vic_2nd == vic)
672                         return &(hdmi_mode[i]);
673         }
674         return NULL;
675 }
676
677 /**
678  * hdmi_vic_to_videomode: transverse vic mode to video mode
679  * @vmode: vic to transverse
680  *
681  */
682 const struct fb_videomode *hdmi_vic_to_videomode(int vic)
683 {
684         int i;
685
686         if (vic == 0)
687                 return NULL;
688
689         for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
690                 if (hdmi_mode[i].vic == (vic & HDMI_VIC_MASK) ||
691                     hdmi_mode[i].vic_2nd == (vic & HDMI_VIC_MASK))
692                         return &hdmi_mode[i].mode;
693         }
694         return NULL;
695 }
696
697 /**
698  * hdmi_init_modelist: initial hdmi mode list
699  * @hdmi:
700  *
701  * NOTES:
702  *
703  */
704 void hdmi_init_modelist(struct hdmi *hdmi)
705 {
706         int i, feature;
707         struct list_head *head = &hdmi->edid.modelist;
708
709         feature = hdmi->property->feature;
710         INIT_LIST_HEAD(&hdmi->edid.modelist);
711         for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
712                 if ((feature & SUPPORT_TMDS_600M) == 0 &&
713                     hdmi_mode[i].mode.pixclock > 340000000)
714                         continue;
715                 if ((feature & SUPPORT_4K) == 0 &&
716                     hdmi_mode[i].mode.xres >= 3840)
717                         continue;
718                 if ((feature & SUPPORT_4K_4096) == 0 &&
719                     hdmi_mode[i].mode.xres == 4096)
720                         continue;
721                 if ((feature & SUPPORT_1080I) == 0 &&
722                     hdmi_mode[i].mode.xres == 1920 &&
723                     hdmi_mode[i].mode.vmode == FB_VMODE_INTERLACED)
724                         continue;
725                 if ((feature & SUPPORT_480I_576I) == 0 &&
726                     hdmi_mode[i].mode.xres == 720 &&
727                     hdmi_mode[i].mode.vmode == FB_VMODE_INTERLACED)
728                         continue;
729                 hdmi_add_videomode(&(hdmi_mode[i].mode), head);
730         }
731 }