]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/vgaigfx.c
igfx: support blanking by turning off panel power and backlight
[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                 off = 0x61204;
70                 break;
71
72         case 0x0126:    /* SNB */
73         case 0x0166:    /* IVB */
74                 off = 0xC7204;
75                 break;
76         }
77
78         /* toggle PP_CONTROL backlight & power state */
79         if(blank)
80                 scr->mmio[off/4] &= ~0x5;
81         else
82                 scr->mmio[off/4] |= 0x5;
83 }
84
85 static void
86 igfxdrawinit(VGAscr *scr)
87 {
88         scr->blank = igfxblank;
89 }
90
91 VGAdev vgaigfxdev = {
92         "igfx",
93         igfxenable,
94         nil,
95         nil,
96         nil,
97         igfxdrawinit,
98 };
99
100 static void
101 igfxcurload(VGAscr* scr, Cursor* curs)
102 {
103         uchar set, clr;
104         u32int *p;
105         int i, j;
106
107         if(scr->storage == 0)
108                 return;
109         p = (u32int*)((uchar*)scr->vaddr + scr->storage);
110         memset(p, 0, 64*64*4);
111         for(i=0;i<32;i++) {
112                 set = curs->set[i];
113                 clr = curs->clr[i];
114                 for(j=0x80; j; j>>=1){
115                         if((set|clr)&j)
116                                 *p++ = (0xFF<<24) | (set&j ? 0x000000 : 0xFFFFFF);
117                         else
118                                 *p++ = 0;
119                 }
120                 if(i & 1)
121                         p += 64-16;
122         }
123         scr->offset = curs->offset;
124 }
125
126 enum {
127         CURCTL = 0,
128         CURBASE,
129         CURPOS,
130
131         NPIPE = 4,
132 };
133
134 static u32int*
135 igfxcurregs(VGAscr* scr, int pipe)
136 {
137         u32int o;
138
139         if(scr->mmio == nil || scr->storage == 0)
140                 return nil;
141         o = pipe == 3 ? 0xf000 : pipe*0x1000;
142         /* check PIPExCONF if enabled */
143         if((scr->mmio[(0x70008 | o)/4] & (1<<31)) == 0)
144                 return nil;
145         switch(scr->pci->did){
146         case 0x0412:    /* Haswell HD Graphics 4600 */
147         case 0x0a16:    /* Haswell HD Graphics 4400 */
148                 if(pipe > 3)
149                         return nil;
150                 if(pipe == 3)
151                         o = 0;
152                 break;
153         case 0x0166:    /* Ivy Bridge */
154         case 0x0152:    /* Core-i3 */
155         case 0x0126:    /* Sandy Bridge HD Graphics 3000 */
156                 if(pipe > 2)
157                         return nil;
158                 break;
159         case 0x2a42:    /* X200 */
160         case 0x29a2:    /* 82P965/G965 HECI desktop */
161         case 0x2a02:    /* CF-R7 */
162         case 0x0102:    /* Sndy Bridge */
163                 if(pipe > 1)
164                         return nil;
165                 o = pipe*0x40;
166                 break;
167         default:
168                 if(pipe > 0)
169                         return nil;
170         }
171         return (u32int*)((uchar*)scr->mmio + (0x70080 + o));
172 }
173
174 static int
175 igfxcurmove(VGAscr* scr, Point p)
176 {
177         int i, x, y;
178         u32int *r;
179
180         for(i=0; i<NPIPE; i++){
181                 if((r = igfxcurregs(scr, i)) != nil){
182                         x = p.x + scr->offset.x;
183                         if(x < 0) x = -x | 0x8000;
184                         y = p.y + scr->offset.y;
185                         if(y < 0) y = -y | 0x8000;
186                         r[CURPOS] = (y << 16) | x;
187                 }
188         }
189         return 0;
190 }
191
192 static void
193 igfxcurenable(VGAscr* scr)
194 {
195         u32int *r;
196         int i;
197
198         igfxenable(scr);
199         igfxcurload(scr, &arrow);
200         igfxcurmove(scr, ZP);
201
202         for(i=0; i<NPIPE; i++){
203                 if((r = igfxcurregs(scr, i)) != nil){
204                         r[CURCTL] = (r[CURCTL] & ~(3<<28 | 1<<5)) | (i<<28) | 7;
205                         r[CURBASE] = scr->storage;
206                 }
207         }
208 }
209
210 static void
211 igfxcurdisable(VGAscr* scr)
212 {
213         u32int *r;
214         int i;
215
216         for(i=0; i<NPIPE; i++){
217                 if((r = igfxcurregs(scr, i)) != nil){
218                         r[CURCTL] &= ~(1<<5 | 7);
219                         r[CURBASE] = 0;
220                 }
221         }
222 }
223
224 VGAcur vgaigfxcur = {
225         "igfxhwgc",
226         igfxcurenable,
227         igfxcurdisable,
228         igfxcurload,
229         igfxcurmove,
230 };