modedb.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:13k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/drivers/video/modedb.c -- Standard video mode database management
  3.  *
  4.  * Copyright (C) 1999 Geert Uytterhoeven
  5.  *
  6.  * 2001 - Documented with DocBook
  7.  * - Brad Douglas <brad@neruo.com>
  8.  *
  9.  *  This file is subject to the terms and conditions of the GNU General Public
  10.  *  License. See the file COPYING in the main directory of this archive for
  11.  *  more details.
  12.  */
  13. #include <linux/module.h>
  14. #include <linux/tty.h>
  15. #include <linux/fb.h>
  16. #include <linux/console_struct.h>
  17. #include <linux/sched.h>
  18. #undef DEBUG
  19. #define name_matches(v, s, l) 
  20.     ((v).name && !strncmp((s), (v).name, (l)) && strlen((v).name) == (l))
  21. #define res_matches(v, x, y) 
  22.     ((v).xres == (x) && (v).yres == (y))
  23. #ifdef DEBUG
  24. #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
  25. #else
  26. #define DPRINTK(fmt, args...)
  27. #endif
  28. const char *global_mode_option = NULL;
  29.     /*
  30.      *  Standard video mode definitions (taken from XFree86)
  31.      */
  32. #define DEFAULT_MODEDB_INDEX 0
  33. static struct fb_videomode modedb[] __initdata = {
  34.     {
  35. /* 640x400 @ 70 Hz, 31.5 kHz hsync */
  36. NULL, 70, 640, 400, 39721, 40, 24, 39, 9, 96, 2,
  37. 0, FB_VMODE_NONINTERLACED
  38.     }, {
  39. /* 640x480 @ 60 Hz, 31.5 kHz hsync */
  40. NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
  41. 0, FB_VMODE_NONINTERLACED
  42.     }, {
  43. /* 800x600 @ 56 Hz, 35.15 kHz hsync */
  44. NULL, 56, 800, 600, 27777, 128, 24, 22, 1, 72, 2,
  45. 0, FB_VMODE_NONINTERLACED
  46.     }, {
  47. /* 1024x768 @ 87 Hz interlaced, 35.5 kHz hsync */
  48. NULL, 87, 1024, 768, 22271, 56, 24, 33, 8, 160, 8,
  49. 0, FB_VMODE_INTERLACED
  50.     }, {
  51. /* 640x400 @ 85 Hz, 37.86 kHz hsync */
  52. NULL, 85, 640, 400, 31746, 96, 32, 41, 1, 64, 3,
  53. FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
  54.     }, {
  55. /* 640x480 @ 72 Hz, 36.5 kHz hsync */
  56. NULL, 72, 640, 480, 31746, 144, 40, 30, 8, 40, 3,
  57. 0, FB_VMODE_NONINTERLACED
  58.     }, {
  59. /* 640x480 @ 75 Hz, 37.50 kHz hsync */
  60. NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3,
  61. 0, FB_VMODE_NONINTERLACED
  62.     }, {
  63. /* 800x600 @ 60 Hz, 37.8 kHz hsync */
  64. NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4,
  65. FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
  66.     }, {
  67. /* 640x480 @ 85 Hz, 43.27 kHz hsync */
  68. NULL, 85, 640, 480, 27777, 80, 56, 25, 1, 56, 3,
  69. 0, FB_VMODE_NONINTERLACED
  70.     }, {
  71. /* 1152x864 @ 89 Hz interlaced, 44 kHz hsync */
  72. NULL, 69, 1152, 864, 15384, 96, 16, 110, 1, 216, 10,
  73. 0, FB_VMODE_INTERLACED
  74.     }, {
  75. /* 800x600 @ 72 Hz, 48.0 kHz hsync */
  76. NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
  77. FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
  78.     }, {
  79. /* 1024x768 @ 60 Hz, 48.4 kHz hsync */
  80. NULL, 60, 1024, 768, 15384, 168, 8, 29, 3, 144, 6,
  81. 0, FB_VMODE_NONINTERLACED
  82.     }, {
  83. /* 640x480 @ 100 Hz, 53.01 kHz hsync */
  84. NULL, 100, 640, 480, 21834, 96, 32, 36, 8, 96, 6,
  85. 0, FB_VMODE_NONINTERLACED
  86.     }, {
  87. /* 1152x864 @ 60 Hz, 53.5 kHz hsync */
  88. NULL, 60, 1152, 864, 11123, 208, 64, 16, 4, 256, 8,
  89. 0, FB_VMODE_NONINTERLACED
  90.     }, {
  91. /* 800x600 @ 85 Hz, 55.84 kHz hsync */
  92. NULL, 85, 800, 600, 16460, 160, 64, 36, 16, 64, 5,
  93. 0, FB_VMODE_NONINTERLACED
  94.     }, {
  95. /* 1024x768 @ 70 Hz, 56.5 kHz hsync */
  96. NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6,
  97. 0, FB_VMODE_NONINTERLACED
  98.     }, {
  99. /* 1280x1024 @ 87 Hz interlaced, 51 kHz hsync */
  100. NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12,
  101. 0, FB_VMODE_INTERLACED
  102.     }, {
  103. /* 800x600 @ 100 Hz, 64.02 kHz hsync */
  104. NULL, 100, 800, 600, 14357, 160, 64, 30, 4, 64, 6,
  105. 0, FB_VMODE_NONINTERLACED
  106.     }, {
  107. /* 1024x768 @ 76 Hz, 62.5 kHz hsync */
  108. NULL, 76, 1024, 768, 11764, 208, 8, 36, 16, 120, 3,
  109. 0, FB_VMODE_NONINTERLACED
  110.     }, {
  111. /* 1152x864 @ 70 Hz, 62.4 kHz hsync */
  112. NULL, 70, 1152, 864, 10869, 106, 56, 20, 1, 160, 10,
  113. 0, FB_VMODE_NONINTERLACED
  114.     }, {
  115. /* 1280x1024 @ 61 Hz, 64.2 kHz hsync */
  116. NULL, 61, 1280, 1024, 9090, 200, 48, 26, 1, 184, 3,
  117. 0, FB_VMODE_NONINTERLACED
  118.     }, {
  119. /* 1024x768 @ 85 Hz, 70.24 kHz hsync */
  120. NULL, 85, 1024, 768, 10111, 192, 32, 34, 14, 160, 6,
  121. 0, FB_VMODE_NONINTERLACED
  122.     }, {
  123. /* 1152x864 @ 78 Hz, 70.8 kHz hsync */
  124. NULL, 78, 1152, 864, 9090, 228, 88, 32, 0, 84, 12,
  125. 0, FB_VMODE_NONINTERLACED
  126.     }, {
  127. /* 1280x1024 @ 70 Hz, 74.59 kHz hsync */
  128. NULL, 70, 1280, 1024, 7905, 224, 32, 28, 8, 160, 8,
  129. 0, FB_VMODE_NONINTERLACED
  130.     }, {
  131. /* 1600x1200 @ 60Hz, 75.00 kHz hsync */
  132. NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
  133. FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
  134.     }, {
  135. /* 1152x864 @ 84 Hz, 76.0 kHz hsync */
  136. NULL, 84, 1152, 864, 7407, 184, 312, 32, 0, 128, 12,
  137. 0, FB_VMODE_NONINTERLACED
  138.     }, {
  139. /* 1280x1024 @ 74 Hz, 78.85 kHz hsync */
  140. NULL, 74, 1280, 1024, 7407, 256, 32, 34, 3, 144, 3,
  141. 0, FB_VMODE_NONINTERLACED
  142.     }, {
  143. /* 1024x768 @ 100Hz, 80.21 kHz hsync */
  144. NULL, 100, 1024, 768, 8658, 192, 32, 21, 3, 192, 10,
  145. 0, FB_VMODE_NONINTERLACED
  146.     }, {
  147. /* 1280x1024 @ 76 Hz, 81.13 kHz hsync */
  148. NULL, 76, 1280, 1024, 7407, 248, 32, 34, 3, 104, 3,
  149. 0, FB_VMODE_NONINTERLACED
  150.     }, {
  151. /* 1600x1200 @ 70 Hz, 87.50 kHz hsync */
  152. NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3,
  153. 0, FB_VMODE_NONINTERLACED
  154.     }, {
  155. /* 1152x864 @ 100 Hz, 89.62 kHz hsync */
  156. NULL, 100, 1152, 864, 7264, 224, 32, 17, 2, 128, 19,
  157. 0, FB_VMODE_NONINTERLACED
  158.     }, {
  159. /* 1280x1024 @ 85 Hz, 91.15 kHz hsync */
  160. NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
  161. FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
  162.     }, {
  163. /* 1600x1200 @ 75 Hz, 93.75 kHz hsync */
  164. NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
  165. FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
  166.     }, {
  167. /* 1600x1200 @ 85 Hz, 105.77 kHz hsync */
  168. NULL, 85, 1600, 1200, 4545, 272, 16, 37, 4, 192, 3,
  169. FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
  170.     }, {
  171. /* 1280x1024 @ 100 Hz, 107.16 kHz hsync */
  172. NULL, 100, 1280, 1024, 5502, 256, 32, 26, 7, 128, 15,
  173. 0, FB_VMODE_NONINTERLACED
  174.     }, {
  175. /* 1800x1440 @ 64Hz, 96.15 kHz hsync  */
  176. NULL, 64, 1800, 1440, 4347, 304, 96, 46, 1, 192, 3,
  177. FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
  178.     }, {
  179. /* 1800x1440 @ 70Hz, 104.52 kHz hsync  */
  180. NULL, 70, 1800, 1440, 4000, 304, 96, 46, 1, 192, 3,
  181. FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
  182.     }, {
  183. /* 512x384 @ 78 Hz, 31.50 kHz hsync */
  184. NULL, 78, 512, 384, 49603, 48, 16, 16, 1, 64, 3,
  185. 0, FB_VMODE_NONINTERLACED
  186.     }, {
  187. /* 512x384 @ 85 Hz, 34.38 kHz hsync */
  188. NULL, 85, 512, 384, 45454, 48, 16, 16, 1, 64, 3,
  189. 0, FB_VMODE_NONINTERLACED
  190.     }, {
  191. /* 320x200 @ 70 Hz, 31.5 kHz hsync, 8:5 aspect ratio */
  192. NULL, 70, 320, 200, 79440, 16, 16, 20, 4, 48, 1,
  193. 0, FB_VMODE_DOUBLE
  194.     }, {
  195. /* 320x240 @ 60 Hz, 31.5 kHz hsync, 4:3 aspect ratio */
  196. NULL, 60, 320, 240, 79440, 16, 16, 16, 5, 48, 1,
  197. 0, FB_VMODE_DOUBLE
  198.     }, {
  199. /* 320x240 @ 72 Hz, 36.5 kHz hsync */
  200. NULL, 72, 320, 240, 63492, 16, 16, 16, 4, 48, 2,
  201. 0, FB_VMODE_DOUBLE
  202.     }, {
  203. /* 400x300 @ 56 Hz, 35.2 kHz hsync, 4:3 aspect ratio */
  204. NULL, 56, 400, 300, 55555, 64, 16, 10, 1, 32, 1,
  205. 0, FB_VMODE_DOUBLE
  206.     }, {
  207. /* 400x300 @ 60 Hz, 37.8 kHz hsync */
  208. NULL, 60, 400, 300, 50000, 48, 16, 11, 1, 64, 2,
  209. 0, FB_VMODE_DOUBLE
  210.     }, {
  211. /* 400x300 @ 72 Hz, 48.0 kHz hsync */
  212. NULL, 72, 400, 300, 40000, 32, 24, 11, 19, 64, 3,
  213. 0, FB_VMODE_DOUBLE
  214.     }, {
  215. /* 480x300 @ 56 Hz, 35.2 kHz hsync, 8:5 aspect ratio */
  216. NULL, 56, 480, 300, 46176, 80, 16, 10, 1, 40, 1,
  217. 0, FB_VMODE_DOUBLE
  218.     }, {
  219. /* 480x300 @ 60 Hz, 37.8 kHz hsync */
  220. NULL, 60, 480, 300, 41858, 56, 16, 11, 1, 80, 2,
  221. 0, FB_VMODE_DOUBLE
  222.     }, {
  223. /* 480x300 @ 63 Hz, 39.6 kHz hsync */
  224. NULL, 63, 480, 300, 40000, 56, 16, 11, 1, 80, 2,
  225. 0, FB_VMODE_DOUBLE
  226.     }, {
  227. /* 480x300 @ 72 Hz, 48.0 kHz hsync */
  228. NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3,
  229. 0, FB_VMODE_DOUBLE
  230.     },
  231. };
  232. static int __init my_atoi(const char *name)
  233. {
  234.     int val = 0;
  235.     for (;; name++) {
  236. switch (*name) {
  237.     case '0'...'9':
  238. val = 10*val+(*name-'0');
  239. break;
  240.     default:
  241. return val;
  242. }
  243.     }
  244. }
  245. static int PROC_CONSOLE(const struct fb_info *info)
  246. {
  247. int fgc;
  248. if (info->display_fg != NULL)
  249. fgc = info->display_fg->vc_num;
  250. else
  251. return -1;
  252. if (!current->tty)
  253. return fgc;
  254. if (current->tty->driver.type != TTY_DRIVER_TYPE_CONSOLE)
  255. /* XXX Should report error here? */
  256. return fgc;
  257. if (MINOR(current->tty->device) < 1)
  258. return fgc;
  259. return MINOR(current->tty->device) - 1;
  260. }
  261. /**
  262.  * __fb_try_mode - test a video mode
  263.  * @var: frame buffer user defined part of display
  264.  * @info: frame buffer info structure
  265.  * @mode: frame buffer video mode structure
  266.  * @bpp: color depth in bits per pixel
  267.  *
  268.  * Tries a video mode to test it's validity for device @info.
  269.  *
  270.  * Returns 1 on success.
  271.  *
  272.  */
  273. int __fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
  274.   const struct fb_videomode *mode, unsigned int bpp)
  275. {
  276.     int err;
  277.     DPRINTK("Trying mode %s %dx%d-%d@%dn", mode->name ? mode->name : "noname",
  278.     mode->xres, mode->yres, bpp, mode->refresh);
  279.     var->xres = mode->xres;
  280.     var->yres = mode->yres;
  281.     var->xres_virtual = mode->xres;
  282.     var->yres_virtual = mode->yres;
  283.     var->xoffset = 0;
  284.     var->yoffset = 0;
  285.     var->bits_per_pixel = bpp;
  286.     var->activate |= FB_ACTIVATE_TEST;
  287.     var->pixclock = mode->pixclock;
  288.     var->left_margin = mode->left_margin;
  289.     var->right_margin = mode->right_margin;
  290.     var->upper_margin = mode->upper_margin;
  291.     var->lower_margin = mode->lower_margin;
  292.     var->hsync_len = mode->hsync_len;
  293.     var->vsync_len = mode->vsync_len;
  294.     var->sync = mode->sync;
  295.     var->vmode = mode->vmode;
  296.     err = info->fbops->fb_set_var(var, PROC_CONSOLE(info), info);
  297.     var->activate &= ~FB_ACTIVATE_TEST;
  298.     return !err;
  299. }
  300. /**
  301.  * fb_find_mode - finds a valid video mode
  302.  * @var: frame buffer user defined part of display
  303.  * @info: frame buffer info structure
  304.  * @mode_option: string video mode to find
  305.  * @db: video mode database
  306.  * @dbsize: size of @db
  307.  * @default_mode: default video mode to fall back to
  308.  * @default_bpp: default color depth in bits per pixel
  309.  *
  310.  * Finds a suitable video mode, starting with the specified mode
  311.  * in @mode_option with fallback to @default_mode.  If
  312.  * @default_mode fails, all modes in the video mode database will
  313.  * be tried.
  314.  *
  315.  * Valid mode specifiers for @mode_option:
  316.  *
  317.  * <xres>x<yres>[-<bpp>][@<refresh>] or
  318.  * <name>[-<bpp>][@<refresh>]
  319.  *
  320.  * with <xres>, <yres>, <bpp> and <refresh> decimal numbers and
  321.  * <name> a string.
  322.  *
  323.  * NOTE: The passed struct @var is _not_ cleared!  This allows you
  324.  * to supply values for e.g. the grayscale and accel_flags fields.
  325.  *
  326.  * Returns zero for failure, 1 if using specified @mode_option,
  327.  * 2 if using specified @mode_option with an ignored refresh rate,
  328.  * 3 if default mode is used, 4 if fall back to any valid mode.
  329.  *
  330.  */
  331. int __init fb_find_mode(struct fb_var_screeninfo *var,
  332. struct fb_info *info, const char *mode_option,
  333. const struct fb_videomode *db, unsigned int dbsize,
  334. const struct fb_videomode *default_mode,
  335. unsigned int default_bpp)
  336. {
  337.     int i, j;
  338.     /* Set up defaults */
  339.     if (!db) {
  340. db = modedb;
  341. dbsize = sizeof(modedb)/sizeof(*modedb);
  342.     }
  343.     if (!default_mode)
  344. default_mode = &modedb[DEFAULT_MODEDB_INDEX];
  345.     if (!default_bpp)
  346. default_bpp = 8;
  347.     /* Did the user specify a video mode? */
  348.     if (mode_option || (mode_option = global_mode_option)) {
  349. const char *name = mode_option;
  350. unsigned int namelen = strlen(name);
  351. int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
  352. unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0;
  353. int yres_specified = 0;
  354. for (i = namelen-1; i >= 0; i--) {
  355.     switch (name[i]) {
  356. case '@':
  357.     namelen = i;
  358.     if (!refresh_specified && !bpp_specified &&
  359. !yres_specified) {
  360. refresh = my_atoi(&name[i+1]);
  361. refresh_specified = 1;
  362.     } else
  363. goto done;
  364.     break;
  365. case '-':
  366.     namelen = i;
  367.     if (!bpp_specified && !yres_specified) {
  368. bpp = my_atoi(&name[i+1]);
  369. bpp_specified = 1;
  370.     } else
  371. goto done;
  372.     break;
  373. case 'x':
  374.     if (!yres_specified) {
  375. yres = my_atoi(&name[i+1]);
  376. yres_specified = 1;
  377.     } else
  378. goto done;
  379.     break;
  380. case '0'...'9':
  381.     break;
  382. default:
  383.     goto done;
  384.     }
  385. }
  386. if (i < 0 && yres_specified) {
  387.     xres = my_atoi(name);
  388.     res_specified = 1;
  389. }
  390. done:
  391. for (i = refresh_specified; i >= 0; i--) {
  392.     DPRINTK("Trying specified video mode%sn",
  393.     i ? "" : " (ignoring refresh rate)");
  394.     for (j = 0; j < dbsize; j++)
  395. if ((name_matches(db[j], name, namelen) ||
  396.      (res_specified && res_matches(db[j], xres, yres))) &&
  397.     (!i || db[j].refresh == refresh) &&
  398.     __fb_try_mode(var, info, &db[j], bpp))
  399.     return 2-i;
  400. }
  401.     }
  402.     DPRINTK("Trying default video moden");
  403.     if (__fb_try_mode(var, info, default_mode, default_bpp))
  404. return 3;
  405.     DPRINTK("Trying all modesn");
  406.     for (i = 0; i < dbsize; i++)
  407. if (__fb_try_mode(var, info, &db[i], default_bpp))
  408.     return 4;
  409.     DPRINTK("No valid mode foundn");
  410.     return 0;
  411. }
  412. EXPORT_SYMBOL(__fb_try_mode);