Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cirrusfb: various improvements

Various improvements to the code:
- kill a structure with only one
field: multiplexing and use the
field directly
- move the cirrusfb_ops structure
down the file to kill forward
declarations
- move cirrusfb_init() to kill
forward declaration
- kill register loads done already
in the init_vgachip()
- kill assigments done by higher
layer in the cirrusfb_pan_display()
- do not overwrite line pitch bit in
the CL_CRT1D register
- kill btype variables if they were
used only once or twice
- add cpu_relax() in the busy waiting
loop

The fix to the CL_CRT1D register handling makess the 1024x768 32bpp mode
work. Previously, only lower resolution modes have worked with 32bpp.

Signed-off-by: Krzysztof Helt <krzysztof.h1@poczta.fm>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Krzysztof Helt and committed by
Linus Torvalds
48c329e9 c4dec396

+58 -144
+58 -144
drivers/video/cirrusfb.c
··· 313 313 }; 314 314 #endif /* CONFIG_ZORRO */ 315 315 316 - struct cirrusfb_regs { 317 - int multiplexing; 318 - }; 319 - 320 316 #ifdef CIRRUSFB_DEBUG 321 317 enum cirrusfb_dbg_reg_class { 322 318 CRT, ··· 327 331 enum cirrus_board btype; 328 332 unsigned char SFR; /* Shadow of special function register */ 329 333 330 - struct cirrusfb_regs currentmode; 334 + int multiplexing; 331 335 int blank_mode; 332 336 u32 pseudo_palette[16]; 333 337 ··· 341 345 /**** BEGIN PROTOTYPES ******************************************************/ 342 346 343 347 /*--- Interface used by the world ------------------------------------------*/ 344 - static int cirrusfb_init(void); 345 - #ifndef MODULE 346 - static int cirrusfb_setup(char *options); 347 - #endif 348 - 349 - static int cirrusfb_open(struct fb_info *info, int user); 350 - static int cirrusfb_release(struct fb_info *info, int user); 351 - static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green, 352 - unsigned blue, unsigned transp, 353 - struct fb_info *info); 354 - static int cirrusfb_check_var(struct fb_var_screeninfo *var, 355 - struct fb_info *info); 356 - static int cirrusfb_set_par(struct fb_info *info); 357 348 static int cirrusfb_pan_display(struct fb_var_screeninfo *var, 358 349 struct fb_info *info); 359 - static int cirrusfb_blank(int blank_mode, struct fb_info *info); 360 - static void cirrusfb_fillrect(struct fb_info *info, 361 - const struct fb_fillrect *region); 362 - static void cirrusfb_copyarea(struct fb_info *info, 363 - const struct fb_copyarea *area); 364 - static void cirrusfb_imageblit(struct fb_info *info, 365 - const struct fb_image *image); 366 - 367 - /* function table of the above functions */ 368 - static struct fb_ops cirrusfb_ops = { 369 - .owner = THIS_MODULE, 370 - .fb_open = cirrusfb_open, 371 - .fb_release = cirrusfb_release, 372 - .fb_setcolreg = cirrusfb_setcolreg, 373 - .fb_check_var = cirrusfb_check_var, 374 - .fb_set_par = cirrusfb_set_par, 375 - .fb_pan_display = cirrusfb_pan_display, 376 - .fb_blank = cirrusfb_blank, 377 - .fb_fillrect = cirrusfb_fillrect, 378 - .fb_copyarea = cirrusfb_copyarea, 379 - .fb_imageblit = cirrusfb_imageblit, 380 - }; 381 350 382 351 /*--- Internal routines ----------------------------------------------------*/ 383 352 static void init_vgachip(struct fb_info *info); ··· 548 587 } 549 588 550 589 static int cirrusfb_decode_var(const struct fb_var_screeninfo *var, 551 - struct cirrusfb_regs *regs, 552 590 struct fb_info *info) 553 591 { 554 592 long freq; ··· 588 628 dev_dbg(info->device, "desired pixclock: %ld kHz\n", freq); 589 629 590 630 maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx]; 591 - regs->multiplexing = 0; 631 + cinfo->multiplexing = 0; 592 632 593 633 /* If the frequency is greater than we can support, we might be able 594 634 * to use multiplexing for the video mode */ ··· 596 636 switch (cinfo->btype) { 597 637 case BT_ALPINE: 598 638 case BT_GD5480: 599 - regs->multiplexing = 1; 639 + cinfo->multiplexing = 1; 600 640 break; 601 641 602 642 default: ··· 651 691 { 652 692 struct cirrusfb_info *cinfo = info->par; 653 693 struct fb_var_screeninfo *var = &info->var; 654 - struct cirrusfb_regs regs; 655 694 u8 __iomem *regbase = cinfo->regbase; 656 695 unsigned char tmp; 657 696 int err; ··· 668 709 669 710 init_vgachip(info); 670 711 671 - err = cirrusfb_decode_var(var, &regs, info); 712 + err = cirrusfb_decode_var(var, info); 672 713 if (err) { 673 714 /* should never happen */ 674 715 dev_dbg(info->device, "mode change aborted. invalid var.\n"); ··· 712 753 vsyncend /= 2; 713 754 vdispend /= 2; 714 755 } 715 - if (regs.multiplexing) { 756 + if (cinfo->multiplexing) { 716 757 htotal /= 2; 717 758 hsyncstart /= 2; 718 759 hsyncend /= 2; ··· 923 964 case BT_ALPINE: 924 965 case BT_GD5480: 925 966 vga_wseq(regbase, CL_SEQR7, 926 - regs.multiplexing ? 967 + cinfo->multiplexing ? 927 968 bi->sr07_1bpp_mux : bi->sr07_1bpp); 928 969 break; 929 970 ··· 977 1018 978 1019 /* pixel mask: pass-through for first plane */ 979 1020 WGen(cinfo, VGA_PEL_MSK, 0x01); 980 - if (regs.multiplexing) 1021 + if (cinfo->multiplexing) 981 1022 /* hidden dac reg: 1280x1024 */ 982 1023 WHDR(cinfo, 0x4a); 983 1024 else ··· 1006 1047 case BT_ALPINE: 1007 1048 case BT_GD5480: 1008 1049 vga_wseq(regbase, CL_SEQR7, 1009 - regs.multiplexing ? 1050 + cinfo->multiplexing ? 1010 1051 bi->sr07_8bpp_mux : bi->sr07_8bpp); 1011 1052 break; 1012 1053 ··· 1060 1101 1061 1102 /* mode register: 256 color mode */ 1062 1103 vga_wgfx(regbase, VGA_GFX_MODE, 64); 1063 - /* pixel mask: pass-through all planes */ 1064 - WGen(cinfo, VGA_PEL_MSK, 0xff); 1065 - if (regs.multiplexing) 1104 + if (cinfo->multiplexing) 1066 1105 /* hidden dac reg: 1280x1024 */ 1067 1106 WHDR(cinfo, 0x4a); 1068 1107 else 1069 1108 /* hidden dac: nothing */ 1070 1109 WHDR(cinfo, 0); 1071 - /* memory mode: chain4, ext. memory */ 1072 - vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a); 1073 - /* plane mask: enable writing to all 4 planes */ 1074 - vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff); 1075 1110 } 1076 1111 1077 1112 /****************************************************** ··· 1130 1177 1131 1178 /* mode register: 256 color mode */ 1132 1179 vga_wgfx(regbase, VGA_GFX_MODE, 64); 1133 - /* pixel mask: pass-through all planes */ 1134 - WGen(cinfo, VGA_PEL_MSK, 0xff); 1135 1180 #ifdef CONFIG_PCI 1136 1181 WHDR(cinfo, 0xc1); /* Copy Xbh */ 1137 1182 #elif defined(CONFIG_ZORRO) 1138 1183 /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */ 1139 1184 WHDR(cinfo, 0xa0); /* hidden dac reg: nothing special */ 1140 1185 #endif 1141 - /* memory mode: chain4, ext. memory */ 1142 - vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a); 1143 - /* plane mask: enable writing to all 4 planes */ 1144 - vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff); 1145 1186 } 1146 1187 1147 1188 /****************************************************** ··· 1200 1253 1201 1254 /* mode register: 256 color mode */ 1202 1255 vga_wgfx(regbase, VGA_GFX_MODE, 64); 1203 - /* pixel mask: pass-through all planes */ 1204 - WGen(cinfo, VGA_PEL_MSK, 0xff); 1205 1256 /* hidden dac reg: 8-8-8 mode (24 or 32) */ 1206 1257 WHDR(cinfo, 0xc5); 1207 - /* memory mode: chain4, ext. memory */ 1208 - vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a); 1209 - /* plane mask: enable writing to all 4 planes */ 1210 - vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff); 1211 1258 } 1212 1259 1213 1260 /****************************************************** ··· 1250 1309 } 1251 1310 1252 1311 1253 - /* text cursor location high */ 1254 - vga_wcrt(regbase, VGA_CRTC_CURSOR_HI, 0); 1255 - /* text cursor location low */ 1256 - vga_wcrt(regbase, VGA_CRTC_CURSOR_LO, 0); 1257 - /* underline row scanline = at very bottom */ 1258 - vga_wcrt(regbase, VGA_CRTC_UNDERLINE, 0); 1259 - 1260 - /* controller mode */ 1261 - vga_wattr(regbase, VGA_ATC_MODE, 1); 1262 - /* overscan (border) color */ 1263 - vga_wattr(regbase, VGA_ATC_OVERSCAN, 0); 1264 - /* color plane enable */ 1265 - vga_wattr(regbase, VGA_ATC_PLANE_ENABLE, 15); 1266 1312 /* pixel panning */ 1267 1313 vga_wattr(regbase, CL_AR33, 0); 1268 - /* color select */ 1269 - vga_wattr(regbase, VGA_ATC_COLOR_PAGE, 0); 1270 1314 1271 1315 /* [ EGS: SetOffset(); ] */ 1272 1316 /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */ 1273 1317 AttrOn(cinfo); 1274 - 1275 - /* set/reset register */ 1276 - vga_wgfx(regbase, VGA_GFX_SR_VALUE, 0); 1277 - /* set/reset enable */ 1278 - vga_wgfx(regbase, VGA_GFX_SR_ENABLE, 0); 1279 - /* color compare */ 1280 - vga_wgfx(regbase, VGA_GFX_COMPARE_VALUE, 0); 1281 - /* data rotate */ 1282 - vga_wgfx(regbase, VGA_GFX_DATA_ROTATE, 0); 1283 - /* read map select */ 1284 - vga_wgfx(regbase, VGA_GFX_PLANE_READ, 0); 1285 - /* miscellaneous register */ 1286 - vga_wgfx(regbase, VGA_GFX_MISC, 1); 1287 - /* color don't care */ 1288 - vga_wgfx(regbase, VGA_GFX_COMPARE_MASK, 15); 1289 - /* bit mask */ 1290 - vga_wgfx(regbase, VGA_GFX_BIT_MASK, 255); 1291 - 1292 - /* graphics cursor attributes: nothing special */ 1293 - vga_wseq(regbase, CL_SEQR12, 0x0); 1294 1318 1295 1319 if (cinfo->btype == BT_LAGUNA) { 1296 1320 /* no tiles */ ··· 1274 1368 1275 1369 vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp); 1276 1370 dev_dbg(info->device, "CL_SEQR1: %d\n", tmp); 1277 - 1278 - cinfo->currentmode = regs; 1279 1371 1280 1372 /* pan to requested offset */ 1281 1373 cirrusfb_pan_display(var, info); ··· 1347 1443 if (var->vmode & FB_VMODE_YWRAP) 1348 1444 return -EINVAL; 1349 1445 1350 - info->var.xoffset = var->xoffset; 1351 - info->var.yoffset = var->yoffset; 1352 - 1353 1446 xoffset = var->xoffset * info->var.bits_per_pixel / 8; 1354 1447 yoffset = var->yoffset; 1355 1448 ··· 1381 1480 vga_wcrt(cinfo->regbase, CL_CRT1B, tmp); 1382 1481 1383 1482 /* construct bit 19 of screen start address */ 1384 - if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) 1385 - vga_wcrt(cinfo->regbase, CL_CRT1D, (base >> 12) & 0x80); 1483 + if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) { 1484 + tmp = vga_rcrt(cinfo->regbase, CL_CRT1D) & ~0x80; 1485 + tmp |= (base >> 12) & 0x80; 1486 + vga_wcrt(cinfo->regbase, CL_CRT1D, tmp); 1487 + } 1386 1488 1387 1489 /* write pixel panning value to AR33; this does not quite work in 8bpp 1388 1490 * ··· 1574 1670 vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff); 1575 1671 /* character map select: doesn't even matter in gx mode */ 1576 1672 vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00); 1577 - /* memory mode: chain-4, no odd/even, ext. memory */ 1578 - vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0e); 1673 + /* memory mode: chain4, ext. memory */ 1674 + vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0a); 1579 1675 1580 1676 /* controller-internal base address of video memory */ 1581 1677 if (bi->init_sr07) ··· 1688 1784 vga_wattr(cinfo->regbase, VGA_ATC_OVERSCAN, 0x00); 1689 1785 /* Color Plane enable: Enable all 4 planes */ 1690 1786 vga_wattr(cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f); 1691 - /* ### vga_wattr(cinfo->regbase, CL_AR33, 0x00); * Pixel Panning: - */ 1692 1787 /* Color Select: - */ 1693 1788 vga_wattr(cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00); 1694 1789 ··· 1966 2063 } 1967 2064 #endif /* CONFIG_ZORRO */ 1968 2065 2066 + /* function table of the above functions */ 2067 + static struct fb_ops cirrusfb_ops = { 2068 + .owner = THIS_MODULE, 2069 + .fb_open = cirrusfb_open, 2070 + .fb_release = cirrusfb_release, 2071 + .fb_setcolreg = cirrusfb_setcolreg, 2072 + .fb_check_var = cirrusfb_check_var, 2073 + .fb_set_par = cirrusfb_set_par, 2074 + .fb_pan_display = cirrusfb_pan_display, 2075 + .fb_blank = cirrusfb_blank, 2076 + .fb_fillrect = cirrusfb_fillrect, 2077 + .fb_copyarea = cirrusfb_copyarea, 2078 + .fb_imageblit = cirrusfb_imageblit, 2079 + }; 2080 + 1969 2081 static int __devinit cirrusfb_set_fbinfo(struct fb_info *info) 1970 2082 { 1971 2083 struct cirrusfb_info *cinfo = info->par; ··· 2029 2111 { 2030 2112 struct cirrusfb_info *cinfo = info->par; 2031 2113 int err; 2032 - enum cirrus_board btype; 2033 - 2034 - btype = cinfo->btype; 2035 2114 2036 2115 /* sanity checks */ 2037 - assert(btype != BT_NONE); 2116 + assert(cinfo->btype != BT_NONE); 2038 2117 2039 2118 /* set all the vital stuff */ 2040 2119 cirrusfb_set_fbinfo(info); ··· 2047 2132 2048 2133 info->var.activate = FB_ACTIVATE_NOW; 2049 2134 2050 - err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info); 2135 + err = cirrusfb_decode_var(&info->var, info); 2051 2136 if (err < 0) { 2052 2137 /* should never happen */ 2053 2138 dev_dbg(info->device, ··· 2089 2174 { 2090 2175 struct cirrusfb_info *cinfo; 2091 2176 struct fb_info *info; 2092 - enum cirrus_board btype; 2093 2177 unsigned long board_addr, board_size; 2094 2178 int ret; 2095 2179 ··· 2106 2192 } 2107 2193 2108 2194 cinfo = info->par; 2109 - cinfo->btype = btype = (enum cirrus_board) ent->driver_data; 2195 + cinfo->btype = (enum cirrus_board) ent->driver_data; 2110 2196 2111 2197 dev_dbg(info->device, 2112 2198 " Found PCI device, base address 0 is 0x%Lx, btype set to %d\n", 2113 - (unsigned long long)pdev->resource[0].start, btype); 2199 + (unsigned long long)pdev->resource[0].start, cinfo->btype); 2114 2200 dev_dbg(info->device, " base address 1 is 0x%Lx\n", 2115 2201 (unsigned long long)pdev->resource[1].start); 2116 2202 ··· 2133 2219 dev_dbg(info->device, "Board address: 0x%lx, register address: 0x%lx\n", 2134 2220 board_addr, info->fix.mmio_start); 2135 2221 2136 - board_size = (btype == BT_GD5480) ? 2222 + board_size = (cinfo->btype == BT_GD5480) ? 2137 2223 32 * MB_ : cirrusfb_get_memsize(info, cinfo->regbase); 2138 2224 2139 2225 ret = pci_request_regions(pdev, "cirrusfb"); ··· 2339 2425 }; 2340 2426 #endif /* CONFIG_ZORRO */ 2341 2427 2342 - static int __init cirrusfb_init(void) 2343 - { 2344 - int error = 0; 2345 - 2346 - #ifndef MODULE 2347 - char *option = NULL; 2348 - 2349 - if (fb_get_options("cirrusfb", &option)) 2350 - return -ENODEV; 2351 - cirrusfb_setup(option); 2352 - #endif 2353 - 2354 - #ifdef CONFIG_ZORRO 2355 - error |= zorro_register_driver(&cirrusfb_zorro_driver); 2356 - #endif 2357 - #ifdef CONFIG_PCI 2358 - error |= pci_register_driver(&cirrusfb_pci_driver); 2359 - #endif 2360 - return error; 2361 - } 2362 - 2363 2428 #ifndef MODULE 2364 2429 static int __init cirrusfb_setup(char *options) 2365 2430 { ··· 2369 2476 MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>"); 2370 2477 MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips"); 2371 2478 MODULE_LICENSE("GPL"); 2479 + 2480 + static int __init cirrusfb_init(void) 2481 + { 2482 + int error = 0; 2483 + 2484 + #ifndef MODULE 2485 + char *option = NULL; 2486 + 2487 + if (fb_get_options("cirrusfb", &option)) 2488 + return -ENODEV; 2489 + cirrusfb_setup(option); 2490 + #endif 2491 + 2492 + #ifdef CONFIG_ZORRO 2493 + error |= zorro_register_driver(&cirrusfb_zorro_driver); 2494 + #endif 2495 + #ifdef CONFIG_PCI 2496 + error |= pci_register_driver(&cirrusfb_pci_driver); 2497 + #endif 2498 + return error; 2499 + } 2372 2500 2373 2501 static void __exit cirrusfb_exit(void) 2374 2502 { ··· 2597 2683 { 2598 2684 /* now busy-wait until we're done */ 2599 2685 while (vga_rgfx(regbase, CL_GR31) & 0x08) 2600 - /* do nothing */ ; 2686 + cpu_relax(); 2601 2687 } 2602 2688 2603 2689 /*******************************************************************