blob: 019f7648f0b57ffcebd7ecc92331bcefc3617418 [file] [log] [blame]
Damien Zammit51fdb922016-01-18 18:34:52 +11001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2011 Chromium OS Authors
5 * Copyright (C) 2013 Vladimir Serbinenko
6 * Copyright (C) 2015 Damien Zammit <damien@zamaudio.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <arch/io.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +020019#include <device/mmio.h>
Damien Zammit51fdb922016-01-18 18:34:52 +110020#include <console/console.h>
21#include <delay.h>
22#include <device/device.h>
23#include <device/pci.h>
24#include <device/pci_ids.h>
Damien Zammit51fdb922016-01-18 18:34:52 +110025#include <device/pci_ops.h>
Damien Zammit51fdb922016-01-18 18:34:52 +110026
27#include <drivers/intel/gma/i915_reg.h>
28#include "chip.h"
29#include "pineview.h"
30#include <drivers/intel/gma/intel_bios.h>
31#include <drivers/intel/gma/i915.h>
Patrick Rudolphbb98b382017-09-30 09:13:53 +020032#include <drivers/intel/gma/opregion.h>
33#include <southbridge/intel/i82801gx/nvs.h>
34#include <cbmem.h>
Damien Zammit51fdb922016-01-18 18:34:52 +110035#include <pc80/vga.h>
36#include <pc80/vga_io.h>
37
38#define GTTSIZE (512*1024)
39
40#define PGETBL2_CTL 0x20c4
41#define PGETBL2_1MB (1 << 8)
42
43#define PGETBL_CTL 0x2020
44#define PGETBL_1MB (3 << 1)
45#define PGETBL_512KB 0
46#define PGETBL_ENABLED 0x1
47
48#define ADPA_HOTPLUG_BITS (ADPA_CRT_HOTPLUG_PERIOD_128 | \
Elyes HAOUAS6e8b3c12016-09-02 19:22:00 +020049 ADPA_CRT_HOTPLUG_WARMUP_10MS | \
50 ADPA_CRT_HOTPLUG_MONITOR_COLOR| \
51 ADPA_CRT_HOTPLUG_SAMPLE_4S | \
52 ADPA_CRT_HOTPLUG_VOLTAGE_50 | \
53 ADPA_CRT_HOTPLUG_VOLREF_325MV | \
54 ADPA_CRT_HOTPLUG_ENABLE)
Damien Zammit51fdb922016-01-18 18:34:52 +110055
56static struct resource *gtt_res = NULL;
57static struct resource *mmio_res = NULL;
58
Patrick Rudolphbb98b382017-09-30 09:13:53 +020059uintptr_t gma_get_gnvs_aslb(const void *gnvs)
60{
61 const global_nvs_t *gnvs_ptr = gnvs;
62 return (uintptr_t)(gnvs_ptr ? gnvs_ptr->aslb : 0);
63}
64
65void gma_set_gnvs_aslb(void *gnvs, uintptr_t aslb)
66{
67 global_nvs_t *gnvs_ptr = gnvs;
68 if (gnvs_ptr)
69 gnvs_ptr->aslb = aslb;
70}
71
Damien Zammit51fdb922016-01-18 18:34:52 +110072static int gtt_setup(u8 *mmiobase)
73{
Elyes HAOUAS6e8b3c12016-09-02 19:22:00 +020074 u32 gttbase;
Kyösti Mälkkic70eed12018-05-22 02:18:00 +030075 struct device *dev = pcidev_on_root(0, 0);
Damien Zammit51fdb922016-01-18 18:34:52 +110076
Elyes HAOUAS6e8b3c12016-09-02 19:22:00 +020077 gttbase = pci_read_config32(dev, BGSM);
78 printk(BIOS_DEBUG, "gttbase = %08x\n", gttbase);
Damien Zammit51fdb922016-01-18 18:34:52 +110079
Elyes HAOUAS6e8b3c12016-09-02 19:22:00 +020080 write32(mmiobase + PGETBL_CTL, gttbase | PGETBL_512KB);
81 udelay(50);
82 write32(mmiobase + PGETBL_CTL, gttbase | PGETBL_512KB);
Damien Zammit51fdb922016-01-18 18:34:52 +110083
Elyes HAOUAS6e8b3c12016-09-02 19:22:00 +020084 write32(mmiobase + GFX_FLSH_CNTL, 0);
Damien Zammit51fdb922016-01-18 18:34:52 +110085
Elyes HAOUAS6e8b3c12016-09-02 19:22:00 +020086 return 0;
Damien Zammit51fdb922016-01-18 18:34:52 +110087}
88
89static void intel_gma_init(const struct northbridge_intel_pineview_config *info,
90 struct device *vga, u8 *mmio, u8 *gtt, u32 physbase, u16 piobase)
91{
92 int i;
93 u32 hactive, vactive;
94 u32 temp;
95
96 printk(BIOS_SPEW, "gtt %x mmio %x addrport %x physbase %x\n",
97 (u32)gtt, (u32)mmio, piobase, physbase);
98
99 gtt_setup(mmio);
100
Elyes HAOUASef20ecc2018-10-04 13:50:14 +0200101 pci_write_config16(vga, GGC, 0x130);
Damien Zammit51fdb922016-01-18 18:34:52 +1100102
103 /* Disable VGA. */
104 write32(mmio + VGACNTRL, VGA_DISP_DISABLE);
105
106 /* Disable pipes. */
107 write32(mmio + PIPECONF(0), 0);
108 write32(mmio + PIPECONF(1), 0);
109
110 write32(mmio + INSTPM, 0x800);
111
112 vga_gr_write(0x18, 0);
113
114 write32(mmio + VGA0, 0x200074);
115 write32(mmio + VGA1, 0x200074);
116
117 write32(mmio + DSPFW3, 0x7f3f00c1 & ~PINEVIEW_SELF_REFRESH_EN);
118 write32(mmio + DSPCLK_GATE_D, 0);
119 write32(mmio + FW_BLC, 0x03060106);
120 write32(mmio + FW_BLC2, 0x00000306);
121
122 write32(mmio + ADPA, ADPA_DAC_ENABLE
123 | ADPA_PIPE_A_SELECT
124 | ADPA_HOTPLUG_BITS
125 | ADPA_USE_VGA_HVPOLARITY
126 | ADPA_VSYNC_CNTL_ENABLE
127 | ADPA_HSYNC_CNTL_ENABLE
128 | ADPA_DPMS_ON
129 );
130
131 write32(mmio + 0x7041c, 0x0);
132
133 write32(mmio + DPLL_MD(0), 0x3);
134 write32(mmio + DPLL_MD(1), 0x3);
135 write32(mmio + DSPCNTR(1), 0x1000000);
136 write32(mmio + PIPESRC(1), 0x027f01df);
137
138 vga_misc_write(0x67);
139 const u8 cr[] = { 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
140 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
141 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3,
142 0xff
143 };
144 vga_cr_write(0x11, 0);
145
146 for (i = 0; i <= 0x18; i++)
147 vga_cr_write(i, cr[i]);
148
149 // Disable screen memory to prevent garbage from appearing.
150 vga_sr_write(1, vga_sr_read(1) | 0x20);
151 hactive = 640;
152 vactive = 400;
153
154 mdelay(1);
155 write32(mmio + DPLL(0),
156 DPLL_VCO_ENABLE | DPLLB_MODE_DAC_SERIAL
157 | DPLL_VGA_MODE_DIS
158 | DPLL_DAC_SERIAL_P2_CLOCK_DIV_10
159 | 0x400601
160 );
161 mdelay(1);
162 write32(mmio + DPLL(0),
163 DPLL_VCO_ENABLE | DPLLB_MODE_DAC_SERIAL
164 | DPLL_VGA_MODE_DIS
165 | DPLL_DAC_SERIAL_P2_CLOCK_DIV_10
166 | 0x400601
167 );
168
169 write32(mmio + ADPA, ADPA_DAC_ENABLE
170 | ADPA_PIPE_A_SELECT
171 | ADPA_HOTPLUG_BITS
172 | ADPA_USE_VGA_HVPOLARITY
173 | ADPA_VSYNC_CNTL_ENABLE
174 | ADPA_HSYNC_CNTL_ENABLE
175 | ADPA_DPMS_ON
176 );
177
178 write32(mmio + HTOTAL(1), 0x031f027f);
179 write32(mmio + HBLANK(1), 0x03170287);
180 write32(mmio + HSYNC(1), 0x02ef028f);
181 write32(mmio + VTOTAL(1), 0x020c01df);
182 write32(mmio + VBLANK(1), 0x020401e7);
183 write32(mmio + VSYNC(1), 0x01eb01e9);
184
185 write32(mmio + HTOTAL(0),
186 ((hactive - 1) << 16)
187 | (hactive - 1));
188 write32(mmio + HBLANK(0),
189 ((hactive - 1) << 16)
190 | (hactive - 1));
191 write32(mmio + HSYNC(0),
192 ((hactive - 1) << 16)
193 | (hactive - 1));
194
195 write32(mmio + VTOTAL(0), ((vactive - 1) << 16)
196 | (vactive - 1));
197 write32(mmio + VBLANK(0), ((vactive - 1) << 16)
198 | (vactive - 1));
199 write32(mmio + VSYNC(0),
200 ((vactive - 1) << 16)
201 | (vactive - 1));
202
203 write32(mmio + PF_WIN_POS(0), 0);
204
205 write32(mmio + PIPESRC(0), (639 << 16) | 399);
206 write32(mmio + PF_CTL(0),PF_ENABLE | PF_FILTER_MED_3x3);
207 write32(mmio + PF_WIN_SZ(0), vactive | (hactive << 16));
208 write32(mmio + PFIT_CONTROL, 0x0);
209
210 mdelay(1);
211
212 write32(mmio + FDI_RX_CTL(0), 0x00002040);
213 mdelay(1);
214 write32(mmio + FDI_RX_CTL(0), 0x80002050);
215 write32(mmio + FDI_TX_CTL(0), 0x00044000);
216 mdelay(1);
217 write32(mmio + FDI_TX_CTL(0), 0x80044000);
218 write32(mmio + PIPECONF(0), PIPECONF_ENABLE | PIPECONF_BPP_6 | PIPECONF_DITHER_EN);
219
220 write32(mmio + VGACNTRL, 0x0);
221 write32(mmio + DSPCNTR(0), DISPLAY_PLANE_ENABLE | DISPPLANE_BGRX888);
222 mdelay(1);
223
224 write32(mmio + ADPA, ADPA_DAC_ENABLE
225 | ADPA_PIPE_A_SELECT
226 | ADPA_HOTPLUG_BITS
227 | ADPA_USE_VGA_HVPOLARITY
228 | ADPA_VSYNC_CNTL_ENABLE
229 | ADPA_HSYNC_CNTL_ENABLE
230 | ADPA_DPMS_ON
231 );
232
233 write32(mmio + DSPFW3, 0x7f3f00c1);
234 write32(mmio + MI_MODE, 0x200 | VS_TIMER_DISPATCH);
235 write32(mmio + CACHE_MODE_0, (0x6820 | (1 << 9)) & ~(1 << 5));
236 write32(mmio + CACHE_MODE_1, 0x380 & ~(1 << 9));
237
238 for (i = 0; i < (8192 - 512) / 4; i++) {
239 outl((i << 2) | 1, piobase);
240 outl(physbase + (i << 12) + 1, piobase + 4);
241 }
242
243 temp = read32(mmio + PGETBL_CTL);
244 printk(BIOS_INFO, "GTT PGETBL_CTL register : 0x%08x\n", temp);
245 temp = read32(mmio + PGETBL2_CTL);
246 printk(BIOS_INFO, "GTT PGETBL2_CTL register: 0x%08x\n", temp);
247
248 /* Clear interrupts. */
249 write32(mmio + DEIIR, 0xffffffff);
250 write32(mmio + SDEIIR, 0xffffffff);
251 write32(mmio + IIR, 0xffffffff);
252 write32(mmio + IMR, 0xffffffff);
253 write32(mmio + EIR, 0xffffffff);
254
255 vga_textmode_init();
256
257 /* Enable screen memory. */
258 vga_sr_write(1, vga_sr_read(1) & ~0x20);
259}
260
261static void gma_func0_init(struct device *dev)
262{
263 u32 reg32;
264
265 /* IGD needs to be Bus Master */
266 reg32 = pci_read_config32(dev, PCI_COMMAND);
267 reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
268 pci_write_config32(dev, PCI_COMMAND, reg32);
269
Julius Wernercd49cce2019-03-05 16:53:33 -0800270 if (!CONFIG(MAINBOARD_DO_NATIVE_VGA_INIT)) {
Damien Zammit51fdb922016-01-18 18:34:52 +1100271 /* PCI Init, will run VBIOS */
272 pci_dev_init(dev);
273 } else {
274 u32 physbase;
275 struct resource *pio_res;
276 struct northbridge_intel_pineview_config *conf = dev->chip_info;
277
Arthur Heymanse6c8f7e2018-08-09 11:31:51 +0200278 int vga_disable = (pci_read_config16(dev, GGC) & 2) >> 1;
279
Damien Zammit51fdb922016-01-18 18:34:52 +1100280 /* Find base addresses */
281 mmio_res = find_resource(dev, 0x10);
282 gtt_res = find_resource(dev, 0x1c);
283 pio_res = find_resource(dev, 0x14);
284 physbase = pci_read_config32(dev, 0x5c) & ~0xf;
285
286 if (gtt_res && gtt_res->base && physbase && pio_res && pio_res->base) {
Arthur Heymanse6c8f7e2018-08-09 11:31:51 +0200287 if (vga_disable) {
288 printk(BIOS_INFO,
289 "IGD is not decoding legacy VGA MEM and IO: skipping NATIVE graphic init\n");
290 } else {
291 printk(BIOS_SPEW, "Initializing VGA. MMIO 0x%llx\n",
292 mmio_res->base);
293 intel_gma_init(conf, dev,
294 res2mmio(mmio_res, 0, 0),
295 res2mmio(gtt_res, 0, 0),
296 physbase, pio_res->base);
297 }
Damien Zammit51fdb922016-01-18 18:34:52 +1100298 }
299
300 /* Linux relies on VBT for panel info. */
Arthur Heymansd3284a62016-09-25 22:48:00 +0200301 generate_fake_intel_oprom(&conf->gfx, dev, "$VBT PINEVIEW");
Damien Zammit51fdb922016-01-18 18:34:52 +1100302 }
Patrick Rudolphbb98b382017-09-30 09:13:53 +0200303
304 intel_gma_restore_opregion();
Damien Zammit51fdb922016-01-18 18:34:52 +1100305}
306
Damien Zammit51fdb922016-01-18 18:34:52 +1100307const struct i915_gpu_controller_info *intel_gma_get_controller_info(void)
308{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300309 struct device *dev = pcidev_on_root(0x2, 0);
Damien Zammit51fdb922016-01-18 18:34:52 +1100310 if (!dev) {
311 printk(BIOS_WARNING, "WARNING: Can't find IGD (0,2,0)\n");
312 return NULL;
313 }
314 struct northbridge_intel_pineview_config *chip = dev->chip_info;
315 return &chip->gfx;
316}
317
Patrick Rudolphbb98b382017-09-30 09:13:53 +0200318static unsigned long
319gma_write_acpi_tables(struct device *const dev,
320 unsigned long current,
321 struct acpi_rsdp *const rsdp)
322{
323 igd_opregion_t *opregion = (igd_opregion_t *)current;
324 global_nvs_t *gnvs;
325
326 if (intel_gma_init_igd_opregion(opregion) != CB_SUCCESS)
327 return current;
328
329 current += sizeof(igd_opregion_t);
330
331 /* GNVS has been already set up */
332 gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS);
333 if (gnvs) {
334 /* IGD OpRegion Base Address */
335 gma_set_gnvs_aslb(gnvs, (uintptr_t)opregion);
336 } else {
337 printk(BIOS_ERR, "Error: GNVS table not found.\n");
338 }
339
340 current = acpi_align_current(current);
341 return current;
342}
343
344static const char *gma_acpi_name(const struct device *dev)
345{
346 return "GFX0";
347}
348
Damien Zammit51fdb922016-01-18 18:34:52 +1100349static struct pci_operations gma_pci_ops = {
Subrata Banik4a0f0712019-03-20 14:29:47 +0530350 .set_subsystem = pci_dev_set_subsystem,
Damien Zammit51fdb922016-01-18 18:34:52 +1100351};
352
353static struct device_operations gma_func0_ops = {
354 .read_resources = pci_dev_read_resources,
355 .set_resources = pci_dev_set_resources,
356 .enable_resources = pci_dev_enable_resources,
357 .acpi_fill_ssdt_generator = 0,
358 .init = gma_func0_init,
359 .scan_bus = 0,
360 .enable = 0,
361 .ops_pci = &gma_pci_ops,
Patrick Rudolphbb98b382017-09-30 09:13:53 +0200362 .acpi_name = gma_acpi_name,
363 .write_acpi_tables = gma_write_acpi_tables,
Damien Zammit51fdb922016-01-18 18:34:52 +1100364};
365
366static const unsigned short pci_device_ids[] =
367{
368 0xa001, 0
369};
370
371static const struct pci_driver gma __pci_driver = {
372 .ops = &gma_func0_ops,
373 .vendor = PCI_VENDOR_ID_INTEL,
374 .devices = pci_device_ids,
375};