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