Add MPIO HD200 port - new files

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25725 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Marcin Bukat 2010-04-26 21:40:16 +00:00
parent b09d3aec39
commit 28d54c6016
29 changed files with 3756 additions and 0 deletions

View file

@ -0,0 +1,172 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id:$
*
* Copyright (C) 2010 Marcin Bukat
*
* 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 "action.h"
#include "button.h"
#include "settings.h"
/*
* The format of the list is as follows
* { Action Code, Button code, Prereq button code }
* if there's no need to check the previous button's value, use BUTTON_NONE
* Insert LAST_ITEM_IN_LIST at the end of each mapping
*/
/* CONTEXT_CUSTOM's used in this file...
CONTEXT_CUSTOM|CONTEXT_TREE = the standard list/tree defines (without directions)
*/
static const struct button_mapping button_context_standard[] = {
{ ACTION_STD_PREV, BUTTON_PREV, BUTTON_NONE },
{ ACTION_STD_PREVREPEAT, BUTTON_PREV|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_STD_NEXT, BUTTON_NEXT, BUTTON_NONE },
{ ACTION_STD_NEXTREPEAT, BUTTON_NEXT|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_STD_CANCEL, BUTTON_REC|BUTTON_REL, BUTTON_REC },
{ ACTION_STD_OK, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT },
{ ACTION_STD_MENU, BUTTON_REC|BUTTON_REPEAT, BUTTON_REC },
{ ACTION_STD_QUICKSCREEN, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_PLAY },
{ ACTION_STD_CONTEXT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT },
LAST_ITEM_IN_LIST
}; /* button_context_standard */
static const struct button_mapping button_context_tree[] = {
{ ACTION_TREE_WPS, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY },
{ ACTION_TREE_STOP, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_PLAY },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_tree */
static const struct button_mapping button_context_tree_scroll_lr[] = {
{ ACTION_NONE, BUTTON_PREV, BUTTON_NONE },
{ ACTION_STD_CANCEL, BUTTON_PREV|BUTTON_REL, BUTTON_PREV },
{ ACTION_TREE_ROOT_INIT, BUTTON_PREV|BUTTON_REPEAT, BUTTON_PREV },
{ ACTION_TREE_PGLEFT, BUTTON_PREV|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_TREE_PGLEFT, BUTTON_PREV|BUTTON_REL, BUTTON_PREV|BUTTON_REPEAT },
{ ACTION_NONE, BUTTON_NEXT, BUTTON_NONE },
{ ACTION_STD_OK, BUTTON_NEXT|BUTTON_REL, BUTTON_NEXT },
{ ACTION_TREE_PGRIGHT, BUTTON_NEXT|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_TREE_PGRIGHT, BUTTON_NEXT|BUTTON_REL, BUTTON_NEXT|BUTTON_REPEAT },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_TREE),
}; /* button_context_tree_scroll_lr */
static const struct button_mapping button_context_wps[] = {
{ ACTION_WPS_PLAY, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY },
{ ACTION_WPS_STOP, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_PLAY },
{ ACTION_WPS_SKIPPREV, BUTTON_PREV|BUTTON_REL, BUTTON_PREV },
{ ACTION_WPS_SEEKBACK, BUTTON_PREV|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_WPS_STOPSEEK, BUTTON_PREV|BUTTON_REL, BUTTON_PREV|BUTTON_REPEAT },
{ ACTION_WPS_SKIPNEXT, BUTTON_NEXT|BUTTON_REL, BUTTON_NEXT },
{ ACTION_WPS_SEEKFWD, BUTTON_NEXT|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_WPS_STOPSEEK, BUTTON_NEXT|BUTTON_REL, BUTTON_NEXT|BUTTON_REPEAT },
{ ACTION_WPS_VOLDOWN, BUTTON_VOL_DOWN, BUTTON_NONE },
{ ACTION_WPS_VOLDOWN, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_WPS_VOLUP, BUTTON_VOL_UP, BUTTON_NONE },
{ ACTION_WPS_VOLUP, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_WPS_BROWSE, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT },
{ ACTION_WPS_CONTEXT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT },
{ ACTION_WPS_MENU, BUTTON_REC|BUTTON_REL, BUTTON_REC },
{ ACTION_WPS_QUICKSCREEN, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT },
LAST_ITEM_IN_LIST,
}; /* button_context_wps */
static const struct button_mapping button_context_settings[] = {
{ ACTION_SETTINGS_INC, BUTTON_VOL_UP, BUTTON_NONE },
{ ACTION_SETTINGS_INCREPEAT, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_SETTINGS_DEC, BUTTON_VOL_DOWN, BUTTON_NONE },
{ ACTION_SETTINGS_DECREPEAT, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_STD_PREV, BUTTON_PREV, BUTTON_NONE },
{ ACTION_STD_PREVREPEAT, BUTTON_PREV|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_STD_NEXT, BUTTON_NEXT, BUTTON_NONE },
{ ACTION_STD_NEXTREPEAT, BUTTON_NEXT|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_STD_OK, BUTTON_SELECT|BUTTON_REL, BUTTON_NONE },
{ ACTION_STD_CANCEL, BUTTON_REC|BUTTON_REL, BUTTON_REC },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_settings */
static const struct button_mapping button_context_yesno[] = {
{ ACTION_YESNO_ACCEPT, BUTTON_SELECT, BUTTON_NONE },
LAST_ITEM_IN_LIST
}; /* button_context_yesno */
static const struct button_mapping button_context_bmark[] = {
{ ACTION_BMS_DELETE, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_LIST),
}; /* button_context_bmark */
static const struct button_mapping button_context_quickscreen[] = {
{ ACTION_QS_TOP, BUTTON_SELECT, BUTTON_NONE },
{ ACTION_QS_TOP, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_QS_DOWN, BUTTON_PLAY, BUTTON_NONE },
{ ACTION_QS_DOWN, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_QS_LEFT, BUTTON_PREV, BUTTON_NONE },
{ ACTION_QS_LEFT, BUTTON_PREV|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_QS_RIGHT, BUTTON_NEXT, BUTTON_NONE },
{ ACTION_QS_RIGHT, BUTTON_NEXT|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_STD_CANCEL, BUTTON_REC, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_quickscreen */
static const struct button_mapping button_context_pitchscreen[] = {
{ ACTION_PS_INC_SMALL, BUTTON_VOL_UP, BUTTON_NONE },
{ ACTION_PS_INC_BIG, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_PS_DEC_SMALL, BUTTON_VOL_DOWN, BUTTON_NONE },
{ ACTION_PS_DEC_BIG, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_PS_NUDGE_LEFT, BUTTON_PREV, BUTTON_NONE },
{ ACTION_PS_NUDGE_LEFTOFF, BUTTON_PREV|BUTTON_REL, BUTTON_NONE },
{ ACTION_PS_NUDGE_RIGHT, BUTTON_NEXT, BUTTON_NONE },
{ ACTION_PS_NUDGE_RIGHTOFF, BUTTON_NEXT|BUTTON_REL, BUTTON_NONE },
{ ACTION_PS_TOGGLE_MODE, BUTTON_PLAY, BUTTON_NONE },
{ ACTION_PS_RESET, BUTTON_SELECT, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_REC, BUTTON_NONE },
{ ACTION_PS_SLOWER, BUTTON_PREV|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_PS_FASTER, BUTTON_NEXT|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_pitchscreen */
const struct button_mapping* get_context_mapping(int context)
{
switch (context)
{
case CONTEXT_STD:
return button_context_standard;
case CONTEXT_WPS:
return button_context_wps;
case CONTEXT_TREE:
case CONTEXT_LIST:
case CONTEXT_MAINMENU:
case CONTEXT_SETTINGS:
case CONTEXT_SETTINGS|CONTEXT_REMOTE:
default:
return button_context_standard;
}
return button_context_standard;
}

459
bootloader/mpio_hd200.c Normal file
View file

@ -0,0 +1,459 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id:$
*
* Copyright (C) 2010 Marcin Bukat
*
* 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 <stdlib.h>
#include <stdio.h>
#include "inttypes.h"
#include "string.h"
#include "cpu.h"
#include "system.h"
#include "lcd.h"
#include "kernel.h"
#include "thread.h"
#include "storage.h"
#include "usb.h"
#include "disk.h"
#include "font.h"
#include "adc.h"
#include "backlight.h"
#include "backlight-target.h"
#include "button.h"
#include "panic.h"
#include "power.h"
#include "powermgmt.h"
#include "file.h"
#include "common.h"
#include <stdarg.h>
/* Maximum allowed firmware image size. 10MB is more than enough */
#define MAX_LOADSIZE (10*1024*1024)
#define DRAM_START 0x31000000
#define BOOTMENU_TIMEOUT (10*HZ)
#define BOOTMENU_OPTIONS 3
/* From common.c */
extern int line;
static const char *bootmenu_options[] = {
"Boot rockbox",
"Boot MPIO firmware",
"Shutdown"
};
enum option_t {
rockbox,
mpio_firmware,
shutdown
};
int usb_screen(void)
{
return 0;
}
char version[] = APPSVERSION;
bool _charger_inserted(void)
{
return (GPIO1_READ & (1<<14)) ? false : true;
}
bool _battery_full(void)
{
return (GPIO_READ & (1<<30)) ? true : false;
}
/* Reset the cookie for the crt0 crash check */
inline void __reset_cookie(void)
{
asm(" move.l #0,%d0");
asm(" move.l %d0,0x10017ffc");
}
void start_rockbox(void)
{
adc_close();
asm(" move.w #0x2700,%sr");
__reset_cookie();
asm(" move.l %0,%%d0" :: "i"(DRAM_START));
asm(" movec.l %d0,%vbr");
asm(" move.l %0,%%sp" :: "m"(*(int *)DRAM_START));
asm(" move.l %0,%%a0" :: "m"(*(int *)(DRAM_START+4)));
asm(" jmp (%a0)");
}
void start_mpio_firmware(void)
{
asm(" move.w #0x2700,%sr");
__reset_cookie();
asm(" movec.l %d0,%vbr");
asm(" move.l 0,%sp");
asm(" jmp 8");
}
void __reset(void)
{
asm(" move.w #0x2700,%sr");
__reset_cookie();
asm(" movec.l %d0,%vbr");
asm(" move.l (0), %sp");
asm(" movea.l (4),%a0");
asm(" jmp (%a0)");
}
void __shutdown(void)
{
/* We need to gracefully spin down the disk to prevent clicks. */
if (ide_powered())
{
/* Make sure ATA has been initialized. */
storage_init();
/* And put the disk into sleep immediately. */
storage_sleepnow();
}
/* Backlight OFF */
_backlight_off();
__reset_cookie();
if (_charger_inserted())
{
/* reset instead of power_off() */
__reset();
}
else
{
power_off();
}
}
/* Print the battery voltage (and a warning message). */
void check_battery(void)
{
int battery_voltage, batt_int, batt_frac;
battery_voltage = battery_adc_voltage();
batt_int = battery_voltage / 1000;
batt_frac = (battery_voltage % 1000) / 10;
printf("Battery: %d.%02dV", batt_int, batt_frac);
if (battery_voltage <= 3500)
{
printf("WARNING! BATTERY LOW!!");
sleep(HZ*2);
}
}
void lcd_putstring_centered(const char *string)
{
int w,h;
font_getstringsize(string, &w, &h, FONT_SYSFIXED);
lcd_putsxy((LCD_WIDTH-w)/2, (LCD_HEIGHT-h)/2, string);
}
void bootmenu(void)
{
int rc;
enum option_t i;
enum option_t option = rockbox;
int button;
const char select[] = "->";
long start_tick = current_tick;
/* backbone of menu */
/* run the loader */
printf("Rockbox boot loader");
printf("Ver: %s", version);
check_battery();
printf("");
printf("=========================");
line += BOOTMENU_OPTIONS+2; /* skip lines */
printf("=========================");
printf("");
printf(" [FF] [PREV] to move ");
printf(" [PLAY] to confirm ");
/* content of menu and keys handling */
while (TIME_BEFORE(current_tick,start_tick + BOOTMENU_TIMEOUT))
{
/* Draw the menu. */
line = 6; /* move below header */
for (i=0;i<BOOTMENU_OPTIONS;i++)
{
if (i != option)
printf(" %s",bootmenu_options[i]);
else
printf("%s %s",select,bootmenu_options[i]);
}
line = 15;
printf("Time left: %ds",(BOOTMENU_TIMEOUT -
(current_tick - start_tick))/HZ);
lcd_update();
button = button_get_w_tmo(HZ);
switch (button)
{
case BUTTON_PREV:
if (option > rockbox)
option--;
else
option = shutdown;
break;
case BUTTON_NEXT:
if (option < shutdown)
option++;
else
option = rockbox;
break;
case BUTTON_PLAY:
case (BUTTON_PLAY|BUTTON_REC):
reset_screen();
switch (option)
{
case rockbox:
rc = storage_init();
if(rc)
{
printf("ATA error: %d", rc);
sleep(HZ*5);
__shutdown();
}
disk_init();
rc = disk_mount_all();
if (rc<=0)
{
printf("No partition found");
sleep(HZ*5);
__shutdown();
}
printf("Loading firmware");
rc = load_firmware((unsigned char *)DRAM_START,
BOOTFILE, MAX_LOADSIZE);
printf("Result: %s", strerror(rc));
if (rc < EOK)
{
printf("Error!");
printf("Can't load " BOOTFILE ": ");
printf(strerror(rc));
sleep(HZ*5);
__shutdown();
}
else
{
start_rockbox();
}
break;
case mpio_firmware:
start_mpio_firmware();
break;
default:
__shutdown();
break;
}
}
}
/* timeout */
__shutdown();
}
void main(void)
{
/* messages */
const char usb_connect_msg[] = "Bootloader USB mode";
const char charging_msg[] = "Charging...";
const char complete_msg[] = "Charging complete";
const char hold_msg[] = "Hold switch on";
const char shutdown_msg[] = "Shutting down...";
/* helper variables for messages */
bool blink_toggle = false;
const char *msg;
bool on_button = false;
int button;
/* We want to read the buttons as early as possible, before the user
releases the ON button */
or_l( ((1<<24)|(1<<4)), &GPIO1_FUNCTION); /* main Hold & Play */
and_l( ~((1<<24)|(1<<4)), &GPIO1_ENABLE); /* HiZ */
if (GPIO1_READ & (1<<24))
on_button = true;
power_init();
system_init();
kernel_init();
set_cpu_frequency(CPUFREQ_NORMAL);
coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS);
enable_irq();
lcd_init();
backlight_init();
font_init();
lcd_setfont(FONT_SYSFIXED);
adc_init();
button_init();
usb_init();
/* handle charging */
if( _charger_inserted())
{
or_l((1<<15),&GPIO_OUT);
cpu_idle_mode(true);
while( _charger_inserted() &&
usb_detect() != USB_INSERTED &&
!on_button)
{
button = button_get_w_tmo(HZ);
switch(button)
{
case BUTTON_ON:
on_button = true;
reset_screen();
break;
case BUTTON_NONE: /* Timeout */
if(!_battery_full())
{
/* To be replaced with a nice animation */
blink_toggle = !blink_toggle;
msg = charging_msg;
}
else
{
blink_toggle = true;
msg = complete_msg;
}
reset_screen();
if(blink_toggle)
lcd_putstring_centered(msg);
check_battery();
break;
}
}
cpu_idle_mode(false);
}
/* handle USB in bootloader */
if (usb_detect() == USB_INSERTED)
{
ide_power_enable(true);
sleep(HZ/20);
usb_enable(true);
cpu_idle_mode(true);
while (usb_detect() == USB_INSERTED)
{
line = 0;
reset_screen();
if(blink_toggle)
{
lcd_putstring_centered(usb_connect_msg);
}
check_battery();
blink_toggle = !blink_toggle;
storage_spin(); /* Prevent the drive from spinning down */
sleep(HZ);
}
cpu_idle_mode(false);
usb_enable(false);
sleep(HZ);
reset_screen();
lcd_update();
}
/* handle ON button press */
if (on_button)
{
if (button_hold() &&
!_charger_inserted() &&
usb_detect() != USB_INSERTED)
{
lcd_putstring_centered(hold_msg);
lcd_update();
sleep(HZ*3);
__shutdown();
}
}
else
{
lcd_putstring_centered(shutdown_msg);
lcd_update();
sleep(HZ*3);
__shutdown();
}
bootmenu();
}
/* These functions are present in the firmware library, but we reimplement
them here because the originals do a lot more than we want */
void screen_dump(void)
{
}

View file

@ -0,0 +1,191 @@
/*
* This config file is for MPIO HD200
*/
#define TARGET_TREE /* this target is using the target tree system */
/* For Rolo and boot loader */
#define MODEL_NUMBER 69
#define MODEL_NAME "MPIO HD200"
/* define this if you use an ATA controller */
#define CONFIG_STORAGE STORAGE_ATA
#define HAVE_LBA48
/* define this if you have recording possibility */
/* not implemented yet
* #define HAVE_RECORDING
*/
/* Define bitmask of input sources - recordable bitmask can be defined
* explicitly if different
* not implemented yet
*/
#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN | SRC_CAP_FMRADIO)
/* define the bitmask of hardware sample rates */
#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
/* define the bitmask of recording sample rates
* not implemented yet
*#define REC_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
*/
/* define this if you have a bitmap LCD display */
#define HAVE_LCD_BITMAP
/* define this if you want album art for this target */
#define HAVE_ALBUMART
/* define this to enable bitmap scaling */
#define HAVE_BMP_SCALING
/* define this to enable JPEG decoding */
#define HAVE_JPEG
/* define this if you can flip your LCD */
#define HAVE_LCD_FLIP
/* define this if you can invert the colours on your LCD */
#define HAVE_LCD_INVERT
/* 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 128
#define LCD_DEPTH 2
#define LCD_PIXELFORMAT VERTICAL_INTERLEAVED
/* Display colours, for screenshots and sim (0xRRGGBB) */
#define LCD_DARKCOLOR 0x000000
#define LCD_BRIGHTCOLOR 0x5a915a
#define LCD_BL_DARKCOLOR 0x000000
#define LCD_BL_BRIGHTCOLOR 0x82b4fa
#define CONFIG_KEYPAD MPIO_HD200_PAD
#define AB_REPEAT_ENABLE 1
#define ACTION_WPSAB_SINGLE ACTION_WPS_BROWSE
/* Define this if you do software codec */
#define CONFIG_CODEC SWCODEC
#define CONFIG_LCD LCD_TL0350A
#define HAVE_LCD_SHUTDOWN
/* Define this for LCD backlight available */
#define HAVE_BACKLIGHT
#define HAVE_BACKLIGHT_BRIGHTNESS
#define MIN_BRIGHTNESS_SETTING 0
#define MAX_BRIGHTNESS_SETTING 31
#define DEFAULT_BRIGHTNESS_SETTING 20
/* define this if you have a disk storage, i.e. something
that needs spinups and can cause skips when shaked */
#define HAVE_DISK_STORAGE
/* Define this if you have a software controlled poweroff */
#define HAVE_SW_POWEROFF
/* 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
/* FM Tuner
* turn off for now
*/
#define CONFIG_TUNER TEA5767
#define CONFIG_TUNER_XTAL 32768
/* we have WM8750 codec in I2S slave mode */
#define HAVE_WM8750
#define CODEC_SLAVE
#define BATTERY_CAPACITY_DEFAULT 950 /* default battery capacity */
#define BATTERY_CAPACITY_MIN 950 /* min. capacity selectable */
#define BATTERY_CAPACITY_MAX 2250 /* max. capacity selectable */
#define BATTERY_CAPACITY_INC 50 /* capacity increment */
#define BATTERY_TYPES_COUNT 1 /* only one type */
#define CONFIG_CHARGING CHARGING_MONITOR
/* define current usage levels */
/* additional current when remote connected */
/*
#define CURRENT_REMOTE 8
*/
#ifndef SIMULATOR
/* Define this if your LCD can set contrast */
#define HAVE_LCD_CONTRAST
/* Define this if you have a Motorola SCF5249 */
#define CONFIG_CPU MCF5249
/* Define this if you want to use coldfire's i2c interface */
#define CONFIG_I2C I2C_COLDFIRE
/* OF resets device instead of poweroff while charging
* this triggers bootloader code which takes care of charging.
* I have feeling that powering off while charging may cause
* partition table corruption I am experiencing from time to time
*/
/* define this if the hardware can be powered off while charging */
/* #define HAVE_POWEROFF_WHILE_CHARGING */
/* The size of the flash ROM */
#define FLASH_SIZE 0x200000
/* Define this to the CPU frequency */
#define CPU_FREQ 11289600
/* Define this if you have ATA power-off control */
#define HAVE_ATA_POWER_OFF
/* Offset ( in the firmware file's header ) to the file length */
#define FIRMWARE_OFFSET_FILE_LENGTH 0
/* Offset ( in the firmware file's header ) to the file CRC */
#define FIRMWARE_OFFSET_FILE_CRC 0
/* Offset ( in the firmware file's header ) to the real data */
#define FIRMWARE_OFFSET_FILE_DATA 8
/* Define this if you have adjustable CPU frequency */
#define HAVE_ADJUSTABLE_CPU_FREQ
#define BOOTFILE_EXT "mpio"
#define BOOTFILE "rockbox." BOOTFILE_EXT
#define BOOTDIR "/.rockbox"
#define BOOTLOADER_ENTRYPOINT 0x001F0000
#define FLASH_ENTRYPOINT 0x00001000
#define FLASH_MAGIC 0xfbfbfbf1
#endif /* SIMULATOR */
/** Port-specific settings **/
/* Main LCD contrast range and defaults taken from OF*/
#define MIN_CONTRAST_SETTING 24
#define MAX_CONTRAST_SETTING 63
#define DEFAULT_CONTRAST_SETTING 27 /* 0x1B */
#define IRAM_LCDFRAMEBUFFER IBSS_ATTR /* put the lcd frame buffer in IRAM */

View file

@ -0,0 +1,145 @@
#include "config.h"
ENTRY(start)
OUTPUT_FORMAT(elf32-m68k)
STARTUP(target/coldfire/crt0.o)
#define PLUGINSIZE PLUGIN_BUFFER_SIZE
#define CODECSIZE CODEC_SIZE
#ifdef DEBUG
#define STUBOFFSET 0x10000
#else
#define STUBOFFSET 0
#endif
#define DRAMSIZE (MEMORYSIZE * 0x100000) - PLUGINSIZE - STUBOFFSET - CODECSIZE
#define DRAMORIG 0x31000000 + STUBOFFSET
#define IRAMORIG 0x10000000
#define IRAMSIZE 0xc000
/* End of the audio buffer, where the codec buffer starts */
#define ENDAUDIOADDR (DRAMORIG + DRAMSIZE)
/* Where the codec buffer ends, and the plugin buffer starts */
#define ENDADDR (ENDAUDIOADDR + CODECSIZE)
MEMORY
{
DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE
}
SECTIONS
{
.vectors :
{
loadaddress = .;
_loadaddress = .;
KEEP(*(.resetvectors));
*(.resetvectors);
KEEP(*(.vectors));
*(.vectors);
} > DRAM
.text :
{
. = ALIGN(0x200);
*(.init.text)
*(.text*)
. = ALIGN(0x4);
} > DRAM
.rodata :
{
*(.rodata) /* problems without this, dunno why */
*(.rodata*)
*(.rodata.str1.1)
*(.rodata.str1.4)
. = ALIGN(0x4);
/* Pseudo-allocate the copies of the data sections */
_datacopy = .;
} > DRAM
/* TRICK ALERT! For RAM execution, we put the .data section at the
same load address as the copy. Thus, we don't waste extra RAM
when we don't actually need the copy. */
.data : AT ( _datacopy )
{
_datastart = .;
*(.data*)
. = ALIGN(0x4);
_dataend = .;
} > DRAM
/DISCARD/ :
{
*(.eh_frame)
}
.iram IRAMORIG :
{
_iramstart = .;
*(.icode)
*(.irodata)
*(.idata)
_iramend = .;
} > IRAM AT> DRAM
_iramcopy = LOADADDR(.iram);
_noloaddram = LOADADDR(.iram);
.ibss (NOLOAD) :
{
_iedata = .;
*(.ibss)
. = ALIGN(0x4);
_iend = .;
} > IRAM
.stack (NOLOAD) :
{
*(.stack)
stackbegin = .;
. += 0x2000;
stackend = .;
} > IRAM
.bss _noloaddram (NOLOAD) :
{
_edata = .;
*(.bss*)
*(COMMON)
. = ALIGN(0x4);
_end = .;
} > DRAM
.audiobuf (NOLOAD) :
{
. = ALIGN(4);
_audiobuffer = .;
audiobuffer = .;
} > DRAM
.audiobufend ENDAUDIOADDR (NOLOAD) :
{
audiobufend = .;
_audiobufend = .;
} > DRAM
.codec ENDAUDIOADDR (NOLOAD) :
{
codecbuf = .;
_codecbuf = .;
}
.plugin ENDADDR (NOLOAD) :
{
_pluginbuf = .;
pluginbuf = .;
}
}

View file

@ -0,0 +1,757 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: ata-as-coldfire.S 17847 2008-06-28 18:10:04Z bagder $
*
* Copyright (C) 2006 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.
*
****************************************************************************/
.section .icode,"ax",@progbits
.equ .ata_port, 0x20000020
.equ .swapmask, 0x00FF00FF
.align 2
.global copy_read_sectors
.type copy_read_sectors,@function
/* Read a number of words from the ATA data port
*
* Utilises line bursts, assumes there is at least one full line to copy.
*
* Arguments:
* (4,%sp) - buffer address
* (8,%sp) - word count
*
* Register usage:
* %a0 - current address
* %a1 - end address
* %a2 - ata port
* %d0 - scratch
* %d1 - shift count
* %d2-%d6 - read buffers
*
* %d7 - byte swap scrach register
* %a3 - byte swap mask
*/
copy_read_sectors:
lea.l (-32, %sp), %sp
movem.l %d2-%d7/%a2-%a3, (%sp)
movem.l (36, %sp), %a0-%a1
add.l %a1, %a1
add.l %a0, %a1
lea.l .ata_port, %a2
lea.l .swapmask, %a3
move.l %a0, %d0
btst.l #0, %d0 /* 16-bit aligned? */
jeq .r_aligned /* yes, do word copy */
/* not 16-bit aligned */
subq.l #1, %a1 /* last byte is done unconditionally */
moveq.l #24, %d1 /* preload shift count */
move.w (%a2), %d2 /* load initial word */
move.b %d2, (%a0)+ /* write high byte of it, aligns dest addr */
/* we have byte swapped */
btst.l #1, %d0 /* longword aligned? (testing old d0 value!) */
bne.b .r_end_u_w1 /* yes, skip leading word handling */
swap %d2 /* move initial word up */
move.w (%a2), %d2 /* combine with second word */
/* byte swap d2 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d2, %d7 /* d7 = .B.D */
eor.l %d7, %d2 /* d2 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d2 /* d2 = .A.C */
or.l %d7, %d2 /* d2 = BADC */
move.l %d2, %d3
lsr.l #8, %d3
move.w %d3, (%a0)+ /* write bytes 2 and 3 as word */
.r_end_u_w1:
moveq.l #12, %d0
add.l %a0, %d0
and.l #0xFFFFFFF0,%d0 /* d0 == first line bound */
cmp.l %a0, %d0 /* any leading longwords? */
bls.b .r_end_u_l1 /* no: skip loop */
.r_loop_u_l1:
move.w (%a2), %d3 /* load first word */
swap %d3 /* move to upper 16 bit */
move.w (%a2), %d3 /* load second word */
/* byte swap d3 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d3, %d7 /* d7 = .B.D */
eor.l %d7, %d3 /* d3 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d3 /* d3 = .A.C */
or.l %d7, %d3 /* d3 = BADC */
move.l %d3, %d4
lsl.l %d1, %d2
lsr.l #8, %d3
or.l %d3, %d2 /* combine old low byte with new top 3 bytes */
move.l %d2, (%a0)+ /* store as long */
move.l %d4, %d2
cmp.l %a0, %d0 /* run up to first line bound */
bhi.b .r_loop_u_l1
.r_end_u_l1:
lea.l (-14, %a1), %a1 /* adjust end addr. to 16 bytes/pass */
.r_loop_u_line:
move.w (%a2), %d3 /* load 1st word */
swap %d3 /* move to upper 16 bit */
move.w (%a2), %d3 /* load 2nd word */
/* byte swap d3 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d3, %d7 /* d7 = .B.D */
eor.l %d7, %d3 /* d3 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d3 /* d3 = .A.C */
or.l %d7, %d3 /* d3 = BADC */
move.l %d3, %d0
lsl.l %d1, %d2
lsr.l #8, %d0
or.l %d0, %d2 /* combine old low byte with new top 3 bytes */
move.w (%a2), %d4 /* load 3rd word */
swap %d4 /* move to upper 16 bit */
move.w (%a2), %d4 /* load 4th word */
/* byte swap d4 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d4, %d7 /* d7 = .B.D */
eor.l %d7, %d4 /* d4 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d4 /* d4 = .A.C */
or.l %d7, %d4 /* d4 = BADC */
move.l %d4, %d0
lsl.l %d1, %d3
lsr.l #8, %d0
or.l %d0, %d3 /* combine old low byte with new top 3 bytes */
move.w (%a2), %d5 /* load 5th word */
swap %d5 /* move to upper 16 bit */
move.w (%a2), %d5 /* load 6th word */
/* byte swap d5 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d5, %d7 /* d7 = .B.D */
eor.l %d7, %d5 /* d5 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d5 /* d5 = .A.C */
or.l %d7, %d5 /* d5 = BADC */
move.l %d5, %d0
lsl.l %d1, %d4
lsr.l #8, %d0
or.l %d0, %d4 /* combine old low byte with new top 3 bytes */
move.w (%a2), %d6 /* load 7th word */
swap %d6 /* move to upper 16 bit */
move.w (%a2), %d6 /* load 8th word */
/* byte swap d6 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d6, %d7 /* d7 = .B.D */
eor.l %d7, %d6 /* d6 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d6 /* d6 = .A.C */
or.l %d7, %d6 /* d6 = BADC */
move.l %d6, %d0
lsl.l %d1, %d5
lsr.l #8, %d0
or.l %d0, %d5 /* combine old low byte with new top 3 bytes */
movem.l %d2-%d5, (%a0) /* store line */
lea.l (16, %a0), %a0
move.l %d6, %d2
cmp.l %a0, %a1 /* run up to last line bound */
bhi.b .r_loop_u_line
lea.l (12, %a1), %a1 /* readjust for longword loop */
cmp.l %a0, %a1 /* any trailing longwords? */
bls.b .r_end_u_l2 /* no: skip loop */
.r_loop_u_l2:
move.w (%a2), %d3 /* load first word */
swap %d3 /* move to upper 16 bit */
move.w (%a2), %d3 /* load second word */
/* byte swap d3 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d3, %d7 /* d7 = .B.D */
eor.l %d7, %d3 /* d3 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d3 /* d3 = .A.C */
or.l %d7, %d3 /* d3 = BADC */
move.l %d3, %d4
lsl.l %d1, %d2
lsr.l #8, %d3
or.l %d3, %d2 /* combine old low byte with new top 3 bytes */
move.l %d2, (%a0)+ /* store as long */
move.l %d4, %d2
cmp.l %a0, %a1 /* run up to last long bound */
bhi.b .r_loop_u_l2
.r_end_u_l2:
addq.l #2, %a1 /* back to final end address */
cmp.l %a0, %a1 /* one word left? */
bls.b .r_end_u_w2
swap %d2 /* move old word to upper 16 bits */
move.w (%a2), %d2 /* load final word */
/* byte swap d2 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d2, %d7 /* d7 = .B.D */
eor.l %d7, %d2 /* d2 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d2 /* d2 = .A.C */
or.l %d7, %d2 /* d2 = BADC */
move.l %d2, %d3
lsr.l #8, %d3
move.w %d3, (%a0)+ /* write bytes 2 and 3 as word */
.r_end_u_w2:
move.b %d2, (%a0)+ /* store final byte */
bra.w .r_exit
/* 16-bit aligned */
.r_aligned:
btst.l #1, %d0 /* longword aligned? */
beq.b .r_end_a_w1 /* yes, skip leading word handling */
/* copy initial word */
/* initial word has to be swapped */
move.w (%a2), %d7
move.b %d7, (%a0)+
lsr.l #8, %d7
move.b %d7, (%a0)+
.r_end_a_w1:
moveq.l #12, %d0
add.l %a0, %d0
and.l #0xFFFFFFF0,%d0 /* d0 == first line bound */
cmp.l %a0, %d0 /* any leading longwords? */
bls.b .r_end_a_l1 /* no: skip loop */
.r_loop_a_l1:
move.w (%a2), %d1 /* load first word */
swap %d1 /* move it to upper 16 bits */
move.w (%a2), %d1 /* load second word */
/* byte swap d1 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d1, %d7 /* d7 = .B.D */
eor.l %d7, %d1 /* d1 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d1 /* d1 = .A.C */
or.l %d7, %d1 /* d1 = BADC */
move.l %d1, (%a0)+ /* store as long */
cmp.l %a0, %d0 /* run up to first line bound */
bhi.b .r_loop_a_l1
.r_end_a_l1:
lea.l (-14, %a1), %a1 /* adjust end addr. to 16 bytes/pass */
.r_loop_a_line:
move.w (%a2), %d0 /* load 1st word */
swap %d0 /* move it to upper 16 bits */
move.w (%a2), %d0 /* load 2nd word */
/* byte swap d0 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d0, %d7 /* d7 = .B.D */
eor.l %d7, %d0 /* d0 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d0 /* d0 = .A.C */
or.l %d7, %d0 /* d0 = BADC */
move.w (%a2), %d1 /* load 3rd word */
swap %d1 /* move it to upper 16 bits */
move.w (%a2), %d1 /* load 4th word */
/* byte swap d1 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d1, %d7 /* d7 = .B.D */
eor.l %d7, %d1 /* d1 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d1 /* d1 = .A.C */
or.l %d7, %d1 /* d1 = BADC */
move.w (%a2), %d2 /* load 5th word */
swap %d2 /* move it to upper 16 bits */
move.w (%a2), %d2 /* load 6th word */
/* byte swap d2 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d2, %d7 /* d7 = .B.D */
eor.l %d7, %d2 /* d2 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d2 /* d2 = .A.C */
or.l %d7, %d2 /* d2 = BADC */
move.w (%a2), %d3 /* load 7th word */
swap %d3 /* move it to upper 16 bits */
move.w (%a2), %d3 /* load 8th word */
/* byte swap d3 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d3, %d7 /* d7 = .B.D */
eor.l %d7, %d3 /* d3 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d3 /* d3 = .A.C */
or.l %d7, %d3 /* d3 = BADC */
movem.l %d0-%d3, (%a0) /* store line */
lea.l (16, %a0), %a0
cmp.l %a0, %a1 /* run up to last line bound */
bhi.b .r_loop_a_line
lea.l (12, %a1), %a1 /* readjust for longword loop */
cmp.l %a0, %a1 /* any trailing longwords? */
bls.b .r_end_a_l2 /* no: skip loop */
.r_loop_a_l2:
move.w (%a2), %d1 /* read first word */
swap %d1 /* move it to upper 16 bits */
move.w (%a2), %d1 /* read second word */
/* byte swap d1 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d1, %d7 /* d7 = .B.D */
eor.l %d7, %d1 /* d1 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d1 /* d1 = .A.C */
or.l %d7, %d1 /* d1 = BADC */
move.l %d1, (%a0)+ /* store as long */
cmp.l %a0, %a1 /* run up to last long bound */
bhi.b .r_loop_a_l2
.r_end_a_l2:
addq.l #2, %a1 /* back to final end address */
cmp.l %a0, %a1 /* one word left? */
bls.b .r_end_a_w2
/* copy final word */
/* final word has to be swapped */
move.w (%a2), %d7
move.b %d7, (%a0)+
lsr.l #8, %d7
move.b %d7, (%a0)+
.r_end_a_w2:
.r_exit:
movem.l (%sp), %d2-%d7/%a2-%a3
lea.l (32, %sp), %sp
rts
.r_end:
.size copy_read_sectors,.r_end-copy_read_sectors
.align 2
.global copy_write_sectors
.type copy_write_sectors,@function
#if 0
/* Write a number of words to the ATA data port
*
* Utilises line bursts, assumes there is at least one full line to copy.
*
* Arguments:
* (4,%sp) - buffer address
* (8,%sp) - word count
*
* Register usage:
* %a0 - current address
* %a1 - end address
* %a2 - ata port
* %d0 - scratch
* %d1 - shift count
* %d2-%d6 - read buffers
*
* %d7 - swap scrach
* %a3 - swap mask
*/
copy_write_sectors:
lea.l (-32, %sp), %sp
movem.l %d2-%d7/%a2-%a3, (%sp)
movem.l (36, %sp), %a0-%a1
add.l %a1, %a1
add.l %a0, %a1
lea.l .ata_port, %a2
lea.l .swapmask, %a3
move.l %a0, %d0
btst.l #0, %d0 /* 16-bit aligned? */
beq .w_aligned /* yes, do word copy */
/* not 16-bit aligned */
subq.l #1, %a1 /* last byte is done unconditionally */
moveq.l #24, %d1 /* preload shift count */
move.b (%a0)+, %d2
btst.l #1, %d0 /* longword aligned? (testing old d0 value!) */
bne.b .w_end_u_w1 /* yes, skip leading word handling */
swap %d2
move.w (%a0)+, %d2
move.l %d2, %d3
lsr.l #8, %d3
/* low word of %d3 has to be byte swaped */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d3, %d7 /* d7 = .B.D */
eor.l %d7, %d3 /* d3 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d3 /* d3 = .A.C */
or.l %d7, %d3 /* d3 = BADC */
move.w %d3, (%a2)
.w_end_u_w1:
moveq.l #12, %d0
add.l %a0, %d0
and.l #0xFFFFFFF0,%d0 /* d0 == first line bound */
cmp.l %a0, %d0 /* any leading longwords? */
bls.b .w_end_u_l1 /* no: skip loop */
.w_loop_u_l1:
move.l (%a0)+, %d3
move.l %d3, %d4
lsl.l %d1, %d2
lsr.l #8, %d3
or.l %d3, %d2
/* byte swap d2 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d2, %d7 /* d7 = .B.D */
eor.l %d7, %d2 /* d2 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d2 /* d2 = .A.C */
or.l %d7, %d2 /* d2 = BADC */
swap %d2
move.w %d2, (%a2)
swap %d2
move.w %d2, (%a2)
move.l %d4, %d2
cmp.l %a0, %d0 /* run up to first line bound */
bhi.b .w_loop_u_l1
.w_end_u_l1:
lea.l (-14, %a1), %a1 /* adjust end addr. to 16 bytes/pass */
.w_loop_u_line:
movem.l (%a0), %d3-%d6
lea.l (16, %a0), %a0
move.l %d3, %d0
lsl.l %d1, %d2
lsr.l #8, %d0
or.l %d0, %d2
/* byte swap d2 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d2, %d7 /* d7 = .B.D */
eor.l %d7, %d2 /* d2 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d2 /* d2 = .A.C */
or.l %d7, %d2 /* d2 = BADC */
swap %d2
move.w %d2, (%a2)
swap %d2
move.w %d2, (%a2)
move.l %d4, %d0
lsl.l %d1, %d3
lsr.l #8, %d0
or.l %d0, %d3
/* byte swap d3 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d3, %d7 /* d7 = .B.D */
eor.l %d7, %d3 /* d3 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d3 /* d3 = .A.C */
or.l %d7, %d3 /* d3 = BADC */
swap %d3
move.w %d3, (%a2)
swap %d3
move.w %d3, (%a2)
move.l %d5, %d0
lsl.l %d1, %d4
lsr.l #8, %d0
or.l %d0, %d4
/* byte swap d4 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d4, %d7 /* d7 = .B.D */
eor.l %d7, %d4 /* d4 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d4 /* d4 = .A.C */
or.l %d7, %d4 /* d4 = BADC */
swap %d4
move.w %d4, (%a2)
swap %d4
move.w %d4, (%a2)
move.l %d6, %d0
lsl.l %d1, %d5
lsr.l #8, %d0
or.l %d0, %d5
/* byte swap d5 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d5, %d7 /* d7 = .B.D */
eor.l %d7, %d5 /* d5 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d5 /* d5 = .A.C */
or.l %d7, %d5 /* d5 = BADC */
swap %d5
move.w %d5, (%a2)
swap %d5
move.w %d5, (%a2)
move.l %d6, %d2
cmp.l %a0, %a1 /* run up to last line bound */
bhi.b .w_loop_u_line
lea.l (12, %a1), %a1 /* readjust for longword loop */
cmp.l %a0, %a1 /* any trailing longwords? */
bls.b .w_end_u_l2 /* no: skip loop */
.w_loop_u_l2:
move.l (%a0)+, %d3
move.l %d3, %d4
lsl.l %d1, %d2
lsr.l #8, %d3
or.l %d3, %d2
/* byte swap d2 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d2, %d7 /* d7 = .B.D */
eor.l %d7, %d2 /* d2 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d2 /* d2 = .A.C */
or.l %d7, %d2 /* d2 = BADC */
swap %d2
move.w %d2, (%a2)
swap %d2
move.w %d2, (%a2)
move.l %d4, %d2
cmp.l %a0, %a1 /* run up to first line bound */
bhi.b .w_loop_u_l2
.w_end_u_l2:
addq.l #2, %a1 /* back to final end address */
cmp.l %a0, %a1 /* one word left? */
bls.b .w_end_u_w2
swap %d2
move.w (%a0)+, %d2
move.l %d2, %d3
lsr.l #8, %d3
/* byte swap d3 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d3, %d7 /* d7 = .B.D */
eor.l %d7, %d3 /* d3 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d3 /* d3 = .A.C */
or.l %d7, %d3 /* d3 = BADC */
move.w %d3, (%a2)
.w_end_u_w2:
lsl.l #8, %d2
move.b (%a0)+, %d2
/* byte swap d2 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d2, %d7 /* d7 = .B.D */
eor.l %d7, %d2 /* d2 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d2 /* d2 = .A.C */
or.l %d7, %d2 /* d2 = BADC */
move.w %d2, (%a2)
bra.w .w_exit
/* 16-bit aligned */
.w_aligned:
btst.l #1, %d0
beq.b .w_end_a_w1
/* this has to be byte swaped */
/* copy initial word */
move.w (%a0)+, %d1
/* byte swap d1 */
move.l %a3, %d7 /* d7 = $00FF00FF */
and.l %d1, %d7 /* d7 = .B.D */
eor.l %d7, %d1 /* d1 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d1 /* d1 = .A.C */
or.l %d7, %d1 /* d1 = BADC */
move.w %d1, (%a2)
.w_end_a_w1:
moveq.l #12, %d0
add.l %a0, %d0
and.l #0xFFFFFFF0,%d0 /* d0 == first line bound */
cmp.l %a0, %d0 /* any leading longwords? */
bls.b .w_end_a_l1 /* no: skip loop */
.w_loop_a_l1:
move.l (%a0)+, %d1
/* byte swap d1 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d1, %d7 /* d7 = .B.D */
eor.l %d7, %d1 /* d1 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d1 /* d1 = .A.C */
or.l %d7, %d1 /* d1 = BADC */
swap %d1
move.w %d1, (%a2)
swap %d1
move.w %d1, (%a2)
cmp.l %a0, %d0 /* run up to first line bound */
bhi.b .w_loop_a_l1
.w_end_a_l1:
lea.l (-14, %a1), %a1 /* adjust end addr. to 16 bytes/pass */
.w_loop_a_line:
movem.l (%a0), %d0-%d3
/* byte swap d0-d3 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d0, %d7 /* d7 = .B.D */
eor.l %d7, %d0 /* d0 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d0 /* d0 = .A.C */
or.l %d7, %d0 /* d0 = BADC */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d1, %d7 /* d7 = .B.D */
eor.l %d7, %d1 /* d1 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d1 /* d1 = .A.C */
or.l %d7, %d1 /* d1 = BADC */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d2, %d7 /* d7 = .B.D */
eor.l %d7, %d2 /* d2 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d2 /* d2 = .A.C */
or.l %d7, %d2 /* d2 = BADC */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d3, %d7 /* d7 = .B.D */
eor.l %d7, %d3 /* d3 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d3 /* d3 = .A.C */
or.l %d7, %d3 /* d3 = BADC */
lea.l (16, %a0), %a0
swap %d0
move.w %d0, (%a2)
swap %d0
move.w %d0, (%a2)
swap %d1
move.w %d1, (%a2)
swap %d1
move.w %d1, (%a2)
swap %d2
move.w %d2, (%a2)
swap %d2
move.w %d2, (%a2)
swap %d3
move.w %d3, (%a2)
swap %d3
move.w %d3, (%a2)
cmp.l %a0, %a1 /* run up to last line bound */
bhi.b .w_loop_a_line
lea.l (12, %a1), %a1 /* readjust for longword loop */
cmp.l %a0, %a1 /* any trailing longwords? */
bls.b .w_end_a_l2 /* no: skip loop */
.w_loop_a_l2:
move.l (%a0)+, %d1
/* byte swap d1 */
move.l %a3, %d7 /* d7 = 0x00FF00FF */
and.l %d1, %d7 /* d7 = .B.D */
eor.l %d7, %d1 /* d1 = A.C. */
lsl.l #8, %d7 /* d7 = B.D. */
lsr.l #8, %d1 /* d1 = .A.C */
or.l %d7, %d1 /* d1 = BADC */
swap %d1
move.w %d1, (%a2)
swap %d1
move.w %d1, (%a2)
cmp.l %a0, %a1 /* run up to first line bound */
bhi.b .w_loop_a_l2
.w_end_a_l2:
addq.l #2, %a1 /* back to final end address */
cmp.l %a0, %a1 /* one word left? */
bls.b .w_end_a_w2
/* this has to be byte swaped */
/* copy final word */
move.w (%a0)+, %d0
move.l %a3, %d7
and.l %d0, %d7
eor.l %d7, %d0
lsl.l #8, %d7
lsr.l #8, %d0
or.l %d7, %d0
move.w %d0, (%a2)
.w_end_a_w2:
.w_exit:
movem.l (%sp), %d2-%d7/%a2-%a3
lea.l (32, %sp), %sp
rts
.w_end:
.size copy_write_sectors,.w_end-copy_write_sectors
#endif

View file

@ -0,0 +1,57 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id:$
*
* Copyright (C) 2010 Marcin Bukat
*
* 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 "cpu.h"
#include <stdbool.h>
#include "kernel.h"
#include "system.h"
#include "power.h"
#include "ata-target.h"
void ata_reset(void)
{
/* GPIO19 */
and_l(~(1<<19), &GPIO_OUT);
sleep(1); /* > 25us */
or_l((1<<19), &GPIO_OUT);
sleep(1); /* > 25us */
}
void ata_enable(bool on)
{
(void)on;
}
/* to be fixed */
bool ata_is_coldstart(void)
{
return true;
}
void ata_device_init(void)
{
/* ATA reset line config */
or_l((1<<19), &GPIO_OUT);
or_l((1<<19), &GPIO_ENABLE);
or_l((1<<19), &GPIO_FUNCTION);
}

View file

@ -0,0 +1,77 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id:$
*
* Copyright (C) 2010 Marcin Bukat
*
* 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 ATA_TARGET_H
#define ATA_TARGET_H
/* asm optimised read & write loops - we skip this for now*/
#define ATA_OPTIMIZED_READING
//#define ATA_OPTIMIZED_WRITING
#define SWAP_WORDS
#define ATA_IOBASE 0x20000000
#define ATA_DATA (*((volatile unsigned short*)(ATA_IOBASE + 0x20)))
#define ATA_CONTROL (*((volatile unsigned short*)(ATA_IOBASE + 0x1c)))
#define ATA_ERROR (*((volatile unsigned short*)(ATA_IOBASE + 0x22)))
#define ATA_NSECTOR (*((volatile unsigned short*)(ATA_IOBASE + 0x24)))
#define ATA_SECTOR (*((volatile unsigned short*)(ATA_IOBASE + 0x26)))
#define ATA_LCYL (*((volatile unsigned short*)(ATA_IOBASE + 0x28)))
#define ATA_HCYL (*((volatile unsigned short*)(ATA_IOBASE + 0x2a)))
#define ATA_SELECT (*((volatile unsigned short*)(ATA_IOBASE + 0x2c)))
#define ATA_COMMAND (*((volatile unsigned short*)(ATA_IOBASE + 0x2e)))
#define STATUS_BSY 0x80
#define STATUS_RDY 0x40
#define STATUS_DF 0x20
#define STATUS_DRQ 0x08
#define STATUS_ERR 0x01
#define ERROR_ABRT 0x04
#define ERROR_IDNF 0x10
#define WRITE_PATTERN1 0xa5
#define WRITE_PATTERN2 0x5a
#define WRITE_PATTERN3 0xaa
#define WRITE_PATTERN4 0x55
#define READ_PATTERN1 0xa5
#define READ_PATTERN2 0x5a
#define READ_PATTERN3 0xaa
#define READ_PATTERN4 0x55
#define READ_PATTERN1_MASK 0xff
#define READ_PATTERN2_MASK 0xff
#define READ_PATTERN3_MASK 0xff
#define READ_PATTERN4_MASK 0xff
#define SET_REG(reg,val) reg = (val)
#define SET_16BITREG(reg,val) reg = (val)
void ata_reset(void);
void ata_enable(bool on);
void ata_device_init(void);
bool ata_is_coldstart(void);
void copy_read_sectors(unsigned char* buf, int wordcount);
//void copy_write_sectors(const unsigned char* buf, int wordcount);
#endif

View file

@ -0,0 +1,49 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id:$
*
* Copyright (C) 2010 Marcin Bukat
*
* 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 "system.h"
#include "cpu.h"
#include "audio.h"
#include "sound.h"
void audio_set_output_source(int source)
{
(void)source;
int level = set_irq_level(DMA_IRQ_LEVEL);
/* PDOR3 */
IIS2CONFIG = (IIS2CONFIG & ~(7 << 8)) | (3 << 8);
restore_irq(level);
}
void audio_input_mux(int source, unsigned flags)
{
(void)source;
(void)flags;
switch(source)
{
case AUDIO_SRC_FMRADIO:
break;
}
/* empty stub */
}

View file

@ -0,0 +1,81 @@
#include "config.h"
ENTRY(start)
OUTPUT_FORMAT(elf32-m68k)
STARTUP(target/coldfire/crt0.o)
#define DRAMSIZE (MEMORYSIZE * 0x100000)
#define DRAMORIG 0x31000000
#define IRAMORIG 0x10000000
#define IRAMSIZE 0x18000
#define FLASHORIG 0x000e0000
#define FLASHSIZE 0x1f800
MEMORY
{
DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE
FLASH : ORIGIN = FLASHORIG, LENGTH = FLASHSIZE
}
SECTIONS
{
.vectors :
{
_datacopy = .;
} > FLASH
.data : AT ( _datacopy )
{
_datastart = .;
KEEP(*(.resetvectors));
*(.resetvectors);
KEEP(*(.vectors));
*(.vectors);
. = ALIGN(0x200);
*(.icode)
*(.irodata)
*(.idata)
*(.data*)
. = ALIGN(0x4);
_dataend = .;
. = ALIGN(0x10); /* Maintain proper alignment for .text section */
} > IRAM
/* TRICK ALERT! Newer versions of the linker don't allow output sections
to overlap even if one of them is empty, so advance the location pointer
"by hand" */
.text LOADADDR(.data) + SIZEOF(.data) :
{
*(.init.text)
*(.text*)
. = ALIGN(0x4);
} > FLASH
.rodata :
{
*(.rodata*)
. = ALIGN(0x4);
_iramcopy = .;
} > FLASH
.stack :
{
*(.stack)
_stackbegin = .;
stackbegin = .;
. += 0x2000;
_stackend = .;
stackend = .;
} > IRAM
.bss DRAMORIG+0x800000:
{
_edata = .;
*(.ibss)
*(.bss*)
*(COMMON)
_end = .;
} > DRAM
}

View file

@ -0,0 +1,81 @@
#include "config.h"
ENTRY(start)
OUTPUT_FORMAT(elf32-m68k)
STARTUP(target/coldfire/crt0.o)
#define DRAMSIZE (MEMORYSIZE * 0x100000)
#define DRAMORIG 0x31000000
#define IRAMORIG 0x10000000
#define IRAMSIZE 0x18000
#define FLASHORIG 0x000e0000
#define FLASHSIZE 0x1f800
MEMORY
{
DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE
FLASH : ORIGIN = FLASHORIG, LENGTH = FLASHSIZE
}
SECTIONS
{
.vectors :
{
_datacopy = .;
} > FLASH
.data : AT ( _datacopy )
{
_datastart = .;
KEEP(*(.resetvectors));
*(.resetvectors);
KEEP(*(.vectors));
*(.vectors);
. = ALIGN(0x200);
*(.icode)
*(.irodata)
*(.idata)
*(.data*)
. = ALIGN(0x4);
_dataend = .;
. = ALIGN(0x10); /* Maintain proper alignment for .text section */
} > IRAM
/* TRICK ALERT! Newer versions of the linker don't allow output sections
to overlap even if one of them is empty, so advance the location pointer
"by hand" */
.text LOADADDR(.data) + SIZEOF(.data) :
{
*(.init.text)
*(.text*)
. = ALIGN(0x4);
} > FLASH
.rodata :
{
*(.rodata*)
. = ALIGN(0x4);
_iramcopy = .;
} > FLASH
.stack :
{
*(.stack)
_stackbegin = .;
stackbegin = .;
. += 0x2000;
_stackend = .;
stackend = .;
} > IRAM
.bss DRAMORIG+0x800000:
{
_edata = .;
*(.ibss)
*(.bss*)
*(COMMON)
_end = .;
} > DRAM
}

View file

@ -0,0 +1,81 @@
#include "config.h"
ENTRY(start)
OUTPUT_FORMAT(elf32-m68k)
STARTUP(target/coldfire/crt0.o)
#define DRAMSIZE (MEMORYSIZE * 0x100000)
#define DRAMORIG 0x31000000
#define IRAMORIG 0x10000000
#define IRAMSIZE 0x18000
#define FLASHORIG 0x000e0000
#define FLASHSIZE 0x1f800
MEMORY
{
DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE
FLASH : ORIGIN = FLASHORIG, LENGTH = FLASHSIZE
}
SECTIONS
{
.vectors :
{
_datacopy = .;
} > IRAM
.data : AT ( _datacopy )
{
_datastart = .;
KEEP(*(.resetvectors));
*(.resetvectors);
KEEP(*(.vectors));
*(.vectors);
. = ALIGN(0x200);
*(.icode)
*(.irodata)
*(.idata)
*(.data*)
. = ALIGN(0x4);
_dataend = .;
. = ALIGN(0x10); /* Maintain proper alignment for .text section */
} > IRAM
/* TRICK ALERT! Newer versions of the linker don't allow output sections
to overlap even if one of them is empty, so advance the location pointer
"by hand" */
.text LOADADDR(.data) + SIZEOF(.data) :
{
*(.init.text)
*(.text*)
. = ALIGN(0x4);
} > IRAM
.rodata :
{
*(.rodata*)
. = ALIGN(0x4);
_iramcopy = .;
} > IRAM
.stack :
{
*(.stack)
_stackbegin = .;
stackbegin = .;
. += 0x2000;
_stackend = .;
stackend = .;
} > IRAM
.bss DRAMORIG+0x800000:
{
_edata = .;
*(.ibss)
*(.bss*)
*(COMMON)
_end = .;
} > DRAM
}

View file

@ -0,0 +1,55 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id:$
*
* Copyright (C) 2010 Marcin Bukat
*
* 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 <stdbool.h>
#include "config.h"
#define HAS_BUTTON_HOLD
bool button_hold(void);
void button_init_device(void);
int button_read_device(void);
/* HD200 specific button codes */
/* Main unit's buttons - flags as in original firmware*/
#define BUTTON_PLAY 0x00000001
#define BUTTON_PREV 0x00000004
#define BUTTON_NEXT 0x00000002
#define BUTTON_VOL_UP 0x00000008
#define BUTTON_VOL_DOWN 0x00000010
#define BUTTON_REC 0x00000020
#define BUTTON_SELECT 0x00002000
#define BUTTON_LEFT BUTTON_PREV
#define BUTTON_RIGHT BUTTON_NEXT
#define BUTTON_ON BUTTON_PLAY
#define BUTTON_REMOTE 0x0
#define BUTTON_MAIN (BUTTON_PLAY|BUTTON_PREV|BUTTON_NEXT|BUTTON_VOL_UP|\
BUTTON_VOL_DOWN|BUTTON_REC|BUTTON_SELECT)
#define POWEROFF_BUTTON BUTTON_PLAY
#define POWEROFF_COUNT 30
#endif /* _BUTTON_TARGET_H_ */

View file

@ -0,0 +1,40 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
* Physical interface of the Philips TEA5767 in iAudio M3
*
* Copyright (C) 2002 by Linus Nielsen Feltzing
*
* 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"
#if (CONFIG_TUNER & TEA5767)
#include "i2c-coldfire.h"
#include "fmradio_i2c.h"
int fmradio_i2c_write(unsigned char address, const unsigned char* buf,
int count)
{
return i2c_write(I2C_IFACE_1, address, buf, count);
}
int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count)
{
return i2c_read(I2C_IFACE_1, address, buf, count);
}
#endif

View file

@ -0,0 +1,84 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id:$
*
* Copyright (C) 2010 Marcin Bukat
*
* 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 "cpu.h"
#include "system.h"
#include "kernel.h"
#include "thread.h"
#include "adc.h"
volatile unsigned short adc_data[NUM_ADC_CHANNELS] IBSS_ATTR;
/* Reading takes 4096 adclk ticks
* We do read one channel at once
*
* state FCPU Fbus Fadc bus/Fadc Fchannelread
* default 11.2896 MHz 5.6448 MHz 5.6448 MHz 2 172.2656 Hz
* normal 45.1584 MHz 22.5792 MHz 2.8224 MHz 8 172.2656 Hz
* max 124.1856 MHz 62.0928 MHz 1.9404 MHz 32 118.4326 Hz
*/
void ADC(void) __attribute__ ((interrupt_handler,section(".icode")));
void ADC(void)
{
static unsigned char channel;
/* read current value */
adc_data[(channel & 0x03)] = ADVALUE;
/* switch channel
*
* set source remark
* ADCONFIG is 16bit wide so we have to shift data by 16bits left
* thats why we shift <<24 instead of <<8
*/
channel++;
and_l(~(3<<24),&ADCONFIG);
or_l( (((channel & 0x03) << 8 )|(1<<7))<<16, &ADCONFIG);
}
unsigned short adc_scan(int channel)
{
/* maybe we can drop &0x03 part */
return adc_data[(channel&0x03)];
}
void adc_init(void)
{
/* GPIO38 GPIO39 */
and_l(~((1<<6)|(1<<7)), &GPIO1_FUNCTION);
/* ADOUT_SEL = 01
* SOURCE SELECT = 000
* CLEAR INTERRUPT FLAG
* ENABLE INTERRUPT = 1
* ADOUT_DRIVE = 00
* ADCLK_SEL = 011 (busclk/8)
*/
ADCONFIG = (1<<10)|(1<<7)|(1<<6)|(1<<1)|(1<<0);
/* ADC interrupt level 4.0 */
or_l((4<<28), &INTPRI8);
}

View file

@ -0,0 +1,41 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id:$
*
* Copyright (C) 2010 Marcin Bukat
*
* 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 _ADC_TARGET_H_
#define _ADC_TARGET_H_
#define NUM_ADC_CHANNELS 4
#define ADC_BUTTONS 1
#define ADC_REMOTE 0
#define ADC_BATTERY 2
#define ADC_REMOTEDETECT 3
#define ADC_UNREG_POWER ADC_BATTERY /* For compatibility */
/* Force a scan now */
unsigned short adc_scan(int channel);
static inline unsigned short adc_read(int channel)
{
return adc_scan(channel);
}
#endif /* _ADC_TARGET_H_ */

View file

@ -0,0 +1,86 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id:$
*
* Copyright (C) 2010 Marcin Bukat
*
* 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 "cpu.h"
#include "kernel.h"
#include "system.h"
#include "backlight.h"
#include "backlight-target.h"
#include "lcd.h"
static bool _backlight_on = false;
static int _brightness = DEFAULT_BRIGHTNESS_SETTING;
/* Returns the current state of the backlight (true=ON, false=OFF). */
bool _backlight_init(void)
{
and_l(~(1<<28),&GPIO_OUT);
or_l((1<<28),&GPIO_FUNCTION);
or_l((1<<28),&GPIO_ENABLE);
return true;
}
void _backlight_hw_on(void)
{
if (_backlight_on)
return;
_backlight_set_brightness(_brightness);
_backlight_on = true;
}
void _backlight_hw_off(void)
{
/* GPIO28 low */
and_l(~(1<<28),&GPIO_OUT);
_backlight_on = false;
}
void _backlight_set_brightness(int val)
{
unsigned char i;
and_l(~(1<<28),&GPIO_OUT);
sleep(4);
for (i=0;i<val;i++)
{
or_l((1<<28),&GPIO_OUT);
and_l(~(1<<28),&GPIO_OUT);
}
or_l((1<<28),&GPIO_OUT);
_brightness = val;
}
void _remote_backlight_on(void)
{
/* I don't have remote to play with */
}
void _remote_backlight_off(void)
{
/* I don't have remote to play with */
}

View file

@ -0,0 +1,35 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id:$
*
* Copyright (C) 2010 Marcin Bukat
*
* 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
bool _backlight_init(void); /* Returns backlight current state (true=ON). */
void _backlight_hw_on(void);
void _backlight_hw_off(void);
void _backlight_set_brightness(int val);
#define _backlight_on() _backlight_hw_on()
#define _backlight_off() _backlight_hw_off()
#define _backlight_on_isr() _backlight_hw_on()
#define _backlight_off_isr() _backlight_hw_off()
#define _backlight_on_normal() _backlight_hw_on()
#define _backlight_off_normal() _backlight_hw_off()
#endif

View file

@ -0,0 +1,123 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id:$
*
* Copyright (C) 2010 Marcin Bukat
*
* 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 "cpu.h"
#include "system.h"
#include "button.h"
#include "backlight.h"
#include "adc.h"
void button_init_device(void)
{
/* Set GPIO36, GPIO56 as general purpose inputs */
or_l((1<<4)|(1<<24),&GPIO1_FUNCTION);
and_l(~((1<<4)|(1<<24)),&GPIO1_ENABLE);
}
bool button_hold(void)
{
/* GPIO36 active high */
return (GPIO1_READ & (1<<4))?true:false;
}
/*
* Get button pressed from hardware
*/
int button_read_device(void)
{
int btn = BUTTON_NONE;
int data = 0;
static bool hold_button = false;
/* for moving average filter */
static unsigned short button_filter[4];
static unsigned char index;
bool hold_button_old;
/* normal buttons */
hold_button_old = hold_button;
hold_button = button_hold();
#ifndef BOOTLOADER
if (hold_button != hold_button_old)
backlight_hold_changed(hold_button);
#endif
if (!hold_button)
{
/* simple moving average filter with 4 item window */
button_filter[index&0x03] = adc_scan(ADC_BUTTONS);
index++;
data = (button_filter[0]+button_filter[1] \
+button_filter[2]+button_filter[3])>>2;
if (data < 2250) // valid button
{
if (data < 900) /* middle */
{
if (data < 500)
{
if (data > 200)
/* 200 - 500 */
btn = BUTTON_REC;
}
else /* 900 - 500 */
btn = BUTTON_VOL_DOWN;
}
else /* 2250 - 900 */
{
if (data < 1600)
{
/* 1600 - 900 */
if (data < 1200)
/* 1200 - 900 */
btn = BUTTON_VOL_UP;
else /* 1600 - 1200 */
btn = BUTTON_NEXT;
}
else /* 1600 - 2250 */
{
if (data < 1900)
/* 1900 - 1600 */
btn = BUTTON_PREV;
else /* 1900 - 2250 */
btn = BUTTON_SELECT;
}
}
}
}
data = GPIO1_READ;
/* GPIO56 active high main PLAY/PAUSE/ON */
if (!hold_button && ((data & (1<<24))))
btn |= BUTTON_PLAY;
return btn;
}

View file

@ -0,0 +1,103 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id:$
*
* Copyright (C) 2010 Marcin Bukat
*
* 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 "cpu.h"
#define LCD_BASE_ADDRESS 0xf0000000
.section .icode,"ax",@progbits
.align 2
.global lcd_write_command
.type lcd_write_command,@function
lcd_write_command:
move.l (4, %sp), %d0
move.w %d0, LCD_BASE_ADDRESS /* data is 1byte but CF uses word
* transfers only */
rts
.wc_end:
.size lcd_write_command,.wc_end-lcd_write_command
.align 2
.global lcd_write_command_e
.type lcd_write_command_e,@function
lcd_write_command_e:
lea.l LCD_BASE_ADDRESS, %a0
move.l (4, %sp), %d0 /* Command */
move.w %d0, (%a0)
move.l (8, %sp), %d0 /* Data */
move.w %d0, (%a0) /* Write to LCD */
rts
.wce_end:
.size lcd_write_command_e,.wce_end-lcd_write_command_e
.align 2
.global lcd_write_data
.type lcd_write_data,@function
/* PIXELFORMAT = VERTICAL_INTERLEAVED
* this means that data is packed verticaly in 8 pixels columns
* first byte is lsb of 2bit color in column
* second byte is msb of 2bit color in column
* so one word of data equals 8 pixels i 2bits color depth packed
* verticaly
*/
lcd_write_data:
movem.l (4, %sp), %a0 /* Data pointer */
move.l (8, %sp), %d0 /* Length i in words */
lea LCD_BASE_ADDRESS+2, %a1 /* LCD data port address */
btst #0, %d0 /* longwords multiply? */
beq .l_write
.w_write:
move.w (%a0)+, %d1 /* load data 3 cycles*/
move.w %d1, (%a1) /* first byte 1 cycle*/
lsr.l #8, %d1 /* load second byte 1 cycle*/
move.w %d1, (%a1) /* transfer 1 cycle*/
subq.l #1, %d0 /* decrement counter 1 cycle*/
beq .write_end
.l_write:
move.l (%a0)+, %d1 /* load data 2 cycles*/
swap %d1 /* 1 cycle */
move.w %d1, (%a1) /* first byte 1 cycle*/
lsr.l #8, %d1 /* 1 cycle */
move.w %d1, (%a1) /* second byte 1 cycle*/
lsr.l #8, %d1 /* 1 cycle */
move.w %d1, (%a1) /* third byte 1 cycle*/
lsr.l #8, %d1 /* 1 cycle */
move.w %d1, (%a1) /* forth byte 1 cycle*/
subq.l #2, %d0 /* decrement counter 1 cycle*/
bne .l_write
.write_end:
rts
.size lcd_write_data,.wd_end-lcd_write_data

View file

@ -0,0 +1,241 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id:$
*
* Copyright (C) 2010 Marcin Bukat
*
* 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 "system.h"
#include "kernel.h"
#include "lcd.h"
/*** definitions ***/
/* TOMATO LSI 0350 - definitions and slightly tweaked functions
* taken from lcd-remote-iaudio.c
*/
#define LCD_SET_DUTY_RATIO 0x48
#define LCD_SELECT_ADC 0xa0
#define LCD_SELECT_SHL 0xc0
#define LCD_SET_COM0 0x44
#define LCD_OSC_ON 0xab
#define LCD_SELECT_DCDC 0x64
#define LCD_SELECT_RES 0x20
#define LCD_SET_VOLUME 0x81
#define LCD_SET_BIAS 0x50
#define LCD_CONTROL_POWER 0x28
#define LCD_DISPLAY_ON 0xae
#define LCD_SET_INITLINE 0x40
#define LCD_SET_COLUMN 0x10
#define LCD_SET_PAGE 0xb0
#define LCD_SET_GRAY 0x88
#define LCD_SET_PWM_FRC 0x90
#define LCD_SET_POWER_SAVE 0xa8
#define LCD_REVERSE 0xa6
#define LCD_RESET 0xe2
/* cached settings */
static bool cached_invert = false;
static bool cached_flip = false;
static int cached_contrast = DEFAULT_CONTRAST_SETTING;
bool lcd_initialized = false;
/*** hardware configuration ***/
int lcd_default_contrast(void)
{
return DEFAULT_CONTRAST_SETTING;
}
void lcd_powersave(bool on)
{
/* What is the point of having else construct here? */
if(lcd_initialized) {
if (on)
lcd_write_command(LCD_SET_POWER_SAVE | 1);
else
lcd_write_command(LCD_SET_POWER_SAVE | 1);
}
}
void lcd_set_contrast(int val)
{
if (val < MIN_CONTRAST_SETTING)
val = MIN_CONTRAST_SETTING;
else if (val > MAX_CONTRAST_SETTING)
val = MAX_CONTRAST_SETTING;
cached_contrast = val;
if(lcd_initialized)
lcd_write_command_e(LCD_SET_VOLUME, val);
}
void lcd_set_invert_display(bool yesno)
{
cached_invert = yesno;
if(lcd_initialized)
lcd_write_command(LCD_REVERSE | yesno);
}
/* turn the display upside down (call lcd_update() afterwards) */
void lcd_set_flip(bool yesno)
{
cached_flip = yesno;
if(lcd_initialized)
{
if(yesno)
{
lcd_write_command(LCD_SELECT_ADC | 1);
lcd_write_command(LCD_SELECT_SHL | 0);
lcd_write_command_e(LCD_SET_COM0, 0);
}
else
{
lcd_write_command(LCD_SELECT_ADC | 0);
lcd_write_command(LCD_SELECT_SHL | 8);
lcd_write_command_e(LCD_SET_COM0, 0);
}
}
}
void lcd_shutdown(void)
{
/* Set power save -> Power OFF (VDD - VSS) .. that's it */
if (lcd_initialized)
lcd_write_command(LCD_SET_POWER_SAVE | 1);
}
void lcd_init_device(void)
{
and_l(~0x00000800, &GPIO_FUNCTION); /* CS3 line */
/* LCD Reset GPO34 */
or_l(0x00000004, &GPIO1_ENABLE); /* set as output */
or_l(0x00000004, &GPIO1_FUNCTION); /* switch to secondary function - GPIO */
and_l(~0x00000004, &GPIO1_OUT); /* RESET low */
sleep(1); /* delay at least 1000 ns */
or_l(0x00000004, &GPIO1_OUT); /* RESET high */
sleep(1);
/* parameters setup taken from original firmware */
lcd_write_command(LCD_RESET);
lcd_write_command_e(LCD_SET_DUTY_RATIO,0x80); /* 1/128 */
lcd_write_command(LCD_OSC_ON);
lcd_write_command(LCD_SELECT_DCDC | 3); /* DC/DC 6xboost */
lcd_write_command(LCD_SELECT_RES | 7); /* Regulator resistor: 7.2 */
lcd_write_command(LCD_SET_BIAS | 6); /* 1/11 */
lcd_write_command(LCD_SET_PWM_FRC | 6); /* 3FRC + 12PWM */
lcd_write_command_e(LCD_SET_GRAY | 0, 0x00);
lcd_write_command_e(LCD_SET_GRAY | 1, 0x00);
lcd_write_command_e(LCD_SET_GRAY | 2, 0x0c);
lcd_write_command_e(LCD_SET_GRAY | 3, 0x00);
lcd_write_command_e(LCD_SET_GRAY | 4, 0xc4);
lcd_write_command_e(LCD_SET_GRAY | 5, 0x00);
lcd_write_command_e(LCD_SET_GRAY | 6, 0xcc);
lcd_write_command_e(LCD_SET_GRAY | 7, 0x00);
lcd_write_command(LCD_CONTROL_POWER | 7); /* All circuits ON */
lcd_write_command(LCD_DISPLAY_ON | 1); /* display on */
/* Ok we are ready */
lcd_initialized = true;
lcd_set_flip(cached_flip);
lcd_set_contrast(cached_contrast);
lcd_set_invert_display(cached_invert);
lcd_update();
}
/* 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(!lcd_initialized)
return;
for(y = 0;y < LCD_FBHEIGHT;y++)
{
lcd_write_command(LCD_SET_PAGE | y);
lcd_write_command_e(LCD_SET_COLUMN, 0);
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 (!lcd_initialized)
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_SET_PAGE | y );
lcd_write_command_e(LCD_SET_COLUMN | ((x >> 4) & 0xf), x & 0x0f);
lcd_write_data (&lcd_framebuffer[y][x], width);
}
}
void lcd_blit_grey_phase(unsigned char *values, unsigned char *phases,
int x, int by, int width, int bheight, int stride)
{
(void)values;
(void)phases;
(void)x;
(void)by;
(void)width;
(void)bheight;
(void)stride;
/* empty stub */
}
void lcd_blit_mono(const unsigned char *data, int x, int by, int width,
int bheight, int stride)
{
(void)data;
(void)x;
(void)by;
(void)width;
(void)bheight;
(void)stride;
/* empty stub */
}

View file

@ -0,0 +1,113 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id:$
*
* Copyright (C) 2010 Marcin Bukat
*
* 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 "cpu.h"
#include <stdbool.h>
#include "kernel.h"
#include "system.h"
#include "lcd.h"
#include "power.h"
#if CONFIG_TUNER
bool tuner_power(bool status)
{
(void)status;
if (status)
{
and_l(~(1<<17), &GPIO1_OUT);
}
else
{
or_l((1<<17), &GPIO1_OUT);
}
return status;
}
#endif /* #if CONFIG_TUNER */
void power_init(void)
{
/* GPIO53 has to be high - low resets device */
/* GPIO49 is FM related */
or_l((1<<21)|(1<<17), &GPIO1_OUT);
or_l((1<<21)|(1<<17), &GPIO1_ENABLE);
or_l((1<<21)|(1<<17)|(1<<14), &GPIO1_FUNCTION);
and_l(~(1<<15), &GPIO_OUT);
or_l((1<<15),&GPIO_ENABLE);
or_l((1<<15),&GPIO_FUNCTION);
or_l((1<<23), &GPIO_OUT);
and_l(~(1<<23), &GPIO_ENABLE);
or_l((1<<23), &GPIO_FUNCTION);
#ifndef BOOTLOADER
/* The boot loader controls the power */
ide_power_enable(true);
#endif
}
unsigned int power_input_status(void)
{
unsigned int status = POWER_INPUT_NONE;
/* GPIO46 is AC plug detect (low = AC plugged) */
if (!(GPIO1_READ & (1<<14)))
status |= POWER_INPUT_MAIN_CHARGER;
return status;
}
/* Returns true if the unit is charging the batteries. */
bool charging_state(void)
{
if (!(GPIO1_READ & (1<<14)))
return (GPIO_READ & (1<<30) )?false:true;
else
return false;
}
void ide_power_enable(bool on)
{
(void)on;
if (on)
and_l(~(1<<31),&GPIO_OUT);
else
or_l((1<<31),&GPIO_OUT);
or_l((1<<31),&GPIO_ENABLE);
or_l((1<<31),&GPIO_FUNCTION);
}
bool ide_powered(void)
{
return true;
}
void power_off(void)
{
lcd_shutdown();
set_irq_level(DISABLE_INTERRUPTS);
and_l(~(1<<21), &GPIO1_OUT); /* pull KEEPACT low */
asm("halt");
while(1);
}

View file

@ -0,0 +1,59 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id:$
*
* Copyright (C) 2010 Marcin Bukat
*
* 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 "adc.h"
#include "powermgmt.h"
const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
{
3700
};
const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
{
3650
};
/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */
const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
{
/* from OF and measurements voltage range is 3.7-4.1 V */
{ 3700, 3740, 3780, 3820, 3860, 3900, 3940, 3980, 4020, 4060, 4100 }
};
/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */
const unsigned short percent_to_volt_charge[11] =
{
/* values measured over one full charging cycle */
3540, 3860, 3930, 3980, 4000, 4020, 4040, 4080, 4130, 4180, 4230 /* LiPo */
};
/* 3.33V as reference */
#define BATTERY_SCALE_FACTOR 3330
/* Returns battery voltage from ADC [millivolts] */
unsigned int battery_adc_voltage(void)
{
return (adc_read(ADC_BATTERY) * BATTERY_SCALE_FACTOR) >> 11;
}

View file

@ -0,0 +1,125 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id:$
*
* Copyright (C) 2010 Marcin Bukat
*
* 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 "cpu.h"
#include "kernel.h"
#include "system.h"
#include "power.h"
#include "timer.h"
/* Settings for all possible clock frequencies (with properly working timers)
*
* xxx_REFRESH_TIMER below
* system.h, CPUFREQ_xxx_MULT |
* | |
* V V
* PLLCR & Rftim. IDECONFIG1/IDECONFIG2
* CPUCLK/Hz MULT ~0x70c00000 16MB CSCR0 CSCR1 CS2Pre CS2Post CS2Wait
* -------------------------------------------------------------------------
* 11289600 1 0x00000200 4 0x0180 0x0180 1 1 0
* 22579200 2 0x05028049 10 0x0180 0x0180 1 1 0
* 33868800 3 0x03024049 15 0x0180 0x0180 1 1 0
* 45158400 4 0x05028045 21 0x0180 0x0180 1 1 0
* 56448000 5 0x02028049 26 0x0580 0x0580 2 1 0
* 67737600 6 0x03024045 32 0x0580 0x0980 2 1 0
* 79027200 7 0x0302a045 37 0x0580 0x0d80 2 1 0
* 90316800 8 0x03030045 43 0x0980 0x0d80 2 1 0
* 101606400 9 0x01024049 48 0x0980 0x1180 2 1 0
* 112896000 10 0x01028049 54 0x0980 0x1580 3 1 0
* 124185600 11 0x0102c049 59 0x0980 0x1180 3 1 1
*/
#define MAX_REFRESH_TIMER 59
#define NORMAL_REFRESH_TIMER 21
#define DEFAULT_REFRESH_TIMER 4
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
void set_cpu_frequency (long) __attribute__ ((section (".icode")));
void set_cpu_frequency(long frequency)
#else
void cf_set_cpu_frequency (long) __attribute__ ((section (".icode")));
void cf_set_cpu_frequency(long frequency)
#endif
{
switch(frequency)
{
case CPUFREQ_MAX:
DCR = (0x8200 | DEFAULT_REFRESH_TIMER);
/* Refresh timer for bypass frequency */
PLLCR &= ~1; /* Bypass mode */
timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, false);
PLLCR = 0x0102c049 | (PLLCR & 0x70C00000);
CSCR0 = 0x00001180; /* Flash: 4 wait states */
CSCR3 = 0x00001180; /* LCD: 4 wait states */
while(!(PLLCR & 0x80000000)) {}; /* Wait until the PLL has locked.
This may take up to 10ms! */
timers_adjust_prescale(CPUFREQ_MAX_MULT, true);
DCR = (0x8200 | MAX_REFRESH_TIMER); /* Refresh timer */
cpu_frequency = CPUFREQ_MAX;
IDECONFIG1 = (1<<28)|(1<<20)|(1<<18)|(1<<13)|(3<<10);
/* BUFEN2 enable on /CS2 | CS2Post 1 clock| CS2Pre 3 clocks*/
IDECONFIG2 = (1<<18)|(1<<16)|(1<<8)|(1<<0); /* TA /CS2 enable + CS2wait */
and_l(~(0x07<<16), &ADCONFIG);
or_l(((1<<7)|(1<<2)|(1<<0))<<16, &ADCONFIG); /* adclk = busclk/32 */
break;
case CPUFREQ_NORMAL:
DCR = (DCR & ~0x01ff) | DEFAULT_REFRESH_TIMER;
/* Refresh timer for bypass frequency */
PLLCR &= ~1; /* Bypass mode */
timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, false);
PLLCR = 0x05028045 | (PLLCR & 0x70C00000);
CSCR0 = 0x00000580; /* Flash: 1 wait state */
CSCR3 = 0x00000980; /* LCD: 0 wait states */
while(!(PLLCR & 0x80000000)) {}; /* Wait until the PLL has locked.
This may take up to 10ms! */
timers_adjust_prescale(CPUFREQ_NORMAL_MULT, true);
DCR = (0x8000 | NORMAL_REFRESH_TIMER); /* Refresh timer */
cpu_frequency = CPUFREQ_NORMAL;
IDECONFIG1 = (1<<28)|(1<<20)|(1<<18)|(1<<13)|(1<<10);
IDECONFIG2 = (1<<18)|(1<<16);
and_l(~(0x07<<16), &ADCONFIG);
or_l(((1<<7)|(1<<1)|(1<<0))<<16, &ADCONFIG); /* adclk = busclk/8 */
break;
default:
DCR = (DCR & ~0x01ff) | DEFAULT_REFRESH_TIMER;
/* Refresh timer for bypass frequency */
PLLCR &= ~1; /* Bypass mode */
timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, true);
/* Power down PLL, but keep CLSEL and CRSEL */
PLLCR = 0x00000200 | (PLLCR & 0x70C00000);
CSCR0 = 0x00000180; /* Flash: 0 wait states */
CSCR3 = 0x00000980; /* LCD: 0 wait states */
DCR = (0x8000 | DEFAULT_REFRESH_TIMER); /* Refresh timer */
cpu_frequency = CPUFREQ_DEFAULT;
IDECONFIG1 = (1<<28)|(1<<20)|(1<<18)|(1<<13)|(1<<10);
IDECONFIG2 = (1<<18)|(1<<16);
and_l(~(0x07<<16), &ADCONFIG);
or_l(((1<<7)|(1<<0))<<16, &ADCONFIG); /* adclk = busclk/2 */
break;
}
}

View file

@ -0,0 +1,81 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id:$
*
* Copyright (C) 2010 Marcin Bukat
*
* 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 <stdbool.h>
#include "cpu.h"
#include "system.h"
#include "kernel.h"
#include "usb.h"
void usb_init_device(void)
{
/* GPIO42 is USB detect input
* but it also serves as MCLK2 for DAC
*/
and_l(~(1<<4), &GPIO1_OUT);
or_l((1<<4)|(1<<18), &GPIO1_ENABLE); /* GPIO36 GPIO50 */
or_l((1<<4)|(1<<18), &GPIO1_FUNCTION);
/* GPIO22 GPIO30*/
/* GPIO31 has to be low to ATA work */
or_l((1<<22)|(1<<30), &GPIO_OUT);
or_l((1<<22)|(1<<30)|(1<<31), &GPIO_ENABLE);
or_l((1<<22)|(1<<30)|(1<<31), &GPIO_FUNCTION);
}
int usb_detect(void)
{
/* GPIO42 active low*/
return (GPIO1_READ & (1<<10)) ? USB_EXTRACTED : USB_INSERTED;
}
void usb_enable(bool on)
{
if(on)
{
or_l((1<<18),&GPIO1_OUT); /* GPIO50 high */
and_l(~(1<<30),&GPIO_OUT); /* GPIO30 low */
/* GPIO36 low delay GPIO36 high delay */
and_l(~(1<<4),&GPIO1_OUT);
or_l((1<<4),&GPIO1_OUT);
and_l(~(1<<18),&GPIO1_OUT); /* GPIO50 low */
sleep(HZ/5); /* delay 200 ms */
and_l(~(1<<22),&GPIO_OUT); /* GPIO22 low */
}
else
{
/* GPIO36 low delay GPIO36 high delay */
and_l(~(1<<4),&GPIO1_OUT);
sleep(HZ/100);
or_l((1<<4),&GPIO1_OUT);
sleep(HZ/100);
or_l((1<<22),&GPIO_OUT); /* GPIO22 high */
or_l((1<<30),&GPIO_OUT); /* GPIO30 high */
and_l(~(1<<4),&GPIO1_OUT); /* GPIO36 low */
//or_l((1<<18),&GPIO1_OUT); /* GPIO50 high */
}
}

View file

@ -0,0 +1,52 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id:$
*
* Coldfire specific code for Wolfson audio codecs based on
* wmcodec-pp.c
*
* Based on code from the ipodlinux project - http://ipodlinux.org/
* Adapted for Rockbox in December 2005
*
* Original file: linux/arch/armnommu/mach-ipod/audio.c
*
* Copyright (c) 2003-2005 Bernard Leach (leachbj@bouncycastle.org)
*
* 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 "system.h"
#include "audiohw.h"
#include "i2c-coldfire.h"
#include "i2s.h"
#include "wmcodec.h"
#if defined(MPIO_HD200)
#define I2C_CODEC_ADDRESS 0x34
#define I2C_IFACE I2C_IFACE_1
#endif
void audiohw_init(void)
{
audiohw_preinit();
}
void wmcodec_write(int reg, int data)
{
unsigned char wmdata[2];
wmdata[0] = (reg << 1) | ((data & 0x100)>>8);
wmdata[1] = data & 0xff;
i2c_write(I2C_IFACE,I2C_CODEC_ADDRESS,wmdata,2);
return;
}

View file

@ -0,0 +1,94 @@
#change for releases
ifndef APPVERSION
APPVERSION=`../../tools/version.sh ../../`
endif
# We use the UCL code available in the Rockbox tools/ directory
CFLAGS=-I../../tools/ucl/include -Wall -DVERSION=\"$(APPVERSION)\"
ifndef V
SILENT = @
endif
ifeq ($(findstring CYGWIN,$(shell uname)),CYGWIN)
OUTPUT=mkmpioboot.exe
CFLAGS+=-mno-cygwin
else
ifeq ($(findstring MINGW,$(shell uname)),MINGW)
OUTPUT=mkmpioboot.exe
else
ifeq ($(findstring mingw,$(CC)),mingw)
OUTPUT=mkmpioboot.exe
else
OUTPUT=mkmpioboot
endif
endif
endif
ifdef RBARCH
CFLAGS += -arch $(RBARCH)
OBJDIR = $(RBARCH)/
endif
all: $(OUTPUT)
# inputs
LIBSOURCES := mkmpioboot.c
SOURCES := $(LIBSOURCES) main.c
OBJS := $(patsubst %.c,%.o,$(addprefix $(OBJDIR),$(SOURCES)))
LIBOBJS := $(patsubst %.c,%.o,$(addprefix $(OBJDIR),$(LIBSOURCES)))
EXTRADEPS := $(LIBUCL)
# explicit dependencies
$(OBJDIR)mkmpioboot.o: mkmpioboot.c mkmpioboot.h
$(OBJDIR)main.o: main.c
$(OBJDIR)%.o: %.c
@echo CC $< $
$(SILENT)mkdir -p $(dir $@)
$(SILENT)$(CC) $(CFLAGS) -c -o $@ $<
libmkamsboot$(RBARCH).a: $(LIBOBJS)
@echo AR $@
$(SILENT)$(AR) ruc $(TARGET_DIR)$@ $^
# building the standalone executable
$(OUTPUT): $(OBJS) $(EXTRADEPS)
@echo LD $@
$(SILENT)$(CC) $(CFLAGS) -o $(OUTPUT) $(OBJS) $(EXTRADEPS)
# some trickery to build ppc and i386 from a single call
ifeq ($(RBARCH),)
$(TARGET_DIR)libmkmpiobooti386.a:
make RBARCH=i386 TARGET_DIR=$(TARGET_DIR) libmkmpiobooti386.a
$(TARGET_DIR)libmkmpiobootppc.a:
make RBARCH=ppc TARGET_DIR=$(TARGET_DIR) libmkmpiobootppc.a
endif
libmkmpioboot-universal: $(TARGET_DIR)libmkmpiobooti386.a $(TARGET_DIR)libmkmpiobootppc.a
@echo lipo $(TARGET_DIR)libmkmpioboot.a
$(SILENT) rm -f $(TARGET_DIR)libmkmpioboot.a
$(SILENT)lipo -create $(TARGET_DIR)libmkmpiobootppc.a $(TARGET_DIR)libmkmpiobooti386.a -output $(TARGET_DIR)libmkmpioboot.a
clean:
rm -f $(OBJS) $(OUTPUT) libmkmpioboot.o $(TARGET_DIR)libmkmpioboot*.a mkmpioboot.dmg
rm -rf mkmpioboot-* i386 ppc $(OBJDIR)
mkmpioboot-i386:
$(MAKE) RBARCH=i386
mv mkmpioboot mkmpioboot-i386
mkmpioboot-ppc:
$(MAKE) RBARCH=ppc
mv mkmpioboot mkmpioboot-ppc
mkmpioboot-mac: mkmpioboot-i386 mkmpioboot-ppc
$(SILENT)lipo -create mkmpioboot-ppc mkmpioboot-i386 -output mkmpioboot-mac
mkmpioboot.dmg: mkmpioboot-mac
mkdir -p mkmpioboot-dmg
cp -p mkmpioboot-mac mkmpioboot-dmg
hdiutil create -srcfolder mkmpioboot-dmg mkmpioboot.dmg

49
rbutil/mkmpioboot/main.c Normal file
View file

@ -0,0 +1,49 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id:$
*
* Copyright (C) 2010 by Marcin Bukat
*
* code taken mostly from mkboot.c
* Copyright (C) 2005 by Linus Nielsen Feltzing
*
* 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 <stdio.h>
#include <stdlib.h>
#include "mkmpioboot.h"
static void usage(void)
{
printf("usage: mkmpioboot <firmware file> <boot file> <output file>\n");
exit(1);
}
int main(int argc, char *argv[])
{
char *infile, *bootfile, *outfile;
int origin = 0xe0000; /* MPIO HD200 bootloader address */
if(argc < 3) {
usage();
}
infile = argv[1];
bootfile = argv[2];
outfile = argv[3];
return mkmpioboot(infile, bootfile, outfile, origin);
}

View file

@ -0,0 +1,188 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id:$
*
* Copyright (C) 2010 by Marcin Bukat
*
* code taken mostly from mkboot.c
* Copyright (C) 2005 by Linus Nielsen Feltzing
*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mkmpioboot.h"
#define OF_FIRMWARE_LEN 0x100000 /* size of HD200_UPG.SYS file */
#define MPIO_STRING_OFFSET 0xfffe0
/* We support only 1.30.05 version of OF for now */
static char *mpio_string = "HD200 HDD Audio Ver113005";
/* MPIO HD200 firmware is plain binary image
* 4 bytes of initial SP (loaded on reset)
* 4 bytes of initial PC (loaded on reset)
* binary image with entry point 0x00000008
*
* We put our bootloader code at 0x000e0000
* and patch reset vector to jump directly
* into our code on reset
*/
static unsigned char image[OF_FIRMWARE_LEN];
static unsigned int get_uint32be(unsigned char* p)
{
return ((p[0] << 24) | (p[1] << 16) | (p[2]<<8) | p[3]);
}
static long checksum(unsigned char* buf, unsigned long length)
{
unsigned long chksum = 69; /* MPIO HD200 model number */
unsigned long i;
if(buf == NULL)
return -1;
for (i = 0; i < length; i++)
{
chksum += *buf++;
}
return chksum;
}
int mkmpioboot(const char* infile, const char* bootfile, const char* outfile, int origin)
{
FILE *f;
int i;
int len;
unsigned long file_checksum;
unsigned char header_checksum[4];
memset(image, 0xff, sizeof(image));
/* First, read the mpio original firmware into the image */
f = fopen(infile, "rb");
if(!f) {
perror(infile);
return -1;
}
i = fread(image, 1, OF_FIRMWARE_LEN, f);
if(i < OF_FIRMWARE_LEN) {
perror(infile);
fclose(f);
return -2;
}
fclose(f);
/* Now check if we have OF file loaded based on presence
* of the version string in firmware
*/
if (strcmp((char*)(image + MPIO_STRING_OFFSET),mpio_string) != 0)
{
perror("Loaded firmware file does not look like MPIO OF file!");
return -3;
}
/* Now, read the boot loader into the image */
f = fopen(bootfile, "rb");
if(!f) {
perror(bootfile);
fclose(f);
return -4;
}
/* get bootloader size
* excluding header
*/
fseek(f, 0, SEEK_END);
len = ftell(f) - 8;
/* Now check if the place we want to put
* our bootloader is free
*/
for(i=0;i<len;i++)
{
if (image[origin+i] != 0)
{
perror("Place for bootloader in OF file not empty");
return -5;
}
}
fseek(f, 0, SEEK_SET);
/* get bootloader checksum from the header*/
fread(header_checksum,1,4,f);
/* omit header */
fseek(f, 8, SEEK_SET);
i = fread(image + origin, 1, len, f);
if(i < len) {
perror(bootfile);
fclose(f);
return -6;
}
fclose(f);
/* calculate checksum and compare with data
* from header
*/
file_checksum = checksum(image + origin, len);
if ( file_checksum != get_uint32be(header_checksum) )
{
printf("Bootloader checksum error\n");
return -7;
}
f = fopen(outfile, "wb");
if(!f) {
perror(outfile);
return -8;
}
/* Patch the stack pointer address */
image[0] = image[origin + 0];
image[1] = image[origin + 1];
image[2] = image[origin + 2];
image[3] = image[origin + 3];
/* Patch the reset vector to start the boot loader */
image[4] = image[origin + 4];
image[5] = image[origin + 5];
image[6] = image[origin + 6];
image[7] = image[origin + 7];
i = fwrite(image, 1, OF_FIRMWARE_LEN, f);
if(i < OF_FIRMWARE_LEN) {
perror(outfile);
fclose(f);
return -9;
}
printf("Wrote 0x%x bytes in %s\n", OF_FIRMWARE_LEN, outfile);
fclose(f);
return 0;
}

View file

@ -0,0 +1,37 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id:$
*
* Copyright (C) 2010 by Marcin Bukat
* code based mainly on mkboot.h
* Copyright (C) 2008 by Dominik Riebeling
*
* 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 MKMPIOBOOT_H
#define MKMPIOBOOT_H
#ifdef __cplusplus
extern "C" {
#endif
int mkmpioboot(const char* infile, const char* bootfile, const char* outfile, int origin);
#ifdef __cplusplus
}
#endif
#endif