]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/vgaigfx.c
kernel: cleanup the software mouse cursor mess
[plan9front.git] / sys / src / 9 / pc / vgaigfx.c
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7 #include "../port/error.h"
8
9 #define Image   IMAGE
10 #include <draw.h>
11 #include <memdraw.h>
12 #include <cursor.h>
13 #include "screen.h"
14
15 static uintptr
16 igfxcuralloc(Pcidev *pci, void *mmio, int apsize)
17 {
18         int n;
19         u32int pa, *buf, *p, *e;
20
21         buf = mallocalign(64*64*4, BY2PG, 0, 0);
22         if(buf == nil){
23                 print("igfx: no memory for cursor image\n");
24                 return 0;
25         }
26         n = (apsize > 128*MB ? 128*1024 : apsize/1024) / 4 - 4;
27         p = (u32int*)((uchar*)mmio + pci->mem[0].size/2) + n;
28         *(u32int*)((uchar*)mmio + 0x2170) = 0;  /* flush write buffers */
29         for(e=p+4, pa=PADDR(buf); p<e; p++, pa+=1<<12)
30                 *p = pa | 1;
31         *(u32int*)((uchar*)mmio + 0x2170) = 0;  /* flush write buffers */
32         return (uintptr)n << 12;
33 }
34
35 static void
36 igfxenable(VGAscr* scr)
37 {
38         Pcidev *p;
39         
40         if(scr->mmio != nil)
41                 return;
42         p = scr->pci;
43         if(p == nil)
44                 return;
45         scr->mmio = vmap(p->mem[0].bar&~0x0F, p->mem[0].size);
46         if(scr->mmio == nil)
47                 return;
48         addvgaseg("igfxmmio", p->mem[0].bar&~0x0F, p->mem[0].size);
49         if(scr->paddr == 0)
50                 vgalinearpci(scr);
51         if(scr->apsize){
52                 addvgaseg("igfxscreen", scr->paddr, scr->apsize);
53                 scr->storage = igfxcuralloc(p, scr->mmio, scr->apsize);
54         }
55         scr->softscreen = 1;
56 }
57
58 static void
59 igfxblank(VGAscr *scr, int blank)
60 {
61         u32int off;
62
63         switch(scr->pci->did){
64         default:
65                 return;
66
67         case 0x2a02:    /* GM965 */
68         case 0x2a42:    /* GM45 */
69         case 0x2592:    /* GM915 */
70                 off = 0x61204;
71                 break;
72
73         case 0x0126:    /* SNB */
74         case 0x0166:    /* IVB */
75                 off = 0xC7204;
76                 break;
77         }
78
79         /* toggle PP_CONTROL backlight & power state */
80         if(blank)
81                 scr->mmio[off/4] &= ~0x5;
82         else
83                 scr->mmio[off/4] |= 0x5;
84 }
85
86 static void
87 igfxdrawinit(VGAscr *scr)
88 {
89         scr->blank = igfxblank;
90 }
91
92 VGAdev vgaigfxdev = {
93         "igfx",
94         igfxenable,
95         nil,
96         nil,
97         nil,
98         igfxdrawinit,
99 };
100
101 static void
102 igfxcurload(VGAscr* scr, Cursor* curs)
103 {
104         uchar set, clr;
105         u32int *p;
106         int i, j;
107
108         if(scr->storage == 0)
109                 return;
110         p = (u32int*)((uchar*)scr->vaddr + scr->storage);
111         memset(p, 0, 64*64*4);
112         for(i=0;i<32;i++) {
113                 set = curs->set[i];
114                 clr = curs->clr[i];
115                 for(j=0x80; j; j>>=1){
116                         if((set|clr)&j)
117                                 *p++ = (0xFF<<24) | (set&j ? 0x000000 : 0xFFFFFF);
118                         else
119                                 *p++ = 0;
120                 }
121                 if(i & 1)
122                         p += 64-16;
123         }
124         scr->offset = curs->offset;
125 }
126
127 enum {
128         CURCTL = 0,
129         CURBASE,
130         CURPOS,
131
132         NPIPE = 4,
133 };
134
135 static u32int*
136 igfxcurregs(VGAscr* scr, int pipe)
137 {
138         u32int o;
139
140         if(scr->mmio == nil || scr->storage == 0)
141                 return nil;
142         o = pipe == 3 ? 0xf000 : pipe*0x1000;
143         /* check PIPExCONF if enabled */
144         if((scr->mmio[(0x70008 | o)/4] & (1<<31)) == 0)
145                 return nil;
146         switch(scr->pci->did){
147         case 0x0412:    /* Haswell HD Graphics 4600 */
148         case 0x0a16:    /* Haswell HD Graphics 4400 */
149                 if(pipe > 3)
150                         return nil;
151                 if(pipe == 3)
152                         o = 0;
153                 break;
154         case 0x0166:    /* Ivy Bridge */
155         case 0x0152:    /* Core-i3 */
156         case 0x0126:    /* Sandy Bridge HD Graphics 3000 */
157                 if(pipe > 2)
158                         return nil;
159                 break;
160         case 0x2592:    /* GM915 */
161         case 0x2a42:    /* X200 */
162         case 0x29a2:    /* 82P965/G965 HECI desktop */
163         case 0x2a02:    /* CF-R7 */
164         case 0x0102:    /* Sndy Bridge */
165                 if(pipe > 1)
166                         return nil;
167                 o = pipe*0x40;
168                 break;
169         default:
170                 if(pipe > 0)
171                         return nil;
172         }
173         return (u32int*)((uchar*)scr->mmio + (0x70080 + o));
174 }
175
176 static int
177 igfxcurmove(VGAscr* scr, Point p)
178 {
179         int i, x, y;
180         u32int *r;
181
182         for(i=0; i<NPIPE; i++){
183                 if((r = igfxcurregs(scr, i)) != nil){
184                         x = p.x + scr->offset.x;
185                         if(x < 0) x = -x | 0x8000;
186                         y = p.y + scr->offset.y;
187                         if(y < 0) y = -y | 0x8000;
188                         r[CURPOS] = (y << 16) | x;
189                 }
190         }
191         return 0;
192 }
193
194 static void
195 igfxcurenable(VGAscr* scr)
196 {
197         u32int *r;
198         int i;
199
200         igfxenable(scr);
201         igfxcurload(scr, &cursor);
202         igfxcurmove(scr, ZP);
203
204         for(i=0; i<NPIPE; i++){
205                 if((r = igfxcurregs(scr, i)) != nil){
206                         r[CURCTL] = (r[CURCTL] & ~(3<<28 | 1<<5)) | (i<<28) | 7;
207                         r[CURBASE] = scr->storage;
208                 }
209         }
210 }
211
212 static void
213 igfxcurdisable(VGAscr* scr)
214 {
215         u32int *r;
216         int i;
217
218         for(i=0; i<NPIPE; i++){
219                 if((r = igfxcurregs(scr, i)) != nil){
220                         r[CURCTL] &= ~(1<<5 | 7);
221                         r[CURBASE] = 0;
222                 }
223         }
224 }
225
226 VGAcur vgaigfxcur = {
227         "igfxhwgc",
228         igfxcurenable,
229         igfxcurdisable,
230         igfxcurload,
231         igfxcurmove,
232 };