diff options
Diffstat (limited to 'drivers/video/s3fb.c')
-rw-r--r-- | drivers/video/s3fb.c | 66 |
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 | ||
67 | static const struct svga_pll s3_pll = {3, 129, 3, 33, 0, 3, | 67 | static const struct svga_pll s3_pll = {3, 129, 3, 33, 0, 3, |
68 | 60000, 240000, 14318}; | 68 | 35000, 240000, 14318}; |
69 | 69 | ||
70 | static const int s3_memsizes[] = {4096, 0, 3072, 8192, 2048, 6144, 1024, 512}; | 70 | static 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 | |||
164 | static void s3fb_settile_fast(struct fb_info *info, struct fb_tilemap *map) | 164 | static 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 | |||
188 | static struct fb_tile_ops s3fb_tile_ops = { | 186 | static 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 | ||
196 | static struct fb_tile_ops s3fb_fast_tile_ops = { | 195 | static 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 | |||
801 | static 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); |