1 /* SPDX-License-Identifier: GPL-2.0-or-later */
4 #include <console/console.h>
5 #include <device/device.h>
6 #include <device/pci.h>
7 #include <device/pci_ops.h>
9 #include <pc80/vga_io.h>
10 #include <framebuffer_info.h>
12 static int width
= CONFIG_DRIVERS_EMULATION_QEMU_BOCHS_XRES
;
13 static int height
= CONFIG_DRIVERS_EMULATION_QEMU_BOCHS_YRES
;
19 VGA_CR_HORIZ_END
= 0x01,
20 VGA_CR_HBLANK_START
= 0x02,
21 VGA_CR_HBLANK_END
= 0x03,
22 VGA_CR_HORIZ_SYNC_PULSE_START
= 0x04,
23 VGA_CR_HORIZ_SYNC_PULSE_END
= 0x05,
24 VGA_CR_VERT_TOTAL
= 0x06,
25 VGA_CR_OVERFLOW
= 0x07,
26 VGA_CR_BYTE_PANNING
= 0x08,
27 VGA_CR_CELL_HEIGHT
= 0x09,
28 VGA_CR_CURSOR_START
= 0x0a,
29 VGA_CR_CURSOR_END
= 0x0b,
30 VGA_CR_START_ADDR_HIGH_REGISTER
= 0x0c,
31 VGA_CR_START_ADDR_LOW_REGISTER
= 0x0d,
32 VGA_CR_CURSOR_ADDR_HIGH
= 0x0e,
33 VGA_CR_CURSOR_ADDR_LOW
= 0x0f,
34 VGA_CR_VSYNC_START
= 0x10,
35 VGA_CR_VSYNC_END
= 0x11,
36 VGA_CR_VDISPLAY_END
= 0x12,
38 VGA_CR_UNDERLINE_LOCATION
= 0x14,
39 VGA_CR_VERTICAL_BLANK_START
= 0x15,
40 VGA_CR_VERTICAL_BLANK_END
= 0x16,
42 VGA_CR_LINE_COMPARE
= 0x18,
45 #define VGA_IO_MISC_COLOR 0x01
47 #define VGA_CR_WIDTH_DIVISOR 8
49 #define VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END1_SHIFT 7
50 #define VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END1_MASK 0x02
51 #define VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END2_SHIFT 3
52 #define VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END2_MASK 0x40
54 #define VGA_CR_OVERFLOW_VERT_TOTAL1_SHIFT 8
55 #define VGA_CR_OVERFLOW_VERT_TOTAL1_MASK 0x01
56 #define VGA_CR_OVERFLOW_VERT_TOTAL2_SHIFT 4
57 #define VGA_CR_OVERFLOW_VERT_TOTAL2_MASK 0x20
59 #define VGA_CR_OVERFLOW_VSYNC_START1_SHIFT 6
60 #define VGA_CR_OVERFLOW_VSYNC_START1_MASK 0x04
61 #define VGA_CR_OVERFLOW_VSYNC_START2_SHIFT 2
62 #define VGA_CR_OVERFLOW_VSYNC_START2_MASK 0x80
64 #define VGA_CR_OVERFLOW_HEIGHT1_SHIFT 7
65 #define VGA_CR_OVERFLOW_HEIGHT1_MASK 0x02
66 #define VGA_CR_OVERFLOW_HEIGHT2_SHIFT 3
67 #define VGA_CR_OVERFLOW_HEIGHT2_MASK 0xc0
68 #define VGA_CR_OVERFLOW_LINE_COMPARE_SHIFT 4
69 #define VGA_CR_OVERFLOW_LINE_COMPARE_MASK 0x10
71 #define VGA_CR_CELL_HEIGHT_LINE_COMPARE_MASK 0x40
72 #define VGA_CR_CELL_HEIGHT_LINE_COMPARE_SHIFT 3
73 #define VGA_CR_CELL_HEIGHT_VERTICAL_BLANK_MASK 0x20
74 #define VGA_CR_CELL_HEIGHT_VERTICAL_BLANK_SHIFT 4
75 #define VGA_CR_CELL_HEIGHT_DOUBLE_SCAN 0x80
78 VGA_CR_CURSOR_START_DISABLE
= (1 << 5)
81 #define VGA_CR_PITCH_DIVISOR 8
85 VGA_CR_MODE_NO_CGA
= 0x01,
86 VGA_CR_MODE_NO_HERCULES
= 0x02,
87 VGA_CR_MODE_ADDRESS_WRAP
= 0x20,
88 VGA_CR_MODE_BYTE_MODE
= 0x40,
89 VGA_CR_MODE_TIMING_ENABLE
= 0x80
95 VGA_SR_CLOCKING_MODE
= 1,
96 VGA_SR_MAP_MASK_REGISTER
= 2,
97 VGA_SR_CHAR_MAP_SELECT
= 3,
98 VGA_SR_MEMORY_MODE
= 4,
103 VGA_SR_RESET_ASYNC
= 1,
104 VGA_SR_RESET_SYNC
= 2
109 VGA_SR_CLOCKING_MODE_8_DOT_CLOCK
= 1
114 VGA_SR_MEMORY_MODE_NORMAL
= 0,
115 VGA_SR_MEMORY_MODE_EXTERNAL_VIDEO_MEMORY
= 2,
116 VGA_SR_MEMORY_MODE_SEQUENTIAL_ADDRESSING
= 4,
117 VGA_SR_MEMORY_MODE_CHAIN4
= 8,
122 VGA_GR_SET_RESET_PLANE
= 0,
123 VGA_GR_SET_RESET_PLANE_ENABLE
= 1,
124 VGA_GR_COLOR_COMPARE
= 2,
125 VGA_GR_READ_MAP_REGISTER
= 4,
128 VGA_GR_COLOR_COMPARE_DISABLE
= 7,
135 VGA_TEXT_TEXT_PLANE
= 0,
136 VGA_TEXT_ATTR_PLANE
= 1,
137 VGA_TEXT_FONT_PLANE
= 2
142 VGA_GR_GR6_GRAPHICS_MODE
= 1,
143 VGA_GR_GR6_MMAP_A0
= (1 << 2),
144 VGA_GR_GR6_MMAP_CGA
= (3 << 2)
149 VGA_GR_MODE_READ_MODE1
= 0x08,
150 VGA_GR_MODE_ODD_EVEN
= 0x10,
151 VGA_GR_MODE_ODD_EVEN_SHIFT
= 0x20,
152 VGA_GR_MODE_256_COLOR
= 0x40
155 #define CIRRUS_CR_EXTENDED_DISPLAY 0x1b
156 #define CIRRUS_CR_EXTENDED_OVERLAY 0x1d
158 #define CIRRUS_CR_EXTENDED_DISPLAY_PITCH_MASK 0x10
159 #define CIRRUS_CR_EXTENDED_DISPLAY_PITCH_SHIFT 4
160 #define CIRRUS_CR_EXTENDED_DISPLAY_START_MASK1 0x1
161 #define CIRRUS_CR_EXTENDED_DISPLAY_START_SHIFT1 16
162 #define CIRRUS_CR_EXTENDED_DISPLAY_START_MASK2 0xc
163 #define CIRRUS_CR_EXTENDED_DISPLAY_START_SHIFT2 15
165 #define CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_MASK 0x80
166 #define CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_SHIFT 12
167 #define CIRRUS_SR_EXTENDED_MODE 7
168 #define CIRRUS_SR_EXTENDED_MODE_LFB_ENABLE 0xf0
169 #define CIRRUS_SR_EXTENDED_MODE_ENABLE_EXT 0x01
170 #define CIRRUS_SR_EXTENDED_MODE_32BPP 0x08
171 #define CIRRUS_HIDDEN_DAC_888COLOR 0xc5
174 write_hidden_dac (uint8_t data
)
184 static void cirrus_init_linear_fb(struct device
*dev
)
186 uint8_t cr_ext
, cr_overlay
;
187 unsigned int pitch
= (width
* 4) / VGA_CR_PITCH_DIVISOR
;
188 uint8_t sr_ext
= 0, hidden_dac
= 0;
189 unsigned int vdisplay_end
= height
- 2;
190 unsigned int line_compare
= 0x3ff;
191 uint8_t overflow
, cell_height_reg
;
192 unsigned int horizontal_end
= width
/ VGA_CR_WIDTH_DIVISOR
;
193 unsigned int horizontal_total
= horizontal_end
+ 40;
194 unsigned int horizontal_blank_start
= horizontal_end
;
195 unsigned int horizontal_sync_pulse_start
= horizontal_end
+ 3;
196 unsigned int horizontal_sync_pulse_end
= 0;
198 unsigned int horizontal_blank_end
= 0;
199 unsigned int vertical_blank_start
= height
+ 1;
200 unsigned int vertical_blank_end
= 0;
201 unsigned int vertical_sync_start
= height
+ 3;
202 unsigned int vertical_sync_end
= 0;
203 unsigned int vertical_total
= height
+ 40;
205 /* find lfb pci bar */
206 addr
= pci_read_config32(dev
, PCI_BASE_ADDRESS_0
);
207 addr
&= ~PCI_BASE_ADDRESS_MEM_ATTR_MASK
;
208 printk(BIOS_DEBUG
, "QEMU VGA: cirrus framebuffer @ %x (pci bar 0)\n",
211 vga_misc_write (VGA_IO_MISC_COLOR
);
213 vga_sr_write (VGA_SR_MEMORY_MODE
,
214 VGA_SR_MEMORY_MODE_NORMAL
);
216 vga_sr_write (VGA_SR_MAP_MASK_REGISTER
,
217 (1 << VGA_TEXT_TEXT_PLANE
)
218 | (1 << VGA_TEXT_ATTR_PLANE
));
220 vga_sr_write (VGA_SR_CLOCKING_MODE
,
221 VGA_SR_CLOCKING_MODE_8_DOT_CLOCK
);
223 vga_palette_disable();
225 /* Disable CR0-7 write protection. */
226 vga_cr_write (VGA_CR_VSYNC_END
, 0);
228 overflow
= ((vertical_total
>> VGA_CR_OVERFLOW_VERT_TOTAL1_SHIFT
)
229 & VGA_CR_OVERFLOW_VERT_TOTAL1_MASK
)
230 | ((vertical_total
>> VGA_CR_OVERFLOW_VERT_TOTAL2_SHIFT
)
231 & VGA_CR_OVERFLOW_VERT_TOTAL2_MASK
)
232 | ((vertical_sync_start
>> VGA_CR_OVERFLOW_VSYNC_START2_SHIFT
)
233 & VGA_CR_OVERFLOW_VSYNC_START2_MASK
)
234 | ((vertical_sync_start
>> VGA_CR_OVERFLOW_VSYNC_START1_SHIFT
)
235 & VGA_CR_OVERFLOW_VSYNC_START1_MASK
)
236 | ((vdisplay_end
>> VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END1_SHIFT
)
237 & VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END1_MASK
)
238 | ((vdisplay_end
>> VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END2_SHIFT
)
239 & VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END2_MASK
)
240 | ((vertical_sync_start
>> VGA_CR_OVERFLOW_VSYNC_START1_SHIFT
)
241 & VGA_CR_OVERFLOW_VSYNC_START1_MASK
)
242 | ((line_compare
>> VGA_CR_OVERFLOW_LINE_COMPARE_SHIFT
)
243 & VGA_CR_OVERFLOW_LINE_COMPARE_MASK
);
245 cell_height_reg
= ((vertical_blank_start
246 >> VGA_CR_CELL_HEIGHT_VERTICAL_BLANK_SHIFT
)
247 & VGA_CR_CELL_HEIGHT_VERTICAL_BLANK_MASK
)
248 | ((line_compare
>> VGA_CR_CELL_HEIGHT_LINE_COMPARE_SHIFT
)
249 & VGA_CR_CELL_HEIGHT_LINE_COMPARE_MASK
);
251 vga_cr_write (VGA_CR_HTOTAL
, horizontal_total
- 1);
252 vga_cr_write (VGA_CR_HORIZ_END
, horizontal_end
- 1);
253 vga_cr_write (VGA_CR_HBLANK_START
, horizontal_blank_start
- 1);
254 vga_cr_write (VGA_CR_HBLANK_END
, horizontal_blank_end
);
255 vga_cr_write (VGA_CR_HORIZ_SYNC_PULSE_START
,
256 horizontal_sync_pulse_start
);
257 vga_cr_write (VGA_CR_HORIZ_SYNC_PULSE_END
,
258 horizontal_sync_pulse_end
);
259 vga_cr_write (VGA_CR_VERT_TOTAL
, vertical_total
& 0xff);
260 vga_cr_write (VGA_CR_OVERFLOW
, overflow
);
261 vga_cr_write (VGA_CR_CELL_HEIGHT
, cell_height_reg
);
262 vga_cr_write (VGA_CR_VSYNC_START
, vertical_sync_start
& 0xff);
263 vga_cr_write (VGA_CR_VSYNC_END
, vertical_sync_end
& 0x0f);
264 vga_cr_write (VGA_CR_VDISPLAY_END
, vdisplay_end
& 0xff);
265 vga_cr_write (VGA_CR_PITCH
, pitch
& 0xff);
266 vga_cr_write (VGA_CR_VERTICAL_BLANK_START
, vertical_blank_start
& 0xff);
267 vga_cr_write (VGA_CR_VERTICAL_BLANK_END
, vertical_blank_end
& 0xff);
268 vga_cr_write (VGA_CR_LINE_COMPARE
, line_compare
& 0xff);
270 vga_gr_write (VGA_GR_MODE
, VGA_GR_MODE_256_COLOR
| VGA_GR_MODE_READ_MODE1
);
271 vga_gr_write (VGA_GR_GR6
, VGA_GR_GR6_GRAPHICS_MODE
);
273 vga_sr_write (VGA_SR_MEMORY_MODE
, VGA_SR_MEMORY_MODE_NORMAL
);
275 vga_cr_write (CIRRUS_CR_EXTENDED_DISPLAY
,
276 (pitch
>> CIRRUS_CR_EXTENDED_DISPLAY_PITCH_SHIFT
)
277 & CIRRUS_CR_EXTENDED_DISPLAY_PITCH_MASK
);
279 vga_cr_write (VGA_CR_MODE
, VGA_CR_MODE_TIMING_ENABLE
280 | VGA_CR_MODE_BYTE_MODE
281 | VGA_CR_MODE_NO_HERCULES
| VGA_CR_MODE_NO_CGA
);
283 vga_cr_write (VGA_CR_START_ADDR_LOW_REGISTER
, 0);
284 vga_cr_write (VGA_CR_START_ADDR_HIGH_REGISTER
, 0);
286 cr_ext
= vga_cr_read (CIRRUS_CR_EXTENDED_DISPLAY
);
287 cr_ext
&= ~(CIRRUS_CR_EXTENDED_DISPLAY_START_MASK1
288 | CIRRUS_CR_EXTENDED_DISPLAY_START_MASK2
);
289 vga_cr_write (CIRRUS_CR_EXTENDED_DISPLAY
, cr_ext
);
291 cr_overlay
= vga_cr_read (CIRRUS_CR_EXTENDED_OVERLAY
);
292 cr_overlay
&= ~(CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_MASK
);
293 vga_cr_write (CIRRUS_CR_EXTENDED_OVERLAY
, cr_overlay
);
295 sr_ext
= CIRRUS_SR_EXTENDED_MODE_LFB_ENABLE
296 | CIRRUS_SR_EXTENDED_MODE_ENABLE_EXT
297 | CIRRUS_SR_EXTENDED_MODE_32BPP
;
298 hidden_dac
= CIRRUS_HIDDEN_DAC_888COLOR
;
299 vga_sr_write (CIRRUS_SR_EXTENDED_MODE
, sr_ext
);
300 write_hidden_dac (hidden_dac
);
302 fb_add_framebuffer_info(addr
, width
, height
, 4 * width
, 32);
305 static void cirrus_init_text_mode(struct device
*dev
)
311 static void cirrus_init(struct device
*dev
)
313 if (CONFIG(LINEAR_FRAMEBUFFER
))
314 cirrus_init_linear_fb(dev
);
315 else if (CONFIG(VGA_TEXT_FRAMEBUFFER
))
316 cirrus_init_text_mode(dev
);
319 static struct device_operations qemu_cirrus_graph_ops
= {
320 .read_resources
= pci_dev_read_resources
,
321 .set_resources
= pci_dev_set_resources
,
322 .enable_resources
= pci_dev_enable_resources
,
326 static const struct pci_driver qemu_cirrus_driver __pci_driver
= {
327 .ops
= &qemu_cirrus_graph_ops
,