soc/intel/alderlake: Add ADL-P 4+4 with 28W TDP
[coreboot.git] / src / device / oprom / yabel / vbe.c
blob5f03e192611bdd8a7a607de08e2b71c1ef363017
1 /******************************************************************************
2 * Copyright (c) 2004, 2008 IBM Corporation
3 * Copyright (c) 2009 Pattrick Hueper <phueper@hueper.net>
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
11 * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer
16 * in the documentation and/or other materials provided with the
17 * distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 * Contributors:
32 * IBM Corporation - initial implementation
33 *****************************************************************************/
35 #include <boot/coreboot_tables.h>
36 #include <framebuffer_info.h>
37 #include <string.h>
38 #include <types.h>
40 #include <endian.h>
42 #include "debug.h"
44 #include <x86emu/x86emu.h>
45 #include <x86emu/regs.h>
46 #include "../x86emu/prim_ops.h"
48 #include "biosemu.h"
49 #include "io.h"
50 #include "mem.h"
51 #include "interrupt.h"
52 #include "device.h"
54 #include <delay.h>
56 #include <vbe.h>
58 // these structs only store a subset of the VBE defined fields
59 // only those needed.
60 typedef struct {
61 char signature[4];
62 u16 version;
63 u8 *oem_string_ptr;
64 u32 capabilities;
65 u16 video_mode_list[256]; // lets hope we never have more than
66 // 256 video modes...
67 u16 total_memory;
68 } vbe_info_t;
70 // pointer to VBEInfoBuffer, set by vbe_prepare
71 u8 *vbe_info_buffer = 0;
73 // virtual BIOS Memory
74 u8 *biosmem;
75 u32 biosmem_size;
77 #if CONFIG(FRAMEBUFFER_SET_VESA_MODE)
78 static inline u8
79 vbe_prepare(void)
81 vbe_info_buffer = biosmem + (VBE_SEGMENT << 4); // segment:offset off VBE Data Area
82 //clear buffer
83 memset(vbe_info_buffer, 0, 512);
84 //set VbeSignature to "VBE2" to indicate VBE 2.0+ request
85 vbe_info_buffer[0] = 'V';
86 vbe_info_buffer[1] = 'B';
87 vbe_info_buffer[2] = 'E';
88 vbe_info_buffer[3] = '2';
89 // ES:DI store pointer to buffer in virtual mem see vbe_info_buffer above...
90 M.x86.R_EDI = 0x0;
91 M.x86.R_ES = VBE_SEGMENT;
93 return 0; // successful init
96 // VBE Function 00h
97 static u8
98 vbe_info(vbe_info_t * info)
100 vbe_prepare();
101 // call VBE function 00h (Info Function)
102 M.x86.R_EAX = 0x4f00;
104 // enable trace
105 CHECK_DBG(DEBUG_TRACE_X86EMU) {
106 X86EMU_trace_on();
108 // run VESA Interrupt
109 runInt10();
111 if (M.x86.R_AL != 0x4f) {
112 DEBUG_PRINTF_VBE("%s: VBE Info Function NOT supported! AL=%x\n",
113 __func__, M.x86.R_AL);
114 return -1;
117 if (M.x86.R_AH != 0x0) {
118 DEBUG_PRINTF_VBE
119 ("%s: VBE Info Function Return Code NOT OK! AH=%x\n",
120 __func__, M.x86.R_AH);
121 return M.x86.R_AH;
123 //printf("VBE Info Dump:");
124 //dump(vbe_info_buffer, 64);
126 //offset 0: signature
127 info->signature[0] = vbe_info_buffer[0];
128 info->signature[1] = vbe_info_buffer[1];
129 info->signature[2] = vbe_info_buffer[2];
130 info->signature[3] = vbe_info_buffer[3];
132 // offset 4: 16bit le containing VbeVersion
133 info->version = in16le(vbe_info_buffer + 4);
135 // offset 6: 32bit le containing segment:offset of OEM String in virtual Mem.
136 info->oem_string_ptr =
137 biosmem + ((in16le(vbe_info_buffer + 8) << 4) +
138 in16le(vbe_info_buffer + 6));
140 // offset 10: 32bit le capabilities
141 info->capabilities = in32le(vbe_info_buffer + 10);
143 // offset 14: 32 bit le containing segment:offset of supported video mode table
144 u16 *video_mode_ptr;
145 video_mode_ptr =
146 (u16 *) (biosmem +
147 ((in16le(vbe_info_buffer + 16) << 4) +
148 in16le(vbe_info_buffer + 14)));
149 u32 i = 0;
150 do {
151 info->video_mode_list[i] = in16le(video_mode_ptr + i);
152 i++;
154 while ((i <
155 (sizeof(info->video_mode_list) /
156 sizeof(info->video_mode_list[0])))
157 && (info->video_mode_list[i - 1] != 0xFFFF));
159 //offset 18: 16bit le total memory in 64KB blocks
160 info->total_memory = in16le(vbe_info_buffer + 18);
162 return 0;
165 static int mode_info_valid;
167 // VBE Function 01h
168 static u8
169 vbe_get_mode_info(vbe_mode_info_t * mode_info)
171 vbe_prepare();
172 // call VBE function 01h (Return VBE Mode Info Function)
173 M.x86.R_EAX = 0x4f01;
174 M.x86.R_CX = mode_info->video_mode;
176 // enable trace
177 CHECK_DBG(DEBUG_TRACE_X86EMU) {
178 X86EMU_trace_on();
180 // run VESA Interrupt
181 runInt10();
183 if (M.x86.R_AL != 0x4f) {
184 DEBUG_PRINTF_VBE
185 ("%s: VBE Return Mode Info Function NOT supported! AL=%x\n",
186 __func__, M.x86.R_AL);
187 return -1;
190 if (M.x86.R_AH != 0x0) {
191 DEBUG_PRINTF_VBE
192 ("%s: VBE Return Mode Info (mode: %04x) Function Return Code NOT OK! AH=%02x\n",
193 __func__, mode_info->video_mode, M.x86.R_AH);
194 return M.x86.R_AH;
197 //pointer to mode_info_block is in ES:DI
198 memcpy(mode_info->mode_info_block,
199 biosmem + ((M.x86.R_ES << 4) + M.x86.R_DI),
200 sizeof(mode_info->mode_info_block));
201 mode_info_valid = 1;
203 //printf("Mode Info Dump:");
204 //dump(mode_info_block, 64);
206 return 0;
209 // VBE Function 02h
210 static u8
211 vbe_set_mode(vbe_mode_info_t * mode_info)
213 vbe_prepare();
214 // call VBE function 02h (Set VBE Mode Function)
215 M.x86.R_EAX = 0x4f02;
216 M.x86.R_BX = mode_info->video_mode;
217 M.x86.R_BX |= 0x4000; // set bit 14 to request linear framebuffer mode
218 M.x86.R_BX &= 0x7FFF; // clear bit 15 to request clearing of framebuffer
220 DEBUG_PRINTF_VBE("%s: setting mode: 0x%04x\n", __func__,
221 M.x86.R_BX);
223 // enable trace
224 CHECK_DBG(DEBUG_TRACE_X86EMU) {
225 X86EMU_trace_on();
227 // run VESA Interrupt
228 runInt10();
230 if (M.x86.R_AL != 0x4f) {
231 DEBUG_PRINTF_VBE
232 ("%s: VBE Set Mode Function NOT supported! AL=%x\n",
233 __func__, M.x86.R_AL);
234 return -1;
237 if (M.x86.R_AH != 0x0) {
238 DEBUG_PRINTF_VBE
239 ("%s: mode: %x VBE Set Mode Function Return Code NOT OK! AH=%x\n",
240 __func__, mode_info->video_mode, M.x86.R_AH);
241 return M.x86.R_AH;
243 return 0;
246 #if 0
247 //VBE Function 08h
248 static u8
249 vbe_set_palette_format(u8 format)
251 vbe_prepare();
252 // call VBE function 09h (Set/Get Palette Data Function)
253 M.x86.R_EAX = 0x4f08;
254 M.x86.R_BL = 0x00; // set format
255 M.x86.R_BH = format;
257 DEBUG_PRINTF_VBE("%s: setting palette format: %d\n", __func__,
258 format);
260 // enable trace
261 CHECK_DBG(DEBUG_TRACE_X86EMU) {
262 X86EMU_trace_on();
264 // run VESA Interrupt
265 runInt10();
267 if (M.x86.R_AL != 0x4f) {
268 DEBUG_PRINTF_VBE
269 ("%s: VBE Set Palette Format Function NOT supported! AL=%x\n",
270 __func__, M.x86.R_AL);
271 return -1;
274 if (M.x86.R_AH != 0x0) {
275 DEBUG_PRINTF_VBE
276 ("%s: VBE Set Palette Format Function Return Code NOT OK! AH=%x\n",
277 __func__, M.x86.R_AH);
278 return M.x86.R_AH;
280 return 0;
283 // VBE Function 09h
284 static u8
285 vbe_set_color(u16 color_number, u32 color_value)
287 vbe_prepare();
288 // call VBE function 09h (Set/Get Palette Data Function)
289 M.x86.R_EAX = 0x4f09;
290 M.x86.R_BL = 0x00; // set color
291 M.x86.R_CX = 0x01; // set only one entry
292 M.x86.R_DX = color_number;
293 // ES:DI is address where color_value is stored, we store it at 2000:0000
294 M.x86.R_ES = 0x2000;
295 M.x86.R_DI = 0x0;
297 // store color value at ES:DI
298 out32le(biosmem + (M.x86.R_ES << 4) + M.x86.R_DI, color_value);
300 DEBUG_PRINTF_VBE("%s: setting color #%x: 0x%04x\n", __func__,
301 color_number, color_value);
303 // enable trace
304 CHECK_DBG(DEBUG_TRACE_X86EMU) {
305 X86EMU_trace_on();
307 // run VESA Interrupt
308 runInt10();
310 if (M.x86.R_AL != 0x4f) {
311 DEBUG_PRINTF_VBE
312 ("%s: VBE Set Palette Function NOT supported! AL=%x\n",
313 __func__, M.x86.R_AL);
314 return -1;
317 if (M.x86.R_AH != 0x0) {
318 DEBUG_PRINTF_VBE
319 ("%s: VBE Set Palette Function Return Code NOT OK! AH=%x\n",
320 __func__, M.x86.R_AH);
321 return M.x86.R_AH;
323 return 0;
326 static u8
327 vbe_get_color(u16 color_number, u32 *color_value)
329 vbe_prepare();
330 // call VBE function 09h (Set/Get Palette Data Function)
331 M.x86.R_EAX = 0x4f09;
332 M.x86.R_BL = 0x00; // get color
333 M.x86.R_CX = 0x01; // get only one entry
334 M.x86.R_DX = color_number;
335 // ES:DI is address where color_value is stored, we store it at 2000:0000
336 M.x86.R_ES = 0x2000;
337 M.x86.R_DI = 0x0;
339 // enable trace
340 CHECK_DBG(DEBUG_TRACE_X86EMU) {
341 X86EMU_trace_on();
343 // run VESA Interrupt
344 runInt10();
346 if (M.x86.R_AL != 0x4f) {
347 DEBUG_PRINTF_VBE
348 ("%s: VBE Set Palette Function NOT supported! AL=%x\n",
349 __func__, M.x86.R_AL);
350 return -1;
353 if (M.x86.R_AH != 0x0) {
354 DEBUG_PRINTF_VBE
355 ("%s: VBE Set Palette Function Return Code NOT OK! AH=%x\n",
356 __func__, M.x86.R_AH);
357 return M.x86.R_AH;
359 // read color value from ES:DI
360 *color_value = in32le(biosmem + (M.x86.R_ES << 4) + M.x86.R_DI);
362 DEBUG_PRINTF_VBE("%s: getting color #%x --> 0x%04x\n", __func__,
363 color_number, *color_value);
365 return 0;
368 // VBE Function 15h
369 static u8
370 vbe_get_ddc_info(vbe_ddc_info_t * ddc_info)
372 vbe_prepare();
373 // call VBE function 15h (DDC Info Function)
374 M.x86.R_EAX = 0x4f15;
375 M.x86.R_BL = 0x00; // get DDC Info
376 M.x86.R_CX = ddc_info->port_number;
377 M.x86.R_ES = 0x0;
378 M.x86.R_DI = 0x0;
380 // enable trace
381 CHECK_DBG(DEBUG_TRACE_X86EMU) {
382 X86EMU_trace_on();
384 // run VESA Interrupt
385 runInt10();
387 if (M.x86.R_AL != 0x4f) {
388 DEBUG_PRINTF_VBE
389 ("%s: VBE Get DDC Info Function NOT supported! AL=%x\n",
390 __func__, M.x86.R_AL);
391 return -1;
394 if (M.x86.R_AH != 0x0) {
395 DEBUG_PRINTF_VBE
396 ("%s: port: %x VBE Get DDC Info Function Return Code NOT OK! AH=%x\n",
397 __func__, ddc_info->port_number, M.x86.R_AH);
398 return M.x86.R_AH;
400 // BH = approx. time in seconds to transfer one EDID block
401 ddc_info->edid_transfer_time = M.x86.R_BH;
402 // BL = DDC Level
403 ddc_info->ddc_level = M.x86.R_BL;
405 vbe_prepare();
406 // call VBE function 15h (DDC Info Function)
407 M.x86.R_EAX = 0x4f15;
408 M.x86.R_BL = 0x01; // read EDID
409 M.x86.R_CX = ddc_info->port_number;
410 M.x86.R_DX = 0x0; // block number
411 // ES:DI is address where EDID is stored, we store it at 2000:0000
412 M.x86.R_ES = 0x2000;
413 M.x86.R_DI = 0x0;
415 // enable trace
416 CHECK_DBG(DEBUG_TRACE_X86EMU) {
417 X86EMU_trace_on();
419 // run VESA Interrupt
420 runInt10();
422 if (M.x86.R_AL != 0x4f) {
423 DEBUG_PRINTF_VBE
424 ("%s: VBE Read EDID Function NOT supported! AL=%x\n",
425 __func__, M.x86.R_AL);
426 return -1;
429 if (M.x86.R_AH != 0x0) {
430 DEBUG_PRINTF_VBE
431 ("%s: port: %x VBE Read EDID Function Return Code NOT OK! AH=%x\n",
432 __func__, ddc_info->port_number, M.x86.R_AH);
433 return M.x86.R_AH;
436 memcpy(ddc_info->edid_block_zero,
437 biosmem + (M.x86.R_ES << 4) + M.x86.R_DI,
438 sizeof(ddc_info->edid_block_zero));
440 return 0;
443 static u32
444 vbe_get_info(void)
446 u8 rval;
447 int i;
449 // XXX FIXME these need to be filled with sane values
451 // get a copy of input struct...
452 screen_info_input_t input;
453 // output is pointer to the address passed as argv[4]
454 screen_info_t local_output;
455 screen_info_t *output = &local_output;
456 // zero input
457 memset(&input, 0, sizeof(screen_info_input_t));
458 // zero output
459 memset(&output, 0, sizeof(screen_info_t));
461 vbe_info_t info;
462 rval = vbe_info(&info);
463 if (rval != 0)
464 return rval;
466 DEBUG_PRINTF_VBE("VbeSignature: %s\n", info.signature);
467 DEBUG_PRINTF_VBE("VbeVersion: 0x%04x\n", info.version);
468 DEBUG_PRINTF_VBE("OemString: %s\n", info.oem_string_ptr);
469 DEBUG_PRINTF_VBE("Capabilities:\n");
470 DEBUG_PRINTF_VBE("\tDAC: %s\n",
471 (info.capabilities & 0x1) ==
472 0 ? "fixed 6bit" : "switchable 6/8bit");
473 DEBUG_PRINTF_VBE("\tVGA: %s\n",
474 (info.capabilities & 0x2) ==
475 0 ? "compatible" : "not compatible");
476 DEBUG_PRINTF_VBE("\tRAMDAC: %s\n",
477 (info.capabilities & 0x4) ==
478 0 ? "normal" : "use blank bit in Function 09h");
480 // argv[4] may be a pointer with enough space to return screen_info_t
481 // as input, it must contain a screen_info_input_t with the following content:
482 // byte[0:3] = "DDC\0" (zero-terminated signature header)
483 // byte[4:5] = reserved space for the return struct... just in case we ever change
484 // the struct and don't have reserved enough memory (and let's hope the struct
485 // never gets larger than 64KB)
486 // byte[6] = monitor port number for DDC requests ("only" one byte... so lets hope we never have more than 255 monitors...
487 // byte[7:8] = max. screen width (OF may want to limit this)
488 // byte[9] = required color depth in bpp
489 if (strncmp((char *) input.signature, "DDC", 4) != 0) {
490 printf
491 ("%s: Invalid input signature! expected: %s, is: %s\n",
492 __func__, "DDC", input.signature);
493 return -1;
495 if (input.size_reserved != sizeof(screen_info_t)) {
496 printf
497 ("%s: Size of return struct is wrong, required: %d, available: %d\n",
498 __func__, (int) sizeof(screen_info_t),
499 input.size_reserved);
500 return -1;
503 vbe_ddc_info_t ddc_info;
504 ddc_info.port_number = input.monitor_number;
505 vbe_get_ddc_info(&ddc_info);
507 #if 0
508 DEBUG_PRINTF_VBE("DDC: edid_transfer_time: %d\n",
509 ddc_info.edid_transfer_time);
510 DEBUG_PRINTF_VBE("DDC: ddc_level: %x\n", ddc_info.ddc_level);
511 DEBUG_PRINTF_VBE("DDC: EDID:\n");
512 CHECK_DBG(DEBUG_VBE) {
513 dump(ddc_info.edid_block_zero,
514 sizeof(ddc_info.edid_block_zero));
516 #endif
517 /* This could fail because of alignment issues, so use a longer form.
518 *((u64 *) ddc_info.edid_block_zero) != (u64) 0x00FFFFFFFFFFFF00ULL
520 if (ddc_info.edid_block_zero[0] != 0x00 ||
521 ddc_info.edid_block_zero[1] != 0xFF ||
522 ddc_info.edid_block_zero[2] != 0xFF ||
523 ddc_info.edid_block_zero[3] != 0xFF ||
524 ddc_info.edid_block_zero[4] != 0xFF ||
525 ddc_info.edid_block_zero[5] != 0xFF ||
526 ddc_info.edid_block_zero[6] != 0xFF ||
527 ddc_info.edid_block_zero[7] != 0x00 ) {
528 // invalid EDID signature... probably no monitor
530 output->display_type = 0x0;
531 return 0;
532 } else if ((ddc_info.edid_block_zero[20] & 0x80) != 0) {
533 // digital display
534 output->display_type = 2;
535 } else {
536 // analog
537 output->display_type = 1;
539 DEBUG_PRINTF_VBE("DDC: found display type %d\n", output->display_type);
540 memcpy(output->edid_block_zero, ddc_info.edid_block_zero,
541 sizeof(ddc_info.edid_block_zero));
542 i = 0;
543 vbe_mode_info_t mode_info;
544 vbe_mode_info_t best_mode_info;
545 // initialize best_mode to 0
546 memset(&best_mode_info, 0, sizeof(best_mode_info));
547 while ((mode_info.video_mode = info.video_mode_list[i]) != 0xFFFF) {
548 //DEBUG_PRINTF_VBE("%x: Mode: %04x\n", i, mode_info.video_mode);
549 vbe_get_mode_info(&mode_info);
551 // FIXME all these values are little endian!
553 DEBUG_PRINTF_VBE("Video Mode 0x%04x available, %s\n",
554 mode_info.video_mode,
555 (le16_to_cpu(mode_info.vesa.mode_attributes) & 0x1) ==
556 0 ? "not supported" : "supported");
557 DEBUG_PRINTF_VBE("\tTTY: %s\n",
558 (le16_to_cpu(mode_info.vesa.mode_attributes) & 0x4) ==
559 0 ? "no" : "yes");
560 DEBUG_PRINTF_VBE("\tMode: %s %s\n",
561 (le16_to_cpu(mode_info.vesa.mode_attributes) & 0x8) ==
562 0 ? "monochrome" : "color",
563 (le16_to_cpu(mode_info.vesa.mode_attributes) & 0x10) ==
564 0 ? "text" : "graphics");
565 DEBUG_PRINTF_VBE("\tVGA: %s\n",
566 (le16_to_cpu(mode_info.vesa.mode_attributes) & 0x20) ==
567 0 ? "compatible" : "not compatible");
568 DEBUG_PRINTF_VBE("\tWindowed Mode: %s\n",
569 (le16_to_cpu(mode_info.vesa.mode_attributes) & 0x40) ==
570 0 ? "yes" : "no");
571 DEBUG_PRINTF_VBE("\tFramebuffer: %s\n",
572 (le16_to_cpu(mode_info.vesa.mode_attributes) & 0x80) ==
573 0 ? "no" : "yes");
574 DEBUG_PRINTF_VBE("\tResolution: %dx%d\n",
575 le16_to_cpu(mode_info.vesa.x_resolution),
576 le16_to_cpu(mode_info.vesa.y_resolution));
577 DEBUG_PRINTF_VBE("\tChar Size: %dx%d\n",
578 mode_info.vesa.x_charsize, mode_info.vesa.y_charsize);
579 DEBUG_PRINTF_VBE("\tColor Depth: %dbpp\n",
580 mode_info.vesa.bits_per_pixel);
581 DEBUG_PRINTF_VBE("\tMemory Model: 0x%x\n",
582 mode_info.vesa.memory_model);
583 DEBUG_PRINTF_VBE("\tFramebuffer Offset: %08x\n",
584 le32_to_cpu(mode_info.vesa.phys_base_ptr));
586 if ((mode_info.vesa.bits_per_pixel == input.color_depth)
587 && (le16_to_cpu(mode_info.vesa.x_resolution) <= input.max_screen_width)
588 && ((le16_to_cpu(mode_info.vesa.mode_attributes) & 0x80) != 0) // framebuffer mode
589 && ((le16_to_cpu(mode_info.vesa.mode_attributes) & 0x10) != 0) // graphics
590 && ((le16_to_cpu(mode_info.vesa.mode_attributes) & 0x8) != 0) // color
591 && (le16_to_cpu(mode_info.vesa.x_resolution) > le16_to_cpu(best_mode_info.vesa.x_resolution))) // better than previous best_mode
593 // yiiiihaah... we found a new best mode
594 memcpy(&best_mode_info, &mode_info, sizeof(mode_info));
596 i++;
599 if (best_mode_info.video_mode != 0) {
600 DEBUG_PRINTF_VBE
601 ("Best Video Mode found: 0x%x, %dx%d, %dbpp, framebuffer_address: 0x%x\n",
602 best_mode_info.video_mode,
603 best_mode_info.vesa.x_resolution,
604 best_mode_info.vesa.y_resolution,
605 best_mode_info.vesa.bits_per_pixel,
606 le32_to_cpu(best_mode_info.vesa.phys_base_ptr));
608 //printf("Mode Info Dump:");
609 //dump(best_mode_info.mode_info_block, 64);
611 // set the video mode
612 vbe_set_mode(&best_mode_info);
614 if ((info.capabilities & 0x1) != 0) {
615 // switch to 8 bit palette format
616 vbe_set_palette_format(8);
618 // setup a palette:
619 // - first 216 colors are mixed colors for each component in 6 steps
620 // (6*6*6=216)
621 // - then 10 shades of the three primary colors
622 // - then 10 shades of grey
623 // -------
624 // = 256 colors
626 // - finally black is color 0 and white color FF (because SLOF expects it
627 // this way...)
628 // this resembles the palette that the kernel/X Server seems to expect...
630 u8 mixed_color_values[6] =
631 { 0xFF, 0xDA, 0xB3, 0x87, 0x54, 0x00 };
632 u8 primary_color_values[10] =
633 { 0xF3, 0xE7, 0xCD, 0xC0, 0xA5, 0x96, 0x77, 0x66, 0x3F,
634 0x27
636 u8 mc_size = sizeof(mixed_color_values);
637 u8 prim_size = sizeof(primary_color_values);
639 u8 curr_color_index;
640 u32 curr_color;
642 u8 r, g, b;
643 // 216 mixed colors
644 for (r = 0; r < mc_size; r++) {
645 for (g = 0; g < mc_size; g++) {
646 for (b = 0; b < mc_size; b++) {
647 curr_color_index =
648 (r * mc_size * mc_size) +
649 (g * mc_size) + b;
650 curr_color = 0;
651 curr_color |= ((u32) mixed_color_values[r]) << 16; //red value
652 curr_color |= ((u32) mixed_color_values[g]) << 8; //green value
653 curr_color |= (u32) mixed_color_values[b]; //blue value
654 vbe_set_color(curr_color_index,
655 curr_color);
660 // 10 shades of each primary color
661 // red
662 for (r = 0; r < prim_size; r++) {
663 curr_color_index = mc_size * mc_size * mc_size + r;
664 curr_color = ((u32) primary_color_values[r]) << 16;
665 vbe_set_color(curr_color_index, curr_color);
667 //green
668 for (g = 0; g < prim_size; g++) {
669 curr_color_index =
670 mc_size * mc_size * mc_size + prim_size + g;
671 curr_color = ((u32) primary_color_values[g]) << 8;
672 vbe_set_color(curr_color_index, curr_color);
674 //blue
675 for (b = 0; b < prim_size; b++) {
676 curr_color_index =
677 mc_size * mc_size * mc_size + prim_size * 2 + b;
678 curr_color = (u32) primary_color_values[b];
679 vbe_set_color(curr_color_index, curr_color);
681 // 10 shades of grey
682 for (i = 0; i < prim_size; i++) {
683 curr_color_index =
684 mc_size * mc_size * mc_size + prim_size * 3 + i;
685 curr_color = 0;
686 curr_color |= ((u32) primary_color_values[i]) << 16; //red
687 curr_color |= ((u32) primary_color_values[i]) << 8; //green
688 curr_color |= ((u32) primary_color_values[i]); //blue
689 vbe_set_color(curr_color_index, curr_color);
692 // SLOF is using color 0x0 (black) and 0xFF (white) to draw to the screen...
693 vbe_set_color(0x00, 0x00000000);
694 vbe_set_color(0xFF, 0x00FFFFFF);
696 output->screen_width = le16_to_cpu(best_mode_info.vesa.x_resolution);
697 output->screen_height = le16_to_cpu(best_mode_info.vesa.y_resolution);
698 output->screen_linebytes = le16_to_cpu(best_mode_info.vesa.bytes_per_scanline);
699 output->color_depth = best_mode_info.vesa.bits_per_pixel;
700 output->framebuffer_address =
701 le32_to_cpu(best_mode_info.vesa.phys_base_ptr);
702 } else {
703 printf("%s: No suitable video mode found!\n", __func__);
704 //unset display_type...
705 output->display_type = 0;
707 return 0;
709 #endif
711 static vbe_mode_info_t mode_info;
713 const vbe_mode_info_t *vbe_mode_info(void)
715 if (!mode_info_valid || !mode_info.vesa.phys_base_ptr)
716 return NULL;
717 return &mode_info;
720 void vbe_set_graphics(void)
722 u8 rval;
724 vbe_info_t info;
725 rval = vbe_info(&info);
726 if (rval != 0)
727 return;
729 DEBUG_PRINTF_VBE("VbeSignature: %s\n", info.signature);
730 DEBUG_PRINTF_VBE("VbeVersion: 0x%04x\n", info.version);
731 DEBUG_PRINTF_VBE("OemString: %s\n", info.oem_string_ptr);
732 DEBUG_PRINTF_VBE("Capabilities:\n");
733 DEBUG_PRINTF_VBE("\tDAC: %s\n",
734 (info.capabilities & 0x1) ==
735 0 ? "fixed 6bit" : "switchable 6/8bit");
736 DEBUG_PRINTF_VBE("\tVGA: %s\n",
737 (info.capabilities & 0x2) ==
738 0 ? "compatible" : "not compatible");
739 DEBUG_PRINTF_VBE("\tRAMDAC: %s\n",
740 (info.capabilities & 0x4) ==
741 0 ? "normal" : "use blank bit in Function 09h");
743 mode_info.video_mode = (1 << 14) | CONFIG_FRAMEBUFFER_VESA_MODE;
744 vbe_get_mode_info(&mode_info);
745 vbe_set_mode(&mode_info);
747 const struct lb_framebuffer fb = {
748 .physical_address = mode_info.vesa.phys_base_ptr,
749 .x_resolution = le16_to_cpu(mode_info.vesa.x_resolution),
750 .y_resolution = le16_to_cpu(mode_info.vesa.y_resolution),
751 .bytes_per_line = le16_to_cpu(mode_info.vesa.bytes_per_scanline),
752 .bits_per_pixel = mode_info.vesa.bits_per_pixel,
753 .red_mask_pos = mode_info.vesa.red_mask_pos,
754 .red_mask_size = mode_info.vesa.red_mask_size,
755 .green_mask_pos = mode_info.vesa.green_mask_pos,
756 .green_mask_size = mode_info.vesa.green_mask_size,
757 .blue_mask_pos = mode_info.vesa.blue_mask_pos,
758 .blue_mask_size = mode_info.vesa.blue_mask_size,
759 .reserved_mask_pos = mode_info.vesa.reserved_mask_pos,
760 .reserved_mask_size = mode_info.vesa.reserved_mask_size,
761 .orientation = LB_FB_ORIENTATION_NORMAL,
764 fb_add_framebuffer_info_ex(&fb);
767 void vbe_textmode_console(void)
769 /* Wait, just a little bit more, pleeeease ;-) */
770 delay(2);
772 M.x86.R_EAX = 0x0003;
773 runInt10();
776 #endif