]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/staging/sm750fb/sm750_accel.c
Merge tag 'armsoc-multiplatform' of git://git.kernel.org/pub/scm/linux/kernel/git...
[mirror_ubuntu-artful-kernel.git] / drivers / staging / sm750fb / sm750_accel.c
CommitLineData
81dee67e
SM
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"
21static inline void write_dpr(struct lynx_accel * accel,int offset,u32 regValue)
22{
23 writel(regValue,accel->dprBase + offset);
24}
25
26static inline u32 read_dpr(struct lynx_accel * accel,int offset)
27{
28 return readl(accel->dprBase + offset);
29}
30
31static inline void write_dpPort(struct lynx_accel * accel,u32 data)
32{
33 writel(data,accel->dpPortBase);
34}
35
36void 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
82void 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
81dee67e
SM
92int 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
139int hw_copyarea(
140struct lynx_accel * accel,
141unsigned int sBase, /* Address of source: offset in frame buffer */
142unsigned int sPitch, /* Pitch value of source surface in BYTE */
143unsigned int sx,
144unsigned int sy, /* Starting coordinate of source surface */
145unsigned int dBase, /* Address of destination: offset in frame buffer */
146unsigned int dPitch, /* Pitch value of destination surface in BYTE */
147unsigned int Bpp, /* Color depth of destination surface */
148unsigned int dx,
149unsigned int dy, /* Starting coordinate of destination surface */
150unsigned int width,
151unsigned int height, /* width and height of rectangle in pixel value */
152unsigned 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
306static 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
7c6f3fdc
GKH
320int 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 */
81dee67e
SM
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