Add AVR32 LCD support
authorMark Jackson <mpfj-list@mimc.co.uk>
Tue, 21 Jul 2009 10:11:37 +0000 (11:11 +0100)
committerAnatolij Gustschin <agust@denx.de>
Sun, 26 Jul 2009 11:12:02 +0000 (13:12 +0200)
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>
cpu/at32ap/at32ap700x/clk.c
cpu/at32ap/at32ap700x/portmux.c
include/asm-avr32/arch-at32ap700x/chip-features.h
include/asm-avr32/arch-at32ap700x/clk.h
include/asm-avr32/arch-at32ap700x/portmux.h
include/asm-avr32/global_data.h
lib_avr32/board.c

index 2c2e19c296c3edbfbfaa2e62fd4059b49a19af83..742bc6b5a21c42b010c83b9a68516036ff665acc 100644 (file)
@@ -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
 }
 
index 2a3b004b049fd16bf1ebc6b5002e21c505e65e99..b1f2c6f1ffba5f6fd9533172e1b2de9d0991fa98 100644 (file)
@@ -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
index c47107e2a641bf6e11c6d66a64611ce2b7b52817..40a2476c9ad43f803098ad083cf356cf2668ea88 100644 (file)
@@ -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__ */
index d83e93b74f6eb06642ac89790cbd6b40f33510c3..7a0b6559e09678c05d69b50212985a4f318686cb 100644 (file)
@@ -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);
 
index 96fe70d4bdad31c7ae264aea548a62eba4e7d00c..1ba52e5ddbccce7a4b843042007b9b138ef41478 100644 (file)
@@ -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__ */
index 97a6c6173c9af26be8966c34933b5a6e44a8546c..efbdda9ba4ca284c19596c8c3990e13062628912 100644 (file)
@@ -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;
 
index 5b2d0ef1d3767835b64e1cd34d10f6102ad14b40..da035063db2dbebf55e3797e6ef80ccc80316646 100644 (file)
@@ -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;