1 #include <linux/module.h>
2 #include <linux/kernel.h>
3 #include <linux/errno.h>
4 #include <linux/string.h>
6 #include <linux/slab.h>
7 #include <linux/delay.h>
9 #include <linux/ioport.h>
10 #include <linux/init.h>
11 #include <linux/pci.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);
46 clr = DE_STRETCH_FORMAT_PATTERN_XY | DE_STRETCH_FORMAT_PATTERN_Y_MASK |
47 DE_STRETCH_FORMAT_PATTERN_X_MASK |
48 DE_STRETCH_FORMAT_ADDRESSING_MASK |
49 DE_STRETCH_FORMAT_SOURCE_HEIGHT_MASK;
51 /* DE_STRETCH bpp format need be initialized in setMode routine */
52 write_dpr(accel, DE_STRETCH_FORMAT,
53 (read_dpr(accel, DE_STRETCH_FORMAT) & ~clr) | reg);
55 /* disable clipping and transparent */
56 write_dpr(accel, DE_CLIP_TL, 0); /* dpr2c */
57 write_dpr(accel, DE_CLIP_BR, 0); /* dpr30 */
59 write_dpr(accel, DE_COLOR_COMPARE_MASK, 0); /* dpr24 */
60 write_dpr(accel, DE_COLOR_COMPARE, 0);
62 clr = DE_CONTROL_TRANSPARENCY | DE_CONTROL_TRANSPARENCY_MATCH |
63 DE_CONTROL_TRANSPARENCY_SELECT;
66 write_dpr(accel, DE_CONTROL, read_dpr(accel, DE_CONTROL) & ~clr);
69 /* set2dformat only be called from setmode functions
70 * but if you need dual framebuffer driver,need call set2dformat
71 * every time you use 2d function */
73 void hw_set2dformat(struct lynx_accel *accel, int fmt)
77 /* fmt=0,1,2 for 8,16,32,bpp on sm718/750/502 */
78 reg = read_dpr(accel, DE_STRETCH_FORMAT);
79 reg &= ~DE_STRETCH_FORMAT_PIXEL_FORMAT_MASK;
80 reg |= ((fmt << DE_STRETCH_FORMAT_PIXEL_FORMAT_SHIFT) &
81 DE_STRETCH_FORMAT_PIXEL_FORMAT_MASK);
82 write_dpr(accel, DE_STRETCH_FORMAT, reg);
85 int hw_fillrect(struct lynx_accel *accel,
86 u32 base, u32 pitch, u32 Bpp,
87 u32 x, u32 y, u32 width, u32 height,
92 if (accel->de_wait() != 0) {
93 /* int time wait and always busy,seems hardware
94 * got something error */
95 pr_debug("De engine always busy\n");
99 write_dpr(accel, DE_WINDOW_DESTINATION_BASE, base); /* dpr40 */
100 write_dpr(accel, DE_PITCH,
101 ((pitch / Bpp << DE_PITCH_DESTINATION_SHIFT) &
102 DE_PITCH_DESTINATION_MASK) |
103 (pitch / Bpp & DE_PITCH_SOURCE_MASK)); /* dpr10 */
105 write_dpr(accel, DE_WINDOW_WIDTH,
106 FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, pitch/Bpp)|
107 FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE, pitch/Bpp)); /* dpr44 */
109 write_dpr(accel, DE_FOREGROUND, color); /* DPR14 */
111 write_dpr(accel, DE_DESTINATION,
112 ((x << DE_DESTINATION_X_SHIFT) & DE_DESTINATION_X_MASK) |
113 (y & DE_DESTINATION_Y_MASK)); /* dpr4 */
115 write_dpr(accel, DE_DIMENSION,
116 ((width << DE_DIMENSION_X_SHIFT) & DE_DIMENSION_X_MASK) |
117 (height & DE_DIMENSION_Y_ET_MASK)); /* dpr8 */
119 deCtrl = DE_CONTROL_STATUS | DE_CONTROL_LAST_PIXEL |
120 DE_CONTROL_COMMAND_RECTANGLE_FILL | DE_CONTROL_ROP_SELECT |
121 (rop & DE_CONTROL_ROP_MASK); /* dpr0xc */
123 write_dpr(accel, DE_CONTROL, deCtrl);
128 struct lynx_accel *accel,
129 unsigned int sBase, /* Address of source: offset in frame buffer */
130 unsigned int sPitch, /* Pitch value of source surface in BYTE */
132 unsigned int sy, /* Starting coordinate of source surface */
133 unsigned int dBase, /* Address of destination: offset in frame buffer */
134 unsigned int dPitch, /* Pitch value of destination surface in BYTE */
135 unsigned int Bpp, /* Color depth of destination surface */
137 unsigned int dy, /* Starting coordinate of destination surface */
139 unsigned int height, /* width and height of rectangle in pixel value */
140 unsigned int rop2) /* ROP value */
142 unsigned int nDirection, de_ctrl;
145 nDirection = LEFT_TO_RIGHT;
146 /* Direction of ROP2 operation: 1 = Left to Right, (-1) = Right to Left */
150 /* If source and destination are the same surface, need to check for overlay cases */
151 if (sBase == dBase && sPitch == dPitch) {
152 /* Determine direction of operation */
163 nDirection = BOTTOM_TO_TOP;
164 } else if (sy > dy) {
174 nDirection = TOP_TO_BOTTOM;
179 /* +------+---+------+
184 +------+---+------+ */
186 nDirection = RIGHT_TO_LEFT;
190 /* +------+---+------+
195 +------+---+------+ */
197 nDirection = LEFT_TO_RIGHT;
202 if ((nDirection == BOTTOM_TO_TOP) || (nDirection == RIGHT_TO_LEFT)) {
211 DE_FOREGROUND are DE_BACKGROUND are don't care.
212 DE_COLOR_COMPARE and DE_COLOR_COMPARE_MAKS are set by set deSetTransparency().
216 It is an address offset (128 bit aligned) from the beginning of frame buffer.
218 write_dpr(accel, DE_WINDOW_SOURCE_BASE, sBase); /* dpr40 */
220 /* 2D Destination Base.
221 It is an address offset (128 bit aligned) from the beginning of frame buffer.
223 write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase); /* dpr44 */
225 /* Program pitch (distance between the 1st points of two adjacent lines).
226 Note that input pitch is BYTE value, but the 2D Pitch register uses
227 pixel values. Need Byte to pixel conversion.
229 write_dpr(accel, DE_PITCH,
230 ((dPitch / Bpp << DE_PITCH_DESTINATION_SHIFT) &
231 DE_PITCH_DESTINATION_MASK) |
232 (sPitch / Bpp & DE_PITCH_SOURCE_MASK)); /* dpr10 */
234 /* Screen Window width in Pixels.
235 2D engine uses this value to calculate the linear address in frame buffer for a given point.
237 write_dpr(accel, DE_WINDOW_WIDTH,
238 FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, (dPitch/Bpp)) |
239 FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE, (sPitch/Bpp))); /* dpr3c */
241 if (accel->de_wait() != 0)
246 write_dpr(accel, DE_SOURCE,
247 ((sx << DE_SOURCE_X_K1_SHIFT) & DE_SOURCE_X_K1_MASK) |
248 (sy & DE_SOURCE_Y_K2_MASK)); /* dpr0 */
249 write_dpr(accel, DE_DESTINATION,
250 ((dx << DE_DESTINATION_X_SHIFT) & DE_DESTINATION_X_MASK) |
251 (dy & DE_DESTINATION_Y_MASK)); /* dpr04 */
252 write_dpr(accel, DE_DIMENSION,
253 ((width << DE_DIMENSION_X_SHIFT) & DE_DIMENSION_X_MASK) |
254 (height & DE_DIMENSION_Y_ET_MASK)); /* dpr08 */
256 de_ctrl = (rop2 & DE_CONTROL_ROP_MASK) | DE_CONTROL_ROP_SELECT |
257 ((nDirection == RIGHT_TO_LEFT) ? DE_CONTROL_DIRECTION : 0) |
258 DE_CONTROL_COMMAND_BITBLT | DE_CONTROL_STATUS;
259 write_dpr(accel, DE_CONTROL, de_ctrl); /* dpr0c */
266 static unsigned int deGetTransparency(struct lynx_accel *accel)
268 unsigned int de_ctrl;
270 de_ctrl = read_dpr(accel, DE_CONTROL);
272 de_ctrl &= (DE_CONTROL_TRANSPARENCY_MATCH |
273 DE_CONTROL_TRANSPARENCY_SELECT | DE_CONTROL_TRANSPARENCY);
278 int hw_imageblit(struct lynx_accel *accel,
279 const char *pSrcbuf, /* pointer to start of source buffer in system memory */
280 u32 srcDelta, /* Pitch value (in bytes) of the source buffer, +ive means top down and -ive mean button up */
281 u32 startBit, /* Mono data can start at any bit in a byte, this value should be 0 to 7 */
282 u32 dBase, /* Address of destination: offset in frame buffer */
283 u32 dPitch, /* Pitch value of destination surface in BYTE */
284 u32 bytePerPixel, /* Color depth of destination surface */
286 u32 dy, /* Starting coordinate of destination surface */
288 u32 height, /* width and height of rectangle in pixel value */
289 u32 fColor, /* Foreground color (corresponding to a 1 in the monochrome data */
290 u32 bColor, /* Background color (corresponding to a 0 in the monochrome data */
291 u32 rop2) /* ROP value */
293 unsigned int ulBytesPerScan;
294 unsigned int ul4BytesPerScan;
295 unsigned int ulBytesRemain;
296 unsigned int de_ctrl = 0;
297 unsigned char ajRemain[4];
300 startBit &= 7; /* Just make sure the start bit is within legal range */
301 ulBytesPerScan = (width + startBit + 7) / 8;
302 ul4BytesPerScan = ulBytesPerScan & ~3;
303 ulBytesRemain = ulBytesPerScan & 3;
305 if (accel->de_wait() != 0)
311 write_dpr(accel, DE_WINDOW_SOURCE_BASE, 0);
313 /* 2D Destination Base.
314 It is an address offset (128 bit aligned) from the beginning of frame buffer.
316 write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase);
317 /* Program pitch (distance between the 1st points of two adjacent lines).
318 Note that input pitch is BYTE value, but the 2D Pitch register uses
319 pixel values. Need Byte to pixel conversion.
321 write_dpr(accel, DE_PITCH,
322 ((dPitch / bytePerPixel << DE_PITCH_DESTINATION_SHIFT) &
323 DE_PITCH_DESTINATION_MASK) |
324 (dPitch / bytePerPixel & DE_PITCH_SOURCE_MASK)); /* dpr10 */
326 /* Screen Window width in Pixels.
327 2D engine uses this value to calculate the linear address in frame buffer for a given point.
329 write_dpr(accel, DE_WINDOW_WIDTH,
330 FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, (dPitch/bytePerPixel)) |
331 FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE, (dPitch/bytePerPixel)));
333 /* Note: For 2D Source in Host Write, only X_K1_MONO field is needed, and Y_K2 field is not used.
334 For mono bitmap, use startBit for X_K1. */
335 write_dpr(accel, DE_SOURCE,
336 (startBit << DE_SOURCE_X_K1_SHIFT) &
337 DE_SOURCE_X_K1_MONO_MASK); /* dpr00 */
339 write_dpr(accel, DE_DESTINATION,
340 ((dx << DE_DESTINATION_X_SHIFT) & DE_DESTINATION_X_MASK) |
341 (dy & DE_DESTINATION_Y_MASK)); /* dpr04 */
343 write_dpr(accel, DE_DIMENSION,
344 ((width << DE_DIMENSION_X_SHIFT) & DE_DIMENSION_X_MASK) |
345 (height & DE_DIMENSION_Y_ET_MASK)); /* dpr08 */
347 write_dpr(accel, DE_FOREGROUND, fColor);
348 write_dpr(accel, DE_BACKGROUND, bColor);
350 de_ctrl = (rop2 & DE_CONTROL_ROP_MASK) |
351 DE_CONTROL_ROP_SELECT | DE_CONTROL_COMMAND_HOST_WRITE |
352 DE_CONTROL_HOST | DE_CONTROL_STATUS;
354 write_dpr(accel, DE_CONTROL, de_ctrl | deGetTransparency(accel));
356 /* Write MONO data (line by line) to 2D Engine data port */
357 for (i = 0; i < height; i++) {
358 /* For each line, send the data in chunks of 4 bytes */
359 for (j = 0; j < (ul4BytesPerScan/4); j++)
360 write_dpPort(accel, *(unsigned int *)(pSrcbuf + (j * 4)));
363 memcpy(ajRemain, pSrcbuf+ul4BytesPerScan, ulBytesRemain);
364 write_dpPort(accel, *(unsigned int *)ajRemain);