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