]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/sm750fb/sm750_accel.c
staging: fbtft: put spaces around assignment operators
[karo-tx-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 #include "sm750_help.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 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 = 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);
49
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);
55
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);
58
59         /* disable clipping and transparent */
60         write_dpr(accel, DE_CLIP_TL, 0); /* dpr2c */
61         write_dpr(accel, DE_CLIP_BR, 0); /* dpr30 */
62
63         write_dpr(accel, DE_COLOR_COMPARE_MASK, 0); /* dpr24 */
64         write_dpr(accel, DE_COLOR_COMPARE, 0);
65
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);
69
70         clr = FIELD_CLEAR(DE_CONTROL, TRANSPARENCY)&
71                 FIELD_CLEAR(DE_CONTROL, TRANSPARENCY_MATCH)&
72                 FIELD_CLEAR(DE_CONTROL, TRANSPARENCY_SELECT);
73
74         /* dpr0c */
75         write_dpr(accel, DE_CONTROL, (read_dpr(accel, DE_CONTROL)&clr)|reg);
76 }
77
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 */
81
82 void hw_set2dformat(struct lynx_accel * accel, int fmt)
83 {
84         u32 reg;
85         
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);
90 }
91
92 int hw_fillrect(struct lynx_accel * accel,
93                                 u32 base, u32 pitch, u32 Bpp,
94                                 u32 x, u32 y, u32 width, u32 height,
95                                 u32 color, u32 rop)
96 {
97         u32 deCtrl;
98
99         if(accel->de_wait() != 0)
100         {
101                 /* int time wait and always busy,seems hardware
102                  * got something error */
103                 pr_debug("%s:De engine always bussy\n", __func__);
104                 return -1;
105         }
106
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 */
111
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 */
115
116         write_dpr(accel, DE_FOREGROUND, color); /* DPR14 */
117
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 */
122
123         write_dpr(accel, DE_DIMENSION,
124                         FIELD_VALUE(0, DE_DIMENSION, X, width)|
125                         FIELD_VALUE(0, DE_DIMENSION, Y_ET, height)); /* dpr8 */
126
127         deCtrl =
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 */
134
135         write_dpr(accel, DE_CONTROL, deCtrl);
136         return 0;
137 }
138
139 int hw_copyarea(
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 */
143 unsigned int sx,
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 */
148 unsigned int dx,
149 unsigned int dy,     /* Starting coordinate of destination surface */
150 unsigned int width,
151 unsigned int height, /* width and height of rectangle in pixel value */
152 unsigned int rop2)   /* ROP value */
153 {
154     unsigned int nDirection, de_ctrl;
155     int opSign;
156     nDirection = LEFT_TO_RIGHT;
157         /* Direction of ROP2 operation: 1 = Left to Right, (-1) = Right to Left */
158     opSign = 1;
159     de_ctrl = 0;
160
161     /* If source and destination are the same surface, need to check for overlay cases */
162     if (sBase == dBase && sPitch == dPitch)
163     {
164         /* Determine direction of operation */
165         if (sy < dy)
166         {
167             /* +----------+
168                |S         |
169                |   +----------+
170                |   |      |   |
171                |   |      |   |
172                +---|------+   |
173                    |         D|
174                    +----------+ */
175
176             nDirection = BOTTOM_TO_TOP;
177         }
178         else if (sy > dy)
179         {
180             /* +----------+
181                |D         |
182                |   +----------+
183                |   |      |   |
184                |   |      |   |
185                +---|------+   |
186                    |         S|
187                    +----------+ */
188
189             nDirection = TOP_TO_BOTTOM;
190         }
191         else
192         {
193             /* sy == dy */
194
195             if (sx <= dx)
196             {
197                 /* +------+---+------+
198                    |S     |   |     D|
199                    |      |   |      |
200                    |      |   |      |
201                    |      |   |      |
202                    +------+---+------+ */
203
204                 nDirection = RIGHT_TO_LEFT;
205             }
206             else
207             {
208                 /* sx > dx */
209
210                 /* +------+---+------+
211                    |D     |   |     S|
212                    |      |   |      |
213                    |      |   |      |
214                    |      |   |      |
215                    +------+---+------+ */
216
217                 nDirection = LEFT_TO_RIGHT;
218             }
219         }
220     }
221
222     if ((nDirection == BOTTOM_TO_TOP) || (nDirection == RIGHT_TO_LEFT))
223     {
224         sx += width - 1;
225         sy += height - 1;
226         dx += width - 1;
227         dy += height - 1;
228         opSign = (-1);
229     }
230
231     /* Note:
232        DE_FOREGROUND are DE_BACKGROUND are don't care.
233        DE_COLOR_COMPARE and DE_COLOR_COMPARE_MAKS are set by set deSetTransparency().
234     */
235
236     /* 2D Source Base.
237        It is an address offset (128 bit aligned) from the beginning of frame buffer.
238     */
239     write_dpr(accel, DE_WINDOW_SOURCE_BASE, sBase); /* dpr40 */
240
241     /* 2D Destination Base.
242        It is an address offset (128 bit aligned) from the beginning of frame buffer.
243     */
244     write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase); /* dpr44 */
245
246 #if 0
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.
250     */
251         if(Bpp == 3){
252                         sx *= 3;
253                         dx *= 3;
254                         width *= 3;
255                 write_dpr(accel, DE_PITCH,
256                                 FIELD_VALUE(0, DE_PITCH, DESTINATION, dPitch) |
257                                 FIELD_VALUE(0, DE_PITCH, SOURCE,      sPitch)); /* dpr10 */
258         }
259         else
260 #endif
261         {
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 */
265         }
266
267     /* Screen Window width in Pixels.
268        2D engine uses this value to calculate the linear address in frame buffer for a given point.
269     */
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 */
273
274         if (accel->de_wait() != 0){
275                 return -1;
276         }
277
278     {
279
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 */
291
292         de_ctrl =
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 */
301     }
302
303     return 0;
304 }
305
306 static unsigned int deGetTransparency(struct lynx_accel * accel)
307 {
308     unsigned int de_ctrl;
309
310     de_ctrl = read_dpr(accel, DE_CONTROL);
311
312     de_ctrl &=
313         FIELD_MASK(DE_CONTROL_TRANSPARENCY_MATCH) |
314         FIELD_MASK(DE_CONTROL_TRANSPARENCY_SELECT)|
315         FIELD_MASK(DE_CONTROL_TRANSPARENCY);
316
317     return de_ctrl;
318 }
319
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 */
327                  u32 dx,
328                  u32 dy,       /* Starting coordinate of destination surface */
329                  u32 width,
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 */
334 {
335     unsigned int ulBytesPerScan;
336     unsigned int ul4BytesPerScan;
337     unsigned int ulBytesRemain;
338     unsigned int de_ctrl = 0;
339     unsigned char ajRemain[4];
340     int i, j;
341
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;
346
347         if(accel->de_wait() != 0)
348     {
349         return -1;
350     }
351
352     /* 2D Source Base.
353        Use 0 for HOST Blt.
354     */
355     write_dpr(accel, DE_WINDOW_SOURCE_BASE, 0);
356
357     /* 2D Destination Base.
358        It is an address offset (128 bit aligned) from the beginning of frame buffer.
359     */
360     write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase);
361 #if 0
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.
365     */
366         if(bytePerPixel == 3 ){
367                 dx *= 3;
368                 width *= 3;
369                 startBit *= 3;
370                 write_dpr(accel, DE_PITCH,
371                                 FIELD_VALUE(0, DE_PITCH, DESTINATION, dPitch) |
372                                 FIELD_VALUE(0, DE_PITCH, SOURCE,      dPitch)); /* dpr10 */
373
374         }
375         else
376 #endif
377         {
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 */
381         }
382
383     /* Screen Window width in Pixels.
384        2D engine uses this value to calculate the linear address in frame buffer for a given point.
385     */
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)));
389
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 */
395
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 */
400
401     write_dpr(accel, DE_DIMENSION,
402         FIELD_VALUE(0, DE_DIMENSION, X,    width) |
403         FIELD_VALUE(0, DE_DIMENSION, Y_ET, height)); /* dpr08 */
404
405     write_dpr(accel, DE_FOREGROUND, fColor);
406     write_dpr(accel, DE_BACKGROUND, bColor);
407
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);
413
414         write_dpr(accel, DE_CONTROL, de_ctrl | deGetTransparency(accel));
415
416     /* Write MONO data (line by line) to 2D Engine data port */
417     for (i=0; i<height; i++)
418     {
419         /* For each line, send the data in chunks of 4 bytes */
420         for (j=0; j<(ul4BytesPerScan/4); j++)
421         {
422             write_dpPort(accel, *(unsigned int *)(pSrcbuf + (j * 4)));
423         }
424
425         if (ulBytesRemain)
426         {
427             memcpy(ajRemain, pSrcbuf+ul4BytesPerScan, ulBytesRemain);
428             write_dpPort(accel, *(unsigned int *)ajRemain);
429         }
430
431         pSrcbuf += srcDelta;
432     }
433
434     return 0;
435 }
436