diff options
| -rw-r--r-- | README | 11 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc512x/diu.c | 16 | ||||
| -rw-r--r-- | board/freescale/mpc8610hpcd/mpc8610hpcd_diu.c | 73 | ||||
| -rw-r--r-- | board/freescale/p1022ds/diu.c | 27 | ||||
| -rw-r--r-- | doc/README.video | 19 | ||||
| -rw-r--r-- | drivers/video/Makefile | 2 | ||||
| -rw-r--r-- | drivers/video/cfb_console.c | 19 | ||||
| -rw-r--r-- | drivers/video/fsl_diu_fb.c | 522 | ||||
| -rw-r--r-- | drivers/video/videomodes.c | 64 | ||||
| -rw-r--r-- | drivers/video/videomodes.h | 3 | ||||
| -rw-r--r-- | include/configs/MPC8610HPCD.h | 10 | ||||
| -rw-r--r-- | include/configs/P1022DS.h | 8 | ||||
| -rw-r--r-- | include/configs/pdm360ng.h | 2 | ||||
| -rw-r--r-- | include/fsl_diu_fb.h | 43 | 
14 files changed, 391 insertions, 428 deletions
| @@ -1096,13 +1096,10 @@ The following options need to be configured:  			CONFIG_VIDEO_LOGO  			CONFIG_VIDEO_BMP_LOGO -		The DIU driver will look for the 'monitor' environment variable, -		and if defined, enable the DIU as a console during boot.  This -		variable should be set to one of these values: - -			'0'	Output video to the DVI connector -			'1'	Output video to the LVDS connector -			'2'	Output video to the Dual-Link LVDS connector +		The DIU driver will look for the 'video-mode' environment +		variable, and if defined, enable the DIU as a console during +		boot.  See the documentation file README.video for a +		description of this variable.  - Keyboard Support:  		CONFIG_KEYBOARD diff --git a/arch/powerpc/cpu/mpc512x/diu.c b/arch/powerpc/cpu/mpc512x/diu.c index c4108af33..9dc1e4825 100644 --- a/arch/powerpc/cpu/mpc512x/diu.c +++ b/arch/powerpc/cpu/mpc512x/diu.c @@ -51,20 +51,10 @@ void diu_set_pixel_clock(unsigned int pixclock)  	debug("DIU: Modified value of CLKDVDR = 0x%08x\n", in_be32(clkdvdr));  } -int platform_diu_init(unsigned int *xres, unsigned int *yres) +int platform_diu_init(unsigned int xres, unsigned int yres, const char *port)  { -	unsigned int pixel_format; - -#if defined(CONFIG_VIDEO_XRES) & defined(CONFIG_VIDEO_YRES) -	*xres = CONFIG_VIDEO_XRES; -	*yres = CONFIG_VIDEO_YRES; -#else -	*xres = 1024; -	*yres = 768; -#endif -	pixel_format = 0x88883316; +	unsigned int pixel_format = 0x88883316;  	debug("mpc5121_diu_init\n"); - -	return fsl_diu_init(*xres, pixel_format, 0); +	return fsl_diu_init(xres, pixel_format, 0);  } diff --git a/board/freescale/mpc8610hpcd/mpc8610hpcd_diu.c b/board/freescale/mpc8610hpcd/mpc8610hpcd_diu.c index 81e53e734..3011bb805 100644 --- a/board/freescale/mpc8610hpcd/mpc8610hpcd_diu.c +++ b/board/freescale/mpc8610hpcd/mpc8610hpcd_diu.c @@ -1,6 +1,7 @@  /* - * Copyright 2007 Freescale Semiconductor, Inc. - * York Sun <yorksun@freescale.com> + * Copyright 2007-2011 Freescale Semiconductor, Inc. + * Authors: York Sun <yorksun@freescale.com> + *          Timur Tabi <timur@freescale.com>   *   * FSL DIU Framebuffer driver   * @@ -27,6 +28,10 @@  #include <command.h>  #include <asm/io.h>  #include <fsl_diu_fb.h> +#include "../common/pixis.h" + +#define PX_BRDCFG0_DLINK	0x10 +#define PX_BRDCFG0_DVISEL	0x08  void diu_set_pixel_clock(unsigned int pixclock)  { @@ -49,50 +54,34 @@ void diu_set_pixel_clock(unsigned int pixclock)  	debug("DIU: Modified value of CLKDVDR = 0x%08x\n", *guts_clkdvdr);  } -int platform_diu_init(unsigned int *xres, unsigned int *yres) +int platform_diu_init(unsigned int xres, unsigned int yres, const char *port)  { -	char *monitor_port; -	int gamma_fix; -	unsigned int pixel_format; -	unsigned char tmp_val; -	unsigned char pixis_arch; -	u8 *pixis_base = (u8 *)PIXIS_BASE; - -	tmp_val = in_8(pixis_base + PIXIS_BRDCFG0); -	pixis_arch = in_8(pixis_base + PIXIS_VER); - -	monitor_port = getenv("monitor"); -	if (!strncmp(monitor_port, "0", 1)) {	/* 0 - DVI */ -		*xres = 1280; -		*yres = 1024; -		if (pixis_arch == 0x01) -			pixel_format = 0x88882317; -		else -			pixel_format = 0x88883316; -		gamma_fix = 0; -		out_8(pixis_base + PIXIS_BRDCFG0, tmp_val | 0x08); +	const char *name; +	int gamma_fix = 0; +	u32 pixel_format = 0x88883316; +	u8 temp; -	} else if (!strncmp(monitor_port, "1", 1)) { /* 1 - Single link LVDS */ -		*xres = 1024; -		*yres = 768; -		pixel_format = 0x88883316; -		gamma_fix = 0; -		out_8(pixis_base + PIXIS_BRDCFG0, (tmp_val & 0xf7) | 0x10); +	temp = in_8(&pixis->brdcfg0); -	} else if (!strncmp(monitor_port, "2", 1)) { /* 2 - Double link LVDS */ -		*xres = 1280; -		*yres = 1024; -		pixel_format = 0x88883316; +	if (strncmp(port, "dlvds", 5) == 0) { +		/* Dual link LVDS */  		gamma_fix = 1; -		out_8(pixis_base + PIXIS_BRDCFG0, tmp_val & 0xe7); - -	} else {	/* DVI */ -		*xres = 1280; -		*yres = 1024; -		pixel_format = 0x88882317; -		gamma_fix = 0; -		out_8(pixis_base + PIXIS_BRDCFG0, tmp_val | 0x08); +		temp &= ~(PX_BRDCFG0_DLINK | PX_BRDCFG0_DVISEL); +		name = "Dual-Link LVDS"; +	} else if (strncmp(port, "lvds", 4) == 0) { +		/* Single link LVDS */ +		temp = (temp & ~PX_BRDCFG0_DVISEL) | PX_BRDCFG0_DLINK; +		name = "Single-Link LVDS"; +	} else { +		/* DVI */ +		if (in_8(&pixis->ver) == 1)	/* Board version */ +			pixel_format = 0x88882317; +		temp |= PX_BRDCFG0_DVISEL; +		name = "DVI";  	} -	return fsl_diu_init(*xres, pixel_format, gamma_fix); +	printf("DIU:   Switching to %s monitor @ %ux%u\n", name, xres, yres); +	out_8(&pixis->brdcfg0, temp); + +	return fsl_diu_init(xres, pixel_format, gamma_fix);  } diff --git a/board/freescale/p1022ds/diu.c b/board/freescale/p1022ds/diu.c index b37e0e269..7d1f6aa12 100644 --- a/board/freescale/p1022ds/diu.c +++ b/board/freescale/p1022ds/diu.c @@ -12,6 +12,7 @@  #include <common.h>  #include <command.h> +#include <linux/ctype.h>  #include <asm/io.h>  #include <stdio_dev.h>  #include <video_fb.h> @@ -81,10 +82,10 @@ void diu_set_pixel_clock(unsigned int pixclock)  	out_be32(&gur->clkdvdr, temp | 0x80000000 | ((pixval & 0x1F) << 16));  } -int platform_diu_init(unsigned int *xres, unsigned int *yres) +int platform_diu_init(unsigned int xres, unsigned int yres, const char *port)  {  	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); -	char *monitor_port; +	const char *name;  	u32 pixel_format;  	u8 temp; @@ -100,21 +101,23 @@ int platform_diu_init(unsigned int *xres, unsigned int *yres)  	temp = in_8(&pixis->brdcfg1); -	monitor_port = getenv("monitor"); -	if (!strncmp(monitor_port, "1", 1)) { /* 1 - Single link LVDS */ -		*xres = 1024; -		*yres = 768; -		/* Enable the DFP port, disable the DVI and the backlight */ -		temp &= ~(PX_BRDCFG1_DVIEN | PX_BRDCFG1_BACKLIGHT); -		temp |= PX_BRDCFG1_DFPEN; +	if (strncmp(port, "lvds", 4) == 0) { +		/* Single link LVDS */ +		temp &= ~PX_BRDCFG1_DVIEN; +		/* +		 * LVDS also needs backlight enabled, otherwise the display +		 * will be blank. +		 */ +		temp |= (PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT); +		name = "Single-Link LVDS";  	} else {	/* DVI */ -		*xres = 1280; -		*yres = 1024;  		/* Enable the DVI port, disable the DFP and the backlight */  		temp &= ~(PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT);  		temp |= PX_BRDCFG1_DVIEN; +		name = "DVI";  	} +	printf("DIU:   Switching to %s monitor @ %ux%u\n", name, xres, yres);  	out_8(&pixis->brdcfg1, temp);  	/* @@ -136,7 +139,7 @@ int platform_diu_init(unsigned int *xres, unsigned int *yres)  	clrsetbits_be32(&gur->pmuxcr, PMUXCR_ELBCDIU_MASK, PMUXCR_ELBCDIU_DIU);  	pmuxcr = in_be32(&gur->pmuxcr); -	return fsl_diu_init(*xres, pixel_format, 0); +	return fsl_diu_init(xres, pixel_format, 0);  }  /* diff --git a/doc/README.video b/doc/README.video index 34e199c2d..0c04bea57 100644 --- a/doc/README.video +++ b/doc/README.video @@ -28,3 +28,22 @@ The driver has been tested with the following configurations:  - MPC823FADS with AD7176 on a PAL TV (YCbYCr)	- arsenio@tin.it  - GENIETV    with AD7177 on a PAL TV (YCbYCr)	- arsenio@tin.it + + +"video-mode" environment variable +=============================== + +The 'video-mode' environment variable can be used to enable and configure +some video drivers.  The format matches the video= command-line option used +for Linux: + +	video-mode=<driver>:<xres>x<yres>-<depth>@<freq><,option=string> + +	<driver>	The video driver name, ignored by U-Boot +	<xres>		The X resolution (in pixels) to use. +	<yres>		The Y resolution (in pixels) to use. +	<depth>		The color depth (in bits) to use. +	<freq>		The frequency (in Hz) to use. +	<options>	A comma-separated list of device-specific options + +Example: video-mode=fslfb:1280x1024-32@60,monitor=dvi diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 2c53a6f3e..086dc0538 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -28,7 +28,7 @@ LIB	:= $(obj)libvideo.o  COBJS-$(CONFIG_ATI_RADEON_FB) += ati_radeon_fb.o videomodes.o  COBJS-$(CONFIG_ATMEL_LCD) += atmel_lcdfb.o  COBJS-$(CONFIG_CFB_CONSOLE) += cfb_console.o -COBJS-$(CONFIG_FSL_DIU_FB) += fsl_diu_fb.o +COBJS-$(CONFIG_FSL_DIU_FB) += fsl_diu_fb.o videomodes.o  COBJS-$(CONFIG_S6E63D6) += s6e63d6.o  COBJS-$(CONFIG_VIDEO_AMBA) += amba.o  COBJS-$(CONFIG_VIDEO_CT69000) += ct69000.o videomodes.o diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index dd849c2dc..b427c8487 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -882,6 +882,8 @@ static int display_rle8_bitmap (bmp_image_t *img, int xoff, int yoff,  	struct palette p[256];  	bmp_color_table_entry_t cte;  	int green_shift, red_off; +	int limit = VIDEO_COLS * VIDEO_ROWS; +	int pixels = 0;  	x = 0;  	y = __le32_to_cpu(img->header.height) - 1; @@ -962,6 +964,10 @@ static int display_rle8_bitmap (bmp_image_t *img, int xoff, int yoff,  				/* unencoded run */  				cnt = bm[1];  				runlen = cnt; +				pixels += cnt; +				if (pixels > limit) +					goto error; +  				bm += 2;  				if (y < height) {  					if (x >= width) { @@ -970,7 +976,6 @@ static int display_rle8_bitmap (bmp_image_t *img, int xoff, int yoff,  					}  					if (x + runlen > width)  						cnt = width - x; -  					draw_bitmap (&fbp, bm, p, cnt, 0);  					x += runlen;  				} @@ -982,9 +987,13 @@ next_run:  			break;  		default:  			/* encoded run */ +			cnt = bm[0]; +			runlen = cnt; +			pixels += cnt; +			if (pixels > limit) +				goto error; +  			if (y < height) { /* only draw into visible area */ -				cnt = bm[0]; -				runlen = cnt;  				if (x >= width) {  					x += runlen;  					bm += 2; @@ -992,7 +1001,6 @@ next_run:  				}  				if (x + runlen > width)  					cnt = width - x; -  				draw_bitmap (&fbp, bm, p, cnt, 1);  				x += runlen;  			} @@ -1001,6 +1009,9 @@ next_run:  		}  	}  	return 0; +error: +	printf("Error: Too much encoded pixel data, validate your bitmap\n"); +	return -1;  }  #endif diff --git a/drivers/video/fsl_diu_fb.c b/drivers/video/fsl_diu_fb.c index 35ed938be..070984904 100644 --- a/drivers/video/fsl_diu_fb.c +++ b/drivers/video/fsl_diu_fb.c @@ -1,6 +1,7 @@  /* - * Copyright 2007, 2010 Freescale Semiconductor, Inc. - * York Sun <yorksun@freescale.com> + * Copyright 2007, 2010-2011 Freescale Semiconductor, Inc. + * Authors: York Sun <yorksun@freescale.com> + *          Timur Tabi <timur@freescale.com>   *   * FSL DIU Framebuffer driver   * @@ -24,12 +25,42 @@   */  #include <common.h> -#include <i2c.h>  #include <malloc.h>  #include <asm/io.h> +#include "videomodes.h" +#include <video_fb.h>  #include <fsl_diu_fb.h> +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 */ @@ -53,6 +84,7 @@ struct fb_videomode {  /* This setting is used for the ifm pdm360ng with PRIMEVIEW PM070WL3 */  static struct fb_videomode fsl_diu_mode_800 = { +	.name		= "800x600-60",  	.refresh	= 60,  	.xres		= 800,  	.yres		= 480, @@ -74,6 +106,7 @@ static struct fb_videomode fsl_diu_mode_800 = {   * hsync 31.5kHz, vsync 60Hz   */  static struct fb_videomode fsl_diu_mode_1024 = { +	.name		= "1024x768-60",  	.refresh	= 60,  	.xres		= 1024,  	.yres		= 768, @@ -109,120 +142,137 @@ static struct fb_videomode fsl_diu_mode_1280 = {   */  struct diu_ad {  	/* Word 0(32-bit) in DDR memory */ -	unsigned int pix_fmt; /* hard coding pixel format */ +	__le32 pix_fmt; /* hard coding pixel format */  	/* Word 1(32-bit) in DDR memory */ -	unsigned int addr; +	__le32 addr;  	/* Word 2(32-bit) in DDR memory */ -	unsigned int src_size_g_alpha; +	__le32 src_size_g_alpha;  	/* Word 3(32-bit) in DDR memory */ -	unsigned int aoi_size; +	__le32 aoi_size;  	/* Word 4(32-bit) in DDR memory */ -	unsigned int offset_xyi; +	__le32 offset_xyi;  	/* Word 5(32-bit) in DDR memory */ -	unsigned int offset_xyd; +	__le32 offset_xyd;  	/* Word 6(32-bit) in DDR memory */ -	unsigned int ckmax_r:8; -	unsigned int ckmax_g:8; -	unsigned int ckmax_b:8; -	unsigned int res9:8; +	__le32 ckmax_r:8; +	__le32 ckmax_g:8; +	__le32 ckmax_b:8; +	__le32 res9:8;  	/* Word 7(32-bit) in DDR memory */ -	unsigned int ckmin_r:8; -	unsigned int ckmin_g:8; -	unsigned int ckmin_b:8; -	unsigned int res10:8; +	__le32 ckmin_r:8; +	__le32 ckmin_g:8; +	__le32 ckmin_b:8; +	__le32 res10:8;  	/* Word 8(32-bit) in DDR memory */ -	unsigned int next_ad; +	__le32 next_ad;  	/* Word 9(32-bit) in DDR memory, just for 64-bit aligned */ -	unsigned int res1; -	unsigned int res2; -	unsigned int res3; -}__attribute__ ((packed)); +	__le32 res[3]; +} __attribute__ ((packed));  /*   * DIU register map   */  struct diu { -	unsigned int desc[3]; -	unsigned int gamma; -	unsigned int pallete; -	unsigned int cursor; -	unsigned int curs_pos; -	unsigned int diu_mode; -	unsigned int bgnd; -	unsigned int bgnd_wb; -	unsigned int disp_size; -	unsigned int wb_size; -	unsigned int wb_mem_addr; -	unsigned int hsyn_para; -	unsigned int vsyn_para; -	unsigned int syn_pol; -	unsigned int thresholds; -	unsigned int int_status; -	unsigned int int_mask; -	unsigned int colorbar[8]; -	unsigned int filling; -	unsigned int plut; +	__be32 desc[3]; +	__be32 gamma; +	__be32 pallete; +	__be32 cursor; +	__be32 curs_pos; +	__be32 diu_mode; +	__be32 bgnd; +	__be32 bgnd_wb; +	__be32 disp_size; +	__be32 wb_size; +	__be32 wb_mem_addr; +	__be32 hsyn_para; +	__be32 vsyn_para; +	__be32 syn_pol; +	__be32 thresholds; +	__be32 int_status; +	__be32 int_mask; +	__be32 colorbar[8]; +	__be32 filling; +	__be32 plut;  } __attribute__ ((packed)); -struct diu_hw { -	struct diu *diu_reg; -	volatile unsigned int mode;		/* DIU operation mode */ -}; -  struct diu_addr { -	unsigned char  *  paddr;	/* Virtual address */ -	unsigned int	   offset; +	void *vaddr;		/* Virtual address */ +	u32 paddr;		/* 32-bit physical address */ +	unsigned int offset;	/* Alignment offset */  }; +static struct fb_info info; +  /* - * Modes of operation of DIU + * Align to 64-bit(8-byte), 32-byte, etc.   */ -#define MFB_MODE0	0	/* DIU off */ -#define MFB_MODE1	1	/* All three planes output to display */ -#define MFB_MODE2	2	/* Plane 1 to display, -				 * planes 2+3 written back to memory */ -#define MFB_MODE3	3	/* All three planes written back to memory */ -#define MFB_MODE4	4	/* Color bar generation */ +static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align) +{ +	u32 offset, ssize; +	u32 mask; -#define MAX_CURS		32 +	ssize = size + bytes_align; +	buf->vaddr = malloc(ssize); +	if (!buf->vaddr) +		return -1; -static struct fb_info fsl_fb_info; -static struct diu_addr gamma, cursor; -static struct diu_ad fsl_diu_fb_ad __attribute__ ((aligned(32))); -static struct diu_ad dummy_ad __attribute__ ((aligned(32))); -static unsigned char *dummy_fb; -static struct diu_hw dr = { -	.mode = MFB_MODE1, -}; +	memset(buf->vaddr, 0, ssize); +	mask = bytes_align - 1; +	offset = (u32)buf->vaddr & mask; +	if (offset) { +		buf->offset = bytes_align - offset; +		buf->vaddr += offset; +	} else +		buf->offset = 0; + +	buf->paddr = virt_to_phys(buf->vaddr); +	return 0; +} + +/* + * Allocate a framebuffer and an Area Descriptor that points to it.  Both + * are created in the same memory block.  The Area Descriptor is updated to + * 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 long size = xres * yres * depth; +	struct diu_addr addr; +	struct diu_ad *ad; +	size_t ad_size = roundup(sizeof(struct diu_ad), 32); + +	/* +	 * Allocate a memory block that holds the Area Descriptor and the +	 * frame buffer right behind it.  To keep the code simple, everything +	 * is aligned on a 32-byte address. +	 */ +	if (allocate_buf(&addr, ad_size + size, 32) < 0) +		return NULL; + +	ad = addr.vaddr; +	ad->addr = cpu_to_le32(addr.paddr + ad_size); +	ad->aoi_size = cpu_to_le32((yres << 16) | xres); +	ad->src_size_g_alpha = cpu_to_le32((yres << 12) | xres); +	ad->offset_xyi = 0; +	ad->offset_xyd = 0; -int fb_enabled = 0; -int fb_initialized = 0; -const int default_xres = 1280; -const int default_pixel_format = 0x88882317; +	if (fb) +		*fb = addr.vaddr + ad_size; -static int map_video_memory(struct fb_info *info, unsigned long bytes_align); -static void enable_lcdc(void); -static void disable_lcdc(void); -static int fsl_diu_enable_panel(struct fb_info *info); -static int fsl_diu_disable_panel(struct fb_info *info); -static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align); -void diu_set_pixel_clock(unsigned int pixclock); +	return ad; +} -int fsl_diu_init(int xres, unsigned int pixel_format, int gamma_fix) +int fsl_diu_init(int xres, u32 pixel_format, int gamma_fix)  {  	struct fb_videomode *fsl_diu_mode_db; -	struct diu_ad *ad = &fsl_diu_fb_ad; -	struct diu *hw; -	struct fb_info *info = &fsl_fb_info; -	struct fb_var_screeninfo *var = &info->var; -	unsigned char *gamma_table_base; +	struct diu_ad *ad; +	struct diu *hw = (struct diu *)CONFIG_SYS_DIU_ADDR; +	u8 *gamma_table_base;  	unsigned int i, j; - -	debug("Enter fsl_diu_init\n"); -	dr.diu_reg = (struct diu *) (CONFIG_SYS_DIU_ADDR); -	hw = (struct diu *) dr.diu_reg; - -	disable_lcdc(); +	struct diu_ad *dummy_ad; +	struct diu_addr gamma; +	struct diu_addr cursor;  	switch (xres) {  	case 800: @@ -235,65 +285,40 @@ int fsl_diu_init(int xres, unsigned int pixel_format, int gamma_fix)  		fsl_diu_mode_db = &fsl_diu_mode_1024;  	} -	if (0 == fb_initialized) { -		allocate_buf(&gamma, 768, 32); -		debug("gamma is allocated @ 0x%x\n", -			(unsigned int)gamma.paddr); -		allocate_buf(&cursor, MAX_CURS * MAX_CURS * 2, 32); -		debug("curosr is allocated @ 0x%x\n", -			(unsigned int)cursor.paddr); - -		/* create a dummy fb and dummy ad */ -		dummy_fb = malloc(64); -		if (NULL == dummy_fb) { -			printf("Cannot allocate dummy fb\n"); -			return -1; -		} -		dummy_ad.addr = cpu_to_le32((unsigned int)dummy_fb); -		dummy_ad.pix_fmt = 0x88882317; -		dummy_ad.src_size_g_alpha = 0x04400000;	/* alpha = 0 */ -		dummy_ad.aoi_size = 0x02000400; -		dummy_ad.offset_xyi = 0; -		dummy_ad.offset_xyd = 0; -		dummy_ad.next_ad = 0; -		/* Memory allocation for framebuffer */ -		if (map_video_memory(info, 32)) { -			printf("Unable to allocate fb memory 1\n"); -			return -1; -		} +	/* The AD struct for the dummy framebuffer and the FB itself */ +	dummy_ad = allocate_fb(2, 4, 4, NULL); +	if (!dummy_ad) { +		printf("DIU:   Out of memory\n"); +		return -1;  	} - -	memset(info->screen_base, 0, info->smem_len); - -	out_be32(&dr.diu_reg->desc[0], (int)&dummy_ad); -	out_be32(&dr.diu_reg->desc[1], (int)&dummy_ad); -	out_be32(&dr.diu_reg->desc[2], (int)&dummy_ad); -	debug("dummy dr.diu_reg->desc[0] = 0x%x\n", dr.diu_reg->desc[0]); -	debug("dummy desc[0] = 0x%x\n", hw->desc[0]); +	dummy_ad->pix_fmt = 0x88883316;  	/* read mode info */ -	var->xres = fsl_diu_mode_db->xres; -	var->yres = fsl_diu_mode_db->yres; -	var->bits_per_pixel = 32; -	var->pixclock = fsl_diu_mode_db->pixclock; -	var->left_margin = fsl_diu_mode_db->left_margin; -	var->right_margin = fsl_diu_mode_db->right_margin; -	var->upper_margin = fsl_diu_mode_db->upper_margin; -	var->lower_margin = fsl_diu_mode_db->lower_margin; -	var->hsync_len = fsl_diu_mode_db->hsync_len; -	var->vsync_len = fsl_diu_mode_db->vsync_len; -	var->sync = fsl_diu_mode_db->sync; -	var->vmode = fsl_diu_mode_db->vmode; -	info->line_length = var->xres * var->bits_per_pixel / 8; +	info.var.xres = fsl_diu_mode_db->xres; +	info.var.yres = fsl_diu_mode_db->yres; +	info.var.bits_per_pixel = 32; +	info.var.pixclock = fsl_diu_mode_db->pixclock; +	info.var.left_margin = fsl_diu_mode_db->left_margin; +	info.var.right_margin = fsl_diu_mode_db->right_margin; +	info.var.upper_margin = fsl_diu_mode_db->upper_margin; +	info.var.lower_margin = fsl_diu_mode_db->lower_margin; +	info.var.hsync_len = fsl_diu_mode_db->hsync_len; +	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; + +	/* Memory allocation for framebuffer */ +	info.smem_len = +		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); +	if (!ad) { +		printf("DIU:   Out of memory\n"); +		return -1; +	}  	ad->pix_fmt = pixel_format; -	ad->addr    = cpu_to_le32((unsigned int)info->screen_base); -	ad->src_size_g_alpha -			= cpu_to_le32((var->yres << 12) | var->xres); -	/* fix me. AOI should not be greater than display size */ -	ad->aoi_size	= cpu_to_le32(( var->yres << 16) |  var->xres); -	ad->offset_xyi = 0; -	ad->offset_xyd = 0;  	/* Disable chroma keying function */  	ad->ckmax_r = 0; @@ -304,195 +329,91 @@ int fsl_diu_init(int xres, unsigned int pixel_format, int gamma_fix)  	ad->ckmin_g = 255;  	ad->ckmin_b = 255; -	gamma_table_base = gamma.paddr; -	debug("gamma_table_base is allocated @ 0x%x\n", -		(unsigned int)gamma_table_base); - -	/* Prep for DIU init  - gamma table */ - +	/* Initialize the gamma table */ +	if (allocate_buf(&gamma, 256 * 3, 32) < 0) { +		printf("DIU:   Out of memory\n"); +		return -1; +	} +	gamma_table_base = gamma.vaddr;  	for (i = 0; i <= 2; i++) -		for (j = 0; j <= 255; j++) +		for (j = 0; j < 256; j++)  			*gamma_table_base++ = j;  	if (gamma_fix == 1) {	/* fix the gamma */ -		debug("Fix gamma table\n"); -		gamma_table_base = gamma.paddr; -		for (i = 0; i < 256*3; i++) { +		gamma_table_base = gamma.vaddr; +		for (i = 0; i < 256 * 3; i++) {  			gamma_table_base[i] = (gamma_table_base[i] << 2)  				| ((gamma_table_base[i] >> 6) & 0x03);  		}  	} -	debug("update-lcdc: HW - %p\n Disabling DIU\n", hw); +	/* Initialize the cursor */ +	if (allocate_buf(&cursor, 32 * 32 * 2, 32) < 0) { +		printf("DIU:   Can't alloc cursor data\n"); +		return -1; +	}  	/* Program DIU registers */ +	out_be32(&hw->diu_mode, 0);	/* Temporarily disable the DIU */ -	out_be32(&hw->gamma, (int)gamma.paddr); -	out_be32(&hw->cursor, (int)cursor.paddr); +	out_be32(&hw->gamma, gamma.paddr); +	out_be32(&hw->cursor, cursor.paddr);  	out_be32(&hw->bgnd, 0x007F7F7F); -	out_be32(&hw->bgnd_wb, 0);				/* BGND_WB */ -	out_be32(&hw->disp_size, var->yres << 16 | var->xres);	/* DISP SIZE */ -	out_be32(&hw->wb_size, 0);				/* WB SIZE */ -	out_be32(&hw->wb_mem_addr, 0);				/* WB MEM ADDR */ -	out_be32(&hw->hsyn_para, var->left_margin << 22 |	/* BP_H */ -			var->hsync_len << 11   |	/* PW_H */ -			var->right_margin);		/* FP_H */ +	out_be32(&hw->bgnd_wb, 0); +	out_be32(&hw->disp_size, info.var.yres << 16 | info.var.xres); +	out_be32(&hw->wb_size, 0); +	out_be32(&hw->wb_mem_addr, 0); +	out_be32(&hw->hsyn_para, info.var.left_margin << 22 | +			info.var.hsync_len << 11 | +			info.var.right_margin); -	out_be32(&hw->vsyn_para, var->upper_margin << 22 |	/* BP_V */ -			var->vsync_len << 11    |	/* PW_V  */ -			var->lower_margin);		/* FP_V  */ +	out_be32(&hw->vsyn_para, info.var.upper_margin << 22 | +			info.var.vsync_len << 11 | +			info.var.lower_margin); -	out_be32(&hw->syn_pol, 0);			/* SYNC SIGNALS POLARITY */ -	out_be32(&hw->thresholds, 0x00037800);		/* The Thresholds */ -	out_be32(&hw->int_status, 0);			/* INTERRUPT STATUS */ -	out_be32(&hw->int_mask, 0);			/* INT MASK */ +	out_be32(&hw->syn_pol, 0); +	out_be32(&hw->thresholds, 0x00037800); +	out_be32(&hw->int_status, 0); +	out_be32(&hw->int_mask, 0);  	out_be32(&hw->plut, 0x01F5F666);  	/* Pixel Clock configuration */ -	debug("DIU pixclock in ps - %d\n", var->pixclock); -	diu_set_pixel_clock(var->pixclock); - -	fb_initialized = 1; - -	/* Enable the DIU */ -	fsl_diu_enable_panel(info); -	enable_lcdc(); - -	return 0; -} - -char *fsl_fb_open(struct fb_info **info) -{ -	*info = &fsl_fb_info; -	return fsl_fb_info.screen_base; -} - -void fsl_diu_close(void) -{ -	struct fb_info *info = &fsl_fb_info; -	fsl_diu_disable_panel(info); -} +	diu_set_pixel_clock(info.var.pixclock); -static int fsl_diu_enable_panel(struct fb_info *info) -{ -	struct diu *hw = dr.diu_reg; -	struct diu_ad *ad = &fsl_diu_fb_ad; - -	debug("Entered: enable_panel\n"); -	if (in_be32(&hw->desc[0]) != (unsigned)ad) -		out_be32(&hw->desc[0], (unsigned)ad); -	debug("desc[0] = 0x%x\n", hw->desc[0]); -	return 0; -} +	/* Set the frame buffers */ +	out_be32(&hw->desc[0], virt_to_phys(ad)); +	out_be32(&hw->desc[1], virt_to_phys(dummy_ad)); +	out_be32(&hw->desc[2], virt_to_phys(dummy_ad)); -static int fsl_diu_disable_panel(struct fb_info *info) -{ -	struct diu *hw = dr.diu_reg; +	/* Enable the DIU, set display to all three planes */ +	out_be32(&hw->diu_mode, 1); -	debug("Entered: disable_panel\n"); -	if (in_be32(&hw->desc[0]) != (unsigned)&dummy_ad) -		out_be32(&hw->desc[0], (unsigned)&dummy_ad);  	return 0;  } -static int map_video_memory(struct fb_info *info, unsigned long bytes_align) -{ -	unsigned long offset; -	unsigned long mask; - -	debug("Entered: map_video_memory\n"); -	/* allocate maximum 1280*1024 with 32bpp */ -	info->smem_len = 1280 * 4 *1024 + bytes_align; -	debug("MAP_VIDEO_MEMORY: smem_len = %d\n", info->smem_len); -	info->screen_base = malloc(info->smem_len); -	if (info->screen_base == NULL) { -		printf("Unable to allocate fb memory\n"); -		return -1; -	} -	info->smem_start = (unsigned int) info->screen_base; -	mask = bytes_align - 1; -	offset = (unsigned long)info->screen_base & mask; -	if (offset) { -		info->screen_base += (bytes_align - offset); -		info->smem_len = info->smem_len - (bytes_align - offset); -	} else -		info->smem_len = info->smem_len - bytes_align; - -	info->screen_size = info->smem_len; - -	debug("Allocated fb @ 0x%08lx, size=%d.\n", -		info->smem_start, info->smem_len); - -	return 0; -} - -static void enable_lcdc(void) -{ -	struct diu *hw = dr.diu_reg; - -	debug("Entered: enable_lcdc, fb_enabled = %d\n", fb_enabled); -	if (!fb_enabled) { -		out_be32(&hw->diu_mode, dr.mode); -		fb_enabled++; -	} -	debug("diu_mode = %d\n", hw->diu_mode); -} - -static void disable_lcdc(void) -{ -	struct diu *hw = dr.diu_reg; - -	debug("Entered: disable_lcdc, fb_enabled = %d\n", fb_enabled); -	if (fb_enabled) { -		out_be32(&hw->diu_mode, 0); -		fb_enabled = 0; -	} -} - -/* - * Align to 64-bit(8-byte), 32-byte, etc. - */ -static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align) +void *video_hw_init(void)  { -	u32 offset, ssize; -	u32 mask; +	static GraphicDevice ctfb; +	const char *options; +	unsigned int depth = 0, freq = 0; -	debug("Entered: allocate_buf\n"); -	ssize = size + bytes_align; -	buf->paddr = malloc(ssize); -	if (!buf->paddr) -		return -1; - -	memset(buf->paddr, 0, ssize); -	mask = bytes_align - 1; -	offset = (u32)buf->paddr & mask; -	if (offset) { -		buf->offset = bytes_align - offset; -		buf->paddr = (unsigned char *) ((u32)buf->paddr + offset); -	} else -		buf->offset = 0; -	return 0; -} - -#if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE) -#include <stdio_dev.h> -#include <video_fb.h> -/* - * The Graphic Device - */ -static GraphicDevice ctfb; +	if (!video_get_video_mode(&ctfb.winSizeX, &ctfb.winSizeY, &depth, &freq, +				  &options)) +		return NULL; -void *video_hw_init(void) -{ -	struct fb_info *info; +	/* Find the monitor port, which is a required option */ +	if (!options) +		return NULL; +	if (strncmp(options, "monitor=", 8) != 0) +		return NULL; -	if (platform_diu_init(&ctfb.winSizeX, &ctfb.winSizeY) < 0) +	if (platform_diu_init(ctfb.winSizeX, ctfb.winSizeY, options + 8) < 0)  		return NULL;  	/* fill in Graphic device struct */  	sprintf(ctfb.modeIdent, "%ix%ix%i %ikHz %iHz", -		ctfb.winSizeX, ctfb.winSizeY, 32, 64, 60); +		ctfb.winSizeX, ctfb.winSizeY, depth, 64, freq); -	ctfb.frameAdrs = (unsigned int)fsl_fb_open(&info); +	ctfb.frameAdrs = (unsigned int)info.screen_base;  	ctfb.plnSizeX = ctfb.winSizeX;  	ctfb.plnSizeY = ctfb.winSizeY; @@ -501,7 +422,7 @@ void *video_hw_init(void)  	ctfb.isaBase = 0;  	ctfb.pciBase = 0; -	ctfb.memSize = info->screen_size; +	ctfb.memSize = info.screen_size;  	/* Cursor Start Address */  	ctfb.dprBase = 0; @@ -510,4 +431,3 @@ void *video_hw_init(void)  	return &ctfb;  } -#endif /* defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE) */ diff --git a/drivers/video/videomodes.c b/drivers/video/videomodes.c index d27ce1d2c..6fe5811ae 100644 --- a/drivers/video/videomodes.c +++ b/drivers/video/videomodes.c @@ -1,6 +1,7 @@  /*   * (C) Copyright 2004   * Pierre Aubert, Staubli Faverges , <p.aubert@staubli.com> + * Copyright 2011 Freescale Semiconductor, Inc.   *   * See file CREDITS for list of people who contributed to this   * project. @@ -73,6 +74,8 @@  ****************************************************************************/  #include <common.h> +#include <linux/ctype.h> +  #include "videomodes.h"  const struct ctfb_vesa_modes vesa_modes[VESA_MODES_COUNT] = { @@ -206,3 +209,64 @@ int video_get_params (struct ctfb_res_modes *pPar, char *penv)  	}  	return bpp;  } + +/* + * Parse the 'video-mode' environment variable + * + * Example: "video-mode=fslfb:1280x1024-32@60,monitor=dvi".  See + * doc/README.video for more information on how to set the variable. + * + * @xres: returned value of X-resolution + * @yres: returned value of Y-resolution + * @depth: returned value of color depth + * @freq: returned value of monitor frequency + * @options: pointer to any remaining options, or NULL + * + * Returns 1 if valid values were found, 0 otherwise + */ +int video_get_video_mode(unsigned int *xres, unsigned int *yres, +	unsigned int *depth, unsigned int *freq, const char **options) +{ +	char *p = getenv("video-mode"); +	if (!p) +		return 0; + +	/* Skip over the driver name, which we don't care about. */ +	p = strchr(p, ':'); +	if (!p) +		return 0; + +	/* Get the X-resolution*/ +	while (*p && !isdigit(*p)) +		p++; +	*xres = simple_strtoul(p, &p, 10); +	if (!*xres) +		return 0; + +	/* Get the Y-resolution */ +	while (*p && !isdigit(*p)) +		p++; +	*yres = simple_strtoul(p, &p, 10); +	if (!*yres) +		return 0; + +	/* Get the depth */ +	while (*p && !isdigit(*p)) +		p++; +	*depth = simple_strtoul(p, &p, 10); +	if (!*depth) +		return 0; + +	/* Get the frequency */ +	while (*p && !isdigit(*p)) +		p++; +	*freq = simple_strtoul(p, &p, 10); +	if (!*freq) +		return 0; + +	/* Find the extra options, if any */ +	p = strchr(p, ','); +	*options = p ? p + 1 : NULL; + +	return 1; +} diff --git a/drivers/video/videomodes.h b/drivers/video/videomodes.h index 0d7c33541..e546ab44f 100644 --- a/drivers/video/videomodes.h +++ b/drivers/video/videomodes.h @@ -86,3 +86,6 @@ extern const struct ctfb_vesa_modes vesa_modes[];  extern const struct ctfb_res_modes res_mode_init[];  int video_get_params (struct ctfb_res_modes *pPar, char *penv); + +int video_get_video_mode(unsigned int *xres, unsigned int *yres, +	unsigned int *depth, unsigned int *freq, const char **options); diff --git a/include/configs/MPC8610HPCD.h b/include/configs/MPC8610HPCD.h index efe03132f..31dbc3b7d 100644 --- a/include/configs/MPC8610HPCD.h +++ b/include/configs/MPC8610HPCD.h @@ -1,5 +1,5 @@  /* - * Copyright 2007, 2010 Freescale Semiconductor, Inc. + * Copyright 2007-2011 Freescale Semiconductor, Inc.   *   * This program is free software; you can redistribute it and/or   * modify it under the terms of the GNU General Public License @@ -23,6 +23,8 @@  /* video */ +#define CONFIG_FSL_DIU_FB +  #ifdef CONFIG_FSL_DIU_FB  #define CONFIG_SYS_DIU_ADDR	(CONFIG_SYS_CCSRBAR + 0x2c000)  #define CONFIG_VIDEO @@ -625,8 +627,6 @@   "diuregs=md e002c000 1d\0" \   "dium=mw e002c01c\0" \   "diuerr=md e002c014 1\0" \ - "othbootargs=diufb=15M video=fslfb:1280x1024-32@60,monitor=0 debug\0" \ - "monitor=0-DVI\0" \   "pmregs=md e00e1000 2b\0" \   "lawregs=md e0000c08 4b\0" \   "lbcregs=md e0005000 36\0" \ @@ -646,9 +646,7 @@   "ramdiskfile=8610hpcd/ramdisk.uboot\0"                         \   "fdtaddr=c00000\0"                                             \   "fdtfile=8610hpcd/mpc8610_hpcd.dtb\0"                          \ - "bdev=sda3\0"							\ - "othbootargs=diufb=15M video=fslfb:1280x1024-32@60,monitor=0\0"\ - "monitor=0-DVI\0" + "bdev=sda3\0"  #endif  #define CONFIG_NFSBOOTCOMMAND					\ diff --git a/include/configs/P1022DS.h b/include/configs/P1022DS.h index fb2a41ce2..e9622e7c0 100644 --- a/include/configs/P1022DS.h +++ b/include/configs/P1022DS.h @@ -202,6 +202,8 @@  #define CONFIG_SYS_PROMPT_HUSH_PS2 "> "  /* Video */ +#define CONFIG_FSL_DIU_FB +  #ifdef CONFIG_FSL_DIU_FB  #define CONFIG_SYS_DIU_ADDR	(CONFIG_SYS_CCSRBAR + 0x10000)  #define CONFIG_VIDEO @@ -219,7 +221,7 @@  #undef CONFIG_SYS_FLASH_EMPTY_INFO  #endif -#ifndef CONFIG_DIU +#ifndef CONFIG_FSL_DIU_FB  #define CONFIG_ATI  #endif @@ -507,9 +509,7 @@  	"diuregs=md e002c000 1d\0"			 		\  	"dium=mw e002c01c\0" 						\  	"diuerr=md e002c014 1\0" 					\ -	"othbootargs=diufb=15M video=fslfb:1280x1024-32@60,monitor=0 tty0\0" \ -	"hwconfig=esdhc;audclk:12\0"					\ -	"monitor=0-DVI\0" +	"hwconfig=esdhc;audclk:12\0"  #define CONFIG_HDBOOT					\  	"setenv bootargs root=/dev/$bdev rw "		\ diff --git a/include/configs/pdm360ng.h b/include/configs/pdm360ng.h index 37a22a7c4..831af6a7d 100644 --- a/include/configs/pdm360ng.h +++ b/include/configs/pdm360ng.h @@ -64,8 +64,6 @@  #define CONFIG_SPLASH_SCREEN  #define CONFIG_VIDEO_LOGO  #define CONFIG_VIDEO_BMP_RLE8 -#define CONFIG_VIDEO_XRES	800 -#define CONFIG_VIDEO_YRES	480  #endif  #define CONFIG_SYS_MPC512X_CLKIN	33333333	/* in Hz */ diff --git a/include/fsl_diu_fb.h b/include/fsl_diu_fb.h index 87443e10c..4c89f4b8b 100644 --- a/include/fsl_diu_fb.h +++ b/include/fsl_diu_fb.h @@ -1,6 +1,7 @@  /* - * Copyright 2007 Freescale Semiconductor, Inc. - * York Sun <yorksun@freescale.com> + * Copyright 2007, 2011 Freescale Semiconductor, Inc. + * Authors: York Sun <yorksun@freescale.com> + *          Timur Tabi <timur@freescale.com>   *   * FSL DIU Framebuffer driver   * @@ -23,38 +24,8 @@   * MA 02111-1307 USA   */ -struct fb_var_screeninfo { -	unsigned int xres;		/* visible resolution		*/ -	unsigned int yres; +int fsl_diu_init(int xres, u32 pixel_format, int gamma_fix); -	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 long smem_start;	/* Start of frame buffer mem */ -					/* (physical address) */ -	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    */ - -	char *screen_base; -	unsigned long screen_size; -}; - - -extern char *fsl_fb_open(struct fb_info **info); -int fsl_diu_init(int xres, unsigned int pixel_format, int gamma_fix); -int platform_diu_init(unsigned int *xres, unsigned int *yres); +/* Prototypes for external board-specific functions */ +int platform_diu_init(unsigned int xres, unsigned int yres, const char *port); +void diu_set_pixel_clock(unsigned int pixclock); |