0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/module.h>
0015 #include <linux/slab.h>
0016 #include <linux/fb.h>
0017 #include <linux/kernel.h>
0018
0019 #undef DEBUG
0020
0021 #define name_matches(v, s, l) \
0022 ((v).name && !strncmp((s), (v).name, (l)) && strlen((v).name) == (l))
0023 #define res_matches(v, x, y) \
0024 ((v).xres == (x) && (v).yres == (y))
0025
0026 #ifdef DEBUG
0027 #define DPRINTK(fmt, args...) printk("modedb %s: " fmt, __func__ , ## args)
0028 #else
0029 #define DPRINTK(fmt, args...)
0030 #endif
0031
0032
0033
0034
0035
0036 static const struct fb_videomode modedb[] = {
0037
0038
0039 { NULL, 70, 640, 400, 39721, 40, 24, 39, 9, 96, 2, 0,
0040 FB_VMODE_NONINTERLACED },
0041
0042
0043 { NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2, 0,
0044 FB_VMODE_NONINTERLACED },
0045
0046
0047 { NULL, 56, 800, 600, 27777, 128, 24, 22, 1, 72, 2, 0,
0048 FB_VMODE_NONINTERLACED },
0049
0050
0051 { NULL, 87, 1024, 768, 22271, 56, 24, 33, 8, 160, 8, 0,
0052 FB_VMODE_INTERLACED },
0053
0054
0055 { NULL, 85, 640, 400, 31746, 96, 32, 41, 1, 64, 3,
0056 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
0057
0058
0059 { NULL, 72, 640, 480, 31746, 144, 40, 30, 8, 40, 3, 0,
0060 FB_VMODE_NONINTERLACED },
0061
0062
0063 { NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3, 0,
0064 FB_VMODE_NONINTERLACED },
0065
0066
0067 { NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4,
0068 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0069 FB_VMODE_NONINTERLACED },
0070
0071
0072 { NULL, 85, 640, 480, 27777, 80, 56, 25, 1, 56, 3, 0,
0073 FB_VMODE_NONINTERLACED },
0074
0075
0076 { NULL, 89, 1152, 864, 15384, 96, 16, 110, 1, 216, 10, 0,
0077 FB_VMODE_INTERLACED },
0078
0079 { NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
0080 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0081 FB_VMODE_NONINTERLACED },
0082
0083
0084 { NULL, 60, 1024, 768, 15384, 168, 8, 29, 3, 144, 6, 0,
0085 FB_VMODE_NONINTERLACED },
0086
0087
0088 { NULL, 100, 640, 480, 21834, 96, 32, 36, 8, 96, 6, 0,
0089 FB_VMODE_NONINTERLACED },
0090
0091
0092 { NULL, 60, 1152, 864, 11123, 208, 64, 16, 4, 256, 8, 0,
0093 FB_VMODE_NONINTERLACED },
0094
0095
0096 { NULL, 85, 800, 600, 16460, 160, 64, 36, 16, 64, 5, 0,
0097 FB_VMODE_NONINTERLACED },
0098
0099
0100 { NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6, 0,
0101 FB_VMODE_NONINTERLACED },
0102
0103
0104 { NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12, 0,
0105 FB_VMODE_INTERLACED },
0106
0107
0108 { NULL, 100, 800, 600, 14357, 160, 64, 30, 4, 64, 6, 0,
0109 FB_VMODE_NONINTERLACED },
0110
0111
0112 { NULL, 76, 1024, 768, 11764, 208, 8, 36, 16, 120, 3, 0,
0113 FB_VMODE_NONINTERLACED },
0114
0115
0116 { NULL, 70, 1152, 864, 10869, 106, 56, 20, 1, 160, 10, 0,
0117 FB_VMODE_NONINTERLACED },
0118
0119
0120 { NULL, 61, 1280, 1024, 9090, 200, 48, 26, 1, 184, 3, 0,
0121 FB_VMODE_NONINTERLACED },
0122
0123
0124 { NULL, 60, 1400, 1050, 9259, 136, 40, 13, 1, 112, 3, 0,
0125 FB_VMODE_NONINTERLACED },
0126
0127
0128 { NULL, 75, 1400, 1050, 7190, 120, 56, 23, 10, 112, 13,
0129 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0130 FB_VMODE_NONINTERLACED },
0131
0132
0133 { NULL, 60, 1400, 1050, 9259, 128, 40, 12, 0, 112, 3,
0134 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0135 FB_VMODE_NONINTERLACED },
0136
0137
0138 { NULL, 85, 1024, 768, 10111, 192, 32, 34, 14, 160, 6, 0,
0139 FB_VMODE_NONINTERLACED },
0140
0141
0142 { NULL, 78, 1152, 864, 9090, 228, 88, 32, 0, 84, 12, 0,
0143 FB_VMODE_NONINTERLACED },
0144
0145
0146 { NULL, 70, 1280, 1024, 7905, 224, 32, 28, 8, 160, 8, 0,
0147 FB_VMODE_NONINTERLACED },
0148
0149
0150 { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
0151 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0152 FB_VMODE_NONINTERLACED },
0153
0154
0155 { NULL, 84, 1152, 864, 7407, 184, 312, 32, 0, 128, 12, 0,
0156 FB_VMODE_NONINTERLACED },
0157
0158
0159 { NULL, 74, 1280, 1024, 7407, 256, 32, 34, 3, 144, 3, 0,
0160 FB_VMODE_NONINTERLACED },
0161
0162
0163 { NULL, 100, 1024, 768, 8658, 192, 32, 21, 3, 192, 10, 0,
0164 FB_VMODE_NONINTERLACED },
0165
0166
0167 { NULL, 76, 1280, 1024, 7407, 248, 32, 34, 3, 104, 3, 0,
0168 FB_VMODE_NONINTERLACED },
0169
0170
0171 { NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3, 0,
0172 FB_VMODE_NONINTERLACED },
0173
0174
0175 { NULL, 100, 1152, 864, 7264, 224, 32, 17, 2, 128, 19, 0,
0176 FB_VMODE_NONINTERLACED },
0177
0178
0179 { NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
0180 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0181 FB_VMODE_NONINTERLACED },
0182
0183
0184 { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
0185 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0186 FB_VMODE_NONINTERLACED },
0187
0188
0189 { NULL, 60, 1680, 1050, 6848, 280, 104, 30, 3, 176, 6,
0190 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0191 FB_VMODE_NONINTERLACED },
0192
0193
0194 { NULL, 85, 1600, 1200, 4545, 272, 16, 37, 4, 192, 3,
0195 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0196 FB_VMODE_NONINTERLACED },
0197
0198
0199 { NULL, 100, 1280, 1024, 5502, 256, 32, 26, 7, 128, 15, 0,
0200 FB_VMODE_NONINTERLACED },
0201
0202
0203 { NULL, 64, 1800, 1440, 4347, 304, 96, 46, 1, 192, 3,
0204 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0205 FB_VMODE_NONINTERLACED },
0206
0207
0208 { NULL, 70, 1800, 1440, 4000, 304, 96, 46, 1, 192, 3,
0209 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0210 FB_VMODE_NONINTERLACED },
0211
0212
0213 { NULL, 78, 512, 384, 49603, 48, 16, 16, 1, 64, 3, 0,
0214 FB_VMODE_NONINTERLACED },
0215
0216
0217 { NULL, 85, 512, 384, 45454, 48, 16, 16, 1, 64, 3, 0,
0218 FB_VMODE_NONINTERLACED },
0219
0220
0221 { NULL, 70, 320, 200, 79440, 16, 16, 20, 4, 48, 1, 0,
0222 FB_VMODE_DOUBLE },
0223
0224
0225 { NULL, 60, 320, 240, 79440, 16, 16, 16, 5, 48, 1, 0,
0226 FB_VMODE_DOUBLE },
0227
0228
0229 { NULL, 72, 320, 240, 63492, 16, 16, 16, 4, 48, 2, 0,
0230 FB_VMODE_DOUBLE },
0231
0232
0233 { NULL, 56, 400, 300, 55555, 64, 16, 10, 1, 32, 1, 0,
0234 FB_VMODE_DOUBLE },
0235
0236
0237 { NULL, 60, 400, 300, 50000, 48, 16, 11, 1, 64, 2, 0,
0238 FB_VMODE_DOUBLE },
0239
0240
0241 { NULL, 72, 400, 300, 40000, 32, 24, 11, 19, 64, 3, 0,
0242 FB_VMODE_DOUBLE },
0243
0244
0245 { NULL, 56, 480, 300, 46176, 80, 16, 10, 1, 40, 1, 0,
0246 FB_VMODE_DOUBLE },
0247
0248
0249 { NULL, 60, 480, 300, 41858, 56, 16, 11, 1, 80, 2, 0,
0250 FB_VMODE_DOUBLE },
0251
0252
0253 { NULL, 63, 480, 300, 40000, 56, 16, 11, 1, 80, 2, 0,
0254 FB_VMODE_DOUBLE },
0255
0256
0257 { NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3, 0,
0258 FB_VMODE_DOUBLE },
0259
0260
0261 { NULL, 60, 1920, 1200, 5177, 128, 336, 1, 38, 208, 3,
0262 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0263 FB_VMODE_NONINTERLACED },
0264
0265
0266 { NULL, 60, 1152, 768, 14047, 158, 26, 29, 3, 136, 6,
0267 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0268 FB_VMODE_NONINTERLACED },
0269
0270
0271 { NULL, 60, 1366, 768, 13806, 120, 10, 14, 3, 32, 5, 0,
0272 FB_VMODE_NONINTERLACED },
0273
0274
0275 { NULL, 60, 1280, 800, 12048, 200, 64, 24, 1, 136, 3, 0,
0276 FB_VMODE_NONINTERLACED },
0277
0278
0279 { NULL, 50, 720, 576, 74074, 64, 16, 39, 5, 64, 5, 0,
0280 FB_VMODE_INTERLACED },
0281
0282
0283 { NULL, 50, 800, 520, 58823, 144, 64, 72, 28, 80, 5, 0,
0284 FB_VMODE_INTERLACED },
0285
0286
0287 { NULL, 60, 864, 480, 27777, 1, 1, 1, 1, 0, 0,
0288 0, FB_VMODE_NONINTERLACED },
0289 };
0290
0291 #ifdef CONFIG_FB_MODE_HELPERS
0292 const struct fb_videomode vesa_modes[] = {
0293
0294 { NULL, 85, 640, 350, 31746, 96, 32, 60, 32, 64, 3,
0295 FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
0296
0297 { NULL, 85, 640, 400, 31746, 96, 32, 41, 01, 64, 3,
0298 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0299
0300 { NULL, 85, 721, 400, 28169, 108, 36, 42, 01, 72, 3,
0301 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0302
0303 { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2,
0304 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0305
0306 { NULL, 72, 640, 480, 31746, 128, 24, 29, 9, 40, 2,
0307 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0308
0309 { NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
0310 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0311
0312 { NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3,
0313 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0314
0315 { NULL, 56, 800, 600, 27777, 128, 24, 22, 01, 72, 2,
0316 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0317 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0318
0319 { NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4,
0320 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0321 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0322
0323 { NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
0324 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0325 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0326
0327 { NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3,
0328 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0329 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0330
0331 { NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3,
0332 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0333 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0334
0335 { NULL, 43, 1024, 768, 22271, 56, 8, 41, 0, 176, 8,
0336 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0337 FB_VMODE_INTERLACED, FB_MODE_IS_VESA },
0338
0339 { NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6,
0340 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0341
0342 { NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6,
0343 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0344
0345 { NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
0346 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0347 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0348
0349 { NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
0350 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0351 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0352
0353 { NULL, 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3,
0354 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0355 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0356
0357 { NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
0358 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0359 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0360
0361 { NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
0362 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0363 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0364
0365 { NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
0366 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0367 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0368
0369 { NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
0370 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0371 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0372
0373 { NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
0374 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0375 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0376
0377 { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
0378 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0379 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0380
0381 { NULL, 65, 1600, 1200, 5698, 304, 64, 46, 1, 192, 3,
0382 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0383 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0384
0385 { NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3,
0386 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0387 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0388
0389 { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
0390 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0391 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0392
0393 { NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
0394 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0395 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0396
0397 { NULL, 60, 1792, 1344, 4882, 328, 128, 46, 1, 200, 3,
0398 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0399
0400 { NULL, 75, 1792, 1344, 3831, 352, 96, 69, 1, 216, 3,
0401 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0402
0403 { NULL, 60, 1856, 1392, 4580, 352, 96, 43, 1, 224, 3,
0404 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0405
0406 { NULL, 75, 1856, 1392, 3472, 352, 128, 104, 1, 224, 3,
0407 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0408
0409 { NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 200, 3,
0410 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0411
0412 { NULL, 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3,
0413 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0414
0415 { NULL, 60, 1920, 1200, 6493, 80, 48, 26, 3, 32, 6,
0416 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0417
0418 { NULL, 60, 1920, 1200, 5174, 336, 136, 36, 3, 200, 6,
0419 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0420
0421 { NULL, 75, 1920, 1200, 4077, 344, 136, 46, 3, 208, 6,
0422 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0423
0424 { NULL, 85, 1920, 1200, 3555, 352, 144, 53, 3, 208, 6,
0425 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0426
0427 { NULL, 60, 2560, 1600, 3724, 80, 48, 37, 3, 32, 6,
0428 FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0429
0430 { NULL, 60, 2560, 1600, 2869, 472, 192, 49, 3, 280, 6,
0431 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0432
0433 { NULL, 75, 2560, 1600, 2256, 488, 208, 63, 3, 280, 6,
0434 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0435
0436 { NULL, 85, 2560, 1600, 1979, 488, 208, 73, 3, 280, 6,
0437 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0438
0439 { NULL, 120, 2560, 1600, 1809, 80, 48, 85, 3, 32, 6,
0440 FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
0441 };
0442 EXPORT_SYMBOL(vesa_modes);
0443
0444 const struct dmt_videomode dmt_modes[DMT_SIZE] = {
0445 { 0x01, 0x0000, 0x000000, &vesa_modes[0] },
0446 { 0x02, 0x3119, 0x000000, &vesa_modes[1] },
0447 { 0x03, 0x0000, 0x000000, &vesa_modes[2] },
0448 { 0x04, 0x3140, 0x000000, &vesa_modes[3] },
0449 { 0x05, 0x314c, 0x000000, &vesa_modes[4] },
0450 { 0x06, 0x314f, 0x000000, &vesa_modes[5] },
0451 { 0x07, 0x3159, 0x000000, &vesa_modes[6] },
0452 { 0x08, 0x0000, 0x000000, &vesa_modes[7] },
0453 { 0x09, 0x4540, 0x000000, &vesa_modes[8] },
0454 { 0x0a, 0x454c, 0x000000, &vesa_modes[9] },
0455 { 0x0b, 0x454f, 0x000000, &vesa_modes[10] },
0456 { 0x0c, 0x4559, 0x000000, &vesa_modes[11] },
0457 { 0x0d, 0x0000, 0x000000, NULL },
0458 { 0x0e, 0x0000, 0x000000, NULL },
0459 { 0x0f, 0x0000, 0x000000, &vesa_modes[12] },
0460 { 0x10, 0x6140, 0x000000, &vesa_modes[13] },
0461 { 0x11, 0x614a, 0x000000, &vesa_modes[14] },
0462 { 0x12, 0x614f, 0x000000, &vesa_modes[15] },
0463 { 0x13, 0x6159, 0x000000, &vesa_modes[16] },
0464 { 0x14, 0x0000, 0x000000, NULL },
0465 { 0x15, 0x714f, 0x000000, &vesa_modes[17] },
0466 { 0x16, 0x0000, 0x7f1c21, NULL },
0467 { 0x17, 0x0000, 0x7f1c28, NULL },
0468 { 0x18, 0x0000, 0x7f1c44, NULL },
0469 { 0x19, 0x0000, 0x7f1c62, NULL },
0470 { 0x1a, 0x0000, 0x000000, NULL },
0471 { 0x1b, 0x0000, 0x8f1821, NULL },
0472 { 0x1c, 0x8100, 0x8f1828, NULL },
0473 { 0x1d, 0x810f, 0x8f1844, NULL },
0474 { 0x1e, 0x8119, 0x8f1862, NULL },
0475 { 0x1f, 0x0000, 0x000000, NULL },
0476 { 0x20, 0x8140, 0x000000, &vesa_modes[18] },
0477 { 0x21, 0x8159, 0x000000, &vesa_modes[19] },
0478 { 0x22, 0x0000, 0x000000, NULL },
0479 { 0x23, 0x8180, 0x000000, &vesa_modes[20] },
0480 { 0x24, 0x818f, 0x000000, &vesa_modes[21] },
0481 { 0x25, 0x8199, 0x000000, &vesa_modes[22] },
0482 { 0x26, 0x0000, 0x000000, NULL },
0483 { 0x27, 0x0000, 0x000000, NULL },
0484 { 0x28, 0x0000, 0x000000, NULL },
0485 { 0x29, 0x0000, 0x0c2021, NULL },
0486 { 0x2a, 0x9040, 0x0c2028, NULL },
0487 { 0x2b, 0x904f, 0x0c2044, NULL },
0488 { 0x2c, 0x9059, 0x0c2062, NULL },
0489 { 0x2d, 0x0000, 0x000000, NULL },
0490 { 0x2e, 0x9500, 0xc11821, NULL },
0491 { 0x2f, 0x9500, 0xc11828, NULL },
0492 { 0x30, 0x950f, 0xc11844, NULL },
0493 { 0x31, 0x9519, 0xc11868, NULL },
0494 { 0x32, 0x0000, 0x000000, NULL },
0495 { 0x33, 0xa940, 0x000000, &vesa_modes[23] },
0496 { 0x34, 0xa945, 0x000000, &vesa_modes[24] },
0497 { 0x35, 0xa94a, 0x000000, &vesa_modes[25] },
0498 { 0x36, 0xa94f, 0x000000, &vesa_modes[26] },
0499 { 0x37, 0xa959, 0x000000, &vesa_modes[27] },
0500 { 0x38, 0x0000, 0x000000, NULL },
0501 { 0x39, 0x0000, 0x0c2821, NULL },
0502 { 0x3a, 0xb300, 0x0c2828, NULL },
0503 { 0x3b, 0xb30f, 0x0c2844, NULL },
0504 { 0x3c, 0xb319, 0x0c2868, NULL },
0505 { 0x3d, 0x0000, 0x000000, NULL },
0506 { 0x3e, 0xc140, 0x000000, &vesa_modes[28] },
0507 { 0x3f, 0xc14f, 0x000000, &vesa_modes[29] },
0508 { 0x40, 0x0000, 0x000000, NULL},
0509 { 0x41, 0xc940, 0x000000, &vesa_modes[30] },
0510 { 0x42, 0xc94f, 0x000000, &vesa_modes[31] },
0511 { 0x43, 0x0000, 0x000000, NULL },
0512 { 0x44, 0x0000, 0x572821, &vesa_modes[34] },
0513 { 0x45, 0xd100, 0x572828, &vesa_modes[35] },
0514 { 0x46, 0xd10f, 0x572844, &vesa_modes[36] },
0515 { 0x47, 0xd119, 0x572862, &vesa_modes[37] },
0516 { 0x48, 0x0000, 0x000000, NULL },
0517 { 0x49, 0xd140, 0x000000, &vesa_modes[32] },
0518 { 0x4a, 0xd14f, 0x000000, &vesa_modes[33] },
0519 { 0x4b, 0x0000, 0x000000, NULL },
0520 { 0x4c, 0x0000, 0x1f3821, &vesa_modes[38] },
0521 { 0x4d, 0x0000, 0x1f3828, &vesa_modes[39] },
0522 { 0x4e, 0x0000, 0x1f3844, &vesa_modes[40] },
0523 { 0x4f, 0x0000, 0x1f3862, &vesa_modes[41] },
0524 { 0x50, 0x0000, 0x000000, &vesa_modes[42] },
0525 };
0526 EXPORT_SYMBOL(dmt_modes);
0527 #endif
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541
0542 static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
0543 const struct fb_videomode *mode, unsigned int bpp)
0544 {
0545 int err = 0;
0546
0547 DPRINTK("Trying mode %s %dx%d-%d@%d\n",
0548 mode->name ? mode->name : "noname",
0549 mode->xres, mode->yres, bpp, mode->refresh);
0550 var->xres = mode->xres;
0551 var->yres = mode->yres;
0552 var->xres_virtual = mode->xres;
0553 var->yres_virtual = mode->yres;
0554 var->xoffset = 0;
0555 var->yoffset = 0;
0556 var->bits_per_pixel = bpp;
0557 var->activate |= FB_ACTIVATE_TEST;
0558 var->pixclock = mode->pixclock;
0559 var->left_margin = mode->left_margin;
0560 var->right_margin = mode->right_margin;
0561 var->upper_margin = mode->upper_margin;
0562 var->lower_margin = mode->lower_margin;
0563 var->hsync_len = mode->hsync_len;
0564 var->vsync_len = mode->vsync_len;
0565 var->sync = mode->sync;
0566 var->vmode = mode->vmode;
0567 if (info->fbops->fb_check_var)
0568 err = info->fbops->fb_check_var(var, info);
0569 var->activate &= ~FB_ACTIVATE_TEST;
0570 return err;
0571 }
0572
0573
0574
0575
0576
0577
0578
0579
0580
0581
0582
0583
0584
0585
0586
0587
0588
0589
0590
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615
0616
0617 int fb_find_mode(struct fb_var_screeninfo *var,
0618 struct fb_info *info, const char *mode_option,
0619 const struct fb_videomode *db, unsigned int dbsize,
0620 const struct fb_videomode *default_mode,
0621 unsigned int default_bpp)
0622 {
0623 int i;
0624
0625
0626 if (!db) {
0627 db = modedb;
0628 dbsize = ARRAY_SIZE(modedb);
0629 }
0630
0631 if (!default_mode)
0632 default_mode = &db[0];
0633
0634 if (!default_bpp)
0635 default_bpp = 8;
0636
0637
0638 if (!mode_option)
0639 mode_option = fb_mode_option;
0640 if (mode_option) {
0641 const char *name = mode_option;
0642 unsigned int namelen = strlen(name);
0643 int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
0644 unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0;
0645 int yres_specified = 0, cvt = 0, rb = 0;
0646 int interlace_specified = 0, interlace = 0;
0647 int margins = 0;
0648 u32 best, diff, tdiff;
0649
0650 for (i = namelen-1; i >= 0; i--) {
0651 switch (name[i]) {
0652 case '@':
0653 namelen = i;
0654 if (!refresh_specified && !bpp_specified &&
0655 !yres_specified) {
0656 refresh = simple_strtol(&name[i+1], NULL,
0657 10);
0658 refresh_specified = 1;
0659 if (cvt || rb)
0660 cvt = 0;
0661 } else
0662 goto done;
0663 break;
0664 case '-':
0665 namelen = i;
0666 if (!bpp_specified && !yres_specified) {
0667 bpp = simple_strtol(&name[i+1], NULL,
0668 10);
0669 bpp_specified = 1;
0670 if (cvt || rb)
0671 cvt = 0;
0672 } else
0673 goto done;
0674 break;
0675 case 'x':
0676 if (!yres_specified) {
0677 yres = simple_strtol(&name[i+1], NULL,
0678 10);
0679 yres_specified = 1;
0680 } else
0681 goto done;
0682 break;
0683 case '0' ... '9':
0684 break;
0685 case 'M':
0686 if (!yres_specified)
0687 cvt = 1;
0688 break;
0689 case 'R':
0690 if (!cvt)
0691 rb = 1;
0692 break;
0693 case 'm':
0694 if (!cvt)
0695 margins = 1;
0696 break;
0697 case 'p':
0698 if (!cvt) {
0699 interlace = 0;
0700 interlace_specified = 1;
0701 }
0702 break;
0703 case 'i':
0704 if (!cvt) {
0705 interlace = 1;
0706 interlace_specified = 1;
0707 }
0708 break;
0709 default:
0710 goto done;
0711 }
0712 }
0713 if (i < 0 && yres_specified) {
0714 xres = simple_strtol(name, NULL, 10);
0715 res_specified = 1;
0716 }
0717 done:
0718 if (cvt) {
0719 struct fb_videomode cvt_mode;
0720 int ret;
0721
0722 DPRINTK("CVT mode %dx%d@%dHz%s%s%s\n", xres, yres,
0723 (refresh) ? refresh : 60,
0724 (rb) ? " reduced blanking" : "",
0725 (margins) ? " with margins" : "",
0726 (interlace) ? " interlaced" : "");
0727
0728 memset(&cvt_mode, 0, sizeof(cvt_mode));
0729 cvt_mode.xres = xres;
0730 cvt_mode.yres = yres;
0731 cvt_mode.refresh = (refresh) ? refresh : 60;
0732
0733 if (interlace)
0734 cvt_mode.vmode |= FB_VMODE_INTERLACED;
0735 else
0736 cvt_mode.vmode &= ~FB_VMODE_INTERLACED;
0737
0738 ret = fb_find_mode_cvt(&cvt_mode, margins, rb);
0739
0740 if (!ret && !fb_try_mode(var, info, &cvt_mode, bpp)) {
0741 DPRINTK("modedb CVT: CVT mode ok\n");
0742 return 1;
0743 }
0744
0745 DPRINTK("CVT mode invalid, getting mode from database\n");
0746 }
0747
0748 DPRINTK("Trying specified video mode%s %ix%i\n",
0749 refresh_specified ? "" : " (ignoring refresh rate)",
0750 xres, yres);
0751
0752 if (!refresh_specified) {
0753
0754
0755
0756
0757
0758
0759
0760 if (db != modedb &&
0761 info->monspecs.vfmin && info->monspecs.vfmax &&
0762 info->monspecs.hfmin && info->monspecs.hfmax &&
0763 info->monspecs.dclkmax) {
0764 refresh = 1000;
0765 } else {
0766 refresh = 60;
0767 }
0768 }
0769
0770 diff = -1;
0771 best = -1;
0772 for (i = 0; i < dbsize; i++) {
0773 if ((name_matches(db[i], name, namelen) ||
0774 (res_specified && res_matches(db[i], xres, yres))) &&
0775 !fb_try_mode(var, info, &db[i], bpp)) {
0776 const int db_interlace = (db[i].vmode &
0777 FB_VMODE_INTERLACED ? 1 : 0);
0778 int score = abs(db[i].refresh - refresh);
0779
0780 if (interlace_specified)
0781 score += abs(db_interlace - interlace);
0782
0783 if (!interlace_specified ||
0784 db_interlace == interlace)
0785 if (refresh_specified &&
0786 db[i].refresh == refresh)
0787 return 1;
0788
0789 if (score < diff) {
0790 diff = score;
0791 best = i;
0792 }
0793 }
0794 }
0795 if (best != -1) {
0796 fb_try_mode(var, info, &db[best], bpp);
0797 return (refresh_specified) ? 2 : 1;
0798 }
0799
0800 diff = 2 * (xres + yres);
0801 best = -1;
0802 DPRINTK("Trying best-fit modes\n");
0803 for (i = 0; i < dbsize; i++) {
0804 DPRINTK("Trying %ix%i\n", db[i].xres, db[i].yres);
0805 if (!fb_try_mode(var, info, &db[i], bpp)) {
0806 tdiff = abs(db[i].xres - xres) +
0807 abs(db[i].yres - yres);
0808
0809
0810
0811
0812
0813 if (xres > db[i].xres || yres > db[i].yres)
0814 tdiff += xres + yres;
0815
0816 if (diff > tdiff) {
0817 diff = tdiff;
0818 best = i;
0819 }
0820 }
0821 }
0822 if (best != -1) {
0823 fb_try_mode(var, info, &db[best], bpp);
0824 return 5;
0825 }
0826 }
0827
0828 DPRINTK("Trying default video mode\n");
0829 if (!fb_try_mode(var, info, default_mode, default_bpp))
0830 return 3;
0831
0832 DPRINTK("Trying all modes\n");
0833 for (i = 0; i < dbsize; i++)
0834 if (!fb_try_mode(var, info, &db[i], default_bpp))
0835 return 4;
0836
0837 DPRINTK("No valid mode found\n");
0838 return 0;
0839 }
0840
0841
0842
0843
0844
0845
0846 void fb_var_to_videomode(struct fb_videomode *mode,
0847 const struct fb_var_screeninfo *var)
0848 {
0849 u32 pixclock, hfreq, htotal, vtotal;
0850
0851 mode->name = NULL;
0852 mode->xres = var->xres;
0853 mode->yres = var->yres;
0854 mode->pixclock = var->pixclock;
0855 mode->hsync_len = var->hsync_len;
0856 mode->vsync_len = var->vsync_len;
0857 mode->left_margin = var->left_margin;
0858 mode->right_margin = var->right_margin;
0859 mode->upper_margin = var->upper_margin;
0860 mode->lower_margin = var->lower_margin;
0861 mode->sync = var->sync;
0862 mode->vmode = var->vmode & FB_VMODE_MASK;
0863 mode->flag = FB_MODE_IS_FROM_VAR;
0864 mode->refresh = 0;
0865
0866 if (!var->pixclock)
0867 return;
0868
0869 pixclock = PICOS2KHZ(var->pixclock) * 1000;
0870
0871 htotal = var->xres + var->right_margin + var->hsync_len +
0872 var->left_margin;
0873 vtotal = var->yres + var->lower_margin + var->vsync_len +
0874 var->upper_margin;
0875
0876 if (var->vmode & FB_VMODE_INTERLACED)
0877 vtotal /= 2;
0878 if (var->vmode & FB_VMODE_DOUBLE)
0879 vtotal *= 2;
0880
0881 if (!htotal || !vtotal)
0882 return;
0883
0884 hfreq = pixclock/htotal;
0885 mode->refresh = hfreq/vtotal;
0886 }
0887
0888
0889
0890
0891
0892
0893 void fb_videomode_to_var(struct fb_var_screeninfo *var,
0894 const struct fb_videomode *mode)
0895 {
0896 var->xres = mode->xres;
0897 var->yres = mode->yres;
0898 var->xres_virtual = mode->xres;
0899 var->yres_virtual = mode->yres;
0900 var->xoffset = 0;
0901 var->yoffset = 0;
0902 var->pixclock = mode->pixclock;
0903 var->left_margin = mode->left_margin;
0904 var->right_margin = mode->right_margin;
0905 var->upper_margin = mode->upper_margin;
0906 var->lower_margin = mode->lower_margin;
0907 var->hsync_len = mode->hsync_len;
0908 var->vsync_len = mode->vsync_len;
0909 var->sync = mode->sync;
0910 var->vmode = mode->vmode & FB_VMODE_MASK;
0911 }
0912
0913
0914
0915
0916
0917
0918
0919
0920
0921 int fb_mode_is_equal(const struct fb_videomode *mode1,
0922 const struct fb_videomode *mode2)
0923 {
0924 return (mode1->xres == mode2->xres &&
0925 mode1->yres == mode2->yres &&
0926 mode1->pixclock == mode2->pixclock &&
0927 mode1->hsync_len == mode2->hsync_len &&
0928 mode1->vsync_len == mode2->vsync_len &&
0929 mode1->left_margin == mode2->left_margin &&
0930 mode1->right_margin == mode2->right_margin &&
0931 mode1->upper_margin == mode2->upper_margin &&
0932 mode1->lower_margin == mode2->lower_margin &&
0933 mode1->sync == mode2->sync &&
0934 mode1->vmode == mode2->vmode);
0935 }
0936
0937
0938
0939
0940
0941
0942
0943
0944
0945
0946
0947
0948
0949
0950
0951
0952
0953
0954 const struct fb_videomode *fb_find_best_mode(const struct fb_var_screeninfo *var,
0955 struct list_head *head)
0956 {
0957 struct list_head *pos;
0958 struct fb_modelist *modelist;
0959 struct fb_videomode *mode, *best = NULL;
0960 u32 diff = -1;
0961
0962 list_for_each(pos, head) {
0963 u32 d;
0964
0965 modelist = list_entry(pos, struct fb_modelist, list);
0966 mode = &modelist->mode;
0967
0968 if (mode->xres >= var->xres && mode->yres >= var->yres) {
0969 d = (mode->xres - var->xres) +
0970 (mode->yres - var->yres);
0971 if (diff > d) {
0972 diff = d;
0973 best = mode;
0974 } else if (diff == d && best &&
0975 mode->refresh > best->refresh)
0976 best = mode;
0977 }
0978 }
0979 return best;
0980 }
0981
0982
0983
0984
0985
0986
0987
0988
0989
0990
0991
0992 const struct fb_videomode *fb_find_nearest_mode(const struct fb_videomode *mode,
0993 struct list_head *head)
0994 {
0995 struct list_head *pos;
0996 struct fb_modelist *modelist;
0997 struct fb_videomode *cmode, *best = NULL;
0998 u32 diff = -1, diff_refresh = -1;
0999
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);