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