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
672int fb_find_mode(struct fb_var_screeninfo *var,
673 struct fb_info *info, const char *mode_option,
674 const struct fb_videomode *db, unsigned int dbsize,
675 const struct fb_videomode *default_mode,
676 unsigned int default_bpp)
677{
678 int i;
679
680
681 if (!db) {
682 db = modedb;
683 dbsize = ARRAY_SIZE(modedb);
684 }
685
686 if (!default_mode)
687 default_mode = &db[0];
688
689 if (!default_bpp)
690 default_bpp = 8;
691
692
693 if (!mode_option)
694 mode_option = fb_mode_option;
695 if (mode_option) {
696 const char *name = mode_option;
697 unsigned int namelen = strlen(name);
698 int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
699 unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0;
700 int yres_specified = 0, cvt = 0, rb = 0, interlace = 0;
701 int margins = 0;
702 u32 best, diff, tdiff;
703
704 for (i = namelen-1; i >= 0; i--) {
705 switch (name[i]) {
706 case '@':
707 namelen = i;
708 if (!refresh_specified && !bpp_specified &&
709 !yres_specified) {
710 refresh = simple_strtol(&name[i+1], NULL,
711 10);
712 refresh_specified = 1;
713 if (cvt || rb)
714 cvt = 0;
715 } else
716 goto done;
717 break;
718 case '-':
719 namelen = i;
720 if (!bpp_specified && !yres_specified) {
721 bpp = simple_strtol(&name[i+1], NULL,
722 10);
723 bpp_specified = 1;
724 if (cvt || rb)
725 cvt = 0;
726 } else
727 goto done;
728 break;
729 case 'x':
730 if (!yres_specified) {
731 yres = simple_strtol(&name[i+1], NULL,
732 10);
733 yres_specified = 1;
734 } else
735 goto done;
736 break;
737 case '0' ... '9':
738 break;
739 case 'M':
740 if (!yres_specified)
741 cvt = 1;
742 break;
743 case 'R':
744 if (!cvt)
745 rb = 1;
746 break;
747 case 'm':
748 if (!cvt)
749 margins = 1;
750 break;
751 case 'i':
752 if (!cvt)
753 interlace = 1;
754 break;
755 default:
756 goto done;
757 }
758 }
759 if (i < 0 && yres_specified) {
760 xres = simple_strtol(name, NULL, 10);
761 res_specified = 1;
762 }
763done:
764 if (cvt) {
765 struct fb_videomode cvt_mode;
766 int ret;
767
768 DPRINTK("CVT mode %dx%d@%dHz%s%s%s\n", xres, yres,
769 (refresh) ? refresh : 60,
770 (rb) ? " reduced blanking" : "",
771 (margins) ? " with margins" : "",
772 (interlace) ? " interlaced" : "");
773
774 memset(&cvt_mode, 0, sizeof(cvt_mode));
775 cvt_mode.xres = xres;
776 cvt_mode.yres = yres;
777 cvt_mode.refresh = (refresh) ? refresh : 60;
778
779 if (interlace)
780 cvt_mode.vmode |= FB_VMODE_INTERLACED;
781 else
782 cvt_mode.vmode &= ~FB_VMODE_INTERLACED;
783
784 ret = fb_find_mode_cvt(&cvt_mode, margins, rb);
785
786 if (!ret && !fb_try_mode(var, info, &cvt_mode, bpp)) {
787 DPRINTK("modedb CVT: CVT mode ok\n");
788 return 1;
789 }
790
791 DPRINTK("CVT mode invalid, getting mode from database\n");
792 }
793
794 DPRINTK("Trying specified video mode%s %ix%i\n",
795 refresh_specified ? "" : " (ignoring refresh rate)",
796 xres, yres);
797
798 if (!refresh_specified) {
799
800
801
802
803
804
805
806 if (db != modedb &&
807 info->monspecs.vfmin && info->monspecs.vfmax &&
808 info->monspecs.hfmin && info->monspecs.hfmax &&
809 info->monspecs.dclkmax) {
810 refresh = 1000;
811 } else {
812 refresh = 60;
813 }
814 }
815
816 diff = -1;
817 best = -1;
818 for (i = 0; i < dbsize; i++) {
819 if ((name_matches(db[i], name, namelen) ||
820 (res_specified && res_matches(db[i], xres, yres))) &&
821 !fb_try_mode(var, info, &db[i], bpp)) {
822 if (refresh_specified && db[i].refresh == refresh)
823 return 1;
824
825 if (abs(db[i].refresh - refresh) < diff) {
826 diff = abs(db[i].refresh - refresh);
827 best = i;
828 }
829 }
830 }
831 if (best != -1) {
832 fb_try_mode(var, info, &db[best], bpp);
833 return (refresh_specified) ? 2 : 1;
834 }
835
836 diff = 2 * (xres + yres);
837 best = -1;
838 DPRINTK("Trying best-fit modes\n");
839 for (i = 0; i < dbsize; i++) {
840 DPRINTK("Trying %ix%i\n", db[i].xres, db[i].yres);
841 if (!fb_try_mode(var, info, &db[i], bpp)) {
842 tdiff = abs(db[i].xres - xres) +
843 abs(db[i].yres - yres);
844
845
846
847
848
849 if (xres > db[i].xres || yres > db[i].yres)
850 tdiff += xres + yres;
851
852 if (diff > tdiff) {
853 diff = tdiff;
854 best = i;
855 }
856 }
857 }
858 if (best != -1) {
859 fb_try_mode(var, info, &db[best], bpp);
860 return 5;
861 }
862 }
863
864 DPRINTK("Trying default video mode\n");
865 if (!fb_try_mode(var, info, default_mode, default_bpp))
866 return 3;
867
868 DPRINTK("Trying all modes\n");
869 for (i = 0; i < dbsize; i++)
870 if (!fb_try_mode(var, info, &db[i], default_bpp))
871 return 4;
872
873 DPRINTK("No valid mode found\n");
874 return 0;
875}
876
877
878
879
880
881
882void fb_var_to_videomode(struct fb_videomode *mode,
883 const struct fb_var_screeninfo *var)
884{
885 u32 pixclock, hfreq, htotal, vtotal;
886
887 mode->name = NULL;
888 mode->xres = var->xres;
889 mode->yres = var->yres;
890 mode->pixclock = var->pixclock;
891 mode->hsync_len = var->hsync_len;
892 mode->vsync_len = var->vsync_len;
893 mode->left_margin = var->left_margin;
894 mode->right_margin = var->right_margin;
895 mode->upper_margin = var->upper_margin;
896 mode->lower_margin = var->lower_margin;
897 mode->sync = var->sync;
898 mode->vmode = var->vmode & FB_VMODE_MASK;
899 mode->flag = FB_MODE_IS_FROM_VAR;
900 mode->refresh = 0;
901
902 if (!var->pixclock)
903 return;
904
905 pixclock = PICOS2KHZ(var->pixclock) * 1000;
906
907 htotal = var->xres + var->right_margin + var->hsync_len +
908 var->left_margin;
909 vtotal = var->yres + var->lower_margin + var->vsync_len +
910 var->upper_margin;
911
912 if (var->vmode & FB_VMODE_INTERLACED)
913 vtotal /= 2;
914 if (var->vmode & FB_VMODE_DOUBLE)
915 vtotal *= 2;
916
917 hfreq = pixclock/htotal;
918 mode->refresh = hfreq/vtotal;
919}
920
921
922
923
924
925
926void fb_videomode_to_var(struct fb_var_screeninfo *var,
927 const struct fb_videomode *mode)
928{
929 var->xres = mode->xres;
930 var->yres = mode->yres;
931 var->xres_virtual = mode->xres;
932 var->yres_virtual = mode->yres;
933 var->xoffset = 0;
934 var->yoffset = 0;
935 var->pixclock = mode->pixclock;
936 var->left_margin = mode->left_margin;
937 var->right_margin = mode->right_margin;
938 var->upper_margin = mode->upper_margin;
939 var->lower_margin = mode->lower_margin;
940 var->hsync_len = mode->hsync_len;
941 var->vsync_len = mode->vsync_len;
942 var->sync = mode->sync;
943 var->vmode = mode->vmode & FB_VMODE_MASK;
944}
945
946
947
948
949
950
951
952
953
954int fb_mode_is_equal(const struct fb_videomode *mode1,
955 const struct fb_videomode *mode2)
956{
957 return (mode1->xres == mode2->xres &&
958 mode1->yres == mode2->yres &&
959 mode1->pixclock == mode2->pixclock &&
960 mode1->hsync_len == mode2->hsync_len &&
961 mode1->vsync_len == mode2->vsync_len &&
962 mode1->left_margin == mode2->left_margin &&
963 mode1->right_margin == mode2->right_margin &&
964 mode1->upper_margin == mode2->upper_margin &&
965 mode1->lower_margin == mode2->lower_margin &&
966 mode1->sync == mode2->sync &&
967 mode1->vmode == mode2->vmode);
968}
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987const struct fb_videomode *fb_find_best_mode(const struct fb_var_screeninfo *var,
988 struct list_head *head)
989{
990 struct list_head *pos;
991 struct fb_modelist *modelist;
992 struct fb_videomode *mode, *best = NULL;
993 u32 diff = -1;
994
995 list_for_each(pos, head) {
996 u32 d;
997
998 modelist = list_entry(pos, struct fb_modelist, list);
999 mode = &modelist->mode;
1000
1001 if (mode->xres >= var->xres && mode->yres >= var->yres) {
1002 d = (mode->xres - var->xres) +
1003 (mode->yres - var->yres);
1004 if (diff > d) {
1005 diff = d;
1006 best = mode;
1007 } else if (diff == d && best &&
1008 mode->refresh > best->refresh)
1009 best = mode;
1010 }
1011 }
1012 return best;
1013}
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025const struct fb_videomode *fb_find_nearest_mode(const struct fb_videomode *mode,
1026 struct list_head *head)
1027{
1028 struct list_head *pos;
1029 struct fb_modelist *modelist;
1030 struct fb_videomode *cmode, *best = NULL;
1031 u32 diff = -1, diff_refresh = -1;
1032
1033 list_for_each(pos, head) {
1034 u32 d;
1035
1036 modelist = list_entry(pos, struct fb_modelist, list);
1037 cmode = &modelist->mode;
1038
1039 d = abs(cmode->xres - mode->xres) +
1040 abs(cmode->yres - mode->yres);
1041 if (diff > d) {
1042 diff = d;
1043 diff_refresh = abs(cmode->refresh - mode->refresh);
1044 best = cmode;
1045 } else if (diff == d) {
1046 d = abs(cmode->refresh - mode->refresh);
1047 if (diff_refresh > d) {
1048 diff_refresh = d;
1049 best = cmode;
1050 }
1051 }
1052 }
1053
1054 return best;
1055}
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065const struct fb_videomode *fb_match_mode(const struct fb_var_screeninfo *var,
1066 struct list_head *head)
1067{
1068 struct list_head *pos;
1069 struct fb_modelist *modelist;
1070 struct fb_videomode *m, mode;
1071
1072 fb_var_to_videomode(&mode, var);
1073 list_for_each(pos, head) {
1074 modelist = list_entry(pos, struct fb_modelist, list);
1075 m = &modelist->mode;
1076 if (fb_mode_is_equal(m, &mode))
1077 return m;
1078 }
1079 return NULL;
1080}
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090int fb_add_videomode(const struct fb_videomode *mode, struct list_head *head)
1091{
1092 struct list_head *pos;
1093 struct fb_modelist *modelist;
1094 struct fb_videomode *m;
1095 int found = 0;
1096
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 found = 1;
1102 break;
1103 }
1104 }
1105 if (!found) {
1106 modelist = kmalloc(sizeof(struct fb_modelist),
1107 GFP_KERNEL);
1108
1109 if (!modelist)
1110 return -ENOMEM;
1111 modelist->mode = *mode;
1112 list_add(&modelist->list, head);
1113 }
1114 return 0;
1115}
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125void fb_delete_videomode(const struct fb_videomode *mode,
1126 struct list_head *head)
1127{
1128 struct list_head *pos, *n;
1129 struct fb_modelist *modelist;
1130 struct fb_videomode *m;
1131
1132 list_for_each_safe(pos, n, head) {
1133 modelist = list_entry(pos, struct fb_modelist, list);
1134 m = &modelist->mode;
1135 if (fb_mode_is_equal(m, mode)) {
1136 list_del(pos);
1137 kfree(pos);
1138 }
1139 }
1140}
1141
1142
1143
1144
1145
1146void fb_destroy_modelist(struct list_head *head)
1147{
1148 struct list_head *pos, *n;
1149
1150 list_for_each_safe(pos, n, head) {
1151 list_del(pos);
1152 kfree(pos);
1153 }
1154}
1155EXPORT_SYMBOL_GPL(fb_destroy_modelist);
1156
1157
1158
1159
1160
1161
1162
1163void fb_videomode_to_modelist(const struct fb_videomode *modedb, int num,
1164 struct list_head *head)
1165{
1166 int i;
1167
1168 INIT_LIST_HEAD(head);
1169
1170 for (i = 0; i < num; i++) {
1171 if (fb_add_videomode(&modedb[i], head))
1172 return;
1173 }
1174}
1175
1176const struct fb_videomode *fb_find_best_display(const struct fb_monspecs *specs,
1177 struct list_head *head)
1178{
1179 struct list_head *pos;
1180 struct fb_modelist *modelist;
1181 const struct fb_videomode *m, *m1 = NULL, *md = NULL, *best = NULL;
1182 int first = 0;
1183
1184 if (!head->prev || !head->next || list_empty(head))
1185 goto finished;
1186
1187
1188 list_for_each(pos, head) {
1189 modelist = list_entry(pos, struct fb_modelist, list);
1190 m = &modelist->mode;
1191
1192 if (!first) {
1193 m1 = m;
1194 first = 1;
1195 }
1196
1197 if (m->flag & FB_MODE_IS_FIRST) {
1198 md = m;
1199 break;
1200 }
1201 }
1202
1203
1204 if (specs->misc & FB_MISC_1ST_DETAIL) {
1205 best = md;
1206 goto finished;
1207 }
1208
1209
1210 if (specs->max_x && specs->max_y) {
1211 struct fb_var_screeninfo var;
1212
1213 memset(&var, 0, sizeof(struct fb_var_screeninfo));
1214 var.xres = (specs->max_x * 7200)/254;
1215 var.yres = (specs->max_y * 7200)/254;
1216 m = fb_find_best_mode(&var, head);
1217 if (m) {
1218 best = m;
1219 goto finished;
1220 }
1221 }
1222
1223
1224 if (md) {
1225 best = md;
1226 goto finished;
1227 }
1228
1229
1230 best = m1;
1231finished:
1232 return best;
1233}
1234EXPORT_SYMBOL(fb_find_best_display);
1235
1236EXPORT_SYMBOL(fb_videomode_to_var);
1237EXPORT_SYMBOL(fb_var_to_videomode);
1238EXPORT_SYMBOL(fb_mode_is_equal);
1239EXPORT_SYMBOL(fb_add_videomode);
1240EXPORT_SYMBOL(fb_match_mode);
1241EXPORT_SYMBOL(fb_find_best_mode);
1242EXPORT_SYMBOL(fb_find_nearest_mode);
1243EXPORT_SYMBOL(fb_videomode_to_modelist);
1244EXPORT_SYMBOL(fb_find_mode);
1245EXPORT_SYMBOL(fb_find_mode_cvt);
1246