aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/s3fb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/s3fb.c')
-rw-r--r--drivers/video/s3fb.c66
1 files changed, 49 insertions, 17 deletions
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c
index 3091b20124b4..756fafb41d78 100644
--- a/drivers/video/s3fb.c
+++ b/drivers/video/s3fb.c
@@ -65,7 +65,7 @@ static const struct svga_fb_format s3fb_formats[] = {
65 65
66 66
67static const struct svga_pll s3_pll = {3, 129, 3, 33, 0, 3, 67static const struct svga_pll s3_pll = {3, 129, 3, 33, 0, 3,
68 60000, 240000, 14318}; 68 35000, 240000, 14318};
69 69
70static const int s3_memsizes[] = {4096, 0, 3072, 8192, 2048, 6144, 1024, 512}; 70static const int s3_memsizes[] = {4096, 0, 3072, 8192, 2048, 6144, 1024, 512};
71 71
@@ -164,7 +164,7 @@ MODULE_PARM_DESC(fasttext, "Enable S3 fast text mode (1=enable, 0=disable, defau
164static void s3fb_settile_fast(struct fb_info *info, struct fb_tilemap *map) 164static void s3fb_settile_fast(struct fb_info *info, struct fb_tilemap *map)
165{ 165{
166 const u8 *font = map->data; 166 const u8 *font = map->data;
167 u8* fb = (u8 *) info->screen_base; 167 u8 __iomem *fb = (u8 __iomem *) info->screen_base;
168 int i, c; 168 int i, c;
169 169
170 if ((map->width != 8) || (map->height != 16) || 170 if ((map->width != 8) || (map->height != 16) ||
@@ -177,20 +177,19 @@ static void s3fb_settile_fast(struct fb_info *info, struct fb_tilemap *map)
177 fb += 2; 177 fb += 2;
178 for (i = 0; i < map->height; i++) { 178 for (i = 0; i < map->height; i++) {
179 for (c = 0; c < map->length; c++) { 179 for (c = 0; c < map->length; c++) {
180 fb[c * 4] = font[c * map->height + i]; 180 fb_writeb(font[c * map->height + i], fb + c * 4);
181 } 181 }
182 fb += 1024; 182 fb += 1024;
183 } 183 }
184} 184}
185 185
186
187
188static struct fb_tile_ops s3fb_tile_ops = { 186static struct fb_tile_ops s3fb_tile_ops = {
189 .fb_settile = svga_settile, 187 .fb_settile = svga_settile,
190 .fb_tilecopy = svga_tilecopy, 188 .fb_tilecopy = svga_tilecopy,
191 .fb_tilefill = svga_tilefill, 189 .fb_tilefill = svga_tilefill,
192 .fb_tileblit = svga_tileblit, 190 .fb_tileblit = svga_tileblit,
193 .fb_tilecursor = svga_tilecursor, 191 .fb_tilecursor = svga_tilecursor,
192 .fb_get_tilemax = svga_get_tilemax,
194}; 193};
195 194
196static struct fb_tile_ops s3fb_fast_tile_ops = { 195static struct fb_tile_ops s3fb_fast_tile_ops = {
@@ -199,6 +198,7 @@ static struct fb_tile_ops s3fb_fast_tile_ops = {
199 .fb_tilefill = svga_tilefill, 198 .fb_tilefill = svga_tilefill,
200 .fb_tileblit = svga_tileblit, 199 .fb_tileblit = svga_tileblit,
201 .fb_tilecursor = svga_tilecursor, 200 .fb_tilecursor = svga_tilecursor,
201 .fb_get_tilemax = svga_get_tilemax,
202}; 202};
203 203
204 204
@@ -326,8 +326,13 @@ static void s3_set_pixclock(struct fb_info *info, u32 pixclock)
326{ 326{
327 u16 m, n, r; 327 u16 m, n, r;
328 u8 regval; 328 u8 regval;
329 int rv;
329 330
330 svga_compute_pll(&s3_pll, 1000000000 / pixclock, &m, &n, &r, info->node); 331 rv = svga_compute_pll(&s3_pll, 1000000000 / pixclock, &m, &n, &r, info->node);
332 if (rv < 0) {
333 printk(KERN_ERR "fb%d: cannot set requested pixclock, keeping old value\n", info->node);
334 return;
335 }
331 336
332 /* Set VGA misc register */ 337 /* Set VGA misc register */
333 regval = vga_r(NULL, VGA_MIS_R); 338 regval = vga_r(NULL, VGA_MIS_R);
@@ -449,6 +454,10 @@ static int s3fb_set_par(struct fb_info *info)
449 info->flags &= ~FBINFO_MISC_TILEBLITTING; 454 info->flags &= ~FBINFO_MISC_TILEBLITTING;
450 info->tileops = NULL; 455 info->tileops = NULL;
451 456
457 /* in 4bpp supports 8p wide tiles only, any tiles otherwise */
458 info->pixmap.blit_x = (bpp == 4) ? (1 << (8 - 1)) : (~(u32)0);
459 info->pixmap.blit_y = ~(u32)0;
460
452 offset_value = (info->var.xres_virtual * bpp) / 64; 461 offset_value = (info->var.xres_virtual * bpp) / 64;
453 screen_size = info->var.yres_virtual * info->fix.line_length; 462 screen_size = info->var.yres_virtual * info->fix.line_length;
454 } else { 463 } else {
@@ -458,6 +467,10 @@ static int s3fb_set_par(struct fb_info *info)
458 info->flags |= FBINFO_MISC_TILEBLITTING; 467 info->flags |= FBINFO_MISC_TILEBLITTING;
459 info->tileops = fasttext ? &s3fb_fast_tile_ops : &s3fb_tile_ops; 468 info->tileops = fasttext ? &s3fb_fast_tile_ops : &s3fb_tile_ops;
460 469
470 /* supports 8x16 tiles only */
471 info->pixmap.blit_x = 1 << (8 - 1);
472 info->pixmap.blit_y = 1 << (16 - 1);
473
461 offset_value = info->var.xres_virtual / 16; 474 offset_value = info->var.xres_virtual / 16;
462 screen_size = (info->var.xres_virtual * info->var.yres_virtual) / 64; 475 screen_size = (info->var.xres_virtual * info->var.yres_virtual) / 64;
463 } 476 }
@@ -656,7 +669,7 @@ static int s3fb_set_par(struct fb_info *info)
656 value = ((value * hmul) / 8) - 5; 669 value = ((value * hmul) / 8) - 5;
657 vga_wcrt(NULL, 0x3C, (value + 1) / 2); 670 vga_wcrt(NULL, 0x3C, (value + 1) / 2);
658 671
659 memset((u8*)info->screen_base, 0x00, screen_size); 672 memset_io(info->screen_base, 0x00, screen_size);
660 /* Device and screen back on */ 673 /* Device and screen back on */
661 svga_wcrt_mask(0x17, 0x80, 0x80); 674 svga_wcrt_mask(0x17, 0x80, 0x80);
662 svga_wseq_mask(0x01, 0x00, 0x20); 675 svga_wseq_mask(0x01, 0x00, 0x20);
@@ -699,7 +712,7 @@ static int s3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
699 break; 712 break;
700 case 16: 713 case 16:
701 if (regno >= 16) 714 if (regno >= 16)
702 return -EINVAL; 715 return 0;
703 716
704 if (fb->var.green.length == 5) 717 if (fb->var.green.length == 5)
705 ((u32*)fb->pseudo_palette)[regno] = ((red & 0xF800) >> 1) | 718 ((u32*)fb->pseudo_palette)[regno] = ((red & 0xF800) >> 1) |
@@ -712,9 +725,9 @@ static int s3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
712 case 24: 725 case 24:
713 case 32: 726 case 32:
714 if (regno >= 16) 727 if (regno >= 16)
715 return -EINVAL; 728 return 0;
716 729
717 ((u32*)fb->pseudo_palette)[regno] = ((transp & 0xFF00) << 16) | ((red & 0xFF00) << 8) | 730 ((u32*)fb->pseudo_palette)[regno] = ((red & 0xFF00) << 8) |
718 (green & 0xFF00) | ((blue & 0xFF00) >> 8); 731 (green & 0xFF00) | ((blue & 0xFF00) >> 8);
719 break; 732 break;
720 default: 733 default:
@@ -767,12 +780,6 @@ static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
767 780
768 unsigned int offset; 781 unsigned int offset;
769 782
770 /* Validate the offsets */
771 if ((var->xoffset + var->xres) > var->xres_virtual)
772 return -EINVAL;
773 if ((var->yoffset + var->yres) > var->yres_virtual)
774 return -EINVAL;
775
776 /* Calculate the offset */ 783 /* Calculate the offset */
777 if (var->bits_per_pixel == 0) { 784 if (var->bits_per_pixel == 0) {
778 offset = (var->yoffset / 16) * (var->xres_virtual / 2) + (var->xoffset / 2); 785 offset = (var->yoffset / 16) * (var->xres_virtual / 2) + (var->xoffset / 2);
@@ -789,6 +796,23 @@ static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
789 return 0; 796 return 0;
790} 797}
791 798
799/* Get capabilities of accelerator based on the mode */
800
801static void s3fb_get_caps(struct fb_info *info, struct fb_blit_caps *caps,
802 struct fb_var_screeninfo *var)
803{
804 if (var->bits_per_pixel == 0) {
805 /* can only support 256 8x16 bitmap */
806 caps->x = 1 << (8 - 1);
807 caps->y = 1 << (16 - 1);
808 caps->len = 256;
809 } else {
810 caps->x = ~(u32)0;
811 caps->y = ~(u32)0;
812 caps->len = ~(u32)0;
813 }
814}
815
792/* ------------------------------------------------------------------------- */ 816/* ------------------------------------------------------------------------- */
793 817
794/* Frame buffer operations */ 818/* Frame buffer operations */
@@ -805,6 +829,7 @@ static struct fb_ops s3fb_ops = {
805 .fb_fillrect = s3fb_fillrect, 829 .fb_fillrect = s3fb_fillrect,
806 .fb_copyarea = cfb_copyarea, 830 .fb_copyarea = cfb_copyarea,
807 .fb_imageblit = s3fb_imageblit, 831 .fb_imageblit = s3fb_imageblit,
832 .fb_get_caps = s3fb_get_caps,
808}; 833};
809 834
810/* ------------------------------------------------------------------------- */ 835/* ------------------------------------------------------------------------- */
@@ -1061,6 +1086,7 @@ static int s3_pci_resume(struct pci_dev* dev)
1061{ 1086{
1062 struct fb_info *info = pci_get_drvdata(dev); 1087 struct fb_info *info = pci_get_drvdata(dev);
1063 struct s3fb_info *par = info->par; 1088 struct s3fb_info *par = info->par;
1089 int err;
1064 1090
1065 dev_info(&(dev->dev), "resume\n"); 1091 dev_info(&(dev->dev), "resume\n");
1066 1092
@@ -1075,7 +1101,13 @@ static int s3_pci_resume(struct pci_dev* dev)
1075 1101
1076 pci_set_power_state(dev, PCI_D0); 1102 pci_set_power_state(dev, PCI_D0);
1077 pci_restore_state(dev); 1103 pci_restore_state(dev);
1078 pci_enable_device(dev); 1104 err = pci_enable_device(dev);
1105 if (err) {
1106 mutex_unlock(&(par->open_lock));
1107 release_console_sem();
1108 dev_err(&(dev->dev), "error %d enabling device for resume\n", err);
1109 return err;
1110 }
1079 pci_set_master(dev); 1111 pci_set_master(dev);
1080 1112
1081 s3fb_set_par(info); 1113 s3fb_set_par(info);