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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_
|
||||
|
||||
Reference in New Issue
Block a user