• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <arch/io.h>
4 #include <device/mmio.h>
5 #include <console/console.h>
6 #include <bootmode.h>
7 #include <cpu/intel/model_206ax/model_206ax.h>
8 #include <delay.h>
9 #include <device/device.h>
10 #include <device/pci.h>
11 #include <device/pci_ids.h>
12 #include <device/pci_ops.h>
13 #include <drivers/intel/gma/libgfxinit.h>
14 #include <drivers/intel/gma/opregion.h>
15 #include <southbridge/intel/bd82x6x/pch.h>
16 #include <types.h>
17 
18 #include "chip.h"
19 #include "sandybridge.h"
20 
21 struct gt_powermeter {
22 	u16 reg;
23 	u32 value;
24 };
25 
26 static const struct gt_powermeter snb_pm_gt1[] = {
27 	{ 0xa200, 0xcc000000 },
28 	{ 0xa204, 0x07000040 },
29 	{ 0xa208, 0x0000fe00 },
30 	{ 0xa20c, 0x00000000 },
31 	{ 0xa210, 0x17000000 },
32 	{ 0xa214, 0x00000021 },
33 	{ 0xa218, 0x0817fe19 },
34 	{ 0xa21c, 0x00000000 },
35 	{ 0xa220, 0x00000000 },
36 	{ 0xa224, 0xcc000000 },
37 	{ 0xa228, 0x07000040 },
38 	{ 0xa22c, 0x0000fe00 },
39 	{ 0xa230, 0x00000000 },
40 	{ 0xa234, 0x17000000 },
41 	{ 0xa238, 0x00000021 },
42 	{ 0xa23c, 0x0817fe19 },
43 	{ 0xa240, 0x00000000 },
44 	{ 0xa244, 0x00000000 },
45 	{ 0xa248, 0x8000421e },
46 	{ 0 },
47 };
48 
49 static const struct gt_powermeter snb_pm_gt2[] = {
50 	{ 0xa200, 0x330000a6 },
51 	{ 0xa204, 0x402d0031 },
52 	{ 0xa208, 0x00165f83 },
53 	{ 0xa20c, 0xf1000000 },
54 	{ 0xa210, 0x00000000 },
55 	{ 0xa214, 0x00160016 },
56 	{ 0xa218, 0x002a002b },
57 	{ 0xa21c, 0x00000000 },
58 	{ 0xa220, 0x00000000 },
59 	{ 0xa224, 0x330000a6 },
60 	{ 0xa228, 0x402d0031 },
61 	{ 0xa22c, 0x00165f83 },
62 	{ 0xa230, 0xf1000000 },
63 	{ 0xa234, 0x00000000 },
64 	{ 0xa238, 0x00160016 },
65 	{ 0xa23c, 0x002a002b },
66 	{ 0xa240, 0x00000000 },
67 	{ 0xa244, 0x00000000 },
68 	{ 0xa248, 0x8000421e },
69 	{ 0 },
70 };
71 
72 static const struct gt_powermeter ivb_pm_gt1[] = {
73 	{ 0xa800, 0x00000000 },
74 	{ 0xa804, 0x00021c00 },
75 	{ 0xa808, 0x00000403 },
76 	{ 0xa80c, 0x02001700 },
77 	{ 0xa810, 0x05000200 },
78 	{ 0xa814, 0x00000000 },
79 	{ 0xa818, 0x00690500 },
80 	{ 0xa81c, 0x0000007f },
81 	{ 0xa820, 0x01002501 },
82 	{ 0xa824, 0x00000300 },
83 	{ 0xa828, 0x01000331 },
84 	{ 0xa82c, 0x0000000c },
85 	{ 0xa830, 0x00010016 },
86 	{ 0xa834, 0x01100101 },
87 	{ 0xa838, 0x00010103 },
88 	{ 0xa83c, 0x00041300 },
89 	{ 0xa840, 0x00000b30 },
90 	{ 0xa844, 0x00000000 },
91 	{ 0xa848, 0x7f000000 },
92 	{ 0xa84c, 0x05000008 },
93 	{ 0xa850, 0x00000001 },
94 	{ 0xa854, 0x00000004 },
95 	{ 0xa858, 0x00000007 },
96 	{ 0xa85c, 0x00000000 },
97 	{ 0xa860, 0x00010000 },
98 	{ 0xa248, 0x0000221e },
99 	{ 0xa900, 0x00000000 },
100 	{ 0xa904, 0x00001c00 },
101 	{ 0xa908, 0x00000000 },
102 	{ 0xa90c, 0x06000000 },
103 	{ 0xa910, 0x09000200 },
104 	{ 0xa914, 0x00000000 },
105 	{ 0xa918, 0x00590000 },
106 	{ 0xa91c, 0x00000000 },
107 	{ 0xa920, 0x04002501 },
108 	{ 0xa924, 0x00000100 },
109 	{ 0xa928, 0x03000410 },
110 	{ 0xa92c, 0x00000000 },
111 	{ 0xa930, 0x00020000 },
112 	{ 0xa934, 0x02070106 },
113 	{ 0xa938, 0x00010100 },
114 	{ 0xa93c, 0x00401c00 },
115 	{ 0xa940, 0x00000000 },
116 	{ 0xa944, 0x00000000 },
117 	{ 0xa948, 0x10000e00 },
118 	{ 0xa94c, 0x02000004 },
119 	{ 0xa950, 0x00000001 },
120 	{ 0xa954, 0x00000004 },
121 	{ 0xa960, 0x00060000 },
122 	{ 0xaa3c, 0x00001c00 },
123 	{ 0xaa54, 0x00000004 },
124 	{ 0xaa60, 0x00060000 },
125 	{ 0 },
126 };
127 
128 static const struct gt_powermeter ivb_pm_gt2_17w[] = {
129 	{ 0xa800, 0x20000000 },
130 	{ 0xa804, 0x000e3800 },
131 	{ 0xa808, 0x00000806 },
132 	{ 0xa80c, 0x0c002f00 },
133 	{ 0xa810, 0x0c000800 },
134 	{ 0xa814, 0x00000000 },
135 	{ 0xa818, 0x00d20d00 },
136 	{ 0xa81c, 0x000000ff },
137 	{ 0xa820, 0x03004b02 },
138 	{ 0xa824, 0x00000600 },
139 	{ 0xa828, 0x07000773 },
140 	{ 0xa82c, 0x00000000 },
141 	{ 0xa830, 0x00020032 },
142 	{ 0xa834, 0x1520040d },
143 	{ 0xa838, 0x00020105 },
144 	{ 0xa83c, 0x00083700 },
145 	{ 0xa840, 0x000016ff },
146 	{ 0xa844, 0x00000000 },
147 	{ 0xa848, 0xff000000 },
148 	{ 0xa84c, 0x0a000010 },
149 	{ 0xa850, 0x00000002 },
150 	{ 0xa854, 0x00000008 },
151 	{ 0xa858, 0x0000000f },
152 	{ 0xa85c, 0x00000000 },
153 	{ 0xa860, 0x00020000 },
154 	{ 0xa248, 0x0000221e },
155 	{ 0xa900, 0x00000000 },
156 	{ 0xa904, 0x00003800 },
157 	{ 0xa908, 0x00000000 },
158 	{ 0xa90c, 0x0c000000 },
159 	{ 0xa910, 0x12000800 },
160 	{ 0xa914, 0x00000000 },
161 	{ 0xa918, 0x00b20000 },
162 	{ 0xa91c, 0x00000000 },
163 	{ 0xa920, 0x08004b02 },
164 	{ 0xa924, 0x00000300 },
165 	{ 0xa928, 0x01000820 },
166 	{ 0xa92c, 0x00000000 },
167 	{ 0xa930, 0x00030000 },
168 	{ 0xa934, 0x15150406 },
169 	{ 0xa938, 0x00020300 },
170 	{ 0xa93c, 0x00903900 },
171 	{ 0xa940, 0x00000000 },
172 	{ 0xa944, 0x00000000 },
173 	{ 0xa948, 0x20001b00 },
174 	{ 0xa94c, 0x0a000010 },
175 	{ 0xa950, 0x00000000 },
176 	{ 0xa954, 0x00000008 },
177 	{ 0xa960, 0x00110000 },
178 	{ 0xaa3c, 0x00003900 },
179 	{ 0xaa54, 0x00000008 },
180 	{ 0xaa60, 0x00110000 },
181 	{ 0 },
182 };
183 
184 static const struct gt_powermeter ivb_pm_gt2_35w[] = {
185 	{ 0xa800, 0x00000000 },
186 	{ 0xa804, 0x00030400 },
187 	{ 0xa808, 0x00000806 },
188 	{ 0xa80c, 0x0c002f00 },
189 	{ 0xa810, 0x0c000300 },
190 	{ 0xa814, 0x00000000 },
191 	{ 0xa818, 0x00d20d00 },
192 	{ 0xa81c, 0x000000ff },
193 	{ 0xa820, 0x03004b02 },
194 	{ 0xa824, 0x00000600 },
195 	{ 0xa828, 0x07000773 },
196 	{ 0xa82c, 0x00000000 },
197 	{ 0xa830, 0x00020032 },
198 	{ 0xa834, 0x1520040d },
199 	{ 0xa838, 0x00020105 },
200 	{ 0xa83c, 0x00083700 },
201 	{ 0xa840, 0x000016ff },
202 	{ 0xa844, 0x00000000 },
203 	{ 0xa848, 0xff000000 },
204 	{ 0xa84c, 0x0a000010 },
205 	{ 0xa850, 0x00000001 },
206 	{ 0xa854, 0x00000008 },
207 	{ 0xa858, 0x00000008 },
208 	{ 0xa85c, 0x00000000 },
209 	{ 0xa860, 0x00020000 },
210 	{ 0xa248, 0x0000221e },
211 	{ 0xa900, 0x00000000 },
212 	{ 0xa904, 0x00003800 },
213 	{ 0xa908, 0x00000000 },
214 	{ 0xa90c, 0x0c000000 },
215 	{ 0xa910, 0x12000800 },
216 	{ 0xa914, 0x00000000 },
217 	{ 0xa918, 0x00b20000 },
218 	{ 0xa91c, 0x00000000 },
219 	{ 0xa920, 0x08004b02 },
220 	{ 0xa924, 0x00000300 },
221 	{ 0xa928, 0x01000820 },
222 	{ 0xa92c, 0x00000000 },
223 	{ 0xa930, 0x00030000 },
224 	{ 0xa934, 0x15150406 },
225 	{ 0xa938, 0x00020300 },
226 	{ 0xa93c, 0x00903900 },
227 	{ 0xa940, 0x00000000 },
228 	{ 0xa944, 0x00000000 },
229 	{ 0xa948, 0x20001b00 },
230 	{ 0xa94c, 0x0a000010 },
231 	{ 0xa950, 0x00000000 },
232 	{ 0xa954, 0x00000008 },
233 	{ 0xa960, 0x00110000 },
234 	{ 0xaa3c, 0x00003900 },
235 	{ 0xaa54, 0x00000008 },
236 	{ 0xaa60, 0x00110000 },
237 	{ 0 },
238 };
239 
240 /*
241  * Some VGA option roms are used for several chipsets but they only have one PCI ID in their
242  * header. If we encounter such an option rom, we need to do the mapping ourselves.
243  */
244 
map_oprom_vendev(u32 vendev)245 u32 map_oprom_vendev(u32 vendev)
246 {
247 	u32 new_vendev = vendev;
248 
249 	switch (vendev) {
250 	case 0x80860102:		/* SNB GT1 Desktop */
251 	case 0x8086010a:		/* SNB GT1 Server  */
252 	case 0x80860112:		/* SNB GT2 Desktop */
253 	case 0x80860116:		/* SNB GT2 Mobile  */
254 	case 0x80860122:		/* SNB GT2 Desktop >=1.3GHz */
255 	case 0x80860126:		/* SNB GT2 Mobile  >=1.3GHz */
256 	case 0x80860152:		/* IVB GT1 Desktop */
257 	case 0x80860156:		/* IVB GT1 Mobile  */
258 	case 0x80860162:		/* IVB GT2 Desktop */
259 	case 0x80860166:		/* IVB GT2 Mobile  */
260 	case 0x8086016a:		/* IVB GT2 Server  */
261 		new_vendev = 0x80860106;/* SNB GT1 Mobile  */
262 		break;
263 	}
264 
265 	return new_vendev;
266 }
267 
268 static struct resource *gtt_res = NULL;
269 
gtt_read(u32 reg)270 u32 gtt_read(u32 reg)
271 {
272 	return read32(res2mmio(gtt_res, reg, 0));
273 }
274 
gtt_write(u32 reg,u32 data)275 void gtt_write(u32 reg, u32 data)
276 {
277 	write32(res2mmio(gtt_res, reg, 0), data);
278 }
279 
gtt_write_powermeter(const struct gt_powermeter * pm)280 static inline void gtt_write_powermeter(const struct gt_powermeter *pm)
281 {
282 	for (; pm && pm->reg; pm++)
283 		gtt_write(pm->reg, pm->value);
284 }
285 
286 #define GTT_RETRY 1000
gtt_poll(u32 reg,u32 mask,u32 value)287 int gtt_poll(u32 reg, u32 mask, u32 value)
288 {
289 	unsigned int try = GTT_RETRY;
290 	u32 data;
291 
292 	while (try--) {
293 		data = gtt_read(reg);
294 		if ((data & mask) == value)
295 			return 1;
296 		udelay(10);
297 	}
298 
299 	printk(BIOS_ERR, "GT init timeout\n");
300 	return 0;
301 }
302 
gma_pm_init_pre_vbios(struct device * dev)303 static void gma_pm_init_pre_vbios(struct device *dev)
304 {
305 	const bool is_sandy = is_sandybridge();
306 
307 	u32 reg32;
308 
309 	printk(BIOS_DEBUG, "GT Power Management Init\n");
310 
311 	gtt_res = probe_resource(dev, PCI_BASE_ADDRESS_0);
312 	if (!gtt_res || !gtt_res->base)
313 		return;
314 
315 	if (is_sandy || cpu_stepping() < IVB_STEP_C0) {
316 		/* 1: Enable force wake */
317 		gtt_write(0xa18c, 0x00000001);
318 		gtt_poll(0x130090, (1 << 0), (1 << 0));
319 	} else {
320 		gtt_write(0xa180, 1 << 5);
321 		gtt_write(0xa188, 0xffff0001);
322 		gtt_poll(0x130040, (1 << 0), (1 << 0));
323 	}
324 
325 	if (is_sandy) {
326 		/* 1d: Set GTT+0x42004 [15:14]=11 (SnB C1+) */
327 		reg32 = gtt_read(0x42004);
328 		reg32 |= (1 << 14) | (1 << 15);
329 		gtt_write(0x42004, reg32);
330 	}
331 
332 	if (!is_sandy) {
333 		/* Display Reset Acknowledge Settings */
334 		reg32 = gtt_read(0x45010);
335 		reg32 |= (1 << 1) | (1 << 0);
336 		gtt_write(0x45010, reg32);
337 	}
338 
339 	/* 2: Get GT SKU from GTT+0x911c[13] */
340 	reg32 = gtt_read(0x911c);
341 	if (is_sandy) {
342 		if (reg32 & (1 << 13)) {
343 			printk(BIOS_DEBUG, "SNB GT1 Power Meter Weights\n");
344 			gtt_write_powermeter(snb_pm_gt1);
345 		} else {
346 			printk(BIOS_DEBUG, "SNB GT2 Power Meter Weights\n");
347 			gtt_write_powermeter(snb_pm_gt2);
348 		}
349 	} else {
350 		u32 unit = mchbar_read32(0x5938) & 0xf;
351 
352 		if (reg32 & (1 << 13)) {
353 			/* GT1 SKU */
354 			printk(BIOS_DEBUG, "IVB GT1 Power Meter Weights\n");
355 			gtt_write_powermeter(ivb_pm_gt1);
356 		} else {
357 			/* GT2 SKU */
358 			u32 tdp = mchbar_read32(0x5930) & 0x7fff;
359 			tdp /= (1 << unit);
360 
361 			if (tdp <= 17) {
362 				/* <=17W ULV */
363 				printk(BIOS_DEBUG, "IVB GT2 17W Power Meter Weights\n");
364 				gtt_write_powermeter(ivb_pm_gt2_17w);
365 			} else if ((tdp >= 25) && (tdp <= 35)) {
366 				/* 25W-35W */
367 				printk(BIOS_DEBUG, "IVB GT2 25W-35W Power Meter Weights\n");
368 				gtt_write_powermeter(ivb_pm_gt2_35w);
369 			} else {
370 				/* All others */
371 				printk(BIOS_DEBUG, "IVB GT2 35W Power Meter Weights\n");
372 				gtt_write_powermeter(ivb_pm_gt2_35w);
373 			}
374 		}
375 	}
376 
377 	/* 3: Gear ratio map */
378 	gtt_write(0xa004, 0x00000010);
379 
380 	/* 4: GFXPAUSE */
381 	gtt_write(0xa000, 0x00070020);
382 
383 	/* 5: Dynamic EU trip control */
384 	gtt_write(0xa080, 0x00000004);
385 
386 	/* 6: ECO bits */
387 	reg32 = gtt_read(0xa180);
388 	reg32 |= (1 << 26) | (1 << 31);
389 	/* (bit 20=1 for SNB step D1+ / IVB A0+) */
390 	if (!is_sandy || cpu_stepping() >= SNB_STEP_D1)
391 		reg32 |= (1 << 20);
392 	gtt_write(0xa180, reg32);
393 
394 	/* 6a: for SnB step D2+ only */
395 	if (is_sandy && cpu_stepping() >= SNB_STEP_D2) {
396 		reg32 = gtt_read(0x9400);
397 		reg32 |= (1 << 7);
398 		gtt_write(0x9400, reg32);
399 
400 		reg32 = gtt_read(0x941c);
401 		reg32 &= 0xf;
402 		reg32 |= (1 << 1);
403 		gtt_write(0x941c, reg32);
404 		gtt_poll(0x941c, (1 << 1), (0 << 1));
405 	}
406 
407 	if (is_sandy) {
408 		/* 6b: Clocking reset controls */
409 		gtt_write(0x9424, 0x00000000);
410 	} else {
411 		reg32 = gtt_read(0x907c);
412 		reg32 |= (1 << 16);
413 		gtt_write(0x907c, reg32);
414 
415 		/* 6b: Clocking reset controls */
416 		gtt_write(0x9424, 0x00000001);
417 	}
418 
419 	/* 7 */
420 	if (gtt_poll(0x138124, (1 << 31), (0 << 31))) {
421 		gtt_write(0x138128, 0x00000029); /* Mailbox Data */
422 		gtt_write(0x138124, 0x80000004); /* Mailbox Cmd for RC6 VID */
423 		if (gtt_poll(0x138124, (1 << 31), (0 << 31)))
424 			gtt_write(0x138124, 0x8000000a);
425 		gtt_poll(0x138124, (1 << 31), (0 << 31));
426 	}
427 
428 	/* 8 */
429 	gtt_write(0xa090, 0x00000000); /* RC Control */
430 	gtt_write(0xa098, 0x03e80000); /* RC1e Wake Rate Limit */
431 	gtt_write(0xa09c, 0x0028001e); /* RC6/6p Wake Rate Limit */
432 	gtt_write(0xa0a0, 0x0000001e); /* RC6pp Wake Rate Limit */
433 	gtt_write(0xa0a8, 0x0001e848); /* RC Evaluation Interval */
434 	gtt_write(0xa0ac, 0x00000019); /* RC Idle Hysteresis */
435 
436 	/* 9 */
437 	gtt_write(0x2054, 0x0000000a); /* Render Idle Max Count */
438 	gtt_write(0x12054,0x0000000a); /* Video Idle Max Count */
439 	gtt_write(0x22054,0x0000000a); /* Blitter Idle Max Count */
440 
441 	/* 10 */
442 	gtt_write(0xa0b0, 0x00000000); /* Unblock Ack to Busy */
443 	gtt_write(0xa0b4, 0x000003e8); /* RC1e Threshold */
444 	gtt_write(0xa0b8, 0x0000c350); /* RC6 Threshold */
445 	gtt_write(0xa0bc, 0x000186a0); /* RC6p Threshold */
446 	gtt_write(0xa0c0, 0x0000fa00); /* RC6pp Threshold */
447 
448 	/* 11 */
449 	gtt_write(0xa010, 0x000f4240); /* RP Down Timeout */
450 	gtt_write(0xa014, 0x12060000); /* RP Interrupt Limits */
451 	gtt_write(0xa02c, 0x00015f90); /* RP Up Threshold */
452 	gtt_write(0xa030, 0x000186a0); /* RP Down Threshold */
453 	gtt_write(0xa068, 0x000186a0); /* RP Up EI */
454 	gtt_write(0xa06c, 0x000493e0); /* RP Down EI */
455 	gtt_write(0xa070, 0x0000000a); /* RP Idle Hysteresis */
456 
457 	/*
458 	 * 11a: Enable Render Standby (RC6)
459 	 *
460 	 * IvyBridge should also support DeepRenderStandby.
461 	 *
462 	 * Unfortunately it does not work reliably on all SKUs so
463 	 * disable it here and it can be enabled by the kernel.
464 	 */
465 	gtt_write(0xa090, 0x88040000); /* HW RC Control */
466 
467 	/* 12: Normal Frequency Request */
468 	/* RPNFREQ_VAL comes from MCHBAR 0x5998 23:16 */
469 	/* only the lower 7 bits are used and shifted left by 25 */
470 	reg32 = mchbar_read32(0x5998);
471 	reg32 >>= 16;
472 	reg32 &= 0x7f;
473 	reg32 <<= 25;
474 	gtt_write(0xa008, reg32);
475 
476 	/* 13: RP Control */
477 	gtt_write(0xa024, 0x00000592);
478 
479 	/* 14: Enable PM Interrupts */
480 	gtt_write(0x4402c, 0x03000076);
481 
482 	/* Clear 0x6c024 [8:6] */
483 	reg32 = gtt_read(0x6c024);
484 	reg32 &= ~0x000001c0;
485 	gtt_write(0x6c024, reg32);
486 
487 	/* Initialize DP buffer translation with recommended defaults */
488 	gtt_write(0xe4f00, 0x0100030c);
489 	gtt_write(0xe4f04, 0x00b8230c);
490 	gtt_write(0xe4f08, 0x06f8930c);
491 	gtt_write(0xe4f0c, 0x05f8e38e);
492 	gtt_write(0xe4f10, 0x00b8030c);
493 	gtt_write(0xe4f14, 0x0b78830c);
494 	gtt_write(0xe4f18, 0x09f8d3cf);
495 	gtt_write(0xe4f1c, 0x01e8030c);
496 	gtt_write(0xe4f20, 0x09f863cf);
497 	gtt_write(0xe4f24, 0x0ff803cf);
498 }
499 
gma_pm_init_post_vbios(struct device * dev)500 static void gma_pm_init_post_vbios(struct device *dev)
501 {
502 	struct northbridge_intel_sandybridge_config *conf = dev->chip_info;
503 	u32 reg32;
504 
505 	printk(BIOS_DEBUG, "GT Power Management Init (post VBIOS)\n");
506 
507 	/* 15: Deassert Force Wake */
508 	if (is_sandybridge() || cpu_stepping() < IVB_STEP_C0) {
509 		gtt_write(0xa18c, gtt_read(0xa18c) & ~1);
510 		gtt_poll(0x130090, (1 << 0), (0 << 0));
511 	} else {
512 		gtt_write(0xa188, 0x1fffe);
513 		if (gtt_poll(0x130040, (1 << 0), (0 << 0)))
514 			gtt_write(0xa188, gtt_read(0xa188) | 1);
515 	}
516 
517 	/* 16: SW RC Control */
518 	gtt_write(0xa094, 0x00060000);
519 
520 	/* Setup Digital Port Hotplug */
521 	reg32 = gtt_read(0xc4030);
522 	if (!reg32) {
523 		reg32  = (conf->gpu_dp_b_hotplug & 0x7) <<  2;
524 		reg32 |= (conf->gpu_dp_c_hotplug & 0x7) << 10;
525 		reg32 |= (conf->gpu_dp_d_hotplug & 0x7) << 18;
526 		gtt_write(0xc4030, reg32);
527 	}
528 
529 	/* Setup Panel Power On Delays */
530 	reg32 = gtt_read(0xc7208);
531 	if (!reg32) {
532 		reg32 = (conf->gpu_panel_port_select & 0x3) << 30;
533 		reg32 |= (conf->gpu_panel_power_up_delay & 0x1fff) << 16;
534 		reg32 |= (conf->gpu_panel_power_backlight_on_delay & 0x1fff);
535 		gtt_write(0xc7208, reg32);
536 	}
537 
538 	/* Setup Panel Power Off Delays */
539 	reg32 = gtt_read(0xc720c);
540 	if (!reg32) {
541 		reg32 = (conf->gpu_panel_power_down_delay & 0x1fff) << 16;
542 		reg32 |= (conf->gpu_panel_power_backlight_off_delay & 0x1fff);
543 		gtt_write(0xc720c, reg32);
544 	}
545 
546 	/* Setup Panel Power Cycle Delay */
547 	if (conf->gpu_panel_power_cycle_delay) {
548 		reg32 = gtt_read(0xc7210);
549 		reg32 &= ~0xff;
550 		reg32 |= conf->gpu_panel_power_cycle_delay & 0xff;
551 		gtt_write(0xc7210, reg32);
552 	}
553 
554 	/* Enable Backlight if needed */
555 	if (conf->gpu_cpu_backlight) {
556 		gtt_write(0x48250, (1 << 31));
557 		gtt_write(0x48254, conf->gpu_cpu_backlight);
558 	}
559 	if (conf->gpu_pch_backlight) {
560 		gtt_write(0xc8250, (1 << 31));
561 		gtt_write(0xc8254, conf->gpu_pch_backlight);
562 	}
563 }
564 
565 /* Enable SCI to ACPI _GPE._L06 */
gma_enable_swsci(void)566 static void gma_enable_swsci(void)
567 {
568 	u16 reg16;
569 
570 	/* Clear DMISCI status */
571 	reg16 = inw(DEFAULT_PMBASE + TCO1_STS);
572 	reg16 &= DMISCI_STS;
573 	outw(reg16, DEFAULT_PMBASE + TCO1_STS);
574 
575 	/* Clear ACPI TCO status */
576 	outl(TCOSCI_STS, DEFAULT_PMBASE + GPE0_STS);
577 
578 	/* Enable ACPI TCO SCIs */
579 	reg16 = inw(DEFAULT_PMBASE + GPE0_EN);
580 	reg16 |= TCOSCI_EN;
581 	outw(reg16, DEFAULT_PMBASE + GPE0_EN);
582 }
583 
gma_func0_init(struct device * dev)584 static void gma_func0_init(struct device *dev)
585 {
586 	intel_gma_init_igd_opregion();
587 
588 	/* Init graphics power management */
589 	gma_pm_init_pre_vbios(dev);
590 
591 	if (!CONFIG(NO_GFX_INIT))
592 		pci_or_config16(dev, PCI_COMMAND, PCI_COMMAND_MASTER);
593 
594 	if (!CONFIG(MAINBOARD_USE_LIBGFXINIT))
595 		/* PCI Init, will run VBIOS */
596 		pci_dev_init(dev);
597 
598 	/* Post VBIOS init */
599 	gma_pm_init_post_vbios(dev);
600 
601 	int vga_disable = (pci_read_config16(dev, GGC) & 2) >> 1;
602 
603 	/* Running graphics init on S3 breaks Linux drm driver. */
604 	if (!acpi_is_wakeup_s3() &&
605 	    CONFIG(MAINBOARD_USE_LIBGFXINIT)) {
606 		if (vga_disable) {
607 			printk(BIOS_INFO,
608 			       "IGD is not decoding legacy VGA MEM and IO: skipping NATIVE graphic init\n");
609 		} else {
610 			/* This should probably run before post VBIOS init. */
611 			printk(BIOS_SPEW, "Initializing VGA without OPROM.\n");
612 			int lightup_ok;
613 			gma_gfxinit(&lightup_ok);
614 			if (lightup_ok)
615 				gfx_set_init_done(1);
616 		}
617 	}
618 
619 	gma_enable_swsci();
620 }
621 
gma_generate_ssdt(const struct device * device)622 static void gma_generate_ssdt(const struct device *device)
623 {
624 	const struct northbridge_intel_sandybridge_config *chip = device->chip_info;
625 
626 	drivers_intel_gma_displays_ssdt_generate(&chip->gfx);
627 }
628 
gma_acpi_name(const struct device * dev)629 static const char *gma_acpi_name(const struct device *dev)
630 {
631 	return "GFX0";
632 }
633 
634 /* Called by PCI set_vga_bridge function */
gma_func0_disable(struct device * dev)635 static void gma_func0_disable(struct device *dev)
636 {
637 	/* Disable VGA decode */
638 	pci_or_config16(pcidev_on_root(0, 0), GGC, 1 << 1);
639 
640 	dev->enabled = 0;
641 }
642 
643 struct device_operations sandybridge_gma_func0_ops = {
644 	.read_resources         = pci_dev_read_resources,
645 	.set_resources          = pci_dev_set_resources,
646 	.enable_resources       = pci_dev_enable_resources,
647 	.acpi_fill_ssdt		= gma_generate_ssdt,
648 	.init                   = gma_func0_init,
649 	.vga_disable                = gma_func0_disable,
650 	.ops_pci                = &pci_dev_ops_pci,
651 	.acpi_name              = gma_acpi_name,
652 };
653