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"
write_dpr(struct lynx_accel * accel,int offset,u32 regValue)21 static inline void write_dpr(struct lynx_accel * accel,int offset,u32 regValue)
22 {
23 	writel(regValue,accel->dprBase + offset);
24 }
25 
read_dpr(struct lynx_accel * accel,int offset)26 static inline u32 read_dpr(struct lynx_accel * accel,int offset)
27 {
28 	return readl(accel->dprBase + offset);
29 }
30 
write_dpPort(struct lynx_accel * accel,u32 data)31 static inline void write_dpPort(struct lynx_accel * accel,u32 data)
32 {
33 	writel(data,accel->dpPortBase);
34 }
35 
hw_de_init(struct lynx_accel * accel)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 
hw_set2dformat(struct lynx_accel * accel,int fmt)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 
hw_fillrect(struct lynx_accel * accel,u32 base,u32 pitch,u32 Bpp,u32 x,u32 y,u32 width,u32 height,u32 color,u32 rop)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 
hw_copyarea(struct lynx_accel * accel,unsigned int sBase,unsigned int sPitch,unsigned int sx,unsigned int sy,unsigned int dBase,unsigned int dPitch,unsigned int Bpp,unsigned int dx,unsigned int dy,unsigned int width,unsigned int height,unsigned int rop2)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 
deGetTransparency(struct lynx_accel * accel)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 
hw_imageblit(struct lynx_accel * accel,const char * pSrcbuf,u32 srcDelta,u32 startBit,u32 dBase,u32 dPitch,u32 bytePerPixel,u32 dx,u32 dy,u32 width,u32 height,u32 fColor,u32 bColor,u32 rop2)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 
438