@@ -50,10 +50,14 @@ struct s3fb_info {
5050static const struct svga_fb_format s3fb_formats [] = {
5151 { 0 , {0 , 6 , 0 }, {0 , 6 , 0 }, {0 , 6 , 0 }, {0 , 0 , 0 }, 0 ,
5252 FB_TYPE_TEXT , FB_AUX_TEXT_SVGA_STEP4 , FB_VISUAL_PSEUDOCOLOR , 8 , 16 },
53- { 4 , {0 , 4 , 0 }, {0 , 4 , 0 }, {0 , 4 , 0 }, {0 , 0 , 0 }, 0 ,
54- FB_TYPE_PACKED_PIXELS , 0 , FB_VISUAL_PSEUDOCOLOR , 8 , 16 },
53+ { 1 , {0 , 1 , 0 }, {0 , 1 , 0 }, {0 , 1 , 0 }, {0 , 0 , 0 }, 2 ,
54+ FB_TYPE_PACKED_PIXELS , 0 , FB_VISUAL_PSEUDOCOLOR , 32 , 64 },
55+ { 2 , {0 , 2 , 0 }, {0 , 2 , 0 }, {0 , 2 , 0 }, {0 , 0 , 0 }, 2 ,
56+ FB_TYPE_PACKED_PIXELS , 0 , FB_VISUAL_PSEUDOCOLOR , 16 , 32 },
5557 { 4 , {0 , 4 , 0 }, {0 , 4 , 0 }, {0 , 4 , 0 }, {0 , 0 , 0 }, 1 ,
5658 FB_TYPE_INTERLEAVED_PLANES , 1 , FB_VISUAL_PSEUDOCOLOR , 8 , 16 },
59+ { 4 , {0 , 4 , 0 }, {0 , 4 , 0 }, {0 , 4 , 0 }, {0 , 0 , 0 }, 2 ,
60+ FB_TYPE_PACKED_PIXELS , 0 , FB_VISUAL_PSEUDOCOLOR , 8 , 16 },
5761 { 8 , {0 , 8 , 0 }, {0 , 8 , 0 }, {0 , 8 , 0 }, {0 , 0 , 0 }, 0 ,
5862 FB_TYPE_PACKED_PIXELS , 0 , FB_VISUAL_PSEUDOCOLOR , 4 , 8 },
5963 {16 , {10 , 5 , 0 }, {5 , 5 , 0 }, {0 , 5 , 0 }, {0 , 0 , 0 }, 0 ,
@@ -557,7 +561,7 @@ static int s3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
557561
558562 /* 32bpp mode is not supported on VIRGE VX,
559563 24bpp is not supported on others */
560- if ((par -> chip == CHIP_988_VIRGE_VX ) ? (rv == 7 ) : (rv == 6 ))
564+ if ((par -> chip == CHIP_988_VIRGE_VX ) ? (rv == 9 ) : (rv == 8 ))
561565 rv = - EINVAL ;
562566
563567 if (rv < 0 ) {
@@ -607,7 +611,7 @@ static int s3fb_set_par(struct fb_info *info)
607611 struct s3fb_info * par = info -> par ;
608612 u32 value , mode , hmul , offset_value , screen_size , multiplex , dbytes ;
609613 u32 bpp = info -> var .bits_per_pixel ;
610- u32 htotal , hsstart ;
614+ u32 htotal , hsstart , pel_msk ;
611615
612616 if (bpp != 0 ) {
613617 info -> fix .ypanstep = 1 ;
@@ -617,9 +621,11 @@ static int s3fb_set_par(struct fb_info *info)
617621 info -> tileops = NULL ;
618622
619623 /* in 4bpp supports 8p wide tiles only, any tiles otherwise */
620- if (bpp == 4 ) {
624+ if (bpp == 4 && (info -> var .nonstd & 1 ) != 0 ) {
625+ int i ;
621626 bitmap_zero (info -> pixmap .blit_x , FB_MAX_BLIT_WIDTH );
622- set_bit (8 - 1 , info -> pixmap .blit_x );
627+ for (i = 8 ; i <= FB_MAX_BLIT_WIDTH ; i += 8 )
628+ set_bit (i - 1 , info -> pixmap .blit_x );
623629 } else {
624630 bitmap_fill (info -> pixmap .blit_x , FB_MAX_BLIT_WIDTH );
625631 }
@@ -730,7 +736,7 @@ static int s3fb_set_par(struct fb_info *info)
730736 vga_wcrt (par -> state .vgabase , 0x50 , 0x00 );
731737 vga_wcrt (par -> state .vgabase , 0x67 , 0x50 );
732738 msleep (10 ); /* screen remains blank sometimes without this */
733- vga_wcrt (par -> state .vgabase , 0x63 , (mode <= 2 ) ? 0x90 : 0x09 );
739+ vga_wcrt (par -> state .vgabase , 0x63 , (mode <= 4 ) ? 0x90 : 0x09 );
734740 vga_wcrt (par -> state .vgabase , 0x66 , 0x90 );
735741 }
736742
@@ -763,12 +769,17 @@ static int s3fb_set_par(struct fb_info *info)
763769 svga_wcrt_mask (par -> state .vgabase , 0x31 , 0x00 , 0x40 );
764770 multiplex = 0 ;
765771 hmul = 1 ;
772+ pel_msk = 0xff ;
773+
774+ svga_wcrt_mask (par -> state .vgabase , 0x08 , 0x00 , 0x60 );
775+ svga_wcrt_mask (par -> state .vgabase , 0x05 , 0x00 , 0x60 );
766776
767777 /* Set mode-specific register values */
768778 switch (mode ) {
769779 case 0 :
770780 fb_dbg (info , "text mode\n" );
771781 svga_set_textmode_vga_regs (par -> state .vgabase );
782+ pel_msk = 0x0f ;
772783
773784 /* Set additional registers like in 8-bit mode */
774785 svga_wcrt_mask (par -> state .vgabase , 0x50 , 0x00 , 0x30 );
@@ -783,8 +794,11 @@ static int s3fb_set_par(struct fb_info *info)
783794 }
784795 break ;
785796 case 1 :
786- fb_dbg (info , "4 bit pseudocolor\n" );
787- vga_wgfx (par -> state .vgabase , VGA_GFX_MODE , 0x40 );
797+ fb_dbg (info , "1 bit pseudocolor\n" );
798+ svga_wseq_mask (par -> state .vgabase , 0x01 , 0x10 , 0x14 );
799+ svga_wcrt_mask (par -> state .vgabase , 0x08 , 0x60 , 0x60 );
800+ svga_wcrt_mask (par -> state .vgabase , 0x05 , 0x40 , 0x60 );
801+ pel_msk = 0x01 ;
788802
789803 /* Set additional registers like in 8-bit mode */
790804 svga_wcrt_mask (par -> state .vgabase , 0x50 , 0x00 , 0x30 );
@@ -794,7 +808,13 @@ static int s3fb_set_par(struct fb_info *info)
794808 svga_wcrt_mask (par -> state .vgabase , 0x3A , 0x00 , 0x30 );
795809 break ;
796810 case 2 :
797- fb_dbg (info , "4 bit pseudocolor, planar\n" );
811+ fb_dbg (info , "2 bit pseudocolor\n" );
812+ svga_wseq_mask (par -> state .vgabase , 0x01 , 0x04 , 0x14 );
813+ svga_wseq_mask (par -> state .vgabase , 0x04 , 0x08 , 0x08 );
814+ vga_wgfx (par -> state .vgabase , VGA_GFX_MODE , 0x20 );
815+ svga_wcrt_mask (par -> state .vgabase , 0x08 , 0x20 , 0x60 );
816+ svga_wcrt_mask (par -> state .vgabase , 0x05 , 0x40 , 0x60 );
817+ pel_msk = 0x03 ;
798818
799819 /* Set additional registers like in 8-bit mode */
800820 svga_wcrt_mask (par -> state .vgabase , 0x50 , 0x00 , 0x30 );
@@ -804,8 +824,35 @@ static int s3fb_set_par(struct fb_info *info)
804824 svga_wcrt_mask (par -> state .vgabase , 0x3A , 0x00 , 0x30 );
805825 break ;
806826 case 3 :
827+ fb_dbg (info , "4 bit pseudocolor, planar\n" );
828+ pel_msk = 0x0f ;
829+
830+ /* Set additional registers like in 8-bit mode */
831+ svga_wcrt_mask (par -> state .vgabase , 0x50 , 0x00 , 0x30 );
832+ svga_wcrt_mask (par -> state .vgabase , 0x67 , 0x00 , 0xF0 );
833+ svga_wcrt_mask (par -> state .vgabase , 0x05 , 0x40 , 0x60 );
834+
835+ /* disable enhanced mode */
836+ svga_wcrt_mask (par -> state .vgabase , 0x3A , 0x00 , 0x30 );
837+ break ;
838+ case 4 :
839+ fb_dbg (info , "4 bit pseudocolor\n" );
840+ vga_wgfx (par -> state .vgabase , VGA_GFX_MODE , 0x40 );
841+ svga_wattr (par -> state .vgabase , 0x33 , 0x01 );
842+ svga_wcrt_mask (par -> state .vgabase , 0x05 , 0x40 , 0x60 );
843+ pel_msk = 0xf0 ;
844+
845+ /* Set additional registers like in 8-bit mode */
846+ svga_wcrt_mask (par -> state .vgabase , 0x50 , 0x00 , 0x30 );
847+ svga_wcrt_mask (par -> state .vgabase , 0x67 , 0x00 , 0xF0 );
848+
849+ /* disable enhanced mode */
850+ svga_wcrt_mask (par -> state .vgabase , 0x3A , 0x00 , 0x30 );
851+ break ;
852+ case 5 :
807853 fb_dbg (info , "8 bit pseudocolor\n" );
808854 svga_wcrt_mask (par -> state .vgabase , 0x50 , 0x00 , 0x30 );
855+ svga_wcrt_mask (par -> state .vgabase , 0x05 , 0x20 , 0x60 );
809856 if (info -> var .pixclock > 20000 ||
810857 par -> chip == CHIP_357_VIRGE_GX2 ||
811858 par -> chip == CHIP_359_VIRGE_GX2P ||
@@ -819,7 +866,7 @@ static int s3fb_set_par(struct fb_info *info)
819866 multiplex = 1 ;
820867 }
821868 break ;
822- case 4 :
869+ case 6 :
823870 fb_dbg (info , "5/5/5 truecolor\n" );
824871 if (par -> chip == CHIP_988_VIRGE_VX ) {
825872 if (info -> var .pixclock > 20000 )
@@ -847,7 +894,7 @@ static int s3fb_set_par(struct fb_info *info)
847894 hmul = 2 ;
848895 }
849896 break ;
850- case 5 :
897+ case 7 :
851898 fb_dbg (info , "5/6/5 truecolor\n" );
852899 if (par -> chip == CHIP_988_VIRGE_VX ) {
853900 if (info -> var .pixclock > 20000 )
@@ -875,12 +922,12 @@ static int s3fb_set_par(struct fb_info *info)
875922 hmul = 2 ;
876923 }
877924 break ;
878- case 6 :
925+ case 8 :
879926 /* VIRGE VX case */
880927 fb_dbg (info , "8/8/8 truecolor\n" );
881928 svga_wcrt_mask (par -> state .vgabase , 0x67 , 0xD0 , 0xF0 );
882929 break ;
883- case 7 :
930+ case 9 :
884931 fb_dbg (info , "8/8/8/8 truecolor\n" );
885932 svga_wcrt_mask (par -> state .vgabase , 0x50 , 0x30 , 0x30 );
886933 svga_wcrt_mask (par -> state .vgabase , 0x67 , 0xD0 , 0xF0 );
@@ -889,6 +936,7 @@ static int s3fb_set_par(struct fb_info *info)
889936 fb_err (info , "unsupported mode - bug\n" );
890937 return - EINVAL ;
891938 }
939+ vga_w (par -> state .vgabase , VGA_PEL_MSK , pel_msk );
892940
893941 if (par -> chip != CHIP_988_VIRGE_VX ) {
894942 svga_wseq_mask (par -> state .vgabase , 0x15 , multiplex ? 0x10 : 0x00 , 0x10 );
@@ -927,33 +975,26 @@ static int s3fb_set_par(struct fb_info *info)
927975static int s3fb_setcolreg (u_int regno , u_int red , u_int green , u_int blue ,
928976 u_int transp , struct fb_info * fb )
929977{
978+ struct s3fb_info * par = fb -> par ;
979+ int cols ;
980+
930981 switch (fb -> var .bits_per_pixel ) {
931982 case 0 :
983+ case 1 :
984+ case 2 :
932985 case 4 :
933- if (regno >= 16 )
934- return - EINVAL ;
935-
936- if ((fb -> var .bits_per_pixel == 4 ) &&
937- (fb -> var .nonstd == 0 )) {
938- outb (0xF0 , VGA_PEL_MSK );
939- outb (regno * 16 , VGA_PEL_IW );
940- } else {
941- outb (0x0F , VGA_PEL_MSK );
942- outb (regno , VGA_PEL_IW );
943- }
944- outb (red >> 10 , VGA_PEL_D );
945- outb (green >> 10 , VGA_PEL_D );
946- outb (blue >> 10 , VGA_PEL_D );
947- break ;
948986 case 8 :
949- if (regno >= 256 )
987+ cols = 1 << (fb -> var .bits_per_pixel ? fb -> var .bits_per_pixel : 4 );
988+ if (regno >= cols )
950989 return - EINVAL ;
951990
952- outb (0xFF , VGA_PEL_MSK );
953- outb (regno , VGA_PEL_IW );
954- outb (red >> 10 , VGA_PEL_D );
955- outb (green >> 10 , VGA_PEL_D );
956- outb (blue >> 10 , VGA_PEL_D );
991+ if ((fb -> var .bits_per_pixel == 4 ) && ((fb -> var .nonstd & 1 ) == 0 ))
992+ regno <<= 4 ;
993+
994+ vga_w (par -> state .vgabase , VGA_PEL_IW , regno );
995+ vga_w (par -> state .vgabase , VGA_PEL_D , red >> 10 );
996+ vga_w (par -> state .vgabase , VGA_PEL_D , green >> 10 );
997+ vga_w (par -> state .vgabase , VGA_PEL_D , blue >> 10 );
957998 break ;
958999 case 16 :
9591000 if (regno >= 16 )
@@ -1041,6 +1082,33 @@ static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
10411082 return 0 ;
10421083}
10431084
1085+ /* Get capabilities of accelerator based on the mode */
1086+
1087+ static void s3fb_get_caps (struct fb_info * info , struct fb_blit_caps * caps ,
1088+ struct fb_var_screeninfo * var )
1089+ {
1090+ int i ;
1091+
1092+ if (var -> bits_per_pixel == 0 ) {
1093+ /* can only support 256 8x16 bitmap */
1094+ bitmap_zero (caps -> x , FB_MAX_BLIT_WIDTH );
1095+ set_bit (8 - 1 , caps -> x );
1096+ bitmap_zero (caps -> y , FB_MAX_BLIT_HEIGHT );
1097+ set_bit (16 - 1 , caps -> y );
1098+ caps -> len = 256 ;
1099+ } else {
1100+ if (var -> bits_per_pixel == 4 && (var -> nonstd & 1 ) != 0 ) {
1101+ bitmap_zero (caps -> x , FB_MAX_BLIT_WIDTH );
1102+ for (i = 8 ; i <= FB_MAX_BLIT_WIDTH ; i += 8 )
1103+ set_bit (i - 1 , caps -> x );
1104+ } else {
1105+ bitmap_fill (caps -> x , FB_MAX_BLIT_WIDTH );
1106+ }
1107+ bitmap_fill (caps -> y , FB_MAX_BLIT_HEIGHT );
1108+ caps -> len = ~(u32 )0 ;
1109+ }
1110+ }
1111+
10441112/* ------------------------------------------------------------------------- */
10451113
10461114/* Frame buffer operations */
@@ -1059,7 +1127,7 @@ static const struct fb_ops s3fb_ops = {
10591127 .fb_copyarea = cfb_copyarea ,
10601128 .fb_imageblit = s3fb_imageblit ,
10611129 __FB_DEFAULT_IOMEM_OPS_MMAP ,
1062- .fb_get_caps = svga_get_caps ,
1130+ .fb_get_caps = s3fb_get_caps ,
10631131};
10641132
10651133/* ------------------------------------------------------------------------- */
0 commit comments