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