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 */
hw_cursor_enable(struct lynx_cursor * cursor)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 }
hw_cursor_disable(struct lynx_cursor * cursor)69 void hw_cursor_disable(struct lynx_cursor * cursor)
70 {
71 	POKE32(HWC_ADDRESS,0);
72 }
73 
hw_cursor_setSize(struct lynx_cursor * cursor,int w,int h)74 void hw_cursor_setSize(struct lynx_cursor * cursor,
75 						int w,int h)
76 {
77 	cursor->w = w;
78 	cursor->h = h;
79 }
hw_cursor_setPos(struct lynx_cursor * cursor,int x,int y)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 }
hw_cursor_setColor(struct lynx_cursor * cursor,u32 fg,u32 bg)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 
hw_cursor_setData(struct lynx_cursor * cursor,u16 rop,const u8 * pcol,const u8 * pmsk)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 
hw_cursor_setData2(struct lynx_cursor * cursor,u16 rop,const u8 * pcol,const u8 * pmsk)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 }
252