diff --git a/bootloader/sansa_as3525.c b/bootloader/sansa_as3525.c index 7e6ac2d..70b7858 100644 --- a/bootloader/sansa_as3525.c +++ b/bootloader/sansa_as3525.c @@ -58,7 +58,7 @@ void main(void) button_init_device(); int btn = button_read_device(); -#if !defined(SANSA_FUZE) && !defined(SANSA_CLIP) +#if !defined(SANSA_FUZE) && !defined(SANSA_CLIP) && !defined(SANSA_CLIPV2) if (button_hold()) { verbose = true; diff --git a/bootloader/show_logo.c b/bootloader/show_logo.c index c0627aa..90cf222 100644 --- a/bootloader/show_logo.c +++ b/bootloader/show_logo.c @@ -41,7 +41,7 @@ int show_logo( void ) lcd_clear_display(); lcd_setfont(FONT_SYSFIXED); -#ifdef SANSA_CLIP +#if defined(SANSA_CLIP) || defined(SANSA_CLIPV2) /* The top 16 lines of the Sansa Clip screen are yellow, and the bottom 48 are blue, so we reverse the usual positioning */ lcd_putsxy(TEXT_XPOS, 0, BOOT_VERSION); diff --git a/firmware/SOURCES b/firmware/SOURCES index 8e1cef3..b2fd196 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -379,7 +379,9 @@ target/arm/pnx0101/timer-pnx0101.c target/arm/as3525/system-as3525.c target/arm/as3525/kernel-as3525.c target/arm/as3525/timer-as3525.c +#ifndef SANSA_CLIPV2 target/arm/as3525/ata_sd_as3525.c +#endif target/arm/as3525/power-as3525.c target/arm/as3525/usb-as3525.c target/arm/as3525/dma-pl081.c @@ -1149,6 +1151,20 @@ target/arm/tcc77x/c100/audio-c100.c #endif /* SIMULATOR */ #endif /* SANSA_C100 */ +#ifdef SANSA_CLIPV2 +#ifndef SIMULATOR +target/arm/as3525/sansa-clipv2/ata-clipv2.c +target/arm/as3525/sansa-clipv2/lcd-ssd1303.c +target/arm/as3525/sansa-clipv2/lcd-as-clip.S +target/arm/as3525/sansa-clipv2/button-clip.c +target/arm/as3525/sansa-clipv2/backlight-clip.c +#ifndef BOOTLOADER +target/arm/powermgmt-ascodec.c +target/arm/as3525/sansa-clip/powermgmt-clip.c +#endif /* !BOOTLOADER */ +#endif /* !SIMULATOR */ +#endif /* SANSA_CLIPV2 */ + #ifdef SANSA_CLIP #ifndef SIMULATOR target/arm/as3525/sansa-clip/lcd-ssd1303.c diff --git a/firmware/export/config-clip.h b/firmware/export/config-clip.h index 57dd6bf..3352bd3 100644 --- a/firmware/export/config-clip.h +++ b/firmware/export/config-clip.h @@ -122,7 +122,7 @@ #define AB_REPEAT_ENABLE 1 /* FM Tuner */ -#define CONFIG_TUNER SI4700 /* in fact SI4702 but let's hope it's compatible */ +#define CONFIG_TUNER SI4700 /* in fact SI4702 */ //#define HAVE_TUNER_PWR_CTRL /* Define this for LCD backlight available */ diff --git a/firmware/export/config-clipv2.h b/firmware/export/config-clipv2.h new file mode 100644 index 0000000..f8c37b6 --- /dev/null +++ b/firmware/export/config-clipv2.h @@ -0,0 +1,215 @@ +/* + * This config file is for the Sandisk Sansa Clip v2 + */ +#define TARGET_TREE /* this target is using the target tree system */ + +/* For Rolo and boot loader */ +#define MODEL_NUMBER 66 +#define MODEL_NAME "Sandisk Sansa Clipv2" +#define FIRMWARE_OFFSET_FILE_DATA 8 +#define FIRMWARE_OFFSET_FILE_CRC 0 + +#if 0 /* disabled since there is no driver (yet) */ + +#define HW_SAMPR_CAPS (SAMPR_CAP_44) + +/* define this if you have recording possibility */ +#define HAVE_RECORDING + +#define REC_SAMPR_CAPS (SAMPR_CAP_22) +#define REC_FREQ_DEFAULT REC_FREQ_22 /* Default is not 44.1kHz */ +#define REC_SAMPR_DEFAULT SAMPR_22 + +#endif + +/* Define bitmask of input sources - recordable bitmask can be defined + explicitly if different */ +#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_FMRADIO) + +/* define this if you have a bitmap LCD display */ +#define HAVE_LCD_BITMAP + +/* define this if you have a light associated with the buttons */ +#define HAVE_BUTTON_LIGHT + +/* define this if you have access to the quickscreen */ +#define HAVE_QUICKSCREEN + +/* define this if you have access to the pitchscreen */ +#define HAVE_PITCHSCREEN + +/* define this if you would like tagcache to build on this target */ +#define HAVE_TAGCACHE + +/* LCD dimensions */ +#define LCD_WIDTH 128 +#define LCD_HEIGHT 64 +#define LCD_DEPTH 1 + +#define LCD_PIXELFORMAT VERTICAL_PACKING +#define HAVE_NEGATIVE_LCD /* bright on dark */ +#define HAVE_LCD_SPLIT /* split display */ + +/* Display colours, for screenshots and sim (0xRRGGBB) */ +#define LCD_DARKCOLOR 0x000000 +#define LCD_BRIGHTCOLOR 0x000000 +#define LCD_BL_DARKCOLOR 0x000000 +#define LCD_BL_BRIGHTCOLOR 0x0de2e5 + +#define LCD_DARKCOLOR_2 0x000000 +#define LCD_BRIGHTCOLOR_2 0x000000 +#define LCD_BL_DARKCOLOR_2 0x000000 +#define LCD_BL_BRIGHTCOLOR_2 0xffe60f + +#define LCD_SPLIT_POS 16 +#define LCD_SPLIT_LINES 2 + +/* define this if you have LCD enable function */ +#define HAVE_LCD_ENABLE + +#ifndef BOOTLOADER +/* Define this if your LCD can be put to sleep. + * HAVE_LCD_ENABLE should be defined as well. */ +//#define HAVE_LCD_SLEEP +//#define HAVE_LCD_SLEEP_SETTING +#endif + +/* define this if you can flip your LCD */ +#define HAVE_LCD_FLIP + +/* define this if you can invert the pixels */ +#define HAVE_LCD_INVERT + +/* Define this if your LCD can set contrast */ +#define HAVE_LCD_CONTRAST + +#define MIN_CONTRAST_SETTING 0 +#define MAX_CONTRAST_SETTING 50 +#define DEFAULT_CONTRAST_SETTING 30 + +#define IRAM_LCDFRAMEBUFFER IDATA_ATTR /* put the lcd frame buffer in IRAM */ + +#define CONFIG_KEYPAD SANSA_CLIP_PAD + +/* define this if the target has volume keys which can be used in the lists */ +#define HAVE_VOLUME_IN_LIST + +/* Define this if you do software codec */ +#define CONFIG_CODEC SWCODEC +/* There is no hardware tone control */ +#define HAVE_SW_TONE_CONTROLS + +/* We're working on the assumption that the AS3525 has something + similar to the AS3514 for audio codec etc */ +#define HAVE_AS3514 + +/* define this if you have a real-time clock */ +#ifndef BOOTLOADER +#define CONFIG_RTC RTC_AS3514 +#endif + +/* Define this if you have a software controlled poweroff */ +#define HAVE_SW_POWEROFF + +#define HAVE_FAT16SUPPORT + +/* The number of bytes reserved for loadable codecs */ +#define CODEC_SIZE 0x100000 + +/* The number of bytes reserved for loadable plugins */ +#define PLUGIN_BUFFER_SIZE 0x80000 + +#define AB_REPEAT_ENABLE 1 + +/* FM Tuner */ +#define CONFIG_TUNER SI4700 /* in fact SI4702 */ +//#define HAVE_TUNER_PWR_CTRL + +/* Define this for LCD backlight available */ +#define HAVE_BACKLIGHT + +/* define this if you have a flash memory storage */ +#define HAVE_FLASH_STORAGE + +/* define this if the flash memory uses the SecureDigital Memory Card protocol */ +#define CONFIG_STORAGE STORAGE_SD + +#define BATTERY_CAPACITY_DEFAULT 380 /* default battery capacity */ +#define BATTERY_CAPACITY_MIN 380 /* min. capacity selectable */ +#define BATTERY_CAPACITY_MAX 380 /* max. capacity selectable */ +#define BATTERY_CAPACITY_INC 0 /* capacity increment */ +#define BATTERY_TYPES_COUNT 1 /* only one type */ + +/* Charging implemented in a target-specific algorithm */ +#define CONFIG_CHARGING CHARGING_TARGET + +/* define this if the unit can be powered or charged via USB */ +#define HAVE_USB_POWER + +/** Non-simulator section **/ +#ifndef SIMULATOR + +/* Define this if you have a AMS AS3525 SoC */ +#define CONFIG_CPU AS3525 /* FIXME: AS3531? */ + +/* Define this if you want to use the AS3525 i2c interface */ +#define CONFIG_I2C I2C_AS3525 + +/* define this if the hardware can be powered off while charging */ +/* Sansa can't be powered off while charging */ +/* #define HAVE_POWEROFF_WHILE_CHARGING */ + +/* The start address index for ROM builds */ +#define ROM_START 0x00000000 + +/* Define this to the CPU frequency */ +#define CPU_FREQ 250000000 + +/* Type of LCD */ +#define CONFIG_LCD LCD_SSD1303 + +#ifndef BOOTLOADER + +#define USB_HANDLED_BY_OF + +#if 0 /* disabled since there is no USB driver */ + +/* USB On-the-go */ +#define CONFIG_USBOTG USBOTG_ARC + +/* enable these for the experimental usb stack */ +#define HAVE_USBSTACK +#define USB_VENDOR_ID 0x0781 +#define USB_PRODUCT_ID 0x7433 +#endif /* BOOTLOADER */ + +#endif + + +/* Virtual LED (icon) */ +#define CONFIG_LED LED_VIRTUAL + +/* Define this if you have adjustable CPU frequency */ +#define HAVE_ADJUSTABLE_CPU_FREQ + +#define BOOTFILE_EXT "sansa" +#define BOOTFILE "rockbox." BOOTFILE_EXT +#define BOOTDIR "/.rockbox" + +#define ICODE_ATTR_TREMOR_NOT_MDCT + +#define INCLUDE_TIMEOUT_API + +#endif /* SIMULATOR */ + +/** Port-specific settings **/ + +/* Main LCD backlight brightness range and defaults */ +#define MIN_BRIGHTNESS_SETTING 1 +#define MAX_BRIGHTNESS_SETTING 12 +#define DEFAULT_BRIGHTNESS_SETTING 6 + +/* Default recording levels */ +#define DEFAULT_REC_MIC_GAIN 23 +#define DEFAULT_REC_LEFT_GAIN 23 +#define DEFAULT_REC_RIGHT_GAIN 23 diff --git a/firmware/export/config.h b/firmware/export/config.h index aa3f4f8..f8472ae 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -362,6 +362,8 @@ Lyre prototype 1*/ #include "config-ondavx767.h" #elif defined(SANSA_CLIP) #include "config-clip.h" +#elif defined(SANSA_CLIPV2) +#include "config-clipv2.h" #elif defined(SANSA_E200V2) #include "config-e200v2.h" #elif defined(SANSA_M200V4) @@ -605,15 +607,13 @@ Lyre prototype 1*/ #if (CONFIG_CPU == IMX31L) #define CPU_ARM #define ARM_ARCH 6 /* ARMv6 */ -#endif -#if defined(CPU_TCC77X) || defined(CPU_TCC780X) || (CONFIG_CPU == DM320) \ - || (CONFIG_CPU == AT91SAM9260) +#elif defined(CPU_TCC77X) || defined(CPU_TCC780X) || (CONFIG_CPU == DM320) \ + || (CONFIG_CPU == AT91SAM9260) || defined(SANSA_CLIPV2) #define CPU_ARM #define ARM_ARCH 5 /* ARMv5 */ -#endif -#if defined(CPU_PP) || (CONFIG_CPU == PNX0101) || (CONFIG_CPU == S3C2440) \ +#elif defined(CPU_PP) || (CONFIG_CPU == PNX0101) || (CONFIG_CPU == S3C2440) \ || (CONFIG_CPU == DSC25) || (CONFIG_CPU == S5L8700) || (CONFIG_CPU == AS3525) #define CPU_ARM #define ARM_ARCH 4 /* ARMv4 */ diff --git a/firmware/target/arm/as3525/boot.lds b/firmware/target/arm/as3525/boot.lds index 9c6d6fa..dcc291b 100644 --- a/firmware/target/arm/as3525/boot.lds +++ b/firmware/target/arm/as3525/boot.lds @@ -6,24 +6,29 @@ OUTPUT_FORMAT(elf32-littlearm) OUTPUT_ARCH(arm) STARTUP(target/arm/crt0.o) -#define IRAMORIG 0x81000000 -#define IRAMSIZE 0x50000 +#ifdef SANSA_CLIPV2 +#define RAMORIG 0x0 /* DRAM */ +#define RAMSIZE (MEM*0x100000) +#else +#define RAMORIG 0x81000000 /* IRAM */ +#define RAMSIZE 0x50000 +#endif MEMORY { - IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE + RAM : ORIGIN = RAMORIG, LENGTH = RAMSIZE } SECTIONS { - . = IRAMORIG; + . = RAMORIG; .text : { *(.init.text) *(.glue_7) *(.glue_7t) *(.text*) - } > IRAM + } > RAM .data : { *(.icode) @@ -33,7 +38,7 @@ SECTIONS *(.ncdata*) *(.rodata*) _dataend = . ; - } > IRAM + } > RAM .stack : { @@ -43,7 +48,7 @@ SECTIONS . += 0x2000; _stackend = .; stackend = .; - } > IRAM + } > RAM .bss : { _edata = .; @@ -52,5 +57,5 @@ SECTIONS *(COMMON) *(.ncbss*); _end = .; - } > IRAM + } > RAM } diff --git a/firmware/target/arm/as3525/clock-target.h b/firmware/target/arm/as3525/clock-target.h index 560e067..0dc6874 100644 --- a/firmware/target/arm/as3525/clock-target.h +++ b/firmware/target/arm/as3525/clock-target.h @@ -56,12 +56,16 @@ #define AS3525_CLK_FCLK 3 /* Available as PCLK input only */ /** ************ Change these to reconfigure clocking scheme *******************/ +#ifdef SANSA_CLIPV2 +#define AS3525_PLLA_FREQ 240000000 +#else /* PLL frequencies and settings*/ #define AS3525_PLLA_FREQ 248000000 /*124,82.7,62,49.6,41.3,35.4 */ /* FCLK_PREDIV-> *7/8 = 217MHz 108.5 ,72.3, 54.25, 43.4, 36.17 */ /* *6/8 = 186MHz 93, 62, 46.5, 37.2 */ /* *5/8 = 155MHz 77.5, 51.67, 38.75 */ #define AS3525_PLLA_SETTING 0x261F +#endif //#define AS3525_PLLA_FREQ 384000000 /*192,128,96,76.8,64,54.9,48,42.7,38.4*/ /* FCLK_PREDIV-> *7/8 = 336MHz 168, 112, 84, 67.2, 56, 48, 42, 37.3*/ @@ -118,9 +122,14 @@ #define AS3525_IDE_SEL AS3525_CLK_PLLA /* Input Source */ #define AS3525_IDE_DIV (CLK_DIV(AS3525_PLLA_FREQ, AS3525_IDE_FREQ) - 1)/*div=1/(n+1)*/ +#ifdef SANSA_CLIPV2 + #define AS3525_MS_FREQ 120000000 +#define AS3525_IDE_FREQ 80000000 +#else #define AS3525_IDE_FREQ 90000000 /* The OF uses 66MHz maximal freq but sd transfers fail on some players with this limit */ +#endif //#define AS3525_USB_SEL AS3525_CLK_PLLA /* Input Source */ //#define AS3525_USB_DIV /* div = 1/(n=0?1:2n)*/ diff --git a/firmware/target/arm/as3525/dma-pl081.c b/firmware/target/arm/as3525/dma-pl081.c index 52fd90f..dd15bb4 100644 --- a/firmware/target/arm/as3525/dma-pl081.c +++ b/firmware/target/arm/as3525/dma-pl081.c @@ -24,9 +24,19 @@ #include "pl081.h" #include "dma-target.h" #include "panic.h" +#include "kernel.h" static int dma_used = 0; static void (*dma_callback[2])(void); /* 2 channels */ +static struct wakeup wait_transfer; + +void dma_wait(int channel) +{ + if(channel != 0) + panicf("dma_wait : only ata"); + + wakeup_wait(&wait_transfer, TIMEOUT_BLOCK); +} void dma_retain(void) { @@ -50,6 +60,8 @@ void dma_init(void) { DMAC_SYNC = 0xffff; /* disable synchronisation logic */ VIC_INT_ENABLE |= INTERRUPT_DMAC; + + wakeup_init(&wait_transfer); } inline void dma_disable_channel(int channel) @@ -117,5 +129,8 @@ void INT_DMAC(void) if(dma_callback[channel]) dma_callback[channel](); + + if(channel == 0) + wakeup_signal(&wait_transfer); } } diff --git a/firmware/target/arm/as3525/dma-target.h b/firmware/target/arm/as3525/dma-target.h index 8121397..c920003 100644 --- a/firmware/target/arm/as3525/dma-target.h +++ b/firmware/target/arm/as3525/dma-target.h @@ -39,3 +39,4 @@ inline void dma_disable_channel(int channel); void dma_retain(void); void dma_release(void); +void dma_wait(int channel); diff --git a/firmware/target/arm/as3525/fmradio-i2c-as3525.c b/firmware/target/arm/as3525/fmradio-i2c-as3525.c index 99b9bdf..58cb71a 100644 --- a/firmware/target/arm/as3525/fmradio-i2c-as3525.c +++ b/firmware/target/arm/as3525/fmradio-i2c-as3525.c @@ -37,6 +37,12 @@ #define I2C_SCL_PIN 4 #define I2C_SDA_PIN 5 +#elif defined(SANSA_CLIPV2) +#define I2C_GPIO(x) GPIOB_PIN(x) +#define I2C_GPIO_DIR GPIOB_DIR +#define I2C_SCL_PIN 6 +#define I2C_SDA_PIN 7 + #elif defined(SANSA_M200V4) #define I2C_GPIO(x) GPIOD_PIN(x) #define I2C_GPIO_DIR GPIOD_DIR diff --git a/firmware/target/arm/as3525/sansa-clipv2/ata-clipv2.c b/firmware/target/arm/as3525/sansa-clipv2/ata-clipv2.c new file mode 100644 index 0000000..33c2a4a --- /dev/null +++ b/firmware/target/arm/as3525/sansa-clipv2/ata-clipv2.c @@ -0,0 +1,790 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2006 Daniel Ankers + * Copyright © 2008-2009 Rafaël Carré + * + * 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 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +/* Driver for the SD controller inside AS3531 SoC */ + +#include "config.h" /* for HAVE_MULTIVOLUME */ +#include "fat.h" +#include "thread.h" +#include "hotswap.h" +#include "system.h" +#include "cpu.h" +#include +#include +#include +#include "as3525.h" +#include "pl081.h" /* DMA controller */ +#include "dma-target.h" /* DMA request lines */ +#include "clock-target.h" +#include "panic.h" +#include "stdbool.h" +#include "ata_idle_notify.h" +#include "sd.h" + +#include "lcd.h" +#include +#include "sysfont.h" + +static int line = 0; +static void printf(const char *format, ...) +{ + char buf[50]; + int len; + va_list ap; + va_start(ap, format); + + len = vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + lcd_puts(0, line++, buf); + lcd_update(); + if(line >= LCD_HEIGHT/SYSFONT_HEIGHT) + line = 0; +} + +/* command flags */ +#define MCI_NO_RESP (0<<0) +#define MCI_RESP (1<<0) +#define MCI_LONG_RESP (1<<1) + +/* controller registers */ +#define SD_BASE 0xC6070000 + +/* + * REGISTERS + * + * m = modify (orr/bic), r = read, w = write + * + * 00 m/r/w + * 04 m/w + * 08 m + * 0C ? + * 10 r/w + * 14 w + * 18 m + * 1C w ==> set a bit before transfer (sometimes) ! + * 20 w ==> set a bit before transfer ! + * 24 w irq mask ? + * 28 w arg + * 2C r/w cmd + * 30 r resp0 + * 34 r resp1 + * 38 r resp2 + * 3C r resp3 + * 40 r irq status (only read in isr) + * 44 m/w irq clear + * 48 r + * 4C m + * 64 w + * 70 r + * 100 FIFO + */ + +/* + * STATUS register + * & 0xBA80 + * & 8 + * & 0x428 + * & 0x418 + */ + +/* + * INFO on CMD register + * + * if(cmd >= 200) cmd -= 200; (>= 200 = acmd?) + * + * COMMANDS (| (x<<16) BITS RESPONSE + * + * 1 ? reserved & ~0x80, | 0x40, | 0x8000 ? + * 5 ? reserved for I/O cards & ~0x80, | 0x40 ? + * 11 ? reserved & ~0x80, | 0x40, | 0x2200, | 0x800 ? + * 14 ? reserved & ~0x80, | 0x40, | 0x2200, ~0x1000 ? + * 19 ? reserved & ~0x80, |0x40, | 0x2700, & ~0x1000 ? + * 20 ? reserved & ~0x80, |0x40, | 0x2700, | 0x800 ? + * 23 ? reserved & ~0x80, | 0x40 ? + * 39 ? reserved & ~0x80, | 0x40 ? + * 51 ? reserved & ~0x80, | 0x40, | 0x2000, | 0x200 ? + * 52 ? reserved for I/O & ~0x80, | 0x40 ? + * 53 ? reserved for I/O & ~0x80, | 0x40, | 0x2200, & ~0x1000 ? + * 253 ? & ~0x80, |0x40, | 0x2700, & ~0x1000 ? + * + * 0 GO IDLE STATE & ~0x4000, & ~0xC0, | 0x4000 no + * 2 ALL SEND CID & ~0x4000, |0xC0 r2 + * 3 SEND RCA & ~0x80, | 0x40 r6 + * 6 SWITCH_FUNC & ~0x80, | 0x40 r1 + * 7 SELECT CARD & ~0x80, | 0x40 r1b + * 8 SEND IF COND & ~0x80, | 0x40, | 0x2200, & ~0x1000 r7 + * 9 SEND CSD & ~0x4000, | 0xc0 r2 + * 12 STOP TRANSMISSION & ~0x80, | 0x40, | 0x4000 r1b + * 13 SEND STATUS & ~0x80, | 0x40 r1 + * 15 GO INACTIVE STATE & ~0x4000, & ~0xC0 no + * 16 SET BLOCKLEN & ~0x80, | 0x40 r1 + * 17 READ SINGLE BLOCK & ~0x80, | 0x40, | 0x2200 r1 + * 18 READ MULTIPLE BLOCK & ~0x80, | 0x40, | 0x2200 r1 + * 24 WRITE BLOCK & ~0x80, |0x40, | 0x2700 r1 + * 25 WRITE MULTIPLE BLOCK & ~0x80, |0x40, | 0x2700 r1 + * 41 SEND APP OP COND & ~0x80, | 0x40 r3 + * 42 LOCK UNLOCK & ~0x80, |0x40, | 0x2700 r1 + * 55 APP CMD & ~0x80, | 0x40 r1 + * 206 SET BUS WIDTH & ~0x80, | 0x40, | 0x2000 r1 + * 207 SELECT CARD ? & ~0x4000, & ~0xC0 r1b + * + * + * bits 5:0 = cmd + * bit 6 (0x40) = response + * bit 7 (0x80) = long response + * => like pl180 <= + * BIT SET IN COMANDS: + * + * bit 8 (0x100) ? write block, write multi_block, lock/unlock + * bit 9 (0x200) ? send if cond, read block, read multi_block, write block, write multi_block, lock/unlock + * bit 10 (0x400) ? write block, write multi_block, lock/unlock + * bit 11 (0x800) ? + * bit 12 (0x1000) ? + * bit 13 (0x2000) ? send if cond, read block, read multi_block, write block, write multi_block, lock/unlock, set bus width + * bit 14 (0x4000) ? go idle state, stop transmission + * bit 15 (0x8000) ? + * + */ + +/* FIXME */ +#define MCI_POWER +#define MCI_CLOCK +#define MCI_ARGUMENT (*(volatile unsigned long *) (SD_BASE+0x28)) +#define MCI_COMMAND (*(volatile unsigned long *) (SD_BASE+0x2C)) +#define MCI_RESPCMD +#define MCI_RESP0 (*(volatile unsigned long *) (SD_BASE+0x30)) +#define MCI_RESP1 (*(volatile unsigned long *) (SD_BASE+0x34)) +#define MCI_RESP2 (*(volatile unsigned long *) (SD_BASE+0x38)) +#define MCI_RESP3 (*(volatile unsigned long *) (SD_BASE+0x3C)) +#define MCI_DATA_TIMER +#define MCI_DATA_LENGTH +#define MCI_DATA_CTRL +#define MCI_STATUS (*(volatile unsigned long *) (SD_BASE+0x40)) +#define MCI_CLEAR (*(volatile unsigned long *) (SD_BASE+0x44)) +#define MCI_MASK (*(volatile unsigned long *) (SD_BASE+0x24)) +#define MCI_SELECT + +#define MCI_ERROR 0 + +#define MCI_FIFO ((unsigned long *) (SD_BASE+0x100)) + +#define MCI_COMMAND_ENABLE (1<<31) +#define MCI_COMMAND_ACTIVE MCI_COMMAND_ENABLE +#define MCI_COMMAND_RESPONSE (1<<6) +#define MCI_COMMAND_LONG_RESPONSE (1<<7) + + + +static int sd_init_card(void); +static void init_controller(void); +/* TODO : BLOCK_SIZE != SECTOR_SIZE ? */ +#define BLOCK_SIZE 512 +#define SECTOR_SIZE 512 + +static tCardInfo card_info; + +/* for compatibility */ +static long last_disk_activity = -1; + +#define MIN_YIELD_PERIOD 5 /* ticks */ +static long next_yield = 0; + +static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)]; +static const char sd_thread_name[] = "ata/sd"; +static struct mutex sd_mtx SHAREDBSS_ATTR; +static struct event_queue sd_queue; +#ifndef BOOTLOADER +static bool sd_enabled = false; +#endif + +//static struct wakeup transfer_completion_signal; +static volatile bool retry; + +static inline void mci_delay(void) { int i = 0xffff; while(i--) ; } + +void INT_NAND(void) +{ + (*(volatile unsigned long *) (SD_BASE+0x0)) &= ~0x10; // ? + const int status = MCI_STATUS; + +#if 0 + if(status & MCI_ERROR) + retry = true; +#endif + +// wakeup_signal(&transfer_completion_signal); + MCI_CLEAR = status; + + static int x = 0; + switch(status) + { + case 0x4: /* cmd received ? */ + case 0x104: /* ? 1 time in init (10th interrupt) */ + case 0x2000: /* ? after cmd read_mul_blocks | 0x2200 */ + + case 0x820: /* ? 1 time while manual copy from FIFO */ + case 0x20: /* ? rx fifo empty */ + break; + default: + printf("%2d NAND 0x%x", ++x, status); + int delay = 0x100000; while(delay--) ; + } + /* + * 0x48 = some kind of status + * 0x106 + * 0x4106 + * 1B906 + * 1F906 + * 1B906 + * 1F906 + * 1F906 + * 1906 + * ... + * 6906 + * 6D06 (dma) + * + * read resp (6, 7, 12, 42) : while bit 9 is unset ; + * + */ + printf("%x %x", status, (*(volatile unsigned long *) (SD_BASE+0x48))); + //while(!button_read_device()); + //while(button_read_device()); + + (*(volatile unsigned long *) (SD_BASE+0x0)) |= 0x10; // ? +} + +static bool send_cmd(const int cmd, const int arg, const int flags, + unsigned long *response) +{ + int val; + val = cmd | MCI_COMMAND_ENABLE; + if(flags & MCI_RESP) + { + val |= MCI_COMMAND_RESPONSE; + if(flags & MCI_LONG_RESP) + val |= MCI_COMMAND_LONG_RESPONSE; + } + + if(cmd == 18) /* r */ + val |= 0x2200; + else if(cmd == 25) /* w */ + val |= 0x2700; + + int tmp = (*(volatile unsigned long *) (SD_BASE+0x10)); + (*(volatile unsigned long *) (SD_BASE+0x10)) = 0; + + MCI_COMMAND = 0x80202000; + MCI_ARGUMENT = 0; + int max = 10; + while(max-- && MCI_COMMAND & MCI_COMMAND_ACTIVE); + + (*(volatile unsigned long *) (SD_BASE+0x08)) &= ~0xff; + (*(volatile unsigned long *) (SD_BASE+0x08)) |= 0; + + MCI_COMMAND = 0x80202000; + MCI_ARGUMENT = 0; + max = 10; + while(max-- && MCI_COMMAND & MCI_COMMAND_ACTIVE); + + (*(volatile unsigned long *) (SD_BASE+0x10)) = tmp; + + MCI_COMMAND = 0x80202000; + MCI_ARGUMENT = 0; + max = 10; + while(max-- && MCI_COMMAND & MCI_COMMAND_ACTIVE); + + mci_delay(); + + MCI_ARGUMENT = arg; + MCI_COMMAND = val; + + (*(volatile unsigned long *) (SD_BASE+0x00)) |= 0x10; + + max = 1000; + while(max-- && MCI_COMMAND & MCI_COMMAND_ACTIVE); /* wait for cmd completion */ + if(!max) + return false; + + if(flags & MCI_RESP) + { + if(flags & MCI_LONG_RESP) + { + /* store the response in little endian order for the words */ + response[0] = MCI_RESP3; + response[1] = MCI_RESP2; + response[2] = MCI_RESP1; + response[3] = MCI_RESP0; + } + else + response[0] = MCI_RESP0; + } + return true; +} + +static int sd_init_card(void) +{ + unsigned long response; + unsigned long temp_reg[4]; + int max_tries = 100; /* max acmd41 attemps */ + bool sdhc; + int i; + + if(!send_cmd(SD_GO_IDLE_STATE, 0, MCI_NO_RESP, NULL)) + return -1; + + mci_delay(); + + sdhc = false; + if(send_cmd(SD_SEND_IF_COND, 0x1AA, MCI_RESP, &response)) + if((response & 0xFFF) == 0x1AA) + sdhc = true; + + do { + /* some MicroSD cards seems to need more delays, so play safe */ + mci_delay(); + mci_delay(); + mci_delay(); + + /* app_cmd */ + if( !send_cmd(SD_APP_CMD, 0, MCI_RESP, &response) /*|| + !(response & (1<<5))*/ ) + { + return -2; + } + + /* acmd41 */ + if(!send_cmd(SD_APP_OP_COND, (sdhc ? 0x40FF8000 : (1<<23)), + MCI_RESP, &card_info.ocr)) + return -3; + } while(!(card_info.ocr & (1<<31)) && max_tries--); + + if(max_tries < 0) + return -4; + + mci_delay(); + mci_delay(); + mci_delay(); + + /* send CID */ + if(!send_cmd(SD_ALL_SEND_CID, 0, MCI_RESP|MCI_LONG_RESP, card_info.cid)) + return -5; + + /* send RCA */ + if(!send_cmd(SD_SEND_RELATIVE_ADDR, 0, MCI_RESP, &card_info.rca)) + return -6; + + /* send CSD */ + if(!send_cmd(SD_SEND_CSD, card_info.rca, + MCI_RESP|MCI_LONG_RESP, temp_reg)) + return -7; + + for(i=0; i<4; i++) + card_info.csd[3-i] = temp_reg[i]; + + sd_parse_csd(&card_info); + + if(!send_cmd(SD_APP_CMD, 0, MCI_RESP, &response) || + !send_cmd(42, 0, MCI_NO_RESP, NULL)) /* disconnect the 50 KOhm pull-up + resistor on CD/DAT3 */ + return -13; + + if(!send_cmd(SD_APP_CMD, card_info.rca, MCI_NO_RESP, NULL)) + return -10; + + if(!send_cmd(SD_SET_BUS_WIDTH, card_info.rca | 2, MCI_NO_RESP, NULL)) + return -11; + + (*(volatile unsigned long *) (SD_BASE+0x18)) &= ~(0x10001); + (*(volatile unsigned long *) (SD_BASE+0x18)) |= 0x1; + + if(!send_cmd(SD_SELECT_CARD, card_info.rca, MCI_NO_RESP, NULL)) + return -9; + + /* not sent in init_card() by OF */ + if(!send_cmd(SD_SET_BLOCKLEN, card_info.blocksize, MCI_NO_RESP, + NULL)) + return -12; + + card_info.initialized = 1; + + return 0; +} + +static void sd_thread(void) __attribute__((noreturn)); +static void sd_thread(void) +{ + struct queue_event ev; + bool idle_notified = false; + + while (1) + { + queue_wait_w_tmo(&sd_queue, &ev, HZ); + + switch ( ev.id ) + { + case SYS_TIMEOUT: + if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ))) + { + idle_notified = false; + } + else + { + /* never let a timer wrap confuse us */ + next_yield = current_tick; + + if (!idle_notified) + { + call_storage_idle_notifys(false); + idle_notified = true; + } + } + break; +#if 0 + case SYS_USB_CONNECTED: + usb_acknowledge(SYS_USB_CONNECTED_ACK); + /* Wait until the USB cable is extracted again */ + usb_wait_for_disconnect(&sd_queue); + + break; + case SYS_USB_DISCONNECTED: + usb_acknowledge(SYS_USB_DISCONNECTED_ACK); + break; +#endif + } + } +} + +static void init_controller(void) +{ + int tmp = (*(volatile unsigned long *) (SD_BASE+0x70)); + int shift = 1 + ((tmp << 26) >> 27); + + (*(volatile unsigned long *) (SD_BASE+0x04)) &= ~((1 << shift) -1); + (*(volatile unsigned long *) (SD_BASE+0x04)) = (1 << shift) -1; + + mci_delay(); + + (*(volatile unsigned long *) (SD_BASE+0x00)) |= 1; + int max = 1000; + while(max-- && !(*(volatile unsigned long *) (SD_BASE+0x00)) & 1) + ; + + MCI_CLEAR = 0xffffffff; + MCI_MASK = 0xffffbffe; + + (*(volatile unsigned long *) (SD_BASE+0x00)) |= 0x10; + (*(volatile unsigned long *) (SD_BASE+0x14)) = 0xffffffff; + + (*(volatile unsigned long *) (SD_BASE+0x10)) = (1<sector_size=card_info.blocksize; + info->num_sectors=card_info.numblocks; + info->vendor="Rockbox"; + info->product = "Internal Storage"; + info->revision="0.00"; +} +#endif + +static int sd_wait_for_state(unsigned int state) +{ + unsigned long response; + unsigned int timeout = 100; /* ticks */ + long t = current_tick; + + while (1) + { + long tick; + + if(!send_cmd(SD_SEND_STATUS, card_info.rca, + MCI_RESP, &response)) + return -1; + + if (((response >> 9) & 0xf) == state) + return 0; + + if(TIME_AFTER(current_tick, t + timeout)) + return -10 * ((response >> 9) & 0xf); + + if (TIME_AFTER((tick = current_tick), next_yield)) + { + yield(); + timeout += current_tick - tick; + next_yield = tick + MIN_YIELD_PERIOD; + } + } +} + +static int sd_transfer_sectors(unsigned long start, int count, void* buf, bool write) +{ + int ret = 0; + + if((int)buf & 3) + panicf("unaligned transfer"); + + /* skip SanDisk OF */ + start += 0xf000; + + mutex_lock(&sd_mtx); +#ifndef BOOTLOADER + sd_enable(true); +#endif + + if (card_info.initialized <= 0) + { + ret = sd_init_card(); + if (!(card_info.initialized)) + { + panicf("card not initialised (%d)", ret); + goto sd_transfer_error; + } + } + + last_disk_activity = current_tick; + ret = sd_wait_for_state(SD_TRAN); + if (ret < 0) + { + const char *st[9] = { + "IDLE", "RDY", "IDENT", "STBY", "TRAN", "DATA", "RCV", "PRG", "DIS" + }; + if(ret <= -10) + panicf("wait for state failed (%s)", st[(-ret / 10) % 9]); + else + panicf("wait for state failed"); + goto sd_transfer_error; + } + + dma_retain(); + + while(count) + { + /* Interrupt handler might set this to true during transfer */ + retry = false; + /* 128 * 512 = 2^16, and doesn't fit in the 16 bits of DATA_LENGTH + * register, so we have to transfer maximum 127 sectors at a time. */ + //unsigned int transfer = (count >= 128) ? 127 : count; /* sectors */ + unsigned int transfer = count; + + const int cmd = + write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK; + + (*(volatile unsigned long *) (SD_BASE+0x00)) |= 2; + while(( *(volatile unsigned long *) (SD_BASE+0x00)) & 2) ; + + //(*(volatile unsigned long *) (SD_BASE+0x1c)) = 512; + (*(volatile unsigned long *) (SD_BASE+0x20)) = transfer * 512; + + (*(volatile unsigned long *) (SD_BASE+0x00)) |= 2; + while(( *(volatile unsigned long *) (SD_BASE+0x00)) & 2) ; + + (*(volatile unsigned long *) (SD_BASE+0x4c)) &= ~0x7fff0fff; + + if(0) + { + (*(volatile unsigned long *) (SD_BASE+0x00)) |= 0x20; + MCI_MASK = 0xBE8C; + (*(volatile unsigned long *) (SD_BASE+0x4c)) |= 0x503f0080; + } + else + { + MCI_MASK = 0xBEB8; + (*(volatile unsigned long *) (SD_BASE+0x4c)) |= 0x3f0030; + } + + if(card_info.ocr & (1<<30) ) /* SDHC */ + ret = send_cmd(cmd, start, MCI_NO_RESP, NULL); + else + ret = send_cmd(cmd, start * BLOCK_SIZE, + MCI_NO_RESP, NULL); + + if (ret < 0) + panicf("transfer multiple blocks failed (%d)", ret); + + if(write) + dma_enable_channel(0, buf, MCI_FIFO, DMA_PERI_SD, + DMAC_FLOWCTRL_PERI_MEM_TO_PERI, true, false, 0, DMA_S8, NULL); + else + dma_enable_channel(0, MCI_FIFO, buf, DMA_PERI_SD, + DMAC_FLOWCTRL_PERI_PERI_TO_MEM, false, true, 0, DMA_S8, NULL); + + line = 0; + lcd_clear_display(); + printf("dma ->"); + dma_wait(0); +// wakeup_wait(&transfer_completion_signal, TIMEOUT_BLOCK); + printf("dma <-"); + int delay = 0x1000000; while(delay--) ; + + if(!retry) + { + buf += transfer * SECTOR_SIZE; + start += transfer; + count -= transfer; + } + + last_disk_activity = current_tick; + + if(!send_cmd(SD_STOP_TRANSMISSION, 0, MCI_NO_RESP, NULL)) + { + ret = -666; + panicf("STOP TRANSMISSION failed"); + goto sd_transfer_error; + } + + ret = sd_wait_for_state(SD_TRAN); + if (ret < 0) + { + panicf(" wait for state TRAN failed (%d)", ret); + goto sd_transfer_error; + } + } + + dma_release(); + +#ifndef BOOTLOADER + sd_enable(false); +#endif + mutex_unlock(&sd_mtx); + return 0; + +sd_transfer_error: + panicf("transfer error : %d",ret); + card_info.initialized = 0; + return ret; +} + +int sd_read_sectors(unsigned long start, int count, void* buf) +{ + return sd_transfer_sectors(start, count, buf, false); +} + +int sd_write_sectors(unsigned long start, int count, const void* buf) +{ +#if defined(BOOTLOADER) || defined(SANSA_CLIPV2) /* we don't need write support in bootloader */ + (void) start; + (void) count; + (void) buf; + return -1; +#else + return sd_transfer_sectors(start, count, (void*)buf, true); +#endif +} + +#ifndef BOOTLOADER +void sd_sleep(void) +{ +} + +void sd_spin(void) +{ +} + +void sd_spindown(int seconds) +{ + (void)seconds; +} + +long sd_last_disk_activity(void) +{ + return last_disk_activity; +} + +void sd_enable(bool on) +{ +#if 0 + if (sd_enabled == on) + return; /* nothing to do */ + if(on) + { + } + else + { + } +#else + /* TODO */ + (void)on; + return; +#endif +} + +tCardInfo *card_get_info_target(int card_no) +{ + (void)card_no; + return &card_info; +} + +#endif /* BOOTLOADER */ diff --git a/firmware/target/arm/as3525/sansa-clipv2/backlight-clip.c b/firmware/target/arm/as3525/sansa-clipv2/backlight-clip.c new file mode 100644 index 0000000..5c0e16b --- /dev/null +++ b/firmware/target/arm/as3525/sansa-clipv2/backlight-clip.c @@ -0,0 +1,51 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright © 2009 Rafaël Carré + * + * 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 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "backlight-target.h" +#include "lcd.h" +#include "as3525.h" +#include "ascodec-target.h" + +void _backlight_on(void) +{ + ascodec_write(0x25, ascodec_read(0x25) | 2); /* lcd power */ + ascodec_write(0x1c, 8|1); + ascodec_write(0x1b, 0x90); + lcd_enable(true); +} + +void _backlight_off(void) +{ + ascodec_write(0x25, ascodec_read(0x25) & ~2); /* lcd power */ + lcd_enable(false); +} + +void _buttonlight_on(void) +{ + GPIOA_DIR |= (1<<5); + GPIOA_PIN(5) = (1<<5); /* set pin a5 high */ +} + +void _buttonlight_off(void) +{ + GPIOA_DIR |= (1<<5); + GPIOA_PIN(5) = 0; /* set pin a5 low */ +} diff --git a/firmware/target/arm/as3525/sansa-clipv2/backlight-target.h b/firmware/target/arm/as3525/sansa-clipv2/backlight-target.h new file mode 100644 index 0000000..d202408 --- /dev/null +++ b/firmware/target/arm/as3525/sansa-clipv2/backlight-target.h @@ -0,0 +1,32 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright © 2009 Rafaël Carré + * + * 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 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef BACKLIGHT_TARGET_H +#define BACKLIGHT_TARGET_H + +#define _backlight_init() true + +void _backlight_on(void); +void _backlight_off(void); + +void _buttonlight_on(void); +void _buttonlight_off(void); + +#endif diff --git a/firmware/target/arm/as3525/sansa-clipv2/button-clip.c b/firmware/target/arm/as3525/sansa-clipv2/button-clip.c new file mode 100644 index 0000000..5987c58 --- /dev/null +++ b/firmware/target/arm/as3525/sansa-clipv2/button-clip.c @@ -0,0 +1,96 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2008 François Dinel + * Copyright © 2008-2009 Rafaël Carré + * + * 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 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "button-target.h" +#include "as3525.h" + +void button_init_device(void) +{ + GPIOA_DIR &= ~((1<<7) | (1<<3)); + GPIOD_DIR &= ~((1<<2) | (1<<1) | (1<<0)); + GPIOD_PIN(3) = 1<<3; + GPIOD_PIN(4) = 1<<4; + GPIOD_PIN(5) = 1<<5; + GPIOD_DIR |= ((1<<5) | (1<<4) | (1<<3)); +} + +int button_read_device(void) +{ + int result = 0; + + if(button_hold()) + return result; + + /* direct GPIO connections */ + + if (GPIOA_PIN(7)) + result |= BUTTON_POWER; + + /* This is a keypad using D3-D5 as columns and D0-D2 as rows */ + + GPIOD_PIN(3) = 0x00; /* activate D3 */ + asm volatile ("nop\nnop\nnop\nnop\nnop\n"); /* wait a bit for reliable results */ + + /* D3D0 is unused */ + + if (!GPIOD_PIN(1)) + result |= BUTTON_VOL_UP; + + if (!GPIOD_PIN(2)) + result |= BUTTON_UP; + + GPIOD_PIN(3) = 1<<3; + + GPIOD_PIN(4) = 0x00; /* activate D4 */ + asm volatile ("nop\nnop\nnop\nnop\nnop\n"); + + if (!GPIOD_PIN(0)) + result |= BUTTON_LEFT; + + if (!GPIOD_PIN(1)) + result |= BUTTON_SELECT; + + if (!GPIOD_PIN(2)) + result |= BUTTON_RIGHT; + + GPIOD_PIN(4) = 1<<4; + + GPIOD_PIN(5) = 0x00; /* activate D5 */ + asm volatile ("nop\nnop\nnop\nnop\nnop\n"); + + if (!GPIOD_PIN(0)) + result |= BUTTON_DOWN; + + if (!GPIOD_PIN(1)) + result |= BUTTON_VOL_DOWN; + + if (!GPIOD_PIN(2)) + result |= BUTTON_HOME; + + GPIOD_PIN(5) = 1<<5; + + return result; +} + +bool button_hold(void) +{ + return (GPIOA_PIN(3) != 0); +} diff --git a/firmware/target/arm/as3525/sansa-clipv2/button-target.h b/firmware/target/arm/as3525/sansa-clipv2/button-target.h new file mode 100644 index 0000000..238fd1d --- /dev/null +++ b/firmware/target/arm/as3525/sansa-clipv2/button-target.h @@ -0,0 +1,59 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2008 François Dinel + * + * 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 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef _BUTTON_TARGET_H_ +#define _BUTTON_TARGET_H_ + +#include +#include "config.h" + +#define HAS_BUTTON_HOLD + +void button_init_device(void); +int button_read_device(void); +bool button_hold(void); + +/* Main unit's buttons */ +#define BUTTON_HOME 0x00000001 + +#define BUTTON_VOL_UP 0x00000002 +#define BUTTON_VOL_DOWN 0x00000004 + +#define BUTTON_UP 0x00000008 +#define BUTTON_DOWN 0x00000010 +#define BUTTON_LEFT 0x00000020 +#define BUTTON_RIGHT 0x00000040 + +#define BUTTON_SELECT 0x00000080 + +#define BUTTON_POWER 0x00000100 + +#define BUTTON_MAIN (BUTTON_HOME|BUTTON_VOL_UP|BUTTON_VOL_DOWN\ + |BUTTON_UP|BUTTON_DOWN|BUTTON_LEFT|BUTTON_RIGHT\ + |BUTTON_SELECT|BUTTON_POWER) + +#define BUTTON_REMOTE 0 + +/* Software power-off */ +#define POWEROFF_BUTTON BUTTON_POWER +#define POWEROFF_COUNT 10 + +#endif /* _BUTTON_TARGET_H_ */ diff --git a/firmware/target/arm/as3525/sansa-clipv2/lcd-as-clip.S b/firmware/target/arm/as3525/sansa-clipv2/lcd-as-clip.S new file mode 100644 index 0000000..0f68a2f --- /dev/null +++ b/firmware/target/arm/as3525/sansa-clipv2/lcd-as-clip.S @@ -0,0 +1,101 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2008 by Jens Arnold + * + * 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 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "as3525.h" + + .text + .align 2 + + .global lcd_grey_data + .type lcd_grey_data,%function + +/* A high performance function to write grey phase data to the display, + * one or multiple pixels. + * + * Arguments: + * r0 - pixel value data address + * r1 - pixel phase data address + * r2 - pixel block count + * + * Register usage: + * r3/r4 - current block of phases + * r5/r6 - current block of values + * r7 - lcd data accumulator + * r8 - phase signs mask + * lr - lcd bridge address + */ + +lcd_grey_data: + stmfd sp!, {r4-r8, lr} + mov r8, #0x80 + orr r8, r8, r8, lsl #8 + orr r8, r8, r8, lsl #16 + + ldr lr, =GPIOA_BASE + mov r3, #(1<<5) + str r3, [lr, #(4*(1<<5))] @ set pin D/C# of LCD controller (data) + + ldr lr, =DBOP_BASE + +.greyloop: + ldmia r1, {r3-r4} /* Fetch 8 pixel phases */ + ldmia r0!, {r5-r6} /* Fetch 8 pixel values */ + + mov r7, #0 + + /* set bits 15..12 */ + tst r3, #0x80 + orrne r7, r7, #0x8000 + tst r3, #0x8000 + orrne r7, r7, #0x4000 + tst r3, #0x800000 + orrne r7, r7, #0x2000 + tst r3, #0x80000000 + orrne r7, r7, #0x1000 + bic r3, r3, r8 + add r3, r3, r5 + + /* set bits 3..0 */ + tst r4, #0x80 + orrne r7, r7, #0x08 + tst r4, #0x8000 + orrne r7, r7, #0x04 + tst r4, #0x800000 + orrne r7, r7, #0x02 + tst r4, #0x80000000 + orrne r7, r7, #0x01 + bic r4, r4, r8 + add r4, r4, r6 + + stmia r1!, {r3-r4} + + strh r7, [lr, #0x10] @ DBOP_DOUT + +1: + ldr r5, [lr, #0xC] @ DBOP_STAT + ands r5, r5, #(1<<10) @ wait until push fifo empties + beq 1b + + subs r2, r2, #1 + bne .greyloop + + ldmfd sp!, {r4-r8, pc} + .size lcd_grey_data,.-lcd_grey_data diff --git a/firmware/target/arm/as3525/sansa-clipv2/lcd-ssd1303.c b/firmware/target/arm/as3525/sansa-clipv2/lcd-ssd1303.c new file mode 100644 index 0000000..2513858 --- /dev/null +++ b/firmware/target/arm/as3525/sansa-clipv2/lcd-ssd1303.c @@ -0,0 +1,352 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 by Alan Korr + * Copyright (C) 2008 François Dinel + * Copyright © 2008-2009 Rafaël Carré + * + * 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 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "config.h" + +#include "hwcompat.h" +#include "kernel.h" +#include "lcd.h" +#include "system.h" +#include "cpu.h" +#include "string.h" + +/*** AS3525 specifics ***/ +#include "as3525.h" + +/*** definitions ***/ + +#define LCD_SET_LOWER_COLUMN_ADDRESS ((char)0x00) +#define LCD_SET_HIGHER_COLUMN_ADDRESS ((char)0x10) +#define LCD_SET_DISPLAY_START_LINE ((char)0x40) +#define LCD_SET_CONTRAST_CONTROL_REGISTER ((char)0x81) +#define LCD_SET_SEGMENT_REMAP ((char)0xA0) +#define LCD_SET_SEGMENT_REMAP_INV ((char)0xA1) +#define LCD_SET_ENTIRE_DISPLAY_OFF ((char)0xA4) +#define LCD_SET_ENTIRE_DISPLAY_ON ((char)0xA5) +#define LCD_SET_NORMAL_DISPLAY ((char)0xA6) +#define LCD_SET_REVERSE_DISPLAY ((char)0xA7) +#define LCD_SET_MULTIPLEX_RATIO ((char)0xA8) +#define LCD_SET_DC_DC ((char)0xAD) +#define LCD_SET_DC_DC_PART2 ((char)0x8A) +#define LCD_SET_DISPLAY_OFF ((char)0xAE) +#define LCD_SET_DISPLAY_ON ((char)0xAF) +#define LCD_SET_PAGE_ADDRESS ((char)0xB0) +#define LCD_SET_COM_OUTPUT_SCAN_DIRECTION ((char)0xC0) +#define LCD_SET_COM_OUTPUT_SCAN_DIRECTION_INV ((char)0xC8) +#define LCD_SET_DISPLAY_CLOCK_AND_OSC_FREQ ((char)0xD5) +#define LCD_SET_VCOM_DESELECT_LEVEL ((char)0xDB) +#define LCD_SET_PRECHARGE_PERIOD ((char)0xD9) +#define LCD_NOP ((char)0xE3) + +/* LCD command codes */ +#define LCD_CNTL_CONTRAST 0x81 /* Contrast */ +#define LCD_CNTL_OUTSCAN 0xc8 /* Output scan direction */ +#define LCD_CNTL_SEGREMAP 0xa1 /* Segment remap */ +#define LCD_CNTL_DISPON 0xaf /* Display on */ + +#define LCD_CNTL_PAGE 0xb0 /* Page address */ +#define LCD_CNTL_HIGHCOL 0x10 /* Upper column address */ +#define LCD_CNTL_LOWCOL 0x00 /* Lower column address */ + +/* DBOP initialisation, do what OF does */ +static void ams3525_dbop_init(void) +{ + CCU_IO |= (1<<12); /* ?? */ + + CGU_DBOP |= /*(1<<3)*/ 0x18 | CLK_DIV(AS3525_PCLK_FREQ, AS3525_DBOP_FREQ); + + DBOP_CTRL = 0x51004; + DBOP_TIMPOL_01 = 0x36A12F; + DBOP_TIMPOL_23 = 0xE037E037; +} + +void lcd_write_command(int byte) +{ + volatile int i = 0; + while(i<10) i++; + + /* unset D/C# (data or command) */ + GPIOB_PIN(2) = 0; + + DBOP_TIMPOL_23 = 0xE0370036; + + /* Write command */ + /* Only bits 15:12 and 3:0 of DBOP_DOUT are meaningful */ + DBOP_DOUT = (byte << 8) | byte; + + /* While push fifo is not empty */ + while ((DBOP_STAT & (1<<10)) == 0) + ; + + DBOP_TIMPOL_23 = 0xE037E037; +} + +void lcd_write_data(const fb_data* p_bytes, int count) +{ + volatile int i = 0; + while(i<10) i++; + /* set D/C# (data or command) */ + GPIOB_PIN(2) = (1<<2); + + while (count--) + { + /* Write pixels */ + /* Only bits 15:12 and 3:0 of DBOP_DOUT are meaningful */ + DBOP_DOUT = (*p_bytes << 8) | *p_bytes; + + p_bytes++; /* next packed pixels */ + + /* While push fifo is not empty */ + while ((DBOP_STAT & (1<<10)) == 0) + ; + } +} + + +/** globals **/ + +static int xoffset; /* needed for flip */ +static bool display_on = false; /* used by lcd_enable */ + +/*** hardware configuration ***/ + +int lcd_default_contrast(void) +{ + return DEFAULT_CONTRAST_SETTING; +} + +void lcd_set_contrast(int val) +{ + lcd_write_command(LCD_CNTL_CONTRAST); + lcd_write_command(val); +} + +void lcd_set_invert_display(bool yesno) +{ + if (yesno) + lcd_write_command(LCD_SET_REVERSE_DISPLAY); + else + lcd_write_command(LCD_SET_NORMAL_DISPLAY); +} + +/* turn the display upside down (call lcd_update() afterwards) */ +void lcd_set_flip(bool yesno) +{ + if (yesno) + { + lcd_write_command(LCD_SET_SEGMENT_REMAP); + lcd_write_command(LCD_SET_COM_OUTPUT_SCAN_DIRECTION); + } + else + { + lcd_write_command(LCD_SET_SEGMENT_REMAP_INV); + lcd_write_command(LCD_SET_COM_OUTPUT_SCAN_DIRECTION_INV); + } +} + +void lcd_enable(bool enable) +{ + if(display_on == enable) + return; + + if( (display_on = enable) ) /* simple '=' is not a typo ! */ + lcd_write_command(LCD_SET_DISPLAY_ON); + else + lcd_write_command(LCD_SET_DISPLAY_OFF); +} + +bool lcd_active(void) +{ + return display_on; +} + +bool lcd_enabled(void) +{ + return display_on; +} + + +/* LCD init, largely based on what OF does */ +void lcd_init_device(void) +{ + int i; +#define LCD_FULLSCREEN (128+4) + fb_data p_bytes[LCD_FULLSCREEN]; /* framebuffer used to clear the screen */ + + ams3525_dbop_init(); + + GPIOB_DIR |= (1<<2)|(1<<5); + GPIOB_PIN(5) = (1<<5); + + /* Set display clock (divide ratio = 1) and oscillator frequency (1) */ + lcd_write_command(LCD_SET_DISPLAY_CLOCK_AND_OSC_FREQ); + lcd_write_command(0x10); + + /* Set VCOM deselect level to 0.76V */ + lcd_write_command(LCD_SET_VCOM_DESELECT_LEVEL); + lcd_write_command(0x34); + + /* Set pre-charge period (p1period is 2 dclk and p2period is 5 dclk) */ + lcd_write_command(LCD_SET_PRECHARGE_PERIOD); + lcd_write_command(0x25); + + /* Set contrast register to 12% */ + lcd_set_contrast(lcd_default_contrast()); + + /* Disable DC-DC */ + lcd_write_command(LCD_SET_DC_DC); + lcd_write_command(LCD_SET_DC_DC_PART2/*|0*/); + + /* Set starting line as 0 */ + lcd_write_command(LCD_SET_DISPLAY_START_LINE /*|(0 & 0x3f)*/); + + /* Column 131 is remapped to SEG0 */ + lcd_write_command(LCD_SET_SEGMENT_REMAP_INV); + + /* Invert COM scan direction (N-1 to 0) */ + lcd_write_command(LCD_SET_COM_OUTPUT_SCAN_DIRECTION_INV); + + /* Set normal display mode (not every pixel ON) */ + lcd_write_command(LCD_SET_ENTIRE_DISPLAY_OFF); + + /* Set normal display mode (not inverted) */ + lcd_write_command(LCD_SET_NORMAL_DISPLAY); + + /* Clear whole framebuffer, including "overscan" + * We don't need to handle that out of screen columns in lcd_clear_display() + * since we will never write into it anymore + */ + lcd_write_command (LCD_SET_HIGHER_COLUMN_ADDRESS /*| 0*/); + lcd_write_command (LCD_SET_LOWER_COLUMN_ADDRESS /*| 0*/); + + memset(p_bytes, 0, sizeof(p_bytes)); /* fills with 0 : pixel off */ + + for(i = 0; i < 8; i++) + { + lcd_write_command (LCD_SET_PAGE_ADDRESS | (i /*& 0xf*/)); + lcd_write_data(p_bytes, LCD_FULLSCREEN /* overscan */); + } + + lcd_enable(true); + + lcd_update(); +} + +/*** Update functions ***/ + +/* Performance function that works with an external buffer + note that by and bheight are in 8-pixel units! */ +void lcd_blit_mono(const unsigned char *data, int x, int by, int width, + int bheight, int stride) +{ + if(!display_on) + return; + + /* Copy display bitmap to hardware */ + while (bheight--) + { + lcd_write_command (LCD_CNTL_PAGE | (by++ & 0xf)); + lcd_write_command (LCD_CNTL_HIGHCOL | (((x+2+xoffset)>>4) & 0xf)); + lcd_write_command (LCD_CNTL_LOWCOL | ((x+2+xoffset) & 0xf)); + + lcd_write_data(data, width); + data += stride; + } +} + +/* Helper function for lcd_grey_phase_blit(). */ +void lcd_grey_data(unsigned char *values, unsigned char *phases, int count); + +/* Performance function that works with an external buffer + note that by and bheight are in 8-pixel units! */ +void lcd_blit_grey_phase(unsigned char *values, unsigned char *phases, + int x, int by, int width, int bheight, int stride) +{ + if(!display_on) + return; + + stride <<= 3; /* 8 pixels per block */ + /* Copy display bitmap to hardware */ + while (bheight--) + { + lcd_write_command (LCD_CNTL_PAGE | (by++ & 0xf)); + lcd_write_command (LCD_CNTL_HIGHCOL | (((x+2+xoffset)>>4) & 0xf)); + lcd_write_command (LCD_CNTL_LOWCOL | ((x+2+xoffset) & 0xf)); + + lcd_grey_data(values, phases, width); + + values += stride; + phases += stride; + } +} + +/* Update the display. + This must be called after all other LCD functions that change the display. */ +void lcd_update(void) ICODE_ATTR; +void lcd_update(void) +{ + int y; + + if(!display_on) + return; + + /* Copy display bitmap to hardware */ + for (y = 0; y < LCD_FBHEIGHT; y++) + { + lcd_write_command (LCD_CNTL_PAGE | (y & 0xf)); + lcd_write_command (LCD_CNTL_HIGHCOL | (((xoffset+2) >> 4) & 0xf)); + lcd_write_command (LCD_CNTL_LOWCOL | ((xoffset+2) & 0xf)); + + lcd_write_data (lcd_framebuffer[y], LCD_WIDTH); + } +} + +/* Update a fraction of the display. */ +void lcd_update_rect(int, int, int, int) ICODE_ATTR; +void lcd_update_rect(int x, int y, int width, int height) +{ + int ymax; + + if(!display_on) + return; + + /* The Y coordinates have to work on even 8 pixel rows */ + ymax = (y + height-1) >> 3; + y >>= 3; + + if(x + width > LCD_WIDTH) + width = LCD_WIDTH - x; + if (width <= 0) + return; /* nothing left to do, 0 is harmful to lcd_write_data() */ + if(ymax >= LCD_FBHEIGHT) + ymax = LCD_FBHEIGHT-1; + + /* Copy specified rectange bitmap to hardware */ + for (; y <= ymax; y++) + { + lcd_write_command (LCD_CNTL_PAGE | (y & 0xf)); + lcd_write_command (LCD_CNTL_HIGHCOL | (((x+2+xoffset) >> 4) & 0xf)); + lcd_write_command (LCD_CNTL_LOWCOL | ((x+2+xoffset) & 0xf)); + + lcd_write_data (&lcd_framebuffer[y][x], width); + } +} diff --git a/firmware/target/arm/as3525/sansa-clipv2/powermgmt-clip.c b/firmware/target/arm/as3525/sansa-clipv2/powermgmt-clip.c new file mode 100644 index 0000000..5feb53c --- /dev/null +++ b/firmware/target/arm/as3525/sansa-clipv2/powermgmt-clip.c @@ -0,0 +1,50 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright © 2008 Rafaël Carré + * + * 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 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "config.h" + +/* The battery manufacturer's website shows discharge curves down to 3.0V, + so 'dangerous' and 'shutoff' levels of 3.4V and 3.3V should be safe. + */ +const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = +{ + 3400 +}; + +const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] = +{ + 3300 +}; + +/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */ +const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] = +{ + { 3300, 3653, 3701, 3735, 3768, 3790, 3833, 3900, 3966, 4056, 4140 } +}; + +#if CONFIG_CHARGING +/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */ +const unsigned short percent_to_volt_charge[11] = +{ + /* TODO: simple linear uncalibrated curve */ + 3300, 3390, 3480, 3570, 3660, 3750, 3840, 3930, 4020, 4110, 4200 +}; +#endif /* CONFIG_CHARGING */ diff --git a/firmware/target/arm/as3525/sansa-clipv2/powermgmt-target.h b/firmware/target/arm/as3525/sansa-clipv2/powermgmt-target.h new file mode 100644 index 0000000..691d134 --- /dev/null +++ b/firmware/target/arm/as3525/sansa-clipv2/powermgmt-target.h @@ -0,0 +1,42 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 by Michael Sevakis + * Copyright (C) 2008 by Bertrik Sikken + * + * 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 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef POWERMGMT_TARGET_H +#define POWERMGMT_TARGET_H + +/* Check if topped-off and monitor voltage while plugged. */ +#define BATT_FULL_VOLTAGE 4160 +#define BATT_VAUTO_RECHARGE 4100 +#define BATT_CHG_V CHG_V_4_20V +#define BATT_CHG_I CHG_I_100MA +#define CHARGER_TOTAL_TIMER (6*3600*2) /* about 1.5 * capacity / current */ +#define ADC_BATTERY ADC_BVDD + +void powermgmt_init_target(void); +void charging_algorithm_step(void); +void charging_algorithm_close(void); + +/* We want to be able to reset the averaging filter */ +#define HAVE_RESET_BATTERY_FILTER + +#define BATT_AVE_SAMPLES 32 + +#endif /* POWERMGMT_TARGET_H */ diff --git a/firmware/target/arm/as3525/system-as3525.c b/firmware/target/arm/as3525/system-as3525.c index e973354..a603c70 100644 --- a/firmware/target/arm/as3525/system-as3525.c +++ b/firmware/target/arm/as3525/system-as3525.c @@ -194,7 +194,7 @@ static void sdram_init(void) /* 16 bits external bus, low power SDRAM, 16 Mbits = 2 Mbytes */ #define MEMORY_MODEL 0x21 -#elif defined(SANSA_E200V2) || defined(SANSA_FUZE) +#elif defined(SANSA_E200V2) || defined(SANSA_FUZE) || defined(SANSA_CLIPV2) /* 16 bits external bus, high performance SDRAM, 64 Mbits = 8 Mbytes */ #define MEMORY_MODEL 0x5 @@ -245,6 +245,7 @@ void memory_init(void) void system_init(void) { +#ifndef SANSA_CLIPV2 unsigned int reset_loops = 640; CCU_SRC = 0x1fffff0 @@ -281,6 +282,18 @@ void system_init(void) #ifdef BOOTLOADER sdram_init(); #endif /* BOOTLOADER */ +#else + unsigned int reset_loops = 640; + + CCU_SRC = 0x57D7BF0; + while(reset_loops--) + CCU_SRL = CCU_SRL_MAGIC_NUMBER; + CCU_SRC = CCU_SRL = 0; + + CGU_PERI &= ~0x7f; /* pclk 24 MHz */ + CGU_PERI |= ((CLK_DIV(AS3525_PLLA_FREQ, AS3525_PCLK_FREQ) - 1) << 2) + | 1; /* clk_in = PLLA */ +#endif /* SANSA_CLIPV2 */ #if 0 /* the GPIO clock is already enabled by the dualboot function */ CGU_PERI |= CGU_GPIO_CLOCK_ENABLE; diff --git a/firmware/target/arm/crt0.S b/firmware/target/arm/crt0.S index 4bd01e4..824fdd6 100644 --- a/firmware/target/arm/crt0.S +++ b/firmware/target/arm/crt0.S @@ -89,7 +89,7 @@ newstart: cmp r3, r2 strhi r4, [r2], #4 bhi 1b - + /* Set up some stack and munge it with 0xdeadbeef */ ldr sp, =stackend ldr r2, =stackbegin @@ -98,12 +98,12 @@ newstart: cmp sp, r2 strhi r3, [r2], #4 bhi 1b - - /* Set up stack for IRQ mode */ + + /* Set up stack for IRQ mode */ msr cpsr_c, #0xd2 ldr sp, =irq_stack - /* Set up stack for FIQ mode */ + /* Set up stack for FIQ mode */ msr cpsr_c, #0xd1 ldr sp, =fiq_stack @@ -140,7 +140,7 @@ prefetch_abort_handler: b UIE data_abort_handler: - sub r0, lr, #8 + sub r0, lr, #8 mov r1, #2 b UIE diff --git a/tools/configure b/tools/configure index c6341ff..ad7647e 100755 --- a/tools/configure +++ b/tools/configure @@ -1908,8 +1908,6 @@ fi ;; 60|Clipv2|clipv2) - echo "Sansa Clipv2 is not yet supported !" - exit 1 target_id=60 modelname="clipv2" target="-DSANSA_CLIPV2" diff --git a/uisimulator/sdl/uisdl.h b/uisimulator/sdl/uisdl.h index 0fe0463..717bd84 100644 --- a/uisimulator/sdl/uisdl.h +++ b/uisimulator/sdl/uisdl.h @@ -285,7 +285,7 @@ #define UI_LCD_POSX 30 /* x position of lcd */ #define UI_LCD_POSY 31 /* y position of lcd */ -#elif defined(SANSA_CLIP) +#elif defined(SANSA_CLIP) || defined(SANSA_CLIPV2) #define UI_TITLE "Sansa Clip" #define UI_WIDTH 205 /* width of GUI window */ #define UI_HEIGHT 325 /* height of GUI window */