[U-Boot] [PATCH] Add AVR32 LCD support

Mark Jackson mpfj-list at mimc.co.uk
Thu Jun 4 15:58:09 CEST 2009


This patch adds support for the AVR32 LCD controller.  This patch is
based off the latest Denx master (not the current AVR32 git).

A quick summary of what's going on:-

Enable LCDC pixel clock
Enable LCDC port pins
Correctly specify LCDC guard time
Add framebuffer pointer to global_data struct
Allocate framebuffer

To use the new code, update your board config to include something like
this:-

#define CONFIG_LCD			1

#if defined(CONFIG_LCD)
#define CONFIG_CMD_BMP
#define CONFIG_ATMEL_LCD		1
#define LCD_BPP				LCD_COLOR16
#define CONFIG_BMP_16BPP		1
#define CONFIG_FB_ADDR			0x10600000
#define CONFIG_WHITE_ON_BLACK		1
#define CONFIG_VIDEO_BMP_GZIP 		1
#define CONFIG_SYS_VIDEO_LOGO_MAX_SIZE		262144
#define CONFIG_ATMEL_LCD_BGR555		1
#define CONFIG_SYS_CONSOLE_IS_IN_ENV	1
#define CONFIG_SPLASH_SCREEN		1
#endif

The standard U-Boot BMP and Splash-screen features should just work.

Signed-off-by: Mark Jackson <mpfj at mimc.co.uk>
---
 cpu/at32ap/at32ap700x/clk.c                       |    5 +
 cpu/at32ap/at32ap700x/portmux.c                   |   90
+++++++++++++++++++++
 drivers/video/atmel_lcdfb.c                       |    5 +-
 include/asm-avr32/arch-at32ap700x/chip-features.h |    5 +
 include/asm-avr32/arch-at32ap700x/clk.h           |    6 ++
 include/asm-avr32/arch-at32ap700x/portmux.h       |    5 +-
 include/asm-avr32/global_data.h                   |    3 +
 include/lcd.h                                     |    2 +-
 lib_avr32/board.c                                 |   11 +++
 9 files changed, 128 insertions(+), 4 deletions(-)

diff --git a/cpu/at32ap/at32ap700x/clk.c b/cpu/at32ap/at32ap700x/clk.c
index 2c2e19c..742bc6b 100644
--- a/cpu/at32ap/at32ap700x/clk.c
+++ b/cpu/at32ap/at32ap700x/clk.c
@@ -65,6 +65,11 @@ void clk_init(void)
 #ifdef CONFIG_PLL
 	/* Use PLL0 as main clock */
 	sm_writel(PM_MCCTRL, SM_BIT(PLLSEL));
+
+#ifdef CONFIG_LCD
+	/* Set up pixel clock for the LCDC */
+	sm_writel(PM_GCCTRL(7), SM_BIT(PLLSEL) | SM_BIT(CEN));
+#endif
 #endif
 }
 
diff --git a/cpu/at32ap/at32ap700x/portmux.c
b/cpu/at32ap/at32ap700x/portmux.c
index 2a3b004..e71b2bf 100644
--- a/cpu/at32ap/at32ap700x/portmux.c
+++ b/cpu/at32ap/at32ap700x/portmux.c
@@ -202,3 +202,93 @@ void portmux_enable_spi1(unsigned long cs_mask,
unsigned long drive_strength)
 			PORTMUX_DIR_OUTPUT | PORTMUX_INIT_HIGH);
 }
 #endif
+
+#ifdef AT32AP700x_CHIP_HAS_LCDC
+void portmux_enable_lcdc(int pin_config)
+{
+	unsigned long portc_mask = 0;
+	unsigned long portd_mask = 0;
+	unsigned long porte_mask = 0;
+
+	switch(pin_config) {
+	case 0:
+		portc_mask = (1 << 19)	/* CC     */
+			| (1 << 20)	/* HSYNC  */
+			| (1 << 21)	/* PCLK   */
+			| (1 << 22)	/* VSYNC  */
+			| (1 << 23)	/* DVAL   */
+			| (1 << 24)	/* MODE   */
+			| (1 << 25)	/* PWR    */
+			| (1 << 26)	/* DATA0  */
+			| (1 << 27)	/* DATA1  */
+			| (1 << 28)	/* DATA2  */
+			| (1 << 29)	/* DATA3  */
+			| (1 << 30)	/* DATA4  */
+			| (1 << 31);	/* DATA5  */
+
+		portd_mask = (1 << 0)	/* DATA6  */
+			| (1 << 1)	/* DATA7  */
+			| (1 << 2)	/* DATA8  */
+			| (1 << 3)	/* DATA9  */
+			| (1 << 4)	/* DATA10 */
+			| (1 << 5)	/* DATA11 */
+			| (1 << 6)	/* DATA12 */
+			| (1 << 7)	/* DATA13 */
+			| (1 << 8)	/* DATA14 */
+			| (1 << 9)	/* DATA15 */
+			| (1 << 10)	/* DATA16 */
+			| (1 << 11)	/* DATA17 */
+			| (1 << 12)	/* DATA18 */
+			| (1 << 13)	/* DATA19 */
+			| (1 << 14)	/* DATA20 */
+			| (1 << 15)	/* DATA21 */
+			| (1 << 16)	/* DATA22 */
+			| (1 << 17);	/* DATA23 */
+		break;
+
+	case 1:
+		portc_mask = (1 << 20)	/* HSYNC  */
+			| (1 << 21)	/* PCLK   */
+			| (1 << 22)	/* VSYNC  */
+			| (1 << 25)	/* PWR    */
+			| (1 << 31);	/* DATA5  */
+
+		portd_mask = (1 << 0)	/* DATA6  */
+			| (1 << 1)	/* DATA7  */
+			| (1 << 7)	/* DATA13 */
+			| (1 << 8)	/* DATA14 */
+			| (1 << 9)	/* DATA15 */
+			| (1 << 16)	/* DATA22 */
+			| (1 << 17);	/* DATA23 */
+
+		porte_mask = (1 << 0)	/* CC     */
+			| (1 << 1)	/* DVAL   */
+			| (1 << 2)	/* MODE   */
+			| (1 << 3)	/* DATA0  */
+			| (1 << 4)	/* DATA1  */
+			| (1 << 5)	/* DATA2  */
+			| (1 << 6)	/* DATA3  */
+			| (1 << 7)	/* DATA4  */
+			| (1 << 8)	/* DATA8  */
+			| (1 << 9)	/* DATA9  */
+			| (1 << 10)	/* DATA10 */
+			| (1 << 11)	/* DATA11 */
+			| (1 << 12)	/* DATA12 */
+			| (1 << 13)	/* DATA16 */
+			| (1 << 14)	/* DATA17 */
+			| (1 << 15)	/* DATA18 */
+			| (1 << 16)	/* DATA19 */
+			| (1 << 17)	/* DATA20 */
+			| (1 << 18);	/* DATA21 */
+		break;
+	}
+
+	/* REVISIT: Some pins are probably pure outputs */
+	portmux_select_peripheral(PORTMUX_PORT_C, portc_mask,
+			PORTMUX_FUNC_A, PORTMUX_BUSKEEPER);
+	portmux_select_peripheral(PORTMUX_PORT_D, portd_mask,
+			PORTMUX_FUNC_A, PORTMUX_BUSKEEPER);
+	portmux_select_peripheral(PORTMUX_PORT_E, porte_mask,
+			PORTMUX_FUNC_B, PORTMUX_BUSKEEPER);
+}
+#endif
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index 3a51cc7..14f578e 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -42,6 +42,7 @@ short console_row;
 /* configurable parameters */
 #define ATMEL_LCDC_CVAL_DEFAULT		0xc8
 #define ATMEL_LCDC_DMA_BURST_LEN	8
+#define ATMEL_LCDC_GUARD_TIME		2
 
 #if defined(CONFIG_AT91SAM9263) || defined(CONFIG_AT91CAP9)
 #define ATMEL_LCDC_FIFO_SIZE		2048
@@ -69,7 +70,7 @@ void lcd_ctrl_init(void *lcdbase)
 
 	/* Turn off the LCD controller and the DMA controller */
 	lcdc_writel(panel_info.mmio, ATMEL_LCDC_PWRCON,
-		    1 << ATMEL_LCDC_GUARDT_OFFSET);
+		    ATMEL_LCDC_GUARD_TIME << ATMEL_LCDC_GUARDT_OFFSET);
 
 	/* Wait for the LCDC core to become idle */
 	while (lcdc_readl(panel_info.mmio, ATMEL_LCDC_PWRCON) &
ATMEL_LCDC_BUSY)
@@ -150,7 +151,7 @@ void lcd_ctrl_init(void *lcdbase)
 
 	lcdc_writel(panel_info.mmio, ATMEL_LCDC_DMACON, ATMEL_LCDC_DMAEN);
 	lcdc_writel(panel_info.mmio, ATMEL_LCDC_PWRCON,
-		    (1 << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR);
+		    (ATMEL_LCDC_GUARD_TIME << ATMEL_LCDC_GUARDT_OFFSET) |
ATMEL_LCDC_PWR);
 }
 
 ulong calc_fbsize(void)
diff --git a/include/asm-avr32/arch-at32ap700x/chip-features.h
b/include/asm-avr32/arch-at32ap700x/chip-features.h
index c47107e..40a2476 100644
--- a/include/asm-avr32/arch-at32ap700x/chip-features.h
+++ b/include/asm-avr32/arch-at32ap700x/chip-features.h
@@ -32,4 +32,9 @@
 #define AT32AP700x_CHIP_HAS_MACB
 #endif
 
+/* AP7000 and AP7002 have LCD controller, but AP7001 does not */
+#if defined(CONFIG_AT32AP7000) || defined(CONFIG_AT32AP7002)
+#define AT32AP700x_CHIP_HAS_LCDC
+#endif
+
 #endif /* __ASM_AVR32_ARCH_CHIP_FEATURES_H__ */
diff --git a/include/asm-avr32/arch-at32ap700x/clk.h
b/include/asm-avr32/arch-at32ap700x/clk.h
index d83e93b..7a0b655 100644
--- a/include/asm-avr32/arch-at32ap700x/clk.h
+++ b/include/asm-avr32/arch-at32ap700x/clk.h
@@ -83,6 +83,12 @@ static inline unsigned long get_spi_clk_rate(unsigned
int dev_id)
 	return get_pba_clk_rate();
 }
 #endif
+#ifdef AT32AP700x_CHIP_HAS_LCDC
+static inline unsigned long get_lcdc_clk_rate(unsigned int dev_id)
+{
+	return get_hsb_clk_rate();
+}
+#endif
 
 extern void clk_init(void);
 
diff --git a/include/asm-avr32/arch-at32ap700x/portmux.h
b/include/asm-avr32/arch-at32ap700x/portmux.h
index 96fe70d..8574aec 100644
--- a/include/asm-avr32/arch-at32ap700x/portmux.h
+++ b/include/asm-avr32/arch-at32ap700x/portmux.h
@@ -85,5 +85,8 @@ void portmux_enable_mmci(unsigned int slot, unsigned
long flags,
 void portmux_enable_spi0(unsigned long cs_mask, unsigned long
drive_strength);
 void portmux_enable_spi1(unsigned long cs_mask, unsigned long
drive_strength);
 #endif
-
+#ifdef AT32AP700x_CHIP_HAS_LCDC
+void portmux_enable_lcdc(int pin_config);
+#endif
+ 
 #endif /* __ASM_AVR32_ARCH_PORTMUX_H__ */
diff --git a/include/asm-avr32/global_data.h
b/include/asm-avr32/global_data.h
index 97a6c61..efbdda9 100644
--- a/include/asm-avr32/global_data.h
+++ b/include/asm-avr32/global_data.h
@@ -42,6 +42,9 @@ typedef	struct	global_data {
 	unsigned long	env_addr;	/* Address of env struct */
 	unsigned long	env_valid;	/* Checksum of env valid? */
 	unsigned long	cpu_hz;		/* cpu core clock frequency */
+#if defined(CONFIG_LCD)
+	void		*fb_base;	/* framebuffer address */
+#endif
 	void		**jt;		/* jump table */
 } gd_t;
 
diff --git a/include/lcd.h b/include/lcd.h
index f054cac..0d6549c 100644
--- a/include/lcd.h
+++ b/include/lcd.h
@@ -314,7 +314,7 @@ void lcd_show_board_info(void);
 #if LCD_BPP == LCD_MONOCHROME
 # define COLOR_MASK(c)		((c)	  | (c) << 1 | (c) << 2 | (c) << 3 | \
 				 (c) << 4 | (c) << 5 | (c) << 6 | (c) << 7)
-#elif LCD_BPP == LCD_COLOR8
+#elif (LCD_BPP == LCD_COLOR8) || (LCD_BPP == LCD_COLOR16)
 # define COLOR_MASK(c)		(c)
 #else
 # error Unsupported LCD BPP.
diff --git a/lib_avr32/board.c b/lib_avr32/board.c
index 57115df..1389ada 100644
--- a/lib_avr32/board.c
+++ b/lib_avr32/board.c
@@ -239,6 +239,17 @@ void board_init_f(ulong board_type)
 	addr -= CONFIG_SYS_DMA_ALLOC_LEN;
 #endif
 
+#ifdef CONFIG_LCD
+#ifdef CONFIG_FB_ADDR
+	printf("LCD: Frame buffer allocated at preset 0x%08x\n",
CONFIG_FB_ADDR);
+	gd->fb_base = (void*)CONFIG_FB_ADDR;
+#else
+	addr = lcd_setmem(addr);
+	printf("LCD: Frame buffer allocated at 0x%08lx\n", addr);
+	gd->fb_base = (void*)addr;
+#endif /* CONFIG_FB_ADDR */
+#endif /* CONFIG_LCD */
+
 	/* Allocate a Board Info struct on a word boundary */
 	addr -= sizeof(bd_t);
 	addr &= ~3UL;



More information about the U-Boot mailing list