Add AVR32 LCD support

This patch adds support for the AVR32 LCD controller.  This patch is
based off the latest u-boot-video.

A quick summary of what's going on:-

Enable LCDC pixel clock
Enable LCDC port pins
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@mimc.co.uk>
[agust@denx.de: fixed some style issues]
Signed-off-by: Anatolij Gustschin <agust@denx.de>
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 @@
 #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..b1f2c6f 100644
--- a/cpu/at32ap/at32ap700x/portmux.c
+++ b/cpu/at32ap/at32ap700x/portmux.c
@@ -202,3 +202,93 @@
 			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/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 @@
 	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..1ba52e5 100644
--- a/include/asm-avr32/arch-at32ap700x/portmux.h
+++ b/include/asm-avr32/arch-at32ap700x/portmux.h
@@ -85,5 +85,8 @@
 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 @@
 	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/lib_avr32/board.c b/lib_avr32/board.c
index 5b2d0ef1..da03506 100644
--- a/lib_avr32/board.c
+++ b/lib_avr32/board.c
@@ -239,6 +239,17 @@
 	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;