blob: 494d78a364e94a1d134370ec16f667fe9d47ed37 [file] [log] [blame]
Alexandru Gagniuc23211b02013-06-09 16:06:07 -05001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050015 */
16
17#include <arch/io.h>
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050018#include <console/console.h>
19#include <device/pci.h>
20#include <device/pci_ids.h>
21#include <pc80/vga_io.h>
Alexandru Gagniuc560433b2013-06-10 15:47:25 -050022#include <stdlib.h>
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050023
24#include "vx900.h"
25
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050026/**
27 * @file chrome9hd.c
28 *
29 * \brief Initialization for Chrome9HD integrated graphics adapters
30 *
31 * This takes care of the initialization we need to do before calling the VGA
32 * BIOS. The device is not documented in the VX900 datasheet.
33 *
34 * The device is documented in:
35 * Open Graphics Programming Manual
36 * Chrome9GraphicsHD Processor
37 * VX900 Series System Processor
38 * Part I: Graphics Core / 2D
39 *
40 * This document was released by VIA to the Xorg project, and is available at:
41 * <http://www.x.org/docs/via/OGPM_Chrome9%20HD%20DX9%20_R100_PartI_Core_2D.pdf>
42 *
43 * STATUS:
44 * We do the minimal initialization described in VIA documents. Running the VGA
45 * option ROM does not get us a usable display. We configure the framebuffer and
46 * the IGP is able to use it. GRUB2 and linux are capable of getting a usable
47 * text console, which uses the monitor's native resolution (even 1920x1080).
48 * The graphical console (linux) does not work properly.
Martin Roth543888d2015-01-06 10:20:42 -070049 * @todo
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050050 * 1. Figure out what sequence we need to do to get the VGA BIOS running
51 * properly. Use the code provided by VIA and compare their sequence to ours,
52 * fill in any missing steps, etc.
53 * 2. Make BAR2 and the framebuffer use the same memory space. This is a feature
54 * called "Direct framebuffer access" which allows us to save memory space by
55 * setting BAR2 of the VGA to the location in memory of the framebuffer. This
56 * reduces the amount of PCI MMIO space we need below 4G, and is especially
57 * useful considering we only have 8GB (33 bits) of memory-mapped space.
58 */
59
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050060/**
Martin Roth6e222252014-12-29 14:44:38 -070061 * vx900_int15
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050062 *
63 * \brief INT15 helpers for Chrome9HD IGP
64 *
65 * The following are helpers for INT15 handlers for the VGA BIOS. The full set
66 * of INT15 callbacks is described in
67 *
68 * VIA/S3Graphics
69 * Video BIOS External Interface Specification for Chrome9 Series IGP
70 * VX900 Series
71 *
72 * This document is only available under NDA, however, the callbacks are very
73 * similar to other VIA/Intel IGP callbacks.
74 *
75 * Callback 0x5f18 is the most important one. It informs the VGA BIOS of the
76 * RAM speed and framebuffer size. The other callbacks seem to be optional.
77 * @{
78 */
79
80/**
81 * \brief Get X86_BL value for VGA INT15 function 5f18
82 *
83 * Int15 5f18 lets the VGA BIOS know the framebuffer size and the memory speed.
84 * This handler is very important. If it is not implemented, the VGA BIOS will
85 * not work correctly.
86 *
87 * To use, just call this from the 15f18 handler, and place the return value in
88 * X86_BL
89 *
90 * @code{.c}
91 * case 0x5f18:
92 * X86_BX = vx900_int15_get_5f18_bl();
93 * res = 0;
94 * break;
95 * @endcode
96 *
97 */
98u8 vx900_int15_get_5f18_bl(void)
99{
100 u8 reg8, ret;
Elyes HAOUAS2a5f6cb2018-05-25 08:09:53 +0200101 struct device *dev;
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500102 /*
103 * BL Bit[7:4]
104 * Memory Data Rate (not to be confused with fCLK)
105 * 0000: 66MHz
106 * 0001: 100MHz
107 * 0010: 133MHz
Elyes HAOUASa342f392018-10-17 10:56:26 +0200108 * 0011: 200MHz (DDR200)
109 * 0100: 266MHz (DDR266)
110 * 0101: 333MHz (DDR333)
111 * 0110: 400MHz (DDR400)
112 * 0111: 533MHz (DDR I/II 533)
113 * 1000: 667MHz (DDR I/II 667)
114 * 1001: 800MHz (DDR3 800)
115 * 1010: 1066MHz (DDR3 1066)
116 * 1011: 1333MHz (DDR3 1333)
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500117 * Bit[3:0]
118 * N: Frame Buffer Size 2^N MB
119 */
120 dev = dev_find_slot(0, PCI_DEVFN(0, 3));
121 reg8 = pci_read_config8(dev, 0xa1);
122 ret = (u32) ((reg8 & 0x70) >> 4) + 2;
123 reg8 = pci_read_config8(dev, 0x90);
124 reg8 = ((reg8 & 0x07) + 3) << 4;
125 ret |= (u32) reg8;
126
127 return ret;
128}
Alexandru Gagniuc560433b2013-06-10 15:47:25 -0500129
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500130/** @} */
131
132static void chrome9hd_set_sid_vid(u16 vendor, u16 device)
133{
134 vga_sr_write(0x36, vendor >> 8); /* SVID high byte */
135 vga_sr_write(0x35, vendor & 0xff); /* SVID low byte */
136 vga_sr_write(0x38, device >> 8); /* SID high byte */
137 vga_sr_write(0x37, device & 0xff); /* SID low byte */
138}
139
Elyes HAOUAS2a5f6cb2018-05-25 08:09:53 +0200140static void chrome9hd_handle_uma(struct device *dev)
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500141{
Lubomir Rinteld8ec9732017-12-28 01:48:09 +0100142 u8 fb_pow = vx900_get_chrome9hd_fb_pow();
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500143
Lubomir Rinteld8ec9732017-12-28 01:48:09 +0100144 if (fb_pow == 0)
145 return;
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500146
147 /* Step 7 - Let GFX know the framebuffer size (through PCI and IOCTL)
148 * The size we set here affects the behavior of BAR2, and the amount of
149 * MMIO space it requests. The default is 512MB, so if we don't set this
150 * before reading the resources, we could waste space below 4G */
151 pci_write_config8(dev, 0xb2, ((0xff << (fb_pow - 2)) & ~(1 << 7)));
152 vga_sr_write(0x68, (0xff << (fb_pow - 1)));
153 /* And also that the framebuffer is in the system, RAM */
154 pci_mod_config8(dev, 0xb0, 0, 1 << 0);
155}
156
157/**
158 * \brief Initialization sequence before running the VGA BIOS
159 *
160 * This is the initialization sequence described in:
161 *
162 * BIOS Porting Guide
163 * VX900 Series
164 * All-in-One System Processor
165 *
166 * This document is only available under NDA.
167 */
Elyes HAOUAS2a5f6cb2018-05-25 08:09:53 +0200168static void chrome9hd_biosguide_init_seq(struct device *dev)
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500169{
Elyes HAOUAS2a5f6cb2018-05-25 08:09:53 +0200170 struct device *mcu = dev_find_device(PCI_VENDOR_ID_VIA,
171 PCI_DEVICE_ID_VIA_VX900_MEMCTRL, 0);
172 struct device *host = dev_find_device(PCI_VENDOR_ID_VIA,
173 PCI_DEVICE_ID_VIA_VX900_HOST_BR, 0);
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500174
175 /* Step 1 - Enable VGA controller */
176 /* FIXME: This is the VGA hole @ 640k-768k, and the vga port io
177 * We need the port IO, but can we disable the memory hole? */
178 pci_mod_config8(mcu, 0xa4, 0, (1 << 7)); /* VGA memory hole */
179
180 /* Step 2 - Forward MDA cycles to GFX */
181 pci_mod_config8(host, 0x4e, 0, (1 << 1));
182
183 /* Step 3 - Enable GFX I/O space */
184 pci_mod_config8(dev, PCI_COMMAND, 0, PCI_COMMAND_IO);
185
186 /* Step 4 - Enable video subsystem */
187 vga_enable_mask((1 << 0), (1 << 0));
188
189 /* FIXME: VGA IO Address Select. 3B5 or 3D5? */
190 vga_misc_mask((1 << 0), (1 << 0));
191
192 /* Step 5 - Unlock accessing of IO space */
193 vga_sr_write(0x10, 0x01);
194
195 chrome9hd_handle_uma(dev);
196
Kyösti Mälkki5cf88242013-10-18 11:02:56 +0300197 uint64_t gfx_base = get_uma_memory_base();
198 if (gfx_base == 0)
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500199 die("uma_memory_base not set. Abandon ship!\n");
Kyösti Mälkki5cf88242013-10-18 11:02:56 +0300200
201 /* Step 8 - Enable memory base register on the GFX */
202 vga_sr_write(0x6d, (gfx_base >> 21) & 0xff); /* base 28:21 */
203 vga_sr_write(0x6e, (gfx_base >> 29) & 0xff); /* base 36:29 */
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500204 vga_sr_write(0x6f, 0x00); /* base 43:37 */
205
206 /* Step 9 - Set SID/VID */
207 chrome9hd_set_sid_vid(0x1106, 0x7122);
208
209}
210
Elyes HAOUAS2a5f6cb2018-05-25 08:09:53 +0200211static void chrome9hd_init(struct device *dev)
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500212{
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800213 printk(BIOS_DEBUG, "======================================================\n");
214 printk(BIOS_DEBUG, "== Chrome9 HD INIT\n");
215 printk(BIOS_DEBUG, "======================================================\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500216
217 chrome9hd_biosguide_init_seq(dev);
218
219 /* Prime PLL FIXME: bad comment */
220 vga_sr_mask(0x3c, 1 << 2, 1 << 2);
221
222 /* FIXME: recheck; VGA IO Address Select. 3B5 or 3D5? */
223 vga_misc_mask(1 << 0, 1 << 0);
224
225 /* FIXME: recheck; Enable Base VGA 16 Bits Decode */
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500226
227 u32 fb_address = pci_read_config32(dev, PCI_BASE_ADDRESS_2);
228 fb_address &= ~0x0F;
229 if (!fb_address) {
230 printk(BIOS_WARNING, "Chrome9HD: No FB BAR assigned!\n");
231 return;
232 }
233
234 printk(BIOS_INFO, "Chrome: Using %dMB Framebuffer at 0x%08X.\n",
235 256, fb_address);
236
237 printk(BIOS_DEBUG, "Initializing VGA...\n");
238
239 pci_dev_init(dev);
240
241 printk(BIOS_DEBUG, "Enable VGA console\n");
242
243 dump_pci_device(dev);
244}
245
Elyes HAOUAS2a5f6cb2018-05-25 08:09:53 +0200246static void chrome9hd_enable(struct device *dev)
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500247{
Elyes HAOUAS2a5f6cb2018-05-25 08:09:53 +0200248 struct device *mcu = dev_find_device(PCI_VENDOR_ID_VIA,
249 PCI_DEVICE_ID_VIA_VX900_MEMCTRL, 0);
Elyes HAOUAS0f92f632014-07-27 19:37:31 +0200250 /* FIXME: here? -=- ACLK 250MHz */
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500251 pci_mod_config8(mcu, 0xbb, 0, 0x01);
252}
253
Elyes HAOUAS2a5f6cb2018-05-25 08:09:53 +0200254static void chrome9hd_disable(struct device *dev)
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500255{
Elyes HAOUAS2a5f6cb2018-05-25 08:09:53 +0200256 struct device *mcu = dev_find_device(PCI_VENDOR_ID_VIA,
257 PCI_DEVICE_ID_VIA_VX900_MEMCTRL, 0);
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500258 /* Disable GFX - This step effectively renders the GFX inert
259 * It won't even show up as a PCI device during enumeration */
260 pci_mod_config8(mcu, 0xa1, 1 << 7, 0);
261}
262
263static struct device_operations chrome9hd_operations = {
264 .read_resources = pci_dev_read_resources,
265 .set_resources = pci_dev_set_resources,
266 .enable_resources = pci_dev_enable_resources,
267 .init = chrome9hd_init,
268 .disable = chrome9hd_disable,
269 .enable = chrome9hd_enable,
270 .ops_pci = 0,
271};
272
273static const struct pci_driver chrome9hd_driver __pci_driver = {
274 .ops = &chrome9hd_operations,
275 .vendor = PCI_VENDOR_ID_VIA,
276 .device = PCI_DEVICE_ID_VIA_VX900_VGA,
277};