#pypp 0 // Iris: micro-kernel for a capability-based operating system. // 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 #include "jz4730.hh" #include "devices.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 // level is in the range [0, 300] static void set_backlight (unsigned level): PWM_DUT (0) = level if level: PWM_CTR (0) = 0xbf GPIO_GPDR (2) |= PWM_ENABLE else: PWM_CTR (0) = 0x3f GPIO_GPDR (2) &= ~PWM_ENABLE // Write to a register. Value must be in range [0, 0xff]. static void write_reg (unsigned reg, unsigned value): unsigned data = (reg << 0xa) | 0x200 | value GPIO_GPDR (2) |= SPEN GPIO_GPDR (2) = (GPIO_GPDR (2) & ~SPDA) | SPCK GPIO_GPDR (2) &= ~SPEN udelay(25) for unsigned i = 0; i < 16; ++i: GPIO_GPDR (2) &= ~SPCK if data & 0x8000: GPIO_GPDR (2) |= SPDA else: GPIO_GPDR (2) &= ~SPDA udelay (25) GPIO_GPDR (2) |= SPCK udelay (25) data <<= 1 GPIO_GPDR (2) |= SPEN udelay(200) static void lcd_enable (): udelay (50) GPIO_GPDR (2) &= ~LCD_RET mdelay(150) GPIO_GPDR (2) |= LCD_RET mdelay(10) // These values have been copied from the linux source. // I have no idea what they do. write_reg (0x00, 0x03) write_reg (0x01, 0x40) write_reg (0x02, 0x11) write_reg (0x03, 0xcd) write_reg (0x04, 0x32) write_reg (0x05, 0x0e) write_reg (0x07, 0x03) write_reg (0x08, 0x08) write_reg (0x09, 0x32) write_reg (0x0A, 0x88) write_reg (0x0B, 0xc6) write_reg (0x0C, 0x20) write_reg (0x0D, 0x20) set_backlight (300) static void lcd_disable (): write_reg (0x00, 0x03) set_backlight (0) static void reset (): // Use gpio pins as pwm. GPIO_GPAUR (2) = (GPIO_GPAUR (2) & ~0x0fffffff) | 0x50000000 // Use gpio pins as lcd master. GPIO_GPALR (1) = (GPIO_GPALR (1) & ~0x0000ffff) | 0x55550000 GPIO_GPAUR (1) = 0x556a5555 // 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 mdelay (150) GPIO_GPDR (2) |= LCD_RET mdelay (10) lcd_enable () // For now, support only 16 bpp. // Screen is 800x480 tft. LCD_CTRL = LCD_CTRL_BPP_16 | LCD_CTRL_BST_16 LCD_VSYNC = 20 LCD_HSYNC = 80 LCD_DAV = (20 << 16) | 500 LCD_DAH = (80 << 16) | 880 LCD_VAT = (880 << 16) | 500 //LCD_CFG = MODE_TFT_GEN | PCLK_N | VSYNC_N // Stop lcd. CPM_MSCR |= 1 << 7 unsigned pclk = 60 * (800 * 3 + 80) * 500 unsigned pllout = get_pllout () CPM_CFCR2 = pllout / pclk - 1 unsigned v = pllout / (pclk * 4) - 1 while v < 0xf && pllout / (v + 1) > 150000000: ++v CPM_CFCR = (CPM_CFCR & ~CPM_CFCR_LFR_MASK) | (v << CPM_CFCR_LFR_BIT) | CPM_CFCR_UPE // Start lcd. CPM_MSCR &= ~(1 << 7) mdelay (1) static void map_io (unsigned physical, unsigned address): Capability page = memory_create_page (__my_memory) alloc_physical (page, physical, 0) memory_map (__my_memory, page, address, 1) //drop (page) int main (): map_gpio () map_pwm0 () map_lcd () map_cpm () reset () while true: Message msg if !wait (&msg): continue switch msg.protected_data: case LCD_BACKLIGHT: set_backlight (msg.data[0] > 300 ? 300 : msg.data[0]) break case LCD_RESET: reset () break