416 lines · c
1/*2 * linux/drivers/video/macmodes.c -- Standard MacOS video modes3 *4 * Copyright (C) 1998 Geert Uytterhoeven5 *6 * 2000 - Removal of OpenFirmware dependencies by:7 * - Ani Joshi8 * - Brad Douglas <brad@neruo.com>9 *10 * 2001 - Documented with DocBook11 * - Brad Douglas <brad@neruo.com>12 *13 * This file is subject to the terms and conditions of the GNU General Public14 * License. See the file COPYING in the main directory of this archive for15 * more details.16 */17 18#include <linux/errno.h>19#include <linux/fb.h>20#include <linux/string.h>21#include <linux/module.h>22 23#include "macmodes.h"24 25 /*26 * MacOS video mode definitions27 *28 * Order IS important! If you change these, don't forget to update29 * mac_modes[] below!30 */31 32#define DEFAULT_MODEDB_INDEX 033 34static const struct fb_videomode mac_modedb[] = {35 {36 /* 512x384, 60Hz, Non-Interlaced (15.67 MHz dot clock) */37 "mac2", 60, 512, 384, 63828, 80, 16, 19, 1, 32, 3,38 0, FB_VMODE_NONINTERLACED39 }, {40 /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */41 "mac5", 60, 640, 480, 39722, 32, 32, 33, 10, 96, 2,42 0, FB_VMODE_NONINTERLACED43 }, {44 /* 640x480, 67Hz, Non-Interlaced (30.0 MHz dotclock) */45 "mac6", 67, 640, 480, 33334, 80, 80, 39, 3, 64, 3,46 0, FB_VMODE_NONINTERLACED47 }, {48 /* 640x870, 75Hz (portrait), Non-Interlaced (57.28 MHz dot clock) */49 "mac7", 75, 640, 870, 17457, 80, 32, 42, 3, 80, 3,50 0, FB_VMODE_NONINTERLACED51 }, {52 /* 800x600, 56 Hz, Non-Interlaced (36.00 MHz dotclock) */53 "mac9", 56, 800, 600, 27778, 112, 40, 22, 1, 72, 2,54 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED55 }, {56 /* 800x600, 60 Hz, Non-Interlaced (40.00 MHz dotclock) */57 "mac10", 60, 800, 600, 25000, 72, 56, 23, 1, 128, 4,58 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED59 }, {60 /* 800x600, 72 Hz, Non-Interlaced (50.00 MHz dotclock) */61 "mac11", 72, 800, 600, 20000, 48, 72, 23, 37, 120, 6,62 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED63 }, {64 /* 800x600, 75 Hz, Non-Interlaced (49.50 MHz dotclock) */65 "mac12", 75, 800, 600, 20203, 144, 32, 21, 1, 80, 3,66 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED67 }, {68 /* 832x624, 75Hz, Non-Interlaced (57.6 MHz dotclock) */69 "mac13", 75, 832, 624, 17362, 208, 48, 39, 1, 64, 3,70 0, FB_VMODE_NONINTERLACED71 }, {72 /* 1024x768, 60 Hz, Non-Interlaced (65.00 MHz dotclock) */73 "mac14", 60, 1024, 768, 15385, 144, 40, 29, 3, 136, 6,74 0, FB_VMODE_NONINTERLACED75 }, {76 /* 1024x768, 72 Hz, Non-Interlaced (75.00 MHz dotclock) */77 "mac15", 72, 1024, 768, 13334, 128, 40, 29, 3, 136, 6,78 0, FB_VMODE_NONINTERLACED79 }, {80 /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */81 "mac16", 75, 1024, 768, 12699, 176, 16, 28, 1, 96, 3,82 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED83 }, {84 /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */85 "mac17", 75, 1024, 768, 12699, 160, 32, 28, 1, 96, 3,86 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED87 }, {88 /* 1152x870, 75 Hz, Non-Interlaced (100.0 MHz dotclock) */89 "mac18", 75, 1152, 870, 10000, 128, 48, 39, 3, 128, 3,90 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED91 }, {92 /* 1280x960, 75 Hz, Non-Interlaced (126.00 MHz dotclock) */93 "mac19", 75, 1280, 960, 7937, 224, 32, 36, 1, 144, 3,94 0, FB_VMODE_NONINTERLACED95 }, {96 /* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */97 "mac20", 75, 1280, 1024, 7408, 232, 64, 38, 1, 112, 3,98 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED99 }, {100 /* 1152x768, 60 Hz, Titanium PowerBook */101 "mac21", 60, 1152, 768, 15386, 158, 26, 29, 3, 136, 6,102 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED103 }, {104 /* 1600x1024, 60 Hz, Non-Interlaced (112.27 MHz dotclock) */105 "mac22", 60, 1600, 1024, 8908, 88, 104, 1, 10, 16, 1,106 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED107 }108 109#if 0110 /* Anyone who has timings for these? */111 {112 /* VMODE_512_384_60I: 512x384, 60Hz, Interlaced (NTSC) */113 "mac1", 60, 512, 384, pixclock, left, right, upper, lower, hslen, vslen,114 sync, FB_VMODE_INTERLACED115 }, {116 /* VMODE_640_480_50I: 640x480, 50Hz, Interlaced (PAL) */117 "mac3", 50, 640, 480, pixclock, left, right, upper, lower, hslen, vslen,118 sync, FB_VMODE_INTERLACED119 }, {120 /* VMODE_640_480_60I: 640x480, 60Hz, Interlaced (NTSC) */121 "mac4", 60, 640, 480, pixclock, left, right, upper, lower, hslen, vslen,122 sync, FB_VMODE_INTERLACED123 }, {124 /* VMODE_768_576_50I: 768x576, 50Hz (PAL full frame), Interlaced */125 "mac8", 50, 768, 576, pixclock, left, right, upper, lower, hslen, vslen,126 sync, FB_VMODE_INTERLACED127 },128#endif129};130 131 132 /*133 * Mapping between MacOS video mode numbers and video mode definitions134 *135 * These MUST be ordered in136 * - increasing resolution137 * - decreasing pixel clock period138 */139 140static const struct mode_map {141 int vmode;142 const struct fb_videomode *mode;143} mac_modes[] = {144 /* 512x384 */145 { VMODE_512_384_60, &mac_modedb[0] },146 /* 640x480 */147 { VMODE_640_480_60, &mac_modedb[1] },148 { VMODE_640_480_67, &mac_modedb[2] },149 /* 640x870 */150 { VMODE_640_870_75P, &mac_modedb[3] },151 /* 800x600 */152 { VMODE_800_600_56, &mac_modedb[4] },153 { VMODE_800_600_60, &mac_modedb[5] },154 { VMODE_800_600_75, &mac_modedb[7] },155 { VMODE_800_600_72, &mac_modedb[6] },156 /* 832x624 */157 { VMODE_832_624_75, &mac_modedb[8] },158 /* 1024x768 */159 { VMODE_1024_768_60, &mac_modedb[9] },160 { VMODE_1024_768_70, &mac_modedb[10] },161 { VMODE_1024_768_75V, &mac_modedb[11] },162 { VMODE_1024_768_75, &mac_modedb[12] },163 /* 1152x768 */164 { VMODE_1152_768_60, &mac_modedb[16] },165 /* 1152x870 */166 { VMODE_1152_870_75, &mac_modedb[13] },167 /* 1280x960 */168 { VMODE_1280_960_75, &mac_modedb[14] },169 /* 1280x1024 */170 { VMODE_1280_1024_75, &mac_modedb[15] },171 /* 1600x1024 */172 { VMODE_1600_1024_60, &mac_modedb[17] },173 { -1, NULL }174};175 176 177 /*178 * Mapping between monitor sense values and MacOS video mode numbers179 */180 181static const struct monitor_map {182 int sense;183 int vmode;184} mac_monitors[] = {185 { 0x000, VMODE_1280_1024_75 }, /* 21" RGB */186 { 0x114, VMODE_640_870_75P }, /* Portrait Monochrome */187 { 0x221, VMODE_512_384_60 }, /* 12" RGB*/188 { 0x331, VMODE_1280_1024_75 }, /* 21" RGB (Radius) */189 { 0x334, VMODE_1280_1024_75 }, /* 21" mono (Radius) */190 { 0x335, VMODE_1280_1024_75 }, /* 21" mono */191 { 0x40A, VMODE_640_480_60I }, /* NTSC */192 { 0x51E, VMODE_640_870_75P }, /* Portrait RGB */193 { 0x603, VMODE_832_624_75 }, /* 12"-16" multiscan */194 { 0x60b, VMODE_1024_768_70 }, /* 13"-19" multiscan */195 { 0x623, VMODE_1152_870_75 }, /* 13"-21" multiscan */196 { 0x62b, VMODE_640_480_67 }, /* 13"/14" RGB */197 { 0x700, VMODE_640_480_50I }, /* PAL */198 { 0x714, VMODE_640_480_60I }, /* NTSC */199 { 0x717, VMODE_800_600_75 }, /* VGA */200 { 0x72d, VMODE_832_624_75 }, /* 16" RGB (Goldfish) */201 { 0x730, VMODE_768_576_50I }, /* PAL (Alternate) */202 { 0x73a, VMODE_1152_870_75 }, /* 3rd party 19" */203 { 0x73f, VMODE_640_480_67 }, /* no sense lines connected at all */204 { 0xBEEF, VMODE_1600_1024_60 }, /* 22" Apple Cinema Display */205 { -1, VMODE_640_480_60 }, /* catch-all, must be last */206};207 208/**209 * mac_vmode_to_var - converts vmode/cmode pair to var structure210 * @vmode: MacOS video mode211 * @cmode: MacOS color mode212 * @var: frame buffer video mode structure213 *214 * Converts a MacOS vmode/cmode pair to a frame buffer video215 * mode structure.216 *217 * Returns negative errno on error, or zero for success.218 *219 */220 221int mac_vmode_to_var(int vmode, int cmode, struct fb_var_screeninfo *var)222{223 const struct fb_videomode *mode = NULL;224 const struct mode_map *map;225 226 for (map = mac_modes; map->vmode != -1; map++)227 if (map->vmode == vmode) {228 mode = map->mode;229 break;230 }231 if (!mode)232 return -EINVAL;233 234 memset(var, 0, sizeof(struct fb_var_screeninfo));235 switch (cmode) {236 case CMODE_8:237 var->bits_per_pixel = 8;238 var->red.offset = 0;239 var->red.length = 8; 240 var->green.offset = 0;241 var->green.length = 8;242 var->blue.offset = 0;243 var->blue.length = 8;244 break;245 246 case CMODE_16:247 var->bits_per_pixel = 16;248 var->red.offset = 10;249 var->red.length = 5;250 var->green.offset = 5;251 var->green.length = 5;252 var->blue.offset = 0;253 var->blue.length = 5;254 break;255 256 case CMODE_32:257 var->bits_per_pixel = 32;258 var->red.offset = 16;259 var->red.length = 8;260 var->green.offset = 8;261 var->green.length = 8;262 var->blue.offset = 0;263 var->blue.length = 8;264 var->transp.offset = 24;265 var->transp.length = 8;266 break;267 268 default:269 return -EINVAL;270 }271 var->xres = mode->xres;272 var->yres = mode->yres;273 var->xres_virtual = mode->xres;274 var->yres_virtual = mode->yres;275 var->height = -1;276 var->width = -1;277 var->pixclock = mode->pixclock;278 var->left_margin = mode->left_margin;279 var->right_margin = mode->right_margin;280 var->upper_margin = mode->upper_margin;281 var->lower_margin = mode->lower_margin;282 var->hsync_len = mode->hsync_len;283 var->vsync_len = mode->vsync_len;284 var->sync = mode->sync;285 var->vmode = mode->vmode;286 return 0;287}288EXPORT_SYMBOL(mac_vmode_to_var);289 290/**291 * mac_var_to_vmode - convert var structure to MacOS vmode/cmode pair292 * @var: frame buffer video mode structure293 * @vmode: MacOS video mode294 * @cmode: MacOS color mode295 *296 * Converts a frame buffer video mode structure to a MacOS297 * vmode/cmode pair.298 *299 * Returns negative errno on error, or zero for success.300 *301 */302 303int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,304 int *cmode)305{306 const struct mode_map *map;307 308 if (var->bits_per_pixel <= 8)309 *cmode = CMODE_8;310 else if (var->bits_per_pixel <= 16)311 *cmode = CMODE_16;312 else if (var->bits_per_pixel <= 32)313 *cmode = CMODE_32;314 else315 return -EINVAL;316 317 /*318 * Find the mac_mode with a matching resolution or failing that, the319 * closest larger resolution. Skip modes with a shorter pixel clock period.320 */321 for (map = mac_modes; map->vmode != -1; map++) {322 const struct fb_videomode *mode = map->mode;323 324 if (var->xres > mode->xres || var->yres > mode->yres)325 continue;326 if (var->xres_virtual > mode->xres || var->yres_virtual > mode->yres)327 continue;328 if (var->pixclock > mode->pixclock)329 continue;330 if ((var->vmode & FB_VMODE_MASK) != mode->vmode)331 continue;332 *vmode = map->vmode;333 334 /*335 * Having found a good resolution, find the matching pixel clock336 * or failing that, the closest longer pixel clock period.337 */338 map++;339 while (map->vmode != -1) {340 const struct fb_videomode *clk_mode = map->mode;341 342 if (mode->xres != clk_mode->xres || mode->yres != clk_mode->yres)343 break;344 if (var->pixclock > mode->pixclock)345 break;346 if (mode->vmode != clk_mode->vmode)347 continue;348 *vmode = map->vmode;349 map++;350 }351 return 0;352 }353 return -EINVAL;354}355 356/**357 * mac_map_monitor_sense - Convert monitor sense to vmode358 * @sense: Macintosh monitor sense number359 *360 * Converts a Macintosh monitor sense number to a MacOS361 * vmode number.362 *363 * Returns MacOS vmode video mode number.364 *365 */366 367int mac_map_monitor_sense(int sense)368{369 const struct monitor_map *map;370 371 for (map = mac_monitors; map->sense != -1; map++)372 if (map->sense == sense)373 break;374 return map->vmode;375}376EXPORT_SYMBOL(mac_map_monitor_sense);377 378/**379 * mac_find_mode - find a video mode380 * @var: frame buffer user defined part of display381 * @info: frame buffer info structure382 * @mode_option: video mode name (see mac_modedb[])383 * @default_bpp: default color depth in bits per pixel384 *385 * Finds a suitable video mode. Tries to set mode specified386 * by @mode_option. If the name of the wanted mode begins with387 * 'mac', the Mac video mode database will be used, otherwise it388 * will fall back to the standard video mode database.389 *390 * Note: Function marked as __init and can only be used during391 * system boot.392 *393 * Returns error code from fb_find_mode (see fb_find_mode394 * function).395 *396 */397 398int mac_find_mode(struct fb_var_screeninfo *var, struct fb_info *info,399 const char *mode_option, unsigned int default_bpp)400{401 const struct fb_videomode *db = NULL;402 unsigned int dbsize = 0;403 404 if (mode_option && !strncmp(mode_option, "mac", 3)) {405 mode_option += 3;406 db = mac_modedb;407 dbsize = ARRAY_SIZE(mac_modedb);408 }409 return fb_find_mode(var, info, mode_option, db, dbsize,410 &mac_modedb[DEFAULT_MODEDB_INDEX], default_bpp);411}412EXPORT_SYMBOL(mac_find_mode);413 414MODULE_DESCRIPTION("MacOS video mode library");415MODULE_LICENSE("GPL");416