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