video: fbmon: add remaining modes to CEA mode database
[linux-2.6.git] / drivers / video / modedb.c
1 /*
2  *  linux/drivers/video/modedb.c -- Standard video mode database management
3  *
4  *      Copyright (C) 1999 Geert Uytterhoeven
5  *
6  *      2001 - Documented with DocBook
7  *      - Brad Douglas <brad@neruo.com>
8  *
9  *  This file is subject to the terms and conditions of the GNU General Public
10  *  License. See the file COPYING in the main directory of this archive for
11  *  more details.
12  */
13
14 #include <linux/module.h>
15 #include <linux/slab.h>
16 #include <linux/fb.h>
17 #include <linux/kernel.h>
18
19 #undef DEBUG
20
21 #define name_matches(v, s, l) \
22     ((v).name && !strncmp((s), (v).name, (l)) && strlen((v).name) == (l))
23 #define res_matches(v, x, y) \
24     ((v).xres == (x) && (v).yres == (y))
25
26 #ifdef DEBUG
27 #define DPRINTK(fmt, args...)   printk("modedb %s: " fmt, __func__ , ## args)
28 #else
29 #define DPRINTK(fmt, args...)
30 #endif
31
32 const char *fb_mode_option;
33 EXPORT_SYMBOL_GPL(fb_mode_option);
34
35 /*
36  *  Standard video mode definitions (taken from XFree86)
37  */
38
39 static const struct fb_videomode modedb[] = {
40
41         /* 640x400 @ 70 Hz, 31.5 kHz hsync */
42         { NULL, 70, 640, 400, 39721, 40, 24, 39, 9, 96, 2, 0,
43                 FB_VMODE_NONINTERLACED },
44
45         /* 640x480 @ 60 Hz, 31.5 kHz hsync */
46         { NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,     0,
47                 FB_VMODE_NONINTERLACED },
48
49         /* 800x600 @ 56 Hz, 35.15 kHz hsync */
50         { NULL, 56, 800, 600, 27777, 128, 24, 22, 1, 72, 2,     0,
51                 FB_VMODE_NONINTERLACED },
52
53         /* 1024x768 @ 87 Hz interlaced, 35.5 kHz hsync */
54         { NULL, 87, 1024, 768, 22271, 56, 24, 33, 8, 160, 8, 0,
55                 FB_VMODE_INTERLACED },
56
57         /* 640x400 @ 85 Hz, 37.86 kHz hsync */
58         { NULL, 85, 640, 400, 31746, 96, 32, 41, 1, 64, 3,
59                 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
60
61         /* 640x480 @ 72 Hz, 36.5 kHz hsync */
62         { NULL, 72, 640, 480, 31746, 144, 40, 30, 8, 40, 3, 0,
63                 FB_VMODE_NONINTERLACED },
64
65         /* 640x480 @ 75 Hz, 37.50 kHz hsync */
66         { NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3,     0,
67                 FB_VMODE_NONINTERLACED },
68
69         /* 800x600 @ 60 Hz, 37.8 kHz hsync */
70         { NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4,
71                 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
72                 FB_VMODE_NONINTERLACED },
73
74         /* 640x480 @ 85 Hz, 43.27 kHz hsync */
75         { NULL, 85, 640, 480, 27777, 80, 56, 25, 1, 56, 3, 0,
76                 FB_VMODE_NONINTERLACED },
77
78         /* 1152x864 @ 89 Hz interlaced, 44 kHz hsync */
79         { NULL, 89, 1152, 864, 15384, 96, 16, 110, 1, 216, 10, 0,
80                 FB_VMODE_INTERLACED },
81         /* 800x600 @ 72 Hz, 48.0 kHz hsync */
82         { NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
83                 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
84                 FB_VMODE_NONINTERLACED },
85
86         /* 1024x768 @ 60 Hz, 48.4 kHz hsync */
87         { NULL, 60, 1024, 768, 15384, 168, 8, 29, 3, 144, 6, 0,
88                 FB_VMODE_NONINTERLACED },
89
90         /* 640x480 @ 100 Hz, 53.01 kHz hsync */
91         { NULL, 100, 640, 480, 21834, 96, 32, 36, 8, 96, 6,     0,
92                 FB_VMODE_NONINTERLACED },
93
94         /* 1152x864 @ 60 Hz, 53.5 kHz hsync */
95         { NULL, 60, 1152, 864, 11123, 208, 64, 16, 4, 256, 8, 0,
96                 FB_VMODE_NONINTERLACED },
97
98         /* 800x600 @ 85 Hz, 55.84 kHz hsync */
99         { NULL, 85, 800, 600, 16460, 160, 64, 36, 16, 64, 5, 0,
100                 FB_VMODE_NONINTERLACED },
101
102         /* 1024x768 @ 70 Hz, 56.5 kHz hsync */
103         { NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6, 0,
104                 FB_VMODE_NONINTERLACED },
105
106         /* 1280x1024 @ 87 Hz interlaced, 51 kHz hsync */
107         { NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12, 0,
108                 FB_VMODE_INTERLACED },
109
110         /* 800x600 @ 100 Hz, 64.02 kHz hsync */
111         { NULL, 100, 800, 600, 14357, 160, 64, 30, 4, 64, 6, 0,
112                 FB_VMODE_NONINTERLACED },
113
114         /* 1024x768 @ 76 Hz, 62.5 kHz hsync */
115         { NULL, 76, 1024, 768, 11764, 208, 8, 36, 16, 120, 3, 0,
116                 FB_VMODE_NONINTERLACED },
117
118         /* 1152x864 @ 70 Hz, 62.4 kHz hsync */
119         { NULL, 70, 1152, 864, 10869, 106, 56, 20, 1, 160, 10, 0,
120                 FB_VMODE_NONINTERLACED },
121
122         /* 1280x1024 @ 61 Hz, 64.2 kHz hsync */
123         { NULL, 61, 1280, 1024, 9090, 200, 48, 26, 1, 184, 3, 0,
124                 FB_VMODE_NONINTERLACED },
125
126         /* 1400x1050 @ 60Hz, 63.9 kHz hsync */
127         { NULL, 60, 1400, 1050, 9259, 136, 40, 13, 1, 112, 3, 0,
128                 FB_VMODE_NONINTERLACED },
129
130         /* 1400x1050 @ 75,107 Hz, 82,392 kHz +hsync +vsync*/
131         { NULL, 75, 1400, 1050, 7190, 120, 56, 23, 10, 112, 13,
132                 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
133                 FB_VMODE_NONINTERLACED },
134
135         /* 1400x1050 @ 60 Hz, ? kHz +hsync +vsync*/
136         { NULL, 60, 1400, 1050, 9259, 128, 40, 12, 0, 112, 3,
137                 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
138                 FB_VMODE_NONINTERLACED },
139
140         /* 1024x768 @ 85 Hz, 70.24 kHz hsync */
141         { NULL, 85, 1024, 768, 10111, 192, 32, 34, 14, 160, 6, 0,
142                 FB_VMODE_NONINTERLACED },
143
144         /* 1152x864 @ 78 Hz, 70.8 kHz hsync */
145         { NULL, 78, 1152, 864, 9090, 228, 88, 32, 0, 84, 12, 0,
146                 FB_VMODE_NONINTERLACED },
147
148         /* 1280x1024 @ 70 Hz, 74.59 kHz hsync */
149         { NULL, 70, 1280, 1024, 7905, 224, 32, 28, 8, 160, 8, 0,
150                 FB_VMODE_NONINTERLACED },
151
152         /* 1600x1200 @ 60Hz, 75.00 kHz hsync */
153         { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
154                 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
155                 FB_VMODE_NONINTERLACED },
156
157         /* 1152x864 @ 84 Hz, 76.0 kHz hsync */
158         { NULL, 84, 1152, 864, 7407, 184, 312, 32, 0, 128, 12, 0,
159                 FB_VMODE_NONINTERLACED },
160
161         /* 1280x1024 @ 74 Hz, 78.85 kHz hsync */
162         { NULL, 74, 1280, 1024, 7407, 256, 32, 34, 3, 144, 3, 0,
163                 FB_VMODE_NONINTERLACED },
164
165         /* 1024x768 @ 100Hz, 80.21 kHz hsync */
166         { NULL, 100, 1024, 768, 8658, 192, 32, 21, 3, 192, 10, 0,
167                 FB_VMODE_NONINTERLACED },
168
169         /* 1280x1024 @ 76 Hz, 81.13 kHz hsync */
170         { NULL, 76, 1280, 1024, 7407, 248, 32, 34, 3, 104, 3, 0,
171                 FB_VMODE_NONINTERLACED },
172
173         /* 1600x1200 @ 70 Hz, 87.50 kHz hsync */
174         { NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3, 0,
175                 FB_VMODE_NONINTERLACED },
176
177         /* 1152x864 @ 100 Hz, 89.62 kHz hsync */
178         { NULL, 100, 1152, 864, 7264, 224, 32, 17, 2, 128, 19, 0,
179                 FB_VMODE_NONINTERLACED },
180
181         /* 1280x1024 @ 85 Hz, 91.15 kHz hsync */
182         { NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
183                 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
184                 FB_VMODE_NONINTERLACED },
185
186         /* 1600x1200 @ 75 Hz, 93.75 kHz hsync */
187         { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
188                 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
189                 FB_VMODE_NONINTERLACED },
190
191         /* 1680x1050 @ 60 Hz, 65.191 kHz hsync */
192         { NULL, 60, 1680, 1050, 6848, 280, 104, 30, 3, 176, 6,
193                 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
194                 FB_VMODE_NONINTERLACED },
195
196         /* 1600x1200 @ 85 Hz, 105.77 kHz hsync */
197         { NULL, 85, 1600, 1200, 4545, 272, 16, 37, 4, 192, 3,
198                 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
199                 FB_VMODE_NONINTERLACED },
200
201         /* 1280x1024 @ 100 Hz, 107.16 kHz hsync */
202         { NULL, 100, 1280, 1024, 5502, 256, 32, 26, 7, 128, 15, 0,
203                 FB_VMODE_NONINTERLACED },
204
205         /* 1800x1440 @ 64Hz, 96.15 kHz hsync  */
206         { NULL, 64, 1800, 1440, 4347, 304, 96, 46, 1, 192, 3,
207                 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
208                 FB_VMODE_NONINTERLACED },
209
210         /* 1800x1440 @ 70Hz, 104.52 kHz hsync  */
211         { NULL, 70, 1800, 1440, 4000, 304, 96, 46, 1, 192, 3,
212                 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
213                 FB_VMODE_NONINTERLACED },
214
215         /* 512x384 @ 78 Hz, 31.50 kHz hsync */
216         { NULL, 78, 512, 384, 49603, 48, 16, 16, 1, 64, 3, 0,
217                 FB_VMODE_NONINTERLACED },
218
219         /* 512x384 @ 85 Hz, 34.38 kHz hsync */
220         { NULL, 85, 512, 384, 45454, 48, 16, 16, 1, 64, 3, 0,
221                 FB_VMODE_NONINTERLACED },
222
223         /* 320x200 @ 70 Hz, 31.5 kHz hsync, 8:5 aspect ratio */
224         { NULL, 70, 320, 200, 79440, 16, 16, 20, 4, 48, 1, 0,
225                 FB_VMODE_DOUBLE },
226
227         /* 320x240 @ 60 Hz, 31.5 kHz hsync, 4:3 aspect ratio */
228         { NULL, 60, 320, 240, 79440, 16, 16, 16, 5, 48, 1, 0,
229                 FB_VMODE_DOUBLE },
230
231         /* 320x240 @ 72 Hz, 36.5 kHz hsync */
232         { NULL, 72, 320, 240, 63492, 16, 16, 16, 4, 48, 2, 0,
233                 FB_VMODE_DOUBLE },
234
235         /* 400x300 @ 56 Hz, 35.2 kHz hsync, 4:3 aspect ratio */
236         { NULL, 56, 400, 300, 55555, 64, 16, 10, 1, 32, 1, 0,
237                 FB_VMODE_DOUBLE },
238
239         /* 400x300 @ 60 Hz, 37.8 kHz hsync */
240         { NULL, 60, 400, 300, 50000, 48, 16, 11, 1, 64, 2, 0,
241                 FB_VMODE_DOUBLE },
242
243         /* 400x300 @ 72 Hz, 48.0 kHz hsync */
244         { NULL, 72, 400, 300, 40000, 32, 24, 11, 19, 64, 3,     0,
245                 FB_VMODE_DOUBLE },
246
247         /* 480x300 @ 56 Hz, 35.2 kHz hsync, 8:5 aspect ratio */
248         { NULL, 56, 480, 300, 46176, 80, 16, 10, 1, 40, 1, 0,
249                 FB_VMODE_DOUBLE },
250
251         /* 480x300 @ 60 Hz, 37.8 kHz hsync */
252         { NULL, 60, 480, 300, 41858, 56, 16, 11, 1, 80, 2, 0,
253                 FB_VMODE_DOUBLE },
254
255         /* 480x300 @ 63 Hz, 39.6 kHz hsync */
256         { NULL, 63, 480, 300, 40000, 56, 16, 11, 1, 80, 2, 0,
257                 FB_VMODE_DOUBLE },
258
259         /* 480x300 @ 72 Hz, 48.0 kHz hsync */
260         { NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3, 0,
261                 FB_VMODE_DOUBLE },
262
263         /* 1920x1200 @ 60 Hz, 74.5 Khz hsync */
264         { NULL, 60, 1920, 1200, 5177, 128, 336, 1, 38, 208, 3,
265                 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
266                 FB_VMODE_NONINTERLACED },
267
268         /* 1152x768, 60 Hz, PowerBook G4 Titanium I and II */
269         { NULL, 60, 1152, 768, 14047, 158, 26, 29, 3, 136, 6,
270                 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
271                 FB_VMODE_NONINTERLACED },
272
273         /* 1366x768, 60 Hz, 47.403 kHz hsync, WXGA 16:9 aspect ratio */
274         { NULL, 60, 1366, 768, 13806, 120, 10, 14, 3, 32, 5, 0,
275                 FB_VMODE_NONINTERLACED },
276
277         /* 1280x800, 60 Hz, 47.403 kHz hsync, WXGA 16:10 aspect ratio */
278         { NULL, 60, 1280, 800, 12048, 200, 64, 24, 1, 136, 3, 0,
279                 FB_VMODE_NONINTERLACED },
280
281         /* 720x576i @ 50 Hz, 15.625 kHz hsync (PAL RGB) */
282         { NULL, 50, 720, 576, 74074, 64, 16, 39, 5, 64, 5, 0,
283                 FB_VMODE_INTERLACED },
284
285         /* 800x520i @ 50 Hz, 15.625 kHz hsync (PAL RGB) */
286         { NULL, 50, 800, 520, 58823, 144, 64, 72, 28, 80, 5, 0,
287                 FB_VMODE_INTERLACED },
288
289         /* 864x480 @ 60 Hz, 35.15 kHz hsync */
290         { NULL, 60, 864, 480, 27777, 1, 1, 1, 1, 0, 0,
291                 0, FB_VMODE_NONINTERLACED },
292 };
293
294 #ifdef CONFIG_FB_MODE_HELPERS
295 const struct fb_videomode cea_modes[CEA_MODEDB_SIZE] = {
296         {},
297         /* 1: 640x480p @ 59.94Hz/60Hz */
298         {.refresh = 59, .xres = 640, .yres = 480, .pixclock = 39721,
299          .left_margin = 48, .right_margin = 16,
300          .upper_margin = 33, .lower_margin = 1,
301          .hsync_len = 96, .vsync_len = 2,
302          .sync = 0,
303          .vmode = FB_VMODE_NONINTERLACED},
304         /* 2: 720x480p @ 59.94Hz/60Hz */
305         {.refresh = 59, .xres = 720, .yres = 480, .pixclock = 37037,
306          .left_margin = 60, .right_margin = 16,
307          .upper_margin = 30, .lower_margin = 9,
308          .hsync_len = 62, .vsync_len = 6,
309          .sync = 0,
310          .vmode = FB_VMODE_NONINTERLACED},
311         /* 3: 720x480p @ 59.94Hz/60Hz */
312         {.refresh = 59, .xres = 720, .yres = 480, .pixclock = 37037,
313          .left_margin = 60, .right_margin = 16,
314          .upper_margin = 30, .lower_margin = 9,
315          .hsync_len = 62, .vsync_len = 6,
316          .sync = 0,
317          .vmode = FB_VMODE_NONINTERLACED},
318         /* 4: 1280x720p @ 59.94Hz/60Hz */
319         {.refresh = 60, .xres = 1280, .yres = 720, .pixclock = 13468,
320          .left_margin = 220, .right_margin = 110,
321          .upper_margin = 20, .lower_margin = 5,
322          .hsync_len = 40, .vsync_len = 5,
323          .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
324          .vmode = FB_VMODE_NONINTERLACED},
325         /* 5: 1920x1080i @ 59.94Hz/60Hz */
326         {.refresh = 60, .xres = 1920, .yres = 1080, .pixclock = 13468,
327          .left_margin = 148, .right_margin = 88,
328          .upper_margin = 15, .lower_margin = 2,
329          .hsync_len = 44, .vsync_len = 5,
330          .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
331          .vmode = FB_VMODE_INTERLACED},
332         /* 6: 720(1440)x480i @ 59.94Hz/60Hz */
333         {.refresh = 59, .xres = 1440, .yres = 480, .pixclock = 37037,
334          .left_margin = 114, .right_margin = 38,
335          .upper_margin = 15, .lower_margin = 4,
336          .hsync_len = 124, .vsync_len = 3,
337          .sync = 0,
338          .vmode = FB_VMODE_INTERLACED},
339         /* 7: 720(1440)x480i @ 59.94Hz/60Hz */
340         {.refresh = 59, .xres = 1440, .yres = 480, .pixclock = 37037,
341          .left_margin = 114, .right_margin = 38,
342          .upper_margin = 15, .lower_margin = 4,
343          .hsync_len = 124, .vsync_len = 3,
344          .sync = 0,
345          .vmode = FB_VMODE_INTERLACED},
346         /* 8: 720(1440)x240p @ 59.94Hz/60Hz */
347         {.refresh = 59, .xres = 1440, .yres = 240, .pixclock = 37037,
348          .left_margin = 114, .right_margin = 38,
349          .upper_margin = 15, .lower_margin = 5,
350          .hsync_len = 124, .vsync_len = 3,
351          .sync = 0,
352          .vmode = FB_VMODE_NONINTERLACED},
353         /* 9: 720(1440)x240p @ 59.94Hz/60Hz */
354         {.refresh = 59, .xres = 1440, .yres = 240, .pixclock = 37037,
355          .left_margin = 114, .right_margin = 38,
356          .upper_margin = 15, .lower_margin = 5,
357          .hsync_len = 124, .vsync_len = 3,
358          .sync = 0,
359          .vmode = FB_VMODE_NONINTERLACED},
360         /* 10: 2880x480i @ 59.94Hz/60Hz */
361         {.refresh = 59, .xres = 2880, .yres = 480, .pixclock = 18518,
362          .left_margin = 228, .right_margin = 76,
363          .upper_margin = 15, .lower_margin = 4,
364          .hsync_len = 248, .vsync_len = 3,
365          .sync = 0,
366          .vmode = FB_VMODE_INTERLACED},
367         /* 11: 2880x480i @ 59.94Hz/60Hz */
368         {.refresh = 59, .xres = 2880, .yres = 480, .pixclock = 18518,
369          .left_margin = 228, .right_margin = 76,
370          .upper_margin = 15, .lower_margin = 4,
371          .hsync_len = 248, .vsync_len = 3,
372          .sync = 0,
373          .vmode = FB_VMODE_INTERLACED},
374         /* 12: 2880x240p @ 59.94Hz/60Hz */
375         {.refresh = 59, .xres = 2880, .yres = 240, .pixclock = 18518,
376          .left_margin = 228, .right_margin = 76,
377          .upper_margin = 15, .lower_margin = 5,
378          .hsync_len = 248, .vsync_len = 3,
379          .sync = 0,
380          .vmode = FB_VMODE_NONINTERLACED},
381         /* 13: 2880x240p @ 59.94Hz/60Hz */
382         {.refresh = 59, .xres = 2880, .yres = 240, .pixclock = 18518,
383          .left_margin = 228, .right_margin = 76,
384          .upper_margin = 15, .lower_margin = 5,
385          .hsync_len = 248, .vsync_len = 3,
386          .sync = 0,
387          .vmode = FB_VMODE_NONINTERLACED},
388         /* 14: 1440x480p @ 59.94Hz/60Hz */
389         {.refresh = 59, .xres = 1440, .yres = 480, .pixclock = 18518,
390          .left_margin = 120, .right_margin = 32,
391          .upper_margin = 30, .lower_margin = 9,
392          .hsync_len = 124, .vsync_len = 6,
393          .sync = 0,
394          .vmode = FB_VMODE_NONINTERLACED},
395         /* 15: 1440x480p @ 59.94Hz/60Hz */
396         {.refresh = 59, .xres = 1440, .yres = 480, .pixclock = 18518,
397          .left_margin = 120, .right_margin = 32,
398          .upper_margin = 30, .lower_margin = 9,
399          .hsync_len = 124, .vsync_len = 6,
400          .sync = 0,
401          .vmode = FB_VMODE_NONINTERLACED},
402         /* 16: 1920x1080p @ 59.94Hz/60Hz */
403         {.refresh = 60, .xres = 1920, .yres = 1080, .pixclock = 6734,
404          .left_margin = 148, .right_margin = 88,
405          .upper_margin = 36, .lower_margin = 4,
406          .hsync_len = 44, .vsync_len = 5,
407          .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
408          .vmode = FB_VMODE_NONINTERLACED},
409         /* 17: 720x576p @ 50Hz */
410         {.refresh = 50, .xres = 720, .yres = 576, .pixclock = 37037,
411          .left_margin = 68, .right_margin = 12,
412          .upper_margin = 39, .lower_margin = 5,
413          .hsync_len = 64, .vsync_len = 5,
414          .sync = 0,
415          .vmode = FB_VMODE_NONINTERLACED},
416         /* 18: 720x576p @ 50Hz */
417         {.refresh = 50, .xres = 720, .yres = 576, .pixclock = 37037,
418          .left_margin = 68, .right_margin = 12,
419          .upper_margin = 39, .lower_margin = 5,
420          .hsync_len = 64, .vsync_len = 5,
421          .sync = 0,
422          .vmode = FB_VMODE_NONINTERLACED},
423         /* 19: 1280x720p @ 50Hz */
424         {.refresh = 50, .xres = 1280, .yres = 720, .pixclock = 13468,
425          .left_margin = 220, .right_margin = 440,
426          .upper_margin = 20, .lower_margin = 5,
427          .hsync_len = 40, .vsync_len = 5,
428          .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
429          .vmode = FB_VMODE_NONINTERLACED},
430         /* 20: 1920x1080i @ 50Hz */
431         {.refresh = 50, .xres = 1920, .yres = 1080, .pixclock = 13468,
432          .left_margin = 148, .right_margin = 528,
433          .upper_margin = 15, .lower_margin = 2,
434          .hsync_len = 44, .vsync_len = 5,
435          .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
436          .vmode = FB_VMODE_INTERLACED},
437         /* 21: 720(1440)x576i @ 50Hz */
438         {.refresh = 50, .xres = 1440, .yres = 576, .pixclock = 37037,
439          .left_margin = 138, .right_margin = 24,
440          .upper_margin = 19, .lower_margin = 2,
441          .hsync_len = 126, .vsync_len = 3,
442          .sync = 0,
443          .vmode = FB_VMODE_INTERLACED},
444         /* 22: 720(1440)x576i @ 50Hz */
445         {.refresh = 50, .xres = 1440, .yres = 576, .pixclock = 37037,
446          .left_margin = 138, .right_margin = 24,
447          .upper_margin = 19, .lower_margin = 2,
448          .hsync_len = 126, .vsync_len = 3,
449          .sync = 0,
450          .vmode = FB_VMODE_INTERLACED},
451         /* 23: 720(1440)x288p @ 50Hz */
452         {.refresh = 49, .xres = 1440, .yres = 288, .pixclock = 37037,
453          .left_margin = 138, .right_margin = 24,
454          .upper_margin = 19, .lower_margin = 4,
455          .hsync_len = 126, .vsync_len = 3,
456          .sync = 0,
457          .vmode = FB_VMODE_NONINTERLACED},
458         /* 24: 720(1440)x288p @ 50Hz */
459         {.refresh = 49, .xres = 1440, .yres = 288, .pixclock = 37037,
460          .left_margin = 138, .right_margin = 24,
461          .upper_margin = 19, .lower_margin = 4,
462          .hsync_len = 126, .vsync_len = 3,
463          .sync = 0,
464          .vmode = FB_VMODE_NONINTERLACED},
465         /* 25: 2880x576i @ 50Hz */
466         {.refresh = 50, .xres = 2880, .yres = 576, .pixclock = 18518,
467          .left_margin = 276, .right_margin = 48,
468          .upper_margin = 19, .lower_margin = 2,
469          .hsync_len = 252, .vsync_len = 3,
470          .sync = 0,
471          .vmode = FB_VMODE_INTERLACED},
472         /* 26: 2880x576i @ 50Hz */
473         {.refresh = 50, .xres = 2880, .yres = 576, .pixclock = 18518,
474          .left_margin = 276, .right_margin = 48,
475          .upper_margin = 19, .lower_margin = 2,
476          .hsync_len = 252, .vsync_len = 3,
477          .sync = 0,
478          .vmode = FB_VMODE_INTERLACED},
479         /* 27: 2880x288p @ 50Hz */
480         {.refresh = 49, .xres = 2880, .yres = 288, .pixclock = 18518,
481          .left_margin = 276, .right_margin = 48,
482          .upper_margin = 19, .lower_margin = 4,
483          .hsync_len = 252, .vsync_len = 3,
484          .sync = 0,
485          .vmode = FB_VMODE_NONINTERLACED},
486         /* 28: 2880x288p @ 50Hz */
487         {.refresh = 49, .xres = 2880, .yres = 288, .pixclock = 18518,
488          .left_margin = 276, .right_margin = 48,
489          .upper_margin = 19, .lower_margin = 4,
490          .hsync_len = 252, .vsync_len = 3,
491          .sync = 0,
492          .vmode = FB_VMODE_NONINTERLACED},
493         /* 29: 1440x576p @ 50Hz */
494         {.refresh = 50, .xres = 1440, .yres = 576, .pixclock = 18518,
495          .left_margin = 136, .right_margin = 24,
496          .upper_margin = 39, .lower_margin = 5,
497          .hsync_len = 128, .vsync_len = 5,
498          .sync = 0,
499          .vmode = FB_VMODE_NONINTERLACED},
500         /* 30: 1440x576p @ 50Hz */
501         {.refresh = 50, .xres = 1440, .yres = 576, .pixclock = 18518,
502          .left_margin = 136, .right_margin = 24,
503          .upper_margin = 39, .lower_margin = 5,
504          .hsync_len = 128, .vsync_len = 5,
505          .sync = 0,
506          .vmode = FB_VMODE_NONINTERLACED},
507         /* 31: 1920x1080p @ 50Hz */
508         {.refresh = 50, .xres = 1920, .yres = 1080, .pixclock = 6734,
509          .left_margin = 148, .right_margin = 528,
510          .upper_margin = 36, .lower_margin = 4,
511          .hsync_len = 44, .vsync_len = 5,
512          .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
513          .vmode = FB_VMODE_NONINTERLACED},
514         /* 32: 1920x1080p @ 23.97Hz/24Hz */
515         {.refresh = 24, .xres = 1920, .yres = 1080, .pixclock = 13468,
516          .left_margin = 148, .right_margin = 638,
517          .upper_margin = 36, .lower_margin = 4,
518          .hsync_len = 44, .vsync_len = 5,
519          .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
520          .vmode = FB_VMODE_NONINTERLACED},
521         /* 33: 1920x1080p @ 25Hz */
522         {.refresh = 25, .xres = 1920, .yres = 1080, .pixclock = 13468,
523          .left_margin = 148, .right_margin = 528,
524          .upper_margin = 36, .lower_margin = 4,
525          .hsync_len = 44, .vsync_len = 5,
526          .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
527          .vmode = FB_VMODE_NONINTERLACED},
528         /* 34: 1920x1080p @ 29.97Hz/30Hz */
529         {.refresh = 30, .xres = 1920, .yres = 1080, .pixclock = 13468,
530          .left_margin = 148, .right_margin = 88,
531          .upper_margin = 36, .lower_margin = 4,
532          .hsync_len = 44, .vsync_len = 5,
533          .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
534          .vmode = FB_VMODE_NONINTERLACED},
535         /* 35: 2880x480p @ 59.94Hz/60Hz */
536         {.refresh = 59, .xres = 2880, .yres = 480, .pixclock = 9259,
537          .left_margin = 240, .right_margin = 64,
538          .upper_margin = 30, .lower_margin = 9,
539          .hsync_len = 248, .vsync_len = 6,
540          .sync = 0,
541          .vmode = FB_VMODE_NONINTERLACED},
542         /* 36: 2880x480p @ 59.94Hz/60Hz */
543         {.refresh = 59, .xres = 2880, .yres = 480, .pixclock = 9259,
544          .left_margin = 240, .right_margin = 64,
545          .upper_margin = 30, .lower_margin = 9,
546          .hsync_len = 248, .vsync_len = 6,
547          .sync = 0,
548          .vmode = FB_VMODE_NONINTERLACED},
549         /* 37: 2880x576p @ 50Hz */
550         {.refresh = 50, .xres = 2880, .yres = 576, .pixclock = 9259,
551          .left_margin = 272, .right_margin = 48,
552          .upper_margin = 39, .lower_margin = 5,
553          .hsync_len = 256, .vsync_len = 5,
554          .sync = 0,
555          .vmode = FB_VMODE_NONINTERLACED},
556         /* 38: 2880x576p @ 50Hz */
557         {.refresh = 50, .xres = 2880, .yres = 576, .pixclock = 9259,
558          .left_margin = 272, .right_margin = 48,
559          .upper_margin = 39, .lower_margin = 5,
560          .hsync_len = 256, .vsync_len = 5,
561          .sync = 0,
562          .vmode = FB_VMODE_NONINTERLACED},
563         /* 39: 1920x1080i @ 50Hz */
564         {.refresh = 50, .xres = 1920, .yres = 1080, .pixclock = 13888,
565          .left_margin = 184, .right_margin = 32,
566          .upper_margin = 57, .lower_margin = 2,
567          .hsync_len = 168, .vsync_len = 5,
568          .sync = FB_SYNC_HOR_HIGH_ACT,
569          .vmode = FB_VMODE_INTERLACED},
570         /* 40: 1920x1080i @ 100Hz */
571         {.refresh = 100, .xres = 1920, .yres = 1080, .pixclock = 6734,
572          .left_margin = 148, .right_margin = 528,
573          .upper_margin = 15, .lower_margin = 2,
574          .hsync_len = 44, .vsync_len = 5,
575          .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
576          .vmode = FB_VMODE_INTERLACED},
577         /* 41: 1280x720p @ 100Hz */
578         {.refresh = 100, .xres = 1280, .yres = 720, .pixclock = 6734,
579          .left_margin = 220, .right_margin = 440,
580          .upper_margin = 20, .lower_margin = 5,
581          .hsync_len = 40, .vsync_len = 5,
582          .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
583          .vmode = FB_VMODE_NONINTERLACED},
584         /* 42: 720x576p @ 100Hz */
585         {.refresh = 100, .xres = 720, .yres = 576, .pixclock = 18518,
586          .left_margin = 68, .right_margin = 12,
587          .upper_margin = 39, .lower_margin = 5,
588          .hsync_len = 64, .vsync_len = 5,
589          .sync = 0,
590          .vmode = FB_VMODE_NONINTERLACED},
591         /* 43: 720x576p @ 100Hz */
592         {.refresh = 100, .xres = 720, .yres = 576, .pixclock = 18518,
593          .left_margin = 68, .right_margin = 12,
594          .upper_margin = 39, .lower_margin = 5,
595          .hsync_len = 64, .vsync_len = 5,
596          .sync = 0,
597          .vmode = FB_VMODE_NONINTERLACED},
598         /* 44: 720(1440)x576i @ 100Hz */
599         {.refresh = 100, .xres = 1440, .yres = 576, .pixclock = 18518,
600          .left_margin = 138, .right_margin = 24,
601          .upper_margin = 19, .lower_margin = 2,
602          .hsync_len = 126, .vsync_len = 3,
603          .sync = 0,
604          .vmode = FB_VMODE_INTERLACED},
605         /* 45: 720(1440)x576i @ 100Hz */
606         {.refresh = 100, .xres = 1440, .yres = 576, .pixclock = 18518,
607          .left_margin = 138, .right_margin = 24,
608          .upper_margin = 19, .lower_margin = 2,
609          .hsync_len = 126, .vsync_len = 3,
610          .sync = 0,
611          .vmode = FB_VMODE_INTERLACED},
612         /* 46: 1920x1080i @ 119.88/120Hz */
613         {.refresh = 120, .xres = 1920, .yres = 1080, .pixclock = 6734,
614          .left_margin = 148, .right_margin = 88,
615          .upper_margin = 15, .lower_margin = 2,
616          .hsync_len = 44, .vsync_len = 5,
617          .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
618          .vmode = FB_VMODE_INTERLACED},
619         /* 47: 1280x720p @ 119.88/120Hz */
620         {.refresh = 120, .xres = 1280, .yres = 720, .pixclock = 6734,
621          .left_margin = 220, .right_margin = 110,
622          .upper_margin = 20, .lower_margin = 5,
623          .hsync_len = 40, .vsync_len = 5,
624          .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
625          .vmode = FB_VMODE_NONINTERLACED},
626         /* 48: 720x480p @ 119.88/120Hz */
627         {.refresh = 119, .xres = 720, .yres = 480, .pixclock = 18518,
628          .left_margin = 60, .right_margin = 16,
629          .upper_margin = 30, .lower_margin = 9,
630          .hsync_len = 62, .vsync_len = 6,
631          .sync = 0,
632          .vmode = FB_VMODE_NONINTERLACED},
633         /* 49: 720x480p @ 119.88/120Hz */
634         {.refresh = 119, .xres = 720, .yres = 480, .pixclock = 18518,
635          .left_margin = 60, .right_margin = 16,
636          .upper_margin = 30, .lower_margin = 9,
637          .hsync_len = 62, .vsync_len = 6,
638          .sync = 0,
639          .vmode = FB_VMODE_NONINTERLACED},
640         /* 50: 720(1440)x480i @ 119.88/120Hz */
641         {.refresh = 119, .xres = 1440, .yres = 480, .pixclock = 18518,
642          .left_margin = 114, .right_margin = 38,
643          .upper_margin = 15, .lower_margin = 4,
644          .hsync_len = 124, .vsync_len = 3,
645          .sync = 0,
646          .vmode = FB_VMODE_INTERLACED},
647         /* 51: 720(1440)x480i @ 119.88/120Hz */
648         {.refresh = 119, .xres = 1440, .yres = 480, .pixclock = 18518,
649          .left_margin = 114, .right_margin = 38,
650          .upper_margin = 15, .lower_margin = 4,
651          .hsync_len = 124, .vsync_len = 3,
652          .sync = 0,
653          .vmode = FB_VMODE_INTERLACED},
654         /* 52: 720x576p @ 200Hz */
655         {.refresh = 200, .xres = 720, .yres = 576, .pixclock = 9259,
656          .left_margin = 68, .right_margin = 12,
657          .upper_margin = 39, .lower_margin = 5,
658          .hsync_len = 64, .vsync_len = 5,
659          .sync = 0,
660          .vmode = FB_VMODE_NONINTERLACED},
661         /* 53: 720x576p @ 200Hz */
662         {.refresh = 200, .xres = 720, .yres = 576, .pixclock = 9259,
663          .left_margin = 68, .right_margin = 12,
664          .upper_margin = 39, .lower_margin = 5,
665          .hsync_len = 64, .vsync_len = 5,
666          .sync = 0,
667          .vmode = FB_VMODE_NONINTERLACED},
668         /* 54: 720(1440)x576i @ 200Hz */
669         {.refresh = 200, .xres = 1440, .yres = 576, .pixclock = 9259,
670          .left_margin = 138, .right_margin = 24,
671          .upper_margin = 19, .lower_margin = 2,
672          .hsync_len = 126, .vsync_len = 3,
673          .sync = 0,
674          .vmode = FB_VMODE_INTERLACED},
675         /* 55: 720(1440)x576i @ 200Hz */
676         {.refresh = 200, .xres = 1440, .yres = 576, .pixclock = 9259,
677          .left_margin = 138, .right_margin = 24,
678          .upper_margin = 19, .lower_margin = 2,
679          .hsync_len = 126, .vsync_len = 3,
680          .sync = 0,
681          .vmode = FB_VMODE_INTERLACED},
682         /* 56: 720x480p @ 239.76/240Hz */
683         {.refresh = 239, .xres = 720, .yres = 480, .pixclock = 9259,
684          .left_margin = 60, .right_margin = 16,
685          .upper_margin = 30, .lower_margin = 9,
686          .hsync_len = 62, .vsync_len = 6,
687          .sync = 0,
688          .vmode = FB_VMODE_NONINTERLACED},
689         /* 57: 720x480p @ 239.76/240Hz */
690         {.refresh = 239, .xres = 720, .yres = 480, .pixclock = 9259,
691          .left_margin = 60, .right_margin = 16,
692          .upper_margin = 30, .lower_margin = 9,
693          .hsync_len = 62, .vsync_len = 6,
694          .sync = 0,
695          .vmode = FB_VMODE_NONINTERLACED},
696         /* 58: 720(1440)x480i @ 239.76/240Hz */
697         {.refresh = 239, .xres = 1440, .yres = 480, .pixclock = 9259,
698          .left_margin = 114, .right_margin = 38,
699          .upper_margin = 15, .lower_margin = 4,
700          .hsync_len = 124, .vsync_len = 3,
701          .sync = 0,
702          .vmode = FB_VMODE_INTERLACED},
703         /* 59: 720(1440)x480i @ 239.76/240Hz */
704         {.refresh = 239, .xres = 1440, .yres = 480, .pixclock = 9259,
705          .left_margin = 114, .right_margin = 38,
706          .upper_margin = 15, .lower_margin = 4,
707          .hsync_len = 124, .vsync_len = 3,
708          .sync = 0,
709          .vmode = FB_VMODE_INTERLACED},
710         /* 60: 1280x720p @ 23.97Hz/24Hz */
711         {.refresh = 24, .xres = 1280, .yres = 720, .pixclock = 16835,
712          .left_margin = 220, .right_margin = 1760,
713          .upper_margin = 20, .lower_margin = 5,
714          .hsync_len = 40, .vsync_len = 5,
715          .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
716          .vmode = FB_VMODE_NONINTERLACED},
717         /* 61: 1280x720p @ 25Hz */
718         {.refresh = 25, .xres = 1280, .yres = 720, .pixclock = 13468,
719          .left_margin = 220, .right_margin = 2420,
720          .upper_margin = 20, .lower_margin = 5,
721          .hsync_len = 40, .vsync_len = 5,
722          .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
723          .vmode = FB_VMODE_NONINTERLACED},
724         /* 62: 1280x720p @ 29.97Hz/30Hz */
725         {.refresh = 30, .xres = 1280, .yres = 720, .pixclock = 13468,
726          .left_margin = 220, .right_margin = 1760,
727          .upper_margin = 20, .lower_margin = 5,
728          .hsync_len = 40, .vsync_len = 5,
729          .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
730          .vmode = FB_VMODE_NONINTERLACED},
731         /* 63: 1920x1080p @ 119.88/120Hz */
732         {.refresh = 120, .xres = 1920, .yres = 1080, .pixclock = 3367,
733          .left_margin = 148, .right_margin = 88,
734          .upper_margin = 36, .lower_margin = 4,
735          .hsync_len = 44, .vsync_len = 5,
736          .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
737          .vmode = FB_VMODE_NONINTERLACED},
738         /* 64: 1920x1080p @ 100Hz */
739         {.refresh = 100, .xres = 1920, .yres = 1080, .pixclock = 3367,
740          .left_margin = 148, .right_margin = 528,
741          .upper_margin = 36, .lower_margin = 4,
742          .hsync_len = 44, .vsync_len = 5,
743          .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
744          .vmode = FB_VMODE_NONINTERLACED},
745 };
746 EXPORT_SYMBOL(cea_modes);
747
748 const struct fb_videomode vesa_modes[] = {
749         /* 0 640x350-85 VESA */
750         { NULL, 85, 640, 350, 31746,  96, 32, 60, 32, 64, 3,
751           FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
752         /* 1 640x400-85 VESA */
753         { NULL, 85, 640, 400, 31746,  96, 32, 41, 01, 64, 3,
754           FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
755         /* 2 720x400-85 VESA */
756         { NULL, 85, 721, 400, 28169, 108, 36, 42, 01, 72, 3,
757           FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
758         /* 3 640x480-60 VESA */
759         { NULL, 60, 640, 480, 39682,  48, 16, 33, 10, 96, 2,
760           0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
761         /* 4 640x480-72 VESA */
762         { NULL, 72, 640, 480, 31746, 128, 24, 29, 9, 40, 2,
763           0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
764         /* 5 640x480-75 VESA */
765         { NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
766           0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
767         /* 6 640x480-85 VESA */
768         { NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3,
769           0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
770         /* 7 800x600-56 VESA */
771         { NULL, 56, 800, 600, 27777, 128, 24, 22, 01, 72, 2,
772           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
773           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
774         /* 8 800x600-60 VESA */
775         { NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4,
776           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
777           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
778         /* 9 800x600-72 VESA */
779         { NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
780           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
781           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
782         /* 10 800x600-75 VESA */
783         { NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3,
784           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
785           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
786         /* 11 800x600-85 VESA */
787         { NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3,
788           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
789           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
790         /* 12 1024x768i-43 VESA */
791         { NULL, 43, 1024, 768, 22271, 56, 8, 41, 0, 176, 8,
792           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
793           FB_VMODE_INTERLACED, FB_MODE_IS_VESA },
794         /* 13 1024x768-60 VESA */
795         { NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6,
796           0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
797         /* 14 1024x768-70 VESA */
798         { NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6,
799           0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
800         /* 15 1024x768-75 VESA */
801         { NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
802           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
803           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
804         /* 16 1024x768-85 VESA */
805         { NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
806           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
807           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
808         /* 17 1152x864-75 VESA */
809         { NULL, 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3,
810           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
811           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
812         /* 18 1280x960-60 VESA */
813         { NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
814           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
815           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
816         /* 19 1280x960-85 VESA */
817         { NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
818           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
819           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
820         /* 20 1280x1024-60 VESA */
821         { NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
822           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
823           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
824         /* 21 1280x1024-75 VESA */
825         { NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
826           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
827           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
828         /* 22 1280x1024-85 VESA */
829         { NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
830           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
831           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
832         /* 23 1600x1200-60 VESA */
833         { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
834           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
835           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
836         /* 24 1600x1200-65 VESA */
837         { NULL, 65, 1600, 1200, 5698, 304,  64, 46, 1, 192, 3,
838           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
839           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
840         /* 25 1600x1200-70 VESA */
841         { NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3,
842           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
843           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
844         /* 26 1600x1200-75 VESA */
845         { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
846           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
847           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
848         /* 27 1600x1200-85 VESA */
849         { NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
850           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
851           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
852         /* 28 1792x1344-60 VESA */
853         { NULL, 60, 1792, 1344, 4882, 328, 128, 46, 1, 200, 3,
854           FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
855         /* 29 1792x1344-75 VESA */
856         { NULL, 75, 1792, 1344, 3831, 352, 96, 69, 1, 216, 3,
857           FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
858         /* 30 1856x1392-60 VESA */
859         { NULL, 60, 1856, 1392, 4580, 352, 96, 43, 1, 224, 3,
860           FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
861         /* 31 1856x1392-75 VESA */
862         { NULL, 75, 1856, 1392, 3472, 352, 128, 104, 1, 224, 3,
863           FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
864         /* 32 1920x1440-60 VESA */
865         { NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 200, 3,
866           FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
867         /* 33 1920x1440-75 VESA */
868         { NULL, 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3,
869           FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
870 };
871 EXPORT_SYMBOL(vesa_modes);
872 #endif /* CONFIG_FB_MODE_HELPERS */
873
874 /**
875  *      fb_try_mode - test a video mode
876  *      @var: frame buffer user defined part of display
877  *      @info: frame buffer info structure
878  *      @mode: frame buffer video mode structure
879  *      @bpp: color depth in bits per pixel
880  *
881  *      Tries a video mode to test it's validity for device @info.
882  *
883  *      Returns 1 on success.
884  *
885  */
886
887 static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
888                        const struct fb_videomode *mode, unsigned int bpp)
889 {
890     int err = 0;
891
892     DPRINTK("Trying mode %s %dx%d-%d@%d\n", mode->name ? mode->name : "noname",
893             mode->xres, mode->yres, bpp, mode->refresh);
894     var->xres = mode->xres;
895     var->yres = mode->yres;
896     var->xres_virtual = mode->xres;
897     var->yres_virtual = mode->yres;
898     var->xoffset = 0;
899     var->yoffset = 0;
900     var->bits_per_pixel = bpp;
901     var->activate |= FB_ACTIVATE_TEST;
902     var->pixclock = mode->pixclock;
903     var->left_margin = mode->left_margin;
904     var->right_margin = mode->right_margin;
905     var->upper_margin = mode->upper_margin;
906     var->lower_margin = mode->lower_margin;
907     var->hsync_len = mode->hsync_len;
908     var->vsync_len = mode->vsync_len;
909     var->sync = mode->sync;
910     var->vmode = mode->vmode;
911     if (info->fbops->fb_check_var)
912         err = info->fbops->fb_check_var(var, info);
913     var->activate &= ~FB_ACTIVATE_TEST;
914     return err;
915 }
916
917 /**
918  *      fb_find_mode - finds a valid video mode
919  *      @var: frame buffer user defined part of display
920  *      @info: frame buffer info structure
921  *      @mode_option: string video mode to find
922  *      @db: video mode database
923  *      @dbsize: size of @db
924  *      @default_mode: default video mode to fall back to
925  *      @default_bpp: default color depth in bits per pixel
926  *
927  *      Finds a suitable video mode, starting with the specified mode
928  *      in @mode_option with fallback to @default_mode.  If
929  *      @default_mode fails, all modes in the video mode database will
930  *      be tried.
931  *
932  *      Valid mode specifiers for @mode_option:
933  *
934  *      <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m] or
935  *      <name>[-<bpp>][@<refresh>]
936  *
937  *      with <xres>, <yres>, <bpp> and <refresh> decimal numbers and
938  *      <name> a string.
939  *
940  *      If 'M' is present after yres (and before refresh/bpp if present),
941  *      the function will compute the timings using VESA(tm) Coordinated
942  *      Video Timings (CVT).  If 'R' is present after 'M', will compute with
943  *      reduced blanking (for flatpanels).  If 'i' is present, compute
944  *      interlaced mode.  If 'm' is present, add margins equal to 1.8%
945  *      of xres rounded down to 8 pixels, and 1.8% of yres. The char
946  *      'i' and 'm' must be after 'M' and 'R'. Example:
947  *
948  *      1024x768MR-8@60m - Reduced blank with margins at 60Hz.
949  *
950  *      NOTE: The passed struct @var is _not_ cleared!  This allows you
951  *      to supply values for e.g. the grayscale and accel_flags fields.
952  *
953  *      Returns zero for failure, 1 if using specified @mode_option,
954  *      2 if using specified @mode_option with an ignored refresh rate,
955  *      3 if default mode is used, 4 if fall back to any valid mode.
956  *
957  */
958
959 int fb_find_mode(struct fb_var_screeninfo *var,
960                  struct fb_info *info, const char *mode_option,
961                  const struct fb_videomode *db, unsigned int dbsize,
962                  const struct fb_videomode *default_mode,
963                  unsigned int default_bpp)
964 {
965     int i;
966
967     /* Set up defaults */
968     if (!db) {
969         db = modedb;
970         dbsize = ARRAY_SIZE(modedb);
971     }
972
973     if (!default_mode)
974         default_mode = &db[0];
975
976     if (!default_bpp)
977         default_bpp = 8;
978
979     /* Did the user specify a video mode? */
980     if (!mode_option)
981         mode_option = fb_mode_option;
982     if (mode_option) {
983         const char *name = mode_option;
984         unsigned int namelen = strlen(name);
985         int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
986         unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0;
987         int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0;
988         u32 best, diff, tdiff;
989
990         for (i = namelen-1; i >= 0; i--) {
991             switch (name[i]) {
992                 case '@':
993                     namelen = i;
994                     if (!refresh_specified && !bpp_specified &&
995                         !yres_specified) {
996                         refresh = simple_strtol(&name[i+1], NULL, 10);
997                         refresh_specified = 1;
998                         if (cvt || rb)
999                             cvt = 0;
1000                     } else
1001                         goto done;
1002                     break;
1003                 case '-':
1004                     namelen = i;
1005                     if (!bpp_specified && !yres_specified) {
1006                         bpp = simple_strtol(&name[i+1], NULL, 10);
1007                         bpp_specified = 1;
1008                         if (cvt || rb)
1009                             cvt = 0;
1010                     } else
1011                         goto done;
1012                     break;
1013                 case 'x':
1014                     if (!yres_specified) {
1015                         yres = simple_strtol(&name[i+1], NULL, 10);
1016                         yres_specified = 1;
1017                     } else
1018                         goto done;
1019                     break;
1020                 case '0' ... '9':
1021                     break;
1022                 case 'M':
1023                     if (!yres_specified)
1024                         cvt = 1;
1025                     break;
1026                 case 'R':
1027                     if (!cvt)
1028                         rb = 1;
1029                     break;
1030                 case 'm':
1031                     if (!cvt)
1032                         margins = 1;
1033                     break;
1034                 case 'i':
1035                     if (!cvt)
1036                         interlace = 1;
1037                     break;
1038                 default:
1039                     goto done;
1040             }
1041         }
1042         if (i < 0 && yres_specified) {
1043             xres = simple_strtol(name, NULL, 10);
1044             res_specified = 1;
1045         }
1046 done:
1047         if (cvt) {
1048             struct fb_videomode cvt_mode;
1049             int ret;
1050
1051             DPRINTK("CVT mode %dx%d@%dHz%s%s%s\n", xres, yres,
1052                     (refresh) ? refresh : 60, (rb) ? " reduced blanking" :
1053                     "", (margins) ? " with margins" : "", (interlace) ?
1054                     " interlaced" : "");
1055
1056             memset(&cvt_mode, 0, sizeof(cvt_mode));
1057             cvt_mode.xres = xres;
1058             cvt_mode.yres = yres;
1059             cvt_mode.refresh = (refresh) ? refresh : 60;
1060
1061             if (interlace)
1062                 cvt_mode.vmode |= FB_VMODE_INTERLACED;
1063             else
1064                 cvt_mode.vmode &= ~FB_VMODE_INTERLACED;
1065
1066             ret = fb_find_mode_cvt(&cvt_mode, margins, rb);
1067
1068             if (!ret && !fb_try_mode(var, info, &cvt_mode, bpp)) {
1069                 DPRINTK("modedb CVT: CVT mode ok\n");
1070                 return 1;
1071             }
1072
1073             DPRINTK("CVT mode invalid, getting mode from database\n");
1074         }
1075
1076         DPRINTK("Trying specified video mode%s %ix%i\n",
1077             refresh_specified ? "" : " (ignoring refresh rate)", xres, yres);
1078
1079         if (!refresh_specified) {
1080                 /*
1081                  * If the caller has provided a custom mode database and a
1082                  * valid monspecs structure, we look for the mode with the
1083                  * highest refresh rate.  Otherwise we play it safe it and
1084                  * try to find a mode with a refresh rate closest to the
1085                  * standard 60 Hz.
1086                  */
1087                 if (db != modedb &&
1088                     info->monspecs.vfmin && info->monspecs.vfmax &&
1089                     info->monspecs.hfmin && info->monspecs.hfmax &&
1090                     info->monspecs.dclkmax) {
1091                         refresh = 1000;
1092                 } else {
1093                         refresh = 60;
1094                 }
1095         }
1096
1097         diff = -1;
1098         best = -1;
1099         for (i = 0; i < dbsize; i++) {
1100                 if ((name_matches(db[i], name, namelen) ||
1101                     (res_specified && res_matches(db[i], xres, yres))) &&
1102                     !fb_try_mode(var, info, &db[i], bpp)) {
1103                         if (refresh_specified && db[i].refresh == refresh) {
1104                                 return 1;
1105                         } else {
1106                                 if (abs(db[i].refresh - refresh) < diff) {
1107                                         diff = abs(db[i].refresh - refresh);
1108                                         best = i;
1109                                 }
1110                         }
1111                 }
1112         }
1113         if (best != -1) {
1114                 fb_try_mode(var, info, &db[best], bpp);
1115                 return (refresh_specified) ? 2 : 1;
1116         }
1117
1118         diff = 2 * (xres + yres);
1119         best = -1;
1120         DPRINTK("Trying best-fit modes\n");
1121         for (i = 0; i < dbsize; i++) {
1122                 DPRINTK("Trying %ix%i\n", db[i].xres, db[i].yres);
1123                 if (!fb_try_mode(var, info, &db[i], bpp)) {
1124                         tdiff = abs(db[i].xres - xres) +
1125                                 abs(db[i].yres - yres);
1126
1127                         /*
1128                          * Penalize modes with resolutions smaller
1129                          * than requested.
1130                          */
1131                         if (xres > db[i].xres || yres > db[i].yres)
1132                                 tdiff += xres + yres;
1133
1134                         if (diff > tdiff) {
1135                                 diff = tdiff;
1136                                 best = i;
1137                         }
1138                 }
1139         }
1140         if (best != -1) {
1141             fb_try_mode(var, info, &db[best], bpp);
1142             return 5;
1143         }
1144     }
1145
1146     DPRINTK("Trying default video mode\n");
1147     if (!fb_try_mode(var, info, default_mode, default_bpp))
1148         return 3;
1149
1150     DPRINTK("Trying all modes\n");
1151     for (i = 0; i < dbsize; i++)
1152         if (!fb_try_mode(var, info, &db[i], default_bpp))
1153             return 4;
1154
1155     DPRINTK("No valid mode found\n");
1156     return 0;
1157 }
1158
1159 /**
1160  * fb_var_to_videomode - convert fb_var_screeninfo to fb_videomode
1161  * @mode: pointer to struct fb_videomode
1162  * @var: pointer to struct fb_var_screeninfo
1163  */
1164 void fb_var_to_videomode(struct fb_videomode *mode,
1165                          const struct fb_var_screeninfo *var)
1166 {
1167         u32 pixclock, hfreq, htotal, vtotal;
1168
1169         mode->name = NULL;
1170         mode->xres = var->xres;
1171         mode->yres = var->yres;
1172         mode->pixclock = var->pixclock;
1173         mode->hsync_len = var->hsync_len;
1174         mode->vsync_len = var->vsync_len;
1175         mode->left_margin = var->left_margin;
1176         mode->right_margin = var->right_margin;
1177         mode->upper_margin = var->upper_margin;
1178         mode->lower_margin = var->lower_margin;
1179         mode->sync = var->sync;
1180         mode->vmode = var->vmode & FB_VMODE_MASK;
1181         mode->flag = FB_MODE_IS_FROM_VAR;
1182         mode->refresh = 0;
1183
1184         if (!var->pixclock)
1185                 return;
1186
1187         pixclock = PICOS2KHZ(var->pixclock) * 1000;
1188
1189         htotal = var->xres + var->right_margin + var->hsync_len +
1190                 var->left_margin;
1191         vtotal = var->yres + var->lower_margin + var->vsync_len +
1192                 var->upper_margin;
1193
1194         if (var->vmode & FB_VMODE_INTERLACED)
1195                 vtotal /= 2;
1196         if (var->vmode & FB_VMODE_DOUBLE)
1197                 vtotal *= 2;
1198
1199         hfreq = pixclock/htotal;
1200         mode->refresh = hfreq/vtotal;
1201 }
1202
1203 /**
1204  * fb_videomode_to_var - convert fb_videomode to fb_var_screeninfo
1205  * @var: pointer to struct fb_var_screeninfo
1206  * @mode: pointer to struct fb_videomode
1207  */
1208 void fb_videomode_to_var(struct fb_var_screeninfo *var,
1209                          const struct fb_videomode *mode)
1210 {
1211         var->xres = mode->xres;
1212         var->yres = mode->yres;
1213         var->xres_virtual = mode->xres;
1214         var->yres_virtual = mode->yres;
1215         var->xoffset = 0;
1216         var->yoffset = 0;
1217         var->pixclock = mode->pixclock;
1218         var->left_margin = mode->left_margin;
1219         var->right_margin = mode->right_margin;
1220         var->upper_margin = mode->upper_margin;
1221         var->lower_margin = mode->lower_margin;
1222         var->hsync_len = mode->hsync_len;
1223         var->vsync_len = mode->vsync_len;
1224         var->sync = mode->sync;
1225         var->vmode = mode->vmode & FB_VMODE_MASK;
1226 }
1227
1228 /**
1229  * fb_mode_is_equal - compare 2 videomodes
1230  * @mode1: first videomode
1231  * @mode2: second videomode
1232  *
1233  * RETURNS:
1234  * 1 if equal, 0 if not
1235  */
1236 int fb_mode_is_equal(const struct fb_videomode *mode1,
1237                      const struct fb_videomode *mode2)
1238 {
1239         return (mode1->xres         == mode2->xres &&
1240                 mode1->yres         == mode2->yres &&
1241                 mode1->pixclock     == mode2->pixclock &&
1242                 mode1->hsync_len    == mode2->hsync_len &&
1243                 mode1->vsync_len    == mode2->vsync_len &&
1244                 mode1->left_margin  == mode2->left_margin &&
1245                 mode1->right_margin == mode2->right_margin &&
1246                 mode1->upper_margin == mode2->upper_margin &&
1247                 mode1->lower_margin == mode2->lower_margin &&
1248                 mode1->sync         == mode2->sync &&
1249                 mode1->vmode        == mode2->vmode);
1250 }
1251
1252 /**
1253  * fb_find_best_mode - find best matching videomode
1254  * @var: pointer to struct fb_var_screeninfo
1255  * @head: pointer to struct list_head of modelist
1256  *
1257  * RETURNS:
1258  * struct fb_videomode, NULL if none found
1259  *
1260  * IMPORTANT:
1261  * This function assumes that all modelist entries in
1262  * info->modelist are valid.
1263  *
1264  * NOTES:
1265  * Finds best matching videomode which has an equal or greater dimension than
1266  * var->xres and var->yres.  If more than 1 videomode is found, will return
1267  * the videomode with the highest refresh rate
1268  */
1269 const struct fb_videomode *fb_find_best_mode(const struct fb_var_screeninfo *var,
1270                                              struct list_head *head)
1271 {
1272         struct list_head *pos;
1273         struct fb_modelist *modelist;
1274         struct fb_videomode *mode, *best = NULL;
1275         u32 diff = -1;
1276
1277         list_for_each(pos, head) {
1278                 u32 d;
1279
1280                 modelist = list_entry(pos, struct fb_modelist, list);
1281                 mode = &modelist->mode;
1282
1283                 if (mode->xres >= var->xres && mode->yres >= var->yres) {
1284                         d = (mode->xres - var->xres) +
1285                                 (mode->yres - var->yres);
1286                         if (diff > d) {
1287                                 diff = d;
1288                                 best = mode;
1289                         } else if (diff == d && best &&
1290                                    mode->refresh > best->refresh)
1291                                 best = mode;
1292                 }
1293         }
1294         return best;
1295 }
1296
1297 /**
1298  * fb_find_nearest_mode - find closest videomode
1299  *
1300  * @mode: pointer to struct fb_videomode
1301  * @head: pointer to modelist
1302  *
1303  * Finds best matching videomode, smaller or greater in dimension.
1304  * If more than 1 videomode is found, will return the videomode with
1305  * the closest refresh rate.
1306  */
1307 const struct fb_videomode *fb_find_nearest_mode(const struct fb_videomode *mode,
1308                                                 struct list_head *head)
1309 {
1310         struct list_head *pos;
1311         struct fb_modelist *modelist;
1312         struct fb_videomode *cmode, *best = NULL;
1313         u32 diff = -1, diff_refresh = -1;
1314
1315         list_for_each(pos, head) {
1316                 u32 d;
1317
1318                 modelist = list_entry(pos, struct fb_modelist, list);
1319                 cmode = &modelist->mode;
1320
1321                 d = abs(cmode->xres - mode->xres) +
1322                         abs(cmode->yres - mode->yres);
1323                 if (diff > d) {
1324                         diff = d;
1325                         diff_refresh = abs(cmode->refresh - mode->refresh);
1326                         best = cmode;
1327                 } else if (diff == d) {
1328                         d = abs(cmode->refresh - mode->refresh);
1329                         if (diff_refresh > d) {
1330                                 diff_refresh = d;
1331                                 best = cmode;
1332                         }
1333                 }
1334         }
1335
1336         return best;
1337 }
1338
1339 /**
1340  * fb_match_mode - find a videomode which exactly matches the timings in var
1341  * @var: pointer to struct fb_var_screeninfo
1342  * @head: pointer to struct list_head of modelist
1343  *
1344  * RETURNS:
1345  * struct fb_videomode, NULL if none found
1346  */
1347 const struct fb_videomode *fb_match_mode(const struct fb_var_screeninfo *var,
1348                                          struct list_head *head)
1349 {
1350         struct list_head *pos;
1351         struct fb_modelist *modelist;
1352         struct fb_videomode *m, mode;
1353
1354         fb_var_to_videomode(&mode, var);
1355         list_for_each(pos, head) {
1356                 modelist = list_entry(pos, struct fb_modelist, list);
1357                 m = &modelist->mode;
1358                 if (fb_mode_is_equal(m, &mode))
1359                         return m;
1360         }
1361         return NULL;
1362 }
1363
1364 /**
1365  * fb_add_videomode - adds videomode entry to modelist
1366  * @mode: videomode to add
1367  * @head: struct list_head of modelist
1368  *
1369  * NOTES:
1370  * Will only add unmatched mode entries
1371  */
1372 int fb_add_videomode(const struct fb_videomode *mode, struct list_head *head)
1373 {
1374         struct list_head *pos;
1375         struct fb_modelist *modelist;
1376         struct fb_videomode *m;
1377         int found = 0;
1378
1379         list_for_each(pos, head) {
1380                 modelist = list_entry(pos, struct fb_modelist, list);
1381                 m = &modelist->mode;
1382                 if (fb_mode_is_equal(m, mode)) {
1383                         found = 1;
1384                         break;
1385                 }
1386         }
1387         if (!found) {
1388                 modelist = kmalloc(sizeof(struct fb_modelist),
1389                                                   GFP_KERNEL);
1390
1391                 if (!modelist)
1392                         return -ENOMEM;
1393                 modelist->mode = *mode;
1394                 list_add_tail(&modelist->list, head);
1395         }
1396         return 0;
1397 }
1398
1399 /**
1400  * fb_delete_videomode - removed videomode entry from modelist
1401  * @mode: videomode to remove
1402  * @head: struct list_head of modelist
1403  *
1404  * NOTES:
1405  * Will remove all matching mode entries
1406  */
1407 void fb_delete_videomode(const struct fb_videomode *mode,
1408                          struct list_head *head)
1409 {
1410         struct list_head *pos, *n;
1411         struct fb_modelist *modelist;
1412         struct fb_videomode *m;
1413
1414         list_for_each_safe(pos, n, head) {
1415                 modelist = list_entry(pos, struct fb_modelist, list);
1416                 m = &modelist->mode;
1417                 if (fb_mode_is_equal(m, mode)) {
1418                         list_del(pos);
1419                         kfree(pos);
1420                 }
1421         }
1422 }
1423
1424 /**
1425  * fb_destroy_modelist - destroy modelist
1426  * @head: struct list_head of modelist
1427  */
1428 void fb_destroy_modelist(struct list_head *head)
1429 {
1430         struct list_head *pos, *n;
1431
1432         list_for_each_safe(pos, n, head) {
1433                 list_del(pos);
1434                 kfree(pos);
1435         }
1436 }
1437 EXPORT_SYMBOL_GPL(fb_destroy_modelist);
1438
1439 /**
1440  * fb_videomode_to_modelist - convert mode array to mode list
1441  * @modedb: array of struct fb_videomode
1442  * @num: number of entries in array
1443  * @head: struct list_head of modelist
1444  */
1445 void fb_videomode_to_modelist(const struct fb_videomode *modedb, int num,
1446                               struct list_head *head)
1447 {
1448         int i;
1449
1450         INIT_LIST_HEAD(head);
1451
1452         for (i = 0; i < num; i++) {
1453                 if (fb_add_videomode(&modedb[i], head))
1454                         return;
1455         }
1456 }
1457
1458 const struct fb_videomode *fb_find_best_display(const struct fb_monspecs *specs,
1459                                                 struct list_head *head)
1460 {
1461         struct list_head *pos;
1462         struct fb_modelist *modelist;
1463         const struct fb_videomode *m, *m1 = NULL, *md = NULL, *best = NULL;
1464         int first = 0;
1465
1466         if (!head->prev || !head->next || list_empty(head))
1467                 goto finished;
1468
1469         /* get the first detailed mode and the very first mode */
1470         list_for_each(pos, head) {
1471                 modelist = list_entry(pos, struct fb_modelist, list);
1472                 m = &modelist->mode;
1473
1474                 if (!first) {
1475                         m1 = m;
1476                         first = 1;
1477                 }
1478
1479                 if (m->flag & FB_MODE_IS_FIRST) {
1480                         md = m;
1481                         break;
1482                 }
1483         }
1484
1485         /* first detailed timing is preferred */
1486         if (specs->misc & FB_MISC_1ST_DETAIL) {
1487                 best = md;
1488                 goto finished;
1489         }
1490
1491         /* find best mode based on display width and height */
1492         if (specs->max_x && specs->max_y) {
1493                 struct fb_var_screeninfo var;
1494
1495                 memset(&var, 0, sizeof(struct fb_var_screeninfo));
1496                 var.xres = (specs->max_x * 7200)/254;
1497                 var.yres = (specs->max_y * 7200)/254;
1498                 m = fb_find_best_mode(&var, head);
1499                 if (m) {
1500                         best = m;
1501                         goto finished;
1502                 }
1503         }
1504
1505         /* use first detailed mode */
1506         if (md) {
1507                 best = md;
1508                 goto finished;
1509         }
1510
1511         /* last resort, use the very first mode */
1512         best = m1;
1513 finished:
1514         return best;
1515 }
1516 EXPORT_SYMBOL(fb_find_best_display);
1517
1518 EXPORT_SYMBOL(fb_videomode_to_var);
1519 EXPORT_SYMBOL(fb_var_to_videomode);
1520 EXPORT_SYMBOL(fb_mode_is_equal);
1521 EXPORT_SYMBOL(fb_add_videomode);
1522 EXPORT_SYMBOL(fb_match_mode);
1523 EXPORT_SYMBOL(fb_find_best_mode);
1524 EXPORT_SYMBOL(fb_find_nearest_mode);
1525 EXPORT_SYMBOL(fb_videomode_to_modelist);
1526 EXPORT_SYMBOL(fb_find_mode);
1527 EXPORT_SYMBOL(fb_find_mode_cvt);