Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / staging / sm750fb / sm750_cursor.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_help.h"
20 #include "sm750_cursor.h"
21
22
23 #define PEEK32(addr) \
24 readl(cursor->mmio + (addr))
25
26 #define POKE32(addr,data) \
27 writel((data),cursor->mmio + (addr))
28
29 /* cursor control for voyager and 718/750*/
30 #define HWC_ADDRESS                         0x0
31 #define HWC_ADDRESS_ENABLE                  31:31
32 #define HWC_ADDRESS_ENABLE_DISABLE          0
33 #define HWC_ADDRESS_ENABLE_ENABLE           1
34 #define HWC_ADDRESS_EXT                     27:27
35 #define HWC_ADDRESS_EXT_LOCAL               0
36 #define HWC_ADDRESS_EXT_EXTERNAL            1
37 #define HWC_ADDRESS_CS                      26:26
38 #define HWC_ADDRESS_CS_0                    0
39 #define HWC_ADDRESS_CS_1                    1
40 #define HWC_ADDRESS_ADDRESS                 25:0
41
42 #define HWC_LOCATION                        0x4
43 #define HWC_LOCATION_TOP                    27:27
44 #define HWC_LOCATION_TOP_INSIDE             0
45 #define HWC_LOCATION_TOP_OUTSIDE            1
46 #define HWC_LOCATION_Y                      26:16
47 #define HWC_LOCATION_LEFT                   11:11
48 #define HWC_LOCATION_LEFT_INSIDE            0
49 #define HWC_LOCATION_LEFT_OUTSIDE           1
50 #define HWC_LOCATION_X                      10:0
51
52 #define HWC_COLOR_12                        0x8
53 #define HWC_COLOR_12_2_RGB565               31:16
54 #define HWC_COLOR_12_1_RGB565               15:0
55
56 #define HWC_COLOR_3                         0xC
57 #define HWC_COLOR_3_RGB565                  15:0
58
59
60 /* hw_cursor_xxx works for voyager,718 and 750 */
61 void hw_cursor_enable(struct lynx_cursor * cursor)
62 {
63         u32 reg;
64         reg = FIELD_VALUE(0,HWC_ADDRESS,ADDRESS,cursor->offset)|
65                         FIELD_SET(0,HWC_ADDRESS,EXT,LOCAL)|
66                         FIELD_SET(0,HWC_ADDRESS,ENABLE,ENABLE);
67         POKE32(HWC_ADDRESS,reg);
68 }
69 void hw_cursor_disable(struct lynx_cursor * cursor)
70 {
71         POKE32(HWC_ADDRESS,0);
72 }
73
74 void hw_cursor_setSize(struct lynx_cursor * cursor,
75                                                 int w,int h)
76 {
77         cursor->w = w;
78         cursor->h = h;
79 }
80 void hw_cursor_setPos(struct lynx_cursor * cursor,
81                                                 int x,int y)
82 {
83         u32 reg;
84         reg = FIELD_VALUE(0,HWC_LOCATION,Y,y)|
85                         FIELD_VALUE(0,HWC_LOCATION,X,x);
86         POKE32(HWC_LOCATION,reg);
87 }
88 void hw_cursor_setColor(struct lynx_cursor * cursor,
89                                                 u32 fg,u32 bg)
90 {
91         POKE32(HWC_COLOR_12,(fg<<16)|(bg&0xffff));
92         POKE32(HWC_COLOR_3,0xffe0);
93 }
94
95 void hw_cursor_setData(struct lynx_cursor * cursor,
96                         u16 rop,const u8* pcol,const u8* pmsk)
97 {
98         int i,j,count,pitch,offset;
99         u8 color,mask,opr;
100         u16 data;
101         void __iomem *pbuffer, *pstart;
102
103         /*  in byte*/
104         pitch = cursor->w >> 3;
105
106         /* in byte      */
107         count = pitch * cursor->h;
108
109         /* in byte */
110         offset = cursor->maxW * 2 / 8;
111
112         data = 0;
113         pstart = cursor->vstart;
114         pbuffer = pstart;
115
116 /*
117         if(odd &1){
118                 hw_cursor_setData2(cursor,rop,pcol,pmsk);
119         }
120         odd++;
121         if(odd > 0xfffffff0)
122                 odd=0;
123 */
124
125         for(i=0;i<count;i++)
126         {
127                 color = *pcol++;
128                 mask = *pmsk++;
129                 data = 0;
130
131                 /* either method below works well,
132                  * but method 2 shows no lag
133                  * and method 1 seems a bit wrong*/
134 #if 0
135                 if(rop == ROP_XOR)
136                         opr = mask ^ color;
137                 else
138                         opr = mask & color;
139
140                 for(j=0;j<8;j++)
141                 {
142
143                         if(opr & (0x80 >> j))
144                         {       //use fg color,id = 2
145                                 data |= 2 << (j*2);
146                         }else{
147                                 //use bg color,id = 1
148                                 data |= 1 << (j*2);
149                         }
150                 }
151 #else
152                 for(j=0;j<8;j++){
153                         if(mask & (0x80>>j)){
154                                 if(rop == ROP_XOR)
155                                         opr = mask ^ color;
156                                 else
157                                         opr = mask & color;
158
159                                 /* 2 stands for forecolor and 1 for backcolor */
160                                 data |= ((opr & (0x80>>j))?2:1)<<(j*2);
161                         }
162                 }
163 #endif
164                 iowrite16(data, pbuffer);
165
166                 /* assume pitch is 1,2,4,8,...*/
167 #if 0
168                 if(!((i+1)&(pitch-1)))   /* below line equal to is line */
169 #else
170                 if((i+1) % pitch == 0)
171 #endif
172                 {
173                         /* need a return */
174                         pstart += offset;
175                         pbuffer = pstart;
176                 }else{
177                         pbuffer += sizeof(u16);
178                 }
179
180         }
181
182
183 }
184
185
186 void hw_cursor_setData2(struct lynx_cursor * cursor,
187                         u16 rop,const u8* pcol,const u8* pmsk)
188 {
189         int i,j,count,pitch,offset;
190         u8 color, mask;
191         u16 data;
192         void __iomem *pbuffer, *pstart;
193
194         /*  in byte*/
195         pitch = cursor->w >> 3;
196
197         /* in byte      */
198         count = pitch * cursor->h;
199
200         /* in byte */
201         offset = cursor->maxW * 2 / 8;
202
203         data = 0;
204         pstart = cursor->vstart;
205         pbuffer = pstart;
206
207         for(i=0;i<count;i++)
208         {
209                 color = *pcol++;
210                 mask = *pmsk++;
211                 data = 0;
212
213                 /* either method below works well, but method 2 shows no lag */
214 #if 0
215                 if(rop == ROP_XOR)
216                         opr = mask ^ color;
217                 else
218                         opr = mask & color;
219
220                 for(j=0;j<8;j++)
221                 {
222
223                         if(opr & (0x80 >> j))
224                         {       //use fg color,id = 2
225                                 data |= 2 << (j*2);
226                         }else{
227                                 //use bg color,id = 1
228                                 data |= 1 << (j*2);
229                         }
230                 }
231 #else
232                 for(j=0;j<8;j++){
233                         if(mask & (1<<j))
234                                 data |= ((color & (1<<j))?1:2)<<(j*2);
235                 }
236 #endif
237                 iowrite16(data, pbuffer);
238
239                 /* assume pitch is 1,2,4,8,...*/
240                 if(!(i&(pitch-1)))
241                 //if((i+1) % pitch == 0)
242                 {
243                         /* need a return */
244                         pstart += offset;
245                         pbuffer = pstart;
246                 }else{
247                         pbuffer += sizeof(u16);
248                 }
249
250         }
251 }