From 8c6b25046d506d8bbde10cb89f63247f9e78b48c Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Mon, 22 Aug 2011 10:54:02 -0500 Subject: [PATCH 1/6] video: update the Freescale DIU driver to use linux/fb.h Update the Freescale DIU video driver (fsl_diu_fb.c) to use linux/fb.h. Some data structures from this header file were just copied into fsl_diu_fb.c. Signed-off-by: Timur Tabi --- drivers/video/fsl_diu_fb.c | 54 ++++---------------------------------- 1 file changed, 5 insertions(+), 49 deletions(-) diff --git a/drivers/video/fsl_diu_fb.c b/drivers/video/fsl_diu_fb.c index e1d6c2614..cb439044f 100644 --- a/drivers/video/fsl_diu_fb.c +++ b/drivers/video/fsl_diu_fb.c @@ -31,52 +31,8 @@ #include "videomodes.h" #include #include - -struct fb_var_screeninfo { - unsigned int xres; /* visible resolution */ - unsigned int yres; - - unsigned int bits_per_pixel; /* guess what */ - - /* Timing: All values in pixclocks, except pixclock (of course) */ - unsigned int pixclock; /* pixel clock in ps (pico seconds) */ - unsigned int left_margin; /* time from sync to picture */ - unsigned int right_margin; /* time from picture to sync */ - unsigned int upper_margin; /* time from sync to picture */ - unsigned int lower_margin; - unsigned int hsync_len; /* length of horizontal sync */ - unsigned int vsync_len; /* length of vertical sync */ - unsigned int sync; /* see FB_SYNC_* */ - unsigned int vmode; /* see FB_VMODE_* */ - unsigned int rotate; /* angle we rotate counter clockwise */ -}; - -struct fb_info { - struct fb_var_screeninfo var; /* Current var */ - unsigned int smem_len; /* Length of frame buffer mem */ - unsigned int type; /* see FB_TYPE_* */ - unsigned int line_length; /* length of a line in bytes */ - - void *screen_base; - unsigned long screen_size; -}; - -struct fb_videomode { - const char *name; /* optional */ - unsigned int refresh; /* optional */ - unsigned int xres; - unsigned int yres; - unsigned int pixclock; - unsigned int left_margin; - unsigned int right_margin; - unsigned int upper_margin; - unsigned int lower_margin; - unsigned int hsync_len; - unsigned int vsync_len; - unsigned int sync; - unsigned int vmode; - unsigned int flag; -}; +#include +#include /* This setting is used for the ifm pdm360ng with PRIMEVIEW PM070WL3 */ static struct fb_videomode fsl_diu_mode_800_480 = { @@ -248,7 +204,7 @@ static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align) * point to the framebuffer memory. Memory is aligned as needed. */ static struct diu_ad *allocate_fb(unsigned int xres, unsigned int yres, - unsigned int depth, void **fb) + unsigned int depth, char **fb) { unsigned long size = xres * yres * depth; struct diu_addr addr; @@ -327,10 +283,10 @@ int fsl_diu_init(u16 xres, u16 yres, u32 pixel_format, int gamma_fix) info.var.vsync_len = fsl_diu_mode_db->vsync_len; info.var.sync = fsl_diu_mode_db->sync; info.var.vmode = fsl_diu_mode_db->vmode; - info.line_length = info.var.xres * info.var.bits_per_pixel / 8; + info.fix.line_length = info.var.xres * info.var.bits_per_pixel / 8; /* Memory allocation for framebuffer */ - info.smem_len = + info.screen_size = info.var.xres * info.var.yres * (info.var.bits_per_pixel / 8); ad = allocate_fb(info.var.xres, info.var.yres, info.var.bits_per_pixel / 8, &info.screen_base); From e9934f0b6032d5f4304fa17241c870b95e7e60f8 Mon Sep 17 00:00:00 2001 From: Stefano Babic Date: Wed, 28 Sep 2011 11:21:15 +0200 Subject: [PATCH 2/6] VIDEO: MX5: Switch MX5 to CONFIG_VIDEO The framebuffer driver for MX5 is based on CONFIG_LCD. In the current implementation, there is a serious bug because the required memory is allocated before relocation, but the driver knows only later which is the resolution of the display. The patch switches the driver to CONFIG_VIDEO and the memory is allocated by the driver itself. We also need to switch the vision2 board code and config file in the same commit so that this commit will be bisectable. Signed-off-by: Stefano Babic CC: Anatolij Gustschin Tested-by: Stefano Babic Signed-off-by: Anatolij Gustschin --- board/ttcontrol/vision2/vision2.c | 36 ++++++---- drivers/video/mxc_ipuv3_fb.c | 112 ++++++++++-------------------- include/configs/vision2.h | 11 ++- 3 files changed, 63 insertions(+), 96 deletions(-) diff --git a/board/ttcontrol/vision2/vision2.c b/board/ttcontrol/vision2/vision2.c index ebca7b6f3..ca0c100d1 100644 --- a/board/ttcontrol/vision2/vision2.c +++ b/board/ttcontrol/vision2/vision2.c @@ -600,6 +600,21 @@ int board_mmc_init(bd_t *bis) } #endif +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); + + gpio_set_value(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_early_init_f(void) { @@ -636,26 +651,15 @@ static void backlight(int on) } } -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); - - gpio_set_value(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) { /* address of boot parameters */ gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100; + lcd_enable(); + + backlight(1); + return 0; } @@ -676,6 +680,8 @@ int board_late_init(void) udelay(2000); #endif + setenv("stdout", "serial"); + return 0; } diff --git a/drivers/video/mxc_ipuv3_fb.c b/drivers/video/mxc_ipuv3_fb.c index a66981c27..eafacef53 100644 --- a/drivers/video/mxc_ipuv3_fb.c +++ b/drivers/video/mxc_ipuv3_fb.c @@ -27,7 +27,6 @@ * MA 02111-1307 USA */ -/* #define DEBUG */ #include #include #include @@ -35,43 +34,17 @@ #include #include #include -#include +#include #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) -{ -} +/* graphics setup */ +static GraphicDevice panel; +struct fb_videomode *gmode; void fb_videomode_to_var(struct fb_var_screeninfo *var, const struct fb_videomode *mode) @@ -440,8 +413,8 @@ static int mxcfb_map_video_memory(struct fb_info *fbi) fbi->fix.line_length; } - fbi->screen_base = (char *)lcd_base; - fbi->fix.smem_start = (unsigned long)lcd_base; + fbi->screen_base = (char *)malloc(fbi->fix.smem_len); + fbi->fix.smem_start = (unsigned long)fbi->screen_base; if (fbi->screen_base == 0) { puts("Unable to allocate framebuffer memory\n"); fbi->fix.smem_len = 0; @@ -561,12 +534,12 @@ static int mxcfb_probe(u32 interface_pix_fmt, struct fb_videomode *mode) 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); + fbi->var.bits_per_pixel = 16; + fbi->fix.line_length = fbi->var.xres * (fbi->var.bits_per_pixel / 8); + fbi->fix.smem_len = fbi->var.yres_virtual * fbi->fix.line_length; mxcfb_check_var(&fbi->var, fbi); @@ -581,19 +554,16 @@ static int mxcfb_probe(u32 interface_pix_fmt, struct fb_videomode *mode) 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; + panel.winSizeX = mode->xres; + panel.winSizeY = mode->yres; + panel.plnSizeX = mode->xres; + panel.plnSizeY = mode->yres; - lcd_line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8; + panel.frameAdrs = (u32)fbi->screen_base; + panel.memSize = fbi->screen_size; - debug("MXC IPUV3 configured\n" - "XRES = %d YRES = %d BitsXpixel = %d\n", - panel_info.vl_col, - panel_info.vl_row, - panel_info.vl_bpix); + panel.gdfBytesPP = 2; + panel.gdfIndex = GDF_16BIT_565RGB; ipu_dump_registers(); @@ -603,29 +573,7 @@ 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) +void *video_hw_init(void) { int ret; @@ -633,10 +581,24 @@ int mx51_fb_init(struct fb_videomode *mode) if (ret) puts("Error initializing IPU\n"); - lcd_base += 56; + ret = mxcfb_probe(IPU_PIX_FMT_RGB666, gmode); + debug("Framebuffer at 0x%x\n", (unsigned int)panel.frameAdrs); - debug("Framebuffer at 0x%x\n", (unsigned int)lcd_base); - ret = mxcfb_probe(IPU_PIX_FMT_RGB666, mode); - - return ret; + return (void *)&panel; +} + +void video_set_lut(unsigned int index, /* color number */ + unsigned char r, /* red */ + unsigned char g, /* green */ + unsigned char b /* blue */ + ) +{ + return; +} + +int mx51_fb_init(struct fb_videomode *mode) +{ + gmode = mode; + + return 0; } diff --git a/include/configs/vision2.h b/include/configs/vision2.h index 540dfa9f6..3b42afc92 100644 --- a/include/configs/vision2.h +++ b/include/configs/vision2.h @@ -46,7 +46,7 @@ /* * Size of malloc() pool */ -#define CONFIG_SYS_MALLOC_LEN (2048 * 1024) +#define CONFIG_SYS_MALLOC_LEN (10 * 1024 * 1024) /* * Hardware drivers @@ -207,12 +207,11 @@ * Framebuffer and LCD */ #define CONFIG_PREBOOT -#define CONFIG_LCD +#define CONFIG_VIDEO #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_CFB_CONSOLE +#define CONFIG_VGA_AS_SINGLE_DEVICE +#define CONFIG_VIDEO_BMP_RLE8 #define CONFIG_SPLASH_SCREEN #define CONFIG_CMD_BMP #define CONFIG_BMP_16BPP From 92a98a4a399801ccebeece3e2f3ab83ee4efe9c7 Mon Sep 17 00:00:00 2001 From: Stefano Babic Date: Wed, 28 Sep 2011 11:21:16 +0200 Subject: [PATCH 3/6] VIDEO: MX5: export pix format Pixel format defines must be available for boards to set up the right display. Move them and export in a new file. Signed-off-by: Stefano Babic CC: Anatolij Gustschin CC: Marek Vasut Tested-by: Stefano Babic Signed-off-by: Anatolij Gustschin --- drivers/video/ipu.h | 46 +-------------------------- include/ipu_pixfmt.h | 76 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 45 deletions(-) create mode 100644 include/ipu_pixfmt.h diff --git a/drivers/video/ipu.h b/drivers/video/ipu.h index d8bc287d8..99a2491cf 100644 --- a/drivers/video/ipu.h +++ b/drivers/video/ipu.h @@ -31,6 +31,7 @@ #define __ASM_ARCH_IPU_H__ #include +#include #define IDMA_CHAN_INVALID 0xFF #define HIGH_RESOLUTION_WIDTH 1024 @@ -89,51 +90,6 @@ typedef enum { 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 diff --git a/include/ipu_pixfmt.h b/include/ipu_pixfmt.h new file mode 100644 index 000000000..0497bff2d --- /dev/null +++ b/include/ipu_pixfmt.h @@ -0,0 +1,76 @@ +/* + * (C) Copyright 2011 + * Stefano Babic, DENX Software Engineering, sbabic@denx.de + * + * Based on Linux IPU driver for MX51 (ipu.h): + * + * (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 __IPU_PIXFMT_H__ +#define __IPU_PIXFMT_H__ + +/* 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 */ + +#endif From 02ae1a1860af28164b41e0b29e53e1a1ee913225 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 6 Oct 2011 00:25:03 +0200 Subject: [PATCH 4/6] MX5: Make IPU display output and pixel format configurable Signed-off-by: Marek Vasut Signed-off-by: Stefano Babic Tested-by: Stefano Babic Signed-off-by: Anatolij Gustschin --- board/ttcontrol/vision2/vision2.c | 6 +++--- drivers/video/mxc_ipuv3_fb.c | 15 ++++++++++----- include/ipu_pixfmt.h | 5 +++++ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/board/ttcontrol/vision2/vision2.c b/board/ttcontrol/vision2/vision2.c index ca0c100d1..e496f6431 100644 --- a/board/ttcontrol/vision2/vision2.c +++ b/board/ttcontrol/vision2/vision2.c @@ -39,12 +39,12 @@ #include #include +#include + DECLARE_GLOBAL_DATA_PTR; static u32 system_rev; -extern int mx51_fb_init(struct fb_videomode *mode); - static struct fb_videomode nec_nl6448bc26_09c = { "NEC_NL6448BC26-09C", 60, /* Refresh */ @@ -610,7 +610,7 @@ void lcd_enable(void) gpio_set_value(2, 1); mxc_request_iomux(MX51_PIN_GPIO1_2, IOMUX_CONFIG_ALT0); - ret = mx51_fb_init(&nec_nl6448bc26_09c); + ret = mx51_fb_init(&nec_nl6448bc26_09c, 0, IPU_PIX_FMT_RGB666); if (ret) puts("LCD cannot be configured\n"); } diff --git a/drivers/video/mxc_ipuv3_fb.c b/drivers/video/mxc_ipuv3_fb.c index eafacef53..1bee54c1a 100644 --- a/drivers/video/mxc_ipuv3_fb.c +++ b/drivers/video/mxc_ipuv3_fb.c @@ -44,7 +44,9 @@ static int mxcfb_unmap_video_memory(struct fb_info *fbi); /* graphics setup */ static GraphicDevice panel; -struct fb_videomode *gmode; +static struct fb_videomode *gmode; +static uint8_t gdisp; +static uint32_t gpixfmt; void fb_videomode_to_var(struct fb_var_screeninfo *var, const struct fb_videomode *mode) @@ -499,7 +501,8 @@ static struct fb_info *mxcfb_init_fbinfo(void) * * @return Appropriate error code to the kernel common code */ -static int mxcfb_probe(u32 interface_pix_fmt, struct fb_videomode *mode) +static int mxcfb_probe(u32 interface_pix_fmt, uint8_t disp, + struct fb_videomode *mode) { struct fb_info *fbi; struct mxcfb_info *mxcfbi; @@ -523,7 +526,7 @@ static int mxcfb_probe(u32 interface_pix_fmt, struct fb_videomode *mode) mxcfbi->blank = FB_BLANK_POWERDOWN; } - mxcfbi->ipu_di = 0; + mxcfbi->ipu_di = disp; ipu_disp_set_global_alpha(mxcfbi->ipu_ch, 1, 0x80); ipu_disp_set_color_key(mxcfbi->ipu_ch, 0, 0); @@ -581,7 +584,7 @@ void *video_hw_init(void) if (ret) puts("Error initializing IPU\n"); - ret = mxcfb_probe(IPU_PIX_FMT_RGB666, gmode); + ret = mxcfb_probe(gpixfmt, gdisp, gmode); debug("Framebuffer at 0x%x\n", (unsigned int)panel.frameAdrs); return (void *)&panel; @@ -596,9 +599,11 @@ void video_set_lut(unsigned int index, /* color number */ return; } -int mx51_fb_init(struct fb_videomode *mode) +int mx51_fb_init(struct fb_videomode *mode, uint8_t disp, uint32_t pixfmt) { gmode = mode; + gdisp = disp; + gpixfmt = pixfmt; return 0; } diff --git a/include/ipu_pixfmt.h b/include/ipu_pixfmt.h index 0497bff2d..656f60546 100644 --- a/include/ipu_pixfmt.h +++ b/include/ipu_pixfmt.h @@ -28,6 +28,9 @@ #ifndef __IPU_PIXFMT_H__ #define __IPU_PIXFMT_H__ +#include +#include + /* IPU Pixel format definitions */ #define fourcc(a, b, c, d)\ (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24)) @@ -73,4 +76,6 @@ #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 */ +int mx51_fb_init(struct fb_videomode *mode, uint8_t disp, uint32_t pixfmt); + #endif From f00291985b231c5c1f05fc6d09488001d22ae7e3 Mon Sep 17 00:00:00 2001 From: Helmut Raiger Date: Wed, 12 Oct 2011 23:08:30 +0200 Subject: [PATCH 5/6] mx31: make HSP clock for mx3fb driver available This additionally updates mx31/generic.c by - replacing __REG() macro accesses with readl() and writel() - providing macros for PDR0 and PLL bit accesses Signed-off-by: Helmut Raiger Acked-by: Marek Vasut Cc: Stefano Babic Acked-by: Stefano Babic Signed-off-by: Anatolij Gustschin --- arch/arm/cpu/arm1136/mx31/generic.c | 40 +++++++++++++++-------- arch/arm/include/asm/arch-mx31/clock.h | 1 + arch/arm/include/asm/arch-mx31/imx-regs.h | 14 ++++++++ 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/arch/arm/cpu/arm1136/mx31/generic.c b/arch/arm/cpu/arm1136/mx31/generic.c index c6def5df9..5524b2327 100644 --- a/arch/arm/cpu/arm1136/mx31/generic.c +++ b/arch/arm/cpu/arm1136/mx31/generic.c @@ -28,10 +28,10 @@ static u32 mx31_decode_pll(u32 reg, u32 infreq) { - u32 mfi = (reg >> 10) & 0xf; - u32 mfn = reg & 0x3ff; - u32 mfd = (reg >> 16) & 0x3ff; - u32 pd = (reg >> 26) & 0xf; + u32 mfi = GET_PLL_MFI(reg); + u32 mfn = GET_PLL_MFN(reg); + u32 mfd = GET_PLL_MFD(reg); + u32 pd = GET_PLL_PD(reg); mfi = mfi <= 5 ? 5 : mfi; mfd += 1; @@ -45,12 +45,12 @@ static u32 mx31_get_mpl_dpdgck_clk(void) { u32 infreq; - if ((__REG(CCM_CCMR) & CCMR_PRCS_MASK) == CCMR_FPM) + if ((readl(CCM_CCMR) & CCMR_PRCS_MASK) == CCMR_FPM) infreq = CONFIG_MX31_CLK32 * 1024; else infreq = CONFIG_MX31_HCLK_FREQ; - return mx31_decode_pll(__REG(CCM_MPCTL), infreq); + return mx31_decode_pll(readl(CCM_MPCTL), infreq); } static u32 mx31_get_mcu_main_clk(void) @@ -64,10 +64,21 @@ static u32 mx31_get_mcu_main_clk(void) static u32 mx31_get_ipg_clk(void) { u32 freq = mx31_get_mcu_main_clk(); - u32 pdr0 = __REG(CCM_PDR0); + u32 pdr0 = readl(CCM_PDR0); - freq /= ((pdr0 >> 3) & 0x7) + 1; - freq /= ((pdr0 >> 6) & 0x3) + 1; + freq /= GET_PDR0_MAX_PODF(pdr0) + 1; + freq /= GET_PDR0_IPG_PODF(pdr0) + 1; + + return freq; +} + +/* hsp is the clock for the ipu */ +static u32 mx31_get_hsp_clk(void) +{ + u32 freq = mx31_get_mcu_main_clk(); + u32 pdr0 = readl(CCM_PDR0); + + freq /= GET_PDR0_HSP_PODF(pdr0) + 1; return freq; } @@ -77,6 +88,7 @@ void mx31_dump_clocks(void) u32 cpufreq = mx31_get_mcu_main_clk(); printf("mx31 cpu clock: %dMHz\n",cpufreq / 1000000); printf("ipg clock : %dHz\n", mx31_get_ipg_clk()); + printf("hsp clock : %dHz\n", mx31_get_hsp_clk()); } unsigned int mxc_get_clock(enum mxc_clock clk) @@ -89,6 +101,8 @@ unsigned int mxc_get_clock(enum mxc_clock clk) case MXC_CSPI_CLK: case MXC_UART_CLK: return mx31_get_ipg_clk(); + case MXC_IPU_CLK: + return mx31_get_hsp_clk(); } return -1; } @@ -105,10 +119,10 @@ void mx31_gpio_mux(unsigned long mode) reg = IOMUXC_BASE + (mode & 0x1fc); shift = (~mode & 0x3) * 8; - tmp = __REG(reg); + tmp = readl(reg); tmp &= ~(0xff << shift); tmp |= ((mode >> IOMUX_MODE_POS) & 0xff) << shift; - __REG(reg) = tmp; + writel(tmp, reg); } void mx31_set_pad(enum iomux_pins pin, u32 config) @@ -119,10 +133,10 @@ void mx31_set_pad(enum iomux_pins pin, u32 config) reg = (IOMUXC_BASE + 0x154) + (pin + 2) / 3 * 4; field = (pin + 2) % 3; - l = __REG(reg); + l = readl(reg); l &= ~(0x1ff << (field * 10)); l |= config << (field * 10); - __REG(reg) = l; + writel(l, reg); } diff --git a/arch/arm/include/asm/arch-mx31/clock.h b/arch/arm/include/asm/arch-mx31/clock.h index cc99a75e9..2e3bce2c3 100644 --- a/arch/arm/include/asm/arch-mx31/clock.h +++ b/arch/arm/include/asm/arch-mx31/clock.h @@ -30,6 +30,7 @@ enum mxc_clock { MXC_IPG_PERCLK, MXC_CSPI_CLK, MXC_UART_CLK, + MXC_IPU_CLK }; unsigned int mxc_get_clock(enum mxc_clock clk); diff --git a/arch/arm/include/asm/arch-mx31/imx-regs.h b/arch/arm/include/asm/arch-mx31/imx-regs.h index 0dcd9fe7e..f263e6bcf 100644 --- a/arch/arm/include/asm/arch-mx31/imx-regs.h +++ b/arch/arm/include/asm/arch-mx31/imx-regs.h @@ -513,6 +513,20 @@ enum iomux_pins { #define PLL_MFI(x) (((x) & 0xf) << 10) #define PLL_MFN(x) (((x) & 0x3ff) << 0) +#define GET_PDR0_CSI_PODF(x) (((x) >> 23) & 0x1ff) +#define GET_PDR0_PER_PODF(x) (((x) >> 16) & 0x1f) +#define GET_PDR0_HSP_PODF(x) (((x) >> 11) & 0x7) +#define GET_PDR0_NFC_PODF(x) (((x) >> 8) & 0x7) +#define GET_PDR0_IPG_PODF(x) (((x) >> 6) & 0x3) +#define GET_PDR0_MAX_PODF(x) (((x) >> 3) & 0x7) +#define GET_PDR0_MCU_PODF(x) ((x) & 0x7) + +#define GET_PLL_PD(x) (((x) >> 26) & 0xf) +#define GET_PLL_MFD(x) (((x) >> 16) & 0x3ff) +#define GET_PLL_MFI(x) (((x) >> 10) & 0xf) +#define GET_PLL_MFN(x) (((x) >> 0) & 0x3ff) + + #define WEIM_ESDCTL0 0xB8001000 #define WEIM_ESDCFG0 0xB8001004 #define WEIM_ESDCTL1 0xB8001008 From 62a22dca32b988cce5d1908e8ac9fadb139bb3e8 Mon Sep 17 00:00:00 2001 From: Helmut Raiger Date: Wed, 12 Oct 2011 23:16:29 +0000 Subject: [PATCH 6/6] video: Moving mx3fb.c to CONFIG_VIDEO mx3fb.c was based on CONFIG_LCD and is moved by this patch to CONFIG_VIDEO, which has greater freedom in selecting videomodes even at runtime. This renders the accumulating list of display defines (CONFIG_DISPLAY_VBEST..., CONFIG_DISPLAY_C057...) obsolete as these may be setup through env variables: uboot> setenv mydisplay 'video=ctfb:x:240,y:320,depth:16,mode:0,pclk:185925, le:9,ri:17,up:7,lo:10,hs:1,vs:1,sync:100663296,vmode:0' uboot> setenv videomode ${mydisplay} This commit also fixes the board config files for qong and imx31_phycore boards as needed. The videomode settings of previously supported displays are added to CONFIG_EXTRA_ENV_SETTINGS now. CONFIG_SYS_MALLOC_LEN for imx31_phycore board is increased to make the frame buffer allocation working with the changed driver. Signed-off-by: Helmut Raiger Signed-off-by: Anatolij Gustschin Cc: Stefano Babic --- drivers/video/Makefile | 2 +- drivers/video/cfb_console.c | 7 + drivers/video/mx3fb.c | 463 +++++++++++++++++++------------- include/configs/imx31_phycore.h | 24 +- include/configs/qong.h | 14 +- 5 files changed, 299 insertions(+), 211 deletions(-) diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 3790f91e7..ecc1896d5 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -35,7 +35,7 @@ COBJS-$(CONFIG_VIDEO_AMBA) += amba.o 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_MX3) += mx3fb.o videomodes.o COBJS-$(CONFIG_VIDEO_MX5) += mxc_ipuv3_fb.o ipu_common.o ipu_disp.o COBJS-$(CONFIG_VIDEO_OMAP3) += omap3_dss.o videomodes.o COBJS-$(CONFIG_VIDEO_SED13806) += sed13806.o diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index 3a93b64da..4e653b827 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -160,6 +160,13 @@ #endif #endif +/* + * Defines for the i.MX31 driver (mx3fb.c) + */ +#ifdef CONFIG_VIDEO_MX3 +#define VIDEO_FB_16BPP_WORD_SWAP +#endif + /* * Include video_fb.h after definitions of VIDEO_HW_RECTFILL etc. */ diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index 0c925a03f..f30deb392 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c @@ -1,6 +1,8 @@ /* * Copyright (C) 2009 * Guennadi Liakhovetski, DENX Software Engineering, + * Copyright (C) 2011 + * HALE electronic GmbH, * * See file CREDITS for list of people who contributed to this * project. @@ -21,100 +23,20 @@ * MA 02111-1307 USA */ #include -#include -#include +#include +#include + #include +#include #include +#include -DECLARE_GLOBAL_DATA_PTR; +#include "videomodes.h" -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; - -void lcd_initcolregs(void) -{ -} - -void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue) -{ -} - -void lcd_disable(void) -{ -} - -void lcd_panel_disable(void) -{ -} - -#define msleep(a) udelay(a * 1000) - -#if defined(CONFIG_DISPLAY_VBEST_VGG322403) -#define XRES 320 -#define YRES 240 -#define PANEL_TYPE IPU_PANEL_TFT -#define PIXEL_CLK 156000 -#define PIXEL_FMT IPU_PIX_FMT_RGB666 -#define H_START_WIDTH 20 /* left_margin */ -#define H_SYNC_WIDTH 30 /* hsync_len */ -#define H_END_WIDTH (38 + 30) /* right_margin + hsync_len */ -#define V_START_WIDTH 7 /* upper_margin */ -#define V_SYNC_WIDTH 3 /* vsync_len */ -#define V_END_WIDTH (26 + 3) /* lower_margin + vsync_len */ -#define SIG_POL (DI_D3_DRDY_SHARP_POL | DI_D3_CLK_POL) +/* this might need panel specific set-up as-well */ #define IF_CONF 0 -#define IF_CLK_DIV 0x175 -#elif defined(CONFIG_DISPLAY_COM57H5M10XRC) -#define XRES 640 -#define YRES 480 -#define PANEL_TYPE IPU_PANEL_TFT -#define PIXEL_CLK 40000 -#define PIXEL_FMT IPU_PIX_FMT_RGB666 -#define H_START_WIDTH 120 /* left_margin */ -#define H_SYNC_WIDTH 30 /* hsync_len */ -#define H_END_WIDTH (10 + 30) /* right_margin + hsync_len */ -#define V_START_WIDTH 35 /* upper_margin */ -#define V_SYNC_WIDTH 3 /* vsync_len */ -#define V_END_WIDTH (7 + 3) /* lower_margin + vsync_len */ -#define SIG_POL (DI_D3_DRDY_SHARP_POL | DI_D3_CLK_POL) -#define IF_CONF 0 -#define IF_CLK_DIV 0x55 -#else -#define XRES 240 -#define YRES 320 -#define PANEL_TYPE IPU_PANEL_TFT -#define PIXEL_CLK 185925 -#define PIXEL_FMT IPU_PIX_FMT_RGB666 -#define H_START_WIDTH 9 /* left_margin */ -#define H_SYNC_WIDTH 1 /* hsync_len */ -#define H_END_WIDTH (16 + 1) /* right_margin + hsync_len */ -#define V_START_WIDTH 7 /* upper_margin */ -#define V_SYNC_WIDTH 1 /* vsync_len */ -#define V_END_WIDTH (9 + 1) /* lower_margin + vsync_len */ -#define SIG_POL (DI_D3_DRDY_SHARP_POL | DI_D3_CLK_POL) -#define IF_CONF 0 -#define IF_CLK_DIV 0x175 -#endif -#define LCD_COLOR_IPU LCD_COLOR16 - -static ushort colormap[256]; - -vidinfo_t panel_info = { - .vl_col = XRES, - .vl_row = YRES, - .vl_bpix = LCD_COLOR_IPU, - .cmap = colormap, -}; - -#define BIT_PER_PIXEL NBITS(LCD_COLOR_IPU) +/* -------------- controller specific stuff -------------- */ /* IPU DMA Controller channel definitions. */ enum ipu_channel { @@ -438,89 +360,134 @@ union chan_param_mem { struct chan_param_mem_interleaved ip; }; -static inline u32 reg_read(unsigned long reg) -{ - return __REG(reg); -} +DECLARE_GLOBAL_DATA_PTR; -static inline void reg_write(u32 value, unsigned long reg) -{ - __REG(reg) = value; -} +/* graphics setup */ +static GraphicDevice panel; +static struct ctfb_res_modes *mode; +static struct ctfb_res_modes var_mode; /* * sdc_init_panel() - initialize a synchronous LCD panel. * @width: width of panel in pixels. * @height: height of panel in pixels. - * @pixel_fmt: pixel format of buffer as FOURCC ASCII code. + * @di_setup: pixel format of the frame buffer + * @di_panel: either SHARP or normal TFT * @return: 0 on success or negative error code on failure. */ -static int sdc_init_panel(u16 width, u16 height, enum pixel_fmt pixel_fmt) +static int sdc_init_panel(u16 width, u16 height, + enum pixel_fmt di_setup, enum ipu_panel di_panel) { - u32 reg; + u32 reg, div; uint32_t old_conf; + int clock; + + debug("%s(width=%d, height=%d)\n", __func__, width, height); + + /* Init clocking, the IPU receives its clock from the hsp divder */ + clock = mxc_get_clock(MXC_IPU_CLK); + if (clock < 0) + return -EACCES; /* Init panel size and blanking periods */ - reg = ((H_SYNC_WIDTH - 1) << 26) | - ((u32)(width + H_START_WIDTH + H_END_WIDTH - 1) << 16); - reg_write(reg, SDC_HOR_CONF); + reg = width + mode->left_margin + mode->right_margin - 1; + if (reg > 1023) { + printf("mx3fb: Display width too large, coerced to 1023!"); + reg = 1023; + } + reg = ((mode->hsync_len - 1) << 26) | (reg << 16); + writel(reg, SDC_HOR_CONF); - reg = ((V_SYNC_WIDTH - 1) << 26) | SDC_V_SYNC_WIDTH_L | - ((u32)(height + V_START_WIDTH + V_END_WIDTH - 1) << 16); - reg_write(reg, SDC_VER_CONF); + reg = height + mode->upper_margin + mode->lower_margin - 1; + if (reg > 1023) { + printf("mx3fb: Display height too large, coerced to 1023!"); + reg = 1023; + } + reg = ((mode->vsync_len - 1) << 26) | SDC_V_SYNC_WIDTH_L | (reg << 16); + writel(reg, SDC_VER_CONF); - switch (PANEL_TYPE) { + switch (di_panel) { case IPU_PANEL_SHARP_TFT: - reg_write(0x00FD0102L, SDC_SHARP_CONF_1); - reg_write(0x00F500F4L, SDC_SHARP_CONF_2); - reg_write(SDC_COM_SHARP | SDC_COM_TFT_COLOR, SDC_COM_CONF); + writel(0x00FD0102L, SDC_SHARP_CONF_1); + writel(0x00F500F4L, SDC_SHARP_CONF_2); + writel(SDC_COM_SHARP | SDC_COM_TFT_COLOR, SDC_COM_CONF); + /* TODO: probably IF_CONF must be adapted (see below)! */ break; case IPU_PANEL_TFT: - reg_write(SDC_COM_TFT_COLOR, SDC_COM_CONF); + writel(SDC_COM_TFT_COLOR, SDC_COM_CONF); break; default: return -EINVAL; } - /* Init clocking */ - /* - * Calculate divider: fractional part is 4 bits so simply multiple by - * 2^4 to get fractional part, as long as we stay under ~250MHz and on - * i.MX31 it (HSP_CLK) is <= 178MHz. Currently 128.267MHz + * Calculate divider: The fractional part is 4 bits so simply + * multiple by 2^4 to get it. + * + * Opposed to the kernel driver mode->pixclock is the time of one + * pixel in pico seconds, so: + * pixel_clk = 1e12 / mode->pixclock + * div = ipu_clk * 16 / pixel_clk + * leads to: + * div = ipu_clk * 16 / (1e12 / mode->pixclock) + * or: + * div = ipu_clk * 16 * mode->pixclock / 1e12 + * + * To avoid integer overflows this is split into 2 shifts and + * one divide with sufficient accuracy: + * 16*1024*128*476837 = 0.9999996682e12 */ + div = ((clock/1024) * (mode->pixclock/128)) / 476837; + debug("hsp_clk is %d, div=%d\n", clock, div); + /* coerce to not less than 4.0, not more than 255.9375 */ + if (div < 0x40) + div = 0x40; + else if (div > 0xFFF) + div = 0xFFF; + /* DISP3_IF_CLK_DOWN_WR is half the divider value and 2 less + * fraction bits. Subtract 1 extra from DISP3_IF_CLK_DOWN_WR + * based on timing debug DISP3_IF_CLK_UP_WR is 0 + */ + writel((((div / 8) - 1) << 22) | div, DI_DISP3_TIME_CONF); - reg_write((((IF_CLK_DIV / 8) - 1) << 22) | - IF_CLK_DIV, DI_DISP3_TIME_CONF); + /* DI settings for display 3: clock idle (bit 26) during vsync */ + old_conf = readl(DI_DISP_IF_CONF) & 0x78FFFFFF; + writel(old_conf | IF_CONF, DI_DISP_IF_CONF); - /* DI settings */ - old_conf = reg_read(DI_DISP_IF_CONF) & 0x78FFFFFF; - reg_write(old_conf | IF_CONF, DI_DISP_IF_CONF); + /* only set display 3 polarity bits */ + old_conf = readl(DI_DISP_SIG_POL) & 0xE0FFFFFF; + writel(old_conf | mode->sync, DI_DISP_SIG_POL); - old_conf = reg_read(DI_DISP_SIG_POL) & 0xE0FFFFFF; - reg_write(old_conf | SIG_POL, DI_DISP_SIG_POL); + writel(fmt_cfg[di_setup].b0, DI_DISP3_B0_MAP); + writel(fmt_cfg[di_setup].b1, DI_DISP3_B1_MAP); + writel(fmt_cfg[di_setup].b2, DI_DISP3_B2_MAP); + writel(readl(DI_DISP_ACC_CC) | + ((fmt_cfg[di_setup].acc - 1) << 12), DI_DISP_ACC_CC); - reg_write(fmt_cfg[pixel_fmt].b0, DI_DISP3_B0_MAP); - reg_write(fmt_cfg[pixel_fmt].b1, DI_DISP3_B1_MAP); - reg_write(fmt_cfg[pixel_fmt].b2, DI_DISP3_B2_MAP); - reg_write(reg_read(DI_DISP_ACC_CC) | - ((fmt_cfg[pixel_fmt].acc - 1) << 12), DI_DISP_ACC_CC); + debug("DI_DISP_IF_CONF = 0x%08X\n", readl(DI_DISP_IF_CONF)); + debug("DI_DISP_SIG_POL = 0x%08X\n", readl(DI_DISP_SIG_POL)); + debug("DI_DISP3_TIME_CONF = 0x%08X\n", readl(DI_DISP3_TIME_CONF)); + debug("SDC_HOR_CONF = 0x%08X\n", readl(SDC_HOR_CONF)); + debug("SDC_VER_CONF = 0x%08X\n", readl(SDC_VER_CONF)); return 0; } static void ipu_ch_param_set_size(union chan_param_mem *params, - uint32_t pixel_fmt, uint16_t width, + uint pixelfmt, uint16_t width, uint16_t height, uint16_t stride) { + debug("%s(pixelfmt=%d, width=%d, height=%d, stride=%d)\n", + __func__, pixelfmt, width, height, stride); + params->pp.fw = width - 1; params->pp.fh_l = height - 1; params->pp.fh_h = (height - 1) >> 8; params->pp.sl = stride - 1; /* See above, for further formats see the Linux driver */ - switch (pixel_fmt) { - case IPU_PIX_FMT_RGB565: + switch (pixelfmt) { + case GDF_16BIT_565RGB: params->ip.bpp = 2; params->ip.pfs = 4; params->ip.npb = 7; @@ -533,7 +500,7 @@ static void ipu_ch_param_set_size(union chan_param_mem *params, params->ip.wid1 = 5; /* Green bit width - 1 */ params->ip.wid2 = 4; /* Blue bit width - 1 */ break; - case IPU_PIX_FMT_RGB24: + case GDF_32BIT_X888RGB: params->ip.bpp = 1; /* 24 BPP & RGB PFS */ params->ip.pfs = 4; params->ip.npb = 7; @@ -547,6 +514,7 @@ static void ipu_ch_param_set_size(union chan_param_mem *params, params->ip.wid2 = 7; /* Blue bit width - 1 */ break; default: + printf("mx3fb: Pixel format not supported!\n"); break; } @@ -564,8 +532,8 @@ static void ipu_write_param_mem(uint32_t addr, uint32_t *data, uint32_t num_words) { for (; num_words > 0; num_words--) { - reg_write(addr, IPU_IMA_ADDR); - reg_write(*data++, IPU_IMA_DATA); + writel(addr, IPU_IMA_ADDR); + writel(*data++, IPU_IMA_DATA); addr++; if ((addr & 0x7) == 5) { addr &= ~0x7; /* set to word 0 */ @@ -574,16 +542,6 @@ static void ipu_write_param_mem(uint32_t addr, uint32_t *data, } } -static uint32_t bpp_to_pixfmt(int bpp) -{ - switch (bpp) { - case 16: - return IPU_PIX_FMT_RGB565; - default: - return 0; - } -} - static uint32_t dma_param_addr(enum ipu_channel channel) { /* Channel Parameter Memory */ @@ -596,11 +554,13 @@ static void ipu_init_channel_buffer(enum ipu_channel channel, void *fbmem) uint32_t reg; uint32_t stride_bytes; - stride_bytes = (XRES * ((BIT_PER_PIXEL + 7) / 8) + 3) & ~3; + stride_bytes = (panel.plnSizeX * panel.gdfBytesPP + 3) & ~3; + + debug("%s(channel=%d, fbmem=%p)\n", __func__, channel, fbmem); /* Build parameter memory data for DMA channel */ - ipu_ch_param_set_size(¶ms, bpp_to_pixfmt(BIT_PER_PIXEL), - XRES, YRES, stride_bytes); + ipu_ch_param_set_size(¶ms, panel.gdfIndex, + panel.plnSizeX, panel.plnSizeY, stride_bytes); ipu_ch_param_set_buffer(¶ms, fbmem, NULL); params.pp.bam = 0; /* Some channels (rotation) have restriction on burst length */ @@ -617,22 +577,22 @@ static void ipu_init_channel_buffer(enum ipu_channel channel, void *fbmem) ipu_write_param_mem(dma_param_addr(channel), (uint32_t *)¶ms, 10); /* Disable double-buffering */ - reg = reg_read(IPU_CHA_DB_MODE_SEL); + reg = readl(IPU_CHA_DB_MODE_SEL); reg &= ~(1UL << channel); - reg_write(reg, IPU_CHA_DB_MODE_SEL); + writel(reg, IPU_CHA_DB_MODE_SEL); } static void ipu_channel_set_priority(enum ipu_channel channel, int prio) { - u32 reg = reg_read(IDMAC_CHA_PRI); + u32 reg = readl(IDMAC_CHA_PRI); if (prio) reg |= 1UL << channel; else reg &= ~(1UL << channel); - reg_write(reg, IDMAC_CHA_PRI); + writel(reg, IDMAC_CHA_PRI); } /* @@ -645,7 +605,7 @@ static int ipu_enable_channel(enum ipu_channel channel) uint32_t reg; /* Reset to buffer 0 */ - reg_write(1UL << channel, IPU_CHA_CUR_BUF); + writel(1UL << channel, IPU_CHA_CUR_BUF); switch (channel) { case IDMAC_SDC_0: @@ -655,8 +615,8 @@ static int ipu_enable_channel(enum ipu_channel channel) break; } - reg = reg_read(IDMAC_CHA_EN); - reg_write(reg | (1UL << channel), IDMAC_CHA_EN); + reg = readl(IDMAC_CHA_EN); + writel(reg | (1UL << channel), IDMAC_CHA_EN); return 0; } @@ -665,13 +625,13 @@ static int ipu_update_channel_buffer(enum ipu_channel channel, void *buf) { uint32_t reg; - reg = reg_read(IPU_CHA_BUF0_RDY); + reg = readl(IPU_CHA_BUF0_RDY); if (reg & (1UL << channel)) return -EACCES; /* 44.3.3.1.9 - Row Number 1 (WORD1, offset 0) */ - reg_write(dma_param_addr(channel) + 0x0008UL, IPU_IMA_ADDR); - reg_write((u32)buf, IPU_IMA_DATA); + writel(dma_param_addr(channel) + 0x0008UL, IPU_IMA_ADDR); + writel((u32)buf, IPU_IMA_DATA); return 0; } @@ -690,7 +650,7 @@ static int idmac_tx_submit(enum ipu_channel channel, void *buf) /* ipu_idmac.c::ipu_select_buffer() */ /* Mark buffer 0 as ready. */ - reg_write(1UL << channel, IPU_CHA_BUF0_RDY); + writel(1UL << channel, IPU_CHA_BUF0_RDY); ret = ipu_enable_channel(channel); @@ -706,8 +666,8 @@ static void sdc_enable_channel(void *fbmem) /* mx3fb.c::sdc_fb_init() */ if (ret >= 0) { - reg = reg_read(SDC_COM_CONF); - reg_write(reg | SDC_COM_BG_EN, SDC_COM_CONF); + reg = readl(SDC_COM_CONF); + writel(reg | SDC_COM_BG_EN, SDC_COM_CONF); } /* @@ -715,31 +675,33 @@ static void sdc_enable_channel(void *fbmem) * interrupts. Next sdc_set_brightness() is going to be called * from mx3fb_blank(). */ - msleep(2); + udelay(2000); } /* * mx3fb_set_par() - set framebuffer parameters and change the operating mode. * @return: 0 on success or negative error code on failure. + * TODO: currently only 666 and TFT as DI setup supported */ static int mx3fb_set_par(void) { int ret; - ret = sdc_init_panel(XRES, YRES, PIXEL_FMT); + ret = sdc_init_panel(panel.plnSizeX, panel.plnSizeY, + IPU_PIX_FMT_RGB666, IPU_PANEL_TFT); if (ret < 0) return ret; - reg_write((H_START_WIDTH << 16) | V_START_WIDTH, SDC_BG_POS); + writel((mode->left_margin << 16) | mode->upper_margin, SDC_BG_POS); return 0; } -/* References in this function refer to respective Linux kernel sources */ -void lcd_enable(void) +static void ll_disp3_enable(void *base) { u32 reg; + debug("%s(base=0x%x)\n", __func__, (u32) base); /* pcm037.c::mxc_board_init() */ /* Display Interface #3 */ @@ -780,78 +742,191 @@ void lcd_enable(void) /* ipu_idmac.c::ipu_idmac_init() */ /* Service request counter to maximum - shouldn't be needed */ - reg_write(0x00000070, IDMAC_CONF); + writel(0x00000070, IDMAC_CONF); /* ipu_idmac.c::ipu_init_channel() */ /* Enable IPU sub modules */ - reg = reg_read(IPU_CONF) | IPU_CONF_SDC_EN | IPU_CONF_DI_EN; - reg_write(reg, IPU_CONF); + reg = readl(IPU_CONF) | IPU_CONF_SDC_EN | IPU_CONF_DI_EN; + writel(reg, IPU_CONF); /* mx3fb.c::init_fb_chan() */ /* set Display Interface clock period */ - reg_write(0x00100010L, DI_HSP_CLK_PER); + writel(0x00100010L, DI_HSP_CLK_PER); /* Might need to trigger HSP clock change - see 44.3.3.8.5 */ /* mx3fb.c::sdc_set_brightness() */ /* This might be board-specific */ - reg_write(0x03000000UL | 255 << 16, SDC_PWM_CTRL); + writel(0x03000000UL | 255 << 16, SDC_PWM_CTRL); /* mx3fb.c::sdc_set_global_alpha() */ /* Use global - not per-pixel - Alpha-blending */ - reg = reg_read(SDC_GW_CTRL) & 0x00FFFFFFL; - reg_write(reg | ((uint32_t) 0xff << 24), SDC_GW_CTRL); + reg = readl(SDC_GW_CTRL) & 0x00FFFFFFL; + writel(reg | ((uint32_t) 0xff << 24), SDC_GW_CTRL); - reg = reg_read(SDC_COM_CONF); - reg_write(reg | SDC_COM_GLB_A, SDC_COM_CONF); + reg = readl(SDC_COM_CONF); + writel(reg | SDC_COM_GLB_A, SDC_COM_CONF); /* mx3fb.c::sdc_set_color_key() */ /* Disable colour-keying for background */ - reg = reg_read(SDC_COM_CONF) & + reg = readl(SDC_COM_CONF) & ~(SDC_COM_GWSEL | SDC_COM_KEY_COLOR_G); - reg_write(reg, SDC_COM_CONF); + writel(reg, SDC_COM_CONF); mx3fb_set_par(); - sdc_enable_channel(lcd_base); + sdc_enable_channel(base); /* * Linux driver calls sdc_set_brightness() here again, * once is enough for us */ + debug("%s() done\n", __func__); } -void lcd_ctrl_init(void *lcdbase) -{ - u32 mem_len = XRES * YRES * BIT_PER_PIXEL / 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); -} - +/* ------------------------ public part ------------------- */ ulong calc_fbsize(void) { - return ((panel_info.vl_col * panel_info.vl_row * - NBITS(panel_info.vl_bpix)) / 8) + PAGE_SIZE; + return panel.plnSizeX * panel.plnSizeY * panel.gdfBytesPP; } -int overwrite_console(void) +/* + * The current implementation is only tested for GDF_16BIT_565RGB! + * It was switched from the original CONFIG_LCD setup to CONFIG_VIDEO, + * because the lcd code seemed loaded with color table stuff, that + * does not relate to most modern TFTs. cfb_console.c looks more + * straight forward. + * This is the environment setting for the original setup + * "unknown=video=ctfb:x:240,y:320,depth:16,mode:0,pclk:185925,le:9,ri:17, + * up:7,lo:10,hs:1,vs:1,sync:100663296,vmode:0" + * "videomode=unknown" + * + * Settings for VBEST VGG322403 display: + * "videomode=video=ctfb:x:320,y:240,depth:16,mode:0,pclk:156000, + * "le:20,ri:68,up:7,lo:29,hs:30,vs:3,sync:100663296,vmode:0" + * + * Settings for COM57H5M10XRC display: + * "videomode=video=ctfb:x:640,y:480,depth:16,mode:0,pclk:40000, + * "le:120,ri:40,up:35,lo:10,hs:30,vs:3,sync:100663296,vmode:0" + */ +void *video_hw_init(void) { - /* Keep stdout / stderr on serial, our LCD is for splashscreen only */ - return 1; + char *penv; + u32 memsize; + unsigned long t1, hsynch, vsynch; + int bits_per_pixel, i, tmp, vesa_idx = 0, videomode; + + tmp = 0; + + puts("Video: "); + + videomode = CONFIG_SYS_DEFAULT_VIDEO_MODE; + /* get video mode via environment */ + penv = getenv("videomode"); + if (penv) { + /* decide if it is a string */ + if (penv[0] <= '9') { + videomode = (int) simple_strtoul(penv, NULL, 16); + tmp = 1; + } + } else { + tmp = 1; + } + if (tmp) { + /* parameter are vesa modes */ + /* search params */ + for (i = 0; i < VESA_MODES_COUNT; i++) { + if (vesa_modes[i].vesanr == videomode) + break; + } + if (i == VESA_MODES_COUNT) { + printf("No VESA Mode found, switching to mode 0x%x ", + CONFIG_SYS_DEFAULT_VIDEO_MODE); + i = 0; + } + mode = (struct ctfb_res_modes *) + &res_mode_init[vesa_modes[i].resindex]; + bits_per_pixel = vesa_modes[i].bits_per_pixel; + vesa_idx = vesa_modes[i].resindex; + } else { + mode = (struct ctfb_res_modes *) &var_mode; + bits_per_pixel = video_get_params(mode, penv); + } + + /* calculate hsynch and vsynch freq (info only) */ + t1 = (mode->left_margin + mode->xres + + mode->right_margin + mode->hsync_len) / 8; + t1 *= 8; + t1 *= mode->pixclock; + t1 /= 1000; + hsynch = 1000000000L / t1; + t1 *= (mode->upper_margin + mode->yres + + mode->lower_margin + mode->vsync_len); + t1 /= 1000; + vsynch = 1000000000L / t1; + + /* fill in Graphic device struct */ + sprintf(panel.modeIdent, "%dx%dx%d %ldkHz %ldHz", + mode->xres, mode->yres, + bits_per_pixel, (hsynch / 1000), (vsynch / 1000)); + printf("%s\n", panel.modeIdent); + panel.winSizeX = mode->xres; + panel.winSizeY = mode->yres; + panel.plnSizeX = mode->xres; + panel.plnSizeY = mode->yres; + + switch (bits_per_pixel) { + case 24: + panel.gdfBytesPP = 4; + panel.gdfIndex = GDF_32BIT_X888RGB; + break; + case 16: + panel.gdfBytesPP = 2; + panel.gdfIndex = GDF_16BIT_565RGB; + break; + default: + panel.gdfBytesPP = 1; + panel.gdfIndex = GDF__8BIT_INDEX; + break; + } + + /* set up Hardware */ + memsize = calc_fbsize(); + + debug("%s() allocating %d bytes\n", __func__, memsize); + + /* fill in missing Graphic device struct */ + panel.frameAdrs = (u32) malloc(memsize); + if (panel.frameAdrs == 0) { + printf("%s() malloc(%d) failed\n", __func__, memsize); + return 0; + } + panel.memSize = memsize; + + ll_disp3_enable((void *) panel.frameAdrs); + memset((void *) panel.frameAdrs, 0, memsize); + + debug("%s() done, framebuffer at 0x%x, size=%d cleared\n", + __func__, panel.frameAdrs, memsize); + + return (void *) &panel; +} + +void video_set_lut(unsigned int index, /* color number */ + unsigned char r, /* red */ + unsigned char g, /* green */ + unsigned char b /* blue */ + ) +{ + return; } diff --git a/include/configs/imx31_phycore.h b/include/configs/imx31_phycore.h index 61f05345b..48bd50bb7 100644 --- a/include/configs/imx31_phycore.h +++ b/include/configs/imx31_phycore.h @@ -53,7 +53,7 @@ /* * Size of malloc() pool */ -#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 128 * 1024) +#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 512 * 1024) /* * Hardware drivers @@ -104,7 +104,8 @@ "mtdparts=" MTDPARTS_DEFAULT "\0" \ "prg_uboot=tftpboot 0x80000000 $(uboot); protect off 0xa0000000 +0x20000; erase 0xa0000000 +0x20000; cp.b 0x80000000 0xa0000000 $(filesize)\0" \ "prg_kernel=tftpboot 0x80000000 $(uimage); erase 0xa0040000 +0x180000; cp.b 0x80000000 0xa0040000 $(filesize)\0" \ - "prg_jffs2=tftpboot 0x80000000 $(jffs2); erase 0xa01c0000 0xa1ffffff; cp.b 0x80000000 0xa01c0000 $(filesize)\0" + "prg_jffs2=tftpboot 0x80000000 $(jffs2); erase 0xa01c0000 0xa1ffffff; cp.b 0x80000000 0xa01c0000 $(filesize)\0" \ + "videomode=video=ctfb:x:240,y:320,depth:16,mode:0,pclk:185925,le:9,ri:17,up:7,lo:10,hs:1,vs:1,sync:1241513985,vmode:0\0" #define CONFIG_SMC911X 1 @@ -201,15 +202,16 @@ #define CONFIG_S6E63D6 1 -#define CONFIG_LCD 1 -#define CONFIG_VIDEO_MX3 1 -#define CONFIG_SYS_WHITE_ON_BLACK 1 -#define LCD_BPP LCD_COLOR8 -#define CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE 1 -#define CONFIG_SYS_CONSOLE_IS_IN_ENV 1 - -#define CONFIG_SPLASH_SCREEN 1 -#define CONFIG_CMD_BMP 1 +#define CONFIG_VIDEO +#define CONFIG_CFB_CONSOLE +#define CONFIG_VIDEO_MX3 +#define CONFIG_VIDEO_LOGO +#define CONFIG_VIDEO_SW_CURSOR +#define CONFIG_VGA_AS_SINGLE_DEVICE +#define CONFIG_SYS_CONSOLE_IS_IN_ENV +#define CONFIG_SPLASH_SCREEN +#define CONFIG_CMD_BMP +#define CONFIG_BMP_16BPP #endif #endif /* __CONFIG_H */ diff --git a/include/configs/qong.h b/include/configs/qong.h index e4bc1d0be..b1fc80c52 100644 --- a/include/configs/qong.h +++ b/include/configs/qong.h @@ -79,15 +79,16 @@ #define CONFIG_DNET_BASE (CS1_BASE + QONG_FPGA_PERIPH_SIZE) /* Framebuffer and LCD */ -#define CONFIG_LCD +#define CONFIG_VIDEO +#define CONFIG_CFB_CONSOLE #define CONFIG_VIDEO_MX3 -#define CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE +#define CONFIG_VIDEO_LOGO +#define CONFIG_VIDEO_SW_CURSOR +#define CONFIG_VGA_AS_SINGLE_DEVICE #define CONFIG_SYS_CONSOLE_IS_IN_ENV -#define LCD_BPP LCD_COLOR16 -#define CONFIG_SPLASH_SCREEN +#define CONFIG_SPLASH_SCREEN #define CONFIG_CMD_BMP #define CONFIG_BMP_16BPP -#define CONFIG_DISPLAY_COM57H5M10XRC /* USB */ #define CONFIG_CMD_USB @@ -177,6 +178,9 @@ " +${filesize};cp.b ${fileaddr} " \ xstr(CONFIG_SYS_MONITOR_BASE) " ${filesize}\0" \ "upd=run load update\0" \ + "videomode=video=ctfb:x:640,y:480,depth:16,mode:0,pclk:40000," \ + "le:120,ri:40,up:35,lo:10,hs:30,vs:3,sync:100663296," \ + "vmode:0\0" \ /* * Miscellaneous configurable options