LCOV - code coverage report
Current view: top level - drivers/video/fbdev/core - syscopyarea.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 191 0.0 %
Date: 2023-08-24 13:40:31 Functions: 0 3 0.0 %

          Line data    Source code
       1             : /*
       2             :  *  Generic Bit Block Transfer for frame buffers located in system RAM with
       3             :  *  packed pixels of any depth.
       4             :  *
       5             :  *  Based almost entirely from cfbcopyarea.c (which is based almost entirely
       6             :  *  on Geert Uytterhoeven's copyarea routine)
       7             :  *
       8             :  *      Copyright (C)  2007 Antonino Daplas <adaplas@pol.net>
       9             :  *
      10             :  *  This file is subject to the terms and conditions of the GNU General Public
      11             :  *  License.  See the file COPYING in the main directory of this archive for
      12             :  *  more details.
      13             :  *
      14             :  */
      15             : #include <linux/module.h>
      16             : #include <linux/kernel.h>
      17             : #include <linux/string.h>
      18             : #include <linux/fb.h>
      19             : #include <asm/types.h>
      20             : #include <asm/io.h>
      21             : #include "fb_draw.h"
      22             : 
      23             :     /*
      24             :      *  Generic bitwise copy algorithm
      25             :      */
      26             : 
      27             : static void
      28           0 : bitcpy(struct fb_info *p, unsigned long *dst, unsigned dst_idx,
      29             :         const unsigned long *src, unsigned src_idx, int bits, unsigned n)
      30             : {
      31             :         unsigned long first, last;
      32           0 :         int const shift = dst_idx-src_idx;
      33             :         int left, right;
      34             : 
      35           0 :         first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
      36           0 :         last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
      37             : 
      38           0 :         if (!shift) {
      39             :                 /* Same alignment for source and dest */
      40           0 :                 if (dst_idx+n <= bits) {
      41             :                         /* Single word */
      42           0 :                         if (last)
      43           0 :                                 first &= last;
      44           0 :                         *dst = comp(*src, *dst, first);
      45             :                 } else {
      46             :                         /* Multiple destination words */
      47             :                         /* Leading bits */
      48           0 :                         if (first != ~0UL) {
      49           0 :                                 *dst = comp(*src, *dst, first);
      50           0 :                                 dst++;
      51           0 :                                 src++;
      52           0 :                                 n -= bits - dst_idx;
      53             :                         }
      54             : 
      55             :                         /* Main chunk */
      56           0 :                         n /= bits;
      57           0 :                         while (n >= 8) {
      58           0 :                                 *dst++ = *src++;
      59           0 :                                 *dst++ = *src++;
      60           0 :                                 *dst++ = *src++;
      61           0 :                                 *dst++ = *src++;
      62           0 :                                 *dst++ = *src++;
      63           0 :                                 *dst++ = *src++;
      64           0 :                                 *dst++ = *src++;
      65           0 :                                 *dst++ = *src++;
      66           0 :                                 n -= 8;
      67             :                         }
      68           0 :                         while (n--)
      69           0 :                                 *dst++ = *src++;
      70             : 
      71             :                         /* Trailing bits */
      72           0 :                         if (last)
      73           0 :                                 *dst = comp(*src, *dst, last);
      74             :                 }
      75             :         } else {
      76             :                 unsigned long d0, d1;
      77             :                 int m;
      78             : 
      79             :                 /* Different alignment for source and dest */
      80           0 :                 right = shift & (bits - 1);
      81           0 :                 left = -shift & (bits - 1);
      82             : 
      83           0 :                 if (dst_idx+n <= bits) {
      84             :                         /* Single destination word */
      85           0 :                         if (last)
      86           0 :                                 first &= last;
      87           0 :                         if (shift > 0) {
      88             :                                 /* Single source word */
      89           0 :                                 *dst = comp(*src << left, *dst, first);
      90           0 :                         } else if (src_idx+n <= bits) {
      91             :                                 /* Single source word */
      92           0 :                                 *dst = comp(*src >> right, *dst, first);
      93             :                         } else {
      94             :                                 /* 2 source words */
      95           0 :                                 d0 = *src++;
      96           0 :                                 d1 = *src;
      97           0 :                                 *dst = comp(d0 >> right | d1 << left, *dst,
      98             :                                             first);
      99             :                         }
     100             :                 } else {
     101             :                         /* Multiple destination words */
     102             :                         /** We must always remember the last value read,
     103             :                             because in case SRC and DST overlap bitwise (e.g.
     104             :                             when moving just one pixel in 1bpp), we always
     105             :                             collect one full long for DST and that might
     106             :                             overlap with the current long from SRC. We store
     107             :                             this value in 'd0'. */
     108           0 :                         d0 = *src++;
     109             :                         /* Leading bits */
     110           0 :                         if (shift > 0) {
     111             :                                 /* Single source word */
     112           0 :                                 *dst = comp(d0 << left, *dst, first);
     113           0 :                                 dst++;
     114           0 :                                 n -= bits - dst_idx;
     115             :                         } else {
     116             :                                 /* 2 source words */
     117           0 :                                 d1 = *src++;
     118           0 :                                 *dst = comp(d0 >> right | d1 << left, *dst,
     119             :                                             first);
     120           0 :                                 d0 = d1;
     121           0 :                                 dst++;
     122           0 :                                 n -= bits - dst_idx;
     123             :                         }
     124             : 
     125             :                         /* Main chunk */
     126           0 :                         m = n % bits;
     127           0 :                         n /= bits;
     128           0 :                         while (n >= 4) {
     129           0 :                                 d1 = *src++;
     130           0 :                                 *dst++ = d0 >> right | d1 << left;
     131           0 :                                 d0 = d1;
     132           0 :                                 d1 = *src++;
     133           0 :                                 *dst++ = d0 >> right | d1 << left;
     134           0 :                                 d0 = d1;
     135           0 :                                 d1 = *src++;
     136           0 :                                 *dst++ = d0 >> right | d1 << left;
     137           0 :                                 d0 = d1;
     138           0 :                                 d1 = *src++;
     139           0 :                                 *dst++ = d0 >> right | d1 << left;
     140           0 :                                 d0 = d1;
     141           0 :                                 n -= 4;
     142             :                         }
     143           0 :                         while (n--) {
     144           0 :                                 d1 = *src++;
     145           0 :                                 *dst++ = d0 >> right | d1 << left;
     146           0 :                                 d0 = d1;
     147             :                         }
     148             : 
     149             :                         /* Trailing bits */
     150           0 :                         if (m) {
     151           0 :                                 if (m <= bits - right) {
     152             :                                         /* Single source word */
     153           0 :                                         d0 >>= right;
     154             :                                 } else {
     155             :                                         /* 2 source words */
     156           0 :                                         d1 = *src;
     157           0 :                                         d0 = d0 >> right | d1 << left;
     158             :                                 }
     159           0 :                                 *dst = comp(d0, *dst, last);
     160             :                         }
     161             :                 }
     162             :         }
     163           0 : }
     164             : 
     165             :     /*
     166             :      *  Generic bitwise copy algorithm, operating backward
     167             :      */
     168             : 
     169             : static void
     170           0 : bitcpy_rev(struct fb_info *p, unsigned long *dst, unsigned dst_idx,
     171             :            const unsigned long *src, unsigned src_idx, unsigned bits,
     172             :            unsigned n)
     173             : {
     174             :         unsigned long first, last;
     175             :         int shift;
     176             : 
     177           0 :         dst += (dst_idx + n - 1) / bits;
     178           0 :         src += (src_idx + n - 1) / bits;
     179           0 :         dst_idx = (dst_idx + n - 1) % bits;
     180           0 :         src_idx = (src_idx + n - 1) % bits;
     181             : 
     182           0 :         shift = dst_idx-src_idx;
     183             : 
     184           0 :         first = ~FB_SHIFT_HIGH(p, ~0UL, (dst_idx + 1) % bits);
     185           0 :         last = FB_SHIFT_HIGH(p, ~0UL, (bits + dst_idx + 1 - n) % bits);
     186             : 
     187           0 :         if (!shift) {
     188             :                 /* Same alignment for source and dest */
     189           0 :                 if ((unsigned long)dst_idx+1 >= n) {
     190             :                         /* Single word */
     191           0 :                         if (first)
     192           0 :                                 last &= first;
     193           0 :                         *dst = comp(*src, *dst, last);
     194             :                 } else {
     195             :                         /* Multiple destination words */
     196             : 
     197             :                         /* Leading bits */
     198           0 :                         if (first) {
     199           0 :                                 *dst = comp(*src, *dst, first);
     200           0 :                                 dst--;
     201           0 :                                 src--;
     202           0 :                                 n -= dst_idx+1;
     203             :                         }
     204             : 
     205             :                         /* Main chunk */
     206           0 :                         n /= bits;
     207           0 :                         while (n >= 8) {
     208           0 :                                 *dst-- = *src--;
     209           0 :                                 *dst-- = *src--;
     210           0 :                                 *dst-- = *src--;
     211           0 :                                 *dst-- = *src--;
     212           0 :                                 *dst-- = *src--;
     213           0 :                                 *dst-- = *src--;
     214           0 :                                 *dst-- = *src--;
     215           0 :                                 *dst-- = *src--;
     216           0 :                                 n -= 8;
     217             :                         }
     218           0 :                         while (n--)
     219           0 :                                 *dst-- = *src--;
     220             :                         /* Trailing bits */
     221           0 :                         if (last != -1UL)
     222           0 :                                 *dst = comp(*src, *dst, last);
     223             :                 }
     224             :         } else {
     225             :                 /* Different alignment for source and dest */
     226             : 
     227           0 :                 int const left = shift & (bits-1);
     228           0 :                 int const right = -shift & (bits-1);
     229             : 
     230           0 :                 if ((unsigned long)dst_idx+1 >= n) {
     231             :                         /* Single destination word */
     232           0 :                         if (first)
     233           0 :                                 last &= first;
     234           0 :                         if (shift < 0) {
     235             :                                 /* Single source word */
     236           0 :                                 *dst = comp(*src >> right, *dst, last);
     237           0 :                         } else if (1+(unsigned long)src_idx >= n) {
     238             :                                 /* Single source word */
     239           0 :                                 *dst = comp(*src << left, *dst, last);
     240             :                         } else {
     241             :                                 /* 2 source words */
     242           0 :                                 *dst = comp(*src << left | *(src-1) >> right,
     243             :                                             *dst, last);
     244             :                         }
     245             :                 } else {
     246             :                         /* Multiple destination words */
     247             :                         /** We must always remember the last value read,
     248             :                             because in case SRC and DST overlap bitwise (e.g.
     249             :                             when moving just one pixel in 1bpp), we always
     250             :                             collect one full long for DST and that might
     251             :                             overlap with the current long from SRC. We store
     252             :                             this value in 'd0'. */
     253             :                         unsigned long d0, d1;
     254             :                         int m;
     255             : 
     256           0 :                         d0 = *src--;
     257             :                         /* Leading bits */
     258           0 :                         if (shift < 0) {
     259             :                                 /* Single source word */
     260           0 :                                 d1 = d0;
     261           0 :                                 d0 >>= right;
     262             :                         } else {
     263             :                                 /* 2 source words */
     264           0 :                                 d1 = *src--;
     265           0 :                                 d0 = d0 << left | d1 >> right;
     266             :                         }
     267           0 :                         if (!first)
     268           0 :                                 *dst = d0;
     269             :                         else
     270           0 :                                 *dst = comp(d0, *dst, first);
     271           0 :                         d0 = d1;
     272           0 :                         dst--;
     273           0 :                         n -= dst_idx+1;
     274             : 
     275             :                         /* Main chunk */
     276           0 :                         m = n % bits;
     277           0 :                         n /= bits;
     278           0 :                         while (n >= 4) {
     279           0 :                                 d1 = *src--;
     280           0 :                                 *dst-- = d0 << left | d1 >> right;
     281           0 :                                 d0 = d1;
     282           0 :                                 d1 = *src--;
     283           0 :                                 *dst-- = d0 << left | d1 >> right;
     284           0 :                                 d0 = d1;
     285           0 :                                 d1 = *src--;
     286           0 :                                 *dst-- = d0 << left | d1 >> right;
     287           0 :                                 d0 = d1;
     288           0 :                                 d1 = *src--;
     289           0 :                                 *dst-- = d0 << left | d1 >> right;
     290           0 :                                 d0 = d1;
     291           0 :                                 n -= 4;
     292             :                         }
     293           0 :                         while (n--) {
     294           0 :                                 d1 = *src--;
     295           0 :                                 *dst-- = d0 << left | d1 >> right;
     296           0 :                                 d0 = d1;
     297             :                         }
     298             : 
     299             :                         /* Trailing bits */
     300           0 :                         if (m) {
     301           0 :                                 if (m <= bits - left) {
     302             :                                         /* Single source word */
     303           0 :                                         d0 <<= left;
     304             :                                 } else {
     305             :                                         /* 2 source words */
     306           0 :                                         d1 = *src;
     307           0 :                                         d0 = d0 << left | d1 >> right;
     308             :                                 }
     309           0 :                                 *dst = comp(d0, *dst, last);
     310             :                         }
     311             :                 }
     312             :         }
     313           0 : }
     314             : 
     315           0 : void sys_copyarea(struct fb_info *p, const struct fb_copyarea *area)
     316             : {
     317           0 :         u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
     318           0 :         u32 height = area->height, width = area->width;
     319           0 :         unsigned long const bits_per_line = p->fix.line_length*8u;
     320           0 :         unsigned long *base = NULL;
     321           0 :         int bits = BITS_PER_LONG, bytes = bits >> 3;
     322           0 :         unsigned dst_idx = 0, src_idx = 0, rev_copy = 0;
     323             : 
     324           0 :         if (p->state != FBINFO_STATE_RUNNING)
     325             :                 return;
     326             : 
     327             :         /* if the beginning of the target area might overlap with the end of
     328             :         the source area, be have to copy the area reverse. */
     329           0 :         if ((dy == sy && dx > sx) || (dy > sy)) {
     330           0 :                 dy += height;
     331           0 :                 sy += height;
     332           0 :                 rev_copy = 1;
     333             :         }
     334             : 
     335             :         /* split the base of the framebuffer into a long-aligned address and
     336             :            the index of the first bit */
     337           0 :         base = (unsigned long *)((unsigned long)p->screen_base & ~(bytes-1));
     338           0 :         dst_idx = src_idx = 8*((unsigned long)p->screen_base & (bytes-1));
     339             :         /* add offset of source and target area */
     340           0 :         dst_idx += dy*bits_per_line + dx*p->var.bits_per_pixel;
     341           0 :         src_idx += sy*bits_per_line + sx*p->var.bits_per_pixel;
     342             : 
     343           0 :         if (p->fbops->fb_sync)
     344           0 :                 p->fbops->fb_sync(p);
     345             : 
     346           0 :         if (rev_copy) {
     347           0 :                 while (height--) {
     348           0 :                         dst_idx -= bits_per_line;
     349           0 :                         src_idx -= bits_per_line;
     350           0 :                         bitcpy_rev(p, base + (dst_idx / bits), dst_idx % bits,
     351           0 :                                 base + (src_idx / bits), src_idx % bits, bits,
     352           0 :                                 width*p->var.bits_per_pixel);
     353             :                 }
     354             :         } else {
     355           0 :                 while (height--) {
     356           0 :                         bitcpy(p, base + (dst_idx / bits), dst_idx % bits,
     357           0 :                                 base + (src_idx / bits), src_idx % bits, bits,
     358           0 :                                 width*p->var.bits_per_pixel);
     359           0 :                         dst_idx += bits_per_line;
     360           0 :                         src_idx += bits_per_line;
     361             :                 }
     362             :         }
     363             : }
     364             : 
     365             : EXPORT_SYMBOL(sys_copyarea);
     366             : 
     367             : MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
     368             : MODULE_DESCRIPTION("Generic copyarea (sys-to-sys)");
     369             : MODULE_LICENSE("GPL");
     370             : 

Generated by: LCOV version 1.14