summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorDaniel Ankers <dan@weirdo.org.uk>2006-10-16 17:21:36 +0000
committerDaniel Ankers <dan@weirdo.org.uk>2006-10-16 17:21:36 +0000
commitd8ef7c58d83591bb0660fc4965cf2319fb5a4718 (patch)
treea71d3d9909cec32d3a8d22b10017a1e8959cfc16 /firmware
parent55d1675ada5273a815966057b811605462e1f7bd (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/SOURCES5
-rw-r--r--firmware/boot.lds4
-rw-r--r--firmware/target/arm/crt0-pp5024.S92
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/adc-e200.c92
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/adc-target.h42
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/lcd-e200.c255
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;
}