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/fb.h> 20#include <linux/string.h> 21#include <linux/module.h> 22 23#include "macmodes.h" 24 25 /* 26 * MacOS video mode definitions 27 * 28 * Order IS important! If you change these, don't forget to update 29 * mac_modes[] below! 30 */ 31 32#define DEFAULT_MODEDB_INDEX 0 33 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_NONINTERLACED 39 }, { 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_NONINTERLACED 43 }, { 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_NONINTERLACED 47 }, { 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_NONINTERLACED 51 }, { 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_NONINTERLACED 55 }, { 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_NONINTERLACED 59 }, { 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_NONINTERLACED 63 }, { 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_NONINTERLACED 67 }, { 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_NONINTERLACED 71 }, { 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_NONINTERLACED 75 }, { 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_NONINTERLACED 79 }, { 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_NONINTERLACED 83 }, { 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_NONINTERLACED 87 }, { 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_NONINTERLACED 91 }, { 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_NONINTERLACED 95 }, { 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_NONINTERLACED 99 }, { 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_NONINTERLACED 103 }, { 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_NONINTERLACED 107 } 108 109}; 110 111 112 /* 113 * Mapping between MacOS video mode numbers and video mode definitions 114 * 115 * These MUST be ordered in 116 * - increasing resolution 117 * - decreasing pixel clock period 118 */ 119 120static const struct mode_map { 121 int vmode; 122 const struct fb_videomode *mode; 123} mac_modes[] = { 124 /* 512x384 */ 125 { VMODE_512_384_60, &mac_modedb[0] }, 126 /* 640x480 */ 127 { VMODE_640_480_60, &mac_modedb[1] }, 128 { VMODE_640_480_67, &mac_modedb[2] }, 129 /* 640x870 */ 130 { VMODE_640_870_75P, &mac_modedb[3] }, 131 /* 800x600 */ 132 { VMODE_800_600_56, &mac_modedb[4] }, 133 { VMODE_800_600_60, &mac_modedb[5] }, 134 { VMODE_800_600_75, &mac_modedb[7] }, 135 { VMODE_800_600_72, &mac_modedb[6] }, 136 /* 832x624 */ 137 { VMODE_832_624_75, &mac_modedb[8] }, 138 /* 1024x768 */ 139 { VMODE_1024_768_60, &mac_modedb[9] }, 140 { VMODE_1024_768_70, &mac_modedb[10] }, 141 { VMODE_1024_768_75V, &mac_modedb[11] }, 142 { VMODE_1024_768_75, &mac_modedb[12] }, 143 /* 1152x768 */ 144 { VMODE_1152_768_60, &mac_modedb[16] }, 145 /* 1152x870 */ 146 { VMODE_1152_870_75, &mac_modedb[13] }, 147 /* 1280x960 */ 148 { VMODE_1280_960_75, &mac_modedb[14] }, 149 /* 1280x1024 */ 150 { VMODE_1280_1024_75, &mac_modedb[15] }, 151 /* 1600x1024 */ 152 { VMODE_1600_1024_60, &mac_modedb[17] }, 153 { -1, NULL } 154}; 155 156 157 /* 158 * Mapping between monitor sense values and MacOS video mode numbers 159 */ 160 161static const struct monitor_map { 162 int sense; 163 int vmode; 164} mac_monitors[] = { 165 { 0x000, VMODE_1280_1024_75 }, /* 21" RGB */ 166 { 0x114, VMODE_640_870_75P }, /* Portrait Monochrome */ 167 { 0x221, VMODE_512_384_60 }, /* 12" RGB*/ 168 { 0x331, VMODE_1280_1024_75 }, /* 21" RGB (Radius) */ 169 { 0x334, VMODE_1280_1024_75 }, /* 21" mono (Radius) */ 170 { 0x335, VMODE_1280_1024_75 }, /* 21" mono */ 171 { 0x40A, VMODE_640_480_60I }, /* NTSC */ 172 { 0x51E, VMODE_640_870_75P }, /* Portrait RGB */ 173 { 0x603, VMODE_832_624_75 }, /* 12"-16" multiscan */ 174 { 0x60b, VMODE_1024_768_70 }, /* 13"-19" multiscan */ 175 { 0x623, VMODE_1152_870_75 }, /* 13"-21" multiscan */ 176 { 0x62b, VMODE_640_480_67 }, /* 13"/14" RGB */ 177 { 0x700, VMODE_640_480_50I }, /* PAL */ 178 { 0x714, VMODE_640_480_60I }, /* NTSC */ 179 { 0x717, VMODE_800_600_75 }, /* VGA */ 180 { 0x72d, VMODE_832_624_75 }, /* 16" RGB (Goldfish) */ 181 { 0x730, VMODE_768_576_50I }, /* PAL (Alternate) */ 182 { 0x73a, VMODE_1152_870_75 }, /* 3rd party 19" */ 183 { 0x73f, VMODE_640_480_67 }, /* no sense lines connected at all */ 184 { 0xBEEF, VMODE_1600_1024_60 }, /* 22" Apple Cinema Display */ 185 { -1, VMODE_640_480_60 }, /* catch-all, must be last */ 186}; 187 188/** 189 * mac_vmode_to_var - converts vmode/cmode pair to var structure 190 * @vmode: MacOS video mode 191 * @cmode: MacOS color mode 192 * @var: frame buffer video mode structure 193 * 194 * Converts a MacOS vmode/cmode pair to a frame buffer video 195 * mode structure. 196 * 197 * Returns negative errno on error, or zero for success. 198 * 199 */ 200 201int mac_vmode_to_var(int vmode, int cmode, struct fb_var_screeninfo *var) 202{ 203 const struct fb_videomode *mode = NULL; 204 const struct mode_map *map; 205 206 for (map = mac_modes; map->vmode != -1; map++) 207 if (map->vmode == vmode) { 208 mode = map->mode; 209 break; 210 } 211 if (!mode) 212 return -EINVAL; 213 214 memset(var, 0, sizeof(struct fb_var_screeninfo)); 215 switch (cmode) { 216 case CMODE_8: 217 var->bits_per_pixel = 8; 218 var->red.offset = 0; 219 var->red.length = 8; 220 var->green.offset = 0; 221 var->green.length = 8; 222 var->blue.offset = 0; 223 var->blue.length = 8; 224 break; 225 226 case CMODE_16: 227 var->bits_per_pixel = 16; 228 var->red.offset = 10; 229 var->red.length = 5; 230 var->green.offset = 5; 231 var->green.length = 5; 232 var->blue.offset = 0; 233 var->blue.length = 5; 234 break; 235 236 case CMODE_32: 237 var->bits_per_pixel = 32; 238 var->red.offset = 16; 239 var->red.length = 8; 240 var->green.offset = 8; 241 var->green.length = 8; 242 var->blue.offset = 0; 243 var->blue.length = 8; 244 var->transp.offset = 24; 245 var->transp.length = 8; 246 break; 247 248 default: 249 return -EINVAL; 250 } 251 var->xres = mode->xres; 252 var->yres = mode->yres; 253 var->xres_virtual = mode->xres; 254 var->yres_virtual = mode->yres; 255 var->height = -1; 256 var->width = -1; 257 var->pixclock = mode->pixclock; 258 var->left_margin = mode->left_margin; 259 var->right_margin = mode->right_margin; 260 var->upper_margin = mode->upper_margin; 261 var->lower_margin = mode->lower_margin; 262 var->hsync_len = mode->hsync_len; 263 var->vsync_len = mode->vsync_len; 264 var->sync = mode->sync; 265 var->vmode = mode->vmode; 266 return 0; 267} 268EXPORT_SYMBOL(mac_vmode_to_var); 269 270/** 271 * mac_var_to_vmode - convert var structure to MacOS vmode/cmode pair 272 * @var: frame buffer video mode structure 273 * @vmode: MacOS video mode 274 * @cmode: MacOS color mode 275 * 276 * Converts a frame buffer video mode structure to a MacOS 277 * vmode/cmode pair. 278 * 279 * Returns negative errno on error, or zero for success. 280 * 281 */ 282 283int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode, 284 int *cmode) 285{ 286 const struct mode_map *map; 287 288 if (var->bits_per_pixel <= 8) 289 *cmode = CMODE_8; 290 else if (var->bits_per_pixel <= 16) 291 *cmode = CMODE_16; 292 else if (var->bits_per_pixel <= 32) 293 *cmode = CMODE_32; 294 else 295 return -EINVAL; 296 297 /* 298 * Find the mac_mode with a matching resolution or failing that, the 299 * closest larger resolution. Skip modes with a shorter pixel clock period. 300 */ 301 for (map = mac_modes; map->vmode != -1; map++) { 302 const struct fb_videomode *mode = map->mode; 303 304 if (var->xres > mode->xres || var->yres > mode->yres) 305 continue; 306 if (var->xres_virtual > mode->xres || var->yres_virtual > mode->yres) 307 continue; 308 if (var->pixclock > mode->pixclock) 309 continue; 310 if ((var->vmode & FB_VMODE_MASK) != mode->vmode) 311 continue; 312 *vmode = map->vmode; 313 314 /* 315 * Having found a good resolution, find the matching pixel clock 316 * or failing that, the closest longer pixel clock period. 317 */ 318 map++; 319 while (map->vmode != -1) { 320 const struct fb_videomode *clk_mode = map->mode; 321 322 if (mode->xres != clk_mode->xres || mode->yres != clk_mode->yres) 323 break; 324 if (var->pixclock > mode->pixclock) 325 break; 326 if (mode->vmode != clk_mode->vmode) 327 continue; 328 *vmode = map->vmode; 329 map++; 330 } 331 return 0; 332 } 333 return -EINVAL; 334} 335 336/** 337 * mac_map_monitor_sense - Convert monitor sense to vmode 338 * @sense: Macintosh monitor sense number 339 * 340 * Converts a Macintosh monitor sense number to a MacOS 341 * vmode number. 342 * 343 * Returns MacOS vmode video mode number. 344 * 345 */ 346 347int mac_map_monitor_sense(int sense) 348{ 349 const struct monitor_map *map; 350 351 for (map = mac_monitors; map->sense != -1; map++) 352 if (map->sense == sense) 353 break; 354 return map->vmode; 355} 356EXPORT_SYMBOL(mac_map_monitor_sense); 357 358/** 359 * mac_find_mode - find a video mode 360 * @var: frame buffer user defined part of display 361 * @info: frame buffer info structure 362 * @mode_option: video mode name (see mac_modedb[]) 363 * @default_bpp: default color depth in bits per pixel 364 * 365 * Finds a suitable video mode. Tries to set mode specified 366 * by @mode_option. If the name of the wanted mode begins with 367 * 'mac', the Mac video mode database will be used, otherwise it 368 * will fall back to the standard video mode database. 369 * 370 * Note: Function marked as __init and can only be used during 371 * system boot. 372 * 373 * Returns error code from fb_find_mode (see fb_find_mode 374 * function). 375 * 376 */ 377 378int mac_find_mode(struct fb_var_screeninfo *var, struct fb_info *info, 379 const char *mode_option, unsigned int default_bpp) 380{ 381 const struct fb_videomode *db = NULL; 382 unsigned int dbsize = 0; 383 384 if (mode_option && !strncmp(mode_option, "mac", 3)) { 385 mode_option += 3; 386 db = mac_modedb; 387 dbsize = ARRAY_SIZE(mac_modedb); 388 } 389 return fb_find_mode(var, info, mode_option, db, dbsize, 390 &mac_modedb[DEFAULT_MODEDB_INDEX], default_bpp); 391} 392EXPORT_SYMBOL(mac_find_mode); 393 394MODULE_LICENSE("GPL"); 395