diff options
| -rw-r--r-- | arch/powerpc/platforms/powermac/bootx_init.c | 35 | ||||
| -rw-r--r-- | drivers/video/offb.c | 307 |
2 files changed, 185 insertions, 157 deletions
diff --git a/arch/powerpc/platforms/powermac/bootx_init.c b/arch/powerpc/platforms/powermac/bootx_init.c index 871b002c9f90..6a026c733f6a 100644 --- a/arch/powerpc/platforms/powermac/bootx_init.c +++ b/arch/powerpc/platforms/powermac/bootx_init.c | |||
| @@ -181,13 +181,18 @@ static void __init bootx_add_chosen_props(unsigned long base, | |||
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | static void __init bootx_add_display_props(unsigned long base, | 183 | static void __init bootx_add_display_props(unsigned long base, |
| 184 | unsigned long *mem_end) | 184 | unsigned long *mem_end, |
| 185 | int has_real_node) | ||
| 185 | { | 186 | { |
| 186 | boot_infos_t *bi = bootx_info; | 187 | boot_infos_t *bi = bootx_info; |
| 187 | u32 tmp; | 188 | u32 tmp; |
| 188 | 189 | ||
| 189 | bootx_dt_add_prop("linux,boot-display", NULL, 0, mem_end); | 190 | if (has_real_node) { |
| 190 | bootx_dt_add_prop("linux,opened", NULL, 0, mem_end); | 191 | bootx_dt_add_prop("linux,boot-display", NULL, 0, mem_end); |
| 192 | bootx_dt_add_prop("linux,opened", NULL, 0, mem_end); | ||
| 193 | } else | ||
| 194 | bootx_dt_add_prop("linux,bootx-noscreen", NULL, 0, mem_end); | ||
| 195 | |||
| 191 | tmp = bi->dispDeviceDepth; | 196 | tmp = bi->dispDeviceDepth; |
| 192 | bootx_dt_add_prop("linux,bootx-depth", &tmp, 4, mem_end); | 197 | bootx_dt_add_prop("linux,bootx-depth", &tmp, 4, mem_end); |
| 193 | tmp = bi->dispDeviceRect[2] - bi->dispDeviceRect[0]; | 198 | tmp = bi->dispDeviceRect[2] - bi->dispDeviceRect[0]; |
| @@ -241,11 +246,6 @@ static void __init bootx_scan_dt_build_strings(unsigned long base, | |||
| 241 | DBG(" detected display ! adding properties names !\n"); | 246 | DBG(" detected display ! adding properties names !\n"); |
| 242 | bootx_dt_add_string("linux,boot-display", mem_end); | 247 | bootx_dt_add_string("linux,boot-display", mem_end); |
| 243 | bootx_dt_add_string("linux,opened", mem_end); | 248 | bootx_dt_add_string("linux,opened", mem_end); |
| 244 | bootx_dt_add_string("linux,bootx-depth", mem_end); | ||
| 245 | bootx_dt_add_string("linux,bootx-width", mem_end); | ||
| 246 | bootx_dt_add_string("linux,bootx-height", mem_end); | ||
| 247 | bootx_dt_add_string("linux,bootx-linebytes", mem_end); | ||
| 248 | bootx_dt_add_string("linux,bootx-addr", mem_end); | ||
| 249 | strncpy(bootx_disp_path, namep, 255); | 249 | strncpy(bootx_disp_path, namep, 255); |
| 250 | } | 250 | } |
| 251 | 251 | ||
| @@ -329,10 +329,13 @@ static void __init bootx_scan_dt_build_struct(unsigned long base, | |||
| 329 | ppp = &pp->next; | 329 | ppp = &pp->next; |
| 330 | } | 330 | } |
| 331 | 331 | ||
| 332 | if (node == bootx_node_chosen) | 332 | if (node == bootx_node_chosen) { |
| 333 | bootx_add_chosen_props(base, mem_end); | 333 | bootx_add_chosen_props(base, mem_end); |
| 334 | if (node == bootx_info->dispDeviceRegEntryOffset) | 334 | if (bootx_info->dispDeviceRegEntryOffset == 0) |
| 335 | bootx_add_display_props(base, mem_end); | 335 | bootx_add_display_props(base, mem_end, 0); |
| 336 | } | ||
| 337 | else if (node == bootx_info->dispDeviceRegEntryOffset) | ||
| 338 | bootx_add_display_props(base, mem_end, 1); | ||
| 336 | 339 | ||
| 337 | /* do all our children */ | 340 | /* do all our children */ |
| 338 | cpp = &np->child; | 341 | cpp = &np->child; |
| @@ -374,6 +377,14 @@ static unsigned long __init bootx_flatten_dt(unsigned long start) | |||
| 374 | mem_end += 4; | 377 | mem_end += 4; |
| 375 | bootx_dt_strend = mem_end; | 378 | bootx_dt_strend = mem_end; |
| 376 | bootx_scan_dt_build_strings(base, 4, &mem_end); | 379 | bootx_scan_dt_build_strings(base, 4, &mem_end); |
| 380 | /* Add some strings */ | ||
| 381 | bootx_dt_add_string("linux,bootx-noscreen", &mem_end); | ||
| 382 | bootx_dt_add_string("linux,bootx-depth", &mem_end); | ||
| 383 | bootx_dt_add_string("linux,bootx-width", &mem_end); | ||
| 384 | bootx_dt_add_string("linux,bootx-height", &mem_end); | ||
| 385 | bootx_dt_add_string("linux,bootx-linebytes", &mem_end); | ||
| 386 | bootx_dt_add_string("linux,bootx-addr", &mem_end); | ||
| 387 | /* Wrap up strings */ | ||
| 377 | hdr->off_dt_strings = bootx_dt_strbase - mem_start; | 388 | hdr->off_dt_strings = bootx_dt_strbase - mem_start; |
| 378 | hdr->dt_strings_size = bootx_dt_strend - bootx_dt_strbase; | 389 | hdr->dt_strings_size = bootx_dt_strend - bootx_dt_strbase; |
| 379 | 390 | ||
| @@ -471,6 +482,7 @@ void __init bootx_init(unsigned long r3, unsigned long r4) | |||
| 471 | if (bi->dispDeviceDepth == 16) | 482 | if (bi->dispDeviceDepth == 16) |
| 472 | bi->dispDeviceDepth = 15; | 483 | bi->dispDeviceDepth = 15; |
| 473 | 484 | ||
| 485 | |||
| 474 | #ifdef CONFIG_BOOTX_TEXT | 486 | #ifdef CONFIG_BOOTX_TEXT |
| 475 | ptr = (unsigned long)bi->logicalDisplayBase; | 487 | ptr = (unsigned long)bi->logicalDisplayBase; |
| 476 | ptr += bi->dispDeviceRect[1] * bi->dispDeviceRowBytes; | 488 | ptr += bi->dispDeviceRect[1] * bi->dispDeviceRowBytes; |
| @@ -508,6 +520,7 @@ void __init bootx_init(unsigned long r3, unsigned long r4) | |||
| 508 | #ifdef CONFIG_BOOTX_TEXT | 520 | #ifdef CONFIG_BOOTX_TEXT |
| 509 | btext_welcome(bi); | 521 | btext_welcome(bi); |
| 510 | #endif | 522 | #endif |
| 523 | |||
| 511 | /* New BootX enters kernel with MMU off, i/os are not allowed | 524 | /* New BootX enters kernel with MMU off, i/os are not allowed |
| 512 | * here. This hack will have been done by the boostrap anyway. | 525 | * here. This hack will have been done by the boostrap anyway. |
| 513 | */ | 526 | */ |
diff --git a/drivers/video/offb.c b/drivers/video/offb.c index ce5f3031b99b..0013311e0564 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c | |||
| @@ -62,8 +62,6 @@ struct offb_par default_par; | |||
| 62 | * Interface used by the world | 62 | * Interface used by the world |
| 63 | */ | 63 | */ |
| 64 | 64 | ||
| 65 | int offb_init(void); | ||
| 66 | |||
| 67 | static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | 65 | static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, |
| 68 | u_int transp, struct fb_info *info); | 66 | u_int transp, struct fb_info *info); |
| 69 | static int offb_blank(int blank, struct fb_info *info); | 67 | static int offb_blank(int blank, struct fb_info *info); |
| @@ -72,11 +70,6 @@ static int offb_blank(int blank, struct fb_info *info); | |||
| 72 | extern boot_infos_t *boot_infos; | 70 | extern boot_infos_t *boot_infos; |
| 73 | #endif | 71 | #endif |
| 74 | 72 | ||
| 75 | static void offb_init_nodriver(struct device_node *); | ||
| 76 | static void offb_init_fb(const char *name, const char *full_name, | ||
| 77 | int width, int height, int depth, int pitch, | ||
| 78 | unsigned long address, struct device_node *dp); | ||
| 79 | |||
| 80 | static struct fb_ops offb_ops = { | 73 | static struct fb_ops offb_ops = { |
| 81 | .owner = THIS_MODULE, | 74 | .owner = THIS_MODULE, |
| 82 | .fb_setcolreg = offb_setcolreg, | 75 | .fb_setcolreg = offb_setcolreg, |
| @@ -229,123 +222,17 @@ static int offb_blank(int blank, struct fb_info *info) | |||
| 229 | return 0; | 222 | return 0; |
| 230 | } | 223 | } |
| 231 | 224 | ||
| 232 | /* | ||
| 233 | * Initialisation | ||
| 234 | */ | ||
| 235 | 225 | ||
| 236 | int __init offb_init(void) | 226 | static void __iomem *offb_map_reg(struct device_node *np, int index, |
| 227 | unsigned long offset, unsigned long size) | ||
| 237 | { | 228 | { |
| 238 | struct device_node *dp = NULL, *boot_disp = NULL; | 229 | struct resource r; |
| 239 | |||
| 240 | if (fb_get_options("offb", NULL)) | ||
| 241 | return -ENODEV; | ||
| 242 | 230 | ||
| 243 | for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) { | 231 | if (of_address_to_resource(np, index, &r)) |
| 244 | if (get_property(dp, "linux,opened", NULL) && | 232 | return 0; |
| 245 | get_property(dp, "linux,boot-display", NULL)) { | 233 | if ((r.start + offset + size) > r.end) |
| 246 | boot_disp = dp; | 234 | return 0; |
| 247 | offb_init_nodriver(dp); | 235 | return ioremap(r.start + offset, size); |
| 248 | } | ||
| 249 | } | ||
| 250 | for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) { | ||
| 251 | if (get_property(dp, "linux,opened", NULL) && | ||
| 252 | dp != boot_disp) | ||
| 253 | offb_init_nodriver(dp); | ||
| 254 | } | ||
| 255 | |||
| 256 | return 0; | ||
| 257 | } | ||
| 258 | |||
| 259 | |||
| 260 | static void __init offb_init_nodriver(struct device_node *dp) | ||
| 261 | { | ||
| 262 | unsigned int len; | ||
| 263 | int i, width = 640, height = 480, depth = 8, pitch = 640; | ||
| 264 | unsigned int flags, rsize, addr_prop = 0; | ||
| 265 | unsigned long max_size = 0; | ||
| 266 | u64 rstart, address = OF_BAD_ADDR; | ||
| 267 | u32 *pp, *addrp, *up; | ||
| 268 | u64 asize; | ||
| 269 | |||
| 270 | pp = (u32 *)get_property(dp, "linux,bootx-depth", &len); | ||
| 271 | if (pp == NULL) | ||
| 272 | pp = (u32 *)get_property(dp, "depth", &len); | ||
| 273 | if (pp && len == sizeof(u32)) | ||
| 274 | depth = *pp; | ||
| 275 | |||
| 276 | pp = (u32 *)get_property(dp, "linux,bootx-width", &len); | ||
| 277 | if (pp == NULL) | ||
| 278 | pp = (u32 *)get_property(dp, "width", &len); | ||
| 279 | if (pp && len == sizeof(u32)) | ||
| 280 | width = *pp; | ||
| 281 | |||
| 282 | pp = (u32 *)get_property(dp, "linux,bootx-height", &len); | ||
| 283 | if (pp == NULL) | ||
| 284 | pp = (u32 *)get_property(dp, "height", &len); | ||
| 285 | if (pp && len == sizeof(u32)) | ||
| 286 | height = *pp; | ||
| 287 | |||
| 288 | pp = (u32 *)get_property(dp, "linux,bootx-linebytes", &len); | ||
| 289 | if (pp == NULL) | ||
| 290 | pp = (u32 *)get_property(dp, "linebytes", &len); | ||
| 291 | if (pp && len == sizeof(u32)) | ||
| 292 | pitch = *pp; | ||
| 293 | else | ||
| 294 | pitch = width * ((depth + 7) / 8); | ||
| 295 | |||
| 296 | rsize = (unsigned long)pitch * (unsigned long)height; | ||
| 297 | |||
| 298 | /* Ok, now we try to figure out the address of the framebuffer. | ||
| 299 | * | ||
| 300 | * Unfortunately, Open Firmware doesn't provide a standard way to do | ||
| 301 | * so. All we can do is a dodgy heuristic that happens to work in | ||
| 302 | * practice. On most machines, the "address" property contains what | ||
| 303 | * we need, though not on Matrox cards found in IBM machines. What I've | ||
| 304 | * found that appears to give good results is to go through the PCI | ||
| 305 | * ranges and pick one that is both big enough and if possible encloses | ||
| 306 | * the "address" property. If none match, we pick the biggest | ||
| 307 | */ | ||
| 308 | up = (u32 *)get_property(dp, "linux,bootx-addr", &len); | ||
| 309 | if (up == NULL) | ||
| 310 | up = (u32 *)get_property(dp, "address", &len); | ||
| 311 | if (up && len == sizeof(u32)) | ||
| 312 | addr_prop = *up; | ||
| 313 | |||
| 314 | for (i = 0; (addrp = of_get_address(dp, i, &asize, &flags)) | ||
| 315 | != NULL; i++) { | ||
| 316 | int match_addrp = 0; | ||
| 317 | |||
| 318 | if (!(flags & IORESOURCE_MEM)) | ||
| 319 | continue; | ||
| 320 | if (asize < rsize) | ||
| 321 | continue; | ||
| 322 | rstart = of_translate_address(dp, addrp); | ||
| 323 | if (rstart == OF_BAD_ADDR) | ||
| 324 | continue; | ||
| 325 | if (addr_prop && (rstart <= addr_prop) && | ||
| 326 | ((rstart + asize) >= (addr_prop + rsize))) | ||
| 327 | match_addrp = 1; | ||
| 328 | if (match_addrp) { | ||
| 329 | address = addr_prop; | ||
| 330 | break; | ||
| 331 | } | ||
| 332 | if (rsize > max_size) { | ||
| 333 | max_size = rsize; | ||
| 334 | address = OF_BAD_ADDR; | ||
| 335 | } | ||
| 336 | |||
| 337 | if (address == OF_BAD_ADDR) | ||
| 338 | address = rstart; | ||
| 339 | } | ||
| 340 | if (address == OF_BAD_ADDR && addr_prop) | ||
| 341 | address = (u64)addr_prop; | ||
| 342 | if (address != OF_BAD_ADDR) { | ||
| 343 | /* kludge for valkyrie */ | ||
| 344 | if (strcmp(dp->name, "valkyrie") == 0) | ||
| 345 | address += 0x1000; | ||
| 346 | offb_init_fb(dp->name, dp->full_name, width, height, depth, | ||
| 347 | pitch, address, dp); | ||
| 348 | } | ||
| 349 | } | 236 | } |
| 350 | 237 | ||
| 351 | static void __init offb_init_fb(const char *name, const char *full_name, | 238 | static void __init offb_init_fb(const char *name, const char *full_name, |
| @@ -402,45 +289,39 @@ static void __init offb_init_fb(const char *name, const char *full_name, | |||
| 402 | 289 | ||
| 403 | par->cmap_type = cmap_unknown; | 290 | par->cmap_type = cmap_unknown; |
| 404 | if (depth == 8) { | 291 | if (depth == 8) { |
| 405 | |||
| 406 | /* Palette hacks disabled for now */ | 292 | /* Palette hacks disabled for now */ |
| 407 | #if 0 | ||
| 408 | if (dp && !strncmp(name, "ATY,Rage128", 11)) { | 293 | if (dp && !strncmp(name, "ATY,Rage128", 11)) { |
| 409 | unsigned long regbase = dp->addrs[2].address; | 294 | par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff); |
| 410 | par->cmap_adr = ioremap(regbase, 0x1FFF); | 295 | if (par->cmap_adr) |
| 411 | par->cmap_type = cmap_r128; | 296 | par->cmap_type = cmap_r128; |
| 412 | } else if (dp && (!strncmp(name, "ATY,RageM3pA", 12) | 297 | } else if (dp && (!strncmp(name, "ATY,RageM3pA", 12) |
| 413 | || !strncmp(name, "ATY,RageM3p12A", 14))) { | 298 | || !strncmp(name, "ATY,RageM3p12A", 14))) { |
| 414 | unsigned long regbase = | 299 | par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff); |
| 415 | dp->parent->addrs[2].address; | 300 | if (par->cmap_adr) |
| 416 | par->cmap_adr = ioremap(regbase, 0x1FFF); | 301 | par->cmap_type = cmap_M3A; |
| 417 | par->cmap_type = cmap_M3A; | ||
| 418 | } else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) { | 302 | } else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) { |
| 419 | unsigned long regbase = | 303 | par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff); |
| 420 | dp->parent->addrs[2].address; | 304 | if (par->cmap_adr) |
| 421 | par->cmap_adr = ioremap(regbase, 0x1FFF); | 305 | par->cmap_type = cmap_M3B; |
| 422 | par->cmap_type = cmap_M3B; | ||
| 423 | } else if (dp && !strncmp(name, "ATY,Rage6", 9)) { | 306 | } else if (dp && !strncmp(name, "ATY,Rage6", 9)) { |
| 424 | unsigned long regbase = dp->addrs[1].address; | 307 | par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff); |
| 425 | par->cmap_adr = ioremap(regbase, 0x1FFF); | 308 | if (par->cmap_adr) |
| 426 | par->cmap_type = cmap_radeon; | 309 | par->cmap_type = cmap_radeon; |
| 427 | } else if (!strncmp(name, "ATY,", 4)) { | 310 | } else if (!strncmp(name, "ATY,", 4)) { |
| 428 | unsigned long base = address & 0xff000000UL; | 311 | unsigned long base = address & 0xff000000UL; |
| 429 | par->cmap_adr = | 312 | par->cmap_adr = |
| 430 | ioremap(base + 0x7ff000, 0x1000) + 0xcc0; | 313 | ioremap(base + 0x7ff000, 0x1000) + 0xcc0; |
| 431 | par->cmap_data = par->cmap_adr + 1; | 314 | par->cmap_data = par->cmap_adr + 1; |
| 432 | par->cmap_type = cmap_m64; | 315 | par->cmap_type = cmap_m64; |
| 433 | } else if (device_is_compatible(dp, "pci1014,b7")) { | 316 | } else if (dp && device_is_compatible(dp, "pci1014,b7")) { |
| 434 | unsigned long regbase = dp->addrs[0].address; | 317 | par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000); |
| 435 | par->cmap_adr = ioremap(regbase + 0x6000, 0x1000); | 318 | if (par->cmap_adr) |
| 436 | par->cmap_type = cmap_gxt2000; | 319 | par->cmap_type = cmap_gxt2000; |
| 437 | } | 320 | } |
| 438 | #endif | 321 | fix->visual = (par->cmap_type != cmap_unknown) ? |
| 439 | fix->visual = par->cmap_adr ? FB_VISUAL_PSEUDOCOLOR | 322 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR; |
| 440 | : FB_VISUAL_STATIC_PSEUDOCOLOR; | ||
| 441 | } else | 323 | } else |
| 442 | fix->visual = /* par->cmap_adr ? FB_VISUAL_DIRECTCOLOR | 324 | fix->visual = FB_VISUAL_TRUECOLOR; |
| 443 | : */ FB_VISUAL_TRUECOLOR; | ||
| 444 | 325 | ||
| 445 | var->xoffset = var->yoffset = 0; | 326 | var->xoffset = var->yoffset = 0; |
| 446 | switch (depth) { | 327 | switch (depth) { |
| @@ -520,5 +401,139 @@ static void __init offb_init_fb(const char *name, const char *full_name, | |||
| 520 | info->node, full_name); | 401 | info->node, full_name); |
| 521 | } | 402 | } |
| 522 | 403 | ||
| 404 | |||
| 405 | static void __init offb_init_nodriver(struct device_node *dp, int no_real_node) | ||
| 406 | { | ||
| 407 | unsigned int len; | ||
| 408 | int i, width = 640, height = 480, depth = 8, pitch = 640; | ||
| 409 | unsigned int flags, rsize, addr_prop = 0; | ||
| 410 | unsigned long max_size = 0; | ||
| 411 | u64 rstart, address = OF_BAD_ADDR; | ||
| 412 | u32 *pp, *addrp, *up; | ||
| 413 | u64 asize; | ||
| 414 | |||
| 415 | pp = (u32 *)get_property(dp, "linux,bootx-depth", &len); | ||
| 416 | if (pp == NULL) | ||
| 417 | pp = (u32 *)get_property(dp, "depth", &len); | ||
| 418 | if (pp && len == sizeof(u32)) | ||
| 419 | depth = *pp; | ||
| 420 | |||
| 421 | pp = (u32 *)get_property(dp, "linux,bootx-width", &len); | ||
| 422 | if (pp == NULL) | ||
| 423 | pp = (u32 *)get_property(dp, "width", &len); | ||
| 424 | if (pp && len == sizeof(u32)) | ||
| 425 | width = *pp; | ||
| 426 | |||
| 427 | pp = (u32 *)get_property(dp, "linux,bootx-height", &len); | ||
| 428 | if (pp == NULL) | ||
| 429 | pp = (u32 *)get_property(dp, "height", &len); | ||
| 430 | if (pp && len == sizeof(u32)) | ||
| 431 | height = *pp; | ||
| 432 | |||
| 433 | pp = (u32 *)get_property(dp, "linux,bootx-linebytes", &len); | ||
| 434 | if (pp == NULL) | ||
| 435 | pp = (u32 *)get_property(dp, "linebytes", &len); | ||
| 436 | if (pp && len == sizeof(u32)) | ||
| 437 | pitch = *pp; | ||
| 438 | else | ||
| 439 | pitch = width * ((depth + 7) / 8); | ||
| 440 | |||
| 441 | rsize = (unsigned long)pitch * (unsigned long)height; | ||
| 442 | |||
| 443 | /* Ok, now we try to figure out the address of the framebuffer. | ||
| 444 | * | ||
| 445 | * Unfortunately, Open Firmware doesn't provide a standard way to do | ||
| 446 | * so. All we can do is a dodgy heuristic that happens to work in | ||
| 447 | * practice. On most machines, the "address" property contains what | ||
| 448 | * we need, though not on Matrox cards found in IBM machines. What I've | ||
| 449 | * found that appears to give good results is to go through the PCI | ||
| 450 | * ranges and pick one that is both big enough and if possible encloses | ||
| 451 | * the "address" property. If none match, we pick the biggest | ||
| 452 | */ | ||
| 453 | up = (u32 *)get_property(dp, "linux,bootx-addr", &len); | ||
| 454 | if (up == NULL) | ||
| 455 | up = (u32 *)get_property(dp, "address", &len); | ||
| 456 | if (up && len == sizeof(u32)) | ||
| 457 | addr_prop = *up; | ||
| 458 | |||
| 459 | /* Hack for when BootX is passing us */ | ||
| 460 | if (no_real_node) | ||
| 461 | goto skip_addr; | ||
| 462 | |||
| 463 | for (i = 0; (addrp = of_get_address(dp, i, &asize, &flags)) | ||
| 464 | != NULL; i++) { | ||
| 465 | int match_addrp = 0; | ||
| 466 | |||
| 467 | if (!(flags & IORESOURCE_MEM)) | ||
| 468 | continue; | ||
| 469 | if (asize < rsize) | ||
| 470 | continue; | ||
| 471 | rstart = of_translate_address(dp, addrp); | ||
| 472 | if (rstart == OF_BAD_ADDR) | ||
| 473 | continue; | ||
| 474 | if (addr_prop && (rstart <= addr_prop) && | ||
| 475 | ((rstart + asize) >= (addr_prop + rsize))) | ||
| 476 | match_addrp = 1; | ||
| 477 | if (match_addrp) { | ||
| 478 | address = addr_prop; | ||
| 479 | break; | ||
| 480 | } | ||
| 481 | if (rsize > max_size) { | ||
| 482 | max_size = rsize; | ||
| 483 | address = OF_BAD_ADDR; | ||
| 484 | } | ||
| 485 | |||
| 486 | if (address == OF_BAD_ADDR) | ||
| 487 | address = rstart; | ||
| 488 | } | ||
| 489 | skip_addr: | ||
| 490 | if (address == OF_BAD_ADDR && addr_prop) | ||
| 491 | address = (u64)addr_prop; | ||
| 492 | if (address != OF_BAD_ADDR) { | ||
| 493 | /* kludge for valkyrie */ | ||
| 494 | if (strcmp(dp->name, "valkyrie") == 0) | ||
| 495 | address += 0x1000; | ||
| 496 | offb_init_fb(no_real_node ? "bootx" : dp->name, | ||
| 497 | no_real_node ? "display" : dp->full_name, | ||
| 498 | width, height, depth, pitch, address, | ||
| 499 | no_real_node ? dp : NULL); | ||
| 500 | } | ||
| 501 | } | ||
| 502 | |||
| 503 | static int __init offb_init(void) | ||
| 504 | { | ||
| 505 | struct device_node *dp = NULL, *boot_disp = NULL; | ||
| 506 | |||
| 507 | if (fb_get_options("offb", NULL)) | ||
| 508 | return -ENODEV; | ||
| 509 | |||
| 510 | /* Check if we have a MacOS display without a node spec */ | ||
| 511 | if (get_property(of_chosen, "linux,bootx-noscreen", NULL) != NULL) { | ||
| 512 | /* The old code tried to work out which node was the MacOS | ||
| 513 | * display based on the address. I'm dropping that since the | ||
| 514 | * lack of a node spec only happens with old BootX versions | ||
| 515 | * (users can update) and with this code, they'll still get | ||
| 516 | * a display (just not the palette hacks). | ||
| 517 | */ | ||
| 518 | offb_init_nodriver(of_chosen, 1); | ||
| 519 | } | ||
| 520 | |||
| 521 | for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) { | ||
| 522 | if (get_property(dp, "linux,opened", NULL) && | ||
| 523 | get_property(dp, "linux,boot-display", NULL)) { | ||
| 524 | boot_disp = dp; | ||
| 525 | offb_init_nodriver(dp, 0); | ||
| 526 | } | ||
| 527 | } | ||
| 528 | for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) { | ||
| 529 | if (get_property(dp, "linux,opened", NULL) && | ||
| 530 | dp != boot_disp) | ||
| 531 | offb_init_nodriver(dp, 0); | ||
| 532 | } | ||
| 533 | |||
| 534 | return 0; | ||
| 535 | } | ||
| 536 | |||
| 537 | |||
| 523 | module_init(offb_init); | 538 | module_init(offb_init); |
| 524 | MODULE_LICENSE("GPL"); | 539 | MODULE_LICENSE("GPL"); |
