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
This commit is contained in:
Daniel Ankers 2006-10-16 17:21:36 +00:00
parent 55d1675ada
commit d8ef7c58d8
7 changed files with 500 additions and 127 deletions

View file

@ -36,31 +36,59 @@
#include "power.h"
#include "file.h"
void main(void)
static inline void blink(void)
{
volatile unsigned int* ptr;
int i;
ptr = (volatile unsigned int*)0x70000020;
while(1)
*ptr &= ~(1 << 13);
for(i = 0; i < 0xfffff; i++)
{
// blink wheel backlight
ptr = (volatile unsigned int*)0x70000020;
if((*ptr) & (1 << 13))
{
*ptr = (*ptr) & ~(1 << 13);
}
else
{
*ptr = (*ptr) | (1 << 13);
}
// wait a while
for(i = 0; i < 0xfffff; i++)
{
}
}
*ptr |= (1 << 13);
for(i = 0; i < 0xfffff; i++)
{
}
}
static inline void slow_blink(void)
{
volatile unsigned int* ptr;
int i;
ptr = (volatile unsigned int*)0x70000020;
*ptr &= ~(1 << 13);
for(i = 0; i < (0xfffff); i++)
{
}
for(i = 0; i < (0xfffff); i++)
{
}
for(i = 0; i < (0xfffff); i++)
{
}
*ptr |= (1 << 13);
for(i = 0; i < (0xfffff); i++)
{
}
for(i = 0; i < (0xfffff); i++)
{
}
for(i = 0; i < (0xfffff); i++)
{
}
}
static inline unsigned long get_pc(void)
{
unsigned long pc;
asm volatile (
"mov %0, pc\n"
: "=r"(pc)
);
return pc;
}
/* These functions are present in the firmware library, but we reimplement
@ -72,7 +100,62 @@ void reset_poweroff_timer(void)
int dbg_ports(void)
{
return 0;
unsigned int gpio_a, gpio_b, gpio_c, gpio_d;
unsigned int gpio_e, gpio_f, gpio_g, gpio_h;
unsigned int gpio_i, gpio_j, gpio_k, gpio_l;
char buf[128];
int line;
lcd_setmargins(0, 0);
lcd_clear_display();
lcd_setfont(FONT_SYSFIXED);
while(1)
{
gpio_a = GPIOA_INPUT_VAL;
gpio_b = GPIOB_INPUT_VAL;
gpio_c = GPIOC_INPUT_VAL;
gpio_g = GPIOG_INPUT_VAL;
gpio_h = GPIOH_INPUT_VAL;
gpio_i = GPIOI_INPUT_VAL;
line = 0;
snprintf(buf, sizeof(buf), "GPIO_A: %02x GPIO_G: %02x", gpio_a, gpio_g);
lcd_puts(0, line++, buf);
snprintf(buf, sizeof(buf), "GPIO_B: %02x GPIO_H: %02x", gpio_b, gpio_h);
lcd_puts(0, line++, buf);
snprintf(buf, sizeof(buf), "GPIO_C: %02x GPIO_I: %02x", gpio_c, gpio_i);
lcd_puts(0, line++, buf);
line++;
gpio_d = GPIOD_INPUT_VAL;
gpio_e = GPIOE_INPUT_VAL;
gpio_f = GPIOF_INPUT_VAL;
gpio_j = GPIOJ_INPUT_VAL;
gpio_k = GPIOK_INPUT_VAL;
gpio_l = GPIOL_INPUT_VAL;
snprintf(buf, sizeof(buf), "GPIO_D: %02x GPIO_J: %02x", gpio_d, gpio_j);
lcd_puts(0, line++, buf);
snprintf(buf, sizeof(buf), "GPIO_E: %02x GPIO_K: %02x", gpio_e, gpio_k);
lcd_puts(0, line++, buf);
snprintf(buf, sizeof(buf), "GPIO_F: %02x GPIO_L: %02x", gpio_f, gpio_l);
lcd_puts(0, line++, buf);
line++;
snprintf(buf, sizeof(buf), "ADC_1: %02x", adc_read(ADC_0));
lcd_puts(0, line++, buf);
snprintf(buf, sizeof(buf), "ADC_2: %02x", adc_read(ADC_1));
lcd_puts(0, line++, buf);
snprintf(buf, sizeof(buf), "ADC_3: %02x", adc_read(ADC_2));
lcd_puts(0, line++, buf);
snprintf(buf, sizeof(buf), "ADC_4: %02x", adc_read(ADC_3));
lcd_puts(0, line++, buf);
lcd_update();
}
return 0;
}
void mpeg_stop(void)
@ -95,3 +178,13 @@ void system_reboot(void)
{
}
void main(void)
{
kernel_init();
adc_init();
lcd_init_device();
dbg_ports();
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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);
}
void lcd_update_rect(int x, int y, int width, int height)
static inline void lcd_bus_idle(void)
{
LCD_CLOCK_GPIO |= (1 << LCD_CLOCK_PIN);
LCD_DATA_OUT_GPIO |= (1 << LCD_DATA_OUT_PIN);
}
void lcd_init_device(void)
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);
}
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();
}
/*** 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;
}