diff --git a/os/run/framebuffer.run b/os/run/framebuffer.run
index 08c9f6d0f9..e4fce354f1 100755
--- a/os/run/framebuffer.run
+++ b/os/run/framebuffer.run
@@ -60,7 +60,7 @@ append_if [have_spec omap4] config {
-
+
}
@@ -88,7 +88,7 @@ lappend_if [have_spec sdl] boot_modules fb_sdl
lappend_if [have_spec pci] boot_modules pci_drv
lappend_if [have_spec vesa] boot_modules vesa_drv
lappend_if [have_spec pl11x] boot_modules pl11x_drv
-lappend_if [have_spec omap4] boot_modules omap44xx_fb_drv
+lappend_if [have_spec omap4] boot_modules omap4_fb_drv
build_boot_image $boot_modules
diff --git a/os/src/drivers/framebuffer/omap4/dispc.h b/os/src/drivers/framebuffer/omap4/dispc.h
new file mode 100644
index 0000000000..fa1a3ee0a9
--- /dev/null
+++ b/os/src/drivers/framebuffer/omap4/dispc.h
@@ -0,0 +1,111 @@
+/*
+ * \brief Display controller
+ * \author Martin Stein
+ * \author Norman Feske
+ * \date 2012-06-11
+ */
+
+#ifndef _DISPC_H_
+#define _DISPC_H_
+
+/* local includes */
+#include
+
+struct Dispc : Mmio
+{
+ /**
+ * Configures the display controller module for outputs LCD 1 and TV
+ */
+ struct Control1 : Register<0x40, 32>
+ {
+ struct Tv_enable : Bitfield<1, 1> { };
+
+ struct Go_tv : Bitfield<6, 1>
+ {
+ enum { HW_UPDATE_DONE = 0x0, /* set by HW after updating */
+ REQUEST_HW_UPDATE = 0x1 }; /* must be set by user */
+ };
+ };
+
+ /**
+ * Configures the display controller module for outputs LCD 1 and TV
+ */
+ struct Config1 : Register<0x44, 32>
+ {
+ /**
+ * Loading of palette/gamma table
+ */
+ struct Load_mode : Bitfield<1, 2>
+ {
+ enum { DATA_EVERY_FRAME = 0x2, };
+ };
+ };
+
+ struct Size_tv : Register<0x78, 32>
+ {
+ struct Width : Bitfield<0, 11> { };
+ struct Height : Bitfield<16, 11> { };
+ };
+
+ /**
+ * Configures base address of the graphics buffer
+ */
+ struct Gfx_ba1 : Register<0x80, 32> { };
+
+ /**
+ * Configures the size of the graphics window
+ */
+ struct Gfx_size : Register<0x8c, 32>
+ {
+ struct Sizex : Bitfield<0,11> { };
+ struct Sizey : Bitfield<16,11> { };
+ };
+
+ /**
+ * Configures the graphics attributes
+ */
+ struct Gfx_attributes : Register<0xa0, 32>
+ {
+ struct Enable : Bitfield<0, 1> { };
+
+ struct Format : Bitfield<1, 5>
+ {
+ enum { RGB16 = 0x6,
+ ARGB32 = 0xc,
+ RGBA32 = 0xd };
+ };
+
+ /**
+ * Select GFX channel output
+ */
+ struct Channelout : Bitfield<8, 1>
+ {
+ enum { TV = 0x1 };
+ };
+
+ struct Channelout2 : Bitfield<30, 2>
+ {
+ enum { PRIMARY_LCD = 0 };
+ };
+ };
+
+ struct Global_buffer : Register<0x800, 32> { };
+
+ struct Divisor : Register<0x804, 32>
+ {
+ struct Enable : Bitfield<0, 1> { };
+ struct Lcd : Bitfield<16, 8> { };
+ };
+
+ /**
+ * Constructor
+ *
+ * \param mmio_base base address of DISPC MMIO
+ */
+ Dispc(Genode::addr_t const mmio_base)
+ :
+ Mmio(mmio_base)
+ { }
+};
+
+#endif /* _DISPC_H_ */
diff --git a/os/src/drivers/framebuffer/omap4/dss.h b/os/src/drivers/framebuffer/omap4/dss.h
new file mode 100644
index 0000000000..3090ea160b
--- /dev/null
+++ b/os/src/drivers/framebuffer/omap4/dss.h
@@ -0,0 +1,29 @@
+/*
+ * \brief General display subsystem registers
+ * \author Norman Feske
+ * \date 2012-06-11
+ */
+
+#ifndef _DSS_H_
+#define _DSS_H_
+
+/* local includes */
+#include
+
+struct Dss : Genode::Mmio
+{
+ Dss(Genode::addr_t const mmio_base) : Genode::Mmio(mmio_base) { }
+
+ struct Sysstatus : Register<0x14, 32> { };
+
+ struct Ctrl : Register<0x40, 32>
+ {
+ struct Venc_hdmi_switch : Bitfield<15, 1>
+ {
+ enum { HDMI = 1 };
+ };
+ };
+ struct Status : Register<0x5c, 32> { };
+};
+
+#endif /* _DSS_H_ */
diff --git a/os/src/drivers/framebuffer/omap4/hdmi.h b/os/src/drivers/framebuffer/omap4/hdmi.h
new file mode 100644
index 0000000000..d153e7496a
--- /dev/null
+++ b/os/src/drivers/framebuffer/omap4/hdmi.h
@@ -0,0 +1,156 @@
+/*
+ * \brief HDMI subsystem registers
+ * \author Norman Feske
+ * \date 2012-06-11
+ */
+
+#ifndef _HDMI_H_
+#define _HDMI_H_
+
+/* local includes */
+#include
+
+struct Hdmi : Mmio
+{
+ struct Pwr_ctrl : Register<0x40, 32>
+ {
+ enum Pll_cmd_type { ALL_OFF = 0,
+ BOTH_ON_ALL_CLKS = 2, };
+
+ struct Pll_cmd : Bitfield<2, 2> { };
+ struct Pll_status : Bitfield<0, 2> { };
+
+ enum Phy_cmd_type { LDOON = 1,
+ TXON = 2 };
+
+ struct Phy_cmd : Bitfield<6, 2> { };
+ struct Phy_status : Bitfield<4, 2> { };
+
+ };
+
+ struct Video_cfg : Register<0x50, 32>
+ {
+ struct Start : Bitfield<31, 1> { };
+
+ struct Packing_mode : Bitfield<8, 3>
+ {
+ enum { PACK_24B = 1 };
+ };
+
+ struct Vsp : Bitfield<7, 1> { };
+ struct Hsp : Bitfield<6, 1> { };
+ struct Interlacing : Bitfield<3, 1> { };
+ struct Tm : Bitfield<0, 2> { };
+ };
+
+ struct Video_size : Register<0x60, 32>
+ {
+ struct X : Bitfield<0, 16> { };
+ struct Y : Bitfield<16, 16> { };
+ };
+
+ struct Video_timing_h : Register<0x68, 32>
+ {
+ struct Bp : Bitfield<20, 12> { };
+ struct Fp : Bitfield<8, 12> { };
+ struct Sw : Bitfield<0, 8> { };
+ };
+
+ struct Video_timing_v : Register<0x6c, 32>
+ {
+ struct Bp : Bitfield<20, 12> { };
+ struct Fp : Bitfield<8, 12> { };
+ struct Sw : Bitfield<0, 8> { };
+ };
+
+ /**
+ * \return true on success
+ */
+ bool issue_pwr_pll_command(Pwr_ctrl::Pll_cmd_type cmd, Delayer &delayer)
+ {
+ write(cmd);
+
+ return wait_for(cmd, delayer);
+ }
+
+ bool issue_pwr_phy_command(Pwr_ctrl::Phy_cmd_type cmd, Delayer &delayer)
+ {
+ write(cmd);
+
+ return wait_for(cmd, delayer);
+ }
+
+ struct Pll_control : Register<0x200, 32>
+ {
+ struct Mode : Bitfield<0, 1>
+ {
+ enum { MANUAL = 0 };
+ };
+
+ struct Reset : Bitfield<3, 1> { };
+ };
+
+ struct Pll_status : Register<0x204, 32>
+ {
+ struct Reset_done : Bitfield<0, 1> { };
+ struct Pll_locked : Bitfield<1, 1> { };
+ };
+
+ bool wait_until_pll_locked(Delayer &delayer)
+ {
+ return wait_for(1, delayer);
+ };
+
+ struct Pll_go : Register<0x208, 32>
+ {
+ struct Go : Bitfield<0, 1> { };
+ };
+
+ bool pll_go(Delayer &delayer)
+ {
+ write(1);
+
+ /* wait for PLL_GO bit change and the PLL reaching locked state */
+ return wait_for(1, delayer)
+ && wait_until_pll_locked(delayer);
+ }
+
+ struct Cfg1 : Register<0x20c, 32>
+ {
+ struct Regm : Bitfield<9, 12> { };
+ struct Regn : Bitfield<1, 8> { };
+ };
+
+ struct Cfg2 : Register<0x210, 32>
+ {
+ struct Highfreq_div_by_2 : Bitfield<12, 1> { };
+ struct Refen : Bitfield<13, 1> { };
+ struct Clkinen : Bitfield<14, 1> { };
+ struct Refsel : Bitfield<21, 2> { };
+ struct Freq_divider : Bitfield<1, 3> { };
+ };
+
+ struct Cfg4 : Register<0x220, 32>
+ {
+ struct Regm2 : Bitfield<18, 7> { };
+ struct Regmf : Bitfield<0, 18> { };
+ };
+
+ bool reset_pll(Delayer &delayer)
+ {
+ write(0);
+
+ return wait_for(1, delayer);
+ };
+
+ struct Txphy_tx_ctrl : Register<0x300, 32>
+ {
+ struct Freqout : Bitfield<30, 2> { };
+ };
+
+ struct Txphy_digital_ctrl : Register<0x304, 32> { };
+
+ Hdmi(Genode::addr_t const mmio_base) : Mmio(mmio_base) { }
+};
+
+#endif /* _HDMI_H_ */
diff --git a/os/src/drivers/framebuffer/omap4/main.cc b/os/src/drivers/framebuffer/omap4/main.cc
new file mode 100644
index 0000000000..38b64afd19
--- /dev/null
+++ b/os/src/drivers/framebuffer/omap4/main.cc
@@ -0,0 +1,209 @@
+/*
+ * \brief Frame-buffer driver for the OMAP4430 display-subsystem (HDMI)
+ * \author Norman Feske
+ * \author Martin Stein
+ * \date 2012-06-01
+ */
+
+/*
+ * Copyright (C) 2012 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+/* Genode includes */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* local includes */
+#include
+#include
+#include
+#include
+
+
+int main(int, char **)
+{
+ using namespace Genode;
+ printf("--- omap44xx framebuffer driver ---\n");
+
+ struct Timer_delayer : Timer::Connection, Delayer
+ {
+ /**
+ * Implementation of 'Delayer' interface
+ */
+ void usleep(unsigned us)
+ {
+ /* polling */
+ if (us == 0)
+ return;
+
+ unsigned ms = us / 1000;
+ if (ms == 0)
+ ms = 1;
+
+ Timer::Connection::msleep(ms);
+ }
+ };
+
+ static Timer_delayer delayer;
+
+ /* memory map */
+ enum {
+ DSS_MMIO_BASE = 0x58000000,
+ DSS_MMIO_SIZE = 0x00001000,
+
+ DISPC_MMIO_BASE = 0x58001000,
+ DISPC_MMIO_SIZE = 0x1000,
+
+ HDMI_MMIO_BASE = 0x58006000,
+ HDMI_MMIO_SIZE = 0x1000,
+ };
+
+ /*
+ * Obtain MMIO resources
+ */
+
+ /* display sub system registers */
+ Attached_io_mem_dataspace dss_mmio(DSS_MMIO_BASE, DSS_MMIO_SIZE);
+ Dss dss((addr_t)dss_mmio.local_addr());
+
+ /* display controller registers */
+ Attached_io_mem_dataspace dispc_mmio(DISPC_MMIO_BASE, DISPC_MMIO_SIZE);
+ Dispc dispc((addr_t)dispc_mmio.local_addr());
+
+ /* HDMI controller registers */
+ Attached_io_mem_dataspace hdmi_mmio(HDMI_MMIO_BASE, HDMI_MMIO_SIZE);
+ Hdmi hdmi((addr_t)hdmi_mmio.local_addr());
+
+ /* enable display core clock and set divider to 1 */
+ dispc.write(1);
+ dispc.write(1);
+
+ /* set load mode */
+ dispc.write(Dispc::Config1::Load_mode::DATA_EVERY_FRAME);
+
+ hdmi.write(0);
+
+ if (!hdmi.issue_pwr_pll_command(Hdmi::Pwr_ctrl::ALL_OFF, delayer)) {
+ PERR("Powering off HDMI timed out\n");
+ return 1;
+ }
+
+ if (!hdmi.issue_pwr_pll_command(Hdmi::Pwr_ctrl::BOTH_ON_ALL_CLKS, delayer)) {
+ PERR("Powering on HDMI timed out\n");
+ return 2;
+ }
+
+ if (!hdmi.reset_pll(delayer)) {
+ PERR("Resetting HDMI PLL timed out\n");
+ return 3;
+ }
+
+ hdmi.write(Hdmi::Pll_control::Mode::MANUAL);
+
+ hdmi.write(270);
+ hdmi.write(15);
+
+ hdmi.write(0);
+ hdmi.write(1);
+ hdmi.write(0);
+ hdmi.write(3);
+ hdmi.write(2);
+
+ hdmi.write(1);
+ hdmi.write(0x35555);
+
+ if (!hdmi.pll_go(delayer)) {
+ PERR("HDMI PLL GO timed out");
+ return 4;
+ }
+
+ if (!hdmi.issue_pwr_phy_command(Hdmi::Pwr_ctrl::LDOON, delayer)) {
+ PERR("HDMI Phy power on timed out");
+ return 5;
+ }
+
+ hdmi.write(1);
+ hdmi.write(0xf0000000);
+
+ if (!hdmi.issue_pwr_phy_command(Hdmi::Pwr_ctrl::TXON, delayer)) {
+ PERR("HDMI Txphy power on timed out");
+ return 6;
+ }
+
+ hdmi.write(160);
+ hdmi.write(24);
+ hdmi.write(136);
+
+ hdmi.write(29);
+ hdmi.write(3);
+ hdmi.write(6);
+
+ hdmi.write(Hdmi::Video_cfg::Packing_mode::PACK_24B);
+
+ hdmi.write(1024);
+ hdmi.write(768);
+
+ hdmi.write(0);
+ hdmi.write(0);
+ hdmi.write(0);
+ hdmi.write(1);
+
+ dss.write(Dss::Ctrl::Venc_hdmi_switch::HDMI);
+
+ dispc.write(1024 - 1);
+ dispc.write(768 - 1);
+
+ hdmi.write(1);
+
+ dispc.write(Dispc::Gfx_attributes::Format::RGB16);
+
+ typedef Genode::uint16_t pixel_t;
+
+ Genode::Dataspace_capability fb_ds =
+ Genode::env()->ram_session()->alloc(1024*768*sizeof(pixel_t), false);
+
+ Genode::addr_t fb_phys_base = Genode::Dataspace_client(fb_ds).phys_addr();
+
+ dispc.write(fb_phys_base);
+
+ dispc.write(1024 - 1);
+ dispc.write(768 - 1);
+
+ dispc.write(0x6d2240);
+ dispc.write(1);
+
+ dispc.write(Dispc::Gfx_attributes::Channelout::TV);
+ 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)) {
+ PERR("Go_tv timed out");
+ return 6;
+ }
+
+ pixel_t *fb_local_base = Genode::env()->rm_session()->attach(fb_ds);
+ for (unsigned y = 0; y < 768; y++) {
+ for (unsigned x = 0; x < 1024; x++) {
+ fb_local_base[y*1024 + x] = (x & 0x1f);
+ fb_local_base[y*1024 + x] |= ((y) & 0x1f) << 11;
+ fb_local_base[y*1024 + x] |= ((x + y) & 0x3f) << 5;
+ }
+ }
+
+ PINF("done");
+ sleep_forever();
+ return 0;
+}
+
diff --git a/os/src/drivers/framebuffer/omap4/mmio.h b/os/src/drivers/framebuffer/omap4/mmio.h
new file mode 100644
index 0000000000..2166b58493
--- /dev/null
+++ b/os/src/drivers/framebuffer/omap4/mmio.h
@@ -0,0 +1,42 @@
+/*
+ * \brief Utilities for accessing MMIO registers
+ * \author Norman Feske
+ * \date 2012-06-15
+ */
+
+#ifndef _MMIO_H_
+#define _MMIO_H_
+
+#include
+
+/* Genode includes */
+#include
+
+struct Delayer
+{
+ virtual void usleep(unsigned us) = 0;
+};
+
+/**
+ * Extend 'Genode::Mmio' framework with the ability to poll for bitfield states
+ */
+struct Mmio : Genode::Mmio
+{
+ template
+ inline bool wait_for(typename BITFIELD::Compound_reg::access_t const value,
+ Delayer &delayer,
+ unsigned max_attempts = 500,
+ unsigned delay_us = 1000)
+ {
+ for (unsigned i = 0; i < max_attempts; i++, delayer.usleep(delay_us))
+ if (read() == value)
+ return true;
+
+ return false;
+ }
+
+ Mmio(Genode::addr_t mmio_base) : Genode::Mmio(mmio_base) { }
+};
+
+
+#endif /* _MMIO_H_ */
diff --git a/os/src/drivers/framebuffer/omap4/target.mk b/os/src/drivers/framebuffer/omap4/target.mk
new file mode 100644
index 0000000000..378aa2c82a
--- /dev/null
+++ b/os/src/drivers/framebuffer/omap4/target.mk
@@ -0,0 +1,14 @@
+#
+# \brief Framebuffer driver specific for OMAP44xx systems
+# \author Martin Stein
+# \date 2012-05-02
+#
+
+TARGET = omap4_fb_drv
+REQUIRES = omap4
+SRC_CC = main.cc
+LIBS = cxx env server
+INC_DIR += $(PRG_DIR)
+
+vpath main.cc $(PRG_DIR)
+