This source file includes following definitions.
- fb_try_mode
- fb_find_mode
- fb_var_to_videomode
- fb_videomode_to_var
- fb_mode_is_equal
- fb_find_best_mode
- fb_find_nearest_mode
- fb_match_mode
- fb_add_videomode
- fb_delete_videomode
- fb_destroy_modelist
- fb_videomode_to_modelist
- fb_find_best_display
1
2
3
4
5
6
7
8
9
10
11
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
33
34
35
36 static const struct fb_videomode modedb[] = {
37
38
39 { NULL, 70, 640, 400, 39721, 40, 24, 39, 9, 96, 2, 0,
40 FB_VMODE_NONINTERLACED },
41
42
43 { NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2, 0,
44 FB_VMODE_NONINTERLACED },
45
46
47 { NULL, 56, 800, 600, 27777, 128, 24, 22, 1, 72, 2, 0,
48 FB_VMODE_NONINTERLACED },
49
50
51 { NULL, 87, 1024, 768, 22271, 56, 24, 33, 8, 160, 8, 0,
52 FB_VMODE_INTERLACED },
53
54
55 { NULL, 85, 640, 400, 31746, 96, 32, 41, 1, 64, 3,
56 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
57
58
59 { NULL, 72, 640, 480, 31746, 144, 40, 30, 8, 40, 3, 0,
60 FB_VMODE_NONINTERLACED },
61
62
63 { NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3, 0,
64 FB_VMODE_NONINTERLACED },
65
66
67 { NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4,
68 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
69 FB_VMODE_NONINTERLACED },
70
71
72 { NULL, 85, 640, 480, 27777, 80, 56, 25, 1, 56, 3, 0,
73 FB_VMODE_NONINTERLACED },
74
75
76 { NULL, 89, 1152, 864, 15384, 96, 16, 110, 1, 216, 10, 0,
77 FB_VMODE_INTERLACED },
78
79 { NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
80 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
81 FB_VMODE_NONINTERLACED },
82
83
84 { NULL, 60, 1024, 768, 15384, 168, 8, 29, 3, 144, 6, 0,
85 FB_VMODE_NONINTERLACED },
86
87
88 { NULL, 100, 640, 480, 21834, 96, 32, 36, 8, 96, 6, 0,
89 FB_VMODE_NONINTERLACED },
90
91
92 { NULL, 60, 1152, 864, 11123, 208, 64, 16, 4, 256, 8, 0,
93 FB_VMODE_NONINTERLACED },
94
95
96 { NULL, 85, 800, 600, 16460, 160, 64, 36, 16, 64, 5, 0,
97 FB_VMODE_NONINTERLACED },
98
99
100 { NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6, 0,
101 FB_VMODE_NONINTERLACED },
102
103
104 { NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12, 0,
105 FB_VMODE_INTERLACED },
106
107
108 { NULL, 100, 800, 600, 14357, 160, 64, 30, 4, 64, 6, 0,
109 FB_VMODE_NONINTERLACED },
110
111
112 { NULL, 76, 1024, 768, 11764, 208, 8, 36, 16, 120, 3, 0,
113 FB_VMODE_NONINTERLACED },
114
115
116 { NULL, 70, 1152, 864, 10869, 106, 56, 20, 1, 160, 10, 0,
117 FB_VMODE_NONINTERLACED },
118
119
120 { NULL, 61, 1280, 1024, 9090, 200, 48, 26, 1, 184, 3, 0,
121 FB_VMODE_NONINTERLACED },
122
123
124 { NULL, 60, 1400, 1050, 9259, 136, 40, 13, 1, 112, 3, 0,
125 FB_VMODE_NONINTERLACED },
126
127
128 { NULL, 75, 1400, 1050, 7190, 120, 56, 23, 10, 112, 13,
129 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
130 FB_VMODE_NONINTERLACED },
131
132
133 { NULL, 60, 1400, 1050, 9259, 128, 40, 12, 0, 112, 3,
134 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
135 FB_VMODE_NONINTERLACED },
136
137
138 { NULL, 85, 1024, 768, 10111, 192, 32, 34, 14, 160, 6, 0,
139 FB_VMODE_NONINTERLACED },
140
141
142 { NULL, 78, 1152, 864, 9090, 228, 88, 32, 0, 84, 12, 0,
143 FB_VMODE_NONINTERLACED },
144
145
146 { NULL, 70, 1280, 1024, 7905, 224, 32, 28, 8, 160, 8, 0,
147 FB_VMODE_NONINTERLACED },
148
149
150 { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
151 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
152 FB_VMODE_NONINTERLACED },
153
154
155 { NULL, 84, 1152, 864, 7407, 184, 312, 32, 0, 128, 12, 0,
156 FB_VMODE_NONINTERLACED },
157
158
159 { NULL, 74, 1280, 1024, 7407, 256, 32, 34, 3, 144, 3, 0,
160 FB_VMODE_NONINTERLACED },
161
162
163 { NULL, 100, 1024, 768, 8658, 192, 32, 21, 3, 192, 10, 0,
164 FB_VMODE_NONINTERLACED },
165
166
167 { NULL, 76, 1280, 1024, 7407, 248, 32, 34, 3, 104, 3, 0,
168 FB_VMODE_NONINTERLACED },
169
170
171 { NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3, 0,
172 FB_VMODE_NONINTERLACED },
173
174
175 { NULL, 100, 1152, 864, 7264, 224, 32, 17, 2, 128, 19, 0,
176 FB_VMODE_NONINTERLACED },
177
178
179 { NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
180 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
181 FB_VMODE_NONINTERLACED },
182
183
184 { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
185 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
186 FB_VMODE_NONINTERLACED },
187
188
189 { NULL, 60, 1680, 1050, 6848, 280, 104, 30, 3, 176, 6,
190 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
191 FB_VMODE_NONINTERLACED },
192
193
194 { NULL, 85, 1600, 1200, 4545, 272, 16, 37, 4, 192, 3,
195 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
196 FB_VMODE_NONINTERLACED },
197
198
199 { NULL, 100, 1280, 1024, 5502, 256, 32, 26, 7, 128, 15, 0,
200 FB_VMODE_NONINTERLACED },
201
202
203 { NULL, 64, 1800, 1440, 4347, 304, 96, 46, 1, 192, 3,
204 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
205 FB_VMODE_NONINTERLACED },
206
207
208 { NULL, 70, 1800, 1440, 4000, 304, 96, 46, 1, 192, 3,
209 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
210 FB_VMODE_NONINTERLACED },
211
212
213 { NULL, 78, 512, 384, 49603, 48, 16, 16, 1, 64, 3, 0,
214 FB_VMODE_NONINTERLACED },
215
216
217 { NULL, 85, 512, 384, 45454, 48, 16, 16, 1, 64, 3, 0,
218 FB_VMODE_NONINTERLACED },
219
220
221 { NULL, 70, 320, 200, 79440, 16, 16, 20, 4, 48, 1, 0,
222 FB_VMODE_DOUBLE },
223
224
225 { NULL, 60, 320, 240, 79440, 16, 16, 16, 5, 48, 1, 0,
226 FB_VMODE_DOUBLE },
227
228
229 { NULL, 72, 320, 240, 63492, 16, 16, 16, 4, 48, 2, 0,
230 FB_VMODE_DOUBLE },
231
232
233 { NULL, 56, 400, 300, 55555, 64, 16, 10, 1, 32, 1, 0,
234 FB_VMODE_DOUBLE },
235
236
237 { NULL, 60, 400, 300, 50000, 48, 16, 11, 1, 64, 2, 0,
238 FB_VMODE_DOUBLE },
239
240
241 { NULL, 72, 400, 300, 40000, 32, 24, 11, 19, 64, 3, 0,
242 FB_VMODE_DOUBLE },
243
244
245 { NULL, 56, 480, 300, 46176, 80, 16, 10, 1, 40, 1, 0,
246 FB_VMODE_DOUBLE },
247
248
249 { NULL, 60, 480, 300, 41858, 56, 16, 11, 1, 80, 2, 0,
250 FB_VMODE_DOUBLE },
251
252
253 { NULL, 63, 480, 300, 40000, 56, 16, 11, 1, 80, 2, 0,
254 FB_VMODE_DOUBLE },
255
256
257 { NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3, 0,
258 FB_VMODE_DOUBLE },
259
260
261 { NULL, 60, 1920, 1200, 5177, 128, 336, 1, 38, 208, 3,
262 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
263 FB_VMODE_NONINTERLACED },
264
265
266 { NULL, 60, 1152, 768, 14047, 158, 26, 29, 3, 136, 6,
267 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
268 FB_VMODE_NONINTERLACED },
269
270
271 { NULL, 60, 1366, 768, 13806, 120, 10, 14, 3, 32, 5, 0,
272 FB_VMODE_NONINTERLACED },
273
274
275 { NULL, 60, 1280, 800, 12048, 200, 64, 24, 1, 136, 3, 0,
276 FB_VMODE_NONINTERLACED },
277
278
279 { NULL, 50, 720, 576, 74074, 64, 16, 39, 5, 64, 5, 0,
280 FB_VMODE_INTERLACED },
281
282
283 { NULL, 50, 800, 520, 58823, 144, 64, 72, 28, 80, 5, 0,
284 FB_VMODE_INTERLACED },
285
286
287 { NULL, 60, 864, 480, 27777, 1, 1, 1, 1, 0, 0,
288 0, FB_VMODE_NONINTERLACED },
289 };
290
291 #ifdef CONFIG_FB_MODE_HELPERS
292 const struct fb_videomode vesa_modes[] = {
293
294 { NULL, 85, 640, 350, 31746, 96, 32, 60, 32, 64, 3,
295 FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
296
297 { NULL, 85, 640, 400, 31746, 96, 32, 41, 01, 64, 3,
298 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
299
300 { NULL, 85, 721, 400, 28169, 108, 36, 42, 01, 72, 3,
301 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
302
303 { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2,
304 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
305
306 { NULL, 72, 640, 480, 31746, 128, 24, 29, 9, 40, 2,
307 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
308
309 { NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
310 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
311
312 { NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3,
313 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
314
315 { NULL, 56, 800, 600, 27777, 128, 24, 22, 01, 72, 2,
316 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
317 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
318
319 { NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4,
320 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
321 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
322
323 { NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
324 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
325 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
326
327 { NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3,
328 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
329 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
330
331 { NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3,
332 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
333 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
334
335 { NULL, 43, 1024, 768, 22271, 56, 8, 41, 0, 176, 8,
336 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
337 FB_VMODE_INTERLACED, FB_MODE_IS_VESA },
338
339 { NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6,
340 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
341
342 { NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6,
343 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
344
345 { NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
346 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
347 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
348
349 { NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
350 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
351 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
352
353 { NULL, 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3,
354 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
355 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
356
357 { NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
358 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
359 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
360
361 { NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
362 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
363 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
364
365 { NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
366 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
367 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
368
369 { NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
370 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
371 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
372
373 { NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
374 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
375 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
376
377 { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
378 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
379 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
380
381 { NULL, 65, 1600, 1200, 5698, 304, 64, 46, 1, 192, 3,
382 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
383 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
384
385 { NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3,
386 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
387 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
388
389 { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
390 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
391 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
392
393 { NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
394 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
395 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
396
397 { NULL, 60, 1792, 1344, 4882, 328, 128, 46, 1, 200, 3,
398 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
399
400 { NULL, 75, 1792, 1344, 3831, 352, 96, 69, 1, 216, 3,
401 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
402
403 { NULL, 60, 1856, 1392, 4580, 352, 96, 43, 1, 224, 3,
404 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
405
406 { NULL, 75, 1856, 1392, 3472, 352, 128, 104, 1, 224, 3,
407 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
408
409 { NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 200, 3,
410 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
411
412 { NULL, 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3,
413 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
414
415 { NULL, 60, 1920, 1200, 6493, 80, 48, 26, 3, 32, 6,
416 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
417
418 { NULL, 60, 1920, 1200, 5174, 336, 136, 36, 3, 200, 6,
419 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
420
421 { NULL, 75, 1920, 1200, 4077, 344, 136, 46, 3, 208, 6,
422 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
423
424 { NULL, 85, 1920, 1200, 3555, 352, 144, 53, 3, 208, 6,
425 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
426
427 { NULL, 60, 2560, 1600, 3724, 80, 48, 37, 3, 32, 6,
428 FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
429
430 { NULL, 60, 2560, 1600, 2869, 472, 192, 49, 3, 280, 6,
431 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
432
433 { NULL, 75, 2560, 1600, 2256, 488, 208, 63, 3, 280, 6,
434 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
435
436 { NULL, 85, 2560, 1600, 1979, 488, 208, 73, 3, 280, 6,
437 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
438
439 { NULL, 120, 2560, 1600, 1809, 80, 48, 85, 3, 32, 6,
440 FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
441 };
442 EXPORT_SYMBOL(vesa_modes);
443
444 const struct dmt_videomode dmt_modes[DMT_SIZE] = {
445 { 0x01, 0x0000, 0x000000, &vesa_modes[0] },
446 { 0x02, 0x3119, 0x000000, &vesa_modes[1] },
447 { 0x03, 0x0000, 0x000000, &vesa_modes[2] },
448 { 0x04, 0x3140, 0x000000, &vesa_modes[3] },
449 { 0x05, 0x314c, 0x000000, &vesa_modes[4] },
450 { 0x06, 0x314f, 0x000000, &vesa_modes[5] },
451 { 0x07, 0x3159, 0x000000, &vesa_modes[6] },
452 { 0x08, 0x0000, 0x000000, &vesa_modes[7] },
453 { 0x09, 0x4540, 0x000000, &vesa_modes[8] },
454 { 0x0a, 0x454c, 0x000000, &vesa_modes[9] },
455 { 0x0b, 0x454f, 0x000000, &vesa_modes[10] },
456 { 0x0c, 0x4559, 0x000000, &vesa_modes[11] },
457 { 0x0d, 0x0000, 0x000000, NULL },
458 { 0x0e, 0x0000, 0x000000, NULL },
459 { 0x0f, 0x0000, 0x000000, &vesa_modes[12] },
460 { 0x10, 0x6140, 0x000000, &vesa_modes[13] },
461 { 0x11, 0x614a, 0x000000, &vesa_modes[14] },
462 { 0x12, 0x614f, 0x000000, &vesa_modes[15] },
463 { 0x13, 0x6159, 0x000000, &vesa_modes[16] },
464 { 0x14, 0x0000, 0x000000, NULL },
465 { 0x15, 0x714f, 0x000000, &vesa_modes[17] },
466 { 0x16, 0x0000, 0x7f1c21, NULL },
467 { 0x17, 0x0000, 0x7f1c28, NULL },
468 { 0x18, 0x0000, 0x7f1c44, NULL },
469 { 0x19, 0x0000, 0x7f1c62, NULL },
470 { 0x1a, 0x0000, 0x000000, NULL },
471 { 0x1b, 0x0000, 0x8f1821, NULL },
472 { 0x1c, 0x8100, 0x8f1828, NULL },
473 { 0x1d, 0x810f, 0x8f1844, NULL },
474 { 0x1e, 0x8119, 0x8f1862, NULL },
475 { 0x1f, 0x0000, 0x000000, NULL },
476 { 0x20, 0x8140, 0x000000, &vesa_modes[18] },
477 { 0x21, 0x8159, 0x000000, &vesa_modes[19] },
478 { 0x22, 0x0000, 0x000000, NULL },
479 { 0x23, 0x8180, 0x000000, &vesa_modes[20] },
480 { 0x24, 0x818f, 0x000000, &vesa_modes[21] },
481 { 0x25, 0x8199, 0x000000, &vesa_modes[22] },
482 { 0x26, 0x0000, 0x000000, NULL },
483 { 0x27, 0x0000, 0x000000, NULL },
484 { 0x28, 0x0000, 0x000000, NULL },
485 { 0x29, 0x0000, 0x0c2021, NULL },
486 { 0x2a, 0x9040, 0x0c2028, NULL },
487 { 0x2b, 0x904f, 0x0c2044, NULL },
488 { 0x2c, 0x9059, 0x0c2062, NULL },
489 { 0x2d, 0x0000, 0x000000, NULL },
490 { 0x2e, 0x9500, 0xc11821, NULL },
491 { 0x2f, 0x9500, 0xc11828, NULL },
492 { 0x30, 0x950f, 0xc11844, NULL },
493 { 0x31, 0x9519, 0xc11868, NULL },
494 { 0x32, 0x0000, 0x000000, NULL },
495 { 0x33, 0xa940, 0x000000, &vesa_modes[23] },
496 { 0x34, 0xa945, 0x000000, &vesa_modes[24] },
497 { 0x35, 0xa94a, 0x000000, &vesa_modes[25] },
498 { 0x36, 0xa94f, 0x000000, &vesa_modes[26] },
499 { 0x37, 0xa959, 0x000000, &vesa_modes[27] },
500 { 0x38, 0x0000, 0x000000, NULL },
501 { 0x39, 0x0000, 0x0c2821, NULL },
502 { 0x3a, 0xb300, 0x0c2828, NULL },
503 { 0x3b, 0xb30f, 0x0c2844, NULL },
504 { 0x3c, 0xb319, 0x0c2868, NULL },
505 { 0x3d, 0x0000, 0x000000, NULL },
506 { 0x3e, 0xc140, 0x000000, &vesa_modes[28] },
507 { 0x3f, 0xc14f, 0x000000, &vesa_modes[29] },
508 { 0x40, 0x0000, 0x000000, NULL},
509 { 0x41, 0xc940, 0x000000, &vesa_modes[30] },
510 { 0x42, 0xc94f, 0x000000, &vesa_modes[31] },
511 { 0x43, 0x0000, 0x000000, NULL },
512 { 0x44, 0x0000, 0x572821, &vesa_modes[34] },
513 { 0x45, 0xd100, 0x572828, &vesa_modes[35] },
514 { 0x46, 0xd10f, 0x572844, &vesa_modes[36] },
515 { 0x47, 0xd119, 0x572862, &vesa_modes[37] },
516 { 0x48, 0x0000, 0x000000, NULL },
517 { 0x49, 0xd140, 0x000000, &vesa_modes[32] },
518 { 0x4a, 0xd14f, 0x000000, &vesa_modes[33] },
519 { 0x4b, 0x0000, 0x000000, NULL },
520 { 0x4c, 0x0000, 0x1f3821, &vesa_modes[38] },
521 { 0x4d, 0x0000, 0x1f3828, &vesa_modes[39] },
522 { 0x4e, 0x0000, 0x1f3844, &vesa_modes[40] },
523 { 0x4f, 0x0000, 0x1f3862, &vesa_modes[41] },
524 { 0x50, 0x0000, 0x000000, &vesa_modes[42] },
525 };
526 EXPORT_SYMBOL(dmt_modes);
527 #endif
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542 static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
543 const struct fb_videomode *mode, unsigned int bpp)
544 {
545 int err = 0;
546
547 DPRINTK("Trying mode %s %dx%d-%d@%d\n",
548 mode->name ? mode->name : "noname",
549 mode->xres, mode->yres, bpp, mode->refresh);
550 var->xres = mode->xres;
551 var->yres = mode->yres;
552 var->xres_virtual = mode->xres;
553 var->yres_virtual = mode->yres;
554 var->xoffset = 0;
555 var->yoffset = 0;
556 var->bits_per_pixel = bpp;
557 var->activate |= FB_ACTIVATE_TEST;
558 var->pixclock = mode->pixclock;
559 var->left_margin = mode->left_margin;
560 var->right_margin = mode->right_margin;
561 var->upper_margin = mode->upper_margin;
562 var->lower_margin = mode->lower_margin;
563 var->hsync_len = mode->hsync_len;
564 var->vsync_len = mode->vsync_len;
565 var->sync = mode->sync;
566 var->vmode = mode->vmode;
567 if (info->fbops->fb_check_var)
568 err = info->fbops->fb_check_var(var, info);
569 var->activate &= ~FB_ACTIVATE_TEST;
570 return err;
571 }
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617 int fb_find_mode(struct fb_var_screeninfo *var,
618 struct fb_info *info, const char *mode_option,
619 const struct fb_videomode *db, unsigned int dbsize,
620 const struct fb_videomode *default_mode,
621 unsigned int default_bpp)
622 {
623 int i;
624
625
626 if (!db) {
627 db = modedb;
628 dbsize = ARRAY_SIZE(modedb);
629 }
630
631 if (!default_mode)
632 default_mode = &db[0];
633
634 if (!default_bpp)
635 default_bpp = 8;
636
637
638 if (!mode_option)
639 mode_option = fb_mode_option;
640 if (mode_option) {
641 const char *name = mode_option;
642 unsigned int namelen = strlen(name);
643 int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
644 unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0;
645 int yres_specified = 0, cvt = 0, rb = 0;
646 int interlace_specified = 0, interlace = 0;
647 int margins = 0;
648 u32 best, diff, tdiff;
649
650 for (i = namelen-1; i >= 0; i--) {
651 switch (name[i]) {
652 case '@':
653 namelen = i;
654 if (!refresh_specified && !bpp_specified &&
655 !yres_specified) {
656 refresh = simple_strtol(&name[i+1], NULL,
657 10);
658 refresh_specified = 1;
659 if (cvt || rb)
660 cvt = 0;
661 } else
662 goto done;
663 break;
664 case '-':
665 namelen = i;
666 if (!bpp_specified && !yres_specified) {
667 bpp = simple_strtol(&name[i+1], NULL,
668 10);
669 bpp_specified = 1;
670 if (cvt || rb)
671 cvt = 0;
672 } else
673 goto done;
674 break;
675 case 'x':
676 if (!yres_specified) {
677 yres = simple_strtol(&name[i+1], NULL,
678 10);
679 yres_specified = 1;
680 } else
681 goto done;
682 break;
683 case '0' ... '9':
684 break;
685 case 'M':
686 if (!yres_specified)
687 cvt = 1;
688 break;
689 case 'R':
690 if (!cvt)
691 rb = 1;
692 break;
693 case 'm':
694 if (!cvt)
695 margins = 1;
696 break;
697 case 'p':
698 if (!cvt) {
699 interlace = 0;
700 interlace_specified = 1;
701 }
702 break;
703 case 'i':
704 if (!cvt) {
705 interlace = 1;
706 interlace_specified = 1;
707 }
708 break;
709 default:
710 goto done;
711 }
712 }
713 if (i < 0 && yres_specified) {
714 xres = simple_strtol(name, NULL, 10);
715 res_specified = 1;
716 }
717 done:
718 if (cvt) {
719 struct fb_videomode cvt_mode;
720 int ret;
721
722 DPRINTK("CVT mode %dx%d@%dHz%s%s%s\n", xres, yres,
723 (refresh) ? refresh : 60,
724 (rb) ? " reduced blanking" : "",
725 (margins) ? " with margins" : "",
726 (interlace) ? " interlaced" : "");
727
728 memset(&cvt_mode, 0, sizeof(cvt_mode));
729 cvt_mode.xres = xres;
730 cvt_mode.yres = yres;
731 cvt_mode.refresh = (refresh) ? refresh : 60;
732
733 if (interlace)
734 cvt_mode.vmode |= FB_VMODE_INTERLACED;
735 else
736 cvt_mode.vmode &= ~FB_VMODE_INTERLACED;
737
738 ret = fb_find_mode_cvt(&cvt_mode, margins, rb);
739
740 if (!ret && !fb_try_mode(var, info, &cvt_mode, bpp)) {
741 DPRINTK("modedb CVT: CVT mode ok\n");
742 return 1;
743 }
744
745 DPRINTK("CVT mode invalid, getting mode from database\n");
746 }
747
748 DPRINTK("Trying specified video mode%s %ix%i\n",
749 refresh_specified ? "" : " (ignoring refresh rate)",
750 xres, yres);
751
752 if (!refresh_specified) {
753
754
755
756
757
758
759
760 if (db != modedb &&
761 info->monspecs.vfmin && info->monspecs.vfmax &&
762 info->monspecs.hfmin && info->monspecs.hfmax &&
763 info->monspecs.dclkmax) {
764 refresh = 1000;
765 } else {
766 refresh = 60;
767 }
768 }
769
770 diff = -1;
771 best = -1;
772 for (i = 0; i < dbsize; i++) {
773 if ((name_matches(db[i], name, namelen) ||
774 (res_specified && res_matches(db[i], xres, yres))) &&
775 !fb_try_mode(var, info, &db[i], bpp)) {
776 const int db_interlace = (db[i].vmode &
777 FB_VMODE_INTERLACED ? 1 : 0);
778 int score = abs(db[i].refresh - refresh);
779
780 if (interlace_specified)
781 score += abs(db_interlace - interlace);
782
783 if (!interlace_specified ||
784 db_interlace == interlace)
785 if (refresh_specified &&
786 db[i].refresh == refresh)
787 return 1;
788
789 if (score < diff) {
790 diff = score;
791 best = i;
792 }
793 }
794 }
795 if (best != -1) {
796 fb_try_mode(var, info, &db[best], bpp);
797 return (refresh_specified) ? 2 : 1;
798 }
799
800 diff = 2 * (xres + yres);
801 best = -1;
802 DPRINTK("Trying best-fit modes\n");
803 for (i = 0; i < dbsize; i++) {
804 DPRINTK("Trying %ix%i\n", db[i].xres, db[i].yres);
805 if (!fb_try_mode(var, info, &db[i], bpp)) {
806 tdiff = abs(db[i].xres - xres) +
807 abs(db[i].yres - yres);
808
809
810
811
812
813 if (xres > db[i].xres || yres > db[i].yres)
814 tdiff += xres + yres;
815
816 if (diff > tdiff) {
817 diff = tdiff;
818 best = i;
819 }
820 }
821 }
822 if (best != -1) {
823 fb_try_mode(var, info, &db[best], bpp);
824 return 5;
825 }
826 }
827
828 DPRINTK("Trying default video mode\n");
829 if (!fb_try_mode(var, info, default_mode, default_bpp))
830 return 3;
831
832 DPRINTK("Trying all modes\n");
833 for (i = 0; i < dbsize; i++)
834 if (!fb_try_mode(var, info, &db[i], default_bpp))
835 return 4;
836
837 DPRINTK("No valid mode found\n");
838 return 0;
839 }
840
841
842
843
844
845
846 void fb_var_to_videomode(struct fb_videomode *mode,
847 const struct fb_var_screeninfo *var)
848 {
849 u32 pixclock, hfreq, htotal, vtotal;
850
851 mode->name = NULL;
852 mode->xres = var->xres;
853 mode->yres = var->yres;
854 mode->pixclock = var->pixclock;
855 mode->hsync_len = var->hsync_len;
856 mode->vsync_len = var->vsync_len;
857 mode->left_margin = var->left_margin;
858 mode->right_margin = var->right_margin;
859 mode->upper_margin = var->upper_margin;
860 mode->lower_margin = var->lower_margin;
861 mode->sync = var->sync;
862 mode->vmode = var->vmode & FB_VMODE_MASK;
863 mode->flag = FB_MODE_IS_FROM_VAR;
864 mode->refresh = 0;
865
866 if (!var->pixclock)
867 return;
868
869 pixclock = PICOS2KHZ(var->pixclock) * 1000;
870
871 htotal = var->xres + var->right_margin + var->hsync_len +
872 var->left_margin;
873 vtotal = var->yres + var->lower_margin + var->vsync_len +
874 var->upper_margin;
875
876 if (var->vmode & FB_VMODE_INTERLACED)
877 vtotal /= 2;
878 if (var->vmode & FB_VMODE_DOUBLE)
879 vtotal *= 2;
880
881 if (!htotal || !vtotal)
882 return;
883
884 hfreq = pixclock/htotal;
885 mode->refresh = hfreq/vtotal;
886 }
887
888
889
890
891
892
893 void fb_videomode_to_var(struct fb_var_screeninfo *var,
894 const struct fb_videomode *mode)
895 {
896 var->xres = mode->xres;
897 var->yres = mode->yres;
898 var->xres_virtual = mode->xres;
899 var->yres_virtual = mode->yres;
900 var->xoffset = 0;
901 var->yoffset = 0;
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 & FB_VMODE_MASK;
911 }
912
913
914
915
916
917
918
919
920
921 int fb_mode_is_equal(const struct fb_videomode *mode1,
922 const struct fb_videomode *mode2)
923 {
924 return (mode1->xres == mode2->xres &&
925 mode1->yres == mode2->yres &&
926 mode1->pixclock == mode2->pixclock &&
927 mode1->hsync_len == mode2->hsync_len &&
928 mode1->vsync_len == mode2->vsync_len &&
929 mode1->left_margin == mode2->left_margin &&
930 mode1->right_margin == mode2->right_margin &&
931 mode1->upper_margin == mode2->upper_margin &&
932 mode1->lower_margin == mode2->lower_margin &&
933 mode1->sync == mode2->sync &&
934 mode1->vmode == mode2->vmode);
935 }
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954 const struct fb_videomode *fb_find_best_mode(const struct fb_var_screeninfo *var,
955 struct list_head *head)
956 {
957 struct list_head *pos;
958 struct fb_modelist *modelist;
959 struct fb_videomode *mode, *best = NULL;
960 u32 diff = -1;
961
962 list_for_each(pos, head) {
963 u32 d;
964
965 modelist = list_entry(pos, struct fb_modelist, list);
966 mode = &modelist->mode;
967
968 if (mode->xres >= var->xres && mode->yres >= var->yres) {
969 d = (mode->xres - var->xres) +
970 (mode->yres - var->yres);
971 if (diff > d) {
972 diff = d;
973 best = mode;
974 } else if (diff == d && best &&
975 mode->refresh > best->refresh)
976 best = mode;
977 }
978 }
979 return best;
980 }
981
982
983
984
985
986
987
988
989
990
991
992 const struct fb_videomode *fb_find_nearest_mode(const struct fb_videomode *mode,
993 struct list_head *head)
994 {
995 struct list_head *pos;
996 struct fb_modelist *modelist;
997 struct fb_videomode *cmode, *best = NULL;
998 u32 diff = -1, diff_refresh = -1;
999
1000 list_for_each(pos, head) {
1001 u32 d;
1002
1003 modelist = list_entry(pos, struct fb_modelist, list);
1004 cmode = &modelist->mode;
1005
1006 d = abs(cmode->xres - mode->xres) +
1007 abs(cmode->yres - mode->yres);
1008 if (diff > d) {
1009 diff = d;
1010 diff_refresh = abs(cmode->refresh - mode->refresh);
1011 best = cmode;
1012 } else if (diff == d) {
1013 d = abs(cmode->refresh - mode->refresh);
1014 if (diff_refresh > d) {
1015 diff_refresh = d;
1016 best = cmode;
1017 }
1018 }
1019 }
1020
1021 return best;
1022 }
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032 const struct fb_videomode *fb_match_mode(const struct fb_var_screeninfo *var,
1033 struct list_head *head)
1034 {
1035 struct list_head *pos;
1036 struct fb_modelist *modelist;
1037 struct fb_videomode *m, mode;
1038
1039 fb_var_to_videomode(&mode, var);
1040 list_for_each(pos, head) {
1041 modelist = list_entry(pos, struct fb_modelist, list);
1042 m = &modelist->mode;
1043 if (fb_mode_is_equal(m, &mode))
1044 return m;
1045 }
1046 return NULL;
1047 }
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057 int fb_add_videomode(const struct fb_videomode *mode, struct list_head *head)
1058 {
1059 struct list_head *pos;
1060 struct fb_modelist *modelist;
1061 struct fb_videomode *m;
1062 int found = 0;
1063
1064 list_for_each(pos, head) {
1065 modelist = list_entry(pos, struct fb_modelist, list);
1066 m = &modelist->mode;
1067 if (fb_mode_is_equal(m, mode)) {
1068 found = 1;
1069 break;
1070 }
1071 }
1072 if (!found) {
1073 modelist = kmalloc(sizeof(struct fb_modelist),
1074 GFP_KERNEL);
1075
1076 if (!modelist)
1077 return -ENOMEM;
1078 modelist->mode = *mode;
1079 list_add(&modelist->list, head);
1080 }
1081 return 0;
1082 }
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092 void fb_delete_videomode(const struct fb_videomode *mode,
1093 struct list_head *head)
1094 {
1095 struct list_head *pos, *n;
1096 struct fb_modelist *modelist;
1097 struct fb_videomode *m;
1098
1099 list_for_each_safe(pos, n, head) {
1100 modelist = list_entry(pos, struct fb_modelist, list);
1101 m = &modelist->mode;
1102 if (fb_mode_is_equal(m, mode)) {
1103 list_del(pos);
1104 kfree(pos);
1105 }
1106 }
1107 }
1108
1109
1110
1111
1112
1113 void fb_destroy_modelist(struct list_head *head)
1114 {
1115 struct list_head *pos, *n;
1116
1117 list_for_each_safe(pos, n, head) {
1118 list_del(pos);
1119 kfree(pos);
1120 }
1121 }
1122 EXPORT_SYMBOL_GPL(fb_destroy_modelist);
1123
1124
1125
1126
1127
1128
1129
1130 void fb_videomode_to_modelist(const struct fb_videomode *modedb, int num,
1131 struct list_head *head)
1132 {
1133 int i;
1134
1135 INIT_LIST_HEAD(head);
1136
1137 for (i = 0; i < num; i++) {
1138 if (fb_add_videomode(&modedb[i], head))
1139 return;
1140 }
1141 }
1142
1143 const struct fb_videomode *fb_find_best_display(const struct fb_monspecs *specs,
1144 struct list_head *head)
1145 {
1146 struct list_head *pos;
1147 struct fb_modelist *modelist;
1148 const struct fb_videomode *m, *m1 = NULL, *md = NULL, *best = NULL;
1149 int first = 0;
1150
1151 if (!head->prev || !head->next || list_empty(head))
1152 goto finished;
1153
1154
1155 list_for_each(pos, head) {
1156 modelist = list_entry(pos, struct fb_modelist, list);
1157 m = &modelist->mode;
1158
1159 if (!first) {
1160 m1 = m;
1161 first = 1;
1162 }
1163
1164 if (m->flag & FB_MODE_IS_FIRST) {
1165 md = m;
1166 break;
1167 }
1168 }
1169
1170
1171 if (specs->misc & FB_MISC_1ST_DETAIL) {
1172 best = md;
1173 goto finished;
1174 }
1175
1176
1177 if (specs->max_x && specs->max_y) {
1178 struct fb_var_screeninfo var;
1179
1180 memset(&var, 0, sizeof(struct fb_var_screeninfo));
1181 var.xres = (specs->max_x * 7200)/254;
1182 var.yres = (specs->max_y * 7200)/254;
1183 m = fb_find_best_mode(&var, head);
1184 if (m) {
1185 best = m;
1186 goto finished;
1187 }
1188 }
1189
1190
1191 if (md) {
1192 best = md;
1193 goto finished;
1194 }
1195
1196
1197 best = m1;
1198 finished:
1199 return best;
1200 }
1201 EXPORT_SYMBOL(fb_find_best_display);
1202
1203 EXPORT_SYMBOL(fb_videomode_to_var);
1204 EXPORT_SYMBOL(fb_var_to_videomode);
1205 EXPORT_SYMBOL(fb_mode_is_equal);
1206 EXPORT_SYMBOL(fb_add_videomode);
1207 EXPORT_SYMBOL(fb_match_mode);
1208 EXPORT_SYMBOL(fb_find_best_mode);
1209 EXPORT_SYMBOL(fb_find_nearest_mode);
1210 EXPORT_SYMBOL(fb_videomode_to_modelist);
1211 EXPORT_SYMBOL(fb_find_mode);
1212 EXPORT_SYMBOL(fb_find_mode_cvt);