From d8ef7c58d83591bb0660fc4965cf2319fb5a4718 Mon Sep 17 00:00:00 2001 From: Daniel Ankers Date: Mon, 16 Oct 2006 17:21:36 +0000 Subject: Big Sansa update: Go back to using the common crt0-pp.S. Add LCD driver. Add ADC driver (may not be needed). Fix a bug in the button driver. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11237 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/arm/sandisk/sansa-e200/adc-e200.c | 92 ++++++++ .../target/arm/sandisk/sansa-e200/adc-target.h | 42 +++- firmware/target/arm/sandisk/sansa-e200/lcd-e200.c | 255 ++++++++++++++++++++- 3 files changed, 384 insertions(+), 5 deletions(-) create mode 100644 firmware/target/arm/sandisk/sansa-e200/adc-e200.c (limited to 'firmware/target/arm/sandisk/sansa-e200') diff --git a/firmware/target/arm/sandisk/sansa-e200/adc-e200.c b/firmware/target/arm/sandisk/sansa-e200/adc-e200.c new file mode 100644 index 0000000000..fbfa7d698a --- /dev/null +++ b/firmware/target/arm/sandisk/sansa-e200/adc-e200.c @@ -0,0 +1,92 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2006 by Barry Wardell + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "config.h" +#include "cpu.h" +#include "system.h" +#include "kernel.h" +#include "thread.h" +#include "adc.h" + +static unsigned short adcdata[NUM_ADC_CHANNELS]; + +/* Scan ADC so that adcdata[channel] gets updated */ +unsigned short adc_scan(int channel) +{ + unsigned int adc_data_1; + unsigned int adc_data_2; + + /* Initialise */ + ADC_ADDR=0x130; + ADC_STATUS=0; /* 4 bytes, 1 per channel. Each byte is 0 if the channel is + off, 0x40 if the channel is on */ + + /* Enable Channel */ + ADC_ADDR |= (0x1000000<> (8*channel)) & 0xff); + adc_data_2 = ((ADC_DATA_2 >> (8*channel+6)) & 0x3); + + adcdata[channel] = (adc_data_1<<2 | adc_data_2); + + return adcdata[channel]; +} + +/* Read 10-bit channel data */ +unsigned short adc_read(int channel) +{ + return adcdata[channel]; +} + +static int adc_counter; + +static void adc_tick(void) +{ + if(++adc_counter == HZ) + { + adc_counter = 0; + adc_scan(ADC_0); + adc_scan(ADC_1); + adc_scan(ADC_2); + adc_scan(ADC_3); + } +} + +void adc_init(void) +{ + /* Enable ADC */ + ADC_ENABLE_ADDR |= ADC_ENABLE; + + /* Initialise */ + ADC_INIT=0; + + /* Force a scan of all channels to get initial values */ + adc_scan(ADC_0); + adc_scan(ADC_1); + adc_scan(ADC_2); + adc_scan(ADC_3); + + tick_add_task(adc_tick); +} diff --git a/firmware/target/arm/sandisk/sansa-e200/adc-target.h b/firmware/target/arm/sandisk/sansa-e200/adc-target.h index a7b884767c..526f99e43b 100644 --- a/firmware/target/arm/sandisk/sansa-e200/adc-target.h +++ b/firmware/target/arm/sandisk/sansa-e200/adc-target.h @@ -1,4 +1,42 @@ -/* blank */ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2006 by Barry Wardell + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef _ADC_TARGET_H_ +#define _ADC_TARGET_H_ -#define ADC_UNREG_POWER 0 /* made up to let powermgmt.c compile */ +#define ADC_ENABLE_ADDR (*(volatile unsigned long*)(0x70000010)) +#define ADC_ENABLE 0x1100 +#define ADC_ADDR (*(volatile unsigned long*)(0x7000ad00)) +#define ADC_STATUS (*(volatile unsigned long*)(0x7000ad04)) +#define ADC_DATA_1 (*(volatile unsigned long*)(0x7000ad20)) +#define ADC_DATA_2 (*(volatile unsigned long*)(0x7000ad24)) +#define ADC_INIT (*(volatile unsigned long*)(0x7000ad2c)) + +#define NUM_ADC_CHANNELS 4 + +#define ADC_0 0 +#define ADC_1 1 +#define ADC_2 2 +#define ADC_3 3 +#define ADC_UNREG_POWER ADC_0 /* For compatibility */ + +/* Force a scan now */ +unsigned short adc_scan(int channel); + +#endif diff --git a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c index dedb196c70..2ee191faa5 100644 --- a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c +++ b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c @@ -1,15 +1,264 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Rockbox driver for Sansa e200 LCDs + * + * Based on reverse engineering done my MrH + * + * Copyright (c) 2006 Daniel Ankers + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "config.h" +#include "cpu.h" +#include "lcd.h" +#include "kernel.h" +#include "system.h" -void lcd_update(void) +#define LCD_DATA_IN_GPIO GPIOB_INPUT_VAL +#define LCD_DATA_IN_PIN 6 + +#define LCD_DATA_OUT_GPIO GPIOB_OUTPUT_VAL +#define LCD_DATA_OUT_PIN 7 + +#define LCD_CLOCK_GPIO GPIOB_OUTPUT_VAL +#define LCD_CLOCK_PIN 5 + +#define LCD_CS_GPIO GPIOD_OUTPUT_VAL +#define LCD_CS_PIN 6 + +#define LCD_REG_0 (*(volatile unsigned long *)(0xc2000000)) +#define LCD_REG_1 (*(volatile unsigned long *)(0xc2000004)) +#define LCD_REG_2 (*(volatile unsigned long *)(0xc2000008)) +#define LCD_REG_3 (*(volatile unsigned long *)(0xc200000c)) +#define LCD_REG_4 (*(volatile unsigned long *)(0xc2000010)) +#define LCD_REG_5 (*(volatile unsigned long *)(0xc2000014)) +#define LCD_REG_6 (*(volatile unsigned long *)(0xc2000018)) +#define LCD_REG_7 (*(volatile unsigned long *)(0xc200001c)) +#define LCD_REG_8 (*(volatile unsigned long *)(0xc2000020)) +#define LCD_REG_9 (*(volatile unsigned long *)(0xc2000024)) +#define LCD_FB_BASE_REG (*(volatile unsigned long *)(0xc2000028)) + +static inline void lcd_init_gpio(void) +{ + GPIOB_ENABLE |= (1<<7); + GPIOB_ENABLE |= (1<<5); + GPIOB_OUTPUT_EN |= (1<<7); + GPIOB_OUTPUT_EN |= (1<<5); + GPIOD_ENABLE |= (1<<6); + GPIOD_OUTPUT_EN |= (1<<6); +} + +static inline void lcd_bus_idle(void) +{ + LCD_CLOCK_GPIO |= (1 << LCD_CLOCK_PIN); + LCD_DATA_OUT_GPIO |= (1 << LCD_DATA_OUT_PIN); +} + +static inline void lcd_send_byte(unsigned char byte) { + int i; + + for (i = 7; i >=0 ; i--) + { + LCD_CLOCK_GPIO &= ~(1 << LCD_CLOCK_PIN); + if ((byte >> i) & 1) + { + LCD_DATA_OUT_GPIO |= (1 << LCD_DATA_OUT_PIN); + } else { + LCD_DATA_OUT_GPIO &= ~(1 << LCD_DATA_OUT_PIN); + } + udelay(1); + LCD_CLOCK_GPIO |= (1 << LCD_CLOCK_PIN); + udelay(1); + lcd_bus_idle(); + udelay(3); + } +} + +static inline void lcd_send_msg(unsigned char cmd, unsigned int data) +{ + lcd_bus_idle(); + udelay(1); + LCD_CS_GPIO &= ~(1 << LCD_CS_PIN); + udelay(10); + lcd_send_byte(cmd); + lcd_send_byte((unsigned char)(data >> 8)); + lcd_send_byte((unsigned char)(data & 0xff)); + LCD_CS_GPIO |= (1 << LCD_CS_PIN); + udelay(1); + lcd_bus_idle(); +} + +static inline void lcd_write_reg(unsigned int reg, unsigned int data) +{ + lcd_send_msg(0x70, reg); + lcd_send_msg(0x72, data); +} + +inline void lcd_init_device(void) +{ +/* All this is magic worked out by MrH */ + +/* Init GPIO ports */ + lcd_init_gpio(); +/* Controller init */ + outl((inl(0x70000084) | (1 << 28)), 0x70000084); + outl((inl(0x70000080) & ~(1 << 28)), 0x70000080); + outl(((inl(0x70000010) & (0x03ffffff)) | (0x15 << 26)), 0x70000010); + outl(((inl(0x70000014) & (0x0fffffff)) | (0x5 << 28)), 0x70000014); + outl((inl(0x70000020) & ~(0x3 << 10)), 0x70000020); + outl((inl(0x6000600c) | (1 << 26)), 0x6000600c); /* Enable controller */ + outl(0x6, 0x600060d0); + outl((inl(0x60006004) | (1 << 26)), 0x60006004); /* Reset controller? */ + outl((inl(0x70000020) & ~(1 << 14)), 0x70000020); + lcd_bus_idle(); + outl((inl(0x60006004) & ~(1 << 26)), 0x60006004); /* Clear reset? */ + udelay(1000); + + LCD_REG_0 = (LCD_REG_0 & (0x00ffffff)) | (0x22 << 24); + LCD_REG_0 = (LCD_REG_0 & (0xff00ffff)) | (0x14 << 16); + LCD_REG_0 = (LCD_REG_0 & (0xffffc0ff)) | (0x3 << 8); + LCD_REG_0 = (LCD_REG_0 & (0xffffffc0)) | (0xa); + + LCD_REG_1 &= 0x00ffffff; + LCD_REG_1 &= 0xff00ffff; + LCD_REG_1 = (LCD_REG_1 & 0xffff03ff) | (0x2 << 10); + LCD_REG_1 = (LCD_REG_1 & 0xfffffc00) | (0xdd); + + LCD_REG_2 |= (1 << 5); + LCD_REG_2 |= (1 << 6); + LCD_REG_2 = (LCD_REG_2 & 0xfffffcff) | (0x2 << 8); + + LCD_REG_7 &= (0xf800ffff); + LCD_REG_7 &= (0xfffff800); + + LCD_REG_8 = (LCD_REG_8 & (0xf800ffff)) | (0xb0 << 16); + LCD_REG_8 = (LCD_REG_8 & (0xfffff800)) | (0xde); /* X-Y Geometry? */ + + LCD_REG_5 |= 0xc; + LCD_REG_5 = (LCD_REG_5 & ~(0x70)) | (0x3 << 4); + LCD_REG_5 |= 2; + + LCD_REG_6 &= ~(1 << 15); + LCD_REG_6 |= (0xe00); + LCD_REG_6 = (LCD_REG_6 & (0xffffff1f)) | (0x4 << 5); + LCD_REG_6 |= (1 << 4); + + LCD_REG_5 &= ~(1 << 7); + LCD_FB_BASE_REG = (unsigned long)lcd_framebuffer; + + udelay(100000); + +/* LCD init */ + outl((inl(0x70000080) & ~(1 << 28)), 0x70000080); + udelay(10000); + outl((inl(0x70000080) | (1 << 28)), 0x70000080); + udelay(10000); + + lcd_write_reg(16, 0x4444); + lcd_write_reg(17, 0x0001); + lcd_write_reg(18, 0x0003); + lcd_write_reg(19, 0x1119); + lcd_write_reg(18, 0x0013); + udelay(50000); + + lcd_write_reg(16, 0x4440); + lcd_write_reg(19, 0x3119); + udelay(150000); + + lcd_write_reg(1, 0x101b); + lcd_write_reg(2, 0x0700); + lcd_write_reg(3, 0x6020); + lcd_write_reg(4, 0x0000); + lcd_write_reg(5, 0x0000); + lcd_write_reg(8, 0x0102); + lcd_write_reg(9, 0x0000); + lcd_write_reg(11, 0x4400); + lcd_write_reg(12, 0x0110); + + lcd_write_reg(64, 0x0000); + lcd_write_reg(65, 0x0000); + lcd_write_reg(66, (219 << 8)); /* Screen resolution? */ + lcd_write_reg(67, 0x0000); + lcd_write_reg(68, (175 << 8)); + lcd_write_reg(69, (219 << 8)); + + lcd_write_reg(48, 0x0000); + lcd_write_reg(49, 0x0704); + lcd_write_reg(50, 0x0107); + lcd_write_reg(51, 0x0704); + lcd_write_reg(52, 0x0107); + lcd_write_reg(53, 0x0002); + lcd_write_reg(54, 0x0707); + lcd_write_reg(55, 0x0503); + lcd_write_reg(56, 0x0000); + lcd_write_reg(57, 0x0000); + + lcd_write_reg(33, 175); + + lcd_write_reg(12, 0x0110); + + lcd_write_reg(16, 0x4740); + + lcd_write_reg(7, 0x0045); + + udelay(50000); + + lcd_write_reg(7, 0x0065); + lcd_write_reg(7, 0x0067); + + udelay(50000); + + lcd_write_reg(7, 0x0077); + lcd_send_msg(0x70, 34); } -void lcd_update_rect(int x, int y, int width, int height) +inline void lcd_update(void) { + if(!(LCD_REG_6 & 1)) + LCD_REG_6 |= 1; +} +inline void lcd_update_rect(int x, int y, int width, int height) +{ + (void) x; + (void) y; + (void) width; + (void) height; + lcd_update(); } -void lcd_init_device(void) + +/*** hardware configuration ***/ + +void lcd_set_contrast(int val) +{ + /* TODO: Implement lcd_set_contrast() */ + (void)val; +} + +void lcd_set_invert_display(bool yesno) { + /* TODO: Implement lcd_set_invert_display() */ + (void)yesno; +} +/* turn the display upside down (call lcd_update() afterwards) */ +void lcd_set_flip(bool yesno) +{ + /* TODO: Implement lcd_set_flip() */ + (void)yesno; } -- cgit v1.2.3