bcm2708: Convert framebuffer driver over to new format

* Remove from raspberry_pi bootloader (which should die soon)
* Change to use new arm device layout
* Create arch_mailbox to check arm mailboxes (WIP)
This commit is contained in:
Alexander von Gluck IV
2015-03-05 22:41:47 -06:00
parent 4f716de692
commit 8a06abf132
7 changed files with 339 additions and 256 deletions
+2
View File
@@ -34,9 +34,11 @@ BootMergeObject boot_arch_$(TARGET_KERNEL_ARCH).o :
arch_uart_pl011.cpp
arch_elf.cpp
arch_framebuffer_920.cpp
arch_framebuffer_bcm2708.cpp
arch_framebuffer_pxa.cpp
arch_framebuffer_omap3.cpp
arch_cpu.cpp
arch_mailbox_bcm2708.cpp
arch_mmu.cpp
arch_start_kernel.S
@@ -0,0 +1,191 @@
/*
* Copyright 2012-2015 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz, [email protected]
* François Revol, [email protected]
* Alexander von Gluck IV, [email protected]
*/
#include "arch_framebuffer.h"
#include <arch/arm/bcm2708.h>
#include <arch/cpu.h>
#include <boot/stage2.h>
#include <boot/platform.h>
#include <boot/menu.h>
#include <boot/kernel_args.h>
#include <boot/platform/generic/video.h>
#include <util/list.h>
#include <drivers/driver_settings.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "arch_mailbox.h"
/*
#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"
*/
//XXX
extern "C" addr_t
mmu_map_physical_memory(addr_t physicalAddress, size_t size, uint32 flags);
extern "C" bool
mmu_get_virtual_mapping(addr_t virtualAddress, phys_addr_t *_physicalAddress);
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 ArchFBArmBCM2708 : public ArchFramebuffer {
public:
ArchFBArmBCM2708(addr_t base)
: ArchFramebuffer(base) {}
~ArchFBArmBCM2708() {}
virtual status_t Init();
virtual status_t Probe();
virtual status_t SetDefaultMode();
virtual status_t SetVideoMode(int width, int height, int depth);
};
extern "C" ArchFramebuffer*
arch_get_fb_arm_bcm2708(addr_t base)
{
return new ArchFBArmBCM2708(base);
}
status_t
ArchFBArmBCM2708::Init()
{
return B_OK;
}
status_t
ArchFBArmBCM2708::Probe()
{
return B_OK;
}
status_t
ArchFBArmBCM2708::SetDefaultMode()
{
status_t result;
do {
result = SetVideoMode(1920, 1080, 16);
} while (result != B_OK);
return B_OK;
}
status_t
ArchFBArmBCM2708::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;
}
// TODO: arch_mailbox calls!
// 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);
fPhysicalBase
= BCM2708_BUS_TO_PHYSICAL(sFramebufferConfig.frame_buffer_address);
fSize = sFramebufferConfig.screen_size;
// TODO: kDefaultPageFlags
//fBase = (addr_t)mmu_map_physical_memory(fPhysicalBase, fSize,
// kDefaultPageFlags);
fBase = (addr_t)mmu_map_physical_memory(fPhysicalBase, fSize, 0);
fCurrentWidth = width;
fCurrentHeight = height;
fCurrentDepth = depth;
fCurrentBytesPerRow = sFramebufferConfig.bytes_per_row;
return B_OK;
}
+50
View File
@@ -0,0 +1,50 @@
/*
* Copyright 2011-2015 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Alexander von Gluck IV, [email protected]
*/
#ifndef _ARCH_MAILBOX_H
#define _ARCH_MAILBOX_H
#include <boot/platform.h>
#include <SupportDefs.h>
#define TRACE_MAILBOX
#ifdef TRACE_MAILBOX
# define TRACE(x...) dprintf(x)
# define CALLED() dprintf("%s()\n", __func__);
#else
# define TRACE(x...) ;
# define CALLED() ;
#endif
#define ERROR(x...) dprintf(x)
class ArchMailbox {
public:
ArchMailbox(addr_t base)
:
fBase(base) {};
~ArchMailbox() {};
virtual status_t Init() { return B_OK; };
virtual status_t Probe() { return B_OK; };
virtual addr_t Base() { return fBase; };
addr_t PhysicalBase() { return fPhysicalBase; };
virtual status_t Write(uint8 channel, uint32 value);
virtual status_t Read(uint8 channel, uint32& value);
protected:
addr_t fBase;
addr_t fPhysicalBase;
};
#endif /* _ARCH_MAILBOX_H */
@@ -0,0 +1,96 @@
/*
* Copyright 2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz, [email protected]
* François Revol, [email protected]
* Alexander von Gluck IV, [email protected]
*/
#include "arch_mailbox.h"
#include <arch_cpu.h>
#include "bcm2708.h"
//extern addr_t gPeripheralBase;
//
//
//static inline addr_t
//convert_mailbox_reg(addr_t reg)
//{
// return gPeripheralBase + ARM_CTRL_0_MAILBOX_BASE + reg;
//}
//
//
//static inline void
//write_mailbox_reg(addr_t reg, uint32 value)
//{
// arch_cpu_memory_write_barrier();
// *(volatile uint32*)convert_mailbox_reg(reg) = value;
//}
//
//
//static inline uint32
//read_mailbox_reg(addr_t reg)
//{
// uint32 result = *(volatile uint32*)convert_mailbox_reg(reg);
// arch_cpu_memory_read_barrier();
// return result;
//}
class ArchMailboxArmBCM2708 : public ArchMailbox {
public:
ArchMailboxArmBCM2708(addr_t base)
:
ArchMailbox(base) {}
~ArchMailboxArmBCM2708() {}
virtual status_t Write(uint8 channel, uint32 value);
virtual status_t Read(uint8 channel, uint32& value);
};
extern "C" ArchMailbox*
arch_get_mailbox_arm_bcm2708(addr_t base)
{
return new ArchMailboxArmBCM2708(base);
}
status_t
ArchMailboxArmBCM2708::Write(uint8 channel, uint32 value)
{
// We have to wait for the mailbox to drain if it is marked full.
//while ((read_mailbox_reg(ARM_MAILBOX_STATUS) & ARM_MAILBOX_FULL) != 0)
// ;
//value &= ARM_MAILBOX_DATA_MASK;
//write_mailbox_reg(ARM_MAILBOX_WRITE, value | channel);
return B_OK;
}
status_t
ArchMailboxArmBCM2708::Read(uint8 channel, uint32& value)
{
//while (true) {
// // Wait for something to arrive in the mailbox.
// if ((read_mailbox_reg(ARM_MAILBOX_STATUS) & ARM_MAILBOX_EMPTY) != 0)
// continue;
// value = read_mailbox_reg(ARM_MAILBOX_READ);
// if ((value & ARM_MAILBOX_CHANNEL_MASK) != channel) {
// // Not for us, retry.
// continue;
// }
// break;
//}
//value &= ARM_MAILBOX_DATA_MASK;
return B_OK;
}
@@ -1,170 +0,0 @@
/*
* 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);
fPhysicalBase
= BCM2708_BUS_TO_PHYSICAL(sFramebufferConfig.frame_buffer_address);
fSize = sFramebufferConfig.screen_size;
fBase = (addr_t)mmu_map_physical_memory(fPhysicalBase, fSize,
kDefaultPageFlags);
fCurrentWidth = width;
fCurrentHeight = height;
fCurrentDepth = depth;
fCurrentBytesPerRow = sFramebufferConfig.bytes_per_row;
return B_OK;
}
@@ -1,74 +0,0 @@
/*
* Copyright 2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz, [email protected]
*/
#include <arch_cpu.h>
#include "bcm2708.h"
extern addr_t gPeripheralBase;
static inline addr_t
convert_mailbox_reg(addr_t reg)
{
return gPeripheralBase + ARM_CTRL_0_MAILBOX_BASE + reg;
}
static inline void
write_mailbox_reg(addr_t reg, uint32 value)
{
arch_cpu_memory_write_barrier();
*(volatile uint32*)convert_mailbox_reg(reg) = value;
}
static inline uint32
read_mailbox_reg(addr_t reg)
{
uint32 result = *(volatile uint32*)convert_mailbox_reg(reg);
arch_cpu_memory_read_barrier();
return result;
}
status_t
write_mailbox(uint8 channel, uint32 value)
{
// We have to wait for the mailbox to drain if it is marked full.
while ((read_mailbox_reg(ARM_MAILBOX_STATUS) & ARM_MAILBOX_FULL) != 0)
;
value &= ARM_MAILBOX_DATA_MASK;
write_mailbox_reg(ARM_MAILBOX_WRITE, value | channel);
return B_OK;
}
status_t
read_mailbox(uint8 channel, uint32& value)
{
while (true) {
// Wait for something to arrive in the mailbox.
if ((read_mailbox_reg(ARM_MAILBOX_STATUS) & ARM_MAILBOX_EMPTY) != 0)
continue;
value = read_mailbox_reg(ARM_MAILBOX_READ);
if ((value & ARM_MAILBOX_CHANNEL_MASK) != channel) {
// Not for us, retry.
continue;
}
break;
}
value &= ARM_MAILBOX_DATA_MASK;
return B_OK;
}
@@ -1,12 +0,0 @@
/*
* Copyright 2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _PLATFORM_MAILBOX_H_
#define _PLATFORM_MAILBOX_H_
status_t write_mailbox(uint8 channel, uint32 value);
status_t read_mailbox(uint8 channel, uint32& value);
#endif // _PLATFORM_MAILBOX_H_