root/drivers/staging/sm750fb/sm750_accel.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. write_dpr
  2. read_dpr
  3. write_dpPort
  4. sm750_hw_de_init
  5. sm750_hw_set2dformat
  6. sm750_hw_fillrect
  7. sm750_hw_copyarea
  8. deGetTransparency
  9. sm750_hw_imageblit

   1 // SPDX-License-Identifier: GPL-2.0
   2 #include <linux/module.h>
   3 #include <linux/kernel.h>
   4 #include <linux/errno.h>
   5 #include <linux/string.h>
   6 #include <linux/mm.h>
   7 #include <linux/slab.h>
   8 #include <linux/delay.h>
   9 #include <linux/fb.h>
  10 #include <linux/ioport.h>
  11 #include <linux/init.h>
  12 #include <linux/pci.h>
  13 #include <linux/vmalloc.h>
  14 #include <linux/pagemap.h>
  15 #include <linux/console.h>
  16 #include <linux/platform_device.h>
  17 #include <linux/screen_info.h>
  18 
  19 #include "sm750.h"
  20 #include "sm750_accel.h"
  21 static inline void write_dpr(struct lynx_accel *accel, int offset, u32 regValue)
  22 {
  23         writel(regValue, accel->dprBase + offset);
  24 }
  25 
  26 static inline u32 read_dpr(struct lynx_accel *accel, int offset)
  27 {
  28         return readl(accel->dprBase + offset);
  29 }
  30 
  31 static inline void write_dpPort(struct lynx_accel *accel, u32 data)
  32 {
  33         writel(data, accel->dpPortBase);
  34 }
  35 
  36 void sm750_hw_de_init(struct lynx_accel *accel)
  37 {
  38         /* setup 2d engine registers */
  39         u32 reg, clr;
  40 
  41         write_dpr(accel, DE_MASKS, 0xFFFFFFFF);
  42 
  43         /* dpr1c */
  44         reg =  0x3;
  45 
  46         clr = DE_STRETCH_FORMAT_PATTERN_XY |
  47               DE_STRETCH_FORMAT_PATTERN_Y_MASK |
  48               DE_STRETCH_FORMAT_PATTERN_X_MASK |
  49               DE_STRETCH_FORMAT_ADDRESSING_MASK |
  50               DE_STRETCH_FORMAT_SOURCE_HEIGHT_MASK;
  51 
  52         /* DE_STRETCH bpp format need be initialized in setMode routine */
  53         write_dpr(accel, DE_STRETCH_FORMAT,
  54                   (read_dpr(accel, DE_STRETCH_FORMAT) & ~clr) | reg);
  55 
  56         /* disable clipping and transparent */
  57         write_dpr(accel, DE_CLIP_TL, 0); /* dpr2c */
  58         write_dpr(accel, DE_CLIP_BR, 0); /* dpr30 */
  59 
  60         write_dpr(accel, DE_COLOR_COMPARE_MASK, 0); /* dpr24 */
  61         write_dpr(accel, DE_COLOR_COMPARE, 0);
  62 
  63         clr = DE_CONTROL_TRANSPARENCY | DE_CONTROL_TRANSPARENCY_MATCH |
  64                 DE_CONTROL_TRANSPARENCY_SELECT;
  65 
  66         /* dpr0c */
  67         write_dpr(accel, DE_CONTROL, read_dpr(accel, DE_CONTROL) & ~clr);
  68 }
  69 
  70 /*
  71  * set2dformat only be called from setmode functions
  72  * but if you need dual framebuffer driver,need call set2dformat
  73  * every time you use 2d function
  74  */
  75 
  76 void sm750_hw_set2dformat(struct lynx_accel *accel, int fmt)
  77 {
  78         u32 reg;
  79 
  80         /* fmt=0,1,2 for 8,16,32,bpp on sm718/750/502 */
  81         reg = read_dpr(accel, DE_STRETCH_FORMAT);
  82         reg &= ~DE_STRETCH_FORMAT_PIXEL_FORMAT_MASK;
  83         reg |= ((fmt << DE_STRETCH_FORMAT_PIXEL_FORMAT_SHIFT) &
  84                 DE_STRETCH_FORMAT_PIXEL_FORMAT_MASK);
  85         write_dpr(accel, DE_STRETCH_FORMAT, reg);
  86 }
  87 
  88 int sm750_hw_fillrect(struct lynx_accel *accel,
  89                       u32 base, u32 pitch, u32 Bpp,
  90                       u32 x, u32 y, u32 width, u32 height,
  91                       u32 color, u32 rop)
  92 {
  93         u32 deCtrl;
  94 
  95         if (accel->de_wait() != 0) {
  96                 /*
  97                  * int time wait and always busy,seems hardware
  98                  * got something error
  99                  */
 100                 pr_debug("De engine always busy\n");
 101                 return -1;
 102         }
 103 
 104         write_dpr(accel, DE_WINDOW_DESTINATION_BASE, base); /* dpr40 */
 105         write_dpr(accel, DE_PITCH,
 106                   ((pitch / Bpp << DE_PITCH_DESTINATION_SHIFT) &
 107                    DE_PITCH_DESTINATION_MASK) |
 108                   (pitch / Bpp & DE_PITCH_SOURCE_MASK)); /* dpr10 */
 109 
 110         write_dpr(accel, DE_WINDOW_WIDTH,
 111                   ((pitch / Bpp << DE_WINDOW_WIDTH_DST_SHIFT) &
 112                    DE_WINDOW_WIDTH_DST_MASK) |
 113                    (pitch / Bpp & DE_WINDOW_WIDTH_SRC_MASK)); /* dpr44 */
 114 
 115         write_dpr(accel, DE_FOREGROUND, color); /* DPR14 */
 116 
 117         write_dpr(accel, DE_DESTINATION,
 118                   ((x << DE_DESTINATION_X_SHIFT) & DE_DESTINATION_X_MASK) |
 119                   (y & DE_DESTINATION_Y_MASK)); /* dpr4 */
 120 
 121         write_dpr(accel, DE_DIMENSION,
 122                   ((width << DE_DIMENSION_X_SHIFT) & DE_DIMENSION_X_MASK) |
 123                   (height & DE_DIMENSION_Y_ET_MASK)); /* dpr8 */
 124 
 125         deCtrl = DE_CONTROL_STATUS | DE_CONTROL_LAST_PIXEL |
 126                 DE_CONTROL_COMMAND_RECTANGLE_FILL | DE_CONTROL_ROP_SELECT |
 127                 (rop & DE_CONTROL_ROP_MASK); /* dpr0xc */
 128 
 129         write_dpr(accel, DE_CONTROL, deCtrl);
 130         return 0;
 131 }
 132 
 133 int sm750_hw_copyarea(
 134 struct lynx_accel *accel,
 135 unsigned int sBase,  /* Address of source: offset in frame buffer */
 136 unsigned int sPitch, /* Pitch value of source surface in BYTE */
 137 unsigned int sx,
 138 unsigned int sy,     /* Starting coordinate of source surface */
 139 unsigned int dBase,  /* Address of destination: offset in frame buffer */
 140 unsigned int dPitch, /* Pitch value of destination surface in BYTE */
 141 unsigned int Bpp,    /* Color depth of destination surface */
 142 unsigned int dx,
 143 unsigned int dy,     /* Starting coordinate of destination surface */
 144 unsigned int width,
 145 unsigned int height, /* width and height of rectangle in pixel value */
 146 unsigned int rop2)   /* ROP value */
 147 {
 148         unsigned int nDirection, de_ctrl;
 149 
 150         nDirection = LEFT_TO_RIGHT;
 151         /* Direction of ROP2 operation: 1 = Left to Right, (-1) = Right to Left */
 152         de_ctrl = 0;
 153 
 154         /* If source and destination are the same surface, need to check for overlay cases */
 155         if (sBase == dBase && sPitch == dPitch) {
 156                 /* Determine direction of operation */
 157                 if (sy < dy) {
 158                         /*  +----------+
 159                          *  |S         |
 160                          *  |   +----------+
 161                          *  |   |      |   |
 162                          *  |   |      |   |
 163                          *  +---|------+   |
 164                          *      |         D|
 165                          *      +----------+
 166                          */
 167 
 168                         nDirection = BOTTOM_TO_TOP;
 169                 } else if (sy > dy) {
 170                         /*  +----------+
 171                          *  |D         |
 172                          *  |   +----------+
 173                          *  |   |      |   |
 174                          *  |   |      |   |
 175                          *  +---|------+   |
 176                          *      |         S|
 177                          *      +----------+
 178                          */
 179 
 180                         nDirection = TOP_TO_BOTTOM;
 181                 } else {
 182                         /* sy == dy */
 183 
 184                         if (sx <= dx) {
 185                                 /* +------+---+------+
 186                                  * |S     |   |     D|
 187                                  * |      |   |      |
 188                                  * |      |   |      |
 189                                  * |      |   |      |
 190                                  * +------+---+------+
 191                                  */
 192 
 193                                 nDirection = RIGHT_TO_LEFT;
 194                         } else {
 195                         /* sx > dx */
 196 
 197                                 /* +------+---+------+
 198                                  * |D     |   |     S|
 199                                  * |      |   |      |
 200                                  * |      |   |      |
 201                                  * |      |   |      |
 202                                  * +------+---+------+
 203                                  */
 204 
 205                                 nDirection = LEFT_TO_RIGHT;
 206                         }
 207                 }
 208         }
 209 
 210         if ((nDirection == BOTTOM_TO_TOP) || (nDirection == RIGHT_TO_LEFT)) {
 211                 sx += width - 1;
 212                 sy += height - 1;
 213                 dx += width - 1;
 214                 dy += height - 1;
 215         }
 216 
 217         /*
 218          * Note:
 219          * DE_FOREGROUND are DE_BACKGROUND are don't care.
 220          * DE_COLOR_COMPARE and DE_COLOR_COMPARE_MAKS
 221          * are set by set deSetTransparency().
 222          */
 223 
 224         /*
 225          * 2D Source Base.
 226          * It is an address offset (128 bit aligned)
 227          * from the beginning of frame buffer.
 228          */
 229         write_dpr(accel, DE_WINDOW_SOURCE_BASE, sBase); /* dpr40 */
 230 
 231         /*
 232          * 2D Destination Base.
 233          * It is an address offset (128 bit aligned)
 234          * from the beginning of frame buffer.
 235          */
 236         write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase); /* dpr44 */
 237 
 238     /*
 239      * Program pitch (distance between the 1st points of two adjacent lines).
 240      * Note that input pitch is BYTE value, but the 2D Pitch register uses
 241      * pixel values. Need Byte to pixel conversion.
 242      */
 243         write_dpr(accel, DE_PITCH,
 244                   ((dPitch / Bpp << DE_PITCH_DESTINATION_SHIFT) &
 245                    DE_PITCH_DESTINATION_MASK) |
 246                   (sPitch / Bpp & DE_PITCH_SOURCE_MASK)); /* dpr10 */
 247 
 248     /*
 249      * Screen Window width in Pixels.
 250      * 2D engine uses this value to calculate the linear address in frame buffer
 251      * for a given point.
 252      */
 253         write_dpr(accel, DE_WINDOW_WIDTH,
 254                   ((dPitch / Bpp << DE_WINDOW_WIDTH_DST_SHIFT) &
 255                    DE_WINDOW_WIDTH_DST_MASK) |
 256                   (sPitch / Bpp & DE_WINDOW_WIDTH_SRC_MASK)); /* dpr3c */
 257 
 258         if (accel->de_wait() != 0)
 259                 return -1;
 260 
 261         write_dpr(accel, DE_SOURCE,
 262                   ((sx << DE_SOURCE_X_K1_SHIFT) & DE_SOURCE_X_K1_MASK) |
 263                   (sy & DE_SOURCE_Y_K2_MASK)); /* dpr0 */
 264         write_dpr(accel, DE_DESTINATION,
 265                   ((dx << DE_DESTINATION_X_SHIFT) & DE_DESTINATION_X_MASK) |
 266                   (dy & DE_DESTINATION_Y_MASK)); /* dpr04 */
 267         write_dpr(accel, DE_DIMENSION,
 268                   ((width << DE_DIMENSION_X_SHIFT) & DE_DIMENSION_X_MASK) |
 269                   (height & DE_DIMENSION_Y_ET_MASK)); /* dpr08 */
 270 
 271         de_ctrl = (rop2 & DE_CONTROL_ROP_MASK) | DE_CONTROL_ROP_SELECT |
 272                 ((nDirection == RIGHT_TO_LEFT) ? DE_CONTROL_DIRECTION : 0) |
 273                 DE_CONTROL_COMMAND_BITBLT | DE_CONTROL_STATUS;
 274         write_dpr(accel, DE_CONTROL, de_ctrl); /* dpr0c */
 275 
 276         return 0;
 277 }
 278 
 279 static unsigned int deGetTransparency(struct lynx_accel *accel)
 280 {
 281         unsigned int de_ctrl;
 282 
 283         de_ctrl = read_dpr(accel, DE_CONTROL);
 284 
 285         de_ctrl &= (DE_CONTROL_TRANSPARENCY_MATCH |
 286                     DE_CONTROL_TRANSPARENCY_SELECT | DE_CONTROL_TRANSPARENCY);
 287 
 288         return de_ctrl;
 289 }
 290 
 291 int sm750_hw_imageblit(struct lynx_accel *accel,
 292                  const char *pSrcbuf, /* pointer to start of source buffer in system memory */
 293                  u32 srcDelta,          /* Pitch value (in bytes) of the source buffer, +ive means top down and -ive mean button up */
 294                  u32 startBit, /* Mono data can start at any bit in a byte, this value should be 0 to 7 */
 295                  u32 dBase,    /* Address of destination: offset in frame buffer */
 296                  u32 dPitch,   /* Pitch value of destination surface in BYTE */
 297                  u32 bytePerPixel,      /* Color depth of destination surface */
 298                  u32 dx,
 299                  u32 dy,       /* Starting coordinate of destination surface */
 300                  u32 width,
 301                  u32 height,   /* width and height of rectangle in pixel value */
 302                  u32 fColor,   /* Foreground color (corresponding to a 1 in the monochrome data */
 303                  u32 bColor,   /* Background color (corresponding to a 0 in the monochrome data */
 304                  u32 rop2)     /* ROP value */
 305 {
 306         unsigned int ulBytesPerScan;
 307         unsigned int ul4BytesPerScan;
 308         unsigned int ulBytesRemain;
 309         unsigned int de_ctrl = 0;
 310         unsigned char ajRemain[4];
 311         int i, j;
 312 
 313         startBit &= 7; /* Just make sure the start bit is within legal range */
 314         ulBytesPerScan = (width + startBit + 7) / 8;
 315         ul4BytesPerScan = ulBytesPerScan & ~3;
 316         ulBytesRemain = ulBytesPerScan & 3;
 317 
 318         if (accel->de_wait() != 0)
 319                 return -1;
 320 
 321         /*
 322          * 2D Source Base.
 323          * Use 0 for HOST Blt.
 324          */
 325         write_dpr(accel, DE_WINDOW_SOURCE_BASE, 0);
 326 
 327         /* 2D Destination Base.
 328          * It is an address offset (128 bit aligned)
 329          * from the beginning of frame buffer.
 330          */
 331         write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase);
 332 
 333         /*
 334          * Program pitch (distance between the 1st points of two adjacent
 335          * lines). Note that input pitch is BYTE value, but the 2D Pitch
 336          * register uses pixel values. Need Byte to pixel conversion.
 337          */
 338         write_dpr(accel, DE_PITCH,
 339                   ((dPitch / bytePerPixel << DE_PITCH_DESTINATION_SHIFT) &
 340                    DE_PITCH_DESTINATION_MASK) |
 341                   (dPitch / bytePerPixel & DE_PITCH_SOURCE_MASK)); /* dpr10 */
 342 
 343         /*
 344          * Screen Window width in Pixels.
 345          * 2D engine uses this value to calculate the linear address
 346          * in frame buffer for a given point.
 347          */
 348         write_dpr(accel, DE_WINDOW_WIDTH,
 349                   ((dPitch / bytePerPixel << DE_WINDOW_WIDTH_DST_SHIFT) &
 350                    DE_WINDOW_WIDTH_DST_MASK) |
 351                   (dPitch / bytePerPixel & DE_WINDOW_WIDTH_SRC_MASK));
 352 
 353          /*
 354           * Note: For 2D Source in Host Write, only X_K1_MONO field is needed,
 355           * and Y_K2 field is not used.
 356           * For mono bitmap, use startBit for X_K1.
 357           */
 358         write_dpr(accel, DE_SOURCE,
 359                   (startBit << DE_SOURCE_X_K1_SHIFT) &
 360                   DE_SOURCE_X_K1_MONO_MASK); /* dpr00 */
 361 
 362         write_dpr(accel, DE_DESTINATION,
 363                   ((dx << DE_DESTINATION_X_SHIFT) & DE_DESTINATION_X_MASK) |
 364                   (dy & DE_DESTINATION_Y_MASK)); /* dpr04 */
 365 
 366         write_dpr(accel, DE_DIMENSION,
 367                   ((width << DE_DIMENSION_X_SHIFT) & DE_DIMENSION_X_MASK) |
 368                   (height & DE_DIMENSION_Y_ET_MASK)); /* dpr08 */
 369 
 370         write_dpr(accel, DE_FOREGROUND, fColor);
 371         write_dpr(accel, DE_BACKGROUND, bColor);
 372 
 373         de_ctrl = (rop2 & DE_CONTROL_ROP_MASK) |
 374                 DE_CONTROL_ROP_SELECT | DE_CONTROL_COMMAND_HOST_WRITE |
 375                 DE_CONTROL_HOST | DE_CONTROL_STATUS;
 376 
 377         write_dpr(accel, DE_CONTROL, de_ctrl | deGetTransparency(accel));
 378 
 379         /* Write MONO data (line by line) to 2D Engine data port */
 380         for (i = 0; i < height; i++) {
 381                 /* For each line, send the data in chunks of 4 bytes */
 382                 for (j = 0; j < (ul4BytesPerScan / 4); j++)
 383                         write_dpPort(accel, *(unsigned int *)(pSrcbuf + (j * 4)));
 384 
 385                 if (ulBytesRemain) {
 386                         memcpy(ajRemain, pSrcbuf + ul4BytesPerScan,
 387                                ulBytesRemain);
 388                         write_dpPort(accel, *(unsigned int *)ajRemain);
 389                 }
 390 
 391                 pSrcbuf += srcDelta;
 392         }
 393 
 394         return 0;
 395 }
 396 

/* [<][>][^][v][top][bottom][index][help] */