Add BCM2708 arch framebuffer implementation for rPi.
It uses the mailbox mechanism to instruct the VideoCore to configure the desired video mode and fills it with a black and white test pattern.
This commit is contained in:
@@ -34,6 +34,8 @@ BootMergeObject boot_platform_raspberrypi_arm.o :
|
|||||||
serial.cpp
|
serial.cpp
|
||||||
video.cpp
|
video.cpp
|
||||||
|
|
||||||
|
arch_framebuffer_bcm2708.cpp
|
||||||
|
|
||||||
$(genericPlatformSources)
|
$(genericPlatformSources)
|
||||||
: -fno-pic
|
: -fno-pic
|
||||||
: boot_platform_generic.a
|
: boot_platform_generic.a
|
||||||
|
|||||||
@@ -0,0 +1,181 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Michael Lotz, [email protected]
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <arm_mmu.h>
|
||||||
|
|
||||||
|
#include "arch_mmu.h"
|
||||||
|
|
||||||
|
#include "arch_framebuffer.h"
|
||||||
|
|
||||||
|
#include "bcm2708.h"
|
||||||
|
#include "mailbox.h"
|
||||||
|
#include "platform_debug.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct framebuffer_config {
|
||||||
|
uint32 width;
|
||||||
|
uint32 height;
|
||||||
|
uint32 virtual_width;
|
||||||
|
uint32 virtual_height;
|
||||||
|
uint32 bytes_per_row; // from GPU
|
||||||
|
uint32 bits_per_pixel;
|
||||||
|
uint32 x_offset;
|
||||||
|
uint32 y_offset;
|
||||||
|
uint32 frame_buffer_address; // from GPU
|
||||||
|
uint32 screen_size; // from GPU
|
||||||
|
uint16 color_map[256];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static framebuffer_config sFramebufferConfig __attribute__((aligned(16)));
|
||||||
|
|
||||||
|
|
||||||
|
class ArchFramebufferBCM2708 : public ArchFramebuffer {
|
||||||
|
public:
|
||||||
|
ArchFramebufferBCM2708();
|
||||||
|
virtual ~ArchFramebufferBCM2708();
|
||||||
|
|
||||||
|
virtual status_t Init();
|
||||||
|
virtual status_t Probe();
|
||||||
|
virtual status_t SetDefaultMode();
|
||||||
|
virtual status_t SetVideoMode(int width, int height, int depth);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static ArchFramebufferBCM2708 sArchFramebuffer;
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" ArchFramebuffer*
|
||||||
|
arch_get_framebuffer_arm_bcm2708()
|
||||||
|
{
|
||||||
|
return &sArchFramebuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ArchFramebufferBCM2708::ArchFramebufferBCM2708()
|
||||||
|
: ArchFramebuffer(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ArchFramebufferBCM2708::~ArchFramebufferBCM2708()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ArchFramebufferBCM2708::Init()
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ArchFramebufferBCM2708::Probe()
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ArchFramebufferBCM2708::SetDefaultMode()
|
||||||
|
{
|
||||||
|
status_t result;
|
||||||
|
do {
|
||||||
|
result = SetVideoMode(1920, 1080, 16);
|
||||||
|
} while (result != B_OK);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ArchFramebufferBCM2708::SetVideoMode(int width, int height, int depth)
|
||||||
|
{
|
||||||
|
debug_assert(((uint32)&sFramebufferConfig & 0x0f) == 0);
|
||||||
|
|
||||||
|
sFramebufferConfig.width = width;
|
||||||
|
sFramebufferConfig.height = height;
|
||||||
|
sFramebufferConfig.virtual_width = sFramebufferConfig.width;
|
||||||
|
sFramebufferConfig.virtual_height = sFramebufferConfig.height;
|
||||||
|
sFramebufferConfig.bytes_per_row = 0; // from GPU
|
||||||
|
sFramebufferConfig.bits_per_pixel = depth;
|
||||||
|
sFramebufferConfig.x_offset = 0;
|
||||||
|
sFramebufferConfig.y_offset = 0;
|
||||||
|
sFramebufferConfig.frame_buffer_address = 0; // from GPU
|
||||||
|
sFramebufferConfig.screen_size = 0; // from GPU
|
||||||
|
|
||||||
|
if (depth < 16) {
|
||||||
|
const int colorMapEntries = sizeof(sFramebufferConfig.color_map)
|
||||||
|
/ sizeof(sFramebufferConfig.color_map[0]);
|
||||||
|
for (int i = 0; i < colorMapEntries; i++)
|
||||||
|
sFramebufferConfig.color_map[i] = 0x1111 * i;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t result = write_mailbox(ARM_MAILBOX_CHANNEL_FRAMEBUFFER,
|
||||||
|
(uint32)&sFramebufferConfig | BCM2708_VIDEO_CORE_L2_COHERENT);
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
uint32 value;
|
||||||
|
result = read_mailbox(ARM_MAILBOX_CHANNEL_FRAMEBUFFER, value);
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if (value != 0) {
|
||||||
|
dprintf("failed to configure framebuffer: %" B_PRIx32 "\n", value);
|
||||||
|
debug_toggle_led(5, DEBUG_DELAY_SHORT);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sFramebufferConfig.frame_buffer_address == 0) {
|
||||||
|
dprintf("didn't get the framebuffer address\n");
|
||||||
|
debug_toggle_led(10, DEBUG_DELAY_SHORT);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_assert(sFramebufferConfig.x_offset == 0
|
||||||
|
&& sFramebufferConfig.y_offset == 0
|
||||||
|
&& sFramebufferConfig.width == (uint32)width
|
||||||
|
&& sFramebufferConfig.height == (uint32)height
|
||||||
|
&& sFramebufferConfig.virtual_width == sFramebufferConfig.width
|
||||||
|
&& sFramebufferConfig.virtual_height == sFramebufferConfig.height
|
||||||
|
&& sFramebufferConfig.bits_per_pixel == (uint32)depth
|
||||||
|
&& sFramebufferConfig.bytes_per_row
|
||||||
|
>= sFramebufferConfig.bits_per_pixel / 8
|
||||||
|
* sFramebufferConfig.width
|
||||||
|
&& sFramebufferConfig.screen_size >= sFramebufferConfig.bytes_per_row
|
||||||
|
* sFramebufferConfig.height);
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
fBase = BCM2708_BUS_TO_PHYSICAL(sFramebufferConfig.frame_buffer_address);
|
||||||
|
#else
|
||||||
|
// TODO: Enable when the MMU works.
|
||||||
|
fBase = (addr_t)mmu_map_physical_memory(
|
||||||
|
BCM2708_BUS_TO_PHYSICAL(sFramebufferConfig.frame_buffer_address),
|
||||||
|
sFramebufferConfig.screen_size, MMU_L2_FLAG_AP_RW | MMU_L2_FLAG_C);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint8* line = (uint8*)fBase;
|
||||||
|
for (uint32 y = 0; y < sFramebufferConfig.height; y++) {
|
||||||
|
volatile uint16* pixel = (volatile uint16*)line;
|
||||||
|
for (uint32 x = 0; x < sFramebufferConfig.width; x++)
|
||||||
|
*(pixel++) = y % 2 == 0 ? 0xffff : 0x0000;
|
||||||
|
|
||||||
|
line += sFramebufferConfig.bytes_per_row;
|
||||||
|
}
|
||||||
|
|
||||||
|
fCurrentWidth = width;
|
||||||
|
fCurrentHeight = height;
|
||||||
|
fCurrentDepth = depth;
|
||||||
|
fCurrentBytesPerRow = sFramebufferConfig.bytes_per_row;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user