1 /* This file is part of the coreboot project. */
2 /* SPDX-License-Identifier: GPL-2.0-or-later */
6 #include <console/console.h>
7 #include <device/device.h>
8 #include <device/pci.h>
9 #include <device/pci_ops.h>
11 #include <pc80/vga_io.h>
13 static int width
= CONFIG_DRIVERS_EMULATION_QEMU_BOCHS_XRES
;
14 static int height
= CONFIG_DRIVERS_EMULATION_QEMU_BOCHS_YRES
;
20 VGA_CR_HORIZ_END
= 0x01,
21 VGA_CR_HBLANK_START
= 0x02,
22 VGA_CR_HBLANK_END
= 0x03,
23 VGA_CR_HORIZ_SYNC_PULSE_START
= 0x04,
24 VGA_CR_HORIZ_SYNC_PULSE_END
= 0x05,
25 VGA_CR_VERT_TOTAL
= 0x06,
26 VGA_CR_OVERFLOW
= 0x07,
27 VGA_CR_BYTE_PANNING
= 0x08,
28 VGA_CR_CELL_HEIGHT
= 0x09,
29 VGA_CR_CURSOR_START
= 0x0a,
30 VGA_CR_CURSOR_END
= 0x0b,
31 VGA_CR_START_ADDR_HIGH_REGISTER
= 0x0c,
32 VGA_CR_START_ADDR_LOW_REGISTER
= 0x0d,
33 VGA_CR_CURSOR_ADDR_HIGH
= 0x0e,
34 VGA_CR_CURSOR_ADDR_LOW
= 0x0f,
35 VGA_CR_VSYNC_START
= 0x10,
36 VGA_CR_VSYNC_END
= 0x11,
37 VGA_CR_VDISPLAY_END
= 0x12,
39 VGA_CR_UNDERLINE_LOCATION
= 0x14,
40 VGA_CR_VERTICAL_BLANK_START
= 0x15,
41 VGA_CR_VERTICAL_BLANK_END
= 0x16,
43 VGA_CR_LINE_COMPARE
= 0x18,
46 #define VGA_IO_MISC_COLOR 0x01
48 #define VGA_CR_WIDTH_DIVISOR 8
50 #define VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END1_SHIFT 7
51 #define VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END1_MASK 0x02
52 #define VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END2_SHIFT 3
53 #define VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END2_MASK 0x40
55 #define VGA_CR_OVERFLOW_VERT_TOTAL1_SHIFT 8
56 #define VGA_CR_OVERFLOW_VERT_TOTAL1_MASK 0x01
57 #define VGA_CR_OVERFLOW_VERT_TOTAL2_SHIFT 4
58 #define VGA_CR_OVERFLOW_VERT_TOTAL2_MASK 0x20
60 #define VGA_CR_OVERFLOW_VSYNC_START1_SHIFT 6
61 #define VGA_CR_OVERFLOW_VSYNC_START1_MASK 0x04
62 #define VGA_CR_OVERFLOW_VSYNC_START2_SHIFT 2
63 #define VGA_CR_OVERFLOW_VSYNC_START2_MASK 0x80
65 #define VGA_CR_OVERFLOW_HEIGHT1_SHIFT 7
66 #define VGA_CR_OVERFLOW_HEIGHT1_MASK 0x02
67 #define VGA_CR_OVERFLOW_HEIGHT2_SHIFT 3
68 #define VGA_CR_OVERFLOW_HEIGHT2_MASK 0xc0
69 #define VGA_CR_OVERFLOW_LINE_COMPARE_SHIFT 4
70 #define VGA_CR_OVERFLOW_LINE_COMPARE_MASK 0x10
72 #define VGA_CR_CELL_HEIGHT_LINE_COMPARE_MASK 0x40
73 #define VGA_CR_CELL_HEIGHT_LINE_COMPARE_SHIFT 3
74 #define VGA_CR_CELL_HEIGHT_VERTICAL_BLANK_MASK 0x20
75 #define VGA_CR_CELL_HEIGHT_VERTICAL_BLANK_SHIFT 4
76 #define VGA_CR_CELL_HEIGHT_DOUBLE_SCAN 0x80
79 VGA_CR_CURSOR_START_DISABLE
= (1 << 5)
82 #define VGA_CR_PITCH_DIVISOR 8
86 VGA_CR_MODE_NO_CGA
= 0x01,
87 VGA_CR_MODE_NO_HERCULES
= 0x02,
88 VGA_CR_MODE_ADDRESS_WRAP
= 0x20,
89 VGA_CR_MODE_BYTE_MODE
= 0x40,
90 VGA_CR_MODE_TIMING_ENABLE
= 0x80
96 VGA_SR_CLOCKING_MODE
= 1,
97 VGA_SR_MAP_MASK_REGISTER
= 2,
98 VGA_SR_CHAR_MAP_SELECT
= 3,
99 VGA_SR_MEMORY_MODE
= 4,
104 VGA_SR_RESET_ASYNC
= 1,
105 VGA_SR_RESET_SYNC
= 2
110 VGA_SR_CLOCKING_MODE_8_DOT_CLOCK
= 1
115 VGA_SR_MEMORY_MODE_NORMAL
= 0,
116 VGA_SR_MEMORY_MODE_EXTERNAL_VIDEO_MEMORY
= 2,
117 VGA_SR_MEMORY_MODE_SEQUENTIAL_ADDRESSING
= 4,
118 VGA_SR_MEMORY_MODE_CHAIN4
= 8,
123 VGA_GR_SET_RESET_PLANE
= 0,
124 VGA_GR_SET_RESET_PLANE_ENABLE
= 1,
125 VGA_GR_COLOR_COMPARE
= 2,
126 VGA_GR_READ_MAP_REGISTER
= 4,
129 VGA_GR_COLOR_COMPARE_DISABLE
= 7,
136 VGA_TEXT_TEXT_PLANE
= 0,
137 VGA_TEXT_ATTR_PLANE
= 1,
138 VGA_TEXT_FONT_PLANE
= 2
143 VGA_GR_GR6_GRAPHICS_MODE
= 1,
144 VGA_GR_GR6_MMAP_A0
= (1 << 2),
145 VGA_GR_GR6_MMAP_CGA
= (3 << 2)
150 VGA_GR_MODE_READ_MODE1
= 0x08,
151 VGA_GR_MODE_ODD_EVEN
= 0x10,
152 VGA_GR_MODE_ODD_EVEN_SHIFT
= 0x20,
153 VGA_GR_MODE_256_COLOR
= 0x40
156 #define CIRRUS_CR_EXTENDED_DISPLAY 0x1b
157 #define CIRRUS_CR_EXTENDED_OVERLAY 0x1d
159 #define CIRRUS_CR_EXTENDED_DISPLAY_PITCH_MASK 0x10
160 #define CIRRUS_CR_EXTENDED_DISPLAY_PITCH_SHIFT 4
161 #define CIRRUS_CR_EXTENDED_DISPLAY_START_MASK1 0x1
162 #define CIRRUS_CR_EXTENDED_DISPLAY_START_SHIFT1 16
163 #define CIRRUS_CR_EXTENDED_DISPLAY_START_MASK2 0xc
164 #define CIRRUS_CR_EXTENDED_DISPLAY_START_SHIFT2 15
166 #define CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_MASK 0x80
167 #define CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_SHIFT 12
168 #define CIRRUS_SR_EXTENDED_MODE 7
169 #define CIRRUS_SR_EXTENDED_MODE_LFB_ENABLE 0xf0
170 #define CIRRUS_SR_EXTENDED_MODE_ENABLE_EXT 0x01
171 #define CIRRUS_SR_EXTENDED_MODE_32BPP 0x08
172 #define CIRRUS_HIDDEN_DAC_888COLOR 0xc5
175 write_hidden_dac (uint8_t data
)
185 static void cirrus_init_linear_fb(struct device
*dev
)
187 uint8_t cr_ext
, cr_overlay
;
188 unsigned int pitch
= (width
* 4) / VGA_CR_PITCH_DIVISOR
;
189 uint8_t sr_ext
= 0, hidden_dac
= 0;
190 unsigned int vdisplay_end
= height
- 2;
191 unsigned int line_compare
= 0x3ff;
192 uint8_t overflow
, cell_height_reg
;
193 unsigned int horizontal_end
= width
/ VGA_CR_WIDTH_DIVISOR
;
194 unsigned int horizontal_total
= horizontal_end
+ 40;
195 unsigned int horizontal_blank_start
= horizontal_end
;
196 unsigned int horizontal_sync_pulse_start
= horizontal_end
+ 3;
197 unsigned int horizontal_sync_pulse_end
= 0;
199 unsigned int horizontal_blank_end
= 0;
200 unsigned int vertical_blank_start
= height
+ 1;
201 unsigned int vertical_blank_end
= 0;
202 unsigned int vertical_sync_start
= height
+ 3;
203 unsigned int vertical_sync_end
= 0;
204 unsigned int vertical_total
= height
+ 40;
206 /* find lfb pci bar */
207 addr
= pci_read_config32(dev
, PCI_BASE_ADDRESS_0
);
208 addr
&= ~PCI_BASE_ADDRESS_MEM_ATTR_MASK
;
209 printk(BIOS_DEBUG
, "QEMU VGA: cirrus framebuffer @ %x (pci bar 0)\n",
212 vga_misc_write (VGA_IO_MISC_COLOR
);
214 vga_sr_write (VGA_SR_MEMORY_MODE
,
215 VGA_SR_MEMORY_MODE_NORMAL
);
217 vga_sr_write (VGA_SR_MAP_MASK_REGISTER
,
218 (1 << VGA_TEXT_TEXT_PLANE
)
219 | (1 << VGA_TEXT_ATTR_PLANE
));
221 vga_sr_write (VGA_SR_CLOCKING_MODE
,
222 VGA_SR_CLOCKING_MODE_8_DOT_CLOCK
);
224 vga_palette_disable();
226 /* Disable CR0-7 write protection. */
227 vga_cr_write (VGA_CR_VSYNC_END
, 0);
229 overflow
= ((vertical_total
>> VGA_CR_OVERFLOW_VERT_TOTAL1_SHIFT
)
230 & VGA_CR_OVERFLOW_VERT_TOTAL1_MASK
)
231 | ((vertical_total
>> VGA_CR_OVERFLOW_VERT_TOTAL2_SHIFT
)
232 & VGA_CR_OVERFLOW_VERT_TOTAL2_MASK
)
233 | ((vertical_sync_start
>> VGA_CR_OVERFLOW_VSYNC_START2_SHIFT
)
234 & VGA_CR_OVERFLOW_VSYNC_START2_MASK
)
235 | ((vertical_sync_start
>> VGA_CR_OVERFLOW_VSYNC_START1_SHIFT
)
236 & VGA_CR_OVERFLOW_VSYNC_START1_MASK
)
237 | ((vdisplay_end
>> VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END1_SHIFT
)
238 & VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END1_MASK
)
239 | ((vdisplay_end
>> VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END2_SHIFT
)
240 & VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END2_MASK
)
241 | ((vertical_sync_start
>> VGA_CR_OVERFLOW_VSYNC_START1_SHIFT
)
242 & VGA_CR_OVERFLOW_VSYNC_START1_MASK
)
243 | ((line_compare
>> VGA_CR_OVERFLOW_LINE_COMPARE_SHIFT
)
244 & VGA_CR_OVERFLOW_LINE_COMPARE_MASK
);
246 cell_height_reg
= ((vertical_blank_start
247 >> VGA_CR_CELL_HEIGHT_VERTICAL_BLANK_SHIFT
)
248 & VGA_CR_CELL_HEIGHT_VERTICAL_BLANK_MASK
)
249 | ((line_compare
>> VGA_CR_CELL_HEIGHT_LINE_COMPARE_SHIFT
)
250 & VGA_CR_CELL_HEIGHT_LINE_COMPARE_MASK
);
252 vga_cr_write (VGA_CR_HTOTAL
, horizontal_total
- 1);
253 vga_cr_write (VGA_CR_HORIZ_END
, horizontal_end
- 1);
254 vga_cr_write (VGA_CR_HBLANK_START
, horizontal_blank_start
- 1);
255 vga_cr_write (VGA_CR_HBLANK_END
, horizontal_blank_end
);
256 vga_cr_write (VGA_CR_HORIZ_SYNC_PULSE_START
,
257 horizontal_sync_pulse_start
);
258 vga_cr_write (VGA_CR_HORIZ_SYNC_PULSE_END
,
259 horizontal_sync_pulse_end
);
260 vga_cr_write (VGA_CR_VERT_TOTAL
, vertical_total
& 0xff);
261 vga_cr_write (VGA_CR_OVERFLOW
, overflow
);
262 vga_cr_write (VGA_CR_CELL_HEIGHT
, cell_height_reg
);
263 vga_cr_write (VGA_CR_VSYNC_START
, vertical_sync_start
& 0xff);
264 vga_cr_write (VGA_CR_VSYNC_END
, vertical_sync_end
& 0x0f);
265 vga_cr_write (VGA_CR_VDISPLAY_END
, vdisplay_end
& 0xff);
266 vga_cr_write (VGA_CR_PITCH
, pitch
& 0xff);
267 vga_cr_write (VGA_CR_VERTICAL_BLANK_START
, vertical_blank_start
& 0xff);
268 vga_cr_write (VGA_CR_VERTICAL_BLANK_END
, vertical_blank_end
& 0xff);
269 vga_cr_write (VGA_CR_LINE_COMPARE
, line_compare
& 0xff);
271 vga_gr_write (VGA_GR_MODE
, VGA_GR_MODE_256_COLOR
| VGA_GR_MODE_READ_MODE1
);
272 vga_gr_write (VGA_GR_GR6
, VGA_GR_GR6_GRAPHICS_MODE
);
274 vga_sr_write (VGA_SR_MEMORY_MODE
, VGA_SR_MEMORY_MODE_NORMAL
);
276 vga_cr_write (CIRRUS_CR_EXTENDED_DISPLAY
,
277 (pitch
>> CIRRUS_CR_EXTENDED_DISPLAY_PITCH_SHIFT
)
278 & CIRRUS_CR_EXTENDED_DISPLAY_PITCH_MASK
);
280 vga_cr_write (VGA_CR_MODE
, VGA_CR_MODE_TIMING_ENABLE
281 | VGA_CR_MODE_BYTE_MODE
282 | VGA_CR_MODE_NO_HERCULES
| VGA_CR_MODE_NO_CGA
);
284 vga_cr_write (VGA_CR_START_ADDR_LOW_REGISTER
, 0);
285 vga_cr_write (VGA_CR_START_ADDR_HIGH_REGISTER
, 0);
287 cr_ext
= vga_cr_read (CIRRUS_CR_EXTENDED_DISPLAY
);
288 cr_ext
&= ~(CIRRUS_CR_EXTENDED_DISPLAY_START_MASK1
289 | CIRRUS_CR_EXTENDED_DISPLAY_START_MASK2
);
290 vga_cr_write (CIRRUS_CR_EXTENDED_DISPLAY
, cr_ext
);
292 cr_overlay
= vga_cr_read (CIRRUS_CR_EXTENDED_OVERLAY
);
293 cr_overlay
&= ~(CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_MASK
);
294 vga_cr_write (CIRRUS_CR_EXTENDED_OVERLAY
, cr_overlay
);
296 sr_ext
= CIRRUS_SR_EXTENDED_MODE_LFB_ENABLE
297 | CIRRUS_SR_EXTENDED_MODE_ENABLE_EXT
298 | CIRRUS_SR_EXTENDED_MODE_32BPP
;
299 hidden_dac
= CIRRUS_HIDDEN_DAC_888COLOR
;
300 vga_sr_write (CIRRUS_SR_EXTENDED_MODE
, sr_ext
);
301 write_hidden_dac (hidden_dac
);
305 edid
.mode
.ha
= width
;
306 edid
.mode
.va
= height
;
307 edid
.panel_bits_per_color
= 8;
308 edid
.panel_bits_per_pixel
= 24;
309 edid_set_framebuffer_bits_per_pixel(&edid
, 32, 0);
310 set_vbe_mode_info_valid(&edid
, addr
);
313 static void cirrus_init_text_mode(struct device
*dev
)
319 static void cirrus_init(struct device
*dev
)
321 if (CONFIG(LINEAR_FRAMEBUFFER
))
322 cirrus_init_linear_fb(dev
);
323 else if (CONFIG(VGA_TEXT_FRAMEBUFFER
))
324 cirrus_init_text_mode(dev
);
327 static struct device_operations qemu_cirrus_graph_ops
= {
328 .read_resources
= pci_dev_read_resources
,
329 .set_resources
= pci_dev_set_resources
,
330 .enable_resources
= pci_dev_enable_resources
,
334 static const struct pci_driver qemu_cirrus_driver __pci_driver
= {
335 .ops
= &qemu_cirrus_graph_ops
,