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