Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / 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 convertion.
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 //              inf_msg("*** ImageBlit return -1 ***\n");
350         return -1;
351     }
352
353     /* 2D Source Base.
354        Use 0 for HOST Blt.
355     */
356     write_dpr(accel,DE_WINDOW_SOURCE_BASE, 0);
357
358     /* 2D Destination Base.
359        It is an address offset (128 bit aligned) from the beginning of frame buffer.
360     */
361     write_dpr(accel,DE_WINDOW_DESTINATION_BASE, dBase);
362 #if 0
363     /* Program pitch (distance between the 1st points of two adjacent lines).
364        Note that input pitch is BYTE value, but the 2D Pitch register uses
365        pixel values. Need Byte to pixel convertion.
366     */
367         if(bytePerPixel == 3 ){
368                 dx *= 3;
369                 width *= 3;
370                 startBit *= 3;
371                 write_dpr(accel,DE_PITCH,
372                                 FIELD_VALUE(0, DE_PITCH, DESTINATION, dPitch) |
373                                 FIELD_VALUE(0, DE_PITCH, SOURCE,      dPitch));//dpr10
374
375         }
376         else
377 #endif
378         {
379                 write_dpr(accel,DE_PITCH,
380                                 FIELD_VALUE(0, DE_PITCH, DESTINATION, dPitch/bytePerPixel) |
381                                 FIELD_VALUE(0, DE_PITCH, SOURCE,      dPitch/bytePerPixel));//dpr10
382         }
383
384     /* Screen Window width in Pixels.
385        2D engine uses this value to calculate the linear address in frame buffer for a given point.
386     */
387     write_dpr(accel,DE_WINDOW_WIDTH,
388         FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, (dPitch/bytePerPixel)) |
389         FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE,      (dPitch/bytePerPixel)));
390
391     /* Note: For 2D Source in Host Write, only X_K1_MONO field is needed, and Y_K2 field is not used.
392              For mono bitmap, use startBit for X_K1. */
393     write_dpr(accel,DE_SOURCE,
394         FIELD_SET  (0, DE_SOURCE, WRAP, DISABLE)       |
395         FIELD_VALUE(0, DE_SOURCE, X_K1_MONO, startBit));//dpr00
396
397     write_dpr(accel,DE_DESTINATION,
398         FIELD_SET  (0, DE_DESTINATION, WRAP, DISABLE) |
399         FIELD_VALUE(0, DE_DESTINATION, X,    dx)    |
400         FIELD_VALUE(0, DE_DESTINATION, Y,    dy));//dpr04
401
402     write_dpr(accel,DE_DIMENSION,
403         FIELD_VALUE(0, DE_DIMENSION, X,    width) |
404         FIELD_VALUE(0, DE_DIMENSION, Y_ET, height));//dpr08
405
406     write_dpr(accel,DE_FOREGROUND, fColor);
407     write_dpr(accel,DE_BACKGROUND, bColor);
408
409         de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, rop2)         |
410                 FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2)    |
411                 FIELD_SET(0, DE_CONTROL, COMMAND, HOST_WRITE) |
412                 FIELD_SET(0, DE_CONTROL, HOST, MONO)          |
413                 FIELD_SET(0, DE_CONTROL, STATUS, START);
414
415         write_dpr(accel,DE_CONTROL, de_ctrl | deGetTransparency(accel));
416
417     /* Write MONO data (line by line) to 2D Engine data port */
418     for (i=0; i<height; i++)
419     {
420         /* For each line, send the data in chunks of 4 bytes */
421         for (j=0; j<(ul4BytesPerScan/4); j++)
422         {
423             write_dpPort(accel, *(unsigned int *)(pSrcbuf + (j * 4)));
424         }
425
426         if (ulBytesRemain)
427         {
428             memcpy(ajRemain, pSrcbuf+ul4BytesPerScan, ulBytesRemain);
429             write_dpPort(accel, *(unsigned int *)ajRemain);
430         }
431
432         pSrcbuf += srcDelta;
433     }
434
435     return 0;
436 }
437