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