#pypp 0 // Iris: micro-kernel for a capability-based operating system. // boot-programs/lcd.ccp: Display driver. // Copyright 2009 Bas Wijnen // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #include "devices.hh" #define ARCH #include "arch.hh" // Pin definitions, all in port 2. #define PWM_ENABLE (1 << 30) #define SPEN (1 << 0) //LCD_SPL #define SPCK (1 << 1) //LCD_CLS #define SPDA (1 << 2) //LCD_PS #define LCD_RET (1 << 3) //LCD_REV //use for lcd reset static void set_backlight (bool state): if state: PWM_DUT (0) = 300 PWM_CTR (0) = 0xbf GPIO_GPDR (2) |= PWM_ENABLE else: PWM_DUT (0) = 0 PWM_CTR (0) = 0x3f GPIO_GPDR (2) &= ~PWM_ENABLE static void reset (): PWM_PER (0) = 300 set_backlight (false) // initialize things. GPIO_GPIER (2) &= ~(PWM_ENABLE | LCD_RET | SPEN | SPCK | SPDA) GPIO_GPDIR (2) |= PWM_ENABLE | LCD_RET | SPEN | SPCK | SPDA udelay (50) GPIO_GPDR (2) &= ~LCD_RET ddelay (2) GPIO_GPDR (2) |= LCD_RET ddelay (1) // For now, support only 16 bpp. // Screen is 800x480 tft. unsigned h = 800, v = 480, hs = 80, vs = 20, fps = 60, Bpp = 2 LCD_CTRL = LCD_CTRL_BPP_16 | LCD_CTRL_BST_16 LCD_VSYNC = vs LCD_HSYNC = hs LCD_DAV = (vs << 16) | (vs + v) LCD_DAH = (hs << 16) | (hs + h) LCD_VAT = ((hs + h) << 16) | (vs + v) #define MODE_TFT_GEN 0 #define PCLK_N (1 << 10) #define VSYNC_N (1 << 8) LCD_CFG = MODE_TFT_GEN | PCLK_N | VSYNC_N cpm_stop_lcd () unsigned pllout = cpm_get_pllout () unsigned pixclock = fps * (hs + h) * (vs + v) CPM_CFCR2 = pllout / pixclock - 1 unsigned val = pllout / (pixclock * 4) - 1 while val < 0xf && pllout / (val + 1) > 150000000: ++val cpm_set_lcdclk_div (val) CPM_CFCR |= CPM_CFCR_UPE cpm_start_lcd () udelay (1000) //LCD_DA0 = framebuffer unsigned frame_size = v * h * Bpp LCD_CMD0 = LCD_CMD_SOFINT | LCD_CMD_EOFINT | (frame_size << LCD_CMD_LEN_BIT) lcd_set_ena () lcd_enable_eof_intr () int main (): map_gpio () map_pwm0 () map_lcd () map_cpm () reset () register_interrupt (IRQ_LCD) set_backlight (true) while true: Message msg if !wait (&msg): continue switch msg.protected_data: case IRQ_LCD: kdebug (0) LCD_STATE &= ~LCD_STATE_EOF register_interrupt (IRQ_LCD) // TODO: allow callback break case LCD_BACKLIGHT: set_backlight (msg.data[0]) break case LCD_RESET: reset () break