diff --git a/os/src/drivers/framebuffer/omap4/dispc.h b/os/src/drivers/framebuffer/omap4/dispc.h index 23f80dfe2..840c116c6 100644 --- a/os/src/drivers/framebuffer/omap4/dispc.h +++ b/os/src/drivers/framebuffer/omap4/dispc.h @@ -18,8 +18,13 @@ struct Dispc : Genode::Mmio */ struct Control1 : Register<0x40, 32> { + struct Lcd_enable : Bitfield<0, 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> { enum { HW_UPDATE_DONE = 0x0, /* set by HW after updating */ @@ -46,11 +51,17 @@ struct Dispc : Genode::Mmio struct Width : Bitfield<0, 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 */ - 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 diff --git a/os/src/drivers/framebuffer/omap4/driver.h b/os/src/drivers/framebuffer/omap4/driver.h index d754a97b4..83eed41fe 100644 --- a/os/src/drivers/framebuffer/omap4/driver.h +++ b/os/src/drivers/framebuffer/omap4/driver.h @@ -34,11 +34,15 @@ class Framebuffer::Driver { public: - enum Mode { MODE_1024_768 }; enum Format { FORMAT_RGB565 }; + enum Output { OUTPUT_LCD, OUTPUT_HDMI }; private: + bool _init_lcd(addr_t phys_base); + + bool _init_hdmi(addr_t phys_base); + struct Timer_delayer : Timer::Connection, Mmio::Delayer { /** @@ -62,6 +66,10 @@ class Framebuffer::Driver Attached_io_mem_dataspace _hdmi_mmio; Hdmi _hdmi; + size_t _fb_width; + size_t _fb_height; + Format _fb_format; + public: Driver(); @@ -74,28 +82,13 @@ class Framebuffer::Driver return 0; } - static size_t width(Mode mode) + size_t buffer_size(size_t width, size_t height, Format format) { - switch (mode) { - case MODE_1024_768: return 1024; - } - return 0; + return bytes_per_pixel(format)*width*height; } - static size_t height(Mode mode) - { - 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); + bool init(size_t width, size_t height, Format format, + Output output, addr_t phys_base); }; @@ -108,13 +101,47 @@ Framebuffer::Driver::Driver() _dispc((addr_t)_dispc_mmio.local_addr()), _hdmi_mmio(Board_base::HDMI_MMIO_BASE, Board_base::HDMI_MMIO_SIZE), - _hdmi((addr_t)_hdmi_mmio.local_addr()) + _hdmi((addr_t)_hdmi_mmio.local_addr()), + + _fb_width(0), + _fb_height(0), + _fb_format(FORMAT_RGB565) { } -bool Framebuffer::Driver::init(Framebuffer::Driver::Mode mode, - Framebuffer::Driver::Format format, - Framebuffer::addr_t phys_base) +bool Framebuffer::Driver::_init_lcd(Framebuffer::addr_t phys_base) +{ + /* disable LCD to allow editing configuration */ + _dispc.write(0); + + /* set load mode */ + _dispc.write(Dispc::Config1::Load_mode::DATA_EVERY_FRAME); + + _dispc.write(_fb_width - 1); + _dispc.write(_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(pixel_format); + + _dispc.write(phys_base); + _dispc.write(phys_base); + + _dispc.write(_fb_width - 1); + _dispc.write(_fb_height - 1); + + _dispc.write(0x6d2240); + _dispc.write(1); + + _dispc.write(1); + _dispc.write(1); + + return true; +} + +bool Framebuffer::Driver::_init_hdmi(Framebuffer::addr_t phys_base) { /* enable display core clock and set divider to 1 */ _dispc.write(1); @@ -182,8 +209,8 @@ bool Framebuffer::Driver::init(Framebuffer::Driver::Mode mode, _hdmi.write(Hdmi::Video_cfg::Packing_mode::PACK_24B); - _hdmi.write(width(mode)); - _hdmi.write(height(mode)); + _hdmi.write(_fb_height); + _hdmi.write(_fb_width); _hdmi.write(0); _hdmi.write(0); @@ -192,21 +219,22 @@ bool Framebuffer::Driver::init(Framebuffer::Driver::Mode mode, _dss.write(Dss::Ctrl::Venc_hdmi_switch::HDMI); - _dispc.write(width(mode) - 1); - _dispc.write(height(mode) - 1); + _dispc.write(_fb_width - 1); + _dispc.write(_fb_height - 1); _hdmi.write(1); Dispc::Gfx_attributes::access_t pixel_format = 0; - switch (format) { + switch (_fb_format) { case FORMAT_RGB565: pixel_format = Dispc::Gfx_attributes::Format::RGB16; break; } _dispc.write(pixel_format); + _dispc.write(phys_base); _dispc.write(phys_base); - _dispc.write(width(mode) - 1); - _dispc.write(height(mode) - 1); + _dispc.write(_fb_width - 1); + _dispc.write(_fb_height - 1); _dispc.write(0x6d2240); _dispc.write(1); @@ -215,7 +243,6 @@ bool Framebuffer::Driver::init(Framebuffer::Driver::Mode mode, _dispc.write(Dispc::Gfx_attributes::Channelout2::PRIMARY_LCD); _dispc.write(1); - _dispc.write(1); if (!_dispc.wait_for(Dispc::Control1::Go_tv::HW_UPDATE_DONE, _delayer)) { @@ -225,3 +252,27 @@ bool Framebuffer::Driver::init(Framebuffer::Driver::Mode mode, 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; +} diff --git a/os/src/drivers/framebuffer/omap4/main.cc b/os/src/drivers/framebuffer/omap4/main.cc index bea7a9930..c5a237a14 100644 --- a/os/src/drivers/framebuffer/omap4/main.cc +++ b/os/src/drivers/framebuffer/omap4/main.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include /* local includes */ @@ -33,7 +34,8 @@ class Framebuffer::Session_component : public Genode::Rpc_objectram_session()->alloc(_size, false)), _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"); struct Could_not_initialize_display : Exception { }; throw Could_not_initialize_display(); @@ -77,8 +81,8 @@ class Framebuffer::Session_component : public Genode::Rpc_objectxml_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; /* @@ -104,7 +129,7 @@ int main(int, char **) /* * 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 fb_root(ep.manage(&fb_session)); /*