X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fvideo%2Fpm2fb.c;h=c6dd924976a4f105457bd15c205a2938a07eeee3;hb=a08d81af37b3d7547813219da68c3c946f742fb3;hp=53dd639e97533283caf555bc94e5fbd456322cc7;hpb=8f5d050af1da13455068cefbaf3c1bc306d6fe0b;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index 53dd639..c6dd924 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c @@ -56,7 +56,7 @@ #undef PM2FB_MASTER_DEBUG #ifdef PM2FB_MASTER_DEBUG #define DPRINTK(a, b...) \ - printk(KERN_DEBUG "pm2fb: %s: " a, __FUNCTION__ , ## b) + printk(KERN_DEBUG "pm2fb: %s: " a, __func__ , ## b) #else #define DPRINTK(a, b...) #endif @@ -66,8 +66,8 @@ /* * Driver data */ -static int hwcursor; -static char *mode __devinitdata; +static int hwcursor = 1; +static char *mode_option __devinitdata; /* * The XFree GLINT driver will (I think to implement hardware cursor @@ -193,8 +193,8 @@ static inline void pm2v_RDAC_WR(struct pm2fb_par *p, s32 idx, u32 v) #else static inline void WAIT_FIFO(struct pm2fb_par *p, u32 a) { - while (pm2_RD(p, PM2R_IN_FIFO_SPACE) < a); - mb(); + while (pm2_RD(p, PM2R_IN_FIFO_SPACE) < a) + cpu_relax(); } #endif @@ -328,7 +328,7 @@ static void reset_card(struct pm2fb_par *p) pm2_WR(p, PM2R_RESET_STATUS, 0); mb(); while (pm2_RD(p, PM2R_RESET_STATUS) & PM2F_BEING_RESET) - ; + cpu_relax(); mb(); #ifdef CONFIG_FB_PM2_FIFO_DISCONNECT DPRINTK("FIFO disconnect enabled\n"); @@ -587,6 +587,11 @@ static int pm2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) return -EINVAL; } + /* permedia cannot blit over 2048 */ + if (var->yres_virtual > 2047) { + var->yres_virtual = 2047; + } + if (var->xoffset) { DPRINTK("xoffset not supported\n"); return -EINVAL; @@ -1036,8 +1041,7 @@ static int pm2fb_sync(struct fb_info *info) mb(); do { while (pm2_RD(par, PM2R_OUT_FIFO_WORDS) == 0) - udelay(10); - rmb(); + cpu_relax(); } while (pm2_RD(par, PM2R_OUT_FIFO) != PM2TAG(PM2R_SYNC)); return 0; @@ -1155,6 +1159,11 @@ static void pm2fb_imageblit(struct fb_info *info, const struct fb_image *image) u32 fgx, bgx; const u32 *src = (const u32 *)image->data; u32 xres = (info->var.xres + 31) & ~31; + int raster_mode = 1; /* invert bits */ + +#ifdef __LITTLE_ENDIAN + raster_mode |= 3 << 7; /* reverse byte order */ +#endif if (info->state != FBINFO_STATE_RUNNING) return; @@ -1204,9 +1213,8 @@ static void pm2fb_imageblit(struct fb_info *info, const struct fb_image *image) pm2_WR(par, PM2R_RENDER, PM2F_RENDER_RECTANGLE | PM2F_INCREASE_X | PM2F_INCREASE_Y); - /* BitMapPackEachScanline & invert bits and byte order*/ - /* force background */ - pm2_WR(par, PM2R_RASTERIZER_MODE, (1 << 9) | 1 | (3 << 7)); + /* BitMapPackEachScanline */ + pm2_WR(par, PM2R_RASTERIZER_MODE, raster_mode | (1 << 9)); pm2_WR(par, PM2R_CONSTANT_COLOR, fgx); pm2_WR(par, PM2R_RENDER, PM2F_RENDER_RECTANGLE | @@ -1220,8 +1228,7 @@ static void pm2fb_imageblit(struct fb_info *info, const struct fb_image *image) PM2F_RENDER_RECTANGLE | PM2F_RENDER_FASTFILL | PM2F_INCREASE_X | PM2F_INCREASE_Y); - /* invert bits and byte order*/ - pm2_WR(par, PM2R_RASTERIZER_MODE, 1 | (3 << 7)); + pm2_WR(par, PM2R_RASTERIZER_MODE, raster_mode); pm2_WR(par, PM2R_FB_BLOCK_COLOR, fgx); pm2_WR(par, PM2R_RENDER, PM2F_RENDER_RECTANGLE | @@ -1257,23 +1264,22 @@ static const u8 cursor_bits_lookup[16] = { static int pm2vfb_cursor(struct fb_info *info, struct fb_cursor *cursor) { struct pm2fb_par *par = info->par; - u8 mode; - - if (!hwcursor) - return -EINVAL; /* just to force soft_cursor() call */ + u8 mode = PM2F_CURSORMODE_TYPE_X; + int x = cursor->image.dx - info->var.xoffset; + int y = cursor->image.dy - info->var.yoffset; - /* Too large of a cursor or wrong bpp :-( */ - if (cursor->image.width > 64 || - cursor->image.height > 64 || - cursor->image.depth > 1) - return -EINVAL; - - mode = PM2F_CURSORMODE_TYPE_X; if (cursor->enable) mode |= PM2F_CURSORMODE_CURSOR_ENABLE; pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_MODE, mode); + if (!cursor->enable) + x = 2047; /* push it outside display */ + pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_X_LOW, x & 0xff); + pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_X_HIGH, (x >> 8) & 0xf); + pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_Y_LOW, y & 0xff); + pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_Y_HIGH, (y >> 8) & 0xf); + /* * If the cursor is not be changed this means either we want the * current cursor state (if enable is set) or we want to query what @@ -1282,16 +1288,6 @@ static int pm2vfb_cursor(struct fb_info *info, struct fb_cursor *cursor) if (!cursor->set) return 0; - if (cursor->set & FB_CUR_SETPOS) { - int x = cursor->image.dx - info->var.xoffset; - int y = cursor->image.dy - info->var.yoffset; - - pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_X_LOW, x & 0xff); - pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_X_HIGH, (x >> 8) & 0xf); - pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_Y_LOW, y & 0xff); - pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_Y_HIGH, (y >> 8) & 0xf); - } - if (cursor->set & FB_CUR_SETHOT) { pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_X_HOT, cursor->hot.x & 0x3f); @@ -1369,11 +1365,121 @@ static int pm2vfb_cursor(struct fb_info *info, struct fb_cursor *cursor) static int pm2fb_cursor(struct fb_info *info, struct fb_cursor *cursor) { struct pm2fb_par *par = info->par; + u8 mode; + + if (!hwcursor) + return -EINVAL; /* just to force soft_cursor() call */ + + /* Too large of a cursor or wrong bpp :-( */ + if (cursor->image.width > 64 || + cursor->image.height > 64 || + cursor->image.depth > 1) + return -EINVAL; if (par->type == PM2_TYPE_PERMEDIA2V) return pm2vfb_cursor(info, cursor); - return -ENXIO; + mode = 0x40; + if (cursor->enable) + mode = 0x43; + + pm2_RDAC_WR(par, PM2I_RD_CURSOR_CONTROL, mode); + + /* + * If the cursor is not be changed this means either we want the + * current cursor state (if enable is set) or we want to query what + * we can do with the cursor (if enable is not set) + */ + if (!cursor->set) + return 0; + + if (cursor->set & FB_CUR_SETPOS) { + int x = cursor->image.dx - info->var.xoffset + 63; + int y = cursor->image.dy - info->var.yoffset + 63; + + WAIT_FIFO(par, 4); + pm2_WR(par, PM2R_RD_CURSOR_X_LSB, x & 0xff); + pm2_WR(par, PM2R_RD_CURSOR_X_MSB, (x >> 8) & 0x7); + pm2_WR(par, PM2R_RD_CURSOR_Y_LSB, y & 0xff); + pm2_WR(par, PM2R_RD_CURSOR_Y_MSB, (y >> 8) & 0x7); + } + + if (cursor->set & FB_CUR_SETCMAP) { + u32 fg_idx = cursor->image.fg_color; + u32 bg_idx = cursor->image.bg_color; + + WAIT_FIFO(par, 7); + pm2_WR(par, PM2R_RD_CURSOR_COLOR_ADDRESS, 1); + pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA, + info->cmap.red[bg_idx] >> 8); + pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA, + info->cmap.green[bg_idx] >> 8); + pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA, + info->cmap.blue[bg_idx] >> 8); + + pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA, + info->cmap.red[fg_idx] >> 8); + pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA, + info->cmap.green[fg_idx] >> 8); + pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA, + info->cmap.blue[fg_idx] >> 8); + } + + if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) { + u8 *bitmap = (u8 *)cursor->image.data; + u8 *mask = (u8 *)cursor->mask; + int i; + + WAIT_FIFO(par, 1); + pm2_WR(par, PM2R_RD_PALETTE_WRITE_ADDRESS, 0); + + for (i = 0; i < cursor->image.height; i++) { + int j = (cursor->image.width + 7) >> 3; + int k = 8 - j; + + WAIT_FIFO(par, 8); + for (; j > 0; j--) { + u8 data = *bitmap ^ *mask; + + if (cursor->rop == ROP_COPY) + data = *mask & *bitmap; + /* bitmap data */ + pm2_WR(par, PM2R_RD_CURSOR_DATA, data); + bitmap++; + mask++; + } + for (; k > 0; k--) + pm2_WR(par, PM2R_RD_CURSOR_DATA, 0); + } + for (; i < 64; i++) { + int j = 8; + WAIT_FIFO(par, 8); + while (j-- > 0) + pm2_WR(par, PM2R_RD_CURSOR_DATA, 0); + } + + mask = (u8 *)cursor->mask; + for (i = 0; i < cursor->image.height; i++) { + int j = (cursor->image.width + 7) >> 3; + int k = 8 - j; + + WAIT_FIFO(par, 8); + for (; j > 0; j--) { + /* mask */ + pm2_WR(par, PM2R_RD_CURSOR_DATA, *mask); + mask++; + } + for (; k > 0; k--) + pm2_WR(par, PM2R_RD_CURSOR_DATA, 0); + } + for (; i < 64; i++) { + int j = 8; + WAIT_FIFO(par, 8); + while (j-- > 0) + pm2_WR(par, PM2R_RD_CURSOR_DATA, 0); + } + } + return 0; } /* ------------ Hardware Independent Functions ------------ */ @@ -1574,17 +1680,19 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev, info->pixmap.scan_align = 1; } - if (!mode) - mode = "640x480@60"; + if (!mode_option) + mode_option = "640x480@60"; - err = fb_find_mode(&info->var, info, mode, NULL, 0, NULL, 8); + err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8); if (!err || err == 4) info->var = pm2fb_var; - if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) + retval = fb_alloc_cmap(&info->cmap, 256, 0); + if (retval < 0) goto err_exit_both; - if (register_framebuffer(info) < 0) + retval = register_framebuffer(info); + if (retval < 0) goto err_exit_all; printk(KERN_INFO "fb%d: %s frame buffer device, memory = %dK.\n", @@ -1638,6 +1746,7 @@ static void __devexit pm2fb_remove(struct pci_dev *pdev) release_mem_region(fix->mmio_start, fix->mmio_len); pci_set_drvdata(pdev, NULL); + fb_dealloc_cmap(&info->cmap); kfree(info->pixmap.addr); kfree(info); } @@ -1691,7 +1800,7 @@ static int __init pm2fb_setup(char *options) else if (!strncmp(this_opt, "noaccel", 7)) noaccel = 1; else - mode = this_opt; + mode_option = this_opt; } return 0; } @@ -1727,8 +1836,10 @@ static void __exit pm2fb_exit(void) #ifdef MODULE module_exit(pm2fb_exit); -module_param(mode, charp, 0); -MODULE_PARM_DESC(mode, "Preferred video mode e.g. '648x480-8@60'"); +module_param(mode_option, charp, 0); +MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'"); +module_param_named(mode, mode_option, charp, 0); +MODULE_PARM_DESC(mode, "Initial video mode e.g. '648x480-8@60' (deprecated)"); module_param(lowhsync, bool, 0); MODULE_PARM_DESC(lowhsync, "Force horizontal sync low regardless of mode"); module_param(lowvsync, bool, 0); @@ -1737,7 +1848,7 @@ module_param(noaccel, bool, 0); MODULE_PARM_DESC(noaccel, "Disable acceleration"); module_param(hwcursor, int, 0644); MODULE_PARM_DESC(hwcursor, "Enable hardware cursor " - "(1=enable, 0=disable, default=0)"); + "(1=enable, 0=disable, default=1)"); #ifdef CONFIG_MTRR module_param(nomtrr, bool, 0); MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)");