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