Index: apps/main.c
===================================================================
RCS file: /cvsroot/rockbox/apps/main.c,v
retrieving revision 1.168
diff -u -r1.168 main.c
--- apps/main.c	12 Apr 2006 10:31:24 -0000	1.168
+++ apps/main.c	12 Apr 2006 23:01:21 -0000
@@ -88,6 +88,10 @@
 #include "lcd-remote.h"
 #endif
 
+#ifdef HAVE_PIEZO
+#include "piezo.h"
+#endif
+
 /*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */
 
 const char appsversion[]=APPSVERSION;
@@ -443,6 +447,10 @@
 #ifdef HAVE_CHARGING
     car_adapter_mode_init();
 #endif
+
+#ifdef HAVE_PIEZO
+    piezo_init();
+#endif
 }
 
 int main(void)
Index: firmware/SOURCES
===================================================================
RCS file: /cvsroot/rockbox/firmware/SOURCES,v
retrieving revision 1.84
diff -u -r1.84 SOURCES
--- firmware/SOURCES	30 Mar 2006 20:18:02 -0000	1.84
+++ firmware/SOURCES	12 Apr 2006 23:01:32 -0000
@@ -202,6 +202,9 @@
 common/sscanf.c
 usb_serial.c
 #endif
+#ifdef HAVE_PIEZO
+drivers/piezo.c
+#endif
 
 #ifndef SIMULATOR
 #ifdef IAUDIO_X5
Index: firmware/drivers/button.c
===================================================================
RCS file: /cvsroot/rockbox/firmware/drivers/button.c,v
retrieving revision 1.138
diff -u -r1.138 button.c
--- firmware/drivers/button.c	6 Apr 2006 18:58:42 -0000	1.138
+++ firmware/drivers/button.c	12 Apr 2006 23:01:33 -0000
@@ -44,6 +44,10 @@
 #include "lcd-remote.h"
 #endif
 
+#ifdef HAVE_PIEZO
+#include "piezo.h"
+#endif
+
 struct event_queue button_queue;
 
 static long lastbtn;   /* Last valid button status */
@@ -200,11 +204,16 @@
         outl(0xffffffff, 0x7000c120);
         outl(0xffffffff, 0x7000c124);
     }
+
     return btn;
 }
 
 void ipod_4g_button_int(void)
 {
+#ifdef HAVE_PIEZO
+    piezo_play_for(50, HZ/15);
+#endif
+
     CPU_HI_INT_CLR = I2C_MASK;
     /* The following delay was 250 in the ipodlinux source, but 50 seems to 
        work fine - tested on Nano, Color/Photo and Video. */
Index: firmware/drivers/piezo.c
===================================================================
RCS file: firmware/drivers/piezo.c
diff -N firmware/drivers/piezo.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ firmware/drivers/piezo.c	12 Apr 2006 23:01:33 -0000
@@ -0,0 +1,126 @@
+#include "thread.h"
+#include "system.h"
+#include "kernel.h"
+#include "usb.h"
+#include "logf.h"
+#include "piezo.h"
+
+static long piezo_stack[DEFAULT_STACK_SIZE/sizeof(long)];
+static const char piezo_thread_name[] = "piezo";
+static struct event_queue piezo_queue;
+unsigned int duration;
+bool beeping;
+
+enum {
+    Q_PIEZO_BEEP = 1,
+    Q_PIEZO_BEEP_FOR,
+    Q_PIEZO_STOP
+};
+
+static inline void piezo_hw_init(void)
+{
+    logf("PIEZO: hw_init");
+    outl(inl(0x70000010) & ~0xc, 0x70000010);
+    outl(inl(0x6000600c) | 0x20000, 0x6000600c);    /* enable device */
+}
+
+static void piezo_hw_tick(int period)
+{    
+    outl(0x80000000 | 0x800000 | period, 0x7000a000); /* set pitch */
+}
+
+static inline void piezo_hw_stop(void)
+{
+    outl(0x0, 0x7000a000);    /* piezo off */
+}
+
+/*
+void piezo_start_for(void)
+{
+    piezo_hw_tick(frequency);
+    sleep(duration);
+    piezo_hw_stop();
+}
+*/
+
+void piezo_thread(void)
+{
+    struct event ev;
+
+    while(1)
+    {
+        queue_wait(&piezo_queue, &ev);
+        switch(ev.id)
+        {
+            case Q_PIEZO_BEEP:
+                piezo_hw_tick((int)ev.data);
+                beeping = true;
+                logf("PIEZO: beep");
+                break;
+            case Q_PIEZO_BEEP_FOR:
+                logf("PIEZO: beep_for start");
+                piezo_hw_tick((int)ev.data);
+                beeping = true;
+                sleep(duration);
+                if (beeping)
+                    piezo_hw_stop();
+                beeping = false;
+                logf("PIEZO: beep_for end");
+                /* remove anything that appeared while sleeping */
+                queue_clear(&piezo_queue);
+                break;
+            case Q_PIEZO_STOP:
+                if (beeping)
+                    piezo_hw_stop();
+                beeping = false;
+                logf("PIEZO: beep stop");
+                break;
+#ifndef SIMULATOR
+            case SYS_USB_CONNECTED:
+                logf("USB: Piezo core");
+                piezo_hw_stop();
+                usb_acknowledge(SYS_USB_CONNECTED_ACK);
+                usb_wait_for_disconnect(&piezo_queue);
+                break ;
+#endif
+            case SYS_TIMEOUT:
+                break;
+        }
+        yield();
+    }
+}
+
+void piezo_play(int inv_freq)
+{
+    queue_post(&piezo_queue, Q_PIEZO_BEEP, (int *)inv_freq);
+}
+
+void piezo_play_for(int inv_freq, int dur)
+{
+    duration = dur;
+    queue_post(&piezo_queue, Q_PIEZO_BEEP_FOR, (int *)inv_freq);
+}
+
+void piezo_stop(void)
+{
+    queue_post(&piezo_queue, Q_PIEZO_STOP, NULL);
+}
+
+void piezo_clear(void)
+{
+    queue_clear(&piezo_queue);
+    piezo_stop();
+}
+
+bool piezo_busy(void)
+{
+    return !queue_empty(&piezo_queue);
+}
+
+void piezo_init(void)
+{
+    logf("PIEZO: init");
+    piezo_hw_init();
+    queue_init(&piezo_queue);
+    create_thread(piezo_thread, piezo_stack, sizeof(piezo_stack), piezo_thread_name);
+}
Index: firmware/export/piezo.h
===================================================================
RCS file: firmware/export/piezo.h
diff -N firmware/export/piezo.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ firmware/export/piezo.h	12 Apr 2006 23:01:34 -0000
@@ -0,0 +1,7 @@
+
+void piezo_init(void);
+void piezo_play(int inv_freq);
+void piezo_play_for(int inv_freq, int dur);
+void piezo_stop(void);
+void piezo_clear(void);
+bool piezo_busy(void);
