diff options
Diffstat (limited to 'drivers/video/mxsfb.c')
| -rw-r--r-- | drivers/video/mxsfb.c | 45 | 
1 files changed, 44 insertions, 1 deletions
| 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;  } |