From 0b22795e26ee09de14f6ac23219adeda12f2fd5b Mon Sep 17 00:00:00 2001 From: Jonathan Gordon Date: Mon, 6 Nov 2006 14:24:18 +0000 Subject: [PATCH] adds ata_idle_notify system which allows callbacks in apps/ to be called when the hard disk is idle but spinning, and just before shutting down. on SWCODEC targets with > 8MB RAM the playback engine will try to refill the buffer if it is less than 75% full while the disk is spinning (temporarily disabled on the nano) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11451 a1c6a512-1295-4272-9138-f99709370657 --- apps/main.c | 2 + apps/playback.c | 48 +++++++++++++--- firmware/SOURCES | 1 + firmware/ata_idle_notify.c | 96 +++++++++++++++++++++++++++++++ firmware/drivers/ata.c | 15 ++++- firmware/export/ata_idle_notify.h | 41 +++++++++++++ 6 files changed, 192 insertions(+), 11 deletions(-) create mode 100644 firmware/ata_idle_notify.c create mode 100644 firmware/export/ata_idle_notify.h diff --git a/apps/main.c b/apps/main.c index 4249fd0b8b..c4ee45cb89 100644 --- a/apps/main.c +++ b/apps/main.c @@ -19,6 +19,7 @@ #include "config.h" #include "ata.h" +#include "ata_idle_notify.h" #include "disk.h" #include "fat.h" #include "lcd.h" @@ -364,6 +365,7 @@ void init(void) } #endif + ata_idle_notify_init(); rc = ata_init(); if(rc) { diff --git a/apps/playback.c b/apps/playback.c index 6d277f7153..f8372665a4 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -74,6 +74,7 @@ #include "metadata.h" #include "splash.h" #include "talk.h" +#include "ata_idle_notify.h" #ifdef HAVE_RECORDING #include "recording.h" @@ -118,6 +119,9 @@ enum { Q_AUDIO_NEW_PLAYLIST, Q_AUDIO_POSTINIT, Q_AUDIO_FILL_BUFFER, +#if MEM > 8 + Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA, +#endif Q_CODEC_REQUEST_PENDING, Q_CODEC_REQUEST_COMPLETE, @@ -2664,11 +2668,6 @@ static void audio_fill_file_buffer( audio_generate_postbuffer_events(); filling = false; - -#ifndef SIMULATOR - if (playing) - ata_sleep(); -#endif } } @@ -3228,14 +3227,30 @@ static void audio_playback_init(void) sound_settings_apply(); } +#if MEM > 8 +/* we dont want this rebuffering on targets with little ram + because the disk may never spin down */ +bool ata_fillbuffer_callback(void) +{ +#ifndef IPOD_NANO + queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA, 0); +#endif + return true; +} +#endif static void audio_thread(void) { struct event ev; - +#if MEM > 8 + size_t high_watermark; +#endif /* At first initialize audio system in background. */ audio_playback_init(); - +#if MEM > 8 + high_watermark = (3*filebuflen)/4; +#endif + while (1) { if (filling) @@ -3244,10 +3259,27 @@ static void audio_thread(void) if (ev.id == SYS_TIMEOUT) ev.id = Q_AUDIO_FILL_BUFFER; } +#if MEM > 8 else + { queue_wait_w_tmo(&audio_queue, &ev, HZ/2); - + if ( (ev.id == SYS_TIMEOUT) && + (FILEBUFUSED < high_watermark)) + register_ata_idle_func(ata_fillbuffer_callback); + } +#else + queue_wait_w_tmo(&audio_queue, &ev, HZ/2); +#endif switch (ev.id) { +#if MEM > 8 + case Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA: + /* only fill if the disk is still spining */ +#ifndef SIMULATOR + if (!ata_disk_is_active()) + break; +#endif +#endif /* MEM > 8 */ + /* else fall through to Q_AUDIO_FILL_BUFFER */ case Q_AUDIO_FILL_BUFFER: LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER"); if (!filling) diff --git a/firmware/SOURCES b/firmware/SOURCES index e9ce8f909b..1ec3c82616 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -95,6 +95,7 @@ drivers/lcd-h300.c drivers/power.c #endif drivers/led.c +ata_idle_notify.c #ifndef SIMULATOR #ifndef TARGET_TREE drivers/adc.c diff --git a/firmware/ata_idle_notify.c b/firmware/ata_idle_notify.c new file mode 100644 index 0000000000..a0a56e958b --- /dev/null +++ b/firmware/ata_idle_notify.c @@ -0,0 +1,96 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2006 Jonathan Gordon + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include +#include "system.h" +#include "ata_idle_notify.h" +#include "logf.h" + +#if USING_ATA_CALLBACK +static ata_idle_notify ata_idle_notify_funcs[MAX_ATA_CALLBACKS]; +static int ata_callback_count = 0; +#endif + +bool register_ata_idle_func(ata_idle_notify function) +{ +#if USING_ATA_CALLBACK + int i; + for (i=0; i ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2006 Jonathan Gordon + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef __ATACALLBACK_H__ +#define __ATACALLBACK_H__ + +#include +#define USING_ATA_CALLBACK !defined(SIMULATOR) \ + && !defined(HAVE_FLASH_DISK) \ + && !defined(HAVE_MMC) + +#define MAX_ATA_CALLBACKS 5 +typedef bool (*ata_idle_notify)(void); + +extern bool register_ata_idle_func(ata_idle_notify function); +#if USING_ATA_CALLBACK +extern void ata_idle_notify_init(void); +extern void unregister_ata_idle_func(ata_idle_notify function); +extern bool call_ata_idle_notifys(void); +#else +#define unregister_ata_idle_func(f) +#define call_ata_idle_notifys() +#define ata_idle_notify_init() +#endif + +#endif /* __ATACALLBACK_H__ */