diff options
| author | Finn Thain <fthain@telegraphics.com.au> | 2009-11-03 08:51:18 -0500 |
|---|---|---|
| committer | Geert Uytterhoeven <geert@linux-m68k.org> | 2010-02-27 12:31:16 -0500 |
| commit | 99e11ab20b26b3236490ae687ab309c2601d180b (patch) | |
| tree | e44e01130117c9a17801bfc2c3434a2d3fd9275f | |
| parent | 34c41d0ab8c2a96bb3db89a209c1dd7e8c44fe13 (diff) | |
macfb: fix 24-bit visual and stuff
Lots of changes. Remove volatile keywords. Take the advice in the comments
and change video_slot to slot_addr. Factor out fifteen or so "channel >>
8" shifts into three shifts higher up the call graph. Make
csc_setpalette() atomic, pass the correct color values. Check for
ioremap() failure. Add missing break statement, thus fixing 24 bit console
visual (blue background bug). Remove some uninformative printk() noise.
Add a description for powerbook 140/170 graphics.
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
| -rw-r--r-- | drivers/video/macfb.c | 144 |
1 files changed, 60 insertions, 84 deletions
diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c index 8b246ee7c069..43207cc6cc19 100644 --- a/drivers/video/macfb.c +++ b/drivers/video/macfb.c | |||
| @@ -120,8 +120,6 @@ struct jet_cmap_regs { | |||
| 120 | 120 | ||
| 121 | #define PIXEL_TO_MM(a) (((a)*10)/28) /* width in mm at 72 dpi */ | 121 | #define PIXEL_TO_MM(a) (((a)*10)/28) /* width in mm at 72 dpi */ |
| 122 | 122 | ||
| 123 | static int video_slot = 0; | ||
| 124 | |||
| 125 | static struct fb_var_screeninfo macfb_defined = { | 123 | static struct fb_var_screeninfo macfb_defined = { |
| 126 | .bits_per_pixel = 8, | 124 | .bits_per_pixel = 8, |
| 127 | .activate = FB_ACTIVATE_NOW, | 125 | .activate = FB_ACTIVATE_NOW, |
| @@ -139,6 +137,7 @@ static struct fb_fix_screeninfo macfb_fix = { | |||
| 139 | .accel = FB_ACCEL_NONE, | 137 | .accel = FB_ACCEL_NONE, |
| 140 | }; | 138 | }; |
| 141 | 139 | ||
| 140 | static void *slot_addr; | ||
| 142 | static struct fb_info fb_info; | 141 | static struct fb_info fb_info; |
| 143 | static u32 pseudo_palette[16]; | 142 | static u32 pseudo_palette[16]; |
| 144 | static int inverse; | 143 | static int inverse; |
| @@ -156,10 +155,6 @@ static int dafb_setpalette(unsigned int regno, unsigned int red, | |||
| 156 | { | 155 | { |
| 157 | static int lastreg = -1; | 156 | static int lastreg = -1; |
| 158 | unsigned long flags; | 157 | unsigned long flags; |
| 159 | |||
| 160 | red >>= 8; | ||
| 161 | green >>= 8; | ||
| 162 | blue >>= 8; | ||
| 163 | 158 | ||
| 164 | local_irq_save(flags); | 159 | local_irq_save(flags); |
| 165 | 160 | ||
| @@ -205,10 +200,6 @@ static int v8_brazil_setpalette(unsigned int regno, unsigned int red, | |||
| 205 | struct fb_info *info) | 200 | struct fb_info *info) |
| 206 | { | 201 | { |
| 207 | unsigned int bpp = info->var.bits_per_pixel; | 202 | unsigned int bpp = info->var.bits_per_pixel; |
| 208 | unsigned char _red =red>>8; | ||
| 209 | unsigned char _green=green>>8; | ||
| 210 | unsigned char _blue =blue>>8; | ||
| 211 | unsigned char _regno; | ||
| 212 | unsigned long flags; | 203 | unsigned long flags; |
| 213 | 204 | ||
| 214 | if (bpp > 8) | 205 | if (bpp > 8) |
| @@ -222,16 +213,16 @@ static int v8_brazil_setpalette(unsigned int regno, unsigned int red, | |||
| 222 | * In 4bpp, the regnos are 0x0f, 0x1f, 0x2f, etc, etc | 213 | * In 4bpp, the regnos are 0x0f, 0x1f, 0x2f, etc, etc |
| 223 | * In 2bpp, the regnos are 0x3f, 0x7f, 0xbf, 0xff | 214 | * In 2bpp, the regnos are 0x3f, 0x7f, 0xbf, 0xff |
| 224 | */ | 215 | */ |
| 225 | _regno = (regno << (8 - bpp)) | (0xFF >> bpp); | 216 | regno = (regno << (8 - bpp)) | (0xFF >> bpp); |
| 226 | nubus_writeb(_regno, &v8_brazil_cmap_regs->addr); | 217 | nubus_writeb(regno, &v8_brazil_cmap_regs->addr); |
| 227 | nop(); | 218 | nop(); |
| 228 | 219 | ||
| 229 | /* send one color channel at a time */ | 220 | /* send one color channel at a time */ |
| 230 | nubus_writeb(_red, &v8_brazil_cmap_regs->lut); | 221 | nubus_writeb(red, &v8_brazil_cmap_regs->lut); |
| 231 | nop(); | 222 | nop(); |
| 232 | nubus_writeb(_green, &v8_brazil_cmap_regs->lut); | 223 | nubus_writeb(green, &v8_brazil_cmap_regs->lut); |
| 233 | nop(); | 224 | nop(); |
| 234 | nubus_writeb(_blue, &v8_brazil_cmap_regs->lut); | 225 | nubus_writeb(blue, &v8_brazil_cmap_regs->lut); |
| 235 | 226 | ||
| 236 | local_irq_restore(flags); | 227 | local_irq_restore(flags); |
| 237 | return 0; | 228 | return 0; |
| @@ -242,11 +233,6 @@ static int rbv_setpalette(unsigned int regno, unsigned int red, | |||
| 242 | unsigned int green, unsigned int blue, | 233 | unsigned int green, unsigned int blue, |
| 243 | struct fb_info *info) | 234 | struct fb_info *info) |
| 244 | { | 235 | { |
| 245 | /* use MSBs */ | ||
| 246 | unsigned char _red =red>>8; | ||
| 247 | unsigned char _green=green>>8; | ||
| 248 | unsigned char _blue =blue>>8; | ||
| 249 | unsigned char _regno; | ||
| 250 | unsigned long flags; | 236 | unsigned long flags; |
| 251 | 237 | ||
| 252 | if (info->var.bits_per_pixel > 8) | 238 | if (info->var.bits_per_pixel > 8) |
| @@ -258,22 +244,22 @@ static int rbv_setpalette(unsigned int regno, unsigned int red, | |||
| 258 | * regno #254 and #255 are the important ones for 1-bit color, | 244 | * regno #254 and #255 are the important ones for 1-bit color, |
| 259 | * regno #252-255 are the important ones for 2-bit color, etc. | 245 | * regno #252-255 are the important ones for 2-bit color, etc. |
| 260 | */ | 246 | */ |
| 261 | _regno = regno + (256-(1 << info->var.bits_per_pixel)); | 247 | regno += 256 - (1 << info->var.bits_per_pixel); |
| 262 | 248 | ||
| 263 | /* reset clut? (VideoToolbox sez "not necessary") */ | 249 | /* reset clut? (VideoToolbox sez "not necessary") */ |
| 264 | nubus_writeb(0xFF, &rbv_cmap_regs->cntl); | 250 | nubus_writeb(0xFF, &rbv_cmap_regs->cntl); |
| 265 | nop(); | 251 | nop(); |
| 266 | 252 | ||
| 267 | /* tell clut which address to use. */ | 253 | /* tell clut which address to use. */ |
| 268 | nubus_writeb(_regno, &rbv_cmap_regs->addr); | 254 | nubus_writeb(regno, &rbv_cmap_regs->addr); |
| 269 | nop(); | 255 | nop(); |
| 270 | 256 | ||
| 271 | /* send one color channel at a time. */ | 257 | /* send one color channel at a time. */ |
| 272 | nubus_writeb(_red, &rbv_cmap_regs->lut); | 258 | nubus_writeb(red, &rbv_cmap_regs->lut); |
| 273 | nop(); | 259 | nop(); |
| 274 | nubus_writeb(_green, &rbv_cmap_regs->lut); | 260 | nubus_writeb(green, &rbv_cmap_regs->lut); |
| 275 | nop(); | 261 | nop(); |
| 276 | nubus_writeb(_blue, &rbv_cmap_regs->lut); | 262 | nubus_writeb(blue, &rbv_cmap_regs->lut); |
| 277 | 263 | ||
| 278 | local_irq_restore(flags); | 264 | local_irq_restore(flags); |
| 279 | return 0; | 265 | return 0; |
| @@ -284,25 +270,19 @@ static int mdc_setpalette(unsigned int regno, unsigned int red, | |||
| 284 | unsigned int green, unsigned int blue, | 270 | unsigned int green, unsigned int blue, |
| 285 | struct fb_info *info) | 271 | struct fb_info *info) |
| 286 | { | 272 | { |
| 287 | volatile struct mdc_cmap_regs *cmap_regs = | 273 | struct mdc_cmap_regs *cmap_regs = slot_addr; |
| 288 | nubus_slot_addr(video_slot); | ||
| 289 | /* use MSBs */ | ||
| 290 | unsigned char _red =red>>8; | ||
| 291 | unsigned char _green=green>>8; | ||
| 292 | unsigned char _blue =blue>>8; | ||
| 293 | unsigned char _regno=regno; | ||
| 294 | unsigned long flags; | 274 | unsigned long flags; |
| 295 | 275 | ||
| 296 | local_irq_save(flags); | 276 | local_irq_save(flags); |
| 297 | 277 | ||
| 298 | /* the nop's are there to order writes. */ | 278 | /* the nop's are there to order writes. */ |
| 299 | nubus_writeb(_regno, &cmap_regs->addr); | 279 | nubus_writeb(regno, &cmap_regs->addr); |
| 300 | nop(); | 280 | nop(); |
| 301 | nubus_writeb(_red, &cmap_regs->lut); | 281 | nubus_writeb(red, &cmap_regs->lut); |
| 302 | nop(); | 282 | nop(); |
| 303 | nubus_writeb(_green, &cmap_regs->lut); | 283 | nubus_writeb(green, &cmap_regs->lut); |
| 304 | nop(); | 284 | nop(); |
| 305 | nubus_writeb(_blue, &cmap_regs->lut); | 285 | nubus_writeb(blue, &cmap_regs->lut); |
| 306 | 286 | ||
| 307 | local_irq_restore(flags); | 287 | local_irq_restore(flags); |
| 308 | return 0; | 288 | return 0; |
| @@ -313,25 +293,24 @@ static int toby_setpalette(unsigned int regno, unsigned int red, | |||
| 313 | unsigned int green, unsigned int blue, | 293 | unsigned int green, unsigned int blue, |
| 314 | struct fb_info *info) | 294 | struct fb_info *info) |
| 315 | { | 295 | { |
| 316 | volatile struct toby_cmap_regs *cmap_regs = | 296 | struct toby_cmap_regs *cmap_regs = slot_addr; |
| 317 | nubus_slot_addr(video_slot); | ||
| 318 | unsigned int bpp = info->var.bits_per_pixel; | 297 | unsigned int bpp = info->var.bits_per_pixel; |
| 319 | /* use MSBs */ | ||
| 320 | unsigned char _red =~(red>>8); | ||
| 321 | unsigned char _green=~(green>>8); | ||
| 322 | unsigned char _blue =~(blue>>8); | ||
| 323 | unsigned char _regno = (regno << (8 - bpp)) | (0xFF >> bpp); | ||
| 324 | unsigned long flags; | 298 | unsigned long flags; |
| 325 | 299 | ||
| 300 | red = ~red; | ||
| 301 | green = ~green; | ||
| 302 | blue = ~blue; | ||
| 303 | regno = (regno << (8 - bpp)) | (0xFF >> bpp); | ||
| 304 | |||
| 326 | local_irq_save(flags); | 305 | local_irq_save(flags); |
| 327 | 306 | ||
| 328 | nubus_writeb(_regno, &cmap_regs->addr); | 307 | nubus_writeb(regno, &cmap_regs->addr); |
| 329 | nop(); | 308 | nop(); |
| 330 | nubus_writeb(_red, &cmap_regs->lut); | 309 | nubus_writeb(red, &cmap_regs->lut); |
| 331 | nop(); | 310 | nop(); |
| 332 | nubus_writeb(_green, &cmap_regs->lut); | 311 | nubus_writeb(green, &cmap_regs->lut); |
| 333 | nop(); | 312 | nop(); |
| 334 | nubus_writeb(_blue, &cmap_regs->lut); | 313 | nubus_writeb(blue, &cmap_regs->lut); |
| 335 | 314 | ||
| 336 | local_irq_restore(flags); | 315 | local_irq_restore(flags); |
| 337 | return 0; | 316 | return 0; |
| @@ -342,23 +321,18 @@ static int jet_setpalette(unsigned int regno, unsigned int red, | |||
| 342 | unsigned int green, unsigned int blue, | 321 | unsigned int green, unsigned int blue, |
| 343 | struct fb_info *info) | 322 | struct fb_info *info) |
| 344 | { | 323 | { |
| 345 | volatile struct jet_cmap_regs *cmap_regs = | 324 | struct jet_cmap_regs *cmap_regs = slot_addr; |
| 346 | nubus_slot_addr(video_slot); | ||
| 347 | /* use MSBs */ | ||
| 348 | unsigned char _red = (red>>8); | ||
| 349 | unsigned char _green = (green>>8); | ||
| 350 | unsigned char _blue = (blue>>8); | ||
| 351 | unsigned long flags; | 325 | unsigned long flags; |
| 352 | 326 | ||
| 353 | local_irq_save(flags); | 327 | local_irq_save(flags); |
| 354 | 328 | ||
| 355 | nubus_writeb(regno, &cmap_regs->addr); | 329 | nubus_writeb(regno, &cmap_regs->addr); |
| 356 | nop(); | 330 | nop(); |
| 357 | nubus_writeb(_red, &cmap_regs->lut); | 331 | nubus_writeb(red, &cmap_regs->lut); |
| 358 | nop(); | 332 | nop(); |
| 359 | nubus_writeb(_green, &cmap_regs->lut); | 333 | nubus_writeb(green, &cmap_regs->lut); |
| 360 | nop(); | 334 | nop(); |
| 361 | nubus_writeb(_blue, &cmap_regs->lut); | 335 | nubus_writeb(blue, &cmap_regs->lut); |
| 362 | 336 | ||
| 363 | local_irq_restore(flags); | 337 | local_irq_restore(flags); |
| 364 | return 0; | 338 | return 0; |
| @@ -383,10 +357,6 @@ static int civic_setpalette(unsigned int regno, unsigned int red, | |||
| 383 | if (info->var.bits_per_pixel > 8) | 357 | if (info->var.bits_per_pixel > 8) |
| 384 | return 1; /* failsafe */ | 358 | return 1; /* failsafe */ |
| 385 | 359 | ||
| 386 | red >>= 8; | ||
| 387 | green >>= 8; | ||
| 388 | blue >>= 8; | ||
| 389 | |||
| 390 | local_irq_save(flags); | 360 | local_irq_save(flags); |
| 391 | 361 | ||
| 392 | /* Set the register address */ | 362 | /* Set the register address */ |
| @@ -462,11 +432,17 @@ static int csc_setpalette(unsigned int regno, unsigned int red, | |||
| 462 | unsigned int green, unsigned int blue, | 432 | unsigned int green, unsigned int blue, |
| 463 | struct fb_info *info) | 433 | struct fb_info *info) |
| 464 | { | 434 | { |
| 465 | mdelay(1); | 435 | unsigned long flags; |
| 436 | |||
| 437 | local_irq_save(flags); | ||
| 438 | |||
| 439 | udelay(1); /* mklinux on PB 5300 waits for 260 ns */ | ||
| 466 | nubus_writeb(regno, &csc_cmap_regs->clut_waddr); | 440 | nubus_writeb(regno, &csc_cmap_regs->clut_waddr); |
| 467 | nubus_writeb(red, &csc_cmap_regs->clut_data); | 441 | nubus_writeb(red, &csc_cmap_regs->clut_data); |
| 468 | nubus_writeb(green, &csc_cmap_regs->clut_data); | 442 | nubus_writeb(green, &csc_cmap_regs->clut_data); |
| 469 | nubus_writeb(blue, &csc_cmap_regs->clut_data); | 443 | nubus_writeb(blue, &csc_cmap_regs->clut_data); |
| 444 | |||
| 445 | local_irq_restore(flags); | ||
| 470 | return 0; | 446 | return 0; |
| 471 | } | 447 | } |
| 472 | 448 | ||
| @@ -493,8 +469,8 @@ static int macfb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
| 493 | case 4: | 469 | case 4: |
| 494 | case 8: | 470 | case 8: |
| 495 | if (macfb_setpalette) | 471 | if (macfb_setpalette) |
| 496 | macfb_setpalette(regno, red, green, blue, | 472 | macfb_setpalette(regno, red >> 8, green >> 8, |
| 497 | fb_info); | 473 | blue >> 8, fb_info); |
| 498 | else | 474 | else |
| 499 | return 1; | 475 | return 1; |
| 500 | break; | 476 | break; |
| @@ -611,8 +587,11 @@ static int __init macfb_init(void) | |||
| 611 | * those mappings are set up, so this is in fact the safest | 587 | * those mappings are set up, so this is in fact the safest |
| 612 | * way to ensure that this driver will work on every possible Mac | 588 | * way to ensure that this driver will work on every possible Mac |
| 613 | */ | 589 | */ |
| 614 | fb_info.screen_base = ioremap(mac_bi_data.videoaddr, macfb_fix.smem_len); | 590 | fb_info.screen_base = ioremap(mac_bi_data.videoaddr, |
| 615 | 591 | macfb_fix.smem_len); | |
| 592 | if (!fb_info.screen_base) | ||
| 593 | return -ENODEV; | ||
| 594 | |||
| 616 | printk("macfb: framebuffer at 0x%08lx, mapped to 0x%p, size %dk\n", | 595 | printk("macfb: framebuffer at 0x%08lx, mapped to 0x%p, size %dk\n", |
| 617 | macfb_fix.smem_start, fb_info.screen_base, | 596 | macfb_fix.smem_start, fb_info.screen_base, |
| 618 | macfb_fix.smem_len / 1024); | 597 | macfb_fix.smem_len / 1024); |
| @@ -620,17 +599,13 @@ static int __init macfb_init(void) | |||
| 620 | macfb_defined.xres, macfb_defined.yres, | 599 | macfb_defined.xres, macfb_defined.yres, |
| 621 | macfb_defined.bits_per_pixel, macfb_fix.line_length); | 600 | macfb_defined.bits_per_pixel, macfb_fix.line_length); |
| 622 | 601 | ||
| 623 | /* | 602 | /* Fill in the available video resolution */ |
| 624 | * Fill in the available video resolution | ||
| 625 | */ | ||
| 626 | macfb_defined.xres_virtual = macfb_defined.xres; | 603 | macfb_defined.xres_virtual = macfb_defined.xres; |
| 627 | macfb_defined.yres_virtual = macfb_defined.yres; | 604 | macfb_defined.yres_virtual = macfb_defined.yres; |
| 628 | macfb_defined.height = PIXEL_TO_MM(macfb_defined.yres); | 605 | macfb_defined.height = PIXEL_TO_MM(macfb_defined.yres); |
| 629 | macfb_defined.width = PIXEL_TO_MM(macfb_defined.xres); | 606 | macfb_defined.width = PIXEL_TO_MM(macfb_defined.xres); |
| 630 | 607 | ||
| 631 | printk("macfb: scrolling: redraw\n"); | 608 | /* Some dummy values for timing to make fbset happy */ |
| 632 | |||
| 633 | /* some dummy values for timing to make fbset happy */ | ||
| 634 | macfb_defined.pixclock = 10000000 / macfb_defined.xres * | 609 | macfb_defined.pixclock = 10000000 / macfb_defined.xres * |
| 635 | 1000 / macfb_defined.yres; | 610 | 1000 / macfb_defined.yres; |
| 636 | macfb_defined.left_margin = (macfb_defined.xres / 8) & 0xf8; | 611 | macfb_defined.left_margin = (macfb_defined.xres / 8) & 0xf8; |
| @@ -666,8 +641,6 @@ static int __init macfb_init(void) | |||
| 666 | macfb_defined.green.length = 5; | 641 | macfb_defined.green.length = 5; |
| 667 | macfb_defined.blue.offset = 0; | 642 | macfb_defined.blue.offset = 0; |
| 668 | macfb_defined.blue.length = 5; | 643 | macfb_defined.blue.length = 5; |
| 669 | printk("macfb: directcolor: " | ||
| 670 | "size=1:5:5:5, shift=15:10:5:0\n"); | ||
| 671 | video_cmap_len = 16; | 644 | video_cmap_len = 16; |
| 672 | /* | 645 | /* |
| 673 | * Should actually be FB_VISUAL_DIRECTCOLOR, but this | 646 | * Should actually be FB_VISUAL_DIRECTCOLOR, but this |
| @@ -683,10 +656,9 @@ static int __init macfb_init(void) | |||
| 683 | macfb_defined.green.length = 8; | 656 | macfb_defined.green.length = 8; |
| 684 | macfb_defined.blue.offset = 0; | 657 | macfb_defined.blue.offset = 0; |
| 685 | macfb_defined.blue.length = 8; | 658 | macfb_defined.blue.length = 8; |
| 686 | printk("macfb: truecolor: " | ||
| 687 | "size=0:8:8:8, shift=0:16:8:0\n"); | ||
| 688 | video_cmap_len = 16; | 659 | video_cmap_len = 16; |
| 689 | macfb_fix.visual = FB_VISUAL_TRUECOLOR; | 660 | macfb_fix.visual = FB_VISUAL_TRUECOLOR; |
| 661 | break; | ||
| 690 | default: | 662 | default: |
| 691 | video_cmap_len = 0; | 663 | video_cmap_len = 0; |
| 692 | macfb_fix.visual = FB_VISUAL_MONO01; | 664 | macfb_fix.visual = FB_VISUAL_MONO01; |
| @@ -704,16 +676,17 @@ static int __init macfb_init(void) | |||
| 704 | * code is really broken :-) | 676 | * code is really broken :-) |
| 705 | */ | 677 | */ |
| 706 | 678 | ||
| 707 | while ((ndev = nubus_find_type(NUBUS_CAT_DISPLAY, NUBUS_TYPE_VIDEO, ndev)) | 679 | while ((ndev = nubus_find_type(NUBUS_CAT_DISPLAY, |
| 708 | != NULL) | 680 | NUBUS_TYPE_VIDEO, ndev))) |
| 709 | { | 681 | { |
| 710 | if (!(mac_bi_data.videoaddr >= ndev->board->slot_addr | 682 | unsigned long base = ndev->board->slot_addr; |
| 711 | && (mac_bi_data.videoaddr < | 683 | |
| 712 | (unsigned long)nubus_slot_addr(ndev->board->slot+1)))) | 684 | if (mac_bi_data.videoaddr < base || |
| 685 | mac_bi_data.videoaddr - base > 0xFFFFFF) | ||
| 713 | continue; | 686 | continue; |
| 687 | |||
| 714 | video_is_nubus = 1; | 688 | video_is_nubus = 1; |
| 715 | /* We should probably just use the slot address... */ | 689 | slot_addr = (unsigned char *)base; |
| 716 | video_slot = ndev->board->slot; | ||
| 717 | 690 | ||
| 718 | switch(ndev->dr_hw) { | 691 | switch(ndev->dr_hw) { |
| 719 | case NUBUS_DRHW_APPLE_MDC: | 692 | case NUBUS_DRHW_APPLE_MDC: |
| @@ -882,6 +855,9 @@ static int __init macfb_init(void) | |||
| 882 | * really support that. | 855 | * really support that. |
| 883 | */ | 856 | */ |
| 884 | 857 | ||
| 858 | /* | ||
| 859 | * Slot 0 ROM says TIM. No external video. B&W. | ||
| 860 | */ | ||
| 885 | case MAC_MODEL_PB140: | 861 | case MAC_MODEL_PB140: |
| 886 | case MAC_MODEL_PB145: | 862 | case MAC_MODEL_PB145: |
| 887 | case MAC_MODEL_PB170: | 863 | case MAC_MODEL_PB170: |
