1 #include<linux/module.h>
2 #include<linux/kernel.h>
3 #include<linux/errno.h>
4 #include<linux/string.h>
7 #include<linux/delay.h>
9 #include<linux/ioport.h>
10 #include<linux/init.h>
12 #include<linux/vmalloc.h>
13 #include<linux/pagemap.h>
14 #include <linux/console.h>
15 #include<linux/platform_device.h>
16 #include<linux/screen_info.h>
19 #include "sm750_accel.h"
20 #include "sm750_help.h"
21 static inline void write_dpr(struct lynx_accel * accel, int offset, u32 regValue)
23 writel(regValue, accel->dprBase + offset);
26 static inline u32 read_dpr(struct lynx_accel * accel, int offset)
28 return readl(accel->dprBase + offset);
31 static inline void write_dpPort(struct lynx_accel * accel, u32 data)
33 writel(data, accel->dpPortBase);
36 void hw_de_init(struct lynx_accel * accel)
38 /* setup 2d engine registers */
41 write_dpr(accel, DE_MASKS, 0xFFFFFFFF);
44 reg = FIELD_SET(0, DE_STRETCH_FORMAT, PATTERN_XY, NORMAL)|
45 FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_Y, 0)|
46 FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X, 0)|
47 FIELD_SET(0, DE_STRETCH_FORMAT, ADDRESSING, XY)|
48 FIELD_VALUE(0, DE_STRETCH_FORMAT, SOURCE_HEIGHT, 3);
50 clr = FIELD_CLEAR(DE_STRETCH_FORMAT, PATTERN_XY)&
51 FIELD_CLEAR(DE_STRETCH_FORMAT, PATTERN_Y)&
52 FIELD_CLEAR(DE_STRETCH_FORMAT, PATTERN_X)&
53 FIELD_CLEAR(DE_STRETCH_FORMAT, ADDRESSING)&
54 FIELD_CLEAR(DE_STRETCH_FORMAT, SOURCE_HEIGHT);
56 /* DE_STRETCH bpp format need be initilized in setMode routine */
57 write_dpr(accel, DE_STRETCH_FORMAT, (read_dpr(accel, DE_STRETCH_FORMAT) & clr) | reg);
59 /* disable clipping and transparent */
60 write_dpr(accel, DE_CLIP_TL, 0); /* dpr2c */
61 write_dpr(accel, DE_CLIP_BR, 0); /* dpr30 */
63 write_dpr(accel, DE_COLOR_COMPARE_MASK, 0); /* dpr24 */
64 write_dpr(accel, DE_COLOR_COMPARE, 0);
66 reg = FIELD_SET(0, DE_CONTROL, TRANSPARENCY, DISABLE)|
67 FIELD_SET(0, DE_CONTROL, TRANSPARENCY_MATCH, OPAQUE)|
68 FIELD_SET(0, DE_CONTROL, TRANSPARENCY_SELECT, SOURCE);
70 clr = FIELD_CLEAR(DE_CONTROL, TRANSPARENCY)&
71 FIELD_CLEAR(DE_CONTROL, TRANSPARENCY_MATCH)&
72 FIELD_CLEAR(DE_CONTROL, TRANSPARENCY_SELECT);
75 write_dpr(accel, DE_CONTROL, (read_dpr(accel, DE_CONTROL)&clr)|reg);
78 /* set2dformat only be called from setmode functions
79 * but if you need dual framebuffer driver,need call set2dformat
80 * every time you use 2d function */
82 void hw_set2dformat(struct lynx_accel * accel, int fmt)
86 /* fmt=0,1,2 for 8,16,32,bpp on sm718/750/502 */
87 reg = read_dpr(accel, DE_STRETCH_FORMAT);
88 reg = FIELD_VALUE(reg, DE_STRETCH_FORMAT, PIXEL_FORMAT, fmt);
89 write_dpr(accel, DE_STRETCH_FORMAT, reg);
92 int hw_fillrect(struct lynx_accel * accel,
93 u32 base, u32 pitch, u32 Bpp,
94 u32 x, u32 y, u32 width, u32 height,
99 if(accel->de_wait() != 0)
101 /* int time wait and always busy,seems hardware
102 * got something error */
103 pr_debug("%s:De engine always bussy\n", __func__);
107 write_dpr(accel, DE_WINDOW_DESTINATION_BASE, base); /* dpr40 */
108 write_dpr(accel, DE_PITCH,
109 FIELD_VALUE(0, DE_PITCH, DESTINATION, pitch/Bpp)|
110 FIELD_VALUE(0, DE_PITCH, SOURCE, pitch/Bpp)); /* dpr10 */
112 write_dpr(accel, DE_WINDOW_WIDTH,
113 FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, pitch/Bpp)|
114 FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE, pitch/Bpp)); /* dpr44 */
116 write_dpr(accel, DE_FOREGROUND, color); /* DPR14 */
118 write_dpr(accel, DE_DESTINATION,
119 FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE)|
120 FIELD_VALUE(0, DE_DESTINATION, X, x)|
121 FIELD_VALUE(0, DE_DESTINATION, Y, y)); /* dpr4 */
123 write_dpr(accel, DE_DIMENSION,
124 FIELD_VALUE(0, DE_DIMENSION, X, width)|
125 FIELD_VALUE(0, DE_DIMENSION, Y_ET, height)); /* dpr8 */
128 FIELD_SET(0, DE_CONTROL, STATUS, START)|
129 FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT)|
130 FIELD_SET(0, DE_CONTROL, LAST_PIXEL, ON)|
131 FIELD_SET(0, DE_CONTROL, COMMAND, RECTANGLE_FILL)|
132 FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2)|
133 FIELD_VALUE(0, DE_CONTROL, ROP, rop); /* dpr0xc */
135 write_dpr(accel, DE_CONTROL, deCtrl);
140 struct lynx_accel * accel,
141 unsigned int sBase, /* Address of source: offset in frame buffer */
142 unsigned int sPitch, /* Pitch value of source surface in BYTE */
144 unsigned int sy, /* Starting coordinate of source surface */
145 unsigned int dBase, /* Address of destination: offset in frame buffer */
146 unsigned int dPitch, /* Pitch value of destination surface in BYTE */
147 unsigned int Bpp, /* Color depth of destination surface */
149 unsigned int dy, /* Starting coordinate of destination surface */
151 unsigned int height, /* width and height of rectangle in pixel value */
152 unsigned int rop2) /* ROP value */
154 unsigned int nDirection, de_ctrl;
156 nDirection = LEFT_TO_RIGHT;
157 /* Direction of ROP2 operation: 1 = Left to Right, (-1) = Right to Left */
161 /* If source and destination are the same surface, need to check for overlay cases */
162 if (sBase == dBase && sPitch == dPitch)
164 /* Determine direction of operation */
176 nDirection = BOTTOM_TO_TOP;
189 nDirection = TOP_TO_BOTTOM;
197 /* +------+---+------+
202 +------+---+------+ */
204 nDirection = RIGHT_TO_LEFT;
210 /* +------+---+------+
215 +------+---+------+ */
217 nDirection = LEFT_TO_RIGHT;
222 if ((nDirection == BOTTOM_TO_TOP) || (nDirection == RIGHT_TO_LEFT))
232 DE_FOREGROUND are DE_BACKGROUND are don't care.
233 DE_COLOR_COMPARE and DE_COLOR_COMPARE_MAKS are set by set deSetTransparency().
237 It is an address offset (128 bit aligned) from the beginning of frame buffer.
239 write_dpr(accel, DE_WINDOW_SOURCE_BASE, sBase); /* dpr40 */
241 /* 2D Destination Base.
242 It is an address offset (128 bit aligned) from the beginning of frame buffer.
244 write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase); /* dpr44 */
247 /* Program pitch (distance between the 1st points of two adjacent lines).
248 Note that input pitch is BYTE value, but the 2D Pitch register uses
249 pixel values. Need Byte to pixel conversion.
255 write_dpr(accel, DE_PITCH,
256 FIELD_VALUE(0, DE_PITCH, DESTINATION, dPitch) |
257 FIELD_VALUE(0, DE_PITCH, SOURCE, sPitch)); /* dpr10 */
262 write_dpr(accel, DE_PITCH,
263 FIELD_VALUE(0, DE_PITCH, DESTINATION, (dPitch/Bpp)) |
264 FIELD_VALUE(0, DE_PITCH, SOURCE, (sPitch/Bpp))); /* dpr10 */
267 /* Screen Window width in Pixels.
268 2D engine uses this value to calculate the linear address in frame buffer for a given point.
270 write_dpr(accel, DE_WINDOW_WIDTH,
271 FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, (dPitch/Bpp)) |
272 FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE, (sPitch/Bpp))); /* dpr3c */
274 if (accel->de_wait() != 0){
280 write_dpr(accel, DE_SOURCE,
281 FIELD_SET (0, DE_SOURCE, WRAP, DISABLE) |
282 FIELD_VALUE(0, DE_SOURCE, X_K1, sx) |
283 FIELD_VALUE(0, DE_SOURCE, Y_K2, sy)); /* dpr0 */
284 write_dpr(accel, DE_DESTINATION,
285 FIELD_SET (0, DE_DESTINATION, WRAP, DISABLE) |
286 FIELD_VALUE(0, DE_DESTINATION, X, dx) |
287 FIELD_VALUE(0, DE_DESTINATION, Y, dy)); /* dpr04 */
288 write_dpr(accel, DE_DIMENSION,
289 FIELD_VALUE(0, DE_DIMENSION, X, width) |
290 FIELD_VALUE(0, DE_DIMENSION, Y_ET, height)); /* dpr08 */
293 FIELD_VALUE(0, DE_CONTROL, ROP, rop2) |
294 FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
295 FIELD_SET(0, DE_CONTROL, COMMAND, BITBLT) |
296 ((nDirection == RIGHT_TO_LEFT) ?
297 FIELD_SET(0, DE_CONTROL, DIRECTION, RIGHT_TO_LEFT)
298 : FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT)) |
299 FIELD_SET(0, DE_CONTROL, STATUS, START);
300 write_dpr(accel, DE_CONTROL, de_ctrl); /* dpr0c */
306 static unsigned int deGetTransparency(struct lynx_accel * accel)
308 unsigned int de_ctrl;
310 de_ctrl = read_dpr(accel, DE_CONTROL);
313 FIELD_MASK(DE_CONTROL_TRANSPARENCY_MATCH) |
314 FIELD_MASK(DE_CONTROL_TRANSPARENCY_SELECT)|
315 FIELD_MASK(DE_CONTROL_TRANSPARENCY);
320 int hw_imageblit(struct lynx_accel *accel,
321 const char *pSrcbuf, /* pointer to start of source buffer in system memory */
322 u32 srcDelta, /* Pitch value (in bytes) of the source buffer, +ive means top down and -ive mean button up */
323 u32 startBit, /* Mono data can start at any bit in a byte, this value should be 0 to 7 */
324 u32 dBase, /* Address of destination: offset in frame buffer */
325 u32 dPitch, /* Pitch value of destination surface in BYTE */
326 u32 bytePerPixel, /* Color depth of destination surface */
328 u32 dy, /* Starting coordinate of destination surface */
330 u32 height, /* width and height of rectange in pixel value */
331 u32 fColor, /* Foreground color (corresponding to a 1 in the monochrome data */
332 u32 bColor, /* Background color (corresponding to a 0 in the monochrome data */
333 u32 rop2) /* ROP value */
335 unsigned int ulBytesPerScan;
336 unsigned int ul4BytesPerScan;
337 unsigned int ulBytesRemain;
338 unsigned int de_ctrl = 0;
339 unsigned char ajRemain[4];
342 startBit &= 7; /* Just make sure the start bit is within legal range */
343 ulBytesPerScan = (width + startBit + 7) / 8;
344 ul4BytesPerScan = ulBytesPerScan & ~3;
345 ulBytesRemain = ulBytesPerScan & 3;
347 if(accel->de_wait() != 0)
355 write_dpr(accel, DE_WINDOW_SOURCE_BASE, 0);
357 /* 2D Destination Base.
358 It is an address offset (128 bit aligned) from the beginning of frame buffer.
360 write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase);
362 /* Program pitch (distance between the 1st points of two adjacent lines).
363 Note that input pitch is BYTE value, but the 2D Pitch register uses
364 pixel values. Need Byte to pixel conversion.
366 if(bytePerPixel == 3 ){
370 write_dpr(accel, DE_PITCH,
371 FIELD_VALUE(0, DE_PITCH, DESTINATION, dPitch) |
372 FIELD_VALUE(0, DE_PITCH, SOURCE, dPitch)); /* dpr10 */
378 write_dpr(accel, DE_PITCH,
379 FIELD_VALUE(0, DE_PITCH, DESTINATION, dPitch/bytePerPixel) |
380 FIELD_VALUE(0, DE_PITCH, SOURCE, dPitch/bytePerPixel)); /* dpr10 */
383 /* Screen Window width in Pixels.
384 2D engine uses this value to calculate the linear address in frame buffer for a given point.
386 write_dpr(accel, DE_WINDOW_WIDTH,
387 FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, (dPitch/bytePerPixel)) |
388 FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE, (dPitch/bytePerPixel)));
390 /* Note: For 2D Source in Host Write, only X_K1_MONO field is needed, and Y_K2 field is not used.
391 For mono bitmap, use startBit for X_K1. */
392 write_dpr(accel, DE_SOURCE,
393 FIELD_SET (0, DE_SOURCE, WRAP, DISABLE) |
394 FIELD_VALUE(0, DE_SOURCE, X_K1_MONO, startBit)); /* dpr00 */
396 write_dpr(accel, DE_DESTINATION,
397 FIELD_SET (0, DE_DESTINATION, WRAP, DISABLE) |
398 FIELD_VALUE(0, DE_DESTINATION, X, dx) |
399 FIELD_VALUE(0, DE_DESTINATION, Y, dy)); /* dpr04 */
401 write_dpr(accel, DE_DIMENSION,
402 FIELD_VALUE(0, DE_DIMENSION, X, width) |
403 FIELD_VALUE(0, DE_DIMENSION, Y_ET, height)); /* dpr08 */
405 write_dpr(accel, DE_FOREGROUND, fColor);
406 write_dpr(accel, DE_BACKGROUND, bColor);
408 de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, rop2) |
409 FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
410 FIELD_SET(0, DE_CONTROL, COMMAND, HOST_WRITE) |
411 FIELD_SET(0, DE_CONTROL, HOST, MONO) |
412 FIELD_SET(0, DE_CONTROL, STATUS, START);
414 write_dpr(accel, DE_CONTROL, de_ctrl | deGetTransparency(accel));
416 /* Write MONO data (line by line) to 2D Engine data port */
417 for (i=0; i<height; i++)
419 /* For each line, send the data in chunks of 4 bytes */
420 for (j=0; j<(ul4BytesPerScan/4); j++)
422 write_dpPort(accel, *(unsigned int *)(pSrcbuf + (j * 4)));
427 memcpy(ajRemain, pSrcbuf+ul4BytesPerScan, ulBytesRemain);
428 write_dpPort(accel, *(unsigned int *)ajRemain);