14ae92968SFrançois Revol /* 24ae92968SFrançois Revol * Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. 34ae92968SFrançois Revol * Distributed under the terms of the MIT License. 44ae92968SFrançois Revol */ 54ae92968SFrançois Revol 64ae92968SFrançois Revol 77ddba3d2SFrançois Revol #include "rom_calls.h" 8*499f2a5cSFrançois Revol #include "console.h" 94ae92968SFrançois Revol #include "video.h" 104ae92968SFrançois Revol //#include "mmu.h" 114ae92968SFrançois Revol //#include "images.h" 124ae92968SFrançois Revol 134ae92968SFrançois Revol #include <arch/cpu.h> 144ae92968SFrançois Revol #include <boot/stage2.h> 154ae92968SFrançois Revol #include <boot/platform.h> 164ae92968SFrançois Revol #include <boot/menu.h> 174ae92968SFrançois Revol #include <boot/kernel_args.h> 18*499f2a5cSFrançois Revol #include <boot/platform/generic/video.h> 194ae92968SFrançois Revol #include <util/list.h> 204ae92968SFrançois Revol #include <drivers/driver_settings.h> 214ae92968SFrançois Revol #include <GraphicsDefs.h> 224ae92968SFrançois Revol 234ae92968SFrançois Revol #include <stdio.h> 244ae92968SFrançois Revol #include <stdlib.h> 254ae92968SFrançois Revol #include <string.h> 264ae92968SFrançois Revol 274ae92968SFrançois Revol 284ae92968SFrançois Revol //#define TRACE_VIDEO 294ae92968SFrançois Revol #ifdef TRACE_VIDEO 304ae92968SFrançois Revol # define TRACE(x) dprintf x 314ae92968SFrançois Revol #else 324ae92968SFrançois Revol # define TRACE(x) ; 334ae92968SFrançois Revol #endif 344ae92968SFrançois Revol 35*499f2a5cSFrançois Revol static addr_t sFrameBuffer; 364ae92968SFrançois Revol 374ae92968SFrançois Revol 38*499f2a5cSFrançois Revol static void 39*499f2a5cSFrançois Revol probe_video_mode() 40*499f2a5cSFrançois Revol { 41*499f2a5cSFrançois Revol if (gScreen == NULL) { 42*499f2a5cSFrançois Revol gKernelArgs.frame_buffer.enabled = false; 43*499f2a5cSFrançois Revol return; 44*499f2a5cSFrançois Revol } 45*499f2a5cSFrançois Revol /* 46*499f2a5cSFrançois Revol if (gScreen->RastPort.BitMap->Depth < 8) { 47*499f2a5cSFrançois Revol gKernelArgs.frame_buffer.enabled = false; 48*499f2a5cSFrançois Revol return; 49*499f2a5cSFrançois Revol } 50*499f2a5cSFrançois Revol */ 51*499f2a5cSFrançois Revol 52*499f2a5cSFrançois Revol /* 53*499f2a5cSFrançois Revol dprintf("Video mode:\n"); 54*499f2a5cSFrançois Revol dprintf("BytesPerRow %d\n", gScreen->RastPort.BitMap->BytesPerRow); 55*499f2a5cSFrançois Revol dprintf("Rows %d\n", gScreen->RastPort.BitMap->Rows); 56*499f2a5cSFrançois Revol dprintf("Flags %02x\n", gScreen->RastPort.BitMap->Flags); 57*499f2a5cSFrançois Revol dprintf("Depth %d\n", gScreen->RastPort.BitMap->Depth); 58*499f2a5cSFrançois Revol for (int i = 0; i < 8; i++) 59*499f2a5cSFrançois Revol dprintf("Planes[%d] %p\n", i, gScreen->RastPort.BitMap->Planes[i]); 60*499f2a5cSFrançois Revol */ 61*499f2a5cSFrançois Revol 62*499f2a5cSFrançois Revol //XXX how do we tell it's a planar framebuffer ?? 63*499f2a5cSFrançois Revol 64*499f2a5cSFrançois Revol gKernelArgs.frame_buffer.width = gScreen->RastPort.BitMap->BytesPerRow * 8; 65*499f2a5cSFrançois Revol gKernelArgs.frame_buffer.height = gScreen->RastPort.BitMap->Rows; 66*499f2a5cSFrançois Revol gKernelArgs.frame_buffer.bytes_per_row = gScreen->RastPort.BitMap->BytesPerRow; 67*499f2a5cSFrançois Revol gKernelArgs.frame_buffer.depth = gScreen->RastPort.BitMap->Depth; 68*499f2a5cSFrançois Revol gKernelArgs.frame_buffer.physical_buffer.size 69*499f2a5cSFrançois Revol = gKernelArgs.frame_buffer.width 70*499f2a5cSFrançois Revol * gKernelArgs.frame_buffer.height 71*499f2a5cSFrançois Revol * gScreen->RastPort.BitMap->Depth / 8; 72*499f2a5cSFrançois Revol gKernelArgs.frame_buffer.physical_buffer.start 73*499f2a5cSFrançois Revol = (phys_addr_t)(gScreen->RastPort.BitMap->Planes[0]); 74*499f2a5cSFrançois Revol 75*499f2a5cSFrançois Revol dprintf("video mode: %ux%ux%u\n", gKernelArgs.frame_buffer.width, 76*499f2a5cSFrançois Revol gKernelArgs.frame_buffer.height, gKernelArgs.frame_buffer.depth); 77*499f2a5cSFrançois Revol 78*499f2a5cSFrançois Revol gKernelArgs.frame_buffer.enabled = true; 79*499f2a5cSFrançois Revol } 80b14f1607SFrançois Revol 81b14f1607SFrançois Revol 824ae92968SFrançois Revol // #pragma mark - 834ae92968SFrançois Revol 844ae92968SFrançois Revol 854ae92968SFrançois Revol bool 864ae92968SFrançois Revol video_mode_hook(Menu *menu, MenuItem *item) 874ae92968SFrançois Revol { 884ae92968SFrançois Revol // nothing yet 894ae92968SFrançois Revol return true; 904ae92968SFrançois Revol } 914ae92968SFrançois Revol 924ae92968SFrançois Revol 934ae92968SFrançois Revol Menu * 944ae92968SFrançois Revol video_mode_menu() 954ae92968SFrançois Revol { 96b14f1607SFrançois Revol Menu *menu = new(nothrow) Menu(CHOICE_MENU, "Select Video Mode"); 97b14f1607SFrançois Revol MenuItem *item; 98b14f1607SFrançois Revol 99b14f1607SFrançois Revol menu->AddItem(item = new(nothrow) MenuItem("Default")); 100b14f1607SFrançois Revol item->SetMarked(true); 101b14f1607SFrançois Revol item->Select(true); 102b14f1607SFrançois Revol item->SetHelpText("The Default video mode is the one currently configured " 103b14f1607SFrançois Revol "in the system. If there is no mode configured yet, a viable mode will " 104b14f1607SFrançois Revol "be chosen automatically."); 105b14f1607SFrançois Revol 106b14f1607SFrançois Revol /* 107b14f1607SFrançois Revol video_mode *mode = NULL; 108b14f1607SFrançois Revol while ((mode = (video_mode *)list_get_next_item(&sModeList, mode)) != NULL) { 109b14f1607SFrançois Revol char label[64]; 110b14f1607SFrançois Revol sprintf(label, "%ux%u %u bit", mode->width, mode->height, 111b14f1607SFrançois Revol mode->bits_per_pixel); 112b14f1607SFrançois Revol 113b14f1607SFrançois Revol menu->AddItem(item = new(nothrow) MenuItem(label)); 114b14f1607SFrançois Revol item->SetData(mode); 115b14f1607SFrançois Revol } 116b14f1607SFrançois Revol */ 117b14f1607SFrançois Revol #if 1 118b14f1607SFrançois Revol uint32 modeID = INVALID_ID; 119b14f1607SFrançois Revol while ((modeID = NextDisplayInfo(modeID)) != INVALID_ID) { 120b14f1607SFrançois Revol //DisplayInfoHandle handle = FindDisplayInfo(modeID); 121b14f1607SFrançois Revol //if (handle == NULL) 122b14f1607SFrançois Revol // continue; 123b14f1607SFrançois Revol struct DisplayInfo info; 124b14f1607SFrançois Revol struct DimensionInfo dimension; 125b14f1607SFrançois Revol struct NameInfo name; 126b14f1607SFrançois Revol if (GetDisplayInfoData(NULL, (uint8 *)&info, sizeof(info), 127b14f1607SFrançois Revol DTAG_DISP, modeID) < 48/*sizeof(struct DisplayInfo)*/) 128b14f1607SFrançois Revol continue; 129b14f1607SFrançois Revol if (GetDisplayInfoData(NULL, (uint8 *)&dimension, sizeof(dimension), 130b14f1607SFrançois Revol DTAG_DIMS, modeID) < 66) 131b14f1607SFrançois Revol continue; 132b14f1607SFrançois Revol /*if (GetDisplayInfoData(NULL, (uint8 *)&name, sizeof(name), 133b14f1607SFrançois Revol DTAG_NAME, modeID) < sizeof(name) - 8) 134b14f1607SFrançois Revol continue;*/ 135b14f1607SFrançois Revol if (info.NotAvailable) 136b14f1607SFrançois Revol continue; 137*499f2a5cSFrançois Revol if (info.PropertyFlags & DIPF_IS_HAM) 138*499f2a5cSFrançois Revol continue; 139*499f2a5cSFrançois Revol if (info.PropertyFlags & DIPF_IS_DUALPF) 140*499f2a5cSFrançois Revol continue; 141b14f1607SFrançois Revol if (dimension.MaxDepth < 4) 142b14f1607SFrançois Revol continue; 143*499f2a5cSFrançois Revol // skip 5 & 6 bit modes 144*499f2a5cSFrançois Revol if (dimension.MaxDepth < 8 && dimension.MaxDepth != 4) 145*499f2a5cSFrançois Revol continue; 146b14f1607SFrançois Revol //dprintf("name: %s\n", name.Name); 147b14f1607SFrançois Revol /* 148b14f1607SFrançois Revol dprintf("mode 0x%08lx: %dx%d flags: 0x%08lx bpp: %d\n", 149b14f1607SFrançois Revol modeID, info.Resolution.x, info.Resolution.y, info.PropertyFlags, 150b14f1607SFrançois Revol info.RedBits + info.GreenBits + info.BlueBits); 151b14f1607SFrançois Revol dprintf("mode: %dx%d -> %dx%d\n", 152b14f1607SFrançois Revol dimension.MinRasterWidth, dimension.MinRasterHeight, 153b14f1607SFrançois Revol dimension.MaxRasterWidth, dimension.MaxRasterHeight); 154*499f2a5cSFrançois Revol */ 155b14f1607SFrançois Revol dprintf("mode: %dx%d %dbpp flags: 0x%08lx\n", 156b14f1607SFrançois Revol dimension.Nominal.MaxX - dimension.Nominal.MinX + 1, 157b14f1607SFrançois Revol dimension.Nominal.MaxY - dimension.Nominal.MinY + 1, 158b14f1607SFrançois Revol dimension.MaxDepth, info.PropertyFlags); 159*499f2a5cSFrançois Revol 160ee0c1302SFrançois Revol char label[128]; 161ee0c1302SFrançois Revol sprintf(label, "%ux%u %u bit %08lx%s%s", 162b14f1607SFrançois Revol dimension.Nominal.MaxX - dimension.Nominal.MinX + 1, 163b14f1607SFrançois Revol dimension.Nominal.MaxY - dimension.Nominal.MinY + 1, 164ee0c1302SFrançois Revol dimension.MaxDepth, info.PropertyFlags, 165*499f2a5cSFrançois Revol (info.PropertyFlags & DIPF_IS_LACE) ? " i" : "", 166*499f2a5cSFrançois Revol (info.PropertyFlags & DIPF_IS_PAL) ? " pal" : ""); 167b14f1607SFrançois Revol 168b14f1607SFrançois Revol menu->AddItem(item = new(nothrow) MenuItem(label)); 169b14f1607SFrançois Revol item->SetData((void *)modeID); 170b14f1607SFrançois Revol } 171b14f1607SFrançois Revol 172b14f1607SFrançois Revol #endif 173b14f1607SFrançois Revol dprintf("done\n"); 174b14f1607SFrançois Revol 175b14f1607SFrançois Revol menu->AddSeparatorItem(); 176b14f1607SFrançois Revol menu->AddItem(item = new(nothrow) MenuItem("Return to main menu")); 177b14f1607SFrançois Revol item->SetType(MENU_ITEM_NO_CHOICE); 178b14f1607SFrançois Revol 179b14f1607SFrançois Revol return menu; 1804ae92968SFrançois Revol } 1814ae92968SFrançois Revol 1824ae92968SFrançois Revol 183*499f2a5cSFrançois Revol // #pragma mark - blit 184*499f2a5cSFrançois Revol 185*499f2a5cSFrançois Revol 186*499f2a5cSFrançois Revol extern "C" void 187*499f2a5cSFrançois Revol platform_blit4(addr_t frameBuffer, const uint8 *data, 188*499f2a5cSFrançois Revol uint16 width, uint16 height, uint16 imageWidth, uint16 left, uint16 top) 189*499f2a5cSFrançois Revol { 190*499f2a5cSFrançois Revol if (!data) 191*499f2a5cSFrançois Revol return; 192*499f2a5cSFrançois Revol // TODO 193*499f2a5cSFrançois Revol } 194*499f2a5cSFrançois Revol 195*499f2a5cSFrançois Revol 196*499f2a5cSFrançois Revol extern "C" void 197*499f2a5cSFrançois Revol platform_set_palette(const uint8 *palette) 198*499f2a5cSFrançois Revol { 199*499f2a5cSFrançois Revol switch (gKernelArgs.frame_buffer.depth) { 200*499f2a5cSFrançois Revol case 4: 201*499f2a5cSFrançois Revol //vga_set_palette((const uint8 *)kPalette16, 0, 16); 202*499f2a5cSFrançois Revol break; 203*499f2a5cSFrançois Revol case 8: 204*499f2a5cSFrançois Revol //if (vesa_set_palette((const uint8 *)palette, 0, 256) != B_OK) 205*499f2a5cSFrançois Revol // dprintf("set palette failed!\n"); 206*499f2a5cSFrançois Revol 207*499f2a5cSFrançois Revol break; 208*499f2a5cSFrançois Revol default: 209*499f2a5cSFrançois Revol break; 210*499f2a5cSFrançois Revol } 211*499f2a5cSFrançois Revol } 212*499f2a5cSFrançois Revol 213*499f2a5cSFrançois Revol 2144ae92968SFrançois Revol // #pragma mark - 2154ae92968SFrançois Revol 2164ae92968SFrançois Revol 2174ae92968SFrançois Revol extern "C" void 2184ae92968SFrançois Revol platform_switch_to_logo(void) 2194ae92968SFrançois Revol { 220*499f2a5cSFrançois Revol return; 221*499f2a5cSFrançois Revol // in debug mode, we'll never show the logo 222*499f2a5cSFrançois Revol if ((platform_boot_options() & BOOT_OPTION_DEBUG_OUTPUT) != 0) 223*499f2a5cSFrançois Revol return; 224*499f2a5cSFrançois Revol 225*499f2a5cSFrançois Revol addr_t lastBase = gKernelArgs.frame_buffer.physical_buffer.start; 226*499f2a5cSFrançois Revol size_t lastSize = gKernelArgs.frame_buffer.physical_buffer.size; 227*499f2a5cSFrançois Revol 2284ae92968SFrançois Revol // TODO: implement me 229*499f2a5cSFrançois Revol 230*499f2a5cSFrançois Revol probe_video_mode(); 231*499f2a5cSFrançois Revol 232*499f2a5cSFrançois Revol // map to virtual memory 233*499f2a5cSFrançois Revol // (should be ok in bootloader thanks to TT0) 234*499f2a5cSFrançois Revol 235*499f2a5cSFrançois Revol sFrameBuffer = gKernelArgs.frame_buffer.physical_buffer.start; 236*499f2a5cSFrançois Revol 237*499f2a5cSFrançois Revol video_display_splash(sFrameBuffer); 238*499f2a5cSFrançois Revol 2394ae92968SFrançois Revol } 2404ae92968SFrançois Revol 2414ae92968SFrançois Revol 2424ae92968SFrançois Revol extern "C" void 2434ae92968SFrançois Revol platform_switch_to_text_mode(void) 2444ae92968SFrançois Revol { 2454ae92968SFrançois Revol // TODO: implement me 2464ae92968SFrançois Revol } 2474ae92968SFrançois Revol 2484ae92968SFrançois Revol 2494ae92968SFrançois Revol extern "C" status_t 2504ae92968SFrançois Revol platform_init_video(void) 2514ae92968SFrançois Revol { 2524ae92968SFrançois Revol // TODO: implement me 253*499f2a5cSFrançois Revol probe_video_mode(); 254*499f2a5cSFrançois Revol 2554ae92968SFrançois Revol return B_OK; 2564ae92968SFrançois Revol } 2574ae92968SFrançois Revol 258