summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Gordon <rockbox@jdgordon.info>2006-11-06 14:24:18 +0000
committerJonathan Gordon <rockbox@jdgordon.info>2006-11-06 14:24:18 +0000
commit0b22795e26ee09de14f6ac23219adeda12f2fd5b (patch)
treec1ccbda32170de48111a4b75e1f723ba953096bf
parente543901777843a1734474aba7aa5d96cf61708ab (diff)
downloadrockbox-0b22795e26ee09de14f6ac23219adeda12f2fd5b.tar.gz
rockbox-0b22795e26ee09de14f6ac23219adeda12f2fd5b.zip
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
-rw-r--r--apps/main.c2
-rw-r--r--apps/playback.c48
-rw-r--r--firmware/SOURCES1
-rw-r--r--firmware/ata_idle_notify.c96
-rw-r--r--firmware/drivers/ata.c15
-rw-r--r--firmware/export/ata_idle_notify.h41
6 files changed, 192 insertions, 11 deletions
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 @@
19#include "config.h" 19#include "config.h"
20 20
21#include "ata.h" 21#include "ata.h"
22#include "ata_idle_notify.h"
22#include "disk.h" 23#include "disk.h"
23#include "fat.h" 24#include "fat.h"
24#include "lcd.h" 25#include "lcd.h"
@@ -364,6 +365,7 @@ void init(void)
364 } 365 }
365#endif 366#endif
366 367
368 ata_idle_notify_init();
367 rc = ata_init(); 369 rc = ata_init();
368 if(rc) 370 if(rc)
369 { 371 {
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 @@
74#include "metadata.h" 74#include "metadata.h"
75#include "splash.h" 75#include "splash.h"
76#include "talk.h" 76#include "talk.h"
77#include "ata_idle_notify.h"
77 78
78#ifdef HAVE_RECORDING 79#ifdef HAVE_RECORDING
79#include "recording.h" 80#include "recording.h"
@@ -118,6 +119,9 @@ enum {
118 Q_AUDIO_NEW_PLAYLIST, 119 Q_AUDIO_NEW_PLAYLIST,
119 Q_AUDIO_POSTINIT, 120 Q_AUDIO_POSTINIT,
120 Q_AUDIO_FILL_BUFFER, 121 Q_AUDIO_FILL_BUFFER,
122#if MEM > 8
123 Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA,
124#endif
121 125
122 Q_CODEC_REQUEST_PENDING, 126 Q_CODEC_REQUEST_PENDING,
123 Q_CODEC_REQUEST_COMPLETE, 127 Q_CODEC_REQUEST_COMPLETE,
@@ -2664,11 +2668,6 @@ static void audio_fill_file_buffer(
2664 2668
2665 audio_generate_postbuffer_events(); 2669 audio_generate_postbuffer_events();
2666 filling = false; 2670 filling = false;
2667
2668#ifndef SIMULATOR
2669 if (playing)
2670 ata_sleep();
2671#endif
2672 } 2671 }
2673 2672
2674} 2673}
@@ -3228,14 +3227,30 @@ static void audio_playback_init(void)
3228 3227
3229 sound_settings_apply(); 3228 sound_settings_apply();
3230} 3229}
3230#if MEM > 8
3231/* we dont want this rebuffering on targets with little ram
3232 because the disk may never spin down */
3233bool ata_fillbuffer_callback(void)
3234{
3235#ifndef IPOD_NANO
3236 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA, 0);
3237#endif
3238 return true;
3239}
3240#endif
3231 3241
3232static void audio_thread(void) 3242static void audio_thread(void)
3233{ 3243{
3234 struct event ev; 3244 struct event ev;
3235 3245#if MEM > 8
3246 size_t high_watermark;
3247#endif
3236 /* At first initialize audio system in background. */ 3248 /* At first initialize audio system in background. */
3237 audio_playback_init(); 3249 audio_playback_init();
3238 3250#if MEM > 8
3251 high_watermark = (3*filebuflen)/4;
3252#endif
3253
3239 while (1) 3254 while (1)
3240 { 3255 {
3241 if (filling) 3256 if (filling)
@@ -3244,10 +3259,27 @@ static void audio_thread(void)
3244 if (ev.id == SYS_TIMEOUT) 3259 if (ev.id == SYS_TIMEOUT)
3245 ev.id = Q_AUDIO_FILL_BUFFER; 3260 ev.id = Q_AUDIO_FILL_BUFFER;
3246 } 3261 }
3262#if MEM > 8
3247 else 3263 else
3264 {
3248 queue_wait_w_tmo(&audio_queue, &ev, HZ/2); 3265 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
3249 3266 if ( (ev.id == SYS_TIMEOUT) &&
3267 (FILEBUFUSED < high_watermark))
3268 register_ata_idle_func(ata_fillbuffer_callback);
3269 }
3270#else
3271 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
3272#endif
3250 switch (ev.id) { 3273 switch (ev.id) {
3274#if MEM > 8
3275 case Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA:
3276 /* only fill if the disk is still spining */
3277#ifndef SIMULATOR
3278 if (!ata_disk_is_active())
3279 break;
3280#endif
3281#endif /* MEM > 8 */
3282 /* else fall through to Q_AUDIO_FILL_BUFFER */
3251 case Q_AUDIO_FILL_BUFFER: 3283 case Q_AUDIO_FILL_BUFFER:
3252 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER"); 3284 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3253 if (!filling) 3285 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
95drivers/power.c 95drivers/power.c
96#endif 96#endif
97drivers/led.c 97drivers/led.c
98ata_idle_notify.c
98#ifndef SIMULATOR 99#ifndef SIMULATOR
99#ifndef TARGET_TREE 100#ifndef TARGET_TREE
100drivers/adc.c 101drivers/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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 Jonathan Gordon
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include <stdbool.h>
20#include "system.h"
21#include "ata_idle_notify.h"
22#include "logf.h"
23
24#if USING_ATA_CALLBACK
25static ata_idle_notify ata_idle_notify_funcs[MAX_ATA_CALLBACKS];
26static int ata_callback_count = 0;
27#endif
28
29bool register_ata_idle_func(ata_idle_notify function)
30{
31#if USING_ATA_CALLBACK
32 int i;
33 for (i=0; i<MAX_ATA_CALLBACKS; i++)
34 {
35 if (ata_idle_notify_funcs[i] == NULL)
36 {
37 ata_idle_notify_funcs[i] = function;
38 ata_callback_count++;
39 return true;
40 }
41 else if (ata_idle_notify_funcs[i] == function)
42 return true;
43 }
44 return false;
45#else
46 function(); /* just call the function now */
47/* this _may_ cause problems later if the calling function
48 sets a variable expecting the callback to unset it, because
49 the callback will be run before this function exits, so before the var is set */
50 return true;
51#endif
52}
53
54#if USING_ATA_CALLBACK
55void unregister_ata_idle_func(ata_idle_notify func)
56{
57 int i;
58 for (i=0; i<MAX_ATA_CALLBACKS; i++)
59 {
60 if (ata_idle_notify_funcs[i] == func)
61 {
62 ata_idle_notify_funcs[i] = NULL;
63 ata_callback_count--;
64 }
65 }
66 return;
67}
68
69bool call_ata_idle_notifys(void)
70{
71 int i;
72 ata_idle_notify function;
73 if (ata_callback_count == 0)
74 return false;
75 ata_callback_count = 0; /* so we dont re-enter every time the callbacks read/write */
76 for (i = 0; i < MAX_ATA_CALLBACKS; i++)
77 {
78 if (ata_idle_notify_funcs[i])
79 {
80 function = ata_idle_notify_funcs[i];
81 ata_idle_notify_funcs[i] = NULL;
82 function();
83 }
84 }
85 return true;
86}
87
88void ata_idle_notify_init(void)
89{
90 int i;
91 for (i=0; i<MAX_ATA_CALLBACKS; i++)
92 {
93 ata_idle_notify_funcs[i] = NULL;
94 }
95}
96#endif
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c
index 00ef0e8eb5..249cb3934e 100644
--- a/firmware/drivers/ata.c
+++ b/firmware/drivers/ata.c
@@ -29,7 +29,7 @@
29#include "power.h" 29#include "power.h"
30#include "string.h" 30#include "string.h"
31#include "hwcompat.h" 31#include "hwcompat.h"
32 32#include "ata_idle_notify.h"
33#ifdef TARGET_TREE 33#ifdef TARGET_TREE
34#include "ata-target.h" 34#include "ata-target.h"
35#endif 35#endif
@@ -1364,6 +1364,7 @@ static void ata_thread(void)
1364{ 1364{
1365 static long last_sleep = 0; 1365 static long last_sleep = 0;
1366 struct event ev; 1366 struct event ev;
1367 static long last_callback_run = 0;
1367 1368
1368 while (1) { 1369 while (1) {
1369 while ( queue_empty( &ata_queue ) ) { 1370 while ( queue_empty( &ata_queue ) ) {
@@ -1373,8 +1374,16 @@ static void ata_thread(void)
1373 TIME_AFTER( current_tick, 1374 TIME_AFTER( current_tick,
1374 last_disk_activity + sleep_timeout ) ) 1375 last_disk_activity + sleep_timeout ) )
1375 { 1376 {
1376 ata_perform_sleep(); 1377 if (!call_ata_idle_notifys())
1377 last_sleep = current_tick; 1378 {
1379 ata_perform_sleep();
1380 last_sleep = current_tick;
1381 }
1382 }
1383 else if (TIME_AFTER(current_tick, last_callback_run+(HZ*5)))
1384 {
1385 last_callback_run = current_tick;
1386 call_ata_idle_notifys();
1378 } 1387 }
1379 1388
1380#ifdef HAVE_ATA_POWER_OFF 1389#ifdef HAVE_ATA_POWER_OFF
diff --git a/firmware/export/ata_idle_notify.h b/firmware/export/ata_idle_notify.h
new file mode 100644
index 0000000000..f5f2a25fd9
--- /dev/null
+++ b/firmware/export/ata_idle_notify.h
@@ -0,0 +1,41 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 Jonathan Gordon
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#ifndef __ATACALLBACK_H__
20#define __ATACALLBACK_H__
21
22#include <stdbool.h>
23#define USING_ATA_CALLBACK !defined(SIMULATOR) \
24 && !defined(HAVE_FLASH_DISK) \
25 && !defined(HAVE_MMC)
26
27#define MAX_ATA_CALLBACKS 5
28typedef bool (*ata_idle_notify)(void);
29
30extern bool register_ata_idle_func(ata_idle_notify function);
31#if USING_ATA_CALLBACK
32extern void ata_idle_notify_init(void);
33extern void unregister_ata_idle_func(ata_idle_notify function);
34extern bool call_ata_idle_notifys(void);
35#else
36#define unregister_ata_idle_func(f)
37#define call_ata_idle_notifys()
38#define ata_idle_notify_init()
39#endif
40
41#endif /* __ATACALLBACK_H__ */