diff options
author | Krzysztof Helt <krzysztof.h1@wp.pl> | 2007-05-08 03:40:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-08 14:15:33 -0400 |
commit | 87a7cc685a847800482db1fd74504b9b4b42264e (patch) | |
tree | 7f59704f152ed5d7452747e06608d2a11ecdc4b5 /drivers/video | |
parent | 34ed25f50b347c7e1ff78f9308e025ddd57c2f20 (diff) |
pm2fb: accelerated fillrect and copyarea
This is a port of accelerated functions from 2.4 kernel. Only fillrect and
copyarea are accelerated. Fillrect is not accelerated in 24-bit mode.
[adaplas]
Add appropriate flags
Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl>
Signed-off-by: Antonino Daplas <adaplas@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/pm2fb.c | 132 |
1 files changed, 128 insertions, 4 deletions
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index 539541946b25..5693da5b1ba7 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c | |||
@@ -103,7 +103,7 @@ static struct fb_fix_screeninfo pm2fb_fix __devinitdata = { | |||
103 | .xpanstep = 1, | 103 | .xpanstep = 1, |
104 | .ypanstep = 1, | 104 | .ypanstep = 1, |
105 | .ywrapstep = 0, | 105 | .ywrapstep = 0, |
106 | .accel = FB_ACCEL_NONE, | 106 | .accel = FB_ACCEL_3DLABS_PERMEDIA2, |
107 | }; | 107 | }; |
108 | 108 | ||
109 | /* | 109 | /* |
@@ -206,6 +206,17 @@ static inline void WAIT_FIFO(struct pm2fb_par* p, u32 a) | |||
206 | } | 206 | } |
207 | #endif | 207 | #endif |
208 | 208 | ||
209 | static void wait_pm2(struct pm2fb_par* par) { | ||
210 | |||
211 | WAIT_FIFO(par, 1); | ||
212 | pm2_WR(par, PM2R_SYNC, 0); | ||
213 | mb(); | ||
214 | do { | ||
215 | while (pm2_RD(par, PM2R_OUT_FIFO_WORDS) == 0); | ||
216 | rmb(); | ||
217 | } while (pm2_RD(par, PM2R_OUT_FIFO) != PM2TAG(PM2R_SYNC)); | ||
218 | } | ||
219 | |||
209 | /* | 220 | /* |
210 | * partial products for the supported horizontal resolutions. | 221 | * partial products for the supported horizontal resolutions. |
211 | */ | 222 | */ |
@@ -1041,6 +1052,117 @@ static int pm2fb_blank(int blank_mode, struct fb_info *info) | |||
1041 | return 0; | 1052 | return 0; |
1042 | } | 1053 | } |
1043 | 1054 | ||
1055 | /* | ||
1056 | * block operation. copy=0: rectangle fill, copy=1: rectangle copy. | ||
1057 | */ | ||
1058 | static void pm2fb_block_op(struct pm2fb_par* par, int copy, | ||
1059 | s32 xsrc, s32 ysrc, | ||
1060 | s32 x, s32 y, s32 w, s32 h, | ||
1061 | u32 color) { | ||
1062 | |||
1063 | if (!w || !h) | ||
1064 | return; | ||
1065 | WAIT_FIFO(par, 6); | ||
1066 | pm2_WR(par, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE | | ||
1067 | PM2F_CONFIG_FB_READ_SOURCE_ENABLE); | ||
1068 | pm2_WR(par, PM2R_FB_PIXEL_OFFSET, 0); | ||
1069 | if (copy) | ||
1070 | pm2_WR(par, PM2R_FB_SOURCE_DELTA, | ||
1071 | ((ysrc-y) & 0xfff) << 16 | ((xsrc-x) & 0xfff)); | ||
1072 | else | ||
1073 | pm2_WR(par, PM2R_FB_BLOCK_COLOR, color); | ||
1074 | pm2_WR(par, PM2R_RECTANGLE_ORIGIN, (y << 16) | x); | ||
1075 | pm2_WR(par, PM2R_RECTANGLE_SIZE, (h << 16) | w); | ||
1076 | wmb(); | ||
1077 | pm2_WR(par, PM2R_RENDER,PM2F_RENDER_RECTANGLE | | ||
1078 | (x<xsrc ? PM2F_INCREASE_X : 0) | | ||
1079 | (y<ysrc ? PM2F_INCREASE_Y : 0) | | ||
1080 | (copy ? 0 : PM2F_RENDER_FASTFILL)); | ||
1081 | wait_pm2(par); | ||
1082 | } | ||
1083 | |||
1084 | static void pm2fb_fillrect (struct fb_info *info, | ||
1085 | const struct fb_fillrect *region) | ||
1086 | { | ||
1087 | struct pm2fb_par *par = info->par; | ||
1088 | struct fb_fillrect modded; | ||
1089 | int vxres, vyres; | ||
1090 | u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ? | ||
1091 | ((u32*)info->pseudo_palette)[region->color] : region->color; | ||
1092 | |||
1093 | if (info->state != FBINFO_STATE_RUNNING) | ||
1094 | return; | ||
1095 | if ((info->flags & FBINFO_HWACCEL_DISABLED) || | ||
1096 | region->rop != ROP_COPY ) { | ||
1097 | cfb_fillrect(info, region); | ||
1098 | return; | ||
1099 | } | ||
1100 | |||
1101 | vxres = info->var.xres_virtual; | ||
1102 | vyres = info->var.yres_virtual; | ||
1103 | |||
1104 | memcpy(&modded, region, sizeof(struct fb_fillrect)); | ||
1105 | |||
1106 | if(!modded.width || !modded.height || | ||
1107 | modded.dx >= vxres || modded.dy >= vyres) | ||
1108 | return; | ||
1109 | |||
1110 | if(modded.dx + modded.width > vxres) | ||
1111 | modded.width = vxres - modded.dx; | ||
1112 | if(modded.dy + modded.height > vyres) | ||
1113 | modded.height = vyres - modded.dy; | ||
1114 | |||
1115 | if(info->var.bits_per_pixel == 8) | ||
1116 | color |= color << 8; | ||
1117 | if(info->var.bits_per_pixel <= 16) | ||
1118 | color |= color << 16; | ||
1119 | |||
1120 | if(info->var.bits_per_pixel != 24) | ||
1121 | pm2fb_block_op(par, 0, 0, 0, | ||
1122 | modded.dx, modded.dy, | ||
1123 | modded.width, modded.height, color); | ||
1124 | else | ||
1125 | cfb_fillrect(info, region); | ||
1126 | } | ||
1127 | |||
1128 | static void pm2fb_copyarea(struct fb_info *info, | ||
1129 | const struct fb_copyarea *area) | ||
1130 | { | ||
1131 | struct pm2fb_par *par = info->par; | ||
1132 | struct fb_copyarea modded; | ||
1133 | u32 vxres, vyres; | ||
1134 | |||
1135 | if (info->state != FBINFO_STATE_RUNNING) | ||
1136 | return; | ||
1137 | if (info->flags & FBINFO_HWACCEL_DISABLED) { | ||
1138 | cfb_copyarea(info, area); | ||
1139 | return; | ||
1140 | } | ||
1141 | |||
1142 | memcpy(&modded, area, sizeof(struct fb_copyarea)); | ||
1143 | |||
1144 | vxres = info->var.xres_virtual; | ||
1145 | vyres = info->var.yres_virtual; | ||
1146 | |||
1147 | if(!modded.width || !modded.height || | ||
1148 | modded.sx >= vxres || modded.sy >= vyres || | ||
1149 | modded.dx >= vxres || modded.dy >= vyres) | ||
1150 | return; | ||
1151 | |||
1152 | if(modded.sx + modded.width > vxres) | ||
1153 | modded.width = vxres - modded.sx; | ||
1154 | if(modded.dx + modded.width > vxres) | ||
1155 | modded.width = vxres - modded.dx; | ||
1156 | if(modded.sy + modded.height > vyres) | ||
1157 | modded.height = vyres - modded.sy; | ||
1158 | if(modded.dy + modded.height > vyres) | ||
1159 | modded.height = vyres - modded.dy; | ||
1160 | |||
1161 | pm2fb_block_op(par, 1, modded.sx, modded.sy, | ||
1162 | modded.dx, modded.dy, | ||
1163 | modded.width, modded.height, 0); | ||
1164 | } | ||
1165 | |||
1044 | /* ------------ Hardware Independent Functions ------------ */ | 1166 | /* ------------ Hardware Independent Functions ------------ */ |
1045 | 1167 | ||
1046 | /* | 1168 | /* |
@@ -1054,8 +1176,8 @@ static struct fb_ops pm2fb_ops = { | |||
1054 | .fb_setcolreg = pm2fb_setcolreg, | 1176 | .fb_setcolreg = pm2fb_setcolreg, |
1055 | .fb_blank = pm2fb_blank, | 1177 | .fb_blank = pm2fb_blank, |
1056 | .fb_pan_display = pm2fb_pan_display, | 1178 | .fb_pan_display = pm2fb_pan_display, |
1057 | .fb_fillrect = cfb_fillrect, | 1179 | .fb_fillrect = pm2fb_fillrect, |
1058 | .fb_copyarea = cfb_copyarea, | 1180 | .fb_copyarea = pm2fb_copyarea, |
1059 | .fb_imageblit = cfb_imageblit, | 1181 | .fb_imageblit = cfb_imageblit, |
1060 | }; | 1182 | }; |
1061 | 1183 | ||
@@ -1204,7 +1326,9 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev, | |||
1204 | info->fix = pm2fb_fix; | 1326 | info->fix = pm2fb_fix; |
1205 | info->pseudo_palette = default_par->palette; | 1327 | info->pseudo_palette = default_par->palette; |
1206 | info->flags = FBINFO_DEFAULT | | 1328 | info->flags = FBINFO_DEFAULT | |
1207 | FBINFO_HWACCEL_YPAN; | 1329 | FBINFO_HWACCEL_YPAN | |
1330 | FBINFO_HWACCEL_COPYAREA | | ||
1331 | FBINFO_HWACCEL_FILLRECT; | ||
1208 | 1332 | ||
1209 | if (!mode) | 1333 | if (!mode) |
1210 | mode = "640x480@60"; | 1334 | mode = "640x480@60"; |