@@ -1146,222 +1146,57 @@ copyarea_line_32bpp(struct fb_info *info, u32 dy, u32 sy,
1146
1146
__raw_writel (TGA_MODE_SBM_24BPP |TGA_MODE_SIMPLE , tga_regs + TGA_MODE_REG );
1147
1147
}
1148
1148
1149
- /* The general case of forward copy in 8bpp mode. */
1149
+ /* The (almost) general case of backward copy in 8bpp mode. */
1150
1150
static inline void
1151
- copyarea_foreward_8bpp (struct fb_info * info , u32 dx , u32 dy , u32 sx , u32 sy ,
1152
- u32 height , u32 width , u32 line_length )
1151
+ copyarea_8bpp (struct fb_info * info , u32 dx , u32 dy , u32 sx , u32 sy ,
1152
+ u32 height , u32 width , u32 line_length ,
1153
+ const struct fb_copyarea * area )
1153
1154
{
1154
1155
struct tga_par * par = (struct tga_par * ) info -> par ;
1155
- unsigned long i , copied , left ;
1156
- unsigned long dpos , spos , dalign , salign , yincr ;
1157
- u32 smask_first , dmask_first , dmask_last ;
1158
- int pixel_shift , need_prime , need_second ;
1159
- unsigned long n64 , n32 , xincr_first ;
1156
+ unsigned i , yincr ;
1157
+ int depos , sepos , backward , last_step , step ;
1158
+ u32 mask_last ;
1159
+ unsigned n32 ;
1160
1160
void __iomem * tga_regs ;
1161
1161
void __iomem * tga_fb ;
1162
1162
1163
- yincr = line_length ;
1164
- if (dy > sy ) {
1165
- dy += height - 1 ;
1166
- sy += height - 1 ;
1167
- yincr = - yincr ;
1168
- }
1169
-
1170
- /* Compute the offsets and alignments in the frame buffer.
1171
- More than anything else, these control how we do copies. */
1172
- dpos = dy * line_length + dx ;
1173
- spos = sy * line_length + sx ;
1174
- dalign = dpos & 7 ;
1175
- salign = spos & 7 ;
1176
- dpos &= -8 ;
1177
- spos &= -8 ;
1178
-
1179
- /* Compute the value for the PIXELSHIFT register. This controls
1180
- both non-co-aligned source and destination and copy direction. */
1181
- if (dalign >= salign )
1182
- pixel_shift = dalign - salign ;
1183
- else
1184
- pixel_shift = 8 - (salign - dalign );
1185
-
1186
- /* Figure out if we need an additional priming step for the
1187
- residue register. */
1188
- need_prime = (salign > dalign );
1189
- if (need_prime )
1190
- dpos -= 8 ;
1191
-
1192
- /* Begin by copying the leading unaligned destination. Copy enough
1193
- to make the next destination address 32-byte aligned. */
1194
- copied = 32 - (dalign + (dpos & 31 ));
1195
- if (copied == 32 )
1196
- copied = 0 ;
1197
- xincr_first = (copied + 7 ) & -8 ;
1198
- smask_first = dmask_first = (1ul << copied ) - 1 ;
1199
- smask_first <<= salign ;
1200
- dmask_first <<= dalign + need_prime * 8 ;
1201
- if (need_prime && copied > 24 )
1202
- copied -= 8 ;
1203
- left = width - copied ;
1204
-
1205
- /* Care for small copies. */
1206
- if (copied > width ) {
1207
- u32 t ;
1208
- t = (1ul << width ) - 1 ;
1209
- t <<= dalign + need_prime * 8 ;
1210
- dmask_first &= t ;
1211
- left = 0 ;
1212
- }
1213
-
1214
- /* Attempt to use 64-byte copies. This is only possible if the
1215
- source and destination are co-aligned at 64 bytes. */
1216
- n64 = need_second = 0 ;
1217
- if ((dpos & 63 ) == (spos & 63 )
1218
- && (height == 1 || line_length % 64 == 0 )) {
1219
- /* We may need a 32-byte copy to ensure 64 byte alignment. */
1220
- need_second = (dpos + xincr_first ) & 63 ;
1221
- if ((need_second & 32 ) != need_second )
1222
- printk (KERN_ERR "tgafb: need_second wrong\n" );
1223
- if (left >= need_second + 64 ) {
1224
- left -= need_second ;
1225
- n64 = left / 64 ;
1226
- left %= 64 ;
1227
- } else
1228
- need_second = 0 ;
1229
- }
1230
-
1231
- /* Copy trailing full 32-byte sections. This will be the main
1232
- loop if the 64 byte loop can't be used. */
1233
- n32 = left / 32 ;
1234
- left %= 32 ;
1235
-
1236
- /* Copy the trailing unaligned destination. */
1237
- dmask_last = (1ul << left ) - 1 ;
1238
-
1239
- tga_regs = par -> tga_regs_base ;
1240
- tga_fb = par -> tga_fb_base ;
1241
-
1242
- /* Set up the MODE and PIXELSHIFT registers. */
1243
- __raw_writel (TGA_MODE_SBM_8BPP |TGA_MODE_COPY , tga_regs + TGA_MODE_REG );
1244
- __raw_writel (pixel_shift , tga_regs + TGA_PIXELSHIFT_REG );
1245
- wmb ();
1246
-
1247
- for (i = 0 ; i < height ; ++ i ) {
1248
- unsigned long j ;
1249
- void __iomem * sfb ;
1250
- void __iomem * dfb ;
1251
-
1252
- sfb = tga_fb + spos ;
1253
- dfb = tga_fb + dpos ;
1254
- if (dmask_first ) {
1255
- __raw_writel (smask_first , sfb );
1256
- wmb ();
1257
- __raw_writel (dmask_first , dfb );
1258
- wmb ();
1259
- sfb += xincr_first ;
1260
- dfb += xincr_first ;
1261
- }
1262
-
1263
- if (need_second ) {
1264
- __raw_writel (0xffffffff , sfb );
1265
- wmb ();
1266
- __raw_writel (0xffffffff , dfb );
1267
- wmb ();
1268
- sfb += 32 ;
1269
- dfb += 32 ;
1270
- }
1271
-
1272
- if (n64 && (((unsigned long )sfb | (unsigned long )dfb ) & 63 ))
1273
- printk (KERN_ERR
1274
- "tgafb: misaligned copy64 (s:%p, d:%p)\n" ,
1275
- sfb , dfb );
1276
-
1277
- for (j = 0 ; j < n64 ; ++ j ) {
1278
- __raw_writel (sfb - tga_fb , tga_regs + TGA_COPY64_SRC );
1279
- wmb ();
1280
- __raw_writel (dfb - tga_fb , tga_regs + TGA_COPY64_DST );
1281
- wmb ();
1282
- sfb += 64 ;
1283
- dfb += 64 ;
1284
- }
1285
-
1286
- for (j = 0 ; j < n32 ; ++ j ) {
1287
- __raw_writel (0xffffffff , sfb );
1288
- wmb ();
1289
- __raw_writel (0xffffffff , dfb );
1290
- wmb ();
1291
- sfb += 32 ;
1292
- dfb += 32 ;
1293
- }
1294
-
1295
- if (dmask_last ) {
1296
- __raw_writel (0xffffffff , sfb );
1297
- wmb ();
1298
- __raw_writel (dmask_last , dfb );
1299
- wmb ();
1300
- }
1301
-
1302
- spos += yincr ;
1303
- dpos += yincr ;
1163
+ /* Do acceleration only if we are aligned on 8 pixels */
1164
+ if ((dx | sx | width ) & 7 ) {
1165
+ cfb_copyarea (info , area );
1166
+ return ;
1304
1167
}
1305
1168
1306
- /* Reset the MODE register to normal. */
1307
- __raw_writel (TGA_MODE_SBM_8BPP |TGA_MODE_SIMPLE , tga_regs + TGA_MODE_REG );
1308
- }
1309
-
1310
- /* The (almost) general case of backward copy in 8bpp mode. */
1311
- static inline void
1312
- copyarea_backward_8bpp (struct fb_info * info , u32 dx , u32 dy , u32 sx , u32 sy ,
1313
- u32 height , u32 width , u32 line_length ,
1314
- const struct fb_copyarea * area )
1315
- {
1316
- struct tga_par * par = (struct tga_par * ) info -> par ;
1317
- unsigned long i , left , yincr ;
1318
- unsigned long depos , sepos , dealign , sealign ;
1319
- u32 mask_first , mask_last ;
1320
- unsigned long n32 ;
1321
- void __iomem * tga_regs ;
1322
- void __iomem * tga_fb ;
1323
-
1324
1169
yincr = line_length ;
1325
1170
if (dy > sy ) {
1326
1171
dy += height - 1 ;
1327
1172
sy += height - 1 ;
1328
1173
yincr = - yincr ;
1329
1174
}
1175
+ backward = dy == sy && dx > sx && dx < sx + width ;
1330
1176
1331
1177
/* Compute the offsets and alignments in the frame buffer.
1332
1178
More than anything else, these control how we do copies. */
1333
- depos = dy * line_length + dx + width ;
1334
- sepos = sy * line_length + sx + width ;
1335
- dealign = depos & 7 ;
1336
- sealign = sepos & 7 ;
1337
-
1338
- /* ??? The documentation appears to be incorrect (or very
1339
- misleading) wrt how pixel shifting works in backward copy
1340
- mode, i.e. when PIXELSHIFT is negative. I give up for now.
1341
- Do handle the common case of co-aligned backward copies,
1342
- but frob everything else back on generic code. */
1343
- if (dealign != sealign ) {
1344
- cfb_copyarea (info , area );
1345
- return ;
1346
- }
1347
-
1348
- /* We begin the copy with the trailing pixels of the
1349
- unaligned destination. */
1350
- mask_first = (1ul << dealign ) - 1 ;
1351
- left = width - dealign ;
1352
-
1353
- /* Care for small copies. */
1354
- if (dealign > width ) {
1355
- mask_first ^= (1ul << (dealign - width )) - 1 ;
1356
- left = 0 ;
1357
- }
1179
+ depos = dy * line_length + dx ;
1180
+ sepos = sy * line_length + sx ;
1181
+ if (backward )
1182
+ depos += width , sepos += width ;
1358
1183
1359
1184
/* Next copy full words at a time. */
1360
- n32 = left / 32 ;
1361
- left %= 32 ;
1185
+ n32 = width / 32 ;
1186
+ last_step = width % 32 ;
1362
1187
1363
1188
/* Finally copy the unaligned head of the span. */
1364
- mask_last = -1 << (32 - left );
1189
+ mask_last = (1ul << last_step ) - 1 ;
1190
+
1191
+ if (!backward ) {
1192
+ step = 32 ;
1193
+ last_step = 32 ;
1194
+ } else {
1195
+ step = -32 ;
1196
+ last_step = - last_step ;
1197
+ sepos -= 32 ;
1198
+ depos -= 32 ;
1199
+ }
1365
1200
1366
1201
tga_regs = par -> tga_regs_base ;
1367
1202
tga_fb = par -> tga_fb_base ;
@@ -1378,25 +1213,33 @@ copyarea_backward_8bpp(struct fb_info *info, u32 dx, u32 dy, u32 sx, u32 sy,
1378
1213
1379
1214
sfb = tga_fb + sepos ;
1380
1215
dfb = tga_fb + depos ;
1381
- if (mask_first ) {
1382
- __raw_writel (mask_first , sfb );
1383
- wmb ();
1384
- __raw_writel (mask_first , dfb );
1385
- wmb ();
1386
- }
1387
1216
1388
- for (j = 0 ; j < n32 ; ++ j ) {
1389
- sfb -= 32 ;
1390
- dfb -= 32 ;
1217
+ for (j = 0 ; j < n32 ; j ++ ) {
1218
+ if (j < 2 && j + 1 < n32 && !backward &&
1219
+ !(((unsigned long )sfb | (unsigned long )dfb ) & 63 )) {
1220
+ do {
1221
+ __raw_writel (sfb - tga_fb , tga_regs + TGA_COPY64_SRC );
1222
+ wmb ();
1223
+ __raw_writel (dfb - tga_fb , tga_regs + TGA_COPY64_DST );
1224
+ wmb ();
1225
+ sfb += 64 ;
1226
+ dfb += 64 ;
1227
+ j += 2 ;
1228
+ } while (j + 1 < n32 );
1229
+ j -- ;
1230
+ continue ;
1231
+ }
1391
1232
__raw_writel (0xffffffff , sfb );
1392
1233
wmb ();
1393
1234
__raw_writel (0xffffffff , dfb );
1394
1235
wmb ();
1236
+ sfb += step ;
1237
+ dfb += step ;
1395
1238
}
1396
1239
1397
1240
if (mask_last ) {
1398
- sfb -= 32 ;
1399
- dfb -= 32 ;
1241
+ sfb += last_step - step ;
1242
+ dfb += last_step - step ;
1400
1243
__raw_writel (mask_last , sfb );
1401
1244
wmb ();
1402
1245
__raw_writel (mask_last , dfb );
@@ -1457,14 +1300,9 @@ tgafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
1457
1300
else if (bpp == 32 )
1458
1301
cfb_copyarea (info , area );
1459
1302
1460
- /* Detect overlapping source and destination that requires
1461
- a backward copy. */
1462
- else if (dy == sy && dx > sx && dx < sx + width )
1463
- copyarea_backward_8bpp (info , dx , dy , sx , sy , height ,
1464
- width , line_length , area );
1465
1303
else
1466
- copyarea_foreward_8bpp (info , dx , dy , sx , sy , height ,
1467
- width , line_length );
1304
+ copyarea_8bpp (info , dx , dy , sx , sy , height ,
1305
+ width , line_length , area );
1468
1306
}
1469
1307
1470
1308
0 commit comments