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