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) {
100 /* int time wait and always busy,seems hardware
101 * got something error */
102 pr_debug("De engine always busy\n");
106 write_dpr(accel, DE_WINDOW_DESTINATION_BASE, base); /* dpr40 */
107 write_dpr(accel, DE_PITCH,
108 FIELD_VALUE(0, DE_PITCH, DESTINATION, pitch/Bpp)|
109 FIELD_VALUE(0, DE_PITCH, SOURCE, pitch/Bpp)); /* dpr10 */
111 write_dpr(accel, DE_WINDOW_WIDTH,
112 FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, pitch/Bpp)|
113 FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE, pitch/Bpp)); /* dpr44 */
115 write_dpr(accel, DE_FOREGROUND, color); /* DPR14 */
117 write_dpr(accel, DE_DESTINATION,
118 FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE)|
119 FIELD_VALUE(0, DE_DESTINATION, X, x)|
120 FIELD_VALUE(0, DE_DESTINATION, Y, y)); /* dpr4 */
122 write_dpr(accel, DE_DIMENSION,
123 FIELD_VALUE(0, DE_DIMENSION, X, width)|
124 FIELD_VALUE(0, DE_DIMENSION, Y_ET, height)); /* dpr8 */
127 FIELD_SET(0, DE_CONTROL, STATUS, START)|
128 FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT)|
129 FIELD_SET(0, DE_CONTROL, LAST_PIXEL, ON)|
130 FIELD_SET(0, DE_CONTROL, COMMAND, RECTANGLE_FILL)|
131 FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2)|
132 FIELD_VALUE(0, DE_CONTROL, ROP, rop); /* dpr0xc */
134 write_dpr(accel, DE_CONTROL, deCtrl);
139 struct lynx_accel *accel,
140 unsigned int sBase, /* Address of source: offset in frame buffer */
141 unsigned int sPitch, /* Pitch value of source surface in BYTE */
143 unsigned int sy, /* Starting coordinate of source surface */
144 unsigned int dBase, /* Address of destination: offset in frame buffer */
145 unsigned int dPitch, /* Pitch value of destination surface in BYTE */
146 unsigned int Bpp, /* Color depth of destination surface */
148 unsigned int dy, /* Starting coordinate of destination surface */
150 unsigned int height, /* width and height of rectangle in pixel value */
151 unsigned int rop2) /* ROP value */
153 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) {
163 /* Determine direction of operation */
174 nDirection = BOTTOM_TO_TOP;
175 } else if (sy > dy) {
185 nDirection = TOP_TO_BOTTOM;
190 /* +------+---+------+
195 +------+---+------+ */
197 nDirection = RIGHT_TO_LEFT;
201 /* +------+---+------+
206 +------+---+------+ */
208 nDirection = LEFT_TO_RIGHT;
213 if ((nDirection == BOTTOM_TO_TOP) || (nDirection == RIGHT_TO_LEFT)) {
222 DE_FOREGROUND are DE_BACKGROUND are don't care.
223 DE_COLOR_COMPARE and DE_COLOR_COMPARE_MAKS are set by set deSetTransparency().
227 It is an address offset (128 bit aligned) from the beginning of frame buffer.
229 write_dpr(accel, DE_WINDOW_SOURCE_BASE, sBase); /* dpr40 */
231 /* 2D Destination Base.
232 It is an address offset (128 bit aligned) from the beginning of frame buffer.
234 write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase); /* dpr44 */
237 /* Program pitch (distance between the 1st points of two adjacent lines).
238 Note that input pitch is BYTE value, but the 2D Pitch register uses
239 pixel values. Need Byte to pixel conversion.
245 write_dpr(accel, DE_PITCH,
246 FIELD_VALUE(0, DE_PITCH, DESTINATION, dPitch) |
247 FIELD_VALUE(0, DE_PITCH, SOURCE, sPitch)); /* dpr10 */
251 write_dpr(accel, DE_PITCH,
252 FIELD_VALUE(0, DE_PITCH, DESTINATION, (dPitch/Bpp)) |
253 FIELD_VALUE(0, DE_PITCH, SOURCE, (sPitch/Bpp))); /* dpr10 */
256 /* Screen Window width in Pixels.
257 2D engine uses this value to calculate the linear address in frame buffer for a given point.
259 write_dpr(accel, DE_WINDOW_WIDTH,
260 FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, (dPitch/Bpp)) |
261 FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE, (sPitch/Bpp))); /* dpr3c */
263 if (accel->de_wait() != 0)
268 write_dpr(accel, DE_SOURCE,
269 FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
270 FIELD_VALUE(0, DE_SOURCE, X_K1, sx) |
271 FIELD_VALUE(0, DE_SOURCE, Y_K2, sy)); /* dpr0 */
272 write_dpr(accel, DE_DESTINATION,
273 FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
274 FIELD_VALUE(0, DE_DESTINATION, X, dx) |
275 FIELD_VALUE(0, DE_DESTINATION, Y, dy)); /* dpr04 */
276 write_dpr(accel, DE_DIMENSION,
277 FIELD_VALUE(0, DE_DIMENSION, X, width) |
278 FIELD_VALUE(0, DE_DIMENSION, Y_ET, height)); /* dpr08 */
280 de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, rop2) |
281 FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
282 FIELD_SET(0, DE_CONTROL, COMMAND, BITBLT) |
283 ((nDirection == RIGHT_TO_LEFT) ?
284 FIELD_SET(0, DE_CONTROL, DIRECTION, RIGHT_TO_LEFT)
285 : FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT)) |
286 FIELD_SET(0, DE_CONTROL, STATUS, START);
287 write_dpr(accel, DE_CONTROL, de_ctrl); /* dpr0c */
294 static unsigned int deGetTransparency(struct lynx_accel *accel)
296 unsigned int de_ctrl;
298 de_ctrl = read_dpr(accel, DE_CONTROL);
301 FIELD_MASK(DE_CONTROL_TRANSPARENCY_MATCH) |
302 FIELD_MASK(DE_CONTROL_TRANSPARENCY_SELECT)|
303 FIELD_MASK(DE_CONTROL_TRANSPARENCY);
308 int hw_imageblit(struct lynx_accel *accel,
309 const char *pSrcbuf, /* pointer to start of source buffer in system memory */
310 u32 srcDelta, /* Pitch value (in bytes) of the source buffer, +ive means top down and -ive mean button up */
311 u32 startBit, /* Mono data can start at any bit in a byte, this value should be 0 to 7 */
312 u32 dBase, /* Address of destination: offset in frame buffer */
313 u32 dPitch, /* Pitch value of destination surface in BYTE */
314 u32 bytePerPixel, /* Color depth of destination surface */
316 u32 dy, /* Starting coordinate of destination surface */
318 u32 height, /* width and height of rectange in pixel value */
319 u32 fColor, /* Foreground color (corresponding to a 1 in the monochrome data */
320 u32 bColor, /* Background color (corresponding to a 0 in the monochrome data */
321 u32 rop2) /* ROP value */
323 unsigned int ulBytesPerScan;
324 unsigned int ul4BytesPerScan;
325 unsigned int ulBytesRemain;
326 unsigned int de_ctrl = 0;
327 unsigned char ajRemain[4];
330 startBit &= 7; /* Just make sure the start bit is within legal range */
331 ulBytesPerScan = (width + startBit + 7) / 8;
332 ul4BytesPerScan = ulBytesPerScan & ~3;
333 ulBytesRemain = ulBytesPerScan & 3;
335 if (accel->de_wait() != 0)
341 write_dpr(accel, DE_WINDOW_SOURCE_BASE, 0);
343 /* 2D Destination Base.
344 It is an address offset (128 bit aligned) from the beginning of frame buffer.
346 write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase);
348 /* Program pitch (distance between the 1st points of two adjacent lines).
349 Note that input pitch is BYTE value, but the 2D Pitch register uses
350 pixel values. Need Byte to pixel conversion.
352 if (bytePerPixel == 3) {
356 write_dpr(accel, DE_PITCH,
357 FIELD_VALUE(0, DE_PITCH, DESTINATION, dPitch) |
358 FIELD_VALUE(0, DE_PITCH, SOURCE, dPitch)); /* dpr10 */
363 write_dpr(accel, DE_PITCH,
364 FIELD_VALUE(0, DE_PITCH, DESTINATION, dPitch/bytePerPixel) |
365 FIELD_VALUE(0, DE_PITCH, SOURCE, dPitch/bytePerPixel)); /* dpr10 */
368 /* Screen Window width in Pixels.
369 2D engine uses this value to calculate the linear address in frame buffer for a given point.
371 write_dpr(accel, DE_WINDOW_WIDTH,
372 FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, (dPitch/bytePerPixel)) |
373 FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE, (dPitch/bytePerPixel)));
375 /* Note: For 2D Source in Host Write, only X_K1_MONO field is needed, and Y_K2 field is not used.
376 For mono bitmap, use startBit for X_K1. */
377 write_dpr(accel, DE_SOURCE,
378 FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
379 FIELD_VALUE(0, DE_SOURCE, X_K1_MONO, startBit)); /* dpr00 */
381 write_dpr(accel, DE_DESTINATION,
382 FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
383 FIELD_VALUE(0, DE_DESTINATION, X, dx) |
384 FIELD_VALUE(0, DE_DESTINATION, Y, dy)); /* dpr04 */
386 write_dpr(accel, DE_DIMENSION,
387 FIELD_VALUE(0, DE_DIMENSION, X, width) |
388 FIELD_VALUE(0, DE_DIMENSION, Y_ET, height)); /* dpr08 */
390 write_dpr(accel, DE_FOREGROUND, fColor);
391 write_dpr(accel, DE_BACKGROUND, bColor);
393 de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, rop2) |
394 FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
395 FIELD_SET(0, DE_CONTROL, COMMAND, HOST_WRITE) |
396 FIELD_SET(0, DE_CONTROL, HOST, MONO) |
397 FIELD_SET(0, DE_CONTROL, STATUS, START);
399 write_dpr(accel, DE_CONTROL, de_ctrl | deGetTransparency(accel));
401 /* Write MONO data (line by line) to 2D Engine data port */
402 for (i = 0; i < height; i++) {
403 /* For each line, send the data in chunks of 4 bytes */
404 for (j = 0; j < (ul4BytesPerScan/4); j++)
405 write_dpPort(accel, *(unsigned int *)(pSrcbuf + (j * 4)));
408 memcpy(ajRemain, pSrcbuf+ul4BytesPerScan, ulBytesRemain);
409 write_dpPort(accel, *(unsigned int *)ajRemain);