Rework i.MX53 framebuffer driver

* Simplify IPU register definitions using templates
* Distinguish between i.MX53 QSB and SMD board in driver
* Support IPU specific overlay mechanism by framebuffer session extension
This commit is contained in:
Stefan Kalkowski 2013-04-30 15:19:18 +02:00 committed by Norman Feske
parent 4fe158a320
commit 0950b2f340
14 changed files with 894 additions and 337 deletions

View File

@ -49,6 +49,9 @@ namespace Genode
IOMUXC_BASE = 0x53fa8000,
IOMUXC_SIZE = 0x00004000,
PWM2_BASE = 0x53fb8000,
PWM2_SIZE = 0x00004000,
IPU_ERR_IRQ = 10,
IPU_SYNC_IRQ = 11,
IPU_BASE = 0x18000000,
@ -60,6 +63,9 @@ namespace Genode
CCM_BASE = 0x53FD4000,
CCM_SIZE = 0x00004000,
IIM_BASE = 0x63f98000,
IIM_SIZE = 0x00004000,
SECURITY_EXTENSION = 1,
};
};

View File

@ -0,0 +1,46 @@
/*
* \brief Client-side i.MX53 specific framebuffer interface
* \author Stefan Kalkowski
* \date 2013-02-26
*/
/*
* Copyright (C) 2006-2013 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.
*/
#ifndef _INCLUDE__IMX_FRAMEBUFFER_SESSION__CLIENT_H_
#define _INCLUDE__IMX_FRAMEBUFFER_SESSION__CLIENT_H_
#include <framebuffer_session/capability.h>
#include <imx_framebuffer_session/imx_framebuffer_session.h>
#include <base/rpc_client.h>
namespace Framebuffer {
struct Imx_client : Genode::Rpc_client<Imx_session>
{
explicit Imx_client(Capability<Imx_session> session)
: Genode::Rpc_client<Imx_session>(session) { }
Genode::Dataspace_capability dataspace() {
return call<Rpc_dataspace>(); }
void release() { call<Rpc_release>(); }
Mode mode() const { return call<Rpc_mode>(); }
void mode_sigh(Genode::Signal_context_capability sigh) {
call<Rpc_mode_sigh>(sigh); }
void refresh(int x, int y, int w, int h) {
call<Rpc_refresh>(x, y, w, h); }
void overlay(Genode::addr_t phys_addr, int x, int y, int alpha) {
call<Rpc_overlay>(phys_addr, x, y, alpha); }
};
}
#endif /* _INCLUDE__IMX_FRAMEBUFFER_SESSION__CLIENT_H_ */

View File

@ -0,0 +1,74 @@
/*
* \brief Connection to i.MX53 specific frame-buffer service
* \author Stefan Kalkowski
* \date 2013-02-26
*/
/*
* Copyright (C) 2008-2013 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.
*/
#ifndef _INCLUDE__IMX_FRAMEBUFFER_SESSION__CONNECTION_H_
#define _INCLUDE__IMX_FRAMEBUFFER_SESSION__CONNECTION_H_
#include <imx_framebuffer_session/client.h>
#include <util/arg_string.h>
#include <base/connection.h>
namespace Framebuffer {
class Imx_connection : public Genode::Connection<Imx_session>,
public Imx_client
{
private:
/**
* Create session and return typed session capability
*/
Capability<Imx_session> _connect(unsigned width, unsigned height,
Mode::Format format)
{
using namespace Genode;
enum { ARGBUF_SIZE = 128 };
char argbuf[ARGBUF_SIZE];
/* donate ram quota for storing server-side meta data */
strncpy(argbuf, "ram_quota=8K", sizeof(argbuf));
/* set optional session-constructor arguments */
if (width)
Arg_string::set_arg(argbuf, sizeof(argbuf), "fb_width", width);
if (height)
Arg_string::set_arg(argbuf, sizeof(argbuf), "fb_height", height);
if (format != Mode::INVALID)
Arg_string::set_arg(argbuf, sizeof(argbuf), "fb_format", format);
return session(argbuf);
}
public:
/**
* Constructor
*
* \param width desired frame-buffer width
* \param height desired frame-buffer height
* \param mode desired pixel format
*
* The specified values are not enforced. After creating the
* session, you should validate the actual frame-buffer attributes
* by calling the 'info' function of the frame-buffer interface.
*/
Imx_connection(unsigned width = 0,
unsigned height = 0,
Mode::Format format = Mode::INVALID)
: Genode::Connection<Imx_session>(_connect(width, height, format)),
Imx_client(cap()) { }
};
}
#endif /* _INCLUDE__IMX_FRAMEBUFFER_SESSION__CONNECTION_H_ */

View File

@ -0,0 +1,48 @@
/*
* \brief i.MX53 specific framebuffer session extension
* \author Stefan Kalkowski
* \date 2013-02-26
*/
/*
* Copyright (C) 2011-2013 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.
*/
#ifndef _INCLUDE__IMX_FRAMEBUFFER_SESSION__IMX_FRAMEBUFFER_SESSION_H_
#define _INCLUDE__IMX_FRAMEBUFFER_SESSION__IMX_FRAMEBUFFER_SESSION_H_
#include <base/capability.h>
#include <base/rpc.h>
#include <framebuffer_session/framebuffer_session.h>
namespace Framebuffer {
struct Imx_session : Session
{
virtual ~Imx_session() { }
/**
* Set overlay properties
*
* \param phys_base physical base address of overlay framebuffer
* \param x horizontal position in pixel
* \param y vertical position in pixel
* \param alpha alpha transparency value of overlay (0-255)
*/
virtual void overlay(Genode::addr_t phys_base, int x, int y, int alpha) = 0;
/*********************
** RPC declaration **
*********************/
GENODE_RPC(Rpc_overlay, void, overlay, Genode::addr_t, int, int, int);
GENODE_RPC_INTERFACE_INHERIT(Session, Rpc_overlay);
};
}
#endif /* _INCLUDE__IMX_FRAMEBUFFER_SESSION__IMX_FRAMEBUFFER_SESSION_H_ */

View File

@ -29,6 +29,7 @@ namespace Platform {
void disable(Device dev) { call<Rpc_disable>(dev); }
void clock_rate(Device dev, unsigned long rate) {
call<Rpc_clock_rate>(dev, rate); }
Board_revision revision() { return call<Rpc_revision>(); }
};
}

View File

@ -23,13 +23,20 @@ namespace Platform {
{
enum Device { IPU };
enum Board_revision {
SMD = 2, /* Freescale i.MX53 SMD Tablet */
QSB = 3, /* Freescale i.MX53 low-cost Quickstart board */
UNKNOWN,
};
static const char *service_name() { return "Platform"; }
virtual ~Session() { }
virtual void enable(Device dev) = 0;
virtual void disable(Device dev) = 0;
virtual void enable(Device dev) = 0;
virtual void disable(Device dev) = 0;
virtual void clock_rate(Device dev, unsigned long rate) = 0;
virtual Board_revision revision() = 0;
/*********************
@ -39,8 +46,10 @@ namespace Platform {
GENODE_RPC(Rpc_enable, void, enable, Device);
GENODE_RPC(Rpc_disable, void, disable, Device);
GENODE_RPC(Rpc_clock_rate, void, clock_rate, Device, unsigned long);
GENODE_RPC(Rpc_revision, Board_revision, revision);
GENODE_RPC_INTERFACE(Rpc_enable, Rpc_disable, Rpc_clock_rate);
GENODE_RPC_INTERFACE(Rpc_enable, Rpc_disable, Rpc_clock_rate,
Rpc_revision);
};
}

View File

@ -14,6 +14,7 @@
/* local includes */
#include <ipu.h>
#include <pwm.h>
namespace Framebuffer {
@ -26,48 +27,68 @@ class Framebuffer::Driver
{
private:
Platform::Connection _platform;
Attached_io_mem_dataspace _ipu_mmio; /* Image processing unit memory */
Ipu _ipu;
Gpio::Connection _gpio;
Platform::Connection _platform;
Attached_io_mem_dataspace _ipu_mmio;
Ipu _ipu;
Attached_io_mem_dataspace _pwm_mmio;
Pwm _pwm;
Gpio::Connection _gpio;
Platform::Session::Board_revision _board;
size_t _width;
size_t _height;
public:
enum {
REFRESH = 60,
WIDTH = 800,
HEIGHT = 480,
PIX_CLK = 29850,
ROUND_PIX_CLK = 38000,
LEFT_MARGIN = 89,
RIGHT_MARGIN = 104,
UPPER_MARGIN = 10,
LOWER_MARGIN = 10,
VSYNC_LEN = 10,
HSYNC_LEN = 10,
enum Resolutions {
QSB_WIDTH = 800,
QSB_HEIGHT = 480,
SMD_WIDTH = 1024,
SMD_HEIGHT = 768,
BYTES_PER_PIXEL = 2,
FRAMEBUFFER_SIZE = WIDTH * HEIGHT * BYTES_PER_PIXEL,
};
enum Gpio_pins {
LCD_BL_GPIO = 88,
LCD_CONT_GPIO = 1,
};
Driver()
: _ipu_mmio(Board_base::IPU_BASE, Board_base::IPU_SIZE),
_ipu((addr_t)_ipu_mmio.local_addr<void>()) { }
_ipu((addr_t)_ipu_mmio.local_addr<void>()),
_pwm_mmio(Board_base::PWM2_BASE, Board_base::PWM2_SIZE),
_pwm((addr_t)_pwm_mmio.local_addr<void>()),
_board(_platform.revision()),
_width(_board == Platform::Session::QSB ? QSB_WIDTH : SMD_WIDTH),
_height(_board == Platform::Session::QSB ? QSB_HEIGHT : SMD_HEIGHT) { }
bool init(addr_t phys_base)
{
/* enable IPU via platform driver */
_platform.enable(Platform::Session::IPU);
_ipu.init(WIDTH, HEIGHT, WIDTH * BYTES_PER_PIXEL, phys_base);
switch (_board) {
case Platform::Session::QSB:
_ipu.init(_width, _height, _width * BYTES_PER_PIXEL,
phys_base, true);
/* Turn on lcd power */
_gpio.direction_output(LCD_BL_GPIO, true);
_gpio.direction_output(LCD_CONT_GPIO, true);
/* Turn display */
_gpio.direction_output(LCD_BL_GPIO, true);
_gpio.direction_output(LCD_CONT_GPIO, true);
break;
case Platform::Session::SMD:
_ipu.init(_width, _height, _width * BYTES_PER_PIXEL,
phys_base, false);
_pwm.enable_display();
break;
default:
PERR("Unknown board revision!");
return false;
}
return true;
}
};
Mode mode() { return Mode(_width, _height, Mode::RGB565); }
size_t size() { return BYTES_PER_PIXEL * _width * _height; }
Ipu &ipu() { return _ipu; }
};

View File

@ -1,6 +1,7 @@
/*
* \brief Image Processing Unit registers
* \author Nikolay Golikov <nik@ksyslabs.org>
* \author Nikolay Golikov <nik@ksyslabs.org>
* \author Stefan Kalkowski <stefan.kalkowski@genode-labs.com>
* \date 2012-11-10
*/
@ -14,311 +15,533 @@
#include <os/attached_io_mem_dataspace.h>
using namespace Genode;
struct Ipu : Genode::Mmio
class Ipu : Genode::Mmio
{
enum {
REGS_OFF = 0x06000000,
CPMEM_OFF = 0x01000000,
IDMAC_CHAN = 23,
};
private:
enum { REGS_OFF = 0x6000000 };
struct Conf : Register<0x0, 32> { };
template<unsigned NR>
struct Int_ctrl : Register<0x3c+(NR*4), 32> { };
struct Srm_pri2 : Register<0xa4, 32>
{
struct Dp_m_srm : Bitfield<3,2> { enum { UPDATE_NOW = 1 }; };
};
struct Disp_gen : Register<0xc4, 32> { };
struct Mem_rst : Register<0xdc, 32> { };
struct Pm : Register<0xe0, 32> { };
struct Gpr : Register<0xe4, 32> { };
struct Ch_db_mode_sel0 : Register<0x150, 32> { };
struct Alt_ch_trb_mode_sel0 : Register<0x178, 32> { };
struct Cur_buf_0 : Register<0x23c, 32> { };
struct Triple_cur_buf_1 : Register<0x25c, 32> { };
struct Ch_buf0_rdy0 : Register<0x268, 32> { };
struct Ch_buf1_rdy0 : Register<0x270, 32> { };
struct Conf : Register<0x0, 32> { };
struct Cur_buf_0 : Register<0x23c, 32> { };
struct Int_ctrl_5 : Register<0x4c, 32> { };
struct Int_ctrl_6 : Register<0x50, 32> { };
struct Int_ctrl_9 : Register<0x5c, 32> { };
struct Int_ctrl_10 : Register<0x60, 32> { };
struct Srm_pri2 : Register<0xa4, 32> { };
struct Disp_gen : Register<0xc4, 32> { };
struct Mem_rst : Register<0xdc, 32> { };
struct Ch_db_mode_sel0 : Register<0x150, 32> { };
/**************************************
** Image DMA controller registers **
**************************************/
/**
* IDMAC cannel enable register
*/
struct Idmac_ch_en : Register_array<0x8004, 32, 32, 1>
{
struct Ch : Bitfield<0, 1> { };
};
enum Idmac_channels {
CHAN_DP_PRIMARY_MAIN = 23,
CHAN_DP_PRIMARY_AUXI = 27,
CHAN_DC_SYNC_FLOW = 28
};
struct Idmac_ch_pri_1 : Register<0x8014, 32> { };
struct Dp_com_conf : Register<0x18000, 32> { };
struct Gr_wnd_ctl_sync : Register<0x18004, 32> { };
struct Di0_general : Register<0x40000, 32> { };
struct Di0_bs_clkgen0 : Register<0x40004, 32> { };
struct Di0_bs_clkgen1 : Register<0x40008, 32> { };
struct Di0_sw_gen0_1 : Register<0x4000c, 32> { };
struct Di0_sw_gen0_2 : Register<0x40010, 32> { };
struct Di0_sw_gen0_3 : Register<0x40014, 32> { };
struct Di0_sw_gen0_4 : Register<0x40018, 32> { };
struct Di0_sw_gen0_5 : Register<0x4001c, 32> { };
struct Di0_sw_gen0_6 : Register<0x40020, 32> { };
struct Di0_sw_gen0_7 : Register<0x40024, 32> { };
struct Di0_sw_gen0_8 : Register<0x40028, 32> { };
struct Di0_sw_gen0_9 : Register<0x4002c, 32> { };
struct Di0_sw_gen1_1 : Register<0x40030, 32> { };
struct Di0_sw_gen1_2 : Register<0x40034, 32> { };
struct Di0_sw_gen1_3 : Register<0x40038, 32> { };
struct Di0_sw_gen1_4 : Register<0x4003c, 32> { };
struct Di0_sw_gen1_5 : Register<0x40040, 32> { };
struct Di0_sw_gen1_6 : Register<0x40044, 32> { };
struct Di0_sw_gen1_7 : Register<0x40048, 32> { };
struct Di0_sw_gen1_8 : Register<0x4004c, 32> { };
struct Di0_sw_gen1_9 : Register<0x40050, 32> { };
struct Di0_sync_as_gen : Register<0x40054, 32> { };
struct Di0_dw_gen_1 : Register<0x40058, 32> { };
struct Di0_dw_set3_1 : Register<0x40118, 32> { };
struct Di0_stp_rep_1 : Register<0x40148, 32> { };
struct Di0_stp_rep_3 : Register<0x4014c, 32> { };
struct Di0_stp_rep_5 : Register<0x40150, 32> { };
struct Di0_stp_rep_7 : Register<0x40154, 32> { };
struct Di0_stp_rep_9 : Register<0x40158, 32> { };
struct Di0_pol : Register<0x40164, 32> { };
struct Di0_scr_conf : Register<0x40170, 32> { };
struct Dc_wr_ch_conf_1 : Register<0x5801c, 32> { };
struct Dc_wr_ch_conf_5 : Register<0x5805c, 32> { };
struct Dc_wr_ch_addr_5 : Register<0x58060, 32> { };
struct Dc_rl0_ch_5 : Register<0x58064, 32> { };
struct Dc_rl1_ch_5 : Register<0x58068, 32> { };
struct Dc_rl2_ch_5 : Register<0x5806c, 32> { };
struct Dc_rl3_ch_5 : Register<0x58070, 32> { };
struct Dc_rl4_ch_5 : Register<0x58074, 32> { };
struct Dc_gen : Register<0x580d4, 32> { };
struct Dc_disp_conf2_0 : Register<0x580e8, 32> { };
struct Dc_map_conf_0 : Register<0x58108, 32> { };
struct Dc_map_conf_1 : Register<0x5810c, 32> { };
struct Dc_map_conf_2 : Register<0x58110, 32> { };
struct Dc_map_conf_15 : Register<0x58144, 32> { };
struct Dc_map_conf_16 : Register<0x58148, 32> { };
struct Dc_map_conf_17 : Register<0x5814c, 32> { };
struct Dc_map_conf_18 : Register<0x58150, 32> { };
struct Dc_map_conf_19 : Register<0x58154, 32> { };
struct Dc_map_conf_20 : Register<0x58158, 32> { };
struct Dc_map_conf_21 : Register<0x5815c, 32> { };
struct Dc_map_conf_22 : Register<0x58160, 32> { };
struct Dmfc_wr_chan : Register<0x60004, 32> { };
struct Dmfc_wr_chan_def : Register<0x60008, 32> { };
struct Dmfc_dp_chan : Register<0x6000c, 32> { };
struct Dmfc_dp_chan_def : Register<0x60010, 32> { };
struct Dmfc_general_1 : Register<0x60014, 32> { };
struct Dmfc_ic_ctrl : Register<0x6001c, 32> { };
struct Dc_tmpl_low10 : Register<0x1080028, 32> { };
struct Dc_tmpl_high10 : Register<0x108002c, 32> { };
struct Dc_tmpl_low11 : Register<0x1080030, 32> { };
struct Dc_tmpl_high11 : Register<0x1080034, 32> { };
struct Dc_tmpl_low12 : Register<0x1080038, 32> { };
struct Dc_tmpl_high12 : Register<0x108003c, 32> { };
struct Idmac_ch_en : Register_array<0x8004, 32, 32, 1>
{
struct Ch : Bitfield<0, 1> { };
};
struct Idmac_ch_pri_1 : Register<0x8014, 32> { };
struct Idmac_wm_en : Register_array<0x801c, 32, 32, 1>
{
struct Ch : Bitfield<0, 1> { };
};
struct Idmac_ch_lock_en_1 : Register<0x8024, 32> { };
/**
* IDMAC channel parametrs memory structure
*/
struct Cp_mem
{
Genode::uint32_t Data[5];
Genode::uint32_t Resetrved[3];
} _ch_cpmem[2];
/***********************************
** Display processor registers **
***********************************/
void cpmem_set_field(Genode::uint8_t word, Genode::uint8_t bit,
Genode::uint8_t size, Genode::uint32_t value)
{
int i = (bit) / 32;
int off = (bit) % 32;
_ch_cpmem[word].Data[i] |= (value) << off;
if (((bit) + (size) - 1) / 32 > i) {
_ch_cpmem[word].Data[i + 1] |= (value) >> (off ? (32 - off) : 0);
struct Dp_com_conf : Register<0x1040000, 32> { };
struct Dp_fg_pos_sync : Register<0x1040008, 32> { };
struct Gr_wnd_ctl_sync : Register<0x1040004, 32> { };
/***********************************
** Display interface registers **
***********************************/
template <Genode::off_t OFF>
struct Di
{
struct General : Register<OFF+0x0, 32> { };
struct Bs_clkgen0 : Register<OFF+0x4, 32> { };
struct Bs_clkgen1 : Register<OFF+0x8, 32> { };
template <unsigned NR>
struct Sync_wave_gen0 : Register<0xc+OFF+(NR*4), 32> { };
template <unsigned NR>
struct Sync_wave_gen1 : Register<0x30+OFF+(NR*4), 32> { };
struct Sync_as_gen : Register<OFF+0x54, 32> { };
template <unsigned NR>
struct Dw_gen : Register<0x58 + OFF + (NR*4), 32> { };
template <unsigned NR>
struct Dw_set3 : Register<0x118 + OFF + (NR*4), 32> { };
template <unsigned NR>
struct Step_repeat : Register<0x148 + OFF + (NR*4), 32> { };
struct Polarity : Register<OFF+0x164, 32> { };
struct Scr_conf : Register<OFF+0x170, 32> { };
};
typedef Di<0x40000> Di0;
typedef Di<0x48000> Di1;
/************************************
** Display controller registers **
************************************/
struct Dc_wr_ch_conf_5 : Register<0x5805c, 32> { };
struct Dc_wr_ch_addr_5 : Register<0x58060, 32> { };
template <unsigned NR>
struct Dc_rl_ch_5 : Register<0x58064+(NR*4), 32> { };
struct Dc_gen : Register<0x580d4, 32> { };
struct Dc_disp_conf2_0 : Register<0x580e8, 32> { };
struct Dc_disp_conf2_1 : Register<0x580ec, 32> { };
template <unsigned NR>
struct Dc_map_conf : Register<0x58108+(NR*4), 32> { };
template <unsigned NR>
struct Dc_template : Register<0x1080000+(NR*4), 32> { };
/***********************************************
** Display multi FIFO controller registers **
***********************************************/
struct Dmfc_wr_chan : Register<0x60004, 32> { };
struct Dmfc_wr_chan_def : Register<0x60008, 32> { };
struct Dmfc_dp_chan : Register<0x6000c, 32> { };
struct Dmfc_dp_chan_def : Register<0x60010, 32> { };
struct Dmfc_general_1 : Register<0x60014, 32> { };
struct Dmfc_ic_ctrl : Register<0x6001c, 32> { };
class Cp_mem
{
public:
enum { OFFSET = 0x1000000 };
unsigned xv : 10; /* XV Virtual Coordinate */
unsigned yv : 9; /* YV Virtual Coordinate */
unsigned xb : 13; /* XB inner Block Coordinate */
unsigned yb : 12; /* YB inner Block Coordinate */
unsigned nsb_b : 1; /* New Sub Block */
unsigned cf : 1; /* Current Field */
unsigned sx : 12; /* Scroll X counter */
unsigned sy : 11; /* Scroll Y counter */
unsigned ns : 10; /* Number of Scroll */
unsigned sdx : 7; /* Scroll Delta X */
unsigned sm : 10; /* Scroll Max */
unsigned scc : 1; /* Scrolling Configuration */
unsigned sce : 1; /* Scrolling Enable */
unsigned sdy : 7; /* Scroll Delta Y */
unsigned sdrx : 1; /* Scroll Horizontal Direction */
unsigned sdry : 1; /* Scroll Vertical Direction */
unsigned bpp : 3; /* Bits per Pixel */
unsigned dec_sel : 2; /* Decode Address Select */
unsigned dim : 1; /* Access Dimension */
unsigned so : 1; /* Scan Order */
unsigned bndm : 3; /* Band Mode */
unsigned bm : 2; /* Block Mode */
unsigned rot : 1; /* Rotation */
unsigned hf : 1; /* Horizontal Flip */
unsigned vf : 1; /* Vertical Flip */
unsigned the : 1; /* Threshold Enable */
unsigned cap : 1; /* Conditional Access Polarity */
unsigned cae : 1; /* Conditional Access Enable */
unsigned fw : 13; /* Frame Width */
unsigned fh : 12; /* Frame Height */
unsigned res0 : 10; /* reserved */
Genode::uint32_t res1[3];
unsigned eba0 : 29; /* Ext Mem Buffer 0 Address */
unsigned eba1 : 29; /* Ext Mem Buffer 1 Address */
unsigned ilo : 20; /* Interlace Offset */
unsigned npb : 7; /* Number of Pixels in Whole Burst Access */
unsigned pfs : 4; /* Pixel Format Select */
unsigned alu : 1; /* Alpha Used */
unsigned albm : 3; /* Alpha Channel Mapping */
unsigned id : 2; /* AXI ID */
unsigned th : 7; /* Threshold */
unsigned sly : 14; /* Stride Line */
unsigned wid0 : 3; /* Width0 */
unsigned wid1 : 3; /* Width1 */
unsigned wid2 : 3; /* Width2 */
unsigned wid3 : 3; /* Width3 */
unsigned off0 : 5; /* Offset0 */
unsigned off1 : 5; /* Offset1 */
unsigned off2 : 5; /* Offset2 */
unsigned off3 : 5; /* Offset3 */
unsigned sxys : 1; /* Select SX SY Set */
unsigned cre : 1; /* Conditional Read Enable */
unsigned dec_sel2 : 1; /* Decode Address Select bit[2] */
unsigned res2 : 9; /* reserved */
Genode::uint32_t res3[3];
Cp_mem() { Genode::memset(this, 0, sizeof(Cp_mem)); }
void * operator new(Genode::size_t size, void* addr) { return addr; }
} __attribute__((packed));
void _init_dma_channel(unsigned channel,
Genode::uint16_t width, Genode::uint16_t height,
Genode::uint32_t stride, Genode::addr_t phys_base)
{
void *dst =(void*)(base + Cp_mem::OFFSET + channel*sizeof(Cp_mem));
Cp_mem cpmem;
cpmem.fw = width - 1;
cpmem.fh = height - 1;
cpmem.sly = stride - 1;
cpmem.eba0 = phys_base >> 3;
cpmem.eba1 = phys_base >> 3;
cpmem.bpp = 3; /* corresponds to 16BPP */
cpmem.pfs = 7; /* corresponds to RGB */
cpmem.npb = 31; /* 32 pixel per burst access */
/* red */
cpmem.wid0 = 4;
cpmem.off0 = 0;
/* green */
cpmem.wid1 = 5;
cpmem.off1 = 5;
/* blue */
cpmem.wid2 = 4; cpmem.off2 = 11;
/* alpha */
cpmem.wid3 = 7;
cpmem.off3 = 16;
Genode::memcpy(dst, (void*)&cpmem, sizeof(Cp_mem));
}
}
/**
* IPU initialization
*/
void init(Genode::uint16_t width, Genode::uint16_t height,
Genode::uint32_t stride,
Genode::addr_t phys_base)
{
/* Reset ipu memory */
write<Mem_rst>(0x807fffff);
while (read<Mem_rst>() & 0x80000000)
;
void _init_di0(Genode::uint16_t width, Genode::uint16_t height,
Genode::uint32_t stride, Genode::addr_t phys_base)
{
/* set MCU_T to divide MCU access window into 2 */
write<Disp_gen>(0x1600000); // ?= 0x600000
/* link display controller events */
write<Dc_rl_ch_5<0> >(0x5030000);
write<Dc_rl_ch_5<2> >(0x602);
write<Dc_rl_ch_5<4> >(0x701);
write<Dc_rl_ch_5<0> >(0x5030000);
write<Dc_rl_ch_5<1> >(0x0);
write<Dc_rl_ch_5<1> >(0x0);
write<Dc_rl_ch_5<2> >(0x602);
write<Dc_rl_ch_5<3> >(0x0);
write<Dc_rl_ch_5<3> >(0x0);
write<Dc_wr_ch_conf_5>(0x2);
write<Dc_wr_ch_addr_5>(0x0);
write<Dc_gen>(0x84);
/*************************
** Display interface **
*************************/
/* clear DI */
write<Di0::General>(0x200000);
/* initialize display interface 0 */
write<Di0::Bs_clkgen0>(0x38);
write<Di0::Bs_clkgen1>(0x30000);
write<Di0::Dw_gen<0> >(0x2020300);
write<Di0::Dw_set3<0> >(0x60000);
write<Di0::Sync_wave_gen0<0> >(0x21310000);
write<Di0::Sync_wave_gen1<0> >(0x10000000);
write<Di0::Sync_wave_gen0<1> >(0x21310001);
write<Di0::Sync_wave_gen1<1> >(0x30141000);
write<Di0::Step_repeat<0> >(0x0);
write<Di0::Sync_wave_gen0<2> >(0x10520000);
write<Di0::Sync_wave_gen1<2> >(0x30142000);
write<Di0::Scr_conf>(0x20a);
write<Di0::Sync_wave_gen0<3> >(0x3010b);
write<Di0::Sync_wave_gen1<3> >(0x8000000);
write<Di0::Step_repeat<1> >(0x1e00000);
write<Di0::Sync_wave_gen0<4> >(0x10319);
write<Di0::Sync_wave_gen1<4> >(0xa000000);
write<Di0::Sync_wave_gen0<5> >(0x0);
write<Di0::Sync_wave_gen1<5> >(0x0);
write<Di0::Sync_wave_gen0<6> >(0x0);
write<Di0::Sync_wave_gen1<6> >(0x0);
write<Di0::Sync_wave_gen0<7> >(0x0);
write<Di0::Sync_wave_gen1<7> >(0x0);
write<Di0::Sync_wave_gen0<8> >(0x0);
write<Di0::Sync_wave_gen1<8> >(0x0);
write<Di0::Step_repeat<2> >(0x320);
write<Di0::Step_repeat<3> >(0x0);
write<Di0::Step_repeat<4> >(0x0);
/* write display connection microcode */
write<Dc_template<10> >(0x8885);
write<Dc_template<11> >(0x380);
write<Dc_template<12> >(0x8845);
write<Dc_template<13> >(0x380);
write<Dc_template<14> >(0x8805);
write<Dc_template<15> >(0x380);
write<Di0::General>(0x220000);
write<Di0::Sync_as_gen>(0x2002);
write<Di0::General>(0x200000);
write<Di0::Sync_as_gen>(0x4002);
write<Di0::Polarity>(0x10);
write<Dc_disp_conf2_0>(0x320);
/* init IDMAC channels */
_init_dma_channel(CHAN_DP_PRIMARY_MAIN, width, height, stride, phys_base);
_init_dma_channel(CHAN_DP_PRIMARY_AUXI, width, height, stride, phys_base);
/* round robin for simultaneous synchronous flows from DC & DP */
write<Dmfc_general_1>(0x3);
/* enable DP, DI0, DC, DMFC */
write<Conf>(0x660);
/* use double buffer for main DMA channel */
write<Ch_db_mode_sel0>(1 << CHAN_DP_PRIMARY_MAIN |
1 << CHAN_DP_PRIMARY_AUXI);
/* buffer used by DMA channel is buffer 1 */
write<Cur_buf_0>(1 << CHAN_DP_PRIMARY_MAIN);
write<Dc_wr_ch_conf_5>(0x82);
/* Enable IDMAC channels */
write<Idmac_ch_en::Ch>(1, CHAN_DP_PRIMARY_MAIN);
write<Idmac_ch_en::Ch>(1, CHAN_DP_PRIMARY_AUXI);
}
void _init_di1(Genode::uint16_t width, Genode::uint16_t height,
Genode::uint32_t stride, Genode::addr_t phys_base)
{
write<Disp_gen>(0x600000); //write<Disp_gen>(0x2400000);
write<Dp_com_conf>(0);
write<Srm_pri2::Dp_m_srm>(Srm_pri2::Dp_m_srm::UPDATE_NOW);
write<Dc_rl_ch_5<0> >(0x2030000);
write<Dc_rl_ch_5<1> >(0);
write<Dc_rl_ch_5<2> >(0x302);
write<Dc_rl_ch_5<3> >(0);
write<Dc_rl_ch_5<4> >(0x401);
write<Dc_wr_ch_conf_5>(0xe);
write<Dc_wr_ch_addr_5>(0x0);
write<Dc_gen>(0x84);
write<Conf>(0);
write<Di1::General>(0x200000);
write<Di1::General>(0x300000);
write<Di1::Bs_clkgen0>(0x10);
write<Di1::Bs_clkgen1>(0x10000);
write<Pm>(0x10101010);
write<Di1::Dw_gen<0> >(0x300);
write<Di1::Dw_set3<0> >(0x20000);
write<Di1::Sync_wave_gen0<0> >(0x29f90000);
write<Di1::Sync_wave_gen1<0> >(0x10000000);
write<Di1::Step_repeat<0> >(0x0);
write<Di1::Sync_wave_gen0<1> >(0x29f90001);
write<Di1::Sync_wave_gen1<1> >(0x30781000);
write<Di1::Step_repeat<0> >(0x0);
write<Di1::Sync_wave_gen0<2> >(0x192a0000);
write<Di1::Sync_wave_gen1<2> >(0x30142000);
write<Di1::Step_repeat<1> >(0x3000000);
write<Di1::Scr_conf>(0x325);
write<Di1::Sync_wave_gen0<3> >(0x300fb);
write<Di1::Sync_wave_gen1<3> >(0x8000000);
write<Di1::Step_repeat<1> >(0x3000000);
write<Di1::Sync_wave_gen0<4> >(0x108c1);
write<Di1::Sync_wave_gen1<4> >(0xa000000);
write<Di1::Step_repeat<2> >(0x400);
write<Di1::Sync_wave_gen0<6> >(0x29f90091);
write<Di1::Sync_wave_gen1<6> >(0x30781000);
write<Di1::Step_repeat<3> >(0x0);
write<Di1::Sync_wave_gen0<7> >(0x192a000a);
write<Di1::Sync_wave_gen1<7> >(0x30142000);
write<Di1::Step_repeat<3> >(0x0);
write<Di1::Sync_wave_gen0<5> >(0x0);
write<Di1::Sync_wave_gen1<5> >(0x0);
write<Di1::Sync_wave_gen0<8> >(0x0);
write<Di1::Sync_wave_gen1<8> >(0x0);
write<Di1::Step_repeat<4> >(0x0);
write<Di1::Step_repeat<2> >(0x400);
write<Di1::Sync_wave_gen0<5> >(0x90011);
write<Di1::Sync_wave_gen1<5> >(0x4000000);
write<Di1::Step_repeat<2> >(0x28a0400);
write<Dc_template<4> >(0x10885);
write<Dc_template<5> >(0x380);
write<Dc_template<6> >(0x845);
write<Dc_template<7> >(0x280);
write<Dc_template<8> >(0x10805);
write<Dc_template<9> >(0x380);
write<Di1::General>(0x6300000);
write<Di1::Sync_as_gen>(0x4000);
write<Di1::Polarity>(0x10);
write<Dc_disp_conf2_1>(0x400);
_init_dma_channel(CHAN_DP_PRIMARY_MAIN, width, height, stride, phys_base);
_init_dma_channel(CHAN_DP_PRIMARY_AUXI, width, height, stride, phys_base);
/* use double buffer for main DMA channel */
write<Ch_db_mode_sel0>(1 << CHAN_DP_PRIMARY_MAIN |
1 << CHAN_DP_PRIMARY_AUXI);
/* buffer used by DMA channel is buffer 1 */
write<Cur_buf_0>(1 << CHAN_DP_PRIMARY_MAIN);
write<Conf>(0x6a0);
/* Enable IDMAC channels */
write<Idmac_ch_en::Ch>(1, CHAN_DP_PRIMARY_MAIN);
write<Idmac_ch_en::Ch>(1, CHAN_DP_PRIMARY_AUXI);
write<Idmac_wm_en>(1 << CHAN_DP_PRIMARY_MAIN |
1 << CHAN_DP_PRIMARY_AUXI);
write<Dc_wr_ch_conf_5>(0x8e);
write<Disp_gen>(0x2600000);
}
public:
/**
* Init display controller mappings
* IPU initialization
*/
write<Dc_map_conf_0>(0x14830820);
write<Dc_map_conf_1>(0x2d4920e6);
write<Dc_map_conf_2>(0x39ac);
write<Dc_map_conf_15>(0xfff07ff);
write<Dc_map_conf_16>(0x5fc17ff);
write<Dc_map_conf_17>(0x11fc0bfc);
write<Dc_map_conf_18>(0x17ff0fff);
write<Dc_map_conf_19>(0x4f807ff);
write<Dc_map_conf_20>(0xff80afc);
write<Dc_map_conf_21>(0xdfc05fc);
write<Dc_map_conf_22>(0x15fc);
void init(Genode::uint16_t width, Genode::uint16_t height,
Genode::uint32_t stride, Genode::addr_t phys_base,
bool di0)
{
/* stop pixel clocks */
write<Di0::General>(0);
write<Di1::General>(0);
/* reset IPU memory buffers */
write<Mem_rst>(0x807fffff);
while (read<Mem_rst>() & 0x80000000) ;
/* initialize pixel format mappings for display controller */
write<Dc_map_conf< 0> >(0x14830820);
write<Dc_map_conf< 1> >(0x2d4920e6);
write<Dc_map_conf< 2> >(0x39ac);
write<Dc_map_conf<15> >(0xfff07ff);
write<Dc_map_conf<16> >(0x5fc17ff);
write<Dc_map_conf<17> >(0x11fc0bfc);
write<Dc_map_conf<18> >(0x17ff0fff);
write<Dc_map_conf<19> >(0x4f807ff);
write<Dc_map_conf<20> >(0xff80afc);
write<Dc_map_conf<21> >(0xdfc05fc);
write<Dc_map_conf<22> >(0x15fc);
/* clear interrupt control registers */
write<Int_ctrl<4> >(0);
write<Int_ctrl<5> >(0);
write<Int_ctrl<8> >(0);
write<Int_ctrl<9> >(0);
/* disable DMFC channel from image converter */
write<Dmfc_ic_ctrl>(0x2);
/* set DMFC FIFO for idma channels */
write<Dmfc_wr_chan>(0x90); /* channel CHAN_DC_SYNC_FLOW */
write<Dmfc_wr_chan_def>(0x202020f6);
write<Dmfc_dp_chan>(0x968a); /* channels CHAN_DP_PRIMARY_XXX */
write<Dmfc_dp_chan_def>(0x2020f6f6);
write<Dmfc_general_1>(0x3);
/* set idma channels 23, 27, 28 as high priority */
write<Idmac_ch_pri_1>(1 << CHAN_DP_PRIMARY_MAIN |
1 << CHAN_DP_PRIMARY_AUXI |
1 << CHAN_DC_SYNC_FLOW);
/*
* generate 8 AXI bursts upon the assertion of DMA request
* for our channels
*/
write<Idmac_ch_lock_en_1>(0x3f0000);
if (di0)
_init_di0(width, height, stride, phys_base);
else
_init_di1(width, height, stride, phys_base);
/************************
** overlay settings **
************************/
write<Dp_com_conf>(1 << 0);
write<Srm_pri2::Dp_m_srm>(Srm_pri2::Dp_m_srm::UPDATE_NOW);
write<Dp_fg_pos_sync>(16);
write<Srm_pri2::Dp_m_srm>(Srm_pri2::Dp_m_srm::UPDATE_NOW);
write<Dp_com_conf>(1 << 0 | 1 << 2);
write<Srm_pri2::Dp_m_srm>(Srm_pri2::Dp_m_srm::UPDATE_NOW);
write<Gr_wnd_ctl_sync>(0xff000000);
write<Srm_pri2::Dp_m_srm>(Srm_pri2::Dp_m_srm::UPDATE_NOW);
}
void overlay(Genode::addr_t phys_base, int x, int y, int alpha)
{
volatile Genode::uint32_t *ptr = (volatile Genode::uint32_t*)
(base + Cp_mem::OFFSET + CHAN_DP_PRIMARY_AUXI*sizeof(Cp_mem));
ptr[8] = (((phys_base >> 3) & 0b111) << 29) | (phys_base >> 3);
ptr[9] = (phys_base >> 6);
write<Dp_fg_pos_sync>(x << 16 | y);
write<Srm_pri2::Dp_m_srm>(Srm_pri2::Dp_m_srm::UPDATE_NOW);
write<Gr_wnd_ctl_sync>(alpha << 24);
write<Srm_pri2::Dp_m_srm>(Srm_pri2::Dp_m_srm::UPDATE_NOW);
}
/**
* Clear interrupt control registers
* Constructor
*
* \param mmio_base base address of IPU
*/
write<Int_ctrl_5>(0x0);
write<Int_ctrl_6>(0x0);
write<Int_ctrl_9>(0x0);
write<Int_ctrl_10>(0x0);
/**
* Init DMFC
*/
write<Dmfc_ic_ctrl>(0x2);
write<Dmfc_wr_chan>(0x90);
write<Dmfc_wr_chan_def>(0x202020f6);
write<Dmfc_dp_chan>(0x9694);
write<Dmfc_dp_chan_def>(0x2020f6f6);
write<Idmac_ch_pri_1>(0x18800000);
write<Gr_wnd_ctl_sync>(0x80000000);
write<Srm_pri2>(0x605080b);
write<Dp_com_conf>(0x4);
write<Srm_pri2>(0x605080b);
/**
* Link display controller events
*/
write<Dc_rl0_ch_5>(0x5030000);
write<Dc_rl2_ch_5>(0x602);
write<Dc_rl4_ch_5>(0x701);
write<Dc_rl0_ch_5>(0x5030000);
write<Dc_rl1_ch_5>(0x0);
write<Dc_rl1_ch_5>(0x0);
write<Dc_rl2_ch_5>(0x602);
write<Dc_rl3_ch_5>(0x0);
write<Dc_rl3_ch_5>(0x0);
/**
* Init display controller
*/
write<Dc_wr_ch_conf_5>(0x2);
write<Dc_wr_ch_addr_5>(0x0);
write<Dc_gen>(0x84);
write<Conf>(0x660);
/**
* Init display interface
*/
write<Di0_bs_clkgen0>(0x38);
write<Di0_bs_clkgen1>(0x30000);
write<Di0_dw_gen_1>(0x2020300);
write<Di0_dw_set3_1>(0x60000);
write<Di0_sw_gen0_1>(0x21310000);
write<Di0_sw_gen1_1>(0x10000000);
write<Di0_sw_gen0_2>(0x21310001);
write<Di0_sw_gen1_2>(0x30141000);
write<Di0_stp_rep_1>(0x0);
write<Di0_sw_gen0_3>(0x10520000);
write<Di0_sw_gen1_3>(0x30142000);
write<Di0_scr_conf>(0x20a);
write<Di0_sw_gen0_4>(0x3010b);
write<Di0_sw_gen1_4>(0x8000000);
write<Di0_stp_rep_3>(0x1e00000);
write<Di0_sw_gen0_5>(0x10319);
write<Di0_sw_gen1_5>(0xa000000);
write<Di0_sw_gen0_6>(0x0);
write<Di0_sw_gen1_6>(0x0);
write<Di0_sw_gen0_7>(0x0);
write<Di0_sw_gen1_7>(0x0);
write<Di0_sw_gen0_8>(0x0);
write<Di0_sw_gen1_8>(0x0);
write<Di0_sw_gen0_9>(0x0);
write<Di0_sw_gen1_9>(0x0);
write<Di0_stp_rep_5>(0x320);
write<Di0_stp_rep_7>(0x0);
write<Di0_stp_rep_9>(0x0);
/**
* Write display connection templates
*/
write<Dc_tmpl_low10>(0x8885);
write<Dc_tmpl_high10>(0x380);
write<Dc_tmpl_low11>(0x8845);
write<Dc_tmpl_high11>(0x380);
write<Dc_tmpl_low12>(0x8805);
write<Dc_tmpl_high12>(0x380);
write<Di0_general>(0x220000);
write<Di0_sync_as_gen>(0x2002);
write<Di0_general>(0x200000);
write<Di0_sync_as_gen>(0x4002);
write<Di0_pol>(0x10);
write<Dc_disp_conf2_0>(0x320);
write<Dmfc_general_1>(0x3);
write<Ch_db_mode_sel0>(0x800000);
write<Cur_buf_0>(0x800000);
write<Dc_wr_ch_conf_1>(0x4);
write<Dc_wr_ch_conf_5>(0x82);
write<Disp_gen>(0x1600000);
/**
* Init IDMAC channel
*/
cpmem_set_field(0, 125, 13, width - 1);
cpmem_set_field(0, 138, 12, height - 1);
cpmem_set_field(1, 102, 14, stride - 1 );
cpmem_set_field(1, 0, 29, 0);
cpmem_set_field(1, 29, 29, phys_base >> 3);
/* bits/pixel */
cpmem_set_field(0, 107, 3, 3);
/* pixel format RGB565 */
cpmem_set_field(1, 85, 4, 7);
/* burst size */
cpmem_set_field(1, 78, 7, 15);
/*******************
** set packing **
*******************/
/* red */
cpmem_set_field(1, 116, 3, 4);
cpmem_set_field(1, 128, 5, 0);
/* green */
cpmem_set_field(1, 119, 3, 5);
cpmem_set_field(1, 133, 5, 5);
/* blue */
cpmem_set_field(1, 122, 3, 4);
cpmem_set_field(1, 138, 5, 11);
/* alpha */
cpmem_set_field(1, 125, 3, 7);
cpmem_set_field(1, 143, 5, 16);
cpmem_set_field(0, 46, 22, 0);
cpmem_set_field(0, 68, 22, 0);
Genode::memcpy((void *)(base + CPMEM_OFF + sizeof(_ch_cpmem) * IDMAC_CHAN),
(void *)&_ch_cpmem, sizeof(_ch_cpmem));
write<Idmac_ch_en::Ch>(1, IDMAC_CHAN);
}
/**
* Constructor
*
* \param mmio_base base address of IPU
*/
Ipu(Genode::addr_t mmio_base)
: Genode::Mmio(mmio_base + REGS_OFF) { }
Ipu(Genode::addr_t mmio_base) : Genode::Mmio(mmio_base + REGS_OFF) { }
};
#endif /* _IPU_H_ */

View File

@ -5,7 +5,7 @@
*/
/* Genode includes */
#include <framebuffer_session/framebuffer_session.h>
#include <imx_framebuffer_session/imx_framebuffer_session.h>
#include <cap_session/connection.h>
#include <dataspace/client.h>
#include <base/printf.h>
@ -22,21 +22,25 @@ namespace Framebuffer {
class Framebuffer::Session_component :
public Genode::Rpc_object<Framebuffer::Session>
public Genode::Rpc_object<Framebuffer::Imx_session>
{
private:
size_t _size;
Dataspace_capability _ds;
addr_t _phys_base;
Mode _mode;
Ipu &_ipu;
public:
Session_component(Driver &driver)
: _size(Driver::FRAMEBUFFER_SIZE),
: _size(driver.size()),
_ds(env()->ram_session()->alloc(_size, false)),
_phys_base(Dataspace_client(_ds).phys_addr())
_phys_base(Dataspace_client(_ds).phys_addr()),
_mode(driver.mode()),
_ipu(driver.ipu())
{
if (!driver.init(_phys_base)) {
PERR("Could not initialize display");
@ -50,12 +54,14 @@ class Framebuffer::Session_component :
** Framebuffer::session interface **
**************************************/
Dataspace_capability dataspace() { return _ds; }
void release() { }
Mode mode() const {
return Mode(Driver::WIDTH, Driver::HEIGHT, Mode::RGB565); }
Dataspace_capability dataspace() { return _ds; }
void release() { }
Mode mode() const { return _mode; }
void mode_sigh(Genode::Signal_context_capability) { }
void refresh(int, int, int, int) { }
void refresh(int, int, int, int) { }
void overlay(Genode::addr_t phys_base, int x, int y, int alpha) {
_ipu.overlay(phys_base, x, y, alpha); }
};
int main(int, char **)

View File

@ -0,0 +1,36 @@
/*
* \brief Pulse width modulation
* \author Stefan Kalkowski
* \date 2013-03-05
*/
/*
* Copyright (C) 2013 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.
*/
#ifndef _PWM_H_
#define _PWM_H_
/* Genode includes */
#include <util/mmio.h>
struct Pwm : Genode::Mmio
{
struct Control : Register<0x0, 32> {};
struct Sample : Register<0xc, 32> {};
struct Period : Register<0x10,32> {};
Pwm(Genode::addr_t const mmio_base) : Genode::Mmio(mmio_base) { }
void enable_display()
{
write<Period>(0x64);
write<Sample>(0x64);
write<Control>(0x3c20001);
}
};
#endif /* _PWM_H_ */

View File

@ -33,6 +33,16 @@ class Ccm : public Genode::Attached_io_mem_dataspace,
struct Ipu_hs_mask : Bitfield <21, 1> { };
};
/**
* Serial Clock Multiplexer Register 2
*/
struct Cscmr2 : Register<0x20, 32> {};
/**
* D1 Clock Divider Register
*/
struct Cdcdr : Register<0x30, 32> {};
/**
* Low power control register
*/
@ -41,7 +51,7 @@ class Ccm : public Genode::Attached_io_mem_dataspace,
struct Bypass_ipu_hs : Bitfield<18, 1> { };
};
struct Cccr5 : Register<0x7c, 32>
struct Ccgr5 : Register<0x7c, 32>
{
struct Ipu_clk_en : Bitfield<10, 2> { };
};
@ -55,14 +65,16 @@ class Ccm : public Genode::Attached_io_mem_dataspace,
void ipu_clk_enable(void)
{
write<Cccr5::Ipu_clk_en>(3);
write<Ccgr5::Ipu_clk_en>(3);
write<Ccdr::Ipu_hs_mask>(0);
write<Clpcr::Bypass_ipu_hs>(0);
write<Cscmr2>(0xa2b32f0b);
write<Cdcdr>(0x14370092);
}
void ipu_clk_disable(void)
{
write<Cccr5::Ipu_clk_en>(0);
write<Ccgr5::Ipu_clk_en>(0);
write<Ccdr::Ipu_hs_mask>(1);
write<Clpcr::Bypass_ipu_hs>(1);
}

View File

@ -0,0 +1,39 @@
/*
* \brief IC identification module register description
* \author Stefan Kalkowski <stefan.kalkowski@genode-labs.com>
* \date 2013-04-29
*/
/*
* Copyright (C) 2013 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.
*/
#ifndef _DRIVERS__PLATFORM__IMX53__IIM_H_
#define _DRIVERS__PLATFORM__IMX53__IIM_H_
/* Genode includes */
#include <util/mmio.h>
#include <drivers/board_base.h>
#include <os/attached_io_mem_dataspace.h>
class Iim : public Genode::Attached_io_mem_dataspace,
Genode::Mmio
{
private:
struct Fuse_bank0_gp6 : Register<0x878, 32> {};
public:
Iim()
: Genode::Attached_io_mem_dataspace(Genode::Board_base::IIM_BASE,
Genode::Board_base::IIM_SIZE),
Genode::Mmio((Genode::addr_t)local_addr<void>()) {}
unsigned long revision() { return read<Fuse_bank0_gp6>() & 0xf; }
};
#endif /* _DRIVERS__PLATFORM__IMX53__IIM_H_ */

View File

@ -22,12 +22,35 @@
class Iomux : public Genode::Attached_io_mem_dataspace,
Genode::Mmio
{
private:
struct Gpr2 : Register<0x8,32>
{
struct Ch1_mode : Bitfield<2, 2> {
enum { ROUTED_TO_DI1 = 0x3 }; };
struct Data_width_ch1 : Bitfield<7, 1> {
enum { PX_18_BITS, PX_24_BITS }; };
struct Bit_mapping_ch1 : Bitfield<8, 1> {
enum { SPWG, JEIDA }; };
struct Di1_vs_polarity : Bitfield<10,1> { };
};
public:
Iomux()
: Genode::Attached_io_mem_dataspace(Genode::Board_base::IOMUXC_BASE,
Genode::Board_base::IOMUXC_SIZE),
Genode::Mmio((Genode::addr_t)local_addr<void>()) {}
Genode::Mmio((Genode::addr_t)local_addr<void>())
{
}
void enable_di1()
{
write<Gpr2::Di1_vs_polarity>(1);
write<Gpr2::Data_width_ch1>(Gpr2::Data_width_ch1::PX_18_BITS);
write<Gpr2::Bit_mapping_ch1>(Gpr2::Bit_mapping_ch1::SPWG);
write<Gpr2::Ch1_mode>(Gpr2::Ch1_mode::ROUTED_TO_DI1);
}
};
#endif /* _DRIVERS__PLATFORM__IMX53__IOMUX_H_ */

View File

@ -18,8 +18,9 @@
#include <root/component.h>
#include <platform_session/platform_session.h>
#include <iomux.h>
#include <ccm.h>
#include <iim.h>
#include <iomux.h>
#include <src.h>
@ -33,17 +34,18 @@ class Platform::Session_component : public Genode::Rpc_object<Platform::Session>
{
private:
Iomux &_iomux; /* I/O multiplexer device */
Ccm &_ccm; /* clock control module */
Src &_src; /* system reset controller */
Iim &_iim; /* IC identification module */
Iomux &_iomux; /* I/O multiplexer device */
Ccm &_ccm; /* clock control module */
Src &_src; /* system reset controller */
public:
/**
* Constructor
*/
Session_component(Iomux &iomux, Ccm &ccm, Src &src)
: _iomux(iomux), _ccm(ccm), _src(src) {}
Session_component(Iim &iim, Iomux &iomux, Ccm &ccm, Src &src)
: _iim(iim), _iomux(iomux), _ccm(ccm), _src(src) {}
/**********************************
@ -56,6 +58,7 @@ class Platform::Session_component : public Genode::Rpc_object<Platform::Session>
case Session::IPU:
_src.reset_ipu();
_ccm.ipu_clk_enable();
_iomux.enable_di1();
break;
default:
PWRN("Invalid device");
@ -80,6 +83,15 @@ class Platform::Session_component : public Genode::Rpc_object<Platform::Session>
PWRN("Invalid device");
};
}
Board_revision revision()
{
switch (_iim.revision()) {
case QSB: return QSB;
case SMD: return SMD;
};
return UNKNOWN;
}
};
@ -87,6 +99,7 @@ class Platform::Root : public Genode::Root_component<Platform::Session_component
{
private:
Iim _iim;
Iomux _iomux;
Ccm _ccm;
Src _src;
@ -94,7 +107,7 @@ class Platform::Root : public Genode::Root_component<Platform::Session_component
protected:
Session_component *_create_session(const char *args) {
return new (md_alloc()) Session_component(_iomux, _ccm, _src); }
return new (md_alloc()) Session_component(_iim, _iomux, _ccm, _src); }
public: