Browse Source

Merge branch 'master' of git://git.denx.de/u-boot-video

master
Wolfgang Denk 10 years ago
parent
commit
33a08c10c7
11 changed files with 4701 additions and 0 deletions
  1. +11
    -0
      arch/arm/include/asm/arch-mx5/crm_regs.h
  2. +68
    -0
      board/ttcontrol/vision2/vision2.c
  3. +1
    -0
      drivers/video/Makefile
  4. +321
    -0
      drivers/video/ipu.h
  5. +1183
    -0
      drivers/video/ipu_common.c
  6. +1359
    -0
      drivers/video/ipu_disp.c
  7. +418
    -0
      drivers/video/ipu_regs.h
  8. +642
    -0
      drivers/video/mxc_ipuv3_fb.c
  9. +68
    -0
      drivers/video/mxcfb.h
  10. +14
    -0
      include/configs/vision2.h
  11. +616
    -0
      include/linux/fb.h

+ 11
- 0
arch/arm/include/asm/arch-mx5/crm_regs.h View File

@ -189,4 +189,15 @@ struct mxc_ccm_reg {
#define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET 0
#define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK 0x7
/* Define the bits in register CCDR */
#define MXC_CCM_CCDR_IPU_HS_MASK (0x1 << 17)
/* Define the bits in register CCGRx */
#define MXC_CCM_CCGR_CG_MASK 0x3
#define MXC_CCM_CCGR5_CG5_OFFSET 10
/* Define the bits in register CLPCR */
#define MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS (0x1 << 18)
#endif /* __ARCH_ARM_MACH_MX51_CRM_REGS_H__ */

+ 68
- 0
board/ttcontrol/vision2/vision2.c View File

@ -37,14 +37,34 @@
#include <fsl_esdhc.h>
#include <fsl_pmic.h>
#include <mc13892.h>
#include <linux/fb.h>
DECLARE_GLOBAL_DATA_PTR;
static u32 system_rev;
extern int mx51_fb_init(struct fb_videomode *mode);
#ifdef CONFIG_HW_WATCHDOG
#include <watchdog.h>
static struct fb_videomode nec_nl6448bc26_09c = {
"NEC_NL6448BC26-09C",
60, /* Refresh */
640, /* xres */
480, /* yres */
37650, /* pixclock = 26.56Mhz */
48, /* left margin */
16, /* right margin */
31, /* upper margin */
12, /* lower margin */
96, /* hsync-len */
2, /* vsync-len */
0, /* sync */
FB_VMODE_NONINTERLACED, /* vmode */
0, /* flag */
};
void hw_watchdog_reset(void)
{
int val;
@ -423,6 +443,9 @@ static void setup_gpios(void)
mxc_request_iomux(MX51_PIN_CSPI1_RDY, IOMUX_CONFIG_ALT3);
mxc_iomux_set_pad(MX51_PIN_CSPI1_RDY, 0x82);
/* PWM Output GPIO1_2 */
mxc_request_iomux(MX51_PIN_GPIO1_2, IOMUX_CONFIG_ALT1);
/*
* Set GPIO1_4 to high and output; it is used to reset
* the system on reboot
@ -630,6 +653,33 @@ int board_early_init_f(void)
return 0;
}
static void backlight(int on)
{
if (on) {
mxc_gpio_set(65, 1);
udelay(10000);
mxc_gpio_set(68, 1);
} else {
mxc_gpio_set(65, 0);
mxc_gpio_set(68, 0);
}
}
void lcd_enable(void)
{
int ret;
mxc_request_iomux(MX51_PIN_DI1_PIN2, IOMUX_CONFIG_ALT0);
mxc_request_iomux(MX51_PIN_DI1_PIN3, IOMUX_CONFIG_ALT0);
mxc_gpio_set(2, 1);
mxc_request_iomux(MX51_PIN_GPIO1_2, IOMUX_CONFIG_ALT0);
ret = mx51_fb_init(&nec_nl6448bc26_09c);
if (ret)
puts("LCD cannot be configured\n");
}
int board_init(void)
{
#ifdef CONFIG_SYS_ARM_WITHOUT_RELOC
@ -709,3 +759,21 @@ int checkboard(void)
return 0;
}
int do_vision_lcd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
int on;
if (argc < 2)
return cmd_usage(cmdtp);
on = (strcmp(argv[1], "on") == 0);
backlight(on);
return 0;
}
U_BOOT_CMD(
lcdbl, CONFIG_SYS_MAXARGS, 1, do_vision_lcd,
"Vision2 Backlight",
"lcdbl [on|off]\n"
);

+ 1
- 0
drivers/video/Makefile View File

@ -34,6 +34,7 @@ COBJS-$(CONFIG_VIDEO_CT69000) += ct69000.o videomodes.o
COBJS-$(CONFIG_VIDEO_MB862xx) += mb862xx.o videomodes.o
COBJS-$(CONFIG_VIDEO_MB86R0xGDC) += mb86r0xgdc.o videomodes.o
COBJS-$(CONFIG_VIDEO_MX3) += mx3fb.o
COBJS-$(CONFIG_VIDEO_MX5) += mxc_ipuv3_fb.o ipu_common.o ipu_disp.o
COBJS-$(CONFIG_VIDEO_SED13806) += sed13806.o
COBJS-$(CONFIG_SED156X) += sed156x.o
COBJS-$(CONFIG_VIDEO_SM501) += sm501.o


+ 321
- 0
drivers/video/ipu.h View File

@ -0,0 +1,321 @@
/*
* Porting to u-boot:
*
* (C) Copyright 2010
* Stefano Babic, DENX Software Engineering, sbabic@denx.de
*
* Linux IPU driver for MX51:
*
* (C) Copyright 2005-2010 Freescale Semiconductor, Inc.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#ifndef __ASM_ARCH_IPU_H__
#define __ASM_ARCH_IPU_H__
#include <linux/types.h>
#define IDMA_CHAN_INVALID 0xFF
#define HIGH_RESOLUTION_WIDTH 1024
struct clk {
const char *name;
int id;
/* Source clock this clk depends on */
struct clk *parent;
/* Secondary clock to enable/disable with this clock */
struct clk *secondary;
/* Current clock rate */
unsigned long rate;
/* Reference count of clock enable/disable */
__s8 usecount;
/* Register bit position for clock's enable/disable control. */
u8 enable_shift;
/* Register address for clock's enable/disable control. */
void *enable_reg;
u32 flags;
/*
* Function ptr to recalculate the clock's rate based on parent
* clock's rate
*/
void (*recalc) (struct clk *);
/*
* Function ptr to set the clock to a new rate. The rate must match a
* supported rate returned from round_rate. Leave blank if clock is not
* programmable
*/
int (*set_rate) (struct clk *, unsigned long);
/*
* Function ptr to round the requested clock rate to the nearest
* supported rate that is less than or equal to the requested rate.
*/
unsigned long (*round_rate) (struct clk *, unsigned long);
/*
* Function ptr to enable the clock. Leave blank if clock can not
* be gated.
*/
int (*enable) (struct clk *);
/*
* Function ptr to disable the clock. Leave blank if clock can not
* be gated.
*/
void (*disable) (struct clk *);
/* Function ptr to set the parent clock of the clock. */
int (*set_parent) (struct clk *, struct clk *);
};
/*
* Enumeration of Synchronous (Memory-less) panel types
*/
typedef enum {
IPU_PANEL_SHARP_TFT,
IPU_PANEL_TFT,
} ipu_panel_t;
/* IPU Pixel format definitions */
#define fourcc(a, b, c, d)\
(((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24))
/*
* Pixel formats are defined with ASCII FOURCC code. The pixel format codes are
* the same used by V4L2 API.
*/
#define IPU_PIX_FMT_GENERIC fourcc('I', 'P', 'U', '0')
#define IPU_PIX_FMT_GENERIC_32 fourcc('I', 'P', 'U', '1')
#define IPU_PIX_FMT_LVDS666 fourcc('L', 'V', 'D', '6')
#define IPU_PIX_FMT_LVDS888 fourcc('L', 'V', 'D', '8')
#define IPU_PIX_FMT_RGB332 fourcc('R', 'G', 'B', '1') /*< 8 RGB-3-3-2 */
#define IPU_PIX_FMT_RGB555 fourcc('R', 'G', 'B', 'O') /*< 16 RGB-5-5-5 */
#define IPU_PIX_FMT_RGB565 fourcc('R', 'G', 'B', 'P') /*< 1 6 RGB-5-6-5 */
#define IPU_PIX_FMT_RGB666 fourcc('R', 'G', 'B', '6') /*< 18 RGB-6-6-6 */
#define IPU_PIX_FMT_BGR666 fourcc('B', 'G', 'R', '6') /*< 18 BGR-6-6-6 */
#define IPU_PIX_FMT_BGR24 fourcc('B', 'G', 'R', '3') /*< 24 BGR-8-8-8 */
#define IPU_PIX_FMT_RGB24 fourcc('R', 'G', 'B', '3') /*< 24 RGB-8-8-8 */
#define IPU_PIX_FMT_BGR32 fourcc('B', 'G', 'R', '4') /*< 32 BGR-8-8-8-8 */
#define IPU_PIX_FMT_BGRA32 fourcc('B', 'G', 'R', 'A') /*< 32 BGR-8-8-8-8 */
#define IPU_PIX_FMT_RGB32 fourcc('R', 'G', 'B', '4') /*< 32 RGB-8-8-8-8 */
#define IPU_PIX_FMT_RGBA32 fourcc('R', 'G', 'B', 'A') /*< 32 RGB-8-8-8-8 */
#define IPU_PIX_FMT_ABGR32 fourcc('A', 'B', 'G', 'R') /*< 32 ABGR-8-8-8-8 */
/* YUV Interleaved Formats */
#define IPU_PIX_FMT_YUYV fourcc('Y', 'U', 'Y', 'V') /*< 16 YUV 4:2:2 */
#define IPU_PIX_FMT_UYVY fourcc('U', 'Y', 'V', 'Y') /*< 16 YUV 4:2:2 */
#define IPU_PIX_FMT_Y41P fourcc('Y', '4', '1', 'P') /*< 12 YUV 4:1:1 */
#define IPU_PIX_FMT_YUV444 fourcc('Y', '4', '4', '4') /*< 24 YUV 4:4:4 */
/* two planes -- one Y, one Cb + Cr interleaved */
#define IPU_PIX_FMT_NV12 fourcc('N', 'V', '1', '2') /* 12 Y/CbCr 4:2:0 */
#define IPU_PIX_FMT_GREY fourcc('G', 'R', 'E', 'Y') /*< 8 Greyscale */
#define IPU_PIX_FMT_YVU410P fourcc('Y', 'V', 'U', '9') /*< 9 YVU 4:1:0 */
#define IPU_PIX_FMT_YUV410P fourcc('Y', 'U', 'V', '9') /*< 9 YUV 4:1:0 */
#define IPU_PIX_FMT_YVU420P fourcc('Y', 'V', '1', '2') /*< 12 YVU 4:2:0 */
#define IPU_PIX_FMT_YUV420P fourcc('I', '4', '2', '0') /*< 12 YUV 4:2:0 */
#define IPU_PIX_FMT_YUV420P2 fourcc('Y', 'U', '1', '2') /*< 12 YUV 4:2:0 */
#define IPU_PIX_FMT_YVU422P fourcc('Y', 'V', '1', '6') /*< 16 YVU 4:2:2 */
#define IPU_PIX_FMT_YUV422P fourcc('4', '2', '2', 'P') /*< 16 YUV 4:2:2 */
/*
* IPU Driver channels definitions.
* Note these are different from IDMA channels
*/
#define IPU_MAX_CH 32
#define _MAKE_CHAN(num, v_in, g_in, a_in, out) \
((num << 24) | (v_in << 18) | (g_in << 12) | (a_in << 6) | out)
#define _MAKE_ALT_CHAN(ch) (ch | (IPU_MAX_CH << 24))
#define IPU_CHAN_ID(ch) (ch >> 24)
#define IPU_CHAN_ALT(ch) (ch & 0x02000000)
#define IPU_CHAN_ALPHA_IN_DMA(ch) ((uint32_t) (ch >> 6) & 0x3F)
#define IPU_CHAN_GRAPH_IN_DMA(ch) ((uint32_t) (ch >> 12) & 0x3F)
#define IPU_CHAN_VIDEO_IN_DMA(ch) ((uint32_t) (ch >> 18) & 0x3F)
#define IPU_CHAN_OUT_DMA(ch) ((uint32_t) (ch & 0x3F))
#define NO_DMA 0x3F
#define ALT 1
/*
* Enumeration of IPU logical channels. An IPU logical channel is defined as a
* combination of an input (memory to IPU), output (IPU to memory), and/or
* secondary input IDMA channels and in some cases an Image Converter task.
* Some channels consist of only an input or output.
*/
typedef enum {
CHAN_NONE = -1,
MEM_DC_SYNC = _MAKE_CHAN(7, 28, NO_DMA, NO_DMA, NO_DMA),
MEM_DC_ASYNC = _MAKE_CHAN(8, 41, NO_DMA, NO_DMA, NO_DMA),
MEM_BG_SYNC = _MAKE_CHAN(9, 23, NO_DMA, 51, NO_DMA),
MEM_FG_SYNC = _MAKE_CHAN(10, 27, NO_DMA, 31, NO_DMA),
MEM_BG_ASYNC0 = _MAKE_CHAN(11, 24, NO_DMA, 52, NO_DMA),
MEM_FG_ASYNC0 = _MAKE_CHAN(12, 29, NO_DMA, 33, NO_DMA),
MEM_BG_ASYNC1 = _MAKE_ALT_CHAN(MEM_BG_ASYNC0),
MEM_FG_ASYNC1 = _MAKE_ALT_CHAN(MEM_FG_ASYNC0),
DIRECT_ASYNC0 = _MAKE_CHAN(13, NO_DMA, NO_DMA, NO_DMA, NO_DMA),
DIRECT_ASYNC1 = _MAKE_CHAN(14, NO_DMA, NO_DMA, NO_DMA, NO_DMA),
} ipu_channel_t;
/*
* Enumeration of types of buffers for a logical channel.
*/
typedef enum {
IPU_OUTPUT_BUFFER = 0, /*< Buffer for output from IPU */
IPU_ALPHA_IN_BUFFER = 1, /*< Buffer for input to IPU */
IPU_GRAPH_IN_BUFFER = 2, /*< Buffer for input to IPU */
IPU_VIDEO_IN_BUFFER = 3, /*< Buffer for input to IPU */
IPU_INPUT_BUFFER = IPU_VIDEO_IN_BUFFER,
IPU_SEC_INPUT_BUFFER = IPU_GRAPH_IN_BUFFER,
} ipu_buffer_t;
#define IPU_PANEL_SERIAL 1
#define IPU_PANEL_PARALLEL 2
struct ipu_channel {
u8 video_in_dma;
u8 alpha_in_dma;
u8 graph_in_dma;
u8 out_dma;
};
enum ipu_dmfc_type {
DMFC_NORMAL = 0,
DMFC_HIGH_RESOLUTION_DC,
DMFC_HIGH_RESOLUTION_DP,
DMFC_HIGH_RESOLUTION_ONLY_DP,
};
/*
* Union of initialization parameters for a logical channel.
*/
typedef union {
struct {
uint32_t di;
unsigned char interlaced;
} mem_dc_sync;
struct {
uint32_t temp;
} mem_sdc_fg;
struct {
uint32_t di;
unsigned char interlaced;
uint32_t in_pixel_fmt;
uint32_t out_pixel_fmt;
unsigned char alpha_chan_en;
} mem_dp_bg_sync;
struct {
uint32_t temp;
} mem_sdc_bg;
struct {
uint32_t di;
unsigned char interlaced;
uint32_t in_pixel_fmt;
uint32_t out_pixel_fmt;
unsigned char alpha_chan_en;
} mem_dp_fg_sync;
} ipu_channel_params_t;
/*
* Bitfield of Display Interface signal polarities.
*/
typedef struct {
unsigned datamask_en:1;
unsigned ext_clk:1;
unsigned interlaced:1;
unsigned odd_field_first:1;
unsigned clksel_en:1;
unsigned clkidle_en:1;
unsigned data_pol:1; /* true = inverted */
unsigned clk_pol:1; /* true = rising edge */
unsigned enable_pol:1;
unsigned Hsync_pol:1; /* true = active high */
unsigned Vsync_pol:1;
} ipu_di_signal_cfg_t;
typedef enum {
RGB,
YCbCr,
YUV
} ipu_color_space_t;
/* Common IPU API */
int32_t ipu_init_channel(ipu_channel_t channel, ipu_channel_params_t *params);
void ipu_uninit_channel(ipu_channel_t channel);
int32_t ipu_init_channel_buffer(ipu_channel_t channel, ipu_buffer_t type,
uint32_t pixel_fmt,
uint16_t width, uint16_t height,
uint32_t stride,
dma_addr_t phyaddr_0, dma_addr_t phyaddr_1,
uint32_t u_offset, uint32_t v_offset);
int32_t ipu_update_channel_buffer(ipu_channel_t channel, ipu_buffer_t type,
uint32_t bufNum, dma_addr_t phyaddr);
int32_t ipu_is_channel_busy(ipu_channel_t channel);
void ipu_clear_buffer_ready(ipu_channel_t channel, ipu_buffer_t type,
uint32_t bufNum);
int32_t ipu_enable_channel(ipu_channel_t channel);
int32_t ipu_disable_channel(ipu_channel_t channel);
int32_t ipu_init_sync_panel(int disp,
uint32_t pixel_clk,
uint16_t width, uint16_t height,
uint32_t pixel_fmt,
uint16_t h_start_width, uint16_t h_sync_width,
uint16_t h_end_width, uint16_t v_start_width,
uint16_t v_sync_width, uint16_t v_end_width,
uint32_t v_to_h_sync, ipu_di_signal_cfg_t sig);
int32_t ipu_disp_set_global_alpha(ipu_channel_t channel, unsigned char enable,
uint8_t alpha);
int32_t ipu_disp_set_color_key(ipu_channel_t channel, unsigned char enable,
uint32_t colorKey);
uint32_t bytes_per_pixel(uint32_t fmt);
void clk_enable(struct clk *clk);
void clk_disable(struct clk *clk);
u32 clk_get_rate(struct clk *clk);
int clk_set_rate(struct clk *clk, unsigned long rate);
long clk_round_rate(struct clk *clk, unsigned long rate);
int clk_set_parent(struct clk *clk, struct clk *parent);
int clk_get_usecount(struct clk *clk);
struct clk *clk_get_parent(struct clk *clk);
void ipu_dump_registers(void);
int ipu_probe(void);
void ipu_dmfc_init(int dmfc_type, int first);
void ipu_init_dc_mappings(void);
void ipu_dmfc_set_wait4eot(int dma_chan, int width);
void ipu_dc_init(int dc_chan, int di, unsigned char interlaced);
void ipu_dc_uninit(int dc_chan);
void ipu_dp_dc_enable(ipu_channel_t channel);
int ipu_dp_init(ipu_channel_t channel, uint32_t in_pixel_fmt,
uint32_t out_pixel_fmt);
void ipu_dp_uninit(ipu_channel_t channel);
void ipu_dp_dc_disable(ipu_channel_t channel, unsigned char swap);
ipu_color_space_t format_to_colorspace(uint32_t fmt);
#endif

+ 1183
- 0
drivers/video/ipu_common.c
File diff suppressed because it is too large
View File


+ 1359
- 0
drivers/video/ipu_disp.c
File diff suppressed because it is too large
View File


+ 418
- 0
drivers/video/ipu_regs.h View File

@ -0,0 +1,418 @@
/*
* Porting to u-boot:
*
* (C) Copyright 2010
* Stefano Babic, DENX Software Engineering, sbabic@denx.de
*
* Linux IPU driver for MX51:
*
* (C) Copyright 2005-2009 Freescale Semiconductor, Inc.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#ifndef __IPU_REGS_INCLUDED__
#define __IPU_REGS_INCLUDED__
#define IPU_DISP0_BASE 0x00000000
#define IPU_MCU_T_DEFAULT 8
#define IPU_DISP1_BASE (IPU_MCU_T_DEFAULT << 25)
#define IPU_CM_REG_BASE 0x1E000000
#define IPU_STAT_REG_BASE 0x1E000200
#define IPU_IDMAC_REG_BASE 0x1E008000
#define IPU_ISP_REG_BASE 0x1E010000
#define IPU_DP_REG_BASE 0x1E018000
#define IPU_IC_REG_BASE 0x1E020000
#define IPU_IRT_REG_BASE 0x1E028000
#define IPU_CSI0_REG_BASE 0x1E030000
#define IPU_CSI1_REG_BASE 0x1E038000
#define IPU_DI0_REG_BASE 0x1E040000
#define IPU_DI1_REG_BASE 0x1E048000
#define IPU_SMFC_REG_BASE 0x1E050000
#define IPU_DC_REG_BASE 0x1E058000
#define IPU_DMFC_REG_BASE 0x1E060000
#define IPU_CPMEM_REG_BASE 0x1F000000
#define IPU_LUT_REG_BASE 0x1F020000
#define IPU_SRM_REG_BASE 0x1F040000
#define IPU_TPM_REG_BASE 0x1F060000
#define IPU_DC_TMPL_REG_BASE 0x1F080000
#define IPU_ISP_TBPR_REG_BASE 0x1F0C0000
#define IPU_VDI_REG_BASE 0x1E068000
extern u32 *ipu_dc_tmpl_reg;
#define DC_EVT_NF 0
#define DC_EVT_NL 1
#define DC_EVT_EOF 2
#define DC_EVT_NFIELD 3
#define DC_EVT_EOL 4
#define DC_EVT_EOFIELD 5
#define DC_EVT_NEW_ADDR 6
#define DC_EVT_NEW_CHAN 7
#define DC_EVT_NEW_DATA 8
#define DC_EVT_NEW_ADDR_W_0 0
#define DC_EVT_NEW_ADDR_W_1 1
#define DC_EVT_NEW_CHAN_W_0 2
#define DC_EVT_NEW_CHAN_W_1 3
#define DC_EVT_NEW_DATA_W_0 4
#define DC_EVT_NEW_DATA_W_1 5
#define DC_EVT_NEW_ADDR_R_0 6
#define DC_EVT_NEW_ADDR_R_1 7
#define DC_EVT_NEW_CHAN_R_0 8
#define DC_EVT_NEW_CHAN_R_1 9
#define DC_EVT_NEW_DATA_R_0 10
#define DC_EVT_NEW_DATA_R_1 11
/* Software reset for ipu */
#define SW_IPU_RST 8
enum {
IPU_CONF_DP_EN = 0x00000020,
IPU_CONF_DI0_EN = 0x00000040,
IPU_CONF_DI1_EN = 0x00000080,
IPU_CONF_DMFC_EN = 0x00000400,
IPU_CONF_DC_EN = 0x00000200,
DI0_COUNTER_RELEASE = 0x01000000,
DI1_COUNTER_RELEASE = 0x02000000,
DI_DW_GEN_ACCESS_SIZE_OFFSET = 24,
DI_DW_GEN_COMPONENT_SIZE_OFFSET = 16,
DI_GEN_DI_CLK_EXT = 0x100000,
DI_GEN_POLARITY_1 = 0x00000001,
DI_GEN_POLARITY_2 = 0x00000002,
DI_GEN_POLARITY_3 = 0x00000004,
DI_GEN_POLARITY_4 = 0x00000008,
DI_GEN_POLARITY_5 = 0x00000010,
DI_GEN_POLARITY_6 = 0x00000020,
DI_GEN_POLARITY_7 = 0x00000040,
DI_GEN_POLARITY_8 = 0x00000080,
DI_GEN_POL_CLK = 0x20000,
DI_POL_DRDY_DATA_POLARITY = 0x00000080,
DI_POL_DRDY_POLARITY_15 = 0x00000010,
DI_VSYNC_SEL_OFFSET = 13,
DC_WR_CH_CONF_FIELD_MODE = 0x00000200,
DC_WR_CH_CONF_PROG_TYPE_OFFSET = 5,
DC_WR_CH_CONF_PROG_TYPE_MASK = 0x000000E0,
DC_WR_CH_CONF_PROG_DI_ID = 0x00000004,
DC_WR_CH_CONF_PROG_DISP_ID_OFFSET = 3,
DC_WR_CH_CONF_PROG_DISP_ID_MASK = 0x00000018,
DP_COM_CONF_FG_EN = 0x00000001,
DP_COM_CONF_GWSEL = 0x00000002,
DP_COM_CONF_GWAM = 0x00000004,
DP_COM_CONF_GWCKE = 0x00000008,
DP_COM_CONF_CSC_DEF_MASK = 0x00000300,
DP_COM_CONF_CSC_DEF_OFFSET = 8,
DP_COM_CONF_CSC_DEF_FG = 0x00000300,
DP_COM_CONF_CSC_DEF_BG = 0x00000200,
DP_COM_CONF_CSC_DEF_BOTH = 0x00000100,
DP_COM_CONF_GAMMA_EN = 0x00001000,
DP_COM_CONF_GAMMA_YUV_EN = 0x00002000,
};
enum di_pins {
DI_PIN11 = 0,
DI_PIN12 = 1,
DI_PIN13 = 2,
DI_PIN14 = 3,
DI_PIN15 = 4,
DI_PIN16 = 5,
DI_PIN17 = 6,
DI_PIN_CS = 7,
DI_PIN_SER_CLK = 0,
DI_PIN_SER_RS = 1,
};
enum di_sync_wave {
DI_SYNC_NONE = -1,
DI_SYNC_CLK = 0,
DI_SYNC_INT_HSYNC = 1,
DI_SYNC_HSYNC = 2,
DI_SYNC_VSYNC = 3,
DI_SYNC_DE = 5,
};
struct ipu_cm {
u32 conf;
u32 sisg_ctrl0;
u32 sisg_ctrl1;
u32 sisg_set[6];
u32 sisg_clear[6];
u32 int_ctrl[15];
u32 sdma_event[10];
u32 srm_pri1;
u32 srm_pri2;
u32 fs_proc_flow[3];
u32 fs_disp_flow[2];
u32 skip;
u32 disp_alt_conf;
u32 disp_gen;
u32 disp_alt[4];
u32 snoop;
u32 mem_rst;
u32 pm;
u32 gpr;
u32 reserved0[26];
u32 ch_db_mode_sel[2];
u32 reserved1[16];
u32 alt_ch_db_mode_sel[2];
u32 reserved2[2];
u32 ch_trb_mode_sel[2];
};
struct ipu_idmac {
u32 conf;
u32 ch_en[2];
u32 sep_alpha;
u32 alt_sep_alpha;
u32 ch_pri[2];
u32 wm_en[2];
u32 lock_en[2];
u32 sub_addr[5];
u32 bndm_en[2];
u32 sc_cord[2];
u32 reserved[45];
u32 ch_busy[2];
};
struct ipu_com_async {
u32 com_conf_async;
u32 graph_wind_ctrl_async;
u32 fg_pos_async;
u32 cur_pos_async;
u32 cur_map_async;
u32 gamma_c_async[8];
u32 gamma_s_async[4];
u32 dp_csca_async[4];
u32 dp_csc_async[2];
};
struct ipu_dp {
u32 com_conf_sync;
u32 graph_wind_ctrl_sync;
u32 fg_pos_sync;
u32 cur_pos_sync;
u32 cur_map_sync;
u32 gamma_c_sync[8];
u32 gamma_s_sync[4];
u32 csca_sync[4];
u32 csc_sync[2];
u32 cur_pos_alt;
struct ipu_com_async async[2];
};
struct ipu_di {
u32 general;
u32 bs_clkgen0;
u32 bs_clkgen1;
u32 sw_gen0[9];
u32 sw_gen1[9];
u32 sync_as;
u32 dw_gen[12];
u32 dw_set[48];
u32 stp_rep[4];
u32 stp_rep9;
u32 ser_conf;
u32 ssc;
u32 pol;
u32 aw0;
u32 aw1;
u32 scr_conf;
u32 stat;
};
struct ipu_stat {
u32 int_stat[15];
u32 cur_buf[2];
u32 alt_cur_buf_0;
u32 alt_cur_buf_1;
u32 srm_stat;
u32 proc_task_stat;
u32 disp_task_stat;
u32 triple_cur_buf[4];
u32 ch_buf0_rdy[2];
u32 ch_buf1_rdy[2];
u32 alt_ch_buf0_rdy[2];
u32 alt_ch_buf1_rdy[2];
u32 ch_buf2_rdy[2];
};
struct ipu_dc_ch {
u32 wr_ch_conf;
u32 wr_ch_addr;
u32 rl[5];
};
struct ipu_dc {
struct ipu_dc_ch dc_ch0_1_2[3];
u32 cmd_ch_conf_3;
u32 cmd_ch_conf_4;
struct ipu_dc_ch dc_ch5_6[2];
struct ipu_dc_ch dc_ch8;
u32 rl6_ch_8;
struct ipu_dc_ch dc_ch9;
u32 rl6_ch_9;
u32 gen;
u32 disp_conf1[4];
u32 disp_conf2[4];
u32 di0_conf[2];
u32 di1_conf[2];
u32 dc_map_ptr[15];
u32 dc_map_val[12];
u32 udge[16];
u32 lla[2];
u32 r_lla[2];
u32 wr_ch_addr_5_alt;
u32 stat;
};
struct ipu_dmfc {
u32 rd_chan;
u32 wr_chan;
u32 wr_chan_def;
u32 dp_chan;
u32 dp_chan_def;
u32 general[2];
u32 ic_ctrl;
u32 wr_chan_alt;
u32 wr_chan_def_alt;
u32 general1_alt;
u32 stat;
};
#define IPU_CM_REG ((struct ipu_cm *)(IPU_CTRL_BASE_ADDR + \
IPU_CM_REG_BASE))
#define IPU_CONF (&IPU_CM_REG->conf)
#define IPU_SRM_PRI1 (&IPU_CM_REG->srm_pri1)
#define IPU_SRM_PRI2 (&IPU_CM_REG->srm_pri2)
#define IPU_FS_PROC_FLOW1 (&IPU_CM_REG->fs_proc_flow[0])
#define IPU_FS_PROC_FLOW2 (&IPU_CM_REG->fs_proc_flow[1])
#define IPU_FS_PROC_FLOW3 (&IPU_CM_REG->fs_proc_flow[2])
#define IPU_FS_DISP_FLOW1 (&IPU_CM_REG->fs_disp_flow[0])
#define IPU_DISP_GEN (&IPU_CM_REG->disp_gen)
#define IPU_MEM_RST (&IPU_CM_REG->mem_rst)
#define IPU_GPR (&IPU_CM_REG->gpr)
#define IPU_CHA_DB_MODE_SEL(ch) (&IPU_CM_REG->ch_db_mode_sel[ch / 32])
#define IPU_STAT ((struct ipu_stat *)(IPU_CTRL_BASE_ADDR + \
IPU_STAT_REG_BASE))
#define IPU_CHA_CUR_BUF(ch) (&IPU_STAT->cur_buf[ch / 32])
#define IPU_CHA_BUF0_RDY(ch) (&IPU_STAT->ch_buf0_rdy[ch / 32])
#define IPU_CHA_BUF1_RDY(ch) (&IPU_STAT->ch_buf1_rdy[ch / 32])
#define IPU_INT_CTRL(n) (&IPU_CM_REG->int_ctrl[(n) - 1])
#define IDMAC_REG ((struct ipu_idmac *)(IPU_CTRL_BASE_ADDR + \
IPU_IDMAC_REG_BASE))
#define IDMAC_CONF (&IDMAC_REG->conf)
#define IDMAC_CHA_EN(ch) (&IDMAC_REG->ch_en[ch / 32])
#define IDMAC_CHA_PRI(ch) (&IDMAC_REG->ch_pri[ch / 32])
#define DI_REG(di) ((struct ipu_di *)(IPU_CTRL_BASE_ADDR + \
((di == 1) ? IPU_DI1_REG_BASE : \
IPU_DI0_REG_BASE)))
#define DI_GENERAL(di) (&DI_REG(di)->general)
#define DI_BS_CLKGEN0(di) (&DI_REG(di)->bs_clkgen0)
#define DI_BS_CLKGEN1(di) (&DI_REG(di)->bs_clkgen1)
#define DI_SW_GEN0(di, gen) (&DI_REG(di)->sw_gen0[gen - 1])
#define DI_SW_GEN1(di, gen) (&DI_REG(di)->sw_gen1[gen - 1])
#define DI_STP_REP(di, gen) (&DI_REG(di)->stp_rep[(gen - 1) / 2])
#define DI_SYNC_AS_GEN(di) (&DI_REG(di)->sync_as)
#define DI_DW_GEN(di, gen) (&DI_REG(di)->dw_gen[gen])
#define DI_DW_SET(di, gen, set) (&DI_REG(di)->dw_set[gen + 12 * set])
#define DI_POL(di) (&DI_REG(di)->pol)
#define DI_SCR_CONF(di) (&DI_REG(di)->scr_conf)
#define DMFC_REG ((struct ipu_dmfc *)(IPU_CTRL_BASE_ADDR + \
IPU_DMFC_REG_BASE))
#define DMFC_WR_CHAN (&DMFC_REG->wr_chan)
#define DMFC_WR_CHAN_DEF (&DMFC_REG->wr_chan_def)
#define DMFC_DP_CHAN (&DMFC_REG->dp_chan)
#define DMFC_DP_CHAN_DEF (&DMFC_REG->dp_chan_def)
#define DMFC_GENERAL1 (&DMFC_REG->general[0])
#define DMFC_IC_CTRL (&DMFC_REG->ic_ctrl)
#define DC_REG ((struct ipu_dc *)(IPU_CTRL_BASE_ADDR + \
IPU_DC_REG_BASE))
#define DC_MAP_CONF_PTR(n) (&DC_REG->dc_map_ptr[n / 2])
#define DC_MAP_CONF_VAL(n) (&DC_REG->dc_map_val[n / 2])
static inline struct ipu_dc_ch *dc_ch_offset(int ch)
{
switch (ch) {
case 0:
case 1:
case 2:
return &DC_REG->dc_ch0_1_2[ch];
case 5:
case 6:
return &DC_REG->dc_ch5_6[ch - 5];
case 8:
return &DC_REG->dc_ch8;
case 9:
return &DC_REG->dc_ch9;
default:
printf("%s: invalid channel %d\n", __func__, ch);
return NULL;
}
}
#define DC_RL_CH(ch, evt) (&dc_ch_offset(ch)->rl[evt / 2])
#define DC_WR_CH_CONF(ch) (&dc_ch_offset(ch)->wr_ch_conf)
#define DC_WR_CH_ADDR(ch) (&dc_ch_offset(ch)->wr_ch_addr)
#define DC_WR_CH_CONF_1 DC_WR_CH_CONF(1)
#define DC_WR_CH_CONF_5 DC_WR_CH_CONF(5)
#define DC_GEN (&DC_REG->gen)
#define DC_DISP_CONF2(disp) (&DC_REG->disp_conf2[disp])
#define DC_STAT (&DC_REG->stat)
#define DP_SYNC 0
#define DP_ASYNC0 0x60
#define DP_ASYNC1 0xBC
#define DP_REG ((struct ipu_dp *)(IPU_CTRL_BASE_ADDR + \
IPU_DP_REG_BASE))
#define DP_COM_CONF(flow) (&DP_REG->com_conf_sync)
#define DP_GRAPH_WIND_CTRL(flow) (&DP_REG->graph_wind_ctrl_sync)
#define DP_CSC_A_0(flow) (&DP_REG->csca_sync[0])
#define DP_CSC_A_1(flow) (&DP_REG->csca_sync[1])
#define DP_CSC_A_2(flow) (&DP_REG->csca_sync[2])
#define DP_CSC_A_3(flow) (&DP_REG->csca_sync[3])
#define DP_CSC_0(flow) (&DP_REG->csc_sync[0])
#define DP_CSC_1(flow) (&DP_REG->csc_sync[1])
/* DC template opcodes */
#define WROD(lf) (0x18 | (lf << 1))
#endif

+ 642
- 0
drivers/video/mxc_ipuv3_fb.c View File

@ -0,0 +1,642 @@
/*
* Porting to u-boot:
*
* (C) Copyright 2010
* Stefano Babic, DENX Software Engineering, sbabic@denx.de
*
* MX51 Linux framebuffer:
*
* (C) Copyright 2004-2010 Freescale Semiconductor, Inc.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/* #define DEBUG */
#include <common.h>
#include <asm/errno.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/fb.h>
#include <asm/io.h>
#include <malloc.h>
#include <lcd.h>
#include "videomodes.h"
#include "ipu.h"
#include "mxcfb.h"
DECLARE_GLOBAL_DATA_PTR;
void *lcd_base; /* Start of framebuffer memory */
void *lcd_console_address; /* Start of console buffer */
int lcd_line_length;
int lcd_color_fg;
int lcd_color_bg;
short console_col;
short console_row;
vidinfo_t panel_info;
static int mxcfb_map_video_memory(struct fb_info *fbi);
static int mxcfb_unmap_video_memory(struct fb_info *fbi);
void lcd_initcolregs(void)
{
}
void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue)
{
}
void lcd_disable(void)
{
}
void lcd_panel_disable(void)
{
}
void fb_videomode_to_var(struct fb_var_screeninfo *var,
const struct fb_videomode *mode)
{
var->xres = mode->xres;
var->yres = mode->yres;
var->xres_virtual = mode->xres;
var->yres_virtual = mode->yres;
var->xoffset = 0;
var->yoffset = 0;
var->pixclock = mode->pixclock;
var->left_margin = mode->left_margin;
var->right_margin = mode->right_margin;
var->upper_margin = mode->upper_margin;
var->lower_margin = mode->lower_margin;
var->hsync_len = mode->hsync_len;
var->vsync_len = mode->vsync_len;
var->sync = mode->sync;
var->vmode = mode->vmode & FB_VMODE_MASK;
}
/*
* Structure containing the MXC specific framebuffer information.
*/
struct mxcfb_info {
int blank;
ipu_channel_t ipu_ch;
int ipu_di;
u32 ipu_di_pix_fmt;
unsigned char overlay;
unsigned char alpha_chan_en;
dma_addr_t alpha_phy_addr0;
dma_addr_t alpha_phy_addr1;
void *alpha_virt_addr0;
void *alpha_virt_addr1;
uint32_t alpha_mem_len;
uint32_t cur_ipu_buf;
uint32_t cur_ipu_alpha_buf;
u32 pseudo_palette[16];
};
enum {
BOTH_ON,
SRC_ON,
TGT_ON,
BOTH_OFF
};
static unsigned long default_bpp = 16;
static unsigned char g_dp_in_use;
static struct fb_info *mxcfb_info[3];
static int ext_clk_used;
static uint32_t bpp_to_pixfmt(struct fb_info *fbi)
{
uint32_t pixfmt = 0;
debug("bpp_to_pixfmt: %d\n", fbi->var.bits_per_pixel);
if (fbi->var.nonstd)
return fbi->var.nonstd;
switch (fbi->var.bits_per_pixel) {
case 24:
pixfmt = IPU_PIX_FMT_BGR24;
break;
case 32:
pixfmt = IPU_PIX_FMT_BGR32;
break;
case 16:
pixfmt = IPU_PIX_FMT_RGB565;
break;
}
return pixfmt;
}
/*
* Set fixed framebuffer parameters based on variable settings.
*
* @param info framebuffer information pointer
*/
static int mxcfb_set_fix(struct fb_info *info)
{
struct fb_fix_screeninfo *fix = &info->fix;
struct fb_var_screeninfo *var = &info->var;
fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
fix->type = FB_TYPE_PACKED_PIXELS;
fix->accel = FB_ACCEL_NONE;
fix->visual = FB_VISUAL_TRUECOLOR;
fix->xpanstep = 1;
fix->ypanstep = 1;
return 0;
}
static int setup_disp_channel1(struct fb_info *fbi)
{
ipu_channel_params_t params;
struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
memset(&params, 0, sizeof(params));
params.mem_dp_bg_sync.di = mxc_fbi->ipu_di;
debug("%s called\n", __func__);
/*
* Assuming interlaced means yuv output, below setting also
* valid for mem_dc_sync. FG should have the same vmode as BG.
*/
if (fbi->var.vmode & FB_VMODE_INTERLACED) {
params.mem_dp_bg_sync.interlaced = 1;
params.mem_dp_bg_sync.out_pixel_fmt =
IPU_PIX_FMT_YUV444;
} else {
if (mxc_fbi->ipu_di_pix_fmt) {
params.mem_dp_bg_sync.out_pixel_fmt =
mxc_fbi->ipu_di_pix_fmt;
} else {
params.mem_dp_bg_sync.out_pixel_fmt =
IPU_PIX_FMT_RGB666;
}
}
params.mem_dp_bg_sync.in_pixel_fmt = bpp_to_pixfmt(fbi);
if (mxc_fbi->alpha_chan_en)
params.mem_dp_bg_sync.alpha_chan_en = 1;
ipu_init_channel(mxc_fbi->ipu_ch, &params);
return 0;
}
static int setup_disp_channel2(struct fb_info *fbi)
{
int retval = 0;
struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
mxc_fbi->cur_ipu_buf = 1;
if (mxc_fbi->alpha_chan_en)
mxc_fbi->cur_ipu_alpha_buf = 1;
fbi->var.xoffset = fbi->var.yoffset = 0;
debug("%s: %x %d %d %d %lx %lx\n",
__func__,
mxc_fbi->ipu_ch,
fbi->var.xres,
fbi->var.yres,
fbi->fix.line_length,
fbi->fix.smem_start,
fbi->fix.smem_start +
(fbi->fix.line_length * fbi->var.yres));
retval = ipu_init_channel_buffer(mxc_fbi->ipu_ch, IPU_INPUT_BUFFER,
bpp_to_pixfmt(fbi),
fbi->var.xres, fbi->var.yres,
fbi->fix.line_length,
fbi->fix.smem_start +
(fbi->fix.line_length * fbi->var.yres),
fbi->fix.smem_start,
0, 0);
if (retval)
printf("ipu_init_channel_buffer error %d\n", retval);
return retval;
}
/*
* Set framebuffer parameters and change the operating mode.
*
* @param info framebuffer information pointer
*/
static int mxcfb_set_par(struct fb_info *fbi)
{
int retval = 0;
u32 mem_len;
ipu_di_signal_cfg_t sig_cfg;
struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
uint32_t out_pixel_fmt;
ipu_disable_channel(mxc_fbi->ipu_ch);
ipu_uninit_channel(mxc_fbi->ipu_ch);
mxcfb_set_fix(fbi);
mem_len = fbi->var.yres_virtual * fbi->fix.line_length;
if (!fbi->fix.smem_start || (mem_len > fbi->fix.smem_len)) {
if (fbi->fix.smem_start)
mxcfb_unmap_video_memory(fbi);
if (mxcfb_map_video_memory(fbi) < 0)
return -ENOMEM;
}
setup_disp_channel1(fbi);
memset(&sig_cfg, 0, sizeof(sig_cfg));
if (fbi->var.vmode & FB_VMODE_INTERLACED) {
sig_cfg.interlaced = 1;
out_pixel_fmt = IPU_PIX_FMT_YUV444;
} else {
if (mxc_fbi->ipu_di_pix_fmt)
out_pixel_fmt = mxc_fbi->ipu_di_pix_fmt;
else
out_pixel_fmt = IPU_PIX_FMT_RGB666;
}
if (fbi->var.vmode & FB_VMODE_ODD_FLD_FIRST) /* PAL */
sig_cfg.odd_field_first = 1;
if ((fbi->var.sync & FB_SYNC_EXT) || ext_clk_used)
sig_cfg.ext_clk = 1;
if (fbi->var.sync & FB_SYNC_HOR_HIGH_ACT)
sig_cfg.Hsync_pol = 1;
if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT)
sig_cfg.Vsync_pol = 1;
if (!(fbi->var.sync & FB_SYNC_CLK_LAT_FALL))
sig_cfg.clk_pol = 1;
if (fbi->var.sync & FB_SYNC_DATA_INVERT)
sig_cfg.data_pol = 1;
if (!(fbi->var.sync & FB_SYNC_OE_LOW_ACT))
sig_cfg.enable_pol = 1;
if (fbi->var.sync & FB_SYNC_CLK_IDLE_EN)
sig_cfg.clkidle_en = 1;
debug("pixclock = %ul Hz\n",
(u32) (PICOS2KHZ(fbi->var.pixclock) * 1000UL));
if (ipu_init_sync_panel(mxc_fbi->ipu_di,
(PICOS2KHZ(fbi->var.pixclock)) * 1000UL,
fbi->var.xres, fbi->var.yres,
out_pixel_fmt,
fbi->var.left_margin,
fbi->var.hsync_len,
fbi->var.right_margin,
fbi->var.upper_margin,
fbi->var.vsync_len,
fbi->var.lower_margin,
0, sig_cfg) != 0) {
puts("mxcfb: Error initializing panel.\n");
return -EINVAL;
}
retval = setup_disp_channel2(fbi);
if (retval)
return retval;
if (mxc_fbi->blank == FB_BLANK_UNBLANK)
ipu_enable_channel(mxc_fbi->ipu_ch);
return retval;
}
/*
* Check framebuffer variable parameters and adjust to valid values.
*
* @param var framebuffer variable parameters
*
* @param info framebuffer information pointer
*/
static int mxcfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
u32 vtotal;
u32 htotal;
if (var->xres_virtual < var->xres)
var->xres_virtual = var->xres;
if (var->yres_virtual < var->yres)
var->yres_virtual = var->yres;
if ((var->bits_per_pixel != 32) && (var->bits_per_pixel != 24) &&
(var->bits_per_pixel != 16) && (var->bits_per_pixel != 8))
var->bits_per_pixel = default_bpp;
switch (var->bits_per_pixel) {
case 8:
var->red.length = 3;
var->red.offset = 5;
var->red.msb_right = 0;
var->green.length = 3;
var->green.offset = 2;
var->green.msb_right = 0;
var->blue.length = 2;
var->blue.offset = 0;
var->blue.msb_right = 0;
var->transp.length = 0;
var->transp.offset = 0;
var->transp.msb_right = 0;
break;
case 16:
var->red.length = 5;
var->red.offset = 11;
var->red.msb_right = 0;
var->green.length = 6;
var->green.offset = 5;
var->green.msb_right = 0;
var->blue.length = 5;
var->blue.offset = 0;
var->blue.msb_right = 0;
var->transp.length = 0;
var->transp.offset = 0;
var->transp.msb_right = 0;
break;
case 24:
var->red.length = 8;
var->red.offset = 16;
var->red.msb_right = 0;
var->green.length = 8;
var->green.offset = 8;
var->green.msb_right = 0;
var->blue.length = 8;
var->blue.offset = 0;
var->blue.msb_right = 0;
var->transp.length = 0;
var->transp.offset = 0;
var->transp.msb_right = 0;
break;
case 32:
var->red.length = 8;
var->red.offset = 16;
var->red.msb_right = 0;
var->green.length = 8;
var->green.offset = 8;
var->green.msb_right = 0;
var->blue.length = 8;
var->blue.offset = 0;
var->blue.msb_right = 0;
var->transp.length = 8;
var->transp.offset = 24;
var->transp.msb_right = 0;
break;
}
if (var->pixclock < 1000) {
htotal = var->xres + var->right_margin + var->hsync_len +
var->left_margin;
vtotal = var->yres + var->lower_margin + var->vsync_len +
var->upper_margin;
var->pixclock = (vtotal * htotal * 6UL) / 100UL;
var->pixclock = KHZ2PICOS(var->pixclock);
printf("pixclock set for 60Hz refresh = %u ps\n",
var->pixclock);
}
var->height = -1;
var->width = -1;
var->grayscale = 0;
return 0;
}
static int mxcfb_map_video_memory(struct fb_info *fbi)
{
if (fbi->fix.smem_len < fbi->var.yres_virtual * fbi->fix.line_length) {
fbi->fix.smem_len = fbi->var.yres_virtual *
fbi->fix.line_length;
}
fbi->screen_base = (char *)lcd_base;
fbi->fix.smem_start = (unsigned long)lcd_base;
if (fbi->screen_base == 0) {
puts("Unable to allocate framebuffer memory\n");
fbi->fix.smem_len = 0;
fbi->fix.smem_start = 0;
return -EBUSY;
}
debug("allocated fb @ paddr=0x%08X, size=%d.\n",
(uint32_t) fbi->fix.smem_start, fbi->fix.smem_len);
fbi->screen_size = fbi->fix.smem_len;
/* Clear the screen */
memset((char *)fbi->screen_base, 0, fbi->fix.smem_len);
return 0;
}
static int mxcfb_unmap_video_memory(struct fb_info *fbi)
{
fbi->screen_base = 0;
fbi->fix.smem_start = 0;
fbi->fix.smem_len = 0;
return 0;
}
/*
* Initializes the framebuffer information pointer. After allocating
* sufficient memory for the framebuffer structure, the fields are
* filled with custom information passed in from the configurable
* structures. This includes information such as bits per pixel,
* color maps, screen width/height and RGBA offsets.
*
* @return Framebuffer structure initialized with our information
*/
static struct fb_info *mxcfb_init_fbinfo(void)
{
#define BYTES_PER_LONG 4
#define PADDING (BYTES_PER_LONG - (sizeof(struct fb_info) % BYTES_PER_LONG))
struct fb_info *fbi;
struct mxcfb_info *mxcfbi;
char *p;
int size = sizeof(struct mxcfb_info) + PADDING +
sizeof(struct fb_info);
debug("%s: %d %d %d %d\n",
__func__,
PADDING,
size,
sizeof(struct mxcfb_info),
sizeof(struct fb_info));
/*
* Allocate sufficient memory for the fb structure
*/
p = malloc(size);
if (!p)
return NULL;
memset(p, 0, size);
fbi = (struct fb_info *)p;
fbi->par = p + sizeof(struct fb_info) + PADDING;
mxcfbi = (struct mxcfb_info *)fbi->par;
debug("Framebuffer structures at: fbi=0x%x mxcfbi=0x%x\n",
(unsigned int)fbi, (unsigned int)mxcfbi);
fbi->var.activate = FB_ACTIVATE_NOW;
fbi->flags = FBINFO_FLAG_DEFAULT;
fbi->pseudo_palette = mxcfbi->pseudo_palette;
return fbi;
}
/*
* Probe routine for the framebuffer driver. It is called during the
* driver binding process. The following functions are performed in
* this routine: Framebuffer initialization, Memory allocation and
* mapping, Framebuffer registration, IPU initialization.
*
* @return Appropriate error code to the kernel common code
*/
static int mxcfb_probe(u32 interface_pix_fmt, struct fb_videomode *mode)
{
struct fb_info *fbi;
struct mxcfb_info *mxcfbi;
int ret = 0;
/*
* Initialize FB structures
*/
fbi = mxcfb_init_fbinfo();
if (!fbi) {
ret = -ENOMEM;
goto err0;
}
mxcfbi = (struct mxcfb_info *)fbi->par;
if (!g_dp_in_use) {
mxcfbi->ipu_ch = MEM_BG_SYNC;
mxcfbi->blank = FB_BLANK_UNBLANK;
} else {
mxcfbi->ipu_ch = MEM_DC_SYNC;
mxcfbi->blank = FB_BLANK_POWERDOWN;
}
mxcfbi->ipu_di = 0;
ipu_disp_set_global_alpha(mxcfbi->ipu_ch, 1, 0x80);
ipu_disp_set_color_key(mxcfbi->ipu_ch, 0, 0);
strcpy(fbi->fix.id, "DISP3 BG");
g_dp_in_use = 1;
mxcfb_info[mxcfbi->ipu_di] = fbi;
/* Need dummy values until real panel is configured */
fbi->var.xres = 640;
fbi->var.yres = 480;
fbi->var.bits_per_pixel = 16;
mxcfbi->ipu_di_pix_fmt = interface_pix_fmt;
fb_videomode_to_var(&fbi->var, mode);
mxcfb_check_var(&fbi->var, fbi);
/* Default Y virtual size is 2x panel size */
fbi->var.yres_virtual = fbi->var.yres * 2;
mxcfb_set_fix(fbi);
/* alocate fb first */
if (mxcfb_map_video_memory(fbi) < 0)
return -ENOMEM;
mxcfb_set_par(fbi);
/* Setting panel_info for lcd */
panel_info.cmap = NULL;
panel_info.vl_col = fbi->var.xres;
panel_info.vl_row = fbi->var.yres;
panel_info.vl_bpix = LCD_BPP;
lcd_line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8;
debug("MXC IPUV3 configured\n"
"XRES = %d YRES = %d BitsXpixel = %d\n",
panel_info.vl_col,
panel_info.vl_row,
panel_info.vl_bpix);
ipu_dump_registers();
return 0;
err0:
return ret;
}
int overwrite_console(void)
{
/* Keep stdout / stderr on serial, our LCD is for splashscreen only */
return 1;
}
void lcd_ctrl_init(void *lcdbase)
{
u32 mem_len = panel_info.vl_col *
panel_info.vl_row *
NBITS(panel_info.vl_bpix) / 8;
/*
* We rely on lcdbase being a physical address, i.e., either MMU off,
* or 1-to-1 mapping. Might want to add some virt2phys here.
*/
if (!lcdbase)
return;
memset(lcdbase, 0, mem_len);
}
int mx51_fb_init(struct fb_videomode *mode)
{
int ret;
ret = ipu_probe();
if (ret)
puts("Error initializing IPU\n");
lcd_base += 56;
debug("Framebuffer at 0x%x\n", (unsigned int)lcd_base);
ret = mxcfb_probe(IPU_PIX_FMT_RGB666, mode);
return ret;
}

+ 68
- 0
drivers/video/mxcfb.h View File

@ -0,0 +1,68 @@
/*
* Porting to u-boot:
*
* (C) Copyright 2010
* Stefano Babic, DENX Software Engineering, sbabic@denx.de
*
* Linux IPU driver for MX51:
*
* (C) Copyright 2004-2009 Freescale Semiconductor, Inc.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#ifndef __ASM_ARCH_MXCFB_H__
#define __ASM_ARCH_MXCFB_H__
#define FB_SYNC_OE_LOW_ACT 0x80000000
#define FB_SYNC_CLK_LAT_FALL 0x40000000
#define FB_SYNC_DATA_INVERT 0x20000000
#define FB_SYNC_CLK_IDLE_EN 0x10000000
#define FB_SYNC_SHARP_MODE 0x08000000
#define FB_SYNC_SWAP_RGB 0x04000000
struct mxcfb_gbl_alpha {
int enable;
int alpha;
};
struct mxcfb_loc_alpha {
int enable;
int alpha_in_pixel;
unsigned long alpha_phy_addr0;
unsigned long alpha_phy_addr1;
};
struct mxcfb_color_key {
int enable;
__u32 color_key;
};
struct mxcfb_pos {
__u16 x;
__u16 y;
};
struct mxcfb_gamma {
int enable;
int constk[16];
int slopek[16];
};
#endif

+ 14
- 0
include/configs/vision2.h View File

@ -211,4 +211,18 @@
#define CONFIG_SYS_NO_FLASH
/*
* Framebuffer and LCD
*/
#define CONFIG_PREBOOT
#define CONFIG_LCD
#define CONFIG_VIDEO_MX5
#define CONFIG_SYS_CONSOLE_ENV_OVERWRITE
#define CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE
#define CONFIG_SYS_CONSOLE_IS_IN_ENV
#define LCD_BPP LCD_COLOR16
#define CONFIG_SPLASH_SCREEN
#define CONFIG_CMD_BMP
#define CONFIG_BMP_16BPP
#endif /* __CONFIG_H */

+ 616
- 0
include/linux/fb.h View File

@ -0,0 +1,616 @@
#ifndef _LINUX_FB_H
#define _LINUX_FB_H
#include <linux/types.h>
/* Definitions of frame buffers */
#define FB_MAX 32 /* sufficient for now */
#define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */
#define FB_VISUAL_MONO01 0 /* Monochr. 1=Black 0=White */
#define FB_VISUAL_MONO10 1 /* Monochr. 1=White 0=Black */
#define FB_VISUAL_TRUECOLOR 2 /* True color */
#define FB_VISUAL_PSEUDOCOLOR 3 /* Pseudo color (like atari) */
#define FB_VISUAL_DIRECTCOLOR 4 /* Direct color */
#define FB_VISUAL_STATIC_PSEUDOCOLOR 5 /* Pseudo color readonly */
#define FB_ACCEL_NONE 0 /* no hardware accelerator */
struct fb_fix_screeninfo {
char id[16]; /* identification string eg "TT Builtin" */
unsigned long smem_start; /* Start of frame buffer mem */
/* (physical address) */
__u32 smem_len; /* Length of frame buffer mem */
__u32 type; /* see FB_TYPE_* */
__u32 type_aux; /* Interleave for interleaved Planes */
__u32 visual; /* see FB_VISUAL_* */
__u16 xpanstep; /* zero if no hardware panning */
__u16 ypanstep; /* zero if no hardware panning */
__u16 ywrapstep; /* zero if no hardware ywrap */
__u32 line_length; /* length of a line in bytes */
unsigned long mmio_start; /* Start of Memory Mapped I/O */
/* (physical address) */
__u32 mmio_len; /* Length of Memory Mapped I/O */
__u32 accel; /* Indicate to driver which */
/* specific chip/card we have */
__u16 reserved[3]; /* Reserved for future compatibility */
};
/*
* Interpretation of offset for color fields: All offsets are from the right,
* inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you
* can use the offset as right argument to <<). A pixel afterwards is a bit
* stream and is written to video memory as that unmodified.
*
* For pseudocolor: offset and length should be the same for all color
* components. Offset specifies the position of the least significant bit
* of the pallette index in a pixel value. Length indicates the number
* of available palette entries (i.e. # of entries = 1 << length).
*/
struct fb_bitfield {
__u32 offset; /* beginning of bitfield */
__u32 length; /* length of bitfield */
__u32 msb_right;
};
#define FB_NONSTD_HAM 1 /* Hold-And-Modify (HAM) */
#define FB_NONSTD_REV_PIX_IN_B 2 /* order of pixels in each byte is reversed */
#define FB_ACTIVATE_NOW 0 /* set values immediately (or vbl)*/
#define FB_ACTIVATE_NXTOPEN 1 /* activate on next open */
#define FB_ACTIVATE_TEST 2 /* don't set, round up impossible */
#define FB_ACTIVATE_MASK 15
/* values */
#define FB_ACTIVATE_VBL 16 /* activate values on next vbl */
#define FB_CHANGE_CMAP_VBL 32 /* change colormap on vbl */
#define FB_ACTIVATE_ALL 64 /* change all VCs on this fb */
#define FB_ACTIVATE_FORCE 128 /* force apply even when no change*/
#define FB_ACTIVATE_INV_MODE 256 /* invalidate videomode */
#define FB_SYNC_HOR_HIGH_ACT 1 /* horizontal sync high active */
#define FB_SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */
#define FB_SYNC_EXT 4 /* external sync */
#define FB_SYNC_COMP_HIGH_ACT 8 /* composite sync high active */
#define FB_SYNC_BROADCAST 16 /* broadcast video timings */
/* vtotal = 144d/288n/576i => PAL */
/* vtotal = 121d/242n/484i => NTSC */
#define FB_SYNC_ON_GREEN 32 /* sync on green */
#define FB_VMODE_NONINTERLACED 0 /* non interlaced */
#define FB_VMODE_INTERLACED 1 /* interlaced */
#define FB_VMODE_DOUBLE 2 /* double scan */
#define FB_VMODE_ODD_FLD_FIRST 4 /* interlaced: top line first */
#define FB_VMODE_MASK 255
#define FB_VMODE_YWRAP 256 /* ywrap instead of panning */
#define FB_VMODE_SMOOTH_XPAN 512 /* smooth xpan possible (internally used) */
#define FB_VMODE_CONUPDATE 512 /* don't update x/yoffset */
/*