Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  *  linux/drivers/video/macmodes.c -- Standard MacOS video modes
0003  *
0004  *  Copyright (C) 1998 Geert Uytterhoeven
0005  *
0006  *      2000 - Removal of OpenFirmware dependencies by:
0007  *      - Ani Joshi
0008  *      - Brad Douglas <brad@neruo.com>
0009  *
0010  *  2001 - Documented with DocBook
0011  *  - Brad Douglas <brad@neruo.com>
0012  *
0013  *  This file is subject to the terms and conditions of the GNU General Public
0014  *  License. See the file COPYING in the main directory of this archive for
0015  *  more details.
0016  */
0017 
0018 #include <linux/errno.h>
0019 #include <linux/fb.h>
0020 #include <linux/string.h>
0021 #include <linux/module.h>
0022 
0023 #include "macmodes.h"
0024 
0025     /*
0026      *  MacOS video mode definitions
0027      *
0028      *  Order IS important! If you change these, don't forget to update
0029      *  mac_modes[] below!
0030      */
0031 
0032 #define DEFAULT_MODEDB_INDEX    0
0033 
0034 static const struct fb_videomode mac_modedb[] = {
0035     {
0036     /* 512x384, 60Hz, Non-Interlaced (15.67 MHz dot clock) */
0037     "mac2", 60, 512, 384, 63828, 80, 16, 19, 1, 32, 3,
0038     0, FB_VMODE_NONINTERLACED
0039     }, {
0040     /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
0041     "mac5", 60, 640, 480, 39722, 32, 32, 33, 10, 96, 2,
0042     0, FB_VMODE_NONINTERLACED
0043     }, {
0044     /* 640x480, 67Hz, Non-Interlaced (30.0 MHz dotclock) */
0045     "mac6", 67, 640, 480, 33334, 80, 80, 39, 3, 64, 3,
0046     0, FB_VMODE_NONINTERLACED
0047     }, {
0048     /* 640x870, 75Hz (portrait), Non-Interlaced (57.28 MHz dot clock) */
0049     "mac7", 75, 640, 870, 17457, 80, 32, 42, 3, 80, 3,
0050     0, FB_VMODE_NONINTERLACED
0051     }, {
0052     /* 800x600, 56 Hz, Non-Interlaced (36.00 MHz dotclock) */
0053     "mac9", 56, 800, 600, 27778, 112, 40, 22, 1, 72, 2,
0054     FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
0055     }, {
0056     /* 800x600, 60 Hz, Non-Interlaced (40.00 MHz dotclock) */
0057     "mac10", 60, 800, 600, 25000, 72, 56, 23, 1, 128, 4,
0058     FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
0059     }, {
0060     /* 800x600, 72 Hz, Non-Interlaced (50.00 MHz dotclock) */
0061     "mac11", 72, 800, 600, 20000, 48, 72, 23, 37, 120, 6,
0062     FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
0063     }, {
0064     /* 800x600, 75 Hz, Non-Interlaced (49.50 MHz dotclock) */
0065     "mac12", 75, 800, 600, 20203, 144, 32, 21, 1, 80, 3,
0066     FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
0067     }, {
0068     /* 832x624, 75Hz, Non-Interlaced (57.6 MHz dotclock) */
0069     "mac13", 75, 832, 624, 17362, 208, 48, 39, 1, 64, 3,
0070     0, FB_VMODE_NONINTERLACED
0071     }, {
0072     /* 1024x768, 60 Hz, Non-Interlaced (65.00 MHz dotclock) */
0073     "mac14", 60, 1024, 768, 15385, 144, 40, 29, 3, 136, 6,
0074     0, FB_VMODE_NONINTERLACED
0075     }, {
0076     /* 1024x768, 72 Hz, Non-Interlaced (75.00 MHz dotclock) */
0077     "mac15", 72, 1024, 768, 13334, 128, 40, 29, 3, 136, 6,
0078     0, FB_VMODE_NONINTERLACED
0079     }, {
0080     /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
0081     "mac16", 75, 1024, 768, 12699, 176, 16, 28, 1, 96, 3,
0082     FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
0083     }, {
0084     /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
0085     "mac17", 75, 1024, 768, 12699, 160, 32, 28, 1, 96, 3,
0086     FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
0087     }, {
0088     /* 1152x870, 75 Hz, Non-Interlaced (100.0 MHz dotclock) */
0089     "mac18", 75, 1152, 870, 10000, 128, 48, 39, 3, 128, 3,
0090     FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
0091     }, {
0092     /* 1280x960, 75 Hz, Non-Interlaced (126.00 MHz dotclock) */
0093     "mac19", 75, 1280, 960, 7937, 224, 32, 36, 1, 144, 3,
0094     0, FB_VMODE_NONINTERLACED
0095     }, {
0096     /* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */
0097     "mac20", 75, 1280, 1024, 7408, 232, 64, 38, 1, 112, 3,
0098     FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
0099     }, {
0100     /* 1152x768, 60 Hz, Titanium PowerBook */
0101     "mac21", 60, 1152, 768, 15386, 158, 26, 29, 3, 136, 6,
0102     FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
0103     }, {
0104     /* 1600x1024, 60 Hz, Non-Interlaced (112.27 MHz dotclock) */
0105     "mac22", 60, 1600, 1024, 8908, 88, 104, 1, 10, 16, 1,
0106     FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
0107     }
0108 
0109 #if 0
0110     /* Anyone who has timings for these? */
0111     {
0112     /* VMODE_512_384_60I: 512x384, 60Hz, Interlaced (NTSC) */
0113     "mac1", 60, 512, 384, pixclock, left, right, upper, lower, hslen, vslen,
0114     sync, FB_VMODE_INTERLACED
0115     }, {
0116     /* VMODE_640_480_50I: 640x480, 50Hz, Interlaced (PAL) */
0117     "mac3", 50, 640, 480, pixclock, left, right, upper, lower, hslen, vslen,
0118     sync, FB_VMODE_INTERLACED
0119     }, {
0120     /* VMODE_640_480_60I: 640x480, 60Hz, Interlaced (NTSC) */
0121     "mac4", 60, 640, 480, pixclock, left, right, upper, lower, hslen, vslen,
0122     sync, FB_VMODE_INTERLACED
0123     }, {
0124     /* VMODE_768_576_50I: 768x576, 50Hz (PAL full frame), Interlaced */
0125     "mac8", 50, 768, 576, pixclock, left, right, upper, lower, hslen, vslen,
0126     sync, FB_VMODE_INTERLACED
0127     },
0128 #endif
0129 };
0130 
0131 
0132     /*
0133      *  Mapping between MacOS video mode numbers and video mode definitions
0134      *
0135      *  These MUST be ordered in
0136      *    - increasing resolution
0137      *    - decreasing pixel clock period
0138      */
0139 
0140 static const struct mode_map {
0141     int vmode;
0142     const struct fb_videomode *mode;
0143 } mac_modes[] = {
0144     /* 512x384 */
0145     { VMODE_512_384_60, &mac_modedb[0] },
0146     /* 640x480 */
0147     { VMODE_640_480_60, &mac_modedb[1] },
0148     { VMODE_640_480_67, &mac_modedb[2] },
0149     /* 640x870 */
0150     { VMODE_640_870_75P, &mac_modedb[3] },
0151     /* 800x600 */
0152     { VMODE_800_600_56, &mac_modedb[4] },
0153     { VMODE_800_600_60, &mac_modedb[5] },
0154     { VMODE_800_600_75, &mac_modedb[7] },
0155     { VMODE_800_600_72, &mac_modedb[6] },
0156     /* 832x624 */
0157     { VMODE_832_624_75, &mac_modedb[8] },
0158     /* 1024x768 */
0159     { VMODE_1024_768_60, &mac_modedb[9] },
0160     { VMODE_1024_768_70, &mac_modedb[10] },
0161     { VMODE_1024_768_75V, &mac_modedb[11] },
0162     { VMODE_1024_768_75, &mac_modedb[12] },
0163     /* 1152x768 */
0164     { VMODE_1152_768_60, &mac_modedb[16] },
0165     /* 1152x870 */
0166     { VMODE_1152_870_75, &mac_modedb[13] },
0167     /* 1280x960 */
0168     { VMODE_1280_960_75, &mac_modedb[14] },
0169     /* 1280x1024 */
0170     { VMODE_1280_1024_75, &mac_modedb[15] },
0171     /* 1600x1024 */
0172     { VMODE_1600_1024_60, &mac_modedb[17] },
0173     { -1, NULL }
0174 };
0175 
0176 
0177     /*
0178      *  Mapping between monitor sense values and MacOS video mode numbers
0179      */
0180 
0181 static const struct monitor_map {
0182     int sense;
0183     int vmode;
0184 } mac_monitors[] = {
0185     { 0x000, VMODE_1280_1024_75 },  /* 21" RGB */
0186     { 0x114, VMODE_640_870_75P },   /* Portrait Monochrome */
0187     { 0x221, VMODE_512_384_60 },    /* 12" RGB*/
0188     { 0x331, VMODE_1280_1024_75 },  /* 21" RGB (Radius) */
0189     { 0x334, VMODE_1280_1024_75 },  /* 21" mono (Radius) */
0190     { 0x335, VMODE_1280_1024_75 },  /* 21" mono */
0191     { 0x40A, VMODE_640_480_60I },   /* NTSC */
0192     { 0x51E, VMODE_640_870_75P },   /* Portrait RGB */
0193     { 0x603, VMODE_832_624_75 },    /* 12"-16" multiscan */
0194     { 0x60b, VMODE_1024_768_70 },   /* 13"-19" multiscan */
0195     { 0x623, VMODE_1152_870_75 },   /* 13"-21" multiscan */
0196     { 0x62b, VMODE_640_480_67 },    /* 13"/14" RGB */
0197     { 0x700, VMODE_640_480_50I },   /* PAL */
0198     { 0x714, VMODE_640_480_60I },   /* NTSC */
0199     { 0x717, VMODE_800_600_75 },    /* VGA */
0200     { 0x72d, VMODE_832_624_75 },    /* 16" RGB (Goldfish) */
0201     { 0x730, VMODE_768_576_50I },   /* PAL (Alternate) */
0202     { 0x73a, VMODE_1152_870_75 },   /* 3rd party 19" */
0203     { 0x73f, VMODE_640_480_67 },    /* no sense lines connected at all */
0204     { 0xBEEF, VMODE_1600_1024_60 }, /* 22" Apple Cinema Display */
0205     { -1,    VMODE_640_480_60 },    /* catch-all, must be last */
0206 };
0207 
0208 /**
0209  *  mac_vmode_to_var - converts vmode/cmode pair to var structure
0210  *  @vmode: MacOS video mode
0211  *  @cmode: MacOS color mode
0212  *  @var: frame buffer video mode structure
0213  *
0214  *  Converts a MacOS vmode/cmode pair to a frame buffer video
0215  *  mode structure.
0216  *
0217  *  Returns negative errno on error, or zero for success.
0218  *
0219  */
0220 
0221 int mac_vmode_to_var(int vmode, int cmode, struct fb_var_screeninfo *var)
0222 {
0223     const struct fb_videomode *mode = NULL;
0224     const struct mode_map *map;
0225 
0226     for (map = mac_modes; map->vmode != -1; map++)
0227     if (map->vmode == vmode) {
0228         mode = map->mode;
0229         break;
0230     }
0231     if (!mode)
0232     return -EINVAL;
0233 
0234     memset(var, 0, sizeof(struct fb_var_screeninfo));
0235     switch (cmode) {
0236     case CMODE_8:
0237         var->bits_per_pixel = 8;
0238         var->red.offset = 0;
0239         var->red.length = 8;   
0240         var->green.offset = 0;
0241         var->green.length = 8;
0242         var->blue.offset = 0;
0243         var->blue.length = 8;
0244         break;
0245 
0246     case CMODE_16:
0247         var->bits_per_pixel = 16;
0248         var->red.offset = 10;
0249         var->red.length = 5;
0250         var->green.offset = 5;
0251         var->green.length = 5;
0252         var->blue.offset = 0;
0253         var->blue.length = 5;
0254         break;
0255 
0256     case CMODE_32:
0257         var->bits_per_pixel = 32;
0258         var->red.offset = 16;
0259         var->red.length = 8;
0260         var->green.offset = 8;
0261         var->green.length = 8;
0262         var->blue.offset = 0;
0263         var->blue.length = 8;
0264         var->transp.offset = 24;
0265         var->transp.length = 8;
0266         break;
0267 
0268     default:
0269         return -EINVAL;
0270     }
0271     var->xres = mode->xres;
0272     var->yres = mode->yres;
0273     var->xres_virtual = mode->xres;
0274     var->yres_virtual = mode->yres;
0275     var->height = -1;
0276     var->width = -1;
0277     var->pixclock = mode->pixclock;
0278     var->left_margin = mode->left_margin;
0279     var->right_margin = mode->right_margin;
0280     var->upper_margin = mode->upper_margin;
0281     var->lower_margin = mode->lower_margin;
0282     var->hsync_len = mode->hsync_len;
0283     var->vsync_len = mode->vsync_len;
0284     var->sync = mode->sync;
0285     var->vmode = mode->vmode;
0286     return 0;
0287 }
0288 EXPORT_SYMBOL(mac_vmode_to_var);
0289 
0290 /**
0291  *  mac_var_to_vmode - convert var structure to MacOS vmode/cmode pair
0292  *  @var: frame buffer video mode structure
0293  *  @vmode: MacOS video mode
0294  *  @cmode: MacOS color mode
0295  *
0296  *  Converts a frame buffer video mode structure to a MacOS
0297  *  vmode/cmode pair.
0298  *
0299  *  Returns negative errno on error, or zero for success.
0300  *
0301  */
0302 
0303 int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
0304              int *cmode)
0305 {
0306     const struct mode_map *map;
0307 
0308     if (var->bits_per_pixel <= 8)
0309     *cmode = CMODE_8;
0310     else if (var->bits_per_pixel <= 16)
0311     *cmode = CMODE_16;
0312     else if (var->bits_per_pixel <= 32)
0313     *cmode = CMODE_32;
0314     else
0315     return -EINVAL;
0316 
0317     /*
0318      * Find the mac_mode with a matching resolution or failing that, the
0319      * closest larger resolution. Skip modes with a shorter pixel clock period.
0320      */
0321     for (map = mac_modes; map->vmode != -1; map++) {
0322     const struct fb_videomode *mode = map->mode;
0323 
0324     if (var->xres > mode->xres || var->yres > mode->yres)
0325         continue;
0326     if (var->xres_virtual > mode->xres || var->yres_virtual > mode->yres)
0327         continue;
0328     if (var->pixclock > mode->pixclock)
0329         continue;
0330     if ((var->vmode & FB_VMODE_MASK) != mode->vmode)
0331         continue;
0332     *vmode = map->vmode;
0333 
0334     /*
0335      * Having found a good resolution, find the matching pixel clock
0336      * or failing that, the closest longer pixel clock period.
0337      */
0338     map++;
0339     while (map->vmode != -1) {
0340         const struct fb_videomode *clk_mode = map->mode;
0341 
0342         if (mode->xres != clk_mode->xres || mode->yres != clk_mode->yres)
0343         break;
0344         if (var->pixclock > mode->pixclock)
0345             break;
0346         if (mode->vmode != clk_mode->vmode)
0347         continue;
0348         *vmode = map->vmode;
0349         map++;
0350     }
0351     return 0;
0352     }
0353     return -EINVAL;
0354 }
0355 
0356 /**
0357  *  mac_map_monitor_sense - Convert monitor sense to vmode
0358  *  @sense: Macintosh monitor sense number
0359  *
0360  *  Converts a Macintosh monitor sense number to a MacOS
0361  *  vmode number.
0362  *
0363  *  Returns MacOS vmode video mode number.
0364  *
0365  */
0366 
0367 int mac_map_monitor_sense(int sense)
0368 {
0369     const struct monitor_map *map;
0370 
0371     for (map = mac_monitors; map->sense != -1; map++)
0372     if (map->sense == sense)
0373         break;
0374     return map->vmode;
0375 }
0376 EXPORT_SYMBOL(mac_map_monitor_sense);
0377 
0378 /**
0379  *  mac_find_mode - find a video mode
0380  *  @var: frame buffer user defined part of display
0381  *  @info: frame buffer info structure
0382  *  @mode_option: video mode name (see mac_modedb[])
0383  *  @default_bpp: default color depth in bits per pixel
0384  *
0385  *  Finds a suitable video mode.  Tries to set mode specified
0386  *  by @mode_option.  If the name of the wanted mode begins with
0387  *  'mac', the Mac video mode database will be used, otherwise it
0388  *  will fall back to the standard video mode database.
0389  *
0390  *  Note: Function marked as __init and can only be used during
0391  *  system boot.
0392  *
0393  *  Returns error code from fb_find_mode (see fb_find_mode
0394  *  function).
0395  *
0396  */
0397 
0398 int mac_find_mode(struct fb_var_screeninfo *var, struct fb_info *info,
0399           const char *mode_option, unsigned int default_bpp)
0400 {
0401     const struct fb_videomode *db = NULL;
0402     unsigned int dbsize = 0;
0403 
0404     if (mode_option && !strncmp(mode_option, "mac", 3)) {
0405     mode_option += 3;
0406     db = mac_modedb;
0407     dbsize = ARRAY_SIZE(mac_modedb);
0408     }
0409     return fb_find_mode(var, info, mode_option, db, dbsize,
0410             &mac_modedb[DEFAULT_MODEDB_INDEX], default_bpp);
0411 }
0412 EXPORT_SYMBOL(mac_find_mode);
0413 
0414 MODULE_LICENSE("GPL");