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 <m...@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; _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot