parent
ee28a69c98
commit
3cb6de2e69
|
@ -18,8 +18,13 @@ struct Dispc : Genode::Mmio
|
||||||
*/
|
*/
|
||||||
struct Control1 : Register<0x40, 32>
|
struct Control1 : Register<0x40, 32>
|
||||||
{
|
{
|
||||||
|
struct Lcd_enable : Bitfield<0, 1> { };
|
||||||
struct Tv_enable : Bitfield<1, 1> { };
|
struct Tv_enable : Bitfield<1, 1> { };
|
||||||
|
struct Go_lcd : Bitfield<5, 1>
|
||||||
|
{
|
||||||
|
enum { HW_UPDATE_DONE = 0x0, /* set by HW after updating */
|
||||||
|
REQUEST_HW_UPDATE = 0x1 }; /* must be set by user */
|
||||||
|
};
|
||||||
struct Go_tv : Bitfield<6, 1>
|
struct Go_tv : Bitfield<6, 1>
|
||||||
{
|
{
|
||||||
enum { HW_UPDATE_DONE = 0x0, /* set by HW after updating */
|
enum { HW_UPDATE_DONE = 0x0, /* set by HW after updating */
|
||||||
|
@ -46,11 +51,17 @@ struct Dispc : Genode::Mmio
|
||||||
struct Width : Bitfield<0, 11> { };
|
struct Width : Bitfield<0, 11> { };
|
||||||
struct Height : Bitfield<16, 11> { };
|
struct Height : Bitfield<16, 11> { };
|
||||||
};
|
};
|
||||||
|
struct Size_lcd : Register<0x7c, 32>
|
||||||
|
{
|
||||||
|
struct Width : Bitfield<0, 11> { };
|
||||||
|
struct Height : Bitfield<16, 11> { };
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures base address of the graphics buffer
|
* Configures base address of the graphics buffer
|
||||||
*/
|
*/
|
||||||
struct Gfx_ba1 : Register<0x80, 32> { };
|
struct Gfx_ba0 : Register<0x80, 32> { };
|
||||||
|
struct Gfx_ba1 : Register<0x84, 32> { };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the size of the graphics window
|
* Configures the size of the graphics window
|
||||||
|
|
|
@ -34,11 +34,15 @@ class Framebuffer::Driver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum Mode { MODE_1024_768 };
|
|
||||||
enum Format { FORMAT_RGB565 };
|
enum Format { FORMAT_RGB565 };
|
||||||
|
enum Output { OUTPUT_LCD, OUTPUT_HDMI };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
bool _init_lcd(addr_t phys_base);
|
||||||
|
|
||||||
|
bool _init_hdmi(addr_t phys_base);
|
||||||
|
|
||||||
struct Timer_delayer : Timer::Connection, Mmio::Delayer
|
struct Timer_delayer : Timer::Connection, Mmio::Delayer
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -62,6 +66,10 @@ class Framebuffer::Driver
|
||||||
Attached_io_mem_dataspace _hdmi_mmio;
|
Attached_io_mem_dataspace _hdmi_mmio;
|
||||||
Hdmi _hdmi;
|
Hdmi _hdmi;
|
||||||
|
|
||||||
|
size_t _fb_width;
|
||||||
|
size_t _fb_height;
|
||||||
|
Format _fb_format;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Driver();
|
Driver();
|
||||||
|
@ -74,28 +82,13 @@ class Framebuffer::Driver
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t width(Mode mode)
|
size_t buffer_size(size_t width, size_t height, Format format)
|
||||||
{
|
{
|
||||||
switch (mode) {
|
return bytes_per_pixel(format)*width*height;
|
||||||
case MODE_1024_768: return 1024;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t height(Mode mode)
|
bool init(size_t width, size_t height, Format format,
|
||||||
{
|
Output output, addr_t phys_base);
|
||||||
switch (mode) {
|
|
||||||
case MODE_1024_768: return 768;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t buffer_size(Mode mode, Format format)
|
|
||||||
{
|
|
||||||
return bytes_per_pixel(format)*width(mode)*height(mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool init(Mode mode, Format format, addr_t phys_base);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,13 +101,47 @@ Framebuffer::Driver::Driver()
|
||||||
_dispc((addr_t)_dispc_mmio.local_addr<void>()),
|
_dispc((addr_t)_dispc_mmio.local_addr<void>()),
|
||||||
|
|
||||||
_hdmi_mmio(Board_base::HDMI_MMIO_BASE, Board_base::HDMI_MMIO_SIZE),
|
_hdmi_mmio(Board_base::HDMI_MMIO_BASE, Board_base::HDMI_MMIO_SIZE),
|
||||||
_hdmi((addr_t)_hdmi_mmio.local_addr<void>())
|
_hdmi((addr_t)_hdmi_mmio.local_addr<void>()),
|
||||||
|
|
||||||
|
_fb_width(0),
|
||||||
|
_fb_height(0),
|
||||||
|
_fb_format(FORMAT_RGB565)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
bool Framebuffer::Driver::init(Framebuffer::Driver::Mode mode,
|
bool Framebuffer::Driver::_init_lcd(Framebuffer::addr_t phys_base)
|
||||||
Framebuffer::Driver::Format format,
|
{
|
||||||
Framebuffer::addr_t phys_base)
|
/* disable LCD to allow editing configuration */
|
||||||
|
_dispc.write<Dispc::Control1::Lcd_enable>(0);
|
||||||
|
|
||||||
|
/* set load mode */
|
||||||
|
_dispc.write<Dispc::Config1::Load_mode>(Dispc::Config1::Load_mode::DATA_EVERY_FRAME);
|
||||||
|
|
||||||
|
_dispc.write<Dispc::Size_lcd::Width>(_fb_width - 1);
|
||||||
|
_dispc.write<Dispc::Size_lcd::Height>(_fb_height - 1);
|
||||||
|
|
||||||
|
Dispc::Gfx_attributes::access_t pixel_format = 0;
|
||||||
|
switch (_fb_format) {
|
||||||
|
case FORMAT_RGB565: pixel_format = Dispc::Gfx_attributes::Format::RGB16; break;
|
||||||
|
}
|
||||||
|
_dispc.write<Dispc::Gfx_attributes::Format>(pixel_format);
|
||||||
|
|
||||||
|
_dispc.write<Dispc::Gfx_ba0>(phys_base);
|
||||||
|
_dispc.write<Dispc::Gfx_ba1>(phys_base);
|
||||||
|
|
||||||
|
_dispc.write<Dispc::Gfx_size::Sizex>(_fb_width - 1);
|
||||||
|
_dispc.write<Dispc::Gfx_size::Sizey>(_fb_height - 1);
|
||||||
|
|
||||||
|
_dispc.write<Dispc::Global_buffer>(0x6d2240);
|
||||||
|
_dispc.write<Dispc::Gfx_attributes::Enable>(1);
|
||||||
|
|
||||||
|
_dispc.write<Dispc::Control1::Lcd_enable>(1);
|
||||||
|
_dispc.write<Dispc::Control1::Go_lcd>(1);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Framebuffer::Driver::_init_hdmi(Framebuffer::addr_t phys_base)
|
||||||
{
|
{
|
||||||
/* enable display core clock and set divider to 1 */
|
/* enable display core clock and set divider to 1 */
|
||||||
_dispc.write<Dispc::Divisor::Lcd>(1);
|
_dispc.write<Dispc::Divisor::Lcd>(1);
|
||||||
|
@ -182,8 +209,8 @@ bool Framebuffer::Driver::init(Framebuffer::Driver::Mode mode,
|
||||||
|
|
||||||
_hdmi.write<Hdmi::Video_cfg::Packing_mode>(Hdmi::Video_cfg::Packing_mode::PACK_24B);
|
_hdmi.write<Hdmi::Video_cfg::Packing_mode>(Hdmi::Video_cfg::Packing_mode::PACK_24B);
|
||||||
|
|
||||||
_hdmi.write<Hdmi::Video_size::X>(width(mode));
|
_hdmi.write<Hdmi::Video_size::X>(_fb_height);
|
||||||
_hdmi.write<Hdmi::Video_size::Y>(height(mode));
|
_hdmi.write<Hdmi::Video_size::Y>(_fb_width);
|
||||||
|
|
||||||
_hdmi.write<Hdmi::Video_cfg::Vsp>(0);
|
_hdmi.write<Hdmi::Video_cfg::Vsp>(0);
|
||||||
_hdmi.write<Hdmi::Video_cfg::Hsp>(0);
|
_hdmi.write<Hdmi::Video_cfg::Hsp>(0);
|
||||||
|
@ -192,21 +219,22 @@ bool Framebuffer::Driver::init(Framebuffer::Driver::Mode mode,
|
||||||
|
|
||||||
_dss.write<Dss::Ctrl::Venc_hdmi_switch>(Dss::Ctrl::Venc_hdmi_switch::HDMI);
|
_dss.write<Dss::Ctrl::Venc_hdmi_switch>(Dss::Ctrl::Venc_hdmi_switch::HDMI);
|
||||||
|
|
||||||
_dispc.write<Dispc::Size_tv::Width>(width(mode) - 1);
|
_dispc.write<Dispc::Size_tv::Width>(_fb_width - 1);
|
||||||
_dispc.write<Dispc::Size_tv::Height>(height(mode) - 1);
|
_dispc.write<Dispc::Size_tv::Height>(_fb_height - 1);
|
||||||
|
|
||||||
_hdmi.write<Hdmi::Video_cfg::Start>(1);
|
_hdmi.write<Hdmi::Video_cfg::Start>(1);
|
||||||
|
|
||||||
Dispc::Gfx_attributes::access_t pixel_format = 0;
|
Dispc::Gfx_attributes::access_t pixel_format = 0;
|
||||||
switch (format) {
|
switch (_fb_format) {
|
||||||
case FORMAT_RGB565: pixel_format = Dispc::Gfx_attributes::Format::RGB16; break;
|
case FORMAT_RGB565: pixel_format = Dispc::Gfx_attributes::Format::RGB16; break;
|
||||||
}
|
}
|
||||||
_dispc.write<Dispc::Gfx_attributes::Format>(pixel_format);
|
_dispc.write<Dispc::Gfx_attributes::Format>(pixel_format);
|
||||||
|
|
||||||
|
_dispc.write<Dispc::Gfx_ba0>(phys_base);
|
||||||
_dispc.write<Dispc::Gfx_ba1>(phys_base);
|
_dispc.write<Dispc::Gfx_ba1>(phys_base);
|
||||||
|
|
||||||
_dispc.write<Dispc::Gfx_size::Sizex>(width(mode) - 1);
|
_dispc.write<Dispc::Gfx_size::Sizex>(_fb_width - 1);
|
||||||
_dispc.write<Dispc::Gfx_size::Sizey>(height(mode) - 1);
|
_dispc.write<Dispc::Gfx_size::Sizey>(_fb_height - 1);
|
||||||
|
|
||||||
_dispc.write<Dispc::Global_buffer>(0x6d2240);
|
_dispc.write<Dispc::Global_buffer>(0x6d2240);
|
||||||
_dispc.write<Dispc::Gfx_attributes::Enable>(1);
|
_dispc.write<Dispc::Gfx_attributes::Enable>(1);
|
||||||
|
@ -215,7 +243,6 @@ bool Framebuffer::Driver::init(Framebuffer::Driver::Mode mode,
|
||||||
_dispc.write<Dispc::Gfx_attributes::Channelout2>(Dispc::Gfx_attributes::Channelout2::PRIMARY_LCD);
|
_dispc.write<Dispc::Gfx_attributes::Channelout2>(Dispc::Gfx_attributes::Channelout2::PRIMARY_LCD);
|
||||||
|
|
||||||
_dispc.write<Dispc::Control1::Tv_enable>(1);
|
_dispc.write<Dispc::Control1::Tv_enable>(1);
|
||||||
|
|
||||||
_dispc.write<Dispc::Control1::Go_tv>(1);
|
_dispc.write<Dispc::Control1::Go_tv>(1);
|
||||||
|
|
||||||
if (!_dispc.wait_for<Dispc::Control1::Go_tv>(Dispc::Control1::Go_tv::HW_UPDATE_DONE, _delayer)) {
|
if (!_dispc.wait_for<Dispc::Control1::Go_tv>(Dispc::Control1::Go_tv::HW_UPDATE_DONE, _delayer)) {
|
||||||
|
@ -225,3 +252,27 @@ bool Framebuffer::Driver::init(Framebuffer::Driver::Mode mode,
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Framebuffer::Driver::init(size_t width, size_t height,
|
||||||
|
Framebuffer::Driver::Format format,
|
||||||
|
Output output,
|
||||||
|
Framebuffer::addr_t phys_base)
|
||||||
|
{
|
||||||
|
_fb_width = width;
|
||||||
|
_fb_height = height;
|
||||||
|
_fb_format = format;
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
|
switch (output) {
|
||||||
|
case OUTPUT_LCD:
|
||||||
|
ret = _init_lcd(phys_base);
|
||||||
|
break;
|
||||||
|
case OUTPUT_HDMI:
|
||||||
|
ret = _init_hdmi(phys_base);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PERR("Unknown output %d specified", output);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <dataspace/client.h>
|
#include <dataspace/client.h>
|
||||||
#include <base/printf.h>
|
#include <base/printf.h>
|
||||||
#include <base/sleep.h>
|
#include <base/sleep.h>
|
||||||
|
#include <os/config.h>
|
||||||
#include <os/static_root.h>
|
#include <os/static_root.h>
|
||||||
|
|
||||||
/* local includes */
|
/* local includes */
|
||||||
|
@ -33,7 +34,8 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Framebuffer::Se
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Driver::Mode _mode;
|
size_t _width;
|
||||||
|
size_t _height;
|
||||||
Driver::Format _format;
|
Driver::Format _format;
|
||||||
size_t _size;
|
size_t _size;
|
||||||
Dataspace_capability _ds;
|
Dataspace_capability _ds;
|
||||||
|
@ -52,15 +54,17 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Framebuffer::Se
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Session_component(Driver &driver)
|
Session_component(Driver &driver, size_t width, size_t height,
|
||||||
|
Driver::Output output)
|
||||||
:
|
:
|
||||||
_mode(Driver::MODE_1024_768),
|
_width(width),
|
||||||
|
_height(height),
|
||||||
_format(Driver::FORMAT_RGB565),
|
_format(Driver::FORMAT_RGB565),
|
||||||
_size(Driver::buffer_size(_mode, _format)),
|
_size(driver.buffer_size(width, height, _format)),
|
||||||
_ds(env()->ram_session()->alloc(_size, false)),
|
_ds(env()->ram_session()->alloc(_size, false)),
|
||||||
_phys_base(Dataspace_client(_ds).phys_addr())
|
_phys_base(Dataspace_client(_ds).phys_addr())
|
||||||
{
|
{
|
||||||
if (!driver.init(_mode, _format, _phys_base)) {
|
if (!driver.init(width, height, _format, output, _phys_base)) {
|
||||||
PERR("Could not initialize display");
|
PERR("Could not initialize display");
|
||||||
struct Could_not_initialize_display : Exception { };
|
struct Could_not_initialize_display : Exception { };
|
||||||
throw Could_not_initialize_display();
|
throw Could_not_initialize_display();
|
||||||
|
@ -77,8 +81,8 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Framebuffer::Se
|
||||||
|
|
||||||
Mode mode() const
|
Mode mode() const
|
||||||
{
|
{
|
||||||
return Mode(Driver::width(_mode),
|
return Mode(_width,
|
||||||
Driver::height(_mode),
|
_height,
|
||||||
_convert_format(_format));
|
_convert_format(_format));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,6 +96,27 @@ int main(int, char **)
|
||||||
{
|
{
|
||||||
using namespace Framebuffer;
|
using namespace Framebuffer;
|
||||||
|
|
||||||
|
size_t width = 1024;
|
||||||
|
size_t height = 768;
|
||||||
|
Driver::Output output = Driver::OUTPUT_HDMI;
|
||||||
|
try {
|
||||||
|
char out[5] = {};
|
||||||
|
Genode::Xml_node config_node = Genode::config()->xml_node();
|
||||||
|
config_node.attribute("width").value(&width);
|
||||||
|
config_node.attribute("height").value(&height);
|
||||||
|
config_node.attribute("output").value(out, sizeof(out));
|
||||||
|
if (!Genode::strcmp(out, "LCD")) {
|
||||||
|
output = Driver::OUTPUT_LCD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Genode::Xml_node::Nonexistent_attribute) {
|
||||||
|
PERR("incorrect configuration, aborting");
|
||||||
|
throw Root::Invalid_args();
|
||||||
|
}
|
||||||
|
catch (Genode::Xml_node::Nonexistent_sub_node) {
|
||||||
|
PDBG("using default configuration: HDMI@%dx%d", width, height);
|
||||||
|
}
|
||||||
|
|
||||||
static Driver driver;
|
static Driver driver;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -104,7 +129,7 @@ int main(int, char **)
|
||||||
/*
|
/*
|
||||||
* Let the entry point serve the framebuffer session and root interfaces
|
* Let the entry point serve the framebuffer session and root interfaces
|
||||||
*/
|
*/
|
||||||
static Session_component fb_session(driver);
|
static Session_component fb_session(driver, width, height, output);
|
||||||
static Static_root<Framebuffer::Session> fb_root(ep.manage(&fb_session));
|
static Static_root<Framebuffer::Session> fb_root(ep.manage(&fb_session));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue