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 BIT(31) 32 #define HWC_ADDRESS_EXT BIT(27) 33 #define HWC_ADDRESS_CS BIT(26) 34 #define HWC_ADDRESS_ADDRESS_MASK 0x3ffffff 35 36 #define HWC_LOCATION 0x4 37 #define HWC_LOCATION_TOP BIT(27) 38 #define HWC_LOCATION_Y_SHIFT 16 39 #define HWC_LOCATION_Y_MASK (0x7ff << 16) 40 #define HWC_LOCATION_LEFT BIT(11) 41 #define HWC_LOCATION_X_MASK 0x7ff 42 43 #define HWC_COLOR_12 0x8 44 #define HWC_COLOR_12_2_RGB565_SHIFT 16 45 #define HWC_COLOR_12_2_RGB565_MASK (0xffff << 16) 46 #define HWC_COLOR_12_1_RGB565_MASK 0xffff 47 48 #define HWC_COLOR_3 0xC 49 #define HWC_COLOR_3_RGB565_MASK 0xffff 50 51 52 /* hw_cursor_xxx works for voyager,718 and 750 */ 53 void hw_cursor_enable(struct lynx_cursor *cursor) 54 { 55 u32 reg; 56 57 reg = (cursor->offset & HWC_ADDRESS_ADDRESS_MASK) | HWC_ADDRESS_ENABLE; 58 POKE32(HWC_ADDRESS, reg); 59 } 60 void hw_cursor_disable(struct lynx_cursor *cursor) 61 { 62 POKE32(HWC_ADDRESS, 0); 63 } 64 65 void hw_cursor_setSize(struct lynx_cursor *cursor, 66 int w, int h) 67 { 68 cursor->w = w; 69 cursor->h = h; 70 } 71 void hw_cursor_setPos(struct lynx_cursor *cursor, 72 int x, int y) 73 { 74 u32 reg; 75 76 reg = (((y << HWC_LOCATION_Y_SHIFT) & HWC_LOCATION_Y_MASK) | 77 (x & HWC_LOCATION_X_MASK)); 78 POKE32(HWC_LOCATION, reg); 79 } 80 void hw_cursor_setColor(struct lynx_cursor *cursor, 81 u32 fg, u32 bg) 82 { 83 u32 reg = (fg << HWC_COLOR_12_2_RGB565_SHIFT) & 84 HWC_COLOR_12_2_RGB565_MASK; 85 86 POKE32(HWC_COLOR_12, reg | (bg & HWC_COLOR_12_1_RGB565_MASK)); 87 POKE32(HWC_COLOR_3, 0xffe0); 88 } 89 90 void hw_cursor_setData(struct lynx_cursor *cursor, 91 u16 rop, const u8 *pcol, const u8 *pmsk) 92 { 93 int i, j, count, pitch, offset; 94 u8 color, mask, opr; 95 u16 data; 96 void __iomem *pbuffer, *pstart; 97 98 /* in byte*/ 99 pitch = cursor->w >> 3; 100 101 /* in byte */ 102 count = pitch * cursor->h; 103 104 /* in byte */ 105 offset = cursor->maxW * 2 / 8; 106 107 data = 0; 108 pstart = cursor->vstart; 109 pbuffer = pstart; 110 111 for (i = 0; i < count; i++) { 112 color = *pcol++; 113 mask = *pmsk++; 114 data = 0; 115 116 for (j = 0; j < 8; j++) { 117 if (mask & (0x80>>j)) { 118 if (rop == ROP_XOR) 119 opr = mask ^ color; 120 else 121 opr = mask & color; 122 123 /* 2 stands for forecolor and 1 for backcolor */ 124 data |= ((opr & (0x80>>j))?2:1)<<(j*2); 125 } 126 } 127 iowrite16(data, pbuffer); 128 129 /* assume pitch is 1,2,4,8,...*/ 130 if ((i + 1) % pitch == 0) { 131 /* need a return */ 132 pstart += offset; 133 pbuffer = pstart; 134 } else { 135 pbuffer += sizeof(u16); 136 } 137 138 } 139 140 141 } 142 143 144 void hw_cursor_setData2(struct lynx_cursor *cursor, 145 u16 rop, const u8 *pcol, const u8 *pmsk) 146 { 147 int i, j, count, pitch, offset; 148 u8 color, mask; 149 u16 data; 150 void __iomem *pbuffer, *pstart; 151 152 /* in byte*/ 153 pitch = cursor->w >> 3; 154 155 /* in byte */ 156 count = pitch * cursor->h; 157 158 /* in byte */ 159 offset = cursor->maxW * 2 / 8; 160 161 data = 0; 162 pstart = cursor->vstart; 163 pbuffer = pstart; 164 165 for (i = 0; i < count; i++) { 166 color = *pcol++; 167 mask = *pmsk++; 168 data = 0; 169 170 for (j = 0; j < 8; j++) { 171 if (mask & (1<<j)) 172 data |= ((color & (1<<j))?1:2)<<(j*2); 173 } 174 iowrite16(data, pbuffer); 175 176 /* assume pitch is 1,2,4,8,...*/ 177 if (!(i&(pitch-1))) { 178 /* need a return */ 179 pstart += offset; 180 pbuffer = pstart; 181 } else { 182 pbuffer += sizeof(u16); 183 } 184 185 } 186 } 187