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>
23 #include <linux/module.h>
24 #include <linux/kernel.h>
25 #include <linux/errno.h>
26 #include <linux/string.h>
28 #include <linux/slab.h>
29 #include <linux/delay.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>
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
)
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
)
90 void hw_cursor_setPos(struct lynx_cursor
*cursor
, int x
, int y
)
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
;
109 u16
*pbuffer
, *pstart
;
112 pitch
= cursor
->w
>> 3;
115 count
= pitch
* cursor
->h
;
118 offset
= cursor
->maxW
* 2 / 8 / 2;
121 pstart
= (u16
*) cursor
->vstart
;
126 hw_cursor_setData2(cursor, rop, pcol, pmsk);
129 if (odd > 0xfffffff0)
133 for (i
= 0; i
< count
; i
++) {
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
)) {
150 /* 2 stands for forecolor and 1 for backcolor */
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) {
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
;
179 u16
*pbuffer
, *pstart
;
182 pitch
= cursor
->w
>> 3;
185 count
= pitch
* cursor
->h
;
188 offset
= cursor
->maxW
* 2 / 8 / 2;
191 pstart
= (u16
*) cursor
->vstart
;
194 for (i
= 0; i
< count
; i
++) {
200 /* either method below works well, but method 2 shows no lag */
202 for (j
= 0; j
< 8; j
++) {
205 ((color
& (1 << j
)) ? 1 : 2) << (j
*
209 writew(data
, pbuffer
);
211 /* assume pitch is 1, 2, 4, 8, ... */
212 if (!(i
& (pitch
- 1))) {