LCOV - code coverage report
Current view: top level - lkbce/drivers/video - modedb.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 92 327 28.1 %
Date: 2017-01-25 Functions: 7 13 53.8 %

          Line data    Source code
       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             : 
      14             : #include <linux/module.h>
      15             : #include <linux/fb.h>
      16             : #include <linux/kernel.h>
      17             : 
      18             : #undef DEBUG
      19             : 
      20             : #define name_matches(v, s, l) \
      21             :     ((v).name && !strncmp((s), (v).name, (l)) && strlen((v).name) == (l))
      22             : #define res_matches(v, x, y) \
      23             :     ((v).xres == (x) && (v).yres == (y))
      24             : 
      25             : #ifdef DEBUG
      26             : #define DPRINTK(fmt, args...)   printk("modedb %s: " fmt, __func__ , ## args)
      27             : #else
      28             : #define DPRINTK(fmt, args...)
      29             : #endif
      30             : 
      31             : const char *fb_mode_option;
      32             : EXPORT_SYMBOL_GPL(fb_mode_option);
      33             : 
      34             :     /*
      35             :      *  Standard video mode definitions (taken from XFree86)
      36             :      */
      37             : 
      38           1 : static const struct fb_videomode modedb[] = {
      39             :     {
      40             :         /* 640x400 @ 70 Hz, 31.5 kHz hsync */
      41             :         NULL, 70, 640, 400, 39721, 40, 24, 39, 9, 96, 2,
      42             :         0, FB_VMODE_NONINTERLACED
      43             :     }, {
      44             :         /* 640x480 @ 60 Hz, 31.5 kHz hsync */
      45             :         NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
      46             :         0, FB_VMODE_NONINTERLACED
      47             :     }, {
      48             :         /* 800x600 @ 56 Hz, 35.15 kHz hsync */
      49             :         NULL, 56, 800, 600, 27777, 128, 24, 22, 1, 72, 2,
      50             :         0, FB_VMODE_NONINTERLACED
      51             :     }, {
      52             :         /* 1024x768 @ 87 Hz interlaced, 35.5 kHz hsync */
      53             :         NULL, 87, 1024, 768, 22271, 56, 24, 33, 8, 160, 8,
      54             :         0, FB_VMODE_INTERLACED
      55             :     }, {
      56             :         /* 640x400 @ 85 Hz, 37.86 kHz hsync */
      57             :         NULL, 85, 640, 400, 31746, 96, 32, 41, 1, 64, 3,
      58             :         FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
      59             :     }, {
      60             :         /* 640x480 @ 72 Hz, 36.5 kHz hsync */
      61             :         NULL, 72, 640, 480, 31746, 144, 40, 30, 8, 40, 3,
      62             :         0, FB_VMODE_NONINTERLACED
      63             :     }, {
      64             :         /* 640x480 @ 75 Hz, 37.50 kHz hsync */
      65             :         NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3,
      66             :         0, FB_VMODE_NONINTERLACED
      67             :     }, {
      68             :         /* 800x600 @ 60 Hz, 37.8 kHz hsync */
      69             :         NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4,
      70             :         FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
      71             :     }, {
      72             :         /* 640x480 @ 85 Hz, 43.27 kHz hsync */
      73             :         NULL, 85, 640, 480, 27777, 80, 56, 25, 1, 56, 3,
      74             :         0, FB_VMODE_NONINTERLACED
      75             :     }, {
      76             :         /* 1152x864 @ 89 Hz interlaced, 44 kHz hsync */
      77             :         NULL, 89, 1152, 864, 15384, 96, 16, 110, 1, 216, 10,
      78             :         0, FB_VMODE_INTERLACED
      79             :     }, {
      80             :         /* 800x600 @ 72 Hz, 48.0 kHz hsync */
      81             :         NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
      82             :         FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
      83             :     }, {
      84             :         /* 1024x768 @ 60 Hz, 48.4 kHz hsync */
      85             :         NULL, 60, 1024, 768, 15384, 168, 8, 29, 3, 144, 6,
      86             :         0, FB_VMODE_NONINTERLACED
      87             :     }, {
      88             :         /* 640x480 @ 100 Hz, 53.01 kHz hsync */
      89             :         NULL, 100, 640, 480, 21834, 96, 32, 36, 8, 96, 6,
      90             :         0, FB_VMODE_NONINTERLACED
      91             :     }, {
      92             :         /* 1152x864 @ 60 Hz, 53.5 kHz hsync */
      93             :         NULL, 60, 1152, 864, 11123, 208, 64, 16, 4, 256, 8,
      94             :         0, FB_VMODE_NONINTERLACED
      95             :     }, {
      96             :         /* 800x600 @ 85 Hz, 55.84 kHz hsync */
      97             :         NULL, 85, 800, 600, 16460, 160, 64, 36, 16, 64, 5,
      98             :         0, FB_VMODE_NONINTERLACED
      99             :     }, {
     100             :         /* 1024x768 @ 70 Hz, 56.5 kHz hsync */
     101             :         NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6,
     102             :         0, FB_VMODE_NONINTERLACED
     103             :     }, {
     104             :         /* 1280x1024 @ 87 Hz interlaced, 51 kHz hsync */
     105             :         NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12,
     106             :         0, FB_VMODE_INTERLACED
     107             :     }, {
     108             :         /* 800x600 @ 100 Hz, 64.02 kHz hsync */
     109             :         NULL, 100, 800, 600, 14357, 160, 64, 30, 4, 64, 6,
     110             :         0, FB_VMODE_NONINTERLACED
     111             :     }, {
     112             :         /* 1024x768 @ 76 Hz, 62.5 kHz hsync */
     113             :         NULL, 76, 1024, 768, 11764, 208, 8, 36, 16, 120, 3,
     114             :         0, FB_VMODE_NONINTERLACED
     115             :     }, {
     116             :         /* 1152x864 @ 70 Hz, 62.4 kHz hsync */
     117             :         NULL, 70, 1152, 864, 10869, 106, 56, 20, 1, 160, 10,
     118             :         0, FB_VMODE_NONINTERLACED
     119             :     }, {
     120             :         /* 1280x1024 @ 61 Hz, 64.2 kHz hsync */
     121             :         NULL, 61, 1280, 1024, 9090, 200, 48, 26, 1, 184, 3,
     122             :         0, FB_VMODE_NONINTERLACED
     123             :     }, {
     124             :         /* 1400x1050 @ 60Hz, 63.9 kHz hsync */
     125             :         NULL, 60, 1400, 1050, 9259, 136, 40, 13, 1, 112, 3,
     126             :         0, FB_VMODE_NONINTERLACED       
     127             :     }, {
     128             :         /* 1400x1050 @ 75,107 Hz, 82,392 kHz +hsync +vsync*/
     129             :         NULL, 75, 1400, 1050, 7190, 120, 56, 23, 10, 112, 13,
     130             :         FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
     131             :     }, {
     132             :         /* 1400x1050 @ 60 Hz, ? kHz +hsync +vsync*/
     133             :         NULL, 60, 1400, 1050, 9259, 128, 40, 12, 0, 112, 3,
     134             :         FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
     135             :     }, {
     136             :         /* 1024x768 @ 85 Hz, 70.24 kHz hsync */
     137             :         NULL, 85, 1024, 768, 10111, 192, 32, 34, 14, 160, 6,
     138             :         0, FB_VMODE_NONINTERLACED
     139             :     }, {
     140             :         /* 1152x864 @ 78 Hz, 70.8 kHz hsync */
     141             :         NULL, 78, 1152, 864, 9090, 228, 88, 32, 0, 84, 12,
     142             :         0, FB_VMODE_NONINTERLACED
     143             :     }, {
     144             :         /* 1280x1024 @ 70 Hz, 74.59 kHz hsync */
     145             :         NULL, 70, 1280, 1024, 7905, 224, 32, 28, 8, 160, 8,
     146             :         0, FB_VMODE_NONINTERLACED
     147             :     }, {
     148             :         /* 1600x1200 @ 60Hz, 75.00 kHz hsync */
     149             :         NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
     150             :         FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
     151             :     }, {
     152             :         /* 1152x864 @ 84 Hz, 76.0 kHz hsync */
     153             :         NULL, 84, 1152, 864, 7407, 184, 312, 32, 0, 128, 12,
     154             :         0, FB_VMODE_NONINTERLACED
     155             :     }, {
     156             :         /* 1280x1024 @ 74 Hz, 78.85 kHz hsync */
     157             :         NULL, 74, 1280, 1024, 7407, 256, 32, 34, 3, 144, 3,
     158             :         0, FB_VMODE_NONINTERLACED
     159             :     }, {
     160             :         /* 1024x768 @ 100Hz, 80.21 kHz hsync */
     161             :         NULL, 100, 1024, 768, 8658, 192, 32, 21, 3, 192, 10,
     162             :         0, FB_VMODE_NONINTERLACED
     163             :     }, {
     164             :         /* 1280x1024 @ 76 Hz, 81.13 kHz hsync */
     165             :         NULL, 76, 1280, 1024, 7407, 248, 32, 34, 3, 104, 3,
     166             :         0, FB_VMODE_NONINTERLACED
     167             :     }, {
     168             :         /* 1600x1200 @ 70 Hz, 87.50 kHz hsync */
     169             :         NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3,
     170             :         0, FB_VMODE_NONINTERLACED
     171             :     }, {
     172             :         /* 1152x864 @ 100 Hz, 89.62 kHz hsync */
     173             :         NULL, 100, 1152, 864, 7264, 224, 32, 17, 2, 128, 19,
     174             :         0, FB_VMODE_NONINTERLACED
     175             :     }, {
     176             :         /* 1280x1024 @ 85 Hz, 91.15 kHz hsync */
     177             :         NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
     178             :         FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
     179             :     }, {
     180             :         /* 1600x1200 @ 75 Hz, 93.75 kHz hsync */
     181             :         NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
     182             :         FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
     183             :     }, {
     184             :         /* 1680x1050 @ 60 Hz, 65.191 kHz hsync */
     185             :         NULL, 60, 1680, 1050, 6848, 280, 104, 30, 3, 176, 6,
     186             :         FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
     187             :     }, {
     188             :         /* 1600x1200 @ 85 Hz, 105.77 kHz hsync */
     189             :         NULL, 85, 1600, 1200, 4545, 272, 16, 37, 4, 192, 3,
     190             :         FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
     191             :     }, {
     192             :         /* 1280x1024 @ 100 Hz, 107.16 kHz hsync */
     193             :         NULL, 100, 1280, 1024, 5502, 256, 32, 26, 7, 128, 15,
     194             :         0, FB_VMODE_NONINTERLACED
     195             :     }, {
     196             :         /* 1800x1440 @ 64Hz, 96.15 kHz hsync  */
     197             :         NULL, 64, 1800, 1440, 4347, 304, 96, 46, 1, 192, 3,
     198             :         FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
     199             :     }, {
     200             :         /* 1800x1440 @ 70Hz, 104.52 kHz hsync  */
     201             :         NULL, 70, 1800, 1440, 4000, 304, 96, 46, 1, 192, 3,
     202             :         FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
     203             :     }, {
     204             :         /* 512x384 @ 78 Hz, 31.50 kHz hsync */
     205             :         NULL, 78, 512, 384, 49603, 48, 16, 16, 1, 64, 3,
     206             :         0, FB_VMODE_NONINTERLACED
     207             :     }, {
     208             :         /* 512x384 @ 85 Hz, 34.38 kHz hsync */
     209             :         NULL, 85, 512, 384, 45454, 48, 16, 16, 1, 64, 3,
     210             :         0, FB_VMODE_NONINTERLACED
     211             :     }, {
     212             :         /* 320x200 @ 70 Hz, 31.5 kHz hsync, 8:5 aspect ratio */
     213             :         NULL, 70, 320, 200, 79440, 16, 16, 20, 4, 48, 1,
     214             :         0, FB_VMODE_DOUBLE
     215             :     }, {
     216             :         /* 320x240 @ 60 Hz, 31.5 kHz hsync, 4:3 aspect ratio */
     217             :         NULL, 60, 320, 240, 79440, 16, 16, 16, 5, 48, 1,
     218             :         0, FB_VMODE_DOUBLE
     219             :     }, {
     220             :         /* 320x240 @ 72 Hz, 36.5 kHz hsync */
     221             :         NULL, 72, 320, 240, 63492, 16, 16, 16, 4, 48, 2,
     222             :         0, FB_VMODE_DOUBLE
     223             :     }, {
     224             :         /* 400x300 @ 56 Hz, 35.2 kHz hsync, 4:3 aspect ratio */
     225             :         NULL, 56, 400, 300, 55555, 64, 16, 10, 1, 32, 1,
     226             :         0, FB_VMODE_DOUBLE
     227             :     }, {
     228             :         /* 400x300 @ 60 Hz, 37.8 kHz hsync */
     229             :         NULL, 60, 400, 300, 50000, 48, 16, 11, 1, 64, 2,
     230             :         0, FB_VMODE_DOUBLE
     231             :     }, {
     232             :         /* 400x300 @ 72 Hz, 48.0 kHz hsync */
     233             :         NULL, 72, 400, 300, 40000, 32, 24, 11, 19, 64, 3,
     234             :         0, FB_VMODE_DOUBLE
     235             :     }, {
     236             :         /* 480x300 @ 56 Hz, 35.2 kHz hsync, 8:5 aspect ratio */
     237             :         NULL, 56, 480, 300, 46176, 80, 16, 10, 1, 40, 1,
     238             :         0, FB_VMODE_DOUBLE
     239             :     }, {
     240             :         /* 480x300 @ 60 Hz, 37.8 kHz hsync */
     241             :         NULL, 60, 480, 300, 41858, 56, 16, 11, 1, 80, 2,
     242             :         0, FB_VMODE_DOUBLE
     243             :     }, {
     244             :         /* 480x300 @ 63 Hz, 39.6 kHz hsync */
     245             :         NULL, 63, 480, 300, 40000, 56, 16, 11, 1, 80, 2,
     246             :         0, FB_VMODE_DOUBLE
     247             :     }, {
     248             :         /* 480x300 @ 72 Hz, 48.0 kHz hsync */
     249             :         NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3,
     250             :         0, FB_VMODE_DOUBLE
     251             :     }, {
     252             :         /* 1920x1200 @ 60 Hz, 74.5 Khz hsync */
     253             :         NULL, 60, 1920, 1200, 5177, 128, 336, 1, 38, 208, 3,
     254             :         FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
     255             :         FB_VMODE_NONINTERLACED
     256             :     }, {
     257             :         /* 1152x768, 60 Hz, PowerBook G4 Titanium I and II */
     258             :         NULL, 60, 1152, 768, 14047, 158, 26, 29, 3, 136, 6,
     259             :         FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
     260             :     }, {
     261             :         /* 1366x768, 60 Hz, 47.403 kHz hsync, WXGA 16:9 aspect ratio */
     262             :         NULL, 60, 1366, 768, 13806, 120, 10, 14, 3, 32, 5,
     263             :         0, FB_VMODE_NONINTERLACED
     264             :    }, {
     265             :         /* 1280x800, 60 Hz, 47.403 kHz hsync, WXGA 16:10 aspect ratio */
     266             :         NULL, 60, 1280, 800, 12048, 200, 64, 24, 1, 136, 3,
     267             :         0, FB_VMODE_NONINTERLACED
     268             :     }, {
     269             :        /* 720x576i @ 50 Hz, 15.625 kHz hsync (PAL RGB) */
     270             :        NULL, 50, 720, 576, 74074, 64, 16, 39, 5, 64, 5,
     271             :        0, FB_VMODE_INTERLACED
     272             :     }, {
     273             :        /* 800x520i @ 50 Hz, 15.625 kHz hsync (PAL RGB) */
     274             :        NULL, 50, 800, 520, 58823, 144, 64, 72, 28, 80, 5,
     275             :        0, FB_VMODE_INTERLACED
     276             :     },
     277             : };
     278             : 
     279             : #ifdef CONFIG_FB_MODE_HELPERS
     280           1 : const struct fb_videomode vesa_modes[] = {
     281             :         /* 0 640x350-85 VESA */
     282             :         { NULL, 85, 640, 350, 31746,  96, 32, 60, 32, 64, 3,
     283             :           FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
     284             :         /* 1 640x400-85 VESA */
     285             :         { NULL, 85, 640, 400, 31746,  96, 32, 41, 01, 64, 3,
     286             :           FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     287             :         /* 2 720x400-85 VESA */
     288             :         { NULL, 85, 721, 400, 28169, 108, 36, 42, 01, 72, 3,
     289             :           FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     290             :         /* 3 640x480-60 VESA */
     291             :         { NULL, 60, 640, 480, 39682,  48, 16, 33, 10, 96, 2, 
     292             :           0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     293             :         /* 4 640x480-72 VESA */
     294             :         { NULL, 72, 640, 480, 31746, 128, 24, 29, 9, 40, 2, 
     295             :           0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     296             :         /* 5 640x480-75 VESA */
     297             :         { NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
     298             :           0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     299             :         /* 6 640x480-85 VESA */
     300             :         { NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3,
     301             :           0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     302             :         /* 7 800x600-56 VESA */
     303             :         { NULL, 56, 800, 600, 27777, 128, 24, 22, 01, 72, 2,
     304             :           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
     305             :           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     306             :         /* 8 800x600-60 VESA */
     307             :         { NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4,
     308             :           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
     309             :           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     310             :         /* 9 800x600-72 VESA */
     311             :         { NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
     312             :           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
     313             :           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     314             :         /* 10 800x600-75 VESA */
     315             :         { NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3,
     316             :           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
     317             :           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     318             :         /* 11 800x600-85 VESA */
     319             :         { NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3,
     320             :           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
     321             :           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     322             :         /* 12 1024x768i-43 VESA */
     323             :         { NULL, 43, 1024, 768, 22271, 56, 8, 41, 0, 176, 8,
     324             :           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
     325             :           FB_VMODE_INTERLACED, FB_MODE_IS_VESA },
     326             :         /* 13 1024x768-60 VESA */
     327             :         { NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6,
     328             :           0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     329             :         /* 14 1024x768-70 VESA */
     330             :         { NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6,
     331             :           0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     332             :         /* 15 1024x768-75 VESA */
     333             :         { NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
     334             :           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
     335             :           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     336             :         /* 16 1024x768-85 VESA */
     337             :         { NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
     338             :           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
     339             :           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     340             :         /* 17 1152x864-75 VESA */
     341             :         { NULL, 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3,
     342             :           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
     343             :           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     344             :         /* 18 1280x960-60 VESA */
     345             :         { NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
     346             :           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
     347             :           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     348             :         /* 19 1280x960-85 VESA */
     349             :         { NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
     350             :           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
     351             :           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     352             :         /* 20 1280x1024-60 VESA */
     353             :         { NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
     354             :           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
     355             :           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     356             :         /* 21 1280x1024-75 VESA */
     357             :         { NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
     358             :           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
     359             :           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     360             :         /* 22 1280x1024-85 VESA */
     361             :         { NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
     362             :           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
     363             :           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     364             :         /* 23 1600x1200-60 VESA */
     365             :         { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
     366             :           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
     367             :           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     368             :         /* 24 1600x1200-65 VESA */
     369             :         { NULL, 65, 1600, 1200, 5698, 304,  64, 46, 1, 192, 3,
     370             :           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
     371             :           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     372             :         /* 25 1600x1200-70 VESA */
     373             :         { NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3,
     374             :           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
     375             :           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     376             :         /* 26 1600x1200-75 VESA */
     377             :         { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, 
     378             :           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
     379             :           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     380             :         /* 27 1600x1200-85 VESA */
     381             :         { NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
     382             :           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
     383             :           FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     384             :         /* 28 1792x1344-60 VESA */
     385             :         { NULL, 60, 1792, 1344, 4882, 328, 128, 46, 1, 200, 3,
     386             :           FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     387             :         /* 29 1792x1344-75 VESA */
     388             :         { NULL, 75, 1792, 1344, 3831, 352, 96, 69, 1, 216, 3,
     389             :           FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     390             :         /* 30 1856x1392-60 VESA */
     391             :         { NULL, 60, 1856, 1392, 4580, 352, 96, 43, 1, 224, 3,
     392             :           FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     393             :         /* 31 1856x1392-75 VESA */
     394             :         { NULL, 75, 1856, 1392, 3472, 352, 128, 104, 1, 224, 3,
     395             :           FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     396             :         /* 32 1920x1440-60 VESA */
     397             :         { NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 200, 3,
     398             :           FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     399             :         /* 33 1920x1440-75 VESA */
     400             :         { NULL, 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3,
     401             :           FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
     402             : };
     403             : EXPORT_SYMBOL(vesa_modes);
     404             : #endif /* CONFIG_FB_MODE_HELPERS */
     405             : 
     406             : /**
     407             :  *      fb_try_mode - test a video mode
     408             :  *      @var: frame buffer user defined part of display
     409             :  *      @info: frame buffer info structure
     410             :  *      @mode: frame buffer video mode structure
     411             :  *      @bpp: color depth in bits per pixel
     412             :  *
     413             :  *      Tries a video mode to test it's validity for device @info.
     414             :  *
     415             :  *      Returns 1 on success.
     416             :  *
     417             :  */
     418             : 
     419             : static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
     420             :                        const struct fb_videomode *mode, unsigned int bpp)
     421             : {
     422           0 :     int err = 0;
     423             : 
     424             :     DPRINTK("Trying mode %s %dx%d-%d@%d\n", mode->name ? mode->name : "noname",
     425             :             mode->xres, mode->yres, bpp, mode->refresh);
     426           0 :     var->xres = mode->xres;
     427           0 :     var->yres = mode->yres;
     428           0 :     var->xres_virtual = mode->xres;
     429           0 :     var->yres_virtual = mode->yres;
     430           0 :     var->xoffset = 0;
     431           0 :     var->yoffset = 0;
     432           0 :     var->bits_per_pixel = bpp;
     433           0 :     var->activate |= FB_ACTIVATE_TEST;
     434           0 :     var->pixclock = mode->pixclock;
     435           0 :     var->left_margin = mode->left_margin;
     436           0 :     var->right_margin = mode->right_margin;
     437           0 :     var->upper_margin = mode->upper_margin;
     438           0 :     var->lower_margin = mode->lower_margin;
     439           0 :     var->hsync_len = mode->hsync_len;
     440           0 :     var->vsync_len = mode->vsync_len;
     441           0 :     var->sync = mode->sync;
     442           0 :     var->vmode = mode->vmode;
     443           0 :     if (info->fbops->fb_check_var)
     444           0 :         err = info->fbops->fb_check_var(var, info);
     445           0 :     var->activate &= ~FB_ACTIVATE_TEST;
     446           0 :     return err;
     447             : }
     448             : 
     449             : /**
     450             :  *      fb_find_mode - finds a valid video mode
     451             :  *      @var: frame buffer user defined part of display
     452             :  *      @info: frame buffer info structure
     453             :  *      @mode_option: string video mode to find
     454             :  *      @db: video mode database
     455             :  *      @dbsize: size of @db
     456             :  *      @default_mode: default video mode to fall back to
     457             :  *      @default_bpp: default color depth in bits per pixel
     458             :  *
     459             :  *      Finds a suitable video mode, starting with the specified mode
     460             :  *      in @mode_option with fallback to @default_mode.  If
     461             :  *      @default_mode fails, all modes in the video mode database will
     462             :  *      be tried.
     463             :  *
     464             :  *      Valid mode specifiers for @mode_option:
     465             :  *
     466             :  *      <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m] or
     467             :  *      <name>[-<bpp>][@<refresh>]
     468             :  *
     469             :  *      with <xres>, <yres>, <bpp> and <refresh> decimal numbers and
     470             :  *      <name> a string.
     471             :  *
     472             :  *      If 'M' is present after yres (and before refresh/bpp if present),
     473             :  *      the function will compute the timings using VESA(tm) Coordinated
     474             :  *      Video Timings (CVT).  If 'R' is present after 'M', will compute with
     475             :  *      reduced blanking (for flatpanels).  If 'i' is present, compute
     476             :  *      interlaced mode.  If 'm' is present, add margins equal to 1.8%
     477             :  *      of xres rounded down to 8 pixels, and 1.8% of yres. The char
     478             :  *      'i' and 'm' must be after 'M' and 'R'. Example:
     479             :  *
     480             :  *      1024x768MR-8@60m - Reduced blank with margins at 60Hz.
     481             :  *
     482             :  *      NOTE: The passed struct @var is _not_ cleared!  This allows you
     483             :  *      to supply values for e.g. the grayscale and accel_flags fields.
     484             :  *
     485             :  *      Returns zero for failure, 1 if using specified @mode_option,
     486             :  *      2 if using specified @mode_option with an ignored refresh rate,
     487             :  *      3 if default mode is used, 4 if fall back to any valid mode.
     488             :  *
     489             :  */
     490             : 
     491             : int fb_find_mode(struct fb_var_screeninfo *var,
     492             :                  struct fb_info *info, const char *mode_option,
     493             :                  const struct fb_videomode *db, unsigned int dbsize,
     494             :                  const struct fb_videomode *default_mode,
     495           0 :                  unsigned int default_bpp)
     496           0 : {
     497           0 :     int i;
     498           0 : 
     499           0 :     /* Set up defaults */
     500           0 :     if (!db) {
     501           0 :         db = modedb;
     502           0 :         dbsize = ARRAY_SIZE(modedb);
     503           0 :     }
     504           0 : 
     505           0 :     if (!default_mode)
     506           0 :         default_mode = &db[0];
     507           0 : 
     508           0 :     if (!default_bpp)
     509           0 :         default_bpp = 8;
     510           0 : 
     511           0 :     /* Did the user specify a video mode? */
     512           0 :     if (!mode_option)
     513           0 :         mode_option = fb_mode_option;
     514           0 :     if (mode_option) {
     515           0 :         const char *name = mode_option;
     516           0 :         unsigned int namelen = strlen(name);
     517           0 :         int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
     518           0 :         unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0;
     519           0 :         int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0;
     520           0 :         u32 best, diff, tdiff;
     521           0 : 
     522           0 :         for (i = namelen-1; i >= 0; i--) {
     523           0 :             switch (name[i]) {
     524           0 :                 case '@':
     525           0 :                     namelen = i;
     526           0 :                     if (!refresh_specified && !bpp_specified &&
     527           0 :                         !yres_specified) {
     528           0 :                         refresh = simple_strtol(&name[i+1], NULL, 10);
     529           0 :                         refresh_specified = 1;
     530           0 :                         if (cvt || rb)
     531           0 :                             cvt = 0;
     532             :                     } else
     533           0 :                         goto done;
     534           0 :                     break;
     535           0 :                 case '-':
     536           0 :                     namelen = i;
     537           0 :                     if (!bpp_specified && !yres_specified) {
     538           0 :                         bpp = simple_strtol(&name[i+1], NULL, 10);
     539           0 :                         bpp_specified = 1;
     540           0 :                         if (cvt || rb)
     541           0 :                             cvt = 0;
     542             :                     } else
     543           0 :                         goto done;
     544           0 :                     break;
     545           0 :                 case 'x':
     546           0 :                     if (!yres_specified) {
     547           0 :                         yres = simple_strtol(&name[i+1], NULL, 10);
     548           0 :                         yres_specified = 1;
     549             :                     } else
     550           0 :                         goto done;
     551           0 :                     break;
     552           0 :                 case '0' ... '9':
     553           0 :                     break;
     554           0 :                 case 'M':
     555           0 :                     if (!yres_specified)
     556           0 :                         cvt = 1;
     557           0 :                     break;
     558           0 :                 case 'R':
     559           0 :                     if (!cvt)
     560           0 :                         rb = 1;
     561           0 :                     break;
     562           0 :                 case 'm':
     563           0 :                     if (!cvt)
     564           0 :                         margins = 1;
     565           0 :                     break;
     566           0 :                 case 'i':
     567           0 :                     if (!cvt)
     568           0 :                         interlace = 1;
     569           0 :                     break;
     570           0 :                 default:
     571           0 :                     goto done;
     572             :             }
     573             :         }
     574           0 :         if (i < 0 && yres_specified) {
     575           0 :             xres = simple_strtol(name, NULL, 10);
     576           0 :             res_specified = 1;
     577             :         }
     578             : done:
     579           0 :         if (cvt) {
     580             :             struct fb_videomode cvt_mode;
     581           0 :             int ret;
     582             : 
     583             :             DPRINTK("CVT mode %dx%d@%dHz%s%s%s\n", xres, yres,
     584             :                     (refresh) ? refresh : 60, (rb) ? " reduced blanking" :
     585             :                     "", (margins) ? " with margins" : "", (interlace) ?
     586             :                     " interlaced" : "");
     587             : 
     588           0 :             memset(&cvt_mode, 0, sizeof(cvt_mode));
     589           0 :             cvt_mode.xres = xres;
     590           0 :             cvt_mode.yres = yres;
     591           0 :             cvt_mode.refresh = (refresh) ? refresh : 60;
     592             : 
     593           0 :             if (interlace)
     594           0 :                 cvt_mode.vmode |= FB_VMODE_INTERLACED;
     595             :             else
     596           0 :                 cvt_mode.vmode &= ~FB_VMODE_INTERLACED;
     597             : 
     598           0 :             ret = fb_find_mode_cvt(&cvt_mode, margins, rb);
     599             : 
     600           0 :             if (!ret && !fb_try_mode(var, info, &cvt_mode, bpp)) {
     601             :                 DPRINTK("modedb CVT: CVT mode ok\n");
     602           0 :                 return 1;
     603             :             }
     604             : 
     605             :             DPRINTK("CVT mode invalid, getting mode from database\n");
     606             :         }
     607             : 
     608             :         DPRINTK("Trying specified video mode%s %ix%i\n",
     609             :             refresh_specified ? "" : " (ignoring refresh rate)", xres, yres);
     610             : 
     611           0 :         if (!refresh_specified) {
     612             :                 /*
     613             :                  * If the caller has provided a custom mode database and a
     614             :                  * valid monspecs structure, we look for the mode with the
     615             :                  * highest refresh rate.  Otherwise we play it safe it and
     616             :                  * try to find a mode with a refresh rate closest to the
     617             :                  * standard 60 Hz.
     618             :                  */
     619           0 :                 if (db != modedb &&
     620             :                     info->monspecs.vfmin && info->monspecs.vfmax &&
     621             :                     info->monspecs.hfmin && info->monspecs.hfmax &&
     622             :                     info->monspecs.dclkmax) {
     623           0 :                         refresh = 1000;
     624             :                 } else {
     625           0 :                         refresh = 60;
     626             :                 }
     627             :         }
     628             : 
     629           0 :         diff = -1;
     630           0 :         best = -1;
     631           0 :         for (i = 0; i < dbsize; i++) {
     632           0 :                 if ((name_matches(db[i], name, namelen) ||
     633           0 :                     (res_specified && res_matches(db[i], xres, yres))) &&
     634             :                     !fb_try_mode(var, info, &db[i], bpp)) {
     635           0 :                         if (refresh_specified && db[i].refresh == refresh) {
     636           0 :                                 return 1;
     637             :                         } else {
     638           0 :                                 if (abs(db[i].refresh - refresh) < diff) {
     639           0 :                                         diff = abs(db[i].refresh - refresh);
     640           0 :                                         best = i;
     641             :                                 }
     642             :                         }
     643             :                 }
     644             :         }
     645           0 :         if (best != -1) {
     646           0 :                 fb_try_mode(var, info, &db[best], bpp);
     647           0 :                 return (refresh_specified) ? 2 : 1;
     648             :         }
     649             : 
     650           0 :         diff = 2 * (xres + yres);
     651           0 :         best = -1;
     652             :         DPRINTK("Trying best-fit modes\n");
     653           0 :         for (i = 0; i < dbsize; i++) {
     654           0 :                 DPRINTK("Trying %ix%i\n", db[i].xres, db[i].yres);
     655           0 :                 if (!fb_try_mode(var, info, &db[i], bpp)) {
     656           0 :                         tdiff = abs(db[i].xres - xres) +
     657           0 :                                 abs(db[i].yres - yres);
     658             : 
     659             :                         /*
     660             :                          * Penalize modes with resolutions smaller
     661             :                          * than requested.
     662             :                          */
     663           0 :                         if (xres > db[i].xres || yres > db[i].yres)
     664           0 :                                 tdiff += xres + yres;
     665             : 
     666           0 :                         if (diff > tdiff) {
     667           0 :                                 diff = tdiff;
     668           0 :                                 best = i;
     669             :                         }
     670             :                 }
     671             :         }
     672           0 :         if (best != -1) {
     673           0 :             fb_try_mode(var, info, &db[best], bpp);
     674           0 :             return 5;
     675             :         }
     676             :     }
     677             : 
     678             :     DPRINTK("Trying default video mode\n");
     679           0 :     if (!fb_try_mode(var, info, default_mode, default_bpp))
     680           0 :         return 3;
     681             : 
     682             :     DPRINTK("Trying all modes\n");
     683           0 :     for (i = 0; i < dbsize; i++)
     684           0 :         if (!fb_try_mode(var, info, &db[i], default_bpp))
     685           0 :             return 4;
     686             : 
     687             :     DPRINTK("No valid mode found\n");
     688           0 :     return 0;
     689             : }
     690             : 
     691             : /**
     692             :  * fb_var_to_videomode - convert fb_var_screeninfo to fb_videomode
     693             :  * @mode: pointer to struct fb_videomode
     694             :  * @var: pointer to struct fb_var_screeninfo
     695             :  */
     696             : void fb_var_to_videomode(struct fb_videomode *mode,
     697             :                          const struct fb_var_screeninfo *var)
     698          37 : {
     699          37 :         u32 pixclock, hfreq, htotal, vtotal;
     700          37 : 
     701          74 :         mode->name = NULL;
     702          37 :         mode->xres = var->xres;
     703          37 :         mode->yres = var->yres;
     704          37 :         mode->pixclock = var->pixclock;
     705          37 :         mode->hsync_len = var->hsync_len;
     706          37 :         mode->vsync_len = var->vsync_len;
     707          37 :         mode->left_margin = var->left_margin;
     708          37 :         mode->right_margin = var->right_margin;
     709          37 :         mode->upper_margin = var->upper_margin;
     710          37 :         mode->lower_margin = var->lower_margin;
     711          37 :         mode->sync = var->sync;
     712          74 :         mode->vmode = var->vmode & FB_VMODE_MASK;
     713          37 :         mode->flag = FB_MODE_IS_FROM_VAR;
     714          37 :         mode->refresh = 0;
     715             : 
     716         111 :         if (!var->pixclock)
     717          37 :                 return;
     718             : 
     719          74 :         pixclock = PICOS2KHZ(var->pixclock) * 1000;
     720             : 
     721         185 :         htotal = var->xres + var->right_margin + var->hsync_len +
     722             :                 var->left_margin;
     723         185 :         vtotal = var->yres + var->lower_margin + var->vsync_len +
     724             :                 var->upper_margin;
     725             : 
     726         111 :         if (var->vmode & FB_VMODE_INTERLACED)
     727          37 :                 vtotal /= 2;
     728         111 :         if (var->vmode & FB_VMODE_DOUBLE)
     729          37 :                 vtotal *= 2;
     730             : 
     731          37 :         hfreq = pixclock/htotal;
     732          37 :         mode->refresh = hfreq/vtotal;
     733          37 : }
     734             : 
     735             : /**
     736             :  * fb_videomode_to_var - convert fb_videomode to fb_var_screeninfo
     737             :  * @var: pointer to struct fb_var_screeninfo
     738             :  * @mode: pointer to struct fb_videomode
     739             :  */
     740             : void fb_videomode_to_var(struct fb_var_screeninfo *var,
     741             :                          const struct fb_videomode *mode)
     742             : {
     743           2 :         var->xres = mode->xres;
     744           2 :         var->yres = mode->yres;
     745           2 :         var->xres_virtual = mode->xres;
     746           2 :         var->yres_virtual = mode->yres;
     747           2 :         var->xoffset = 0;
     748           2 :         var->yoffset = 0;
     749           2 :         var->pixclock = mode->pixclock;
     750           2 :         var->left_margin = mode->left_margin;
     751           2 :         var->right_margin = mode->right_margin;
     752           2 :         var->upper_margin = mode->upper_margin;
     753           2 :         var->lower_margin = mode->lower_margin;
     754           2 :         var->hsync_len = mode->hsync_len;
     755           2 :         var->vsync_len = mode->vsync_len;
     756           2 :         var->sync = mode->sync;
     757           4 :         var->vmode = mode->vmode & FB_VMODE_MASK;
     758           2 : }
     759             : 
     760             : /**
     761             :  * fb_mode_is_equal - compare 2 videomodes
     762             :  * @mode1: first videomode
     763             :  * @mode2: second videomode
     764             :  *
     765             :  * RETURNS:
     766             :  * 1 if equal, 0 if not
     767             :  */
     768             : int fb_mode_is_equal(const struct fb_videomode *mode1,
     769             :                      const struct fb_videomode *mode2)
     770             : {
     771         608 :         return (mode1->xres         == mode2->xres &&
     772             :                 mode1->yres         == mode2->yres &&
     773             :                 mode1->pixclock     == mode2->pixclock &&
     774             :                 mode1->hsync_len    == mode2->hsync_len &&
     775             :                 mode1->vsync_len    == mode2->vsync_len &&
     776             :                 mode1->left_margin  == mode2->left_margin &&
     777             :                 mode1->right_margin == mode2->right_margin &&
     778             :                 mode1->upper_margin == mode2->upper_margin &&
     779             :                 mode1->lower_margin == mode2->lower_margin &&
     780             :                 mode1->sync         == mode2->sync &&
     781             :                 mode1->vmode        == mode2->vmode);
     782             : }
     783             : 
     784             : /**
     785             :  * fb_find_best_mode - find best matching videomode
     786             :  * @var: pointer to struct fb_var_screeninfo
     787             :  * @head: pointer to struct list_head of modelist
     788             :  *
     789             :  * RETURNS:
     790             :  * struct fb_videomode, NULL if none found
     791             :  *
     792             :  * IMPORTANT:
     793             :  * This function assumes that all modelist entries in
     794             :  * info->modelist are valid.
     795             :  *
     796             :  * NOTES:
     797             :  * Finds best matching videomode which has an equal or greater dimension than
     798             :  * var->xres and var->yres.  If more than 1 videomode is found, will return
     799             :  * the videomode with the highest refresh rate
     800             :  */
     801             : const struct fb_videomode *fb_find_best_mode(const struct fb_var_screeninfo *var,
     802             :                                              struct list_head *head)
     803             : {
     804           0 :         struct list_head *pos;
     805           0 :         struct fb_modelist *modelist;
     806           0 :         struct fb_videomode *mode, *best = NULL;
     807           0 :         u32 diff = -1;
     808           0 : 
     809           0 :         list_for_each(pos, head) {
     810           0 :                 u32 d;
     811           0 : 
     812           0 :                 modelist = list_entry(pos, struct fb_modelist, list);
     813           0 :                 mode = &modelist->mode;
     814             : 
     815           0 :                 if (mode->xres >= var->xres && mode->yres >= var->yres) {
     816           0 :                         d = (mode->xres - var->xres) +
     817             :                                 (mode->yres - var->yres);
     818           0 :                         if (diff > d) {
     819           0 :                                 diff = d;
     820           0 :                                 best = mode;
     821           0 :                         } else if (diff == d && best &&
     822             :                                    mode->refresh > best->refresh)
     823           0 :                                 best = mode;
     824             :                 }
     825             :         }
     826           0 :         return best;
     827             : }
     828             : 
     829             : /**
     830             :  * fb_find_nearest_mode - find closest videomode
     831             :  *
     832             :  * @mode: pointer to struct fb_videomode
     833             :  * @head: pointer to modelist
     834             :  *
     835             :  * Finds best matching videomode, smaller or greater in dimension.
     836             :  * If more than 1 videomode is found, will return the videomode with
     837             :  * the closest refresh rate.
     838             :  */
     839             : const struct fb_videomode *fb_find_nearest_mode(const struct fb_videomode *mode,
     840             :                                                 struct list_head *head)
     841             : {
     842           0 :         struct list_head *pos;
     843           0 :         struct fb_modelist *modelist;
     844           0 :         struct fb_videomode *cmode, *best = NULL;
     845           0 :         u32 diff = -1, diff_refresh = -1;
     846           0 : 
     847           0 :         list_for_each(pos, head) {
     848           0 :                 u32 d;
     849           0 : 
     850           0 :                 modelist = list_entry(pos, struct fb_modelist, list);
     851           0 :                 cmode = &modelist->mode;
     852           0 : 
     853           0 :                 d = abs(cmode->xres - mode->xres) +
     854           0 :                         abs(cmode->yres - mode->yres);
     855           0 :                 if (diff > d) {
     856           0 :                         diff = d;
     857           0 :                         best = cmode;
     858           0 :                 } else if (diff == d) {
     859           0 :                         d = abs(cmode->refresh - mode->refresh);
     860           0 :                         if (diff_refresh > d) {
     861           0 :                                 diff_refresh = d;
     862           0 :                                 best = cmode;
     863             :                         }
     864             :                 }
     865             :         }
     866             : 
     867           0 :         return best;
     868             : }
     869             : 
     870             : /**
     871             :  * fb_match_mode - find a videomode which exactly matches the timings in var
     872             :  * @var: pointer to struct fb_var_screeninfo
     873             :  * @head: pointer to struct list_head of modelist
     874             :  *
     875             :  * RETURNS:
     876             :  * struct fb_videomode, NULL if none found
     877             :  */
     878             : const struct fb_videomode *fb_match_mode(const struct fb_var_screeninfo *var,
     879             :                                          struct list_head *head)
     880             : {
     881           0 :         struct list_head *pos;
     882           0 :         struct fb_modelist *modelist;
     883           0 :         struct fb_videomode *m, mode;
     884           0 : 
     885           0 :         fb_var_to_videomode(&mode, var);
     886           0 :         list_for_each(pos, head) {
     887           0 :                 modelist = list_entry(pos, struct fb_modelist, list);
     888           0 :                 m = &modelist->mode;
     889           0 :                 if (fb_mode_is_equal(m, &mode))
     890           0 :                         return m;
     891             :         }
     892           0 :         return NULL;
     893             : }
     894             : 
     895             : /**
     896             :  * fb_add_videomode: adds videomode entry to modelist
     897             :  * @mode: videomode to add
     898             :  * @head: struct list_head of modelist
     899             :  *
     900             :  * NOTES:
     901             :  * Will only add unmatched mode entries
     902             :  */
     903             : int fb_add_videomode(const struct fb_videomode *mode, struct list_head *head)
     904             : {
     905          13 :         struct list_head *pos;
     906          13 :         struct fb_modelist *modelist;
     907          13 :         struct fb_videomode *m;
     908          26 :         int found = 0;
     909          13 : 
     910         104 :         list_for_each(pos, head) {
     911          65 :                 modelist = list_entry(pos, struct fb_modelist, list);
     912          26 :                 m = &modelist->mode;
     913          52 :                 if (fb_mode_is_equal(m, mode)) {
     914          13 :                         found = 1;
     915          13 :                         break;
     916          13 :                 }
     917             :         }
     918          52 :         if (!found) {
     919          65 :                 modelist = kmalloc(sizeof(struct fb_modelist),
     920             :                                                   GFP_KERNEL);
     921             : 
     922          26 :                 if (!modelist)
     923          13 :                         return -ENOMEM;
     924          13 :                 modelist->mode = *mode;
     925          26 :                 list_add(&modelist->list, head);
     926             :         }
     927          39 :         return 0;
     928             : }
     929             : 
     930             : /**
     931             :  * fb_delete_videomode: removed videomode entry from modelist
     932             :  * @mode: videomode to remove
     933             :  * @head: struct list_head of modelist
     934             :  *
     935             :  * NOTES:
     936             :  * Will remove all matching mode entries
     937             :  */
     938             : void fb_delete_videomode(const struct fb_videomode *mode,
     939             :                          struct list_head *head)
     940          12 : {
     941          12 :         struct list_head *pos, *n;
     942          12 :         struct fb_modelist *modelist;
     943          12 :         struct fb_videomode *m;
     944          12 : 
     945         120 :         list_for_each_safe(pos, n, head) {
     946          60 :                 modelist = list_entry(pos, struct fb_modelist, list);
     947          24 :                 m = &modelist->mode;
     948          48 :                 if (fb_mode_is_equal(m, mode)) {
     949          24 :                         list_del(pos);
     950          12 :                         kfree(pos);
     951             :                 }
     952          12 :         }
     953             : }
     954             : 
     955             : /**
     956             :  * fb_destroy_modelist: destroy modelist
     957             :  * @head: struct list_head of modelist
     958             :  */
     959             : void fb_destroy_modelist(struct list_head *head)
     960             : {
     961           2 :         struct list_head *pos, *n;
     962           2 : 
     963          14 :         list_for_each_safe(pos, n, head) {
     964           6 :                 list_del(pos);
     965           6 :                 kfree(pos);
     966             :         }
     967             : }
     968             : EXPORT_SYMBOL_GPL(fb_destroy_modelist);
     969             : 
     970           2 : /**
     971             :  * fb_videomode_to_modelist: convert mode array to mode list
     972             :  * @modedb: array of struct fb_videomode
     973             :  * @num: number of entries in array
     974             :  * @head: struct list_head of modelist
     975             :  */
     976             : void fb_videomode_to_modelist(const struct fb_videomode *modedb, int num,
     977             :                               struct list_head *head)
     978             : {
     979           1 :         int i;
     980           1 : 
     981           2 :         INIT_LIST_HEAD(head);
     982             : 
     983           5 :         for (i = 0; i < num; i++) {
     984           9 :                 if (fb_add_videomode(&modedb[i], head))
     985           2 :                         return;
     986             :         }
     987             : }
     988             : 
     989             : const struct fb_videomode *fb_find_best_display(const struct fb_monspecs *specs,
     990           1 :                                                 struct list_head *head)
     991             : {
     992           0 :         struct list_head *pos;
     993           0 :         struct fb_modelist *modelist;
     994           0 :         const struct fb_videomode *m, *m1 = NULL, *md = NULL, *best = NULL;
     995           0 :         int first = 0;
     996           0 : 
     997           0 :         if (!head->prev || !head->next || list_empty(head))
     998           0 :                 goto finished;
     999           0 : 
    1000           0 :         /* get the first detailed mode and the very first mode */
    1001           0 :         list_for_each(pos, head) {
    1002           0 :                 modelist = list_entry(pos, struct fb_modelist, list);
    1003           0 :                 m = &modelist->mode;
    1004             : 
    1005           0 :                 if (!first) {
    1006           0 :                         m1 = m;
    1007           0 :                         first = 1;
    1008             :                 }
    1009             : 
    1010           0 :                 if (m->flag & FB_MODE_IS_FIRST) {
    1011           0 :                         md = m;
    1012           0 :                         break;
    1013             :                 }
    1014             :         }
    1015             : 
    1016             :         /* first detailed timing is preferred */
    1017           0 :         if (specs->misc & FB_MISC_1ST_DETAIL) {
    1018           0 :                 best = md;
    1019           0 :                 goto finished;
    1020             :         }
    1021             : 
    1022             :         /* find best mode based on display width and height */
    1023           0 :         if (specs->max_x && specs->max_y) {
    1024             :                 struct fb_var_screeninfo var;
    1025             : 
    1026           0 :                 memset(&var, 0, sizeof(struct fb_var_screeninfo));
    1027           0 :                 var.xres = (specs->max_x * 7200)/254;
    1028           0 :                 var.yres = (specs->max_y * 7200)/254;
    1029           0 :                 m = fb_find_best_mode(&var, head);
    1030           0 :                 if (m) {
    1031           0 :                         best = m;
    1032           0 :                         goto finished;
    1033             :                 }
    1034             :         }
    1035             : 
    1036             :         /* use first detailed mode */
    1037           0 :         if (md) {
    1038           0 :                 best = md;
    1039           0 :                 goto finished;
    1040             :         }
    1041             : 
    1042             :         /* last resort, use the very first mode */
    1043           0 :         best = m1;
    1044           0 : finished:
    1045           0 :         return best;
    1046             : }
    1047             : EXPORT_SYMBOL(fb_find_best_display);
    1048             : 
    1049             : EXPORT_SYMBOL(fb_videomode_to_var);
    1050             : EXPORT_SYMBOL(fb_var_to_videomode);
    1051             : EXPORT_SYMBOL(fb_mode_is_equal);
    1052             : EXPORT_SYMBOL(fb_add_videomode);
    1053             : EXPORT_SYMBOL(fb_match_mode);
    1054             : EXPORT_SYMBOL(fb_find_best_mode);
    1055             : EXPORT_SYMBOL(fb_find_nearest_mode);
    1056             : EXPORT_SYMBOL(fb_videomode_to_modelist);
    1057             : EXPORT_SYMBOL(fb_find_mode);

Generated by: LCOV version 1.10