Lynx framebuffers multidomain implementation.
[linux/elbrus.git] / drivers / video / lynxfb / lynx_cursor.c
blob92d2b149c995825153e78cd515b495952e86fff7
1 /*******************************************************************
2 *Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
3 *Permission is hereby granted, free of charge, to any person obtaining a copy
4 *of this software and associated documentation files (the "Software"), to deal
5 *in the Software without restriction, including without limitation the rights to
6 *use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 *of the Software, and to permit persons to whom the Software is furnished to
8 *do so, subject to the following conditions:
10 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
12 *OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13 *NONINFRINGEMENT. IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
14 *HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
15 *WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
16 *FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
17 *OTHER DEALINGS IN THE SOFTWARE.
18 *******************************************************************/
19 #include <linux/version.h>
20 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
21 #include <linux/config.h>
22 #endif
23 #include <linux/module.h>
24 #include <linux/kernel.h>
25 #include <linux/errno.h>
26 #include <linux/string.h>
27 #include <linux/mm.h>
28 #include <linux/slab.h>
29 #include <linux/delay.h>
30 #include <linux/fb.h>
31 #include <linux/ioport.h>
32 #include <linux/init.h>
33 #include <linux/pci.h>
34 #include <linux/vmalloc.h>
35 #include <linux/pagemap.h>
36 #include <linux/console.h>
37 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
38 /* no below two header files in 2.6.9 */
39 #include <linux/platform_device.h>
40 #include <linux/screen_info.h>
41 #else
42 /* nothing by far */
43 #endif
45 #include "lynx_drv.h"
46 #include "lynx_help.h"
47 #include "lynx_cursor.h"
49 #define PEEK32(addr) \
50 readl(cursor->mmio + (addr))
52 #define POKE32(addr, data) \
53 writel((data), cursor->mmio + (addr))
55 /* cursor control for voyager and 718/750*/
57 #define HWC_ADDRESS 0x0
58 #define HWC_ADDRESS_ENABLE_LSB 31
59 #define HWC_ADDRESS_EXT_LSB 27
60 #define HWC_ADDRESS_CS 26
61 #define HWC_ADDRESS_ADDRESS_LSB 0
62 #define HWC_LOCATION 0x4
63 #define HWC_LOCATION_TOP_LSB 27
64 #define HWC_LOCATION_Y_LSB 16
65 #define HWC_LOCATION_LEFT 11
66 #define HWC_LOCATION_X_LSB 0
67 #define HWC_COLOR_12 0x8
68 #define HWC_COLOR_3 0xC
70 /* hw_cursor_xxx works for voyager, 718 and 750 */
71 void hw_cursor_enable(struct lynx_cursor *cursor)
73 u32 reg;
74 reg = ((cursor->offset << HWC_ADDRESS_ADDRESS_LSB) &
75 (~(1 << HWC_ADDRESS_EXT_LSB))) | (1 << HWC_ADDRESS_ENABLE_LSB);
76 POKE32(HWC_ADDRESS, reg);
79 void hw_cursor_disable(struct lynx_cursor *cursor)
81 POKE32(HWC_ADDRESS, 0);
84 void hw_cursor_setSize(struct lynx_cursor *cursor, int w, int h)
86 cursor->w = w;
87 cursor->h = h;
90 void hw_cursor_setPos(struct lynx_cursor *cursor, int x, int y)
92 u32 reg;
93 reg = (y << HWC_LOCATION_Y_LSB) | (x << HWC_LOCATION_X_LSB);
94 POKE32(HWC_LOCATION, reg);
97 void hw_cursor_setColor(struct lynx_cursor *cursor, u32 fg, u32 bg)
99 POKE32(HWC_COLOR_12, (fg << 16) | (bg & 0xffff));
100 POKE32(HWC_COLOR_3, 0xffe0);
103 void hw_cursor_setData(struct lynx_cursor *cursor,
104 u16 rop, const u8 * pcol, const u8 * pmsk)
106 int i, j, count, pitch, offset;
107 u8 color, mask, opr;
108 u16 data;
109 u16 *pbuffer, *pstart;
111 /* in byte */
112 pitch = cursor->w >> 3;
114 /* in byte */
115 count = pitch * cursor->h;
117 /* in ushort */
118 offset = cursor->maxW * 2 / 8 / 2;
120 data = 0;
121 pstart = (u16 *) cursor->vstart;
122 pbuffer = pstart;
125 if (odd &1) {
126 hw_cursor_setData2(cursor, rop, pcol, pmsk);
128 odd++;
129 if (odd > 0xfffffff0)
130 odd=0;
133 for (i = 0; i < count; i++) {
135 color = *pcol++;
136 mask = *pmsk++;
137 data = 0;
139 /* either method below works well,
140 * but method 2 shows no lag
141 * and method 1 seems a bit wrong*/
143 for (j = 0; j < 8; j++) {
144 if (mask & (0x80 >> j)) {
145 if (rop == ROP_XOR)
146 opr = mask ^ color;
147 else
148 opr = mask & color;
150 /* 2 stands for forecolor and 1 for backcolor */
151 data |=
152 ((opr & (0x80 >> j)) ? 2 : 1) << (j *
157 writew(data, pbuffer);
159 /* assume pitch is 1, 2, 4, 8, ... */
160 if ((i + 1) % pitch == 0) {
161 /* need a return */
162 pstart += offset;
163 pbuffer = pstart;
164 } else {
165 pbuffer++;
173 void hw_cursor_setData2(struct lynx_cursor *cursor,
174 u16 rop, const u8 * pcol, const u8 * pmsk)
176 int i, j, count, pitch, offset;
177 u8 color, mask;
178 u16 data;
179 u16 *pbuffer, *pstart;
181 /* in byte */
182 pitch = cursor->w >> 3;
184 /* in byte */
185 count = pitch * cursor->h;
187 /* in ushort */
188 offset = cursor->maxW * 2 / 8 / 2;
190 data = 0;
191 pstart = (u16 *) cursor->vstart;
192 pbuffer = pstart;
194 for (i = 0; i < count; i++) {
196 color = *pcol++;
197 mask = *pmsk++;
198 data = 0;
200 /* either method below works well, but method 2 shows no lag */
202 for (j = 0; j < 8; j++) {
203 if (mask & (1 << j))
204 data |=
205 ((color & (1 << j)) ? 1 : 2) << (j *
209 writew(data, pbuffer);
211 /* assume pitch is 1, 2, 4, 8, ... */
212 if (!(i & (pitch - 1))) {
215 /* need a return */
216 pstart += offset;
217 pbuffer = pstart;
218 } else {
219 pbuffer++;