diff options
author | Daniel Ankers <dan@weirdo.org.uk> | 2006-10-16 17:21:36 +0000 |
---|---|---|
committer | Daniel Ankers <dan@weirdo.org.uk> | 2006-10-16 17:21:36 +0000 |
commit | d8ef7c58d83591bb0660fc4965cf2319fb5a4718 (patch) | |
tree | a71d3d9909cec32d3a8d22b10017a1e8959cfc16 /firmware | |
parent | 55d1675ada5273a815966057b811605462e1f7bd (diff) |
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
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/SOURCES | 5 | ||||
-rw-r--r-- | firmware/boot.lds | 4 | ||||
-rw-r--r-- | firmware/target/arm/crt0-pp5024.S | 92 | ||||
-rw-r--r-- | firmware/target/arm/sandisk/sansa-e200/adc-e200.c | 92 | ||||
-rw-r--r-- | firmware/target/arm/sandisk/sansa-e200/adc-target.h | 42 | ||||
-rw-r--r-- | firmware/target/arm/sandisk/sansa-e200/lcd-e200.c | 255 |
6 files changed, 385 insertions, 105 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES index c95b37d660..62e1fd0853 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -169,11 +169,7 @@ rolo.c thread.c timer.c #ifdef CPU_PP -#if (CONFIG_CPU == PP5024) -target/arm/crt0-pp5024.S -#else target/arm/crt0-pp.S -#endif #elif defined(CPU_ARM) target/arm/crt0.S #elif defined(CPU_COLDFIRE) @@ -236,6 +232,7 @@ drivers/m5636.c #ifdef SANSA_E200 target/arm/sandisk/sansa-e200/ata-e200.c target/arm/sandisk/sansa-e200/lcd-e200.c +target/arm/sandisk/sansa-e200/adc-e200.c #endif #ifdef IAUDIO_X5 diff --git a/firmware/boot.lds b/firmware/boot.lds index 0337b816f2..f361e45e9e 100644 --- a/firmware/boot.lds +++ b/firmware/boot.lds @@ -11,11 +11,7 @@ OUTPUT_ARCH(arm) /* the ipods can't have the crt0.o mentioned here, but the others can't do without it! */ #ifdef CPU_PP -#if (CONFIG_CPU == PP5024) -INPUT(target/arm/crt0-pp5024.o) -#else INPUT(target/arm/crt0-pp.o) -#endif #else INPUT(target/arm/crt0.o) #endif diff --git a/firmware/target/arm/crt0-pp5024.S b/firmware/target/arm/crt0-pp5024.S deleted file mode 100644 index 72edf37052..0000000000 --- a/firmware/target/arm/crt0-pp5024.S +++ /dev/null @@ -1,92 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2002 by Linus Nielsen Feltzing - * - * 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" - -#define THUMB_MODE(_r_, _l_) \ - ldr _r_,=_l_ ## f+1 ;\ - bx _r_ ;\ - .pool ;\ - .code 16 ;\ - .thumb_func ;\ - _l_: - -// Switch to ARM mode -#define ARM_MODE(_r_, _l_) \ - ldr _r_,=_l_ ## f ;\ - bx _r_ ;\ - .pool ;\ - .code 32 ;\ - _l_: - - -.equ MODE_MASK, 0x1f -.equ T_BIT, 0x20 -.equ F_BIT, 0x40 -.equ I_BIT, 0x80 -.equ MODE_IRQ, 0x12 -.equ MODE_SVC, 0x13 -.equ MODE_SYS, 0x1f - - - - .section .init.text,"ax",%progbits - - .global start -start: - - .equ PROC_ID, 0x60000000 - .equ COP_CTRL, 0x60007004 - .equ COP_STATUS, 0x60007004 - .equ IIS_CONFIG, 0x70002800 - .equ SLEEP, 0x80000000 - .equ WAKE, 0x0 - .equ SLEEPING, 0x80000000 - - - /* Find out which processor we are */ - mov r0, #PROC_ID - ldr r0, [r0] - and r0, r0, #0xff - cmp r0, #0x55 - beq 1f - - /* put us (co-processor) to sleep */ - ldr r4, =COP_CTRL - mov r3, #SLEEP - str r3, [r4] - ldr pc, =cop_wake_start - -cop_wake_start: - /* jump the COP to startup */ - ldr r0, =startup_loc - ldr pc, [r0] - -1: - msr cpsr_c, #0xd3 - - ldr sp, =0x40017f00 /* set stack */ - - - /* execute the loader - this will load an image to 0x10000000 */ - bl main - -startup_loc: - .word 0x0 - 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<<channel); + + /* Start? */ + ADC_ADDR |= 0x20000000; + ADC_ADDR |= 0x80000000; + + /* ADC_DATA_1 and ADC_DATA_2 are both four bytes, one byte per channel. + For each channel, ADC_DATA_1 stores the 8-bit msb, ADC_DATA_2 stores the + 2-bit lsb (in bits 0 and 1). Each channel is 10 bits total. */ + adc_data_1 = ((ADC_DATA_1 >> (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; } |