Kernel: Add Framebuffer class for Raspberry Pi

It initializes framebuffer and exposes access to its properties.
This commit is contained in:
Marcin Undak 2021-10-14 22:54:48 -04:00 committed by Andreas Kling
parent 3cc5752a69
commit dbb61620be
Notes: sideshowbarker 2024-07-18 01:42:24 +09:00
4 changed files with 167 additions and 1 deletions

View file

@ -0,0 +1,114 @@
/*
* Copyright (c) 2021, Marcin Undak <mcinek@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <Kernel/Prekernel/Arch/aarch64/Framebuffer.h>
#include <Kernel/Prekernel/Arch/aarch64/FramebufferMailboxMessages.h>
#include <Kernel/Prekernel/Arch/aarch64/Utils.h>
namespace Prekernel {
Framebuffer::Framebuffer()
{
// FIXME: query HDMI for best mode
// https://github.com/raspberrypi/userland/blob/master/host_applications/linux/apps/tvservice/tvservice.c
m_width = 1280;
m_height = 720;
m_depth = 32;
m_initialized = false;
struct __attribute__((aligned(16))) {
Mailbox::MessageHeader header;
FramebufferSetPhysicalSizeMboxMessage set_physical_size;
FramebufferSetVirtualSizeMboxMessage set_virtual_size;
FramebufferSetVirtualOffsetMboxMessage set_virtual_offset;
FramebufferSetDepthMboxMessage set_depth;
FramebufferSetPixelOrderMboxMessage set_pixel_order;
FramebufferAllocateBufferMboxMessage allocate_buffer;
FramebufferGetPithMboxMessage get_pitch;
Mailbox::MessageTail tail;
} message_queue;
message_queue.header.set_queue_size(sizeof(message_queue));
message_queue.set_physical_size.width = m_width;
message_queue.set_physical_size.height = m_height;
message_queue.set_virtual_size.width = m_width;
message_queue.set_virtual_size.height = m_height;
// FIXME! those next 2 lines crash...
// message_queue.set_virtual_offset.x = 0;
// message_queue.set_virtual_offset.y = 0;
message_queue.set_depth.depth_bits = 32;
message_queue.set_pixel_order.pixel_order = FramebufferSetPixelOrderMboxMessage::PixelOrder::RGB;
message_queue.allocate_buffer.alignment = 4096;
if (!Mailbox::the().send_queue(&message_queue, sizeof(message_queue))) {
warnln("Framebuffer(): Mailbox send failed.");
return;
}
// Now message queue contains responses. Process them.
if (message_queue.set_physical_size.width != m_width || message_queue.set_physical_size.height != m_height) {
warnln("Framebuffer(): Setting physical dimension failed.");
return;
}
if (message_queue.set_virtual_size.width != m_width || message_queue.set_virtual_size.height != m_height) {
warnln("Framebuffer(): Setting virtual dimension failed.");
return;
}
if (message_queue.set_virtual_offset.x != 0 || message_queue.set_virtual_offset.y != 0) {
warnln("Framebuffer(): Setting virtual offset failed.");
return;
}
if (message_queue.set_depth.depth_bits != m_depth) {
warnln("Framebuffer(): Setting depth failed.");
return;
}
if (message_queue.allocate_buffer.size == 0 || message_queue.allocate_buffer.address == 0) {
warnln("Framebuffer(): Allocating buffer failed.");
return;
}
if (message_queue.get_pitch.pitch == 0) {
warnln("Framebuffer(): Retrieving pitch failed.");
return;
}
// Convert GPU address space to RAM
// GPU maps memory from 0x80000000 instead of 0x00000000
m_gpu_buffer = reinterpret_cast<u8*>(message_queue.allocate_buffer.address & 0x3FFFFFFF);
m_buffer_size = message_queue.allocate_buffer.size;
m_pitch = message_queue.get_pitch.pitch;
switch (message_queue.set_pixel_order.pixel_order) {
case FramebufferSetPixelOrderMboxMessage::PixelOrder::RGB:
m_pixel_order = PixelOrder::RGB;
break;
case FramebufferSetPixelOrderMboxMessage::PixelOrder::BGR:
m_pixel_order = PixelOrder::BGR;
break;
default:
warnln("Framebuffer(): Unsupported pixel order reported by GPU.");
m_pixel_order = PixelOrder::RGB;
break;
}
dbgln("Initialized framebuffer: 1280 x 720 @ 32 bits");
m_initialized = true;
}
Framebuffer& Framebuffer::the()
{
static Framebuffer instance;
return instance;
}
}

View file

@ -0,0 +1,43 @@
/*
* Copyright (c) 2021, Marcin Undak <mcinek@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Types.h>
namespace Prekernel {
class Framebuffer {
public:
enum class PixelOrder {
RGB,
BGR,
};
static Framebuffer& the();
bool initialized() const { return m_initialized; }
u16 width() const { return m_width; }
u16 height() const { return m_height; }
u8 depth() const { return m_depth; }
u8* gpu_buffer() const { return m_gpu_buffer; }
u32 buffer_size() const { return m_buffer_size; }
u32 pitch() const { return m_pitch; }
PixelOrder pixel_order() { return m_pixel_order; }
private:
u16 m_width;
u16 m_height;
u8 m_depth;
u8* m_gpu_buffer;
u32 m_buffer_size;
u32 m_pitch;
bool m_initialized;
PixelOrder m_pixel_order;
Framebuffer();
};
}

View file

@ -22,6 +22,7 @@ public:
height = 0;
}
};
static_assert(sizeof(FramebufferSetPhysicalSizeMboxMessage) == 20);
class FramebufferSetVirtualSizeMboxMessage : public Mailbox::Message {
public:
@ -35,6 +36,7 @@ public:
height = 0;
}
};
static_assert(sizeof(FramebufferSetVirtualSizeMboxMessage) == 20);
class FramebufferSetVirtualOffsetMboxMessage : public Mailbox::Message {
public:
@ -48,6 +50,7 @@ public:
y = 0;
}
};
static_assert(sizeof(FramebufferSetVirtualOffsetMboxMessage) == 20);
class FramebufferSetDepthMboxMessage : public Mailbox::Message {
public:
@ -59,6 +62,7 @@ public:
depth_bits = 0;
}
};
static_assert(sizeof(FramebufferSetDepthMboxMessage) == 16);
class FramebufferSetPixelOrderMboxMessage : public Mailbox::Message {
public:
@ -75,6 +79,7 @@ public:
pixel_order = PixelOrder::BGR;
}
};
static_assert(sizeof(FramebufferSetPixelOrderMboxMessage) == 16);
class FramebufferAllocateBufferMboxMessage : public Mailbox::Message {
public:
@ -91,6 +96,7 @@ public:
size = 0;
}
};
static_assert(sizeof(FramebufferAllocateBufferMboxMessage) == 20);
class FramebufferGetPithMboxMessage : public Mailbox::Message {
public:
@ -102,4 +108,6 @@ public:
pitch = 0;
}
};
static_assert(sizeof(FramebufferGetPithMboxMessage) == 16);
}

View file

@ -5,14 +5,15 @@ set(SOURCES
if ("${SERENITY_ARCH}" STREQUAL "aarch64")
set(SOURCES
${SOURCES}
Arch/aarch64/Aarch64_asm_utils.S
Arch/aarch64/GPIO.cpp
Arch/aarch64/Framebuffer.cpp
Arch/aarch64/Mailbox.cpp
Arch/aarch64/MainIdRegister.cpp
Arch/aarch64/MMIO.cpp
Arch/aarch64/Timer.cpp
Arch/aarch64/UART.cpp
Arch/aarch64/Utils.cpp
Arch/aarch64/Aarch64_asm_utils.S
Arch/aarch64/boot.S
Arch/aarch64/init.cpp
)