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 /drivers/video/macfb.c | |
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>
Diffstat (limited to 'drivers/video/macfb.c')
-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: |