diff options
Diffstat (limited to 'drivers/video')
| -rw-r--r-- | drivers/video/Makefile | 1 | ||||
| -rw-r--r-- | drivers/video/cfb_console.c | 37 | ||||
| -rw-r--r-- | drivers/video/da8xx-fb.c | 338 | ||||
| -rw-r--r-- | drivers/video/da8xx-fb.h | 116 | ||||
| -rw-r--r-- | drivers/video/exynos_mipi_dsi_common.c | 62 | ||||
| -rw-r--r-- | drivers/video/exynos_mipi_dsi_common.h | 2 | ||||
| -rw-r--r-- | drivers/video/exynos_mipi_dsi_lowlevel.c | 2 | ||||
| -rw-r--r-- | drivers/video/exynos_mipi_dsi_lowlevel.h | 2 | ||||
| -rw-r--r-- | drivers/video/l5f31188.c | 192 | ||||
| -rw-r--r-- | drivers/video/mxc_ipuv3_fb.c | 5 | ||||
| -rw-r--r-- | drivers/video/mxsfb.c | 45 | ||||
| -rw-r--r-- | drivers/video/s6e8ax0.c | 59 | ||||
| -rw-r--r-- | drivers/video/sed156x.c | 1 | 
13 files changed, 738 insertions, 124 deletions
| diff --git a/drivers/video/Makefile b/drivers/video/Makefile index f1fb26c18..6dee1e930 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -19,6 +19,7 @@ COBJS-$(CONFIG_EXYNOS_MIPI_DSIM) += exynos_mipi_dsi.o exynos_mipi_dsi_common.o \  				exynos_mipi_dsi_lowlevel.o  COBJS-$(CONFIG_EXYNOS_PWM_BL) += exynos_pwm_bl.o  COBJS-$(CONFIG_FSL_DIU_FB) += fsl_diu_fb.o videomodes.o +COBJS-$(CONFIG_L5F31188) += l5f31188.o  COBJS-$(CONFIG_MPC8XX_LCD) += mpc8xx_lcd.o  COBJS-$(CONFIG_PXA_LCD) += pxa_lcd.o  COBJS-$(CONFIG_S6E8AX0) += s6e8ax0.o diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index 96ef8f9c2..fd2885573 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -197,7 +197,6 @@  #include <linux/types.h>  #include <stdio_dev.h>  #include <video_font.h> -#include <video_font_data.h>  #if defined(CONFIG_CMD_DATE)  #include <rtc.h> @@ -431,6 +430,16 @@ static const int video_font_draw_table32[16][4] = {  	{0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff}  }; +/* + * Implement a weak default function for boards that optionally + * need to skip the cfb initialization. + */ +__weak int board_cfb_skip(void) +{ +	/* As default, don't skip cfb init */ +	return 0; +} +  static void video_drawchars(int xx, int yy, unsigned char *s, int count)  {  	u8 *cdat, *dest, *dest0; @@ -452,6 +461,10 @@ static void video_drawchars(int xx, int yy, unsigned char *s, int count)  				((u32 *) dest)[0] =  					(video_font_draw_table8[bits >> 4] &  					 eorx) ^ bgx; + +				if (VIDEO_FONT_WIDTH == 4) +					continue; +  				((u32 *) dest)[1] =  					(video_font_draw_table8[bits & 15] &  					 eorx) ^ bgx; @@ -477,6 +490,10 @@ static void video_drawchars(int xx, int yy, unsigned char *s, int count)  					SHORTSWAP32((video_font_draw_table15  						     [bits >> 4 & 3] & eorx) ^  						    bgx); + +				if (VIDEO_FONT_WIDTH == 4) +					continue; +  				((u32 *) dest)[2] =  					SHORTSWAP32((video_font_draw_table15  						     [bits >> 2 & 3] & eorx) ^ @@ -507,6 +524,10 @@ static void video_drawchars(int xx, int yy, unsigned char *s, int count)  					SHORTSWAP32((video_font_draw_table16  						     [bits >> 4 & 3] & eorx) ^  						    bgx); + +				if (VIDEO_FONT_WIDTH == 4) +					continue; +  				((u32 *) dest)[2] =  					SHORTSWAP32((video_font_draw_table16  						     [bits >> 2 & 3] & eorx) ^ @@ -541,6 +562,11 @@ static void video_drawchars(int xx, int yy, unsigned char *s, int count)  				((u32 *) dest)[3] =  					SWAP32((video_font_draw_table32  						[bits >> 4][3] & eorx) ^ bgx); + + +				if (VIDEO_FONT_WIDTH == 4) +					continue; +  				((u32 *) dest)[4] =  					SWAP32((video_font_draw_table32  						[bits & 15][0] & eorx) ^ bgx); @@ -576,6 +602,10 @@ static void video_drawchars(int xx, int yy, unsigned char *s, int count)  				((u32 *) dest)[2] =  					(video_font_draw_table24[bits >> 4][2]  					 & eorx) ^ bgx; + +				if (VIDEO_FONT_WIDTH == 4) +					continue; +  				((u32 *) dest)[3] =  					(video_font_draw_table24[bits & 15][0]  					 & eorx) ^ bgx; @@ -1996,6 +2026,8 @@ static void *video_logo(void)  		return video_fb_address + video_logo_height * VIDEO_LINE_LEN;  	}  #endif +	if (board_cfb_skip()) +		return 0;  	sprintf(info, " %s", version_string); @@ -2205,6 +2237,9 @@ int drv_video_init(void)  	/* Init video chip - returns with framebuffer cleared */  	skip_dev_init = (video_init() == -1); +	if (board_cfb_skip()) +		return 0; +  #if !defined(CONFIG_VGA_AS_SINGLE_DEVICE)  	debug("KBD: Keyboard init ...\n");  	skip_dev_init |= (VIDEO_KBD_INIT_FCT == -1); diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 373991dde..3a5f325cd 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -24,10 +24,17 @@  #include <asm/arch/hardware.h>  #include "videomodes.h" -#include <asm/arch/da8xx-fb.h> +#include "da8xx-fb.h" + +#if !defined(DA8XX_LCD_CNTL_BASE) +#define DA8XX_LCD_CNTL_BASE	DAVINCI_LCD_CNTL_BASE +#endif  #define DRIVER_NAME "da8xx_lcdc" +#define LCD_VERSION_1	1 +#define LCD_VERSION_2	2 +  /* LCD Status Register */  #define LCD_END_OF_FRAME1		(1 << 9)  #define LCD_END_OF_FRAME0		(1 << 8) @@ -42,9 +49,14 @@  #define LCD_DMA_BURST_4			0x2  #define LCD_DMA_BURST_8			0x3  #define LCD_DMA_BURST_16		0x4 -#define LCD_END_OF_FRAME_INT_ENA	(1 << 2) +#define LCD_V1_END_OF_FRAME_INT_ENA	(1 << 2) +#define LCD_V2_END_OF_FRAME0_INT_ENA	(1 << 8) +#define LCD_V2_END_OF_FRAME1_INT_ENA	(1 << 9)  #define LCD_DUAL_FRAME_BUFFER_ENABLE	(1 << 0) +#define LCD_V2_TFT_24BPP_MODE		(1 << 25) +#define LCD_V2_TFT_24BPP_UNPACK		(1 << 26) +  /* LCD Control Register */  #define LCD_CLK_DIVISOR(x)		((x) << 8)  #define LCD_RASTER_MODE			0x01 @@ -58,12 +70,20 @@  #define LCD_MONO_8BIT_MODE		(1 << 9)  #define LCD_RASTER_ORDER		(1 << 8)  #define LCD_TFT_MODE			(1 << 7) -#define LCD_UNDERFLOW_INT_ENA		(1 << 6) -#define LCD_PL_ENABLE			(1 << 4) +#define LCD_V1_UNDERFLOW_INT_ENA	(1 << 6) +#define LCD_V2_UNDERFLOW_INT_ENA	(1 << 5) +#define LCD_V1_PL_INT_ENA		(1 << 4) +#define LCD_V2_PL_INT_ENA		(1 << 6)  #define LCD_MONOCHROME_MODE		(1 << 1)  #define LCD_RASTER_ENABLE		(1 << 0)  #define LCD_TFT_ALT_ENABLE		(1 << 23)  #define LCD_STN_565_ENABLE		(1 << 24) +#define LCD_V2_DMA_CLK_EN		(1 << 2) +#define LCD_V2_LIDD_CLK_EN		(1 << 1) +#define LCD_V2_CORE_CLK_EN		(1 << 0) +#define LCD_V2_LPP_B10			26 +#define LCD_V2_TFT_24BPP_MODE		(1 << 25) +#define LCD_V2_TFT_24BPP_UNPACK		(1 << 26)  /* LCD Raster Timing 2 Register */  #define LCD_AC_BIAS_TRANSITIONS_PER_INT(x)	((x) << 16) @@ -74,6 +94,8 @@  #define LCD_INVERT_LINE_CLOCK			(1 << 21)  #define LCD_INVERT_FRAME_CLOCK			(1 << 20) +/* Clock registers available only on Version 2 */ +#define  LCD_CLK_MAIN_RESET			(1 << 3)  /* LCD Block */  struct da8xx_lcd_regs {  	u32	revid; @@ -97,6 +119,15 @@ struct da8xx_lcd_regs {  	u32	dma_frm_buf_ceiling_addr_0;  	u32	dma_frm_buf_base_addr_1;  	u32	dma_frm_buf_ceiling_addr_1; +	u32	resv1; +	u32	raw_stat; +	u32	masked_stat; +	u32	int_ena_set; +	u32	int_ena_clr; +	u32	end_of_int_ind; +	/* Clock registers available only on Version 2 */ +	u32	clk_ena; +	u32	clk_reset;  };  #define LCD_NUM_BUFFERS	1 @@ -107,6 +138,8 @@ struct da8xx_lcd_regs {  #define RIGHT_MARGIN	64  #define UPPER_MARGIN	32  #define LOWER_MARGIN	32 +#define WAIT_FOR_FRAME_DONE	true +#define NO_WAIT_FOR_FRAME_DONE	false  #define calc_fbsize() (panel.plnSizeX * panel.plnSizeY * panel.gdfBytesPP) @@ -119,6 +152,8 @@ static GraphicDevice gpanel;  static const struct da8xx_panel *lcd_panel;  static struct fb_info *da8xx_fb_info;  static int bits_x_pixel; +static unsigned int lcd_revision; +const struct lcd_ctrl_config *da8xx_lcd_cfg;  static inline unsigned int lcdc_read(u32 *addr)  { @@ -179,35 +214,24 @@ static struct fb_fix_screeninfo da8xx_fb_fix = {  	.accel = FB_ACCEL_NONE  }; -static const struct display_panel disp_panel = { -	QVGA, -	16, -	16, -	COLOR_ACTIVE, -}; - -static const struct lcd_ctrl_config lcd_cfg = { -	&disp_panel, -	.ac_bias		= 255, -	.ac_bias_intrpt		= 0, -	.dma_burst_sz		= 16, -	.bpp			= 16, -	.fdd			= 255, -	.tft_alt_mode		= 0, -	.stn_565_mode		= 0, -	.mono_8bit_mode		= 0, -	.invert_line_clock	= 1, -	.invert_frm_clock	= 1, -	.sync_edge		= 0, -	.sync_ctrl		= 1, -	.raster_order		= 0, -}; -  /* Enable the Raster Engine of the LCD Controller */  static inline void lcd_enable_raster(void)  {  	u32 reg; +	/* Put LCDC in reset for several cycles */ +	if (lcd_revision == LCD_VERSION_2) +		lcdc_write(LCD_CLK_MAIN_RESET, +			   &da8xx_fb_reg_base->clk_reset); + +	udelay(1000); +	/* Bring LCDC out of reset */ +	if (lcd_revision == LCD_VERSION_2) +		lcdc_write(0, +			   &da8xx_fb_reg_base->clk_reset); + +	udelay(1000); +  	reg = lcdc_read(&da8xx_fb_reg_base->raster_ctrl);  	if (!(reg & LCD_RASTER_ENABLE))  		lcdc_write(reg | LCD_RASTER_ENABLE, @@ -215,14 +239,40 @@ static inline void lcd_enable_raster(void)  }  /* Disable the Raster Engine of the LCD Controller */ -static inline void lcd_disable_raster(void) +static inline void lcd_disable_raster(bool wait_for_frame_done)  {  	u32 reg; +	u32 loop_cnt = 0; +	u32 stat; +	u32 i = 0; + +	if (wait_for_frame_done) +		loop_cnt = 5000;  	reg = lcdc_read(&da8xx_fb_reg_base->raster_ctrl);  	if (reg & LCD_RASTER_ENABLE)  		lcdc_write(reg & ~LCD_RASTER_ENABLE,  			&da8xx_fb_reg_base->raster_ctrl); + +	/* Wait for the current frame to complete */ +	do { +		if (lcd_revision == LCD_VERSION_1) +			stat = lcdc_read(&da8xx_fb_reg_base->stat); +		else +			stat = lcdc_read(&da8xx_fb_reg_base->raw_stat); + +		mdelay(1); +	} while (!(stat & 0x01) && (i++ < loop_cnt)); + +	if (lcd_revision == LCD_VERSION_1) +		lcdc_write(stat, &da8xx_fb_reg_base->stat); +	else +		lcdc_write(stat, &da8xx_fb_reg_base->raw_stat); + +	if ((loop_cnt != 0) && (i >= loop_cnt)) { +		printf("LCD Controller timed out\n"); +		return; +	}  }  static void lcd_blit(int load_mode, struct da8xx_fb_par *par) @@ -231,6 +281,7 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)  	u32 end;  	u32 reg_ras;  	u32 reg_dma; +	u32 reg_int;  	/* init reg to clear PLM (loading mode) fields */  	reg_ras = lcdc_read(&da8xx_fb_reg_base->raster_ctrl); @@ -243,7 +294,15 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)  		end      = par->dma_end;  		reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY); -		reg_dma |= LCD_END_OF_FRAME_INT_ENA; +		if (lcd_revision == LCD_VERSION_1) { +			reg_dma |= LCD_V1_END_OF_FRAME_INT_ENA; +		} else { +			reg_int = lcdc_read(&da8xx_fb_reg_base->int_ena_set) | +				LCD_V2_END_OF_FRAME0_INT_ENA | +				LCD_V2_END_OF_FRAME1_INT_ENA | +				LCD_V2_UNDERFLOW_INT_ENA | LCD_SYNC_LOST; +			lcdc_write(reg_int, &da8xx_fb_reg_base->int_ena_set); +		}  #if (LCD_NUM_BUFFERS == 2)  		reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE; @@ -264,7 +323,13 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)  		end      = start + par->palette_sz - 1;  		reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY); -		reg_ras |= LCD_PL_ENABLE; +		if (lcd_revision == LCD_VERSION_1) { +			reg_ras |= LCD_V1_PL_INT_ENA; +		} else { +			reg_int = lcdc_read(&da8xx_fb_reg_base->int_ena_set) | +				LCD_V2_PL_INT_ENA; +			lcdc_write(reg_int, &da8xx_fb_reg_base->int_ena_set); +		}  		lcdc_write(start, &da8xx_fb_reg_base->dma_frm_buf_base_addr_0);  		lcdc_write(end, &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_0); @@ -348,6 +413,7 @@ static void lcd_cfg_vertical_sync(int back_porch, int pulse_width,  static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)  {  	u32 reg; +	u32 reg_int;  	reg = lcdc_read(&da8xx_fb_reg_base->raster_ctrl) & ~(LCD_TFT_MODE |  						LCD_MONO_8BIT_MODE | @@ -375,7 +441,13 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)  	}  	/* enable additional interrupts here */ -	reg |= LCD_UNDERFLOW_INT_ENA; +	if (lcd_revision == LCD_VERSION_1) { +		reg |= LCD_V1_UNDERFLOW_INT_ENA; +	} else { +		reg_int = lcdc_read(&da8xx_fb_reg_base->int_ena_set) | +			LCD_V2_UNDERFLOW_INT_ENA; +		lcdc_write(reg_int, &da8xx_fb_reg_base->int_ena_set); +	}  	lcdc_write(reg, &da8xx_fb_reg_base->raster_ctrl); @@ -413,22 +485,53 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,  	/* Set the Panel Width */  	/* Pixels per line = (PPL + 1)*16 */ -	/*0x3F in bits 4..9 gives max horisontal resolution = 1024 pixels*/ -	width &= 0x3f0; +	if (lcd_revision == LCD_VERSION_1) { +		/* +		 * 0x3F in bits 4..9 gives max horisontal resolution = 1024 +		 * pixels +		 */ +		width &= 0x3f0; +	} else { +		/* +		 * 0x7F in bits 4..10 gives max horizontal resolution = 2048 +		 * pixels. +		 */ +		width &= 0x7f0; +	}  	reg = lcdc_read(&da8xx_fb_reg_base->raster_timing_0);  	reg &= 0xfffffc00; -	reg |= ((width >> 4) - 1) << 4; +	if (lcd_revision == LCD_VERSION_1) { +		reg |= ((width >> 4) - 1) << 4; +	} else { +		width = (width >> 4) - 1; +		reg |= ((width & 0x3f) << 4) | ((width & 0x40) >> 3); +	}  	lcdc_write(reg, &da8xx_fb_reg_base->raster_timing_0);  	/* Set the Panel Height */ +	/* Set bits 9:0 of Lines Per Pixel */  	reg = lcdc_read(&da8xx_fb_reg_base->raster_timing_1);  	reg = ((height - 1) & 0x3ff) | (reg & 0xfffffc00);  	lcdc_write(reg, &da8xx_fb_reg_base->raster_timing_1); +	/* Set bit 10 of Lines Per Pixel */ +	if (lcd_revision == LCD_VERSION_2) { +		reg = lcdc_read(&da8xx_fb_reg_base->raster_timing_2); +		reg |= ((height - 1) & 0x400) << 16; +		lcdc_write(reg, &da8xx_fb_reg_base->raster_timing_2); +	} +  	/* Set the Raster Order of the Frame Buffer */  	reg = lcdc_read(&da8xx_fb_reg_base->raster_ctrl) & ~(1 << 8);  	if (raster_order)  		reg |= LCD_RASTER_ORDER; + +	if (bpp == 24) +		reg |= (LCD_TFT_MODE | LCD_V2_TFT_24BPP_MODE); +	else if (bpp == 32) +		reg |= (LCD_TFT_MODE | LCD_V2_TFT_24BPP_MODE +				| LCD_V2_TFT_24BPP_UNPACK); +  	lcdc_write(reg, &da8xx_fb_reg_base->raster_ctrl);  	switch (bpp) { @@ -436,6 +539,8 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,  	case 2:  	case 4:  	case 16: +	case 24: +	case 32:  		par->palette_sz = 16 * 2;  		break; @@ -494,6 +599,23 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,  			update_hw = 1;  			palette[0] = 0x4000;  		} +	} else if (((info->var.bits_per_pixel == 32) && regno < 32) || +		   ((info->var.bits_per_pixel == 24) && regno < 24)) { +		red >>= (24 - info->var.red.length); +		red <<= info->var.red.offset; + +		green >>= (24 - info->var.green.length); +		green <<= info->var.green.offset; + +		blue >>= (24 - info->var.blue.length); +		blue <<= info->var.blue.offset; + +		par->pseudo_palette[regno] = red | green | blue; + +		if (palette[0] != 0x4000) { +			update_hw = 1; +			palette[0] = 0x4000; +		}  	}  	/* Update the palette in the h/w as needed. */ @@ -506,11 +628,18 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,  static void lcd_reset(struct da8xx_fb_par *par)  {  	/* Disable the Raster if previously Enabled */ -	lcd_disable_raster(); +	lcd_disable_raster(NO_WAIT_FOR_FRAME_DONE);  	/* DMA has to be disabled */  	lcdc_write(0, &da8xx_fb_reg_base->dma_ctrl);  	lcdc_write(0, &da8xx_fb_reg_base->raster_ctrl); + +	if (lcd_revision == LCD_VERSION_2) { +		lcdc_write(0, &da8xx_fb_reg_base->int_ena_set); +		/* Write 1 to reset */ +		lcdc_write(LCD_CLK_MAIN_RESET, &da8xx_fb_reg_base->clk_reset); +		lcdc_write(0, &da8xx_fb_reg_base->clk_reset); +	}  }  static void lcd_calc_clk_divider(struct da8xx_fb_par *par) @@ -521,12 +650,17 @@ static void lcd_calc_clk_divider(struct da8xx_fb_par *par)  	lcd_clk = clk_get(2);  	div = lcd_clk / par->pxl_clk; -	debug("LCD Clock: 0x%x Divider: 0x%x PixClk: 0x%x\n", -		lcd_clk, div, par->pxl_clk); +	debug("LCD Clock: %d Divider: %d PixClk: %d\n", +	      lcd_clk, div, par->pxl_clk);  	/* Configure the LCD clock divisor. */  	lcdc_write(LCD_CLK_DIVISOR(div) |  			(LCD_RASTER_MODE & 0x1), &da8xx_fb_reg_base->ctrl); + +	if (lcd_revision == LCD_VERSION_2) +		lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN | +				LCD_V2_CORE_CLK_EN, +				&da8xx_fb_reg_base->clk_ena);  }  static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, @@ -566,7 +700,8 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,  	if (ret < 0)  		return ret; -	if (QVGA != cfg->p_disp_panel->panel_type) +	if ((QVGA != cfg->p_disp_panel->panel_type) && +	    (WVGA != cfg->p_disp_panel->panel_type))  		return -EINVAL;  	if (cfg->bpp <= cfg->p_disp_panel->max_bpp && @@ -602,7 +737,7 @@ static void lcdc_dma_start(void)  		&da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_1);  } -static u32 lcdc_irq_handler(void) +static u32 lcdc_irq_handler_rev01(void)  {  	struct da8xx_fb_par *par = da8xx_fb_info->par;  	u32 stat = lcdc_read(&da8xx_fb_reg_base->stat); @@ -610,7 +745,7 @@ static u32 lcdc_irq_handler(void)  	if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {  		debug("LCD_SYNC_LOST\n"); -		lcd_disable_raster(); +		lcd_disable_raster(NO_WAIT_FOR_FRAME_DONE);  		lcdc_write(stat, &da8xx_fb_reg_base->stat);  		lcd_enable_raster();  		return LCD_SYNC_LOST; @@ -622,13 +757,13 @@ static u32 lcdc_irq_handler(void)  		 * interrupt via the following write to the status register. If  		 * this is done after then one gets multiple PL done interrupts.  		 */ -		lcd_disable_raster(); +		lcd_disable_raster(NO_WAIT_FOR_FRAME_DONE);  		lcdc_write(stat, &da8xx_fb_reg_base->stat);  		/* Disable PL completion inerrupt */  		reg_ras  = lcdc_read(&da8xx_fb_reg_base->raster_ctrl); -		reg_ras &= ~LCD_PL_ENABLE; +		reg_ras &= ~LCD_V1_PL_INT_ENA;  		lcdc_write(reg_ras, &da8xx_fb_reg_base->raster_ctrl);  		/* Setup and start data loading mode */ @@ -650,6 +785,66 @@ static u32 lcdc_irq_handler(void)  	return stat;  } +static u32 lcdc_irq_handler_rev02(void) +{ +	struct da8xx_fb_par *par = da8xx_fb_info->par; +	u32 stat = lcdc_read(&da8xx_fb_reg_base->masked_stat); +	u32 reg_int; + +	if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { +		debug("LCD_SYNC_LOST\n"); +		lcd_disable_raster(NO_WAIT_FOR_FRAME_DONE); +		lcdc_write(stat, &da8xx_fb_reg_base->masked_stat); +		lcd_enable_raster(); +		lcdc_write(0, &da8xx_fb_reg_base->end_of_int_ind); +		return LCD_SYNC_LOST; +	} else if (stat & LCD_PL_LOAD_DONE) { +		debug("LCD_PL_LOAD_DONE\n"); +		/* +		 * Must disable raster before changing state of any control bit. +		 * And also must be disabled before clearing the PL loading +		 * interrupt via the following write to the status register. If +		 * this is done after then one gets multiple PL done interrupts. +		 */ +		lcd_disable_raster(NO_WAIT_FOR_FRAME_DONE); + +		lcdc_write(stat, &da8xx_fb_reg_base->masked_stat); + +		/* Disable PL completion inerrupt */ +		reg_int  = lcdc_read(&da8xx_fb_reg_base->int_ena_clr) | +			(LCD_V2_PL_INT_ENA); +		lcdc_write(reg_int, &da8xx_fb_reg_base->int_ena_clr); + +		/* Setup and start data loading mode */ +		lcd_blit(LOAD_DATA, par); +		lcdc_write(0, &da8xx_fb_reg_base->end_of_int_ind); +		return LCD_PL_LOAD_DONE; +	} else { +		lcdc_write(stat, &da8xx_fb_reg_base->masked_stat); + +		if (stat & LCD_END_OF_FRAME0) +			debug("LCD_END_OF_FRAME0\n"); + +		lcdc_write(par->dma_start, +			   &da8xx_fb_reg_base->dma_frm_buf_base_addr_0); +		lcdc_write(par->dma_end, +			   &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_0); +		par->vsync_flag = 1; +		lcdc_write(0, &da8xx_fb_reg_base->end_of_int_ind); +		return LCD_END_OF_FRAME0; +	} +	lcdc_write(0, &da8xx_fb_reg_base->end_of_int_ind); +	return stat; +} + +static u32 lcdc_irq_handler(void) +{ +	if (lcd_revision == LCD_VERSION_1) +		return lcdc_irq_handler_rev01(); +	else +		return lcdc_irq_handler_rev02(); +} +  static u32 wait_for_event(u32 event)  {  	u32 timeout = 50000; @@ -673,6 +868,7 @@ void *video_hw_init(void)  {  	struct da8xx_fb_par *par;  	u32 size; +	u32 rev;  	char *p;  	if (!lcd_panel) { @@ -685,6 +881,10 @@ void *video_hw_init(void)  	gpanel.plnSizeY = lcd_panel->height;  	switch (bits_x_pixel) { +	case 32: +		gpanel.gdfBytesPP = 4; +		gpanel.gdfIndex = GDF_32BIT_X888RGB; +		break;  	case 24:  		gpanel.gdfBytesPP = 4;  		gpanel.gdfIndex = GDF_32BIT_X888RGB; @@ -699,12 +899,29 @@ void *video_hw_init(void)  		break;  	} -	da8xx_fb_reg_base = (struct da8xx_lcd_regs *)DAVINCI_LCD_CNTL_BASE; +	da8xx_fb_reg_base = (struct da8xx_lcd_regs *)DA8XX_LCD_CNTL_BASE; + +	/* Determine LCD IP Version */ +	rev = lcdc_read(&da8xx_fb_reg_base->revid); +	switch (rev) { +	case 0x4C100102: +		lcd_revision = LCD_VERSION_1; +		break; +	case 0x4F200800: +	case 0x4F201000: +		lcd_revision = LCD_VERSION_2; +		break; +	default: +		printf("Unknown PID Reg value 0x%x, defaulting to LCD revision 1\n", +		       rev); +		lcd_revision = LCD_VERSION_1; +		break; +	} -	debug("Resolution: %dx%d %x\n", -		gpanel.winSizeX, -		gpanel.winSizeY, -		lcd_cfg.bpp); +	debug("rev: 0x%x Resolution: %dx%d %d\n", rev, +	      gpanel.winSizeX, +	      gpanel.winSizeY, +	      da8xx_lcd_cfg->bpp);  	size = sizeof(struct fb_info) + sizeof(struct da8xx_fb_par);  	da8xx_fb_info = malloc(size); @@ -722,13 +939,14 @@ void *video_hw_init(void)  	par = da8xx_fb_info->par;  	par->pxl_clk = lcd_panel->pxl_clk; -	if (lcd_init(par, &lcd_cfg, lcd_panel) < 0) { +	if (lcd_init(par, da8xx_lcd_cfg, lcd_panel) < 0) {  		printf("lcd_init failed\n");  		goto err_release_fb;  	}  	/* allocate frame buffer */ -	par->vram_size = lcd_panel->width * lcd_panel->height * lcd_cfg.bpp; +	par->vram_size = lcd_panel->width * lcd_panel->height * +			da8xx_lcd_cfg->bpp;  	par->vram_size = par->vram_size * LCD_NUM_BUFFERS / 8;  	par->vram_virt = malloc(par->vram_size); @@ -741,12 +959,13 @@ void *video_hw_init(void)  		printf("GLCD: malloc for frame buffer failed\n");  		goto err_release_fb;  	} +	gd->fb_base = (int)par->vram_virt;  	gpanel.frameAdrs = (unsigned int)par->vram_virt;  	da8xx_fb_info->screen_base = (char *) par->vram_virt;  	da8xx_fb_fix.smem_start	= gpanel.frameAdrs;  	da8xx_fb_fix.smem_len = par->vram_size; -	da8xx_fb_fix.line_length = (lcd_panel->width * lcd_cfg.bpp) / 8; +	da8xx_fb_fix.line_length = (lcd_panel->width * da8xx_lcd_cfg->bpp) / 8;  	par->dma_start = par->vram_phys;  	par->dma_end   = par->dma_start + lcd_panel->height * @@ -762,7 +981,7 @@ void *video_hw_init(void)  	par->p_palette_base = (unsigned int)par->v_palette_base;  	/* Initialize par */ -	da8xx_fb_info->var.bits_per_pixel = lcd_cfg.bpp; +	da8xx_fb_info->var.bits_per_pixel = da8xx_lcd_cfg->bpp;  	da8xx_fb_var.xres = lcd_panel->width;  	da8xx_fb_var.xres_virtual = lcd_panel->width; @@ -771,8 +990,8 @@ void *video_hw_init(void)  	da8xx_fb_var.yres_virtual = lcd_panel->height * LCD_NUM_BUFFERS;  	da8xx_fb_var.grayscale = -	    lcd_cfg.p_disp_panel->panel_shade == MONOCHROME ? 1 : 0; -	da8xx_fb_var.bits_per_pixel = lcd_cfg.bpp; +	    da8xx_lcd_cfg->p_disp_panel->panel_shade == MONOCHROME ? 1 : 0; +	da8xx_fb_var.bits_per_pixel = da8xx_lcd_cfg->bpp;  	da8xx_fb_var.hsync_len = lcd_panel->hsw;  	da8xx_fb_var.vsync_len = lcd_panel->vsw; @@ -787,8 +1006,11 @@ void *video_hw_init(void)  	/* Clear interrupt */  	memset((void *)par->vram_virt, 0, par->vram_size); -	lcd_disable_raster(); -	lcdc_write(0xFFFF, &da8xx_fb_reg_base->stat); +	lcd_disable_raster(NO_WAIT_FOR_FRAME_DONE); +	if (lcd_revision == LCD_VERSION_1) +		lcdc_write(0xFFFF, &da8xx_fb_reg_base->stat); +	else +		lcdc_write(0xFFFF, &da8xx_fb_reg_base->masked_stat);  	debug("Palette at 0x%x size %d\n", par->p_palette_base,  		par->palette_sz);  	lcdc_dma_start(); @@ -823,8 +1045,10 @@ void video_set_lut(unsigned int index,	/* color number */  	return;  } -void da8xx_video_init(const struct da8xx_panel *panel, int bits_pixel) +void da8xx_video_init(const struct da8xx_panel *panel, +		      const struct lcd_ctrl_config *lcd_cfg, int bits_pixel)  {  	lcd_panel = panel; +	da8xx_lcd_cfg = lcd_cfg;  	bits_x_pixel = bits_pixel;  } diff --git a/drivers/video/da8xx-fb.h b/drivers/video/da8xx-fb.h new file mode 100644 index 000000000..6447a4047 --- /dev/null +++ b/drivers/video/da8xx-fb.h @@ -0,0 +1,116 @@ +/* + * Porting to u-boot: + * + * (C) Copyright 2011 + * Stefano Babic, DENX Software Engineering, sbabic@denx.de. + * + * Copyright (C) 2008-2009 MontaVista Software Inc. + * Copyright (C) 2008-2009 Texas Instruments Inc + * + * Based on the LCD driver for TI Avalanche processors written by + * Ajay Singh and Shalom Hai. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#ifndef DA8XX_FB_H +#define DA8XX_FB_H + +enum panel_type { +	QVGA = 0, +	WVGA +}; + +enum panel_shade { +	MONOCHROME = 0, +	COLOR_ACTIVE, +	COLOR_PASSIVE, +}; + +enum raster_load_mode { +	LOAD_DATA = 1, +	LOAD_PALETTE, +}; + +struct display_panel { +	enum panel_type panel_type; /* QVGA */ +	int max_bpp; +	int min_bpp; +	enum panel_shade panel_shade; +}; + +struct da8xx_panel { +	const char	name[25];	/* Full name <vendor>_<model> */ +	unsigned short	width; +	unsigned short	height; +	int		hfp;		/* Horizontal front porch */ +	int		hbp;		/* Horizontal back porch */ +	int		hsw;		/* Horizontal Sync Pulse Width */ +	int		vfp;		/* Vertical front porch */ +	int		vbp;		/* Vertical back porch */ +	int		vsw;		/* Vertical Sync Pulse Width */ +	unsigned int	pxl_clk;	/* Pixel clock */ +	unsigned char	invert_pxl_clk;	/* Invert Pixel clock */ +}; + +struct da8xx_lcdc_platform_data { +	const char manu_name[10]; +	void *controller_data; +	const char type[25]; +	void (*panel_power_ctrl)(int); +}; + +struct lcd_ctrl_config { +	const struct display_panel *p_disp_panel; + +	/* AC Bias Pin Frequency */ +	int ac_bias; + +	/* AC Bias Pin Transitions per Interrupt */ +	int ac_bias_intrpt; + +	/* DMA burst size */ +	int dma_burst_sz; + +	/* Bits per pixel */ +	int bpp; + +	/* FIFO DMA Request Delay */ +	int fdd; + +	/* TFT Alternative Signal Mapping (Only for active) */ +	unsigned char tft_alt_mode; + +	/* 12 Bit Per Pixel (5-6-5) Mode (Only for passive) */ +	unsigned char stn_565_mode; + +	/* Mono 8-bit Mode: 1=D0-D7 or 0=D0-D3 */ +	unsigned char mono_8bit_mode; + +	/* Invert line clock */ +	unsigned char invert_line_clock; + +	/* Invert frame clock  */ +	unsigned char invert_frm_clock; + +	/* Horizontal and Vertical Sync Edge: 0=rising 1=falling */ +	unsigned char sync_edge; + +	/* Horizontal and Vertical Sync: Control: 0=ignore */ +	unsigned char sync_ctrl; + +	/* Raster Data Order Select: 1=Most-to-least 0=Least-to-most */ +	unsigned char raster_order; +}; + +struct lcd_sync_arg { +	int back_porch; +	int front_porch; +	int pulse_width; +}; + +void da8xx_video_init(const struct da8xx_panel *panel, +		      const struct lcd_ctrl_config *lcd_cfg, +		      int bits_pixel); + +#endif  /* ifndef DA8XX_FB_H */ diff --git a/drivers/video/exynos_mipi_dsi_common.c b/drivers/video/exynos_mipi_dsi_common.c index 2cc847f6e..97e12484f 100644 --- a/drivers/video/exynos_mipi_dsi_common.c +++ b/drivers/video/exynos_mipi_dsi_common.c @@ -50,7 +50,7 @@ static unsigned int dpll_table[15] = {  };  static void exynos_mipi_dsi_long_data_wr(struct mipi_dsim_device *dsim, -		unsigned int data0, unsigned int data1) +		const unsigned char *data0, unsigned int data1)  {  	unsigned int data_cnt = 0, payload = 0; @@ -62,42 +62,40 @@ static void exynos_mipi_dsi_long_data_wr(struct mipi_dsim_device *dsim,  		 */  		if ((data1 - data_cnt) < 4) {  			if ((data1 - data_cnt) == 3) { -				payload = *(u8 *)(data0 + data_cnt) | -					(*(u8 *)(data0 + (data_cnt + 1))) << 8 | -					(*(u8 *)(data0 + (data_cnt + 2))) << 16; +				payload = data0[data_cnt] | +					data0[data_cnt + 1] << 8 | +					data0[data_cnt + 2] << 16;  			debug("count = 3 payload = %x, %x %x %x\n", -				payload, *(u8 *)(data0 + data_cnt), -				*(u8 *)(data0 + (data_cnt + 1)), -				*(u8 *)(data0 + (data_cnt + 2))); +				payload, data0[data_cnt], +				data0[data_cnt + 1], +				data0[data_cnt + 2]);  			} else if ((data1 - data_cnt) == 2) { -				payload = *(u8 *)(data0 + data_cnt) | -					(*(u8 *)(data0 + (data_cnt + 1))) << 8; +				payload = data0[data_cnt] | +					data0[data_cnt + 1] << 8;  			debug("count = 2 payload = %x, %x %x\n", payload, -				*(u8 *)(data0 + data_cnt), -				*(u8 *)(data0 + (data_cnt + 1))); +				data0[data_cnt], data0[data_cnt + 1]);  			} else if ((data1 - data_cnt) == 1) { -				payload = *(u8 *)(data0 + data_cnt); +				payload = data0[data_cnt];  			}  		} else {  			/* send 4bytes per one time. */ -			payload = *(u8 *)(data0 + data_cnt) | -				(*(u8 *)(data0 + (data_cnt + 1))) << 8 | -				(*(u8 *)(data0 + (data_cnt + 2))) << 16 | -				(*(u8 *)(data0 + (data_cnt + 3))) << 24; +			payload = data0[data_cnt] | +				data0[data_cnt + 1] << 8 | +				data0[data_cnt + 2] << 16 | +				data0[data_cnt + 3] << 24;  			debug("count = 4 payload = %x, %x %x %x %x\n",  				payload, *(u8 *)(data0 + data_cnt), -				*(u8 *)(data0 + (data_cnt + 1)), -				*(u8 *)(data0 + (data_cnt + 2)), -				*(u8 *)(data0 + (data_cnt + 3))); - +				data0[data_cnt + 1], +				data0[data_cnt + 2], +				data0[data_cnt + 3]);  		}  		exynos_mipi_dsi_wr_tx_data(dsim, payload);  	}  }  int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id, -	unsigned int data0, unsigned int data1) +	const unsigned char *data0, unsigned int data1)  {  	unsigned int timeout = TRY_GET_FIFO_TIMEOUT;  	unsigned long delay_val, delay; @@ -136,8 +134,8 @@ int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id,  	case MIPI_DSI_DCS_SHORT_WRITE_PARAM:  	case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE:  		debug("data0 = %x data1 = %x\n", -				data0, data1); -		exynos_mipi_dsi_wr_tx_header(dsim, data_id, data0, data1); +				data0[0], data0[1]); +		exynos_mipi_dsi_wr_tx_header(dsim, data_id, data0[0], data0[1]);  		if (check_rx_ack) {  			/* process response func should be implemented */  			return 0; @@ -150,7 +148,7 @@ int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id,  	case MIPI_DSI_COLOR_MODE_ON:  	case MIPI_DSI_SHUTDOWN_PERIPHERAL:  	case MIPI_DSI_TURN_ON_PERIPHERAL: -		exynos_mipi_dsi_wr_tx_header(dsim, data_id, data0, data1); +		exynos_mipi_dsi_wr_tx_header(dsim, data_id, data0[0], data0[1]);  		if (check_rx_ack) {  			/* process response func should be implemented. */  			return 0; @@ -172,7 +170,7 @@ int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id,  	case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:  	case MIPI_DSI_DCS_READ:  		exynos_mipi_dsi_clear_all_interrupt(dsim); -		exynos_mipi_dsi_wr_tx_header(dsim, data_id, data0, data1); +		exynos_mipi_dsi_wr_tx_header(dsim, data_id, data0[0], data0[1]);  		/* process response func should be implemented. */  		return 0; @@ -183,21 +181,19 @@ int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id,  	case MIPI_DSI_GENERIC_LONG_WRITE:  	case MIPI_DSI_DCS_LONG_WRITE:  	{ -		unsigned int data_cnt = 0, payload = 0; +		unsigned int payload = 0;  		/* if data count is less then 4, then send 3bytes data.  */  		if (data1 < 4) { -			payload = *(u8 *)(data0) | -				*(u8 *)(data0 + 1) << 8 | -				*(u8 *)(data0 + 2) << 16; +			payload = data0[0] | +				data0[1] << 8 | +				data0[2] << 16;  			exynos_mipi_dsi_wr_tx_data(dsim, payload);  			debug("count = %d payload = %x,%x %x %x\n", -				data1, payload, -				*(u8 *)(data0 + data_cnt), -				*(u8 *)(data0 + (data_cnt + 1)), -				*(u8 *)(data0 + (data_cnt + 2))); +				data1, payload, data0[0], +				data0[1], data0[2]);  		} else {  			/* in case that data count is more then 4 */  			exynos_mipi_dsi_long_data_wr(dsim, data0, data1); diff --git a/drivers/video/exynos_mipi_dsi_common.h b/drivers/video/exynos_mipi_dsi_common.h index 318c7ecec..ef6510abd 100644 --- a/drivers/video/exynos_mipi_dsi_common.h +++ b/drivers/video/exynos_mipi_dsi_common.h @@ -13,7 +13,7 @@  #define _EXYNOS_MIPI_DSI_COMMON_H  int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id, -	unsigned int data0, unsigned int data1); +	const unsigned char *data0, unsigned int data1);  int exynos_mipi_dsi_pll_on(struct mipi_dsim_device *dsim, unsigned int enable);  unsigned long exynos_mipi_dsi_change_pll(struct mipi_dsim_device *dsim,  	unsigned int pre_divider, unsigned int main_divider, diff --git a/drivers/video/exynos_mipi_dsi_lowlevel.c b/drivers/video/exynos_mipi_dsi_lowlevel.c index b47eee45d..1313bcea4 100644 --- a/drivers/video/exynos_mipi_dsi_lowlevel.c +++ b/drivers/video/exynos_mipi_dsi_lowlevel.c @@ -600,7 +600,7 @@ unsigned int exynos_mipi_dsi_get_fifo_state(struct mipi_dsim_device *dsim)  }  void exynos_mipi_dsi_wr_tx_header(struct mipi_dsim_device *dsim, -	unsigned int di, unsigned int data0, unsigned int data1) +	unsigned int di, const unsigned char data0, const unsigned char data1)  {  	struct exynos_mipi_dsim *mipi_dsim =  		(struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); diff --git a/drivers/video/exynos_mipi_dsi_lowlevel.h b/drivers/video/exynos_mipi_dsi_lowlevel.h index 8a45954e9..59f6ce09e 100644 --- a/drivers/video/exynos_mipi_dsi_lowlevel.h +++ b/drivers/video/exynos_mipi_dsi_lowlevel.h @@ -91,7 +91,7 @@ unsigned int _exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device  						*dsim);  void _exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim);  void exynos_mipi_dsi_wr_tx_header(struct mipi_dsim_device *dsim, -		unsigned int di, unsigned int data0, unsigned int data1); +		unsigned int di, const unsigned char data0, const unsigned char data1);  void exynos_mipi_dsi_wr_tx_data(struct mipi_dsim_device *dsim,  		unsigned int tx_data); diff --git a/drivers/video/l5f31188.c b/drivers/video/l5f31188.c new file mode 100644 index 000000000..3312dcfb3 --- /dev/null +++ b/drivers/video/l5f31188.c @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved. + * Hyungwon Hwang <human.hwang@samsung.com> + * + * SPDX-License-Identifier:      GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/mipi_dsim.h> + +#define SCAN_FROM_LEFT_TO_RIGHT 0 +#define SCAN_FROM_RIGHT_TO_LEFT 1 +#define SCAN_FROM_TOP_TO_BOTTOM 0 +#define SCAN_FROM_BOTTOM_TO_TOP 1 + +static void l5f31188_sleep_in(struct mipi_dsim_device *dev, +		struct mipi_dsim_master_ops *ops) +{ +	ops->cmd_write(dev, MIPI_DSI_DCS_SHORT_WRITE, 0x10, 0x00); +} + +static void l5f31188_sleep_out(struct mipi_dsim_device *dev, +		struct mipi_dsim_master_ops *ops) +{ +	ops->cmd_write(dev, MIPI_DSI_DCS_SHORT_WRITE, 0x11, 0x00); +} + +static void l5f31188_set_gamma(struct mipi_dsim_device *dev, +		struct mipi_dsim_master_ops *ops) +{ +	ops->cmd_write(dev, MIPI_DSI_DCS_SHORT_WRITE, 0x26, 0x00); +} + +static void l5f31188_display_off(struct mipi_dsim_device *dev, +		struct mipi_dsim_master_ops *ops) +{ +	ops->cmd_write(dev, MIPI_DSI_DCS_SHORT_WRITE, 0x28, 0x00); +} + +static void l5f31188_display_on(struct mipi_dsim_device *dev, +		struct mipi_dsim_master_ops *ops) +{ +	ops->cmd_write(dev, MIPI_DSI_DCS_SHORT_WRITE, 0x29, 0x00); +} + +static void l5f31188_ctl_memory_access(struct mipi_dsim_device *dev, +		struct mipi_dsim_master_ops *ops, +		int h_direction, int v_direction) +{ +	ops->cmd_write(dev, MIPI_DSI_DCS_SHORT_WRITE_PARAM, 0x36, +			(((h_direction & 0x1) << 1) | (v_direction & 0x1))); +} + +static void l5f31188_set_pixel_format(struct mipi_dsim_device *dev, +		struct mipi_dsim_master_ops *ops) +{ +	ops->cmd_write(dev, MIPI_DSI_DCS_SHORT_WRITE_PARAM, 0x3A, 0x70); +} + +static void l5f31188_write_disbv(struct mipi_dsim_device *dev, +		struct mipi_dsim_master_ops *ops, unsigned int brightness) +{ +	ops->cmd_write(dev, MIPI_DSI_DCS_SHORT_WRITE_PARAM, 0x51, brightness); +} + +static void l5f31188_write_ctrld(struct mipi_dsim_device *dev, +		struct mipi_dsim_master_ops *ops) +{ +	ops->cmd_write(dev, MIPI_DSI_DCS_SHORT_WRITE_PARAM, 0x53, 0x2C); +} + +static void l5f31188_write_cabc(struct mipi_dsim_device *dev, +		struct mipi_dsim_master_ops *ops, +			unsigned int wm_mode) +{ +	ops->cmd_write(dev, MIPI_DSI_DCS_SHORT_WRITE_PARAM, 0x55, wm_mode); +} + +static void l5f31188_write_cabcmb(struct mipi_dsim_device *dev, +		struct mipi_dsim_master_ops *ops, unsigned int min_brightness) +{ +	ops->cmd_write(dev, MIPI_DSI_DCS_SHORT_WRITE_PARAM, 0x5E, +			min_brightness); +} + +static void l5f31188_set_extension(struct mipi_dsim_device *dev, +		struct mipi_dsim_master_ops *ops) +{ +	const unsigned char data_to_send[] = { +		0xB9, 0xFF, 0x83, 0x94 +	}; + +	ops->cmd_write(dev, MIPI_DSI_DCS_LONG_WRITE, +			(unsigned int)data_to_send, ARRAY_SIZE(data_to_send)); +} + +static void l5f31188_set_dgc_lut(struct mipi_dsim_device *dev, +		struct mipi_dsim_master_ops *ops) +{ +	const unsigned char data_to_send[] = { +		0xC1, 0x01, 0x00, 0x04, 0x0E, 0x18, 0x1E, 0x26, +		0x2F, 0x36, 0x3E, 0x47, 0x4E, 0x56, 0x5D, 0x65, +		0x6D, 0x75, 0x7D, 0x84, 0x8C, 0x94, 0x9C, 0xA4, +		0xAD, 0xB5, 0xBD, 0xC5, 0xCC, 0xD4, 0xDE, 0xE5, +		0xEE, 0xF7, 0xFF, 0x3F, 0x9A, 0xCE, 0xD4, 0x21, +		0xA1, 0x26, 0x54, 0x00, 0x00, 0x04, 0x0E, 0x19, +		0x1F, 0x27, 0x30, 0x37, 0x40, 0x48, 0x50, 0x58, +		0x60, 0x67, 0x6F, 0x77, 0x7F, 0x87, 0x8F, 0x97, +		0x9F, 0xA7, 0xB0, 0xB8, 0xC0, 0xC8, 0xCE, 0xD8, +		0xE0, 0xE7, 0xF0, 0xF7, 0xFF, 0x3C, 0xEB, 0xFD, +		0x2F, 0x66, 0xA8, 0x2C, 0x46, 0x00, 0x00, 0x04, +		0x0E, 0x18, 0x1E, 0x26, 0x30, 0x38, 0x41, 0x4A, +		0x52, 0x5A, 0x62, 0x6B, 0x73, 0x7B, 0x83, 0x8C, +		0x94, 0x9C, 0xA5, 0xAD, 0xB6, 0xBD, 0xC5, 0xCC, +		0xD4, 0xDD, 0xE3, 0xEB, 0xF2, 0xF9, 0xFF, 0x3F, +		0xA4, 0x8A, 0x8F, 0xC7, 0x33, 0xF5, 0xE9, 0x00 +	}; +	ops->cmd_write(dev, MIPI_DSI_DCS_LONG_WRITE, +			(unsigned int)data_to_send, ARRAY_SIZE(data_to_send)); +} + +static void l5f31188_set_tcon(struct mipi_dsim_device *dev, +		struct mipi_dsim_master_ops *ops) +{ +	const unsigned char data_to_send[] = { +		0xC7, 0x00, 0x20 +	}; +	ops->cmd_write(dev, MIPI_DSI_DCS_LONG_WRITE, +			(unsigned int)data_to_send, ARRAY_SIZE(data_to_send)); +} + +static void l5f31188_set_ptba(struct mipi_dsim_device *dev, +		struct mipi_dsim_master_ops *ops) +{ +	const unsigned char data_to_send[] = { +		0xBF, 0x06, 0x10 +	}; +	ops->cmd_write(dev, MIPI_DSI_DCS_LONG_WRITE, +			(unsigned int)data_to_send, ARRAY_SIZE(data_to_send)); +} + +static void l5f31188_set_eco(struct mipi_dsim_device *dev, +		struct mipi_dsim_master_ops *ops) +{ +	ops->cmd_write(dev, MIPI_DSI_DCS_SHORT_WRITE_PARAM, 0xC6, 0x0C); +} + +static int l5f31188_panel_init(struct mipi_dsim_device *dev) +{ +	struct mipi_dsim_master_ops *ops = dev->master_ops; + +	l5f31188_set_extension(dev, ops); +	l5f31188_set_dgc_lut(dev, ops); + +	l5f31188_set_eco(dev, ops); +	l5f31188_set_tcon(dev, ops); +	l5f31188_set_ptba(dev, ops); +	l5f31188_set_gamma(dev, ops); +	l5f31188_ctl_memory_access(dev, ops, +			SCAN_FROM_LEFT_TO_RIGHT, SCAN_FROM_TOP_TO_BOTTOM); +	l5f31188_set_pixel_format(dev, ops); +	l5f31188_write_disbv(dev, ops, 0xFF); +	l5f31188_write_ctrld(dev, ops); +	l5f31188_write_cabc(dev, ops, 0x0); +	l5f31188_write_cabcmb(dev, ops, 0x0); + +	l5f31188_sleep_out(dev, ops); + +	/* 120 msec */ +	udelay(120 * 1000); + +	return 0; +} + +static void l5f31188_display_enable(struct mipi_dsim_device *dev) +{ +	struct mipi_dsim_master_ops *ops = dev->master_ops; +	l5f31188_display_on(dev, ops); +} + +static struct mipi_dsim_lcd_driver l5f31188_dsim_ddi_driver = { +	.name = "l5f31188", +	.id = -1, + +	.mipi_panel_init = l5f31188_panel_init, +	.mipi_display_on = l5f31188_display_enable, +}; + +void l5f31188_init(void) +{ +	exynos_mipi_dsi_register_lcd_driver(&l5f31188_dsim_ddi_driver); +} diff --git a/drivers/video/mxc_ipuv3_fb.c b/drivers/video/mxc_ipuv3_fb.c index fd74370ed..3e21fb230 100644 --- a/drivers/video/mxc_ipuv3_fb.c +++ b/drivers/video/mxc_ipuv3_fb.c @@ -399,8 +399,9 @@ static int mxcfb_map_video_memory(struct fb_info *fbi)  		fbi->fix.smem_len = fbi->var.yres_virtual *  				    fbi->fix.line_length;  	} - -	fbi->screen_base = (char *)malloc(fbi->fix.smem_len); +	fbi->fix.smem_len = roundup(fbi->fix.smem_len, ARCH_DMA_MINALIGN); +	fbi->screen_base = (char *)memalign(ARCH_DMA_MINALIGN, +					    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"); diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index 6bf9fc503..03b0f88ac 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c @@ -15,11 +15,25 @@  #include <asm/errno.h>  #include <asm/io.h> +#include <asm/imx-common/dma.h> +  #include "videomodes.h"  #define	PS2KHZ(ps)	(1000000000UL / (ps))  static GraphicDevice panel; +struct mxs_dma_desc desc; + +/** + * mxsfb_system_setup() - Fine-tune LCDIF configuration + * + * This function is used to adjust the LCDIF configuration. This is usually + * needed when driving the controller in System-Mode to operate an 8080 or + * 6800 connected SmartLCD. + */ +__weak void mxsfb_system_setup(void) +{ +}  /*   * DENX M28EVK: @@ -75,6 +89,9 @@ static void mxs_lcd_init(GraphicDevice *panel,  	writel(valid_data << LCDIF_CTRL1_BYTE_PACKING_FORMAT_OFFSET,  		®s->hw_lcdif_ctrl1); + +	mxsfb_system_setup(); +  	writel((mode->yres << LCDIF_TRANSFER_COUNT_V_COUNT_OFFSET) | mode->xres,  		®s->hw_lcdif_transfer_count); @@ -102,8 +119,10 @@ static void mxs_lcd_init(GraphicDevice *panel,  	/* Flush FIFO first */  	writel(LCDIF_CTRL1_FIFO_CLEAR, ®s->hw_lcdif_ctrl1_set); +#ifndef CONFIG_VIDEO_MXS_MODE_SYSTEM  	/* Sync signals ON */  	setbits_le32(®s->hw_lcdif_vdctrl4, LCDIF_VDCTRL4_SYNC_SIGNALS_ON); +#endif  	/* FIFO cleared */  	writel(LCDIF_CTRL1_FIFO_CLEAR, ®s->hw_lcdif_ctrl1_clr); @@ -161,7 +180,8 @@ void *video_hw_init(void)  	panel.memSize = mode.xres * mode.yres * panel.gdfBytesPP;  	/* Allocate framebuffer */ -	fb = malloc(panel.memSize); +	fb = memalign(ARCH_DMA_MINALIGN, +		      roundup(panel.memSize, ARCH_DMA_MINALIGN));  	if (!fb) {  		printf("MXSFB: Error allocating framebuffer!\n");  		return NULL; @@ -177,5 +197,28 @@ void *video_hw_init(void)  	/* Start framebuffer */  	mxs_lcd_init(&panel, &mode, bpp); +#ifdef CONFIG_VIDEO_MXS_MODE_SYSTEM +	/* +	 * If the LCD runs in system mode, the LCD refresh has to be triggered +	 * manually by setting the RUN bit in HW_LCDIF_CTRL register. To avoid +	 * having to set this bit manually after every single change in the +	 * framebuffer memory, we set up specially crafted circular DMA, which +	 * sets the RUN bit, then waits until it gets cleared and repeats this +	 * infinitelly. This way, we get smooth continuous updates of the LCD. +	 */ +	struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE; + +	memset(&desc, 0, sizeof(struct mxs_dma_desc)); +	desc.address = (dma_addr_t)&desc; +	desc.cmd.data = MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN | +			MXS_DMA_DESC_WAIT4END | +			(1 << MXS_DMA_DESC_PIO_WORDS_OFFSET); +	desc.cmd.pio_words[0] = readl(®s->hw_lcdif_ctrl) | LCDIF_CTRL_RUN; +	desc.cmd.next = (uint32_t)&desc.cmd; + +	/* Execute the DMA chain. */ +	mxs_dma_circ_start(MXS_DMA_CHANNEL_AHB_APBH_LCDIF, &desc); +#endif +  	return (void *)&panel;  } diff --git a/drivers/video/s6e8ax0.c b/drivers/video/s6e8ax0.c index fc092522b..0e97f511f 100644 --- a/drivers/video/s6e8ax0.c +++ b/drivers/video/s6e8ax0.c @@ -34,11 +34,11 @@ static void s6e8ax0_panel_cond(struct mipi_dsim_device *dsim_dev)  	if (reverse) {  		ops->cmd_write(dsim_dev, MIPI_DSI_DCS_LONG_WRITE, -			(unsigned int)data_to_send_reverse, +			data_to_send_reverse,  			ARRAY_SIZE(data_to_send_reverse));  	} else {  		ops->cmd_write(dsim_dev, MIPI_DSI_DCS_LONG_WRITE, -			(unsigned int)data_to_send, ARRAY_SIZE(data_to_send)); +			data_to_send, ARRAY_SIZE(data_to_send));  	}  } @@ -50,8 +50,7 @@ static void s6e8ax0_display_cond(struct mipi_dsim_device *dsim_dev)  	};  	ops->cmd_write(dsim_dev, MIPI_DSI_DCS_LONG_WRITE, -			(unsigned int)data_to_send, -			ARRAY_SIZE(data_to_send)); +			data_to_send, ARRAY_SIZE(data_to_send));  }  static void s6e8ax0_gamma_cond(struct mipi_dsim_device *dsim_dev) @@ -65,15 +64,18 @@ static void s6e8ax0_gamma_cond(struct mipi_dsim_device *dsim_dev)  	};  	ops->cmd_write(dsim_dev, MIPI_DSI_DCS_LONG_WRITE, -			(unsigned int)data_to_send, -			ARRAY_SIZE(data_to_send)); +			data_to_send, ARRAY_SIZE(data_to_send));  }  static void s6e8ax0_gamma_update(struct mipi_dsim_device *dsim_dev)  {  	struct mipi_dsim_master_ops *ops = dsim_dev->master_ops; +	static const unsigned char data_to_send[] = { +		0xf7, 0x03 +	}; -	ops->cmd_write(dsim_dev, MIPI_DSI_DCS_SHORT_WRITE_PARAM, 0xf7, 0x3); +	ops->cmd_write(dsim_dev, MIPI_DSI_DCS_SHORT_WRITE_PARAM, data_to_send, +			ARRAY_SIZE(data_to_send));  }  static void s6e8ax0_etc_source_control(struct mipi_dsim_device *dsim_dev) @@ -84,8 +86,7 @@ static void s6e8ax0_etc_source_control(struct mipi_dsim_device *dsim_dev)  	};  	ops->cmd_write(dsim_dev, MIPI_DSI_DCS_LONG_WRITE, -			(unsigned int)data_to_send, -			ARRAY_SIZE(data_to_send)); +			data_to_send, ARRAY_SIZE(data_to_send));  }  static void s6e8ax0_etc_pentile_control(struct mipi_dsim_device *dsim_dev) @@ -97,8 +98,7 @@ static void s6e8ax0_etc_pentile_control(struct mipi_dsim_device *dsim_dev)  	};  	ops->cmd_write(dsim_dev, MIPI_DSI_DCS_LONG_WRITE, -			(unsigned int)data_to_send, -			ARRAY_SIZE(data_to_send)); +			data_to_send, ARRAY_SIZE(data_to_send));  }  static void s6e8ax0_etc_mipi_control1(struct mipi_dsim_device *dsim_dev) @@ -109,8 +109,7 @@ static void s6e8ax0_etc_mipi_control1(struct mipi_dsim_device *dsim_dev)  	};  	ops->cmd_write(dsim_dev, MIPI_DSI_DCS_LONG_WRITE, -			(unsigned int)data_to_send, -			ARRAY_SIZE(data_to_send)); +			data_to_send, ARRAY_SIZE(data_to_send));  }  static void s6e8ax0_etc_mipi_control2(struct mipi_dsim_device *dsim_dev) @@ -121,8 +120,7 @@ static void s6e8ax0_etc_mipi_control2(struct mipi_dsim_device *dsim_dev)  	};  	ops->cmd_write(dsim_dev, MIPI_DSI_DCS_LONG_WRITE, -			(unsigned int)data_to_send, -			ARRAY_SIZE(data_to_send)); +			data_to_send, ARRAY_SIZE(data_to_send));  }  static void s6e8ax0_etc_power_control(struct mipi_dsim_device *dsim_dev) @@ -133,14 +131,18 @@ static void s6e8ax0_etc_power_control(struct mipi_dsim_device *dsim_dev)  	};  	ops->cmd_write(dsim_dev, MIPI_DSI_DCS_LONG_WRITE, -		(unsigned int)data_to_send, ARRAY_SIZE(data_to_send)); +		data_to_send, ARRAY_SIZE(data_to_send));  }  static void s6e8ax0_etc_mipi_control3(struct mipi_dsim_device *dsim_dev)  {  	struct mipi_dsim_master_ops *ops = dsim_dev->master_ops; +	static const unsigned char data_to_send[] = { +		0xe3, 0x40 +	}; -	ops->cmd_write(dsim_dev, MIPI_DSI_DCS_SHORT_WRITE_PARAM, 0xe3, 0x40); +	ops->cmd_write(dsim_dev, MIPI_DSI_DCS_SHORT_WRITE_PARAM, data_to_send, +		       ARRAY_SIZE(data_to_send));  }  static void s6e8ax0_etc_mipi_control4(struct mipi_dsim_device *dsim_dev) @@ -151,7 +153,7 @@ static void s6e8ax0_etc_mipi_control4(struct mipi_dsim_device *dsim_dev)  	};  	ops->cmd_write(dsim_dev, MIPI_DSI_DCS_LONG_WRITE, -		(unsigned int)data_to_send, ARRAY_SIZE(data_to_send)); +		data_to_send, ARRAY_SIZE(data_to_send));  }  static void s6e8ax0_elvss_set(struct mipi_dsim_device *dsim_dev) @@ -162,24 +164,29 @@ static void s6e8ax0_elvss_set(struct mipi_dsim_device *dsim_dev)  	};  	ops->cmd_write(dsim_dev, MIPI_DSI_DCS_LONG_WRITE, -			(unsigned int)data_to_send, -			ARRAY_SIZE(data_to_send)); +			data_to_send, ARRAY_SIZE(data_to_send));  }  static void s6e8ax0_display_on(struct mipi_dsim_device *dsim_dev)  {  	struct mipi_dsim_master_ops *ops = dsim_dev->master_ops; +	static const unsigned char data_to_send[] = { +		0x29, 0x00 +	}; -	ops->cmd_write(dsim_dev, -		MIPI_DSI_DCS_SHORT_WRITE, 0x29, 0x00); +	ops->cmd_write(dsim_dev, MIPI_DSI_DCS_SHORT_WRITE, data_to_send, +		       ARRAY_SIZE(data_to_send));  }  static void s6e8ax0_sleep_out(struct mipi_dsim_device *dsim_dev)  {  	struct mipi_dsim_master_ops *ops = dsim_dev->master_ops; +	static const unsigned char data_to_send[] = { +		0x11, 0x00 +	}; -	ops->cmd_write(dsim_dev, -		MIPI_DSI_DCS_SHORT_WRITE, 0x11, 0x00); +	ops->cmd_write(dsim_dev, MIPI_DSI_DCS_SHORT_WRITE, data_to_send, +		       ARRAY_SIZE(data_to_send));  }  static void s6e8ax0_apply_level1_key(struct mipi_dsim_device *dsim_dev) @@ -190,7 +197,7 @@ static void s6e8ax0_apply_level1_key(struct mipi_dsim_device *dsim_dev)  	};  	ops->cmd_write(dsim_dev, MIPI_DSI_DCS_LONG_WRITE, -		(unsigned int)data_to_send, ARRAY_SIZE(data_to_send)); +		data_to_send, ARRAY_SIZE(data_to_send));  }  static void s6e8ax0_apply_mtp_key(struct mipi_dsim_device *dsim_dev) @@ -201,7 +208,7 @@ static void s6e8ax0_apply_mtp_key(struct mipi_dsim_device *dsim_dev)  	};  	ops->cmd_write(dsim_dev, MIPI_DSI_DCS_LONG_WRITE, -		(unsigned int)data_to_send, ARRAY_SIZE(data_to_send)); +		data_to_send, ARRAY_SIZE(data_to_send));  }  static void s6e8ax0_panel_init(struct mipi_dsim_device *dsim_dev) diff --git a/drivers/video/sed156x.c b/drivers/video/sed156x.c index d8b0d7f5d..f324354c3 100644 --- a/drivers/video/sed156x.c +++ b/drivers/video/sed156x.c @@ -25,7 +25,6 @@  /* include the font data */  #include <video_font.h> -#include <video_font_data.h>  #if VIDEO_FONT_WIDTH != 8 || VIDEO_FONT_HEIGHT != 16  #error Expecting VIDEO_FONT_WIDTH == 8 && VIDEO_FONT_HEIGHT == 16 |