]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/vgaigfx.c
igfx: add support for haswell graphics
[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 ulong
16 stolenmb(Pcidev *p)
17 {
18         switch(p->did){
19         case 0x0412:    /* Haswell HD Graphics 4600 */
20         case 0x0a16:    /* Haswell HD Graphics 4400 */
21         case 0x0166:    /* Ivy Bridge */
22         case 0x0102:    /* Core-5 Sandy Bridge */
23         case 0x0152:    /* Core-i3 */
24                 switch((pcicfgr16(p, 0x50) >> 3) & 0x1f){
25                 case 0x01:      return 32  - 2;
26                 case 0x02:      return 64  - 2;         /* 0102 Dell machine here */
27                 case 0x03:      return 96  - 2;
28                 case 0x04:      return 128 - 2;
29                 case 0x05:      return 32  - 2;
30                 case 0x06:      return 48  - 2;
31                 case 0x07:      return 64  - 2;
32                 case 0x08:      return 128 - 2;
33                 case 0x09:      return 256 - 2;
34                 case 0x0A:      return 96  - 2;
35                 case 0x0B:      return 160 - 2;
36                 case 0x0C:      return 224 - 2;
37                 case 0x0D:      return 352 - 2;
38                 case 0x0E:      return 448 - 2;
39                 case 0x0F:      return 480 - 2;
40                 case 0x10:      return 512 - 2;
41                 }
42                 break;
43         case 0x2a42:    /* X200 */
44         case 0x29a2:    /* 82P965/G965 HECI desktop */
45         case 0x2a02:    /* CF-R7 */
46                 switch((pcicfgr16(p, 0x52) >> 4) & 7){
47                 case 0x01:      return 1;
48                 case 0x02:      return 4;
49                 case 0x03:      return 8;
50                 case 0x04:      return 16;
51                 case 0x05:      return 32;
52                 case 0x06:      return 48;
53                 case 0x07:      return 64;
54                 }
55                 break;
56         }
57         return 0;
58 }
59
60 static uintptr
61 gmsize(Pcidev *pci, void *mmio)
62 {
63         u32int x, i, npg, *gtt;
64
65         npg = stolenmb(pci)<<(20-12);
66         if(npg == 0)
67                 return 0;
68         gtt = (u32int*)((uchar*)mmio + pci->mem[0].size/2);
69         if((gtt[0]&1) == 0)
70                 return 0;
71         x = (gtt[0]>>12)+1;
72         for(i=1; i<npg; i++){
73                 if((gtt[i]&1) == 0 || (gtt[i]>>12) != x)
74                         break;
75                 x++;
76         }
77         if(0) print("igfx: graphics memory at %p-%p (%ud MB)\n", 
78                 (uintptr)(x-i)<<12, (uintptr)x<<12, (i>>(20-12)));
79         return (uintptr)i<<12;
80 }
81
82 static void
83 igfxenable(VGAscr* scr)
84 {
85         Pcidev *p;
86         
87         if(scr->mmio != nil)
88                 return;
89         p = scr->pci;
90         if(p == nil)
91                 return;
92         scr->mmio = vmap(p->mem[0].bar&~0x0F, p->mem[0].size);
93         if(scr->mmio == nil)
94                 return;
95         addvgaseg("igfxmmio", p->mem[0].bar&~0x0F, p->mem[0].size);
96         if(scr->paddr == 0)
97                 vgalinearpci(scr);
98         if(scr->apsize){
99                 addvgaseg("igfxscreen", scr->paddr, scr->apsize);
100                 scr->storage = gmsize(p, scr->mmio);
101                 if(scr->storage < MB)
102                         scr->storage = 0;
103                 else if(scr->storage > scr->apsize)
104                         scr->storage = scr->apsize;
105                 if(scr->storage != 0)
106                         scr->storage -= PGROUND(64*64*4);
107         }
108         scr->softscreen = 1;
109 }
110
111 VGAdev vgaigfxdev = {
112         "igfx",
113         igfxenable,
114 };
115
116 static void
117 igfxcurload(VGAscr* scr, Cursor* curs)
118 {
119         uchar set, clr;
120         u32int *p;
121         int i, j;
122
123         if(scr->storage == 0)
124                 return;
125         p = (u32int*)((uchar*)scr->vaddr + scr->storage);
126         memset(p, 0, 64*64*4);
127         for(i=0;i<32;i++) {
128                 set = curs->set[i];
129                 clr = curs->clr[i];
130                 for(j=0x80; j; j>>=1){
131                         if((set|clr)&j)
132                                 *p++ = (0xFF<<24) | (set&j ? 0x000000 : 0xFFFFFF);
133                         else
134                                 *p++ = 0;
135                 }
136                 if(i & 1)
137                         p += 64-16;
138         }
139         scr->offset = curs->offset;
140 }
141
142 enum {
143         CURCTL = 0,
144         CURBASE,
145         CURPOS,
146
147         NPIPE = 4,
148 };
149
150 static u32int*
151 igfxcurregs(VGAscr* scr, int pipe)
152 {
153         u32int o;
154
155         if(scr->mmio == nil || scr->storage == 0)
156                 return nil;
157         o = pipe == 3 ? 0xf000 : pipe*0x1000;
158         /* check PIPExCONF if enabled */
159         if((scr->mmio[(0x70008 | o)/4] & (1<<31)) == 0)
160                 return nil;
161         switch(scr->pci->did){
162         case 0x0412:    /* Haswell HD Graphics 4600 */
163         case 0x0a16:    /* Haswell HD Graphics 4400 */
164                 if(pipe > 3)
165                         return nil;
166                 if(pipe == 3)
167                         o = 0;
168                 break;
169         case 0x0166:    /* Ivy Bridge */
170         case 0x0152:    /* Core-i3 */
171                 if(pipe > 2)
172                         return nil;
173                 break;
174         case 0x2a42:    /* X200 */
175         case 0x29a2:    /* 82P965/G965 HECI desktop */
176         case 0x2a02:    /* CF-R7 */
177         case 0x0102:    /* Sndy Bridge */
178                 if(pipe > 1)
179                         return nil;
180                 o = pipe*0x40;
181                 break;
182         default:
183                 if(pipe > 0)
184                         return nil;
185         }
186         return (u32int*)((uchar*)scr->mmio + (0x70080 + o));
187 }
188
189 static int
190 igfxcurmove(VGAscr* scr, Point p)
191 {
192         int i, x, y;
193         u32int *r;
194
195         for(i=0; i<NPIPE; i++){
196                 if((r = igfxcurregs(scr, i)) != nil){
197                         x = p.x + scr->offset.x;
198                         if(x < 0) x = -x | 0x8000;
199                         y = p.y + scr->offset.y;
200                         if(y < 0) y = -y | 0x8000;
201                         r[CURPOS] = (y << 16) | x;
202                 }
203         }
204         return 0;
205 }
206
207 static void
208 igfxcurenable(VGAscr* scr)
209 {
210         u32int *r;
211         int i;
212
213         igfxenable(scr);
214         igfxcurload(scr, &arrow);
215         igfxcurmove(scr, ZP);
216
217         for(i=0; i<NPIPE; i++){
218                 if((r = igfxcurregs(scr, i)) != nil){
219                         r[CURCTL] = (r[CURCTL] & ~(3<<28 | 1<<5)) | (i<<28) | 7;
220                         r[CURBASE] = scr->storage;
221                 }
222         }
223 }
224
225 static void
226 igfxcurdisable(VGAscr* scr)
227 {
228         u32int *r;
229         int i;
230
231         for(i=0; i<NPIPE; i++){
232                 if((r = igfxcurregs(scr, i)) != nil){
233                         r[CURCTL] &= ~(1<<5 | 7);
234                         r[CURBASE] = 0;
235                 }
236         }
237 }
238
239 VGAcur vgaigfxcur = {
240         "igfxhwgc",
241         igfxcurenable,
242         igfxcurdisable,
243         igfxcurload,
244         igfxcurmove,
245 };