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 58 void sm750_hw_cursor_disable(struct lynx_cursor *cursor) 59 { 60 poke32(HWC_ADDRESS, 0); 61 } 62 63 void sm750_hw_cursor_setSize(struct lynx_cursor *cursor, 64 int w, int h) 65 { 66 cursor->w = w; 67 cursor->h = h; 68 } 69 70 void sm750_hw_cursor_setPos(struct lynx_cursor *cursor, 71 int x, int y) 72 { 73 u32 reg; 74 75 reg = ((y << HWC_LOCATION_Y_SHIFT) & HWC_LOCATION_Y_MASK) | 76 (x & HWC_LOCATION_X_MASK); 77 poke32(HWC_LOCATION, reg); 78 } 79 80 void sm750_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 sm750_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 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