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 
65 	reg = FIELD_VALUE(0, HWC_ADDRESS, ADDRESS, cursor->offset)|
66 			FIELD_SET(0, HWC_ADDRESS, EXT, LOCAL)|
67 			FIELD_SET(0, HWC_ADDRESS, ENABLE, ENABLE);
68 	POKE32(HWC_ADDRESS, reg);
69 }
hw_cursor_disable(struct lynx_cursor * cursor)70 void hw_cursor_disable(struct lynx_cursor *cursor)
71 {
72 	POKE32(HWC_ADDRESS, 0);
73 }
74 
hw_cursor_setSize(struct lynx_cursor * cursor,int w,int h)75 void hw_cursor_setSize(struct lynx_cursor *cursor,
76 						int w, int h)
77 {
78 	cursor->w = w;
79 	cursor->h = h;
80 }
hw_cursor_setPos(struct lynx_cursor * cursor,int x,int y)81 void hw_cursor_setPos(struct lynx_cursor *cursor,
82 						int x, int y)
83 {
84 	u32 reg;
85 
86 	reg = FIELD_VALUE(0, HWC_LOCATION, Y, y)|
87 			FIELD_VALUE(0, HWC_LOCATION, X, x);
88 	POKE32(HWC_LOCATION, reg);
89 }
hw_cursor_setColor(struct lynx_cursor * cursor,u32 fg,u32 bg)90 void hw_cursor_setColor(struct lynx_cursor *cursor,
91 						u32 fg, u32 bg)
92 {
93 	POKE32(HWC_COLOR_12, (fg<<16)|(bg&0xffff));
94 	POKE32(HWC_COLOR_3, 0xffe0);
95 }
96 
hw_cursor_setData(struct lynx_cursor * cursor,u16 rop,const u8 * pcol,const u8 * pmsk)97 void hw_cursor_setData(struct lynx_cursor *cursor,
98 			u16 rop, const u8 *pcol, const u8 *pmsk)
99 {
100 	int i, j, count, pitch, offset;
101 	u8 color, mask, opr;
102 	u16 data;
103 	void __iomem *pbuffer, *pstart;
104 
105 	/*  in byte*/
106 	pitch = cursor->w >> 3;
107 
108 	/* in byte	*/
109 	count = pitch * cursor->h;
110 
111 	/* in byte */
112 	offset = cursor->maxW * 2 / 8;
113 
114 	data = 0;
115 	pstart = cursor->vstart;
116 	pbuffer = pstart;
117 
118 /*
119 	if(odd &1){
120 		hw_cursor_setData2(cursor,rop,pcol,pmsk);
121 	}
122 	odd++;
123 	if(odd > 0xfffffff0)
124 		odd=0;
125 */
126 
127 	for (i = 0; i < count; i++) {
128 		color = *pcol++;
129 		mask = *pmsk++;
130 		data = 0;
131 
132 		for (j = 0; j < 8; j++) {
133 			if (mask & (0x80>>j)) {
134 				if (rop == ROP_XOR)
135 					opr = mask ^ color;
136 				else
137 					opr = mask & color;
138 
139 				/* 2 stands for forecolor and 1 for backcolor */
140 				data |= ((opr & (0x80>>j))?2:1)<<(j*2);
141 			}
142 		}
143 		iowrite16(data, pbuffer);
144 
145 		/* assume pitch is 1,2,4,8,...*/
146 		if ((i+1) % pitch == 0)
147 		{
148 			/* need a return */
149 			pstart += offset;
150 			pbuffer = pstart;
151 		} else {
152 			pbuffer += sizeof(u16);
153 		}
154 
155 	}
156 
157 
158 }
159 
160 
hw_cursor_setData2(struct lynx_cursor * cursor,u16 rop,const u8 * pcol,const u8 * pmsk)161 void hw_cursor_setData2(struct lynx_cursor *cursor,
162 			u16 rop, const u8 *pcol, const u8 *pmsk)
163 {
164 	int i, j, count, pitch, offset;
165 	u8 color, mask;
166 	u16 data;
167 	void __iomem *pbuffer, *pstart;
168 
169 	/*  in byte*/
170 	pitch = cursor->w >> 3;
171 
172 	/* in byte	*/
173 	count = pitch * cursor->h;
174 
175 	/* in byte */
176 	offset = cursor->maxW * 2 / 8;
177 
178 	data = 0;
179 	pstart = cursor->vstart;
180 	pbuffer = pstart;
181 
182 	for (i = 0; i < count; i++) {
183 		color = *pcol++;
184 		mask = *pmsk++;
185 		data = 0;
186 
187 		for (j = 0; j < 8; j++) {
188 			if (mask & (1<<j))
189 				data |= ((color & (1<<j))?1:2)<<(j*2);
190 		}
191 		iowrite16(data, pbuffer);
192 
193 		/* assume pitch is 1,2,4,8,...*/
194 		if (!(i&(pitch-1))) {
195 			/* need a return */
196 			pstart += offset;
197 			pbuffer = pstart;
198 		} else {
199 			pbuffer += sizeof(u16);
200 		}
201 
202 	}
203 }
204