Index: firmware/export/config/sansafuze.h
===================================================================
--- firmware/export/config/sansafuze.h	(revision 24186)
+++ firmware/export/config/sansafuze.h	(working copy)
@@ -204,3 +204,4 @@

 #define INCLUDE_TIMEOUT_API

+#define DBOP_PRECHARGE 0x80FF
Index: firmware/export/config/sansac200v2.h
===================================================================
--- firmware/export/config/sansac200v2.h	(revision 24186)
+++ firmware/export/config/sansac200v2.h	(working copy)
@@ -197,3 +197,5 @@
 #define DEFAULT_REC_MIC_GAIN    23
 #define DEFAULT_REC_LEFT_GAIN   23
 #define DEFAULT_REC_RIGHT_GAIN  23
+
+#define DBOP_PRECHARGE 0xF0FF
Index: firmware/export/config/sansae200v2.h
===================================================================
--- firmware/export/config/sansae200v2.h	(revision 24186)
+++ firmware/export/config/sansae200v2.h	(working copy)
@@ -210,3 +210,5 @@
 #define DEFAULT_REC_MIC_GAIN    23
 #define DEFAULT_REC_LEFT_GAIN   23
 #define DEFAULT_REC_RIGHT_GAIN  23
+
+#define DBOP_PRECHARGE 0xF0FF
Index: firmware/SOURCES
===================================================================
--- firmware/SOURCES	(revision 24186)
+++ firmware/SOURCES	(working copy)
@@ -1235,6 +1235,7 @@
 target/arm/as3525/lcd-as-e200v2-fuze.S
 target/arm/as3525/button-e200v2-fuze.c
 target/arm/as3525/backlight-e200v2-fuze.c
+target/arm/as3525/dbop-as3525.c
 #ifndef BOOTLOADER
 target/arm/powermgmt-ascodec.c
 target/arm/as3525/sansa-e200v2/powermgmt-e200v2.c
@@ -1247,6 +1248,7 @@
 target/arm/lcd-c200_c200v2.c
 target/arm/as3525/sansa-c200v2/button-c200v2.c
 target/arm/as3525/sansa-c200v2/backlight-c200v2.c
+target/arm/as3525/dbop-as3525.c
 #ifndef BOOTLOADER
 target/arm/as3525/powermgmt-as3525.c
 #endif /* !BOOTLOADER */
@@ -1269,6 +1271,7 @@
 target/arm/as3525/sansa-fuze/lcd-fuze.c
 target/arm/as3525/lcd-as-e200v2-fuze.S
 target/arm/as3525/backlight-e200v2-fuze.c
+target/arm/as3525/dbop-as3525.c
 #ifndef BOOTLOADER
 target/arm/powermgmt-ascodec.c
 target/arm/as3525/sansa-fuze/powermgmt-fuze.c
Index: firmware/target/arm/lcd-c200_c200v2.c
===================================================================
--- firmware/target/arm/lcd-c200_c200v2.c	(revision 24186)
+++ firmware/target/arm/lcd-c200_c200v2.c	(working copy)
@@ -25,11 +25,8 @@
 #include "lcd.h"
 #include "kernel.h"
 #include "system.h"
-
 #ifdef SANSA_C200V2
-/* button driver needs to know if a lcd operation is in progress */
-static bool lcd_busy = false;
-static unsigned short dbop_input = 0xFFFF;
+#include "dbop-as3525.h"
 #endif

 /* Display status */
@@ -183,45 +180,6 @@
     lcd_delay(20);
 }

-static unsigned short lcd_dbop_read(void)
-{
-    unsigned int dbop_ctrl_old = DBOP_CTRL;
-    unsigned int dbop_timpol23_old = DBOP_TIMPOL_23;
-    unsigned int value;
-    
-    /* make sure that the DBOP FIFO is empty */
-    while ((DBOP_STAT & (1<<10)) == 0);
-
-    /* write DBOP_DOUT to pre-charge DBOP data lines with a high level */
-    DBOP_TIMPOL_23 = 0xe167e167;    /* no strobe towards lcd */
-    DBOP_CTRL = (1 << 16) |         /* enw=1 (enable write) */
-                (1 << 12);          /* ow=1 (16-bit data width) */
-    DBOP_DOUT = 0xFFFF;             /* all pins high */
-    while ((DBOP_STAT & (1<<10)) == 0);
-
-    /* perform a DBOP read */
-    DBOP_CTRL = (1 << 15) |         /* strd=1 (start read) */
-                (1 << 12) |         /* ow=1 (16-bit data width) */
-                (31 << 0);          /* rs_t=31 (read DBOP at end of cycle) */
-    while ((DBOP_STAT & (1<<16)) == 0);
-    value = DBOP_DIN;
-    
-    /* restore previous values */
-    DBOP_TIMPOL_23 = dbop_timpol23_old;
-    DBOP_CTRL = dbop_ctrl_old;
-    
-    return value;
-}
-
-/* get the DBOP input value, either directly or cached if DBOP is busy */
-unsigned short int lcd_dbop_input(void)
-{
-    if (!lcd_busy) {
-        dbop_input = lcd_dbop_read();
-    }
-    return dbop_input;
-}
-
 #endif

 /* LCD init */
@@ -292,13 +250,7 @@

 void lcd_set_contrast(int val)
 {
-#ifdef SANSA_C200V2
-    lcd_busy = true;
-#endif
     lcd_send_command(R_CONTRAST_CONTROL1, val);
-#ifdef SANSA_C200V2
-    lcd_busy = false;
-#endif
 }

 void lcd_set_invert_display(bool yesno)
@@ -313,9 +265,6 @@
     if (yesno == is_lcd_enabled)
         return;

-#ifdef SANSA_C200V2
-    lcd_busy = true;
-#endif
     if ((is_lcd_enabled = yesno))
     {
         lcd_send_command(R_STANDBY_OFF, 0);
@@ -326,9 +275,6 @@
     {
         lcd_send_command(R_STANDBY_ON, 0);
     }
-#ifdef SANSA_C200V2
-    lcd_busy = false;
-#endif
 }
 #endif

@@ -343,18 +289,12 @@
 /* turn the display upside down (call lcd_update() afterwards) */
 void lcd_set_flip(bool yesno)
 {
-#ifdef SANSA_C200V2
-    lcd_busy = true;
-#endif
     lcd_send_command(R_DRIVER_OUTPUT_MODE, yesno ? 0x02 : 0x07);
-#ifdef SANSA_C200V2
-    lcd_busy = false;
-#endif
 }

 /*** update functions ***/

-#if MEMORYSIZE > 2
+#if MEMORYSIZE > 2  /* not for C200V2 */
 void lcd_yuv_set_options(unsigned options)
 {
     lcd_yuv_options = options;
@@ -450,12 +390,6 @@

     addr = &lcd_framebuffer[y][x];

-#ifdef SANSA_C200V2
-    lcd_busy = true;
-    /* perform a dbop read before doing a potentially lengthy lcd update */
-    dbop_input = lcd_dbop_read();
-#endif
-
     if (width <= 1) {
         /* The X end address must be larger than the X start address, so we
          * switch to vertical mode for single column updates and set the
@@ -476,8 +410,4 @@
         lcd_write_data(addr, width);
         addr += LCD_WIDTH;
     } while (--height > 0);
-
-#ifdef SANSA_C200V2
-    lcd_busy = false;
-#endif
 }
Index: firmware/target/arm/as3525/sansa-c200v2/button-c200v2.c
===================================================================
--- firmware/target/arm/as3525/sansa-c200v2/button-c200v2.c	(revision 24186)
+++ firmware/target/arm/as3525/sansa-c200v2/button-c200v2.c	(working copy)
@@ -5,9 +5,9 @@
  *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
  *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
  *                     \/            \/     \/    \/            \/
- * $Id: button-e200v2.c 19035 2008-11-07 05:31:05Z jdgordon $
+ * $Id: button-c200v2.c 19035 2008-11-07 05:31:05Z jdgordon $
  *
- * Copyright (C) 2006 by Barry Wardell
+ * Copyright (C) 2006 by Barry Wardell, (C) 2009 by Bertrik Sikken
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -19,29 +19,20 @@
  *
  ****************************************************************************/

+#include "config.h"
 #include "system.h"
 #include "button-target.h"
 #include "button.h"
 #include "backlight.h"
-#include "powermgmt.h"
+#include "dbop-as3525.h"

+static unsigned short _dbop_din;

-static unsigned short _dbop_din    = 0xFFFF;
-
-/* in the lcd driver */
-extern unsigned short int lcd_dbop_input(void);
-
 static bool hold_button     = false;
 #ifndef BOOTLOADER
 static bool hold_button_old = false;
 #endif

-/* for the debug menu */
-unsigned short button_dbop_data(void)
-{
-    return _dbop_din;
-}
-
 void button_init_device(void)
 {
     GPIOA_DIR &= ~(1<<3);
@@ -59,7 +50,7 @@
 {
     int btn = BUTTON_NONE;

-    _dbop_din = lcd_dbop_input();
+    _dbop_din = dbop_read_input();

     /* hold button handling */
     hold_button = ((_dbop_din & (1<<12)) == 0);
Index: firmware/target/arm/as3525/sansa-e200v2/lcd-e200v2.c
===================================================================
--- firmware/target/arm/as3525/sansa-e200v2/lcd-e200v2.c	(revision 24186)
+++ firmware/target/arm/as3525/sansa-e200v2/lcd-e200v2.c	(working copy)
@@ -26,6 +26,7 @@
 #include "debug.h"
 #include "system.h"
 #include "clock-target.h"
+#include "dbop-as3525.h"

 /* The controller is unknown, but some registers appear to be the same as the
    HD66789R */
@@ -89,8 +90,6 @@
 #define R_DISP_CONTROL_REV    0x0000
 static unsigned short r_disp_control_rev = R_DISP_CONTROL_NORMAL;

-static volatile bool lcd_busy = false;
-
 static inline void lcd_delay(int x)
 {
     do {
@@ -435,8 +434,6 @@
     yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
     yuv_src[2] = src[2] + (yuv_src[1] - src[1]);

-    lcd_busy = true;
-
     lcd_write_reg(R_ENTRY_MODE,
         display_flipped ? R_ENTRY_MODE_VIDEO_FLIPPED : R_ENTRY_MODE_VIDEO_NORMAL
     );
@@ -473,8 +470,6 @@
         }
         while (--height > 0);
     }
-
-    lcd_busy = false;
 }

 /* Update the display.
@@ -484,8 +479,6 @@
     if (!display_on)
         return;

-    lcd_busy = true;
-
     lcd_write_reg(R_ENTRY_MODE, r_entry_mode);

     /* Set start position and window */
@@ -494,8 +487,6 @@
     lcd_write_cmd(R_WRITE_DATA_2_GRAM);

     lcd_write_data((fb_data*)lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT);
-
-    lcd_busy = false;
 }

 /* Update a fraction of the display. */
@@ -525,8 +516,6 @@
     if (y >= ymax)
         return; /* nothing left to do */

-    lcd_busy = true;
-
     lcd_write_reg(R_ENTRY_MODE, r_entry_mode);

     lcd_window(x, y, xmax, ymax);
@@ -541,25 +530,4 @@
         ptr += LCD_WIDTH;
     }
     while (--height >= 0);
-
-    lcd_busy = false;
 }
-
-/* writes one red pixel outside the visible area, needed for correct
- * dbop reads */
-bool lcd_button_support(void)
-{
-    if (lcd_busy)
-        return false;
-
-    lcd_write_reg(R_ENTRY_MODE, r_entry_mode);
-
-    /* Set start position and window */
-    lcd_window(LCD_WIDTH+1, LCD_HEIGHT+1, LCD_WIDTH+2, LCD_HEIGHT+2);
-
-    lcd_write_cmd(R_WRITE_DATA_2_GRAM);
-
-    lcd_write_value16(0xf<<12);
-
-    return true;
-}
Index: firmware/target/arm/as3525/dbop-as3525.c
===================================================================
--- firmware/target/arm/as3525/dbop-as3525.c	(revision 0)
+++ firmware/target/arm/as3525/dbop-as3525.c	(revision 0)
@@ -0,0 +1,71 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2009 by Bertrik Sikken
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+#include "as3525.h"
+#include "dbop-as3525.h"
+
+static short int dbop_input_value = 0;
+
+/* read the DBOP data pins */
+unsigned short dbop_read_input(void)
+{
+    unsigned int dbop_ctrl_old = DBOP_CTRL;
+    unsigned int dbop_timpol23_old = DBOP_TIMPOL_23;
+
+    /* make sure that the DBOP FIFO is empty */
+    while ((DBOP_STAT & (1<<10)) == 0);
+
+    /* write DBOP_DOUT to pre-charge DBOP data lines with a defined level */
+    DBOP_TIMPOL_23 = 0xe007e007;    /* no strobe towards lcd */
+    int delay = 10;
+    while (delay--) asm volatile ("nop\n");
+    DBOP_CTRL = (1 << 19) |         /* tri-state output */
+                (1 << 16) |         /* enw=1 (enable write) */
+                (1 << 12);          /* ow=1 (16-bit data width) */
+    DBOP_DOUT = DBOP_PRECHARGE;
+    while ((DBOP_STAT & (1<<10)) == 0);
+
+#if defined(SANSA_FUZE) || defined(SANSA_E200V2)
+    delay = 50;
+    while (delay--) asm volatile ("nop\n");
+#endif
+
+    /* perform a DBOP read */
+    DBOP_CTRL = (1 << 19) |         /* tri-state output */
+                (1 << 15) |         /* strd=1 (start read) */
+                (1 << 12) |         /* ow=1 (16-bit data width) */
+                (31 << 0);          /* rs_t=31 (read DBOP at end of cycle) */
+    while ((DBOP_STAT & (1<<16)) == 0);
+    dbop_input_value = DBOP_DIN;
+
+    /* restore previous values */
+    DBOP_TIMPOL_23 = dbop_timpol23_old;
+    DBOP_CTRL = dbop_ctrl_old;
+
+    return dbop_input_value;
+}
+
+/* for the debug menu */
+unsigned short dbop_debug(void)
+{
+    return dbop_input_value;
+}
Index: firmware/target/arm/as3525/debug-as3525.c
===================================================================
--- firmware/target/arm/as3525/debug-as3525.c	(revision 24186)
+++ firmware/target/arm/as3525/debug-as3525.c	(working copy)
@@ -68,7 +68,7 @@
  * if I put the below into a sansa-fuze/debug-target.h, it doesn't work*/
 #if defined(SANSA_FUZE) || defined(SANSA_E200V2) || defined(SANSA_C200V2)
 #define DEBUG_DBOP
-unsigned short button_dbop_data(void);
+#include "dbop-as3525.h"
 #endif

 static inline unsigned read_cp15 (void)
@@ -392,7 +392,7 @@
 #ifdef DEBUG_DBOP
         line++;
         lcd_puts(0, line++, "[DBOP_DIN]");
-        lcd_putsf(0, line++, "DBOP_DIN: %4x", button_dbop_data());
+        lcd_putsf(0, line++, "DBOP_DIN: %4x", dbop_debug());
 #endif
         line++;
         lcd_puts(0, line++, "[CP15]");
Index: firmware/target/arm/as3525/dbop-as3525.h
===================================================================
--- firmware/target/arm/as3525/dbop-as3525.h	(revision 0)
+++ firmware/target/arm/as3525/dbop-as3525.h	(revision 0)
@@ -0,0 +1,23 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2009 by Bertrik Sikken
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+unsigned short int  dbop_read_input(void);
+unsigned short      dbop_debug(void);
Index: firmware/target/arm/as3525/button-e200v2-fuze.c
===================================================================
--- firmware/target/arm/as3525/button-e200v2-fuze.c	(revision 24186)
+++ firmware/target/arm/as3525/button-e200v2-fuze.c	(working copy)
@@ -20,10 +20,12 @@
  *
  ****************************************************************************/

+#include "config.h"
 #include "system.h"
 #include "button.h"
 #include "button-target.h"
 #include "backlight.h"
+#include "dbop-as3525.h"


 #ifdef SANSA_FUZE
@@ -32,7 +34,6 @@
 #define WHEEL_COUNTER_DIV       4
 #define ACCEL_INCREMENT         2
 #define ACCEL_SHIFT             2
-#define BUTTON_DELAY            60
 #endif

 #ifdef SANSA_E200V2
@@ -41,12 +42,6 @@
 #define WHEEL_COUNTER_DIV       2
 #define ACCEL_INCREMENT         3
 #define ACCEL_SHIFT             1
-#define BUTTON_DELAY            20
-
-/* read_missed is true if buttons could not
- * be read (see lcd_button_support) */
-static bool read_missed              = false;
-
 #endif

 /* Buttons */
@@ -54,11 +49,7 @@
 #ifndef BOOTLOADER
 static bool hold_button_old = false;
 #endif
-static unsigned short _dbop_din    = BUTTON_NONE;

-/* in the lcd driver */
-extern bool lcd_button_support(void);
-
 void button_init_device(void)
 {
     GPIOA_DIR |= (1<<1);     
@@ -66,10 +57,9 @@
 }

 #if !defined(BOOTLOADER) && defined(HAVE_SCROLLWHEEL)
-static void scrollwheel(unsigned short dbop_din)
+static void scrollwheel(unsigned int wheel_value)
 {
     /* current wheel values, parsed from dbop and the resulting button */
-    unsigned         wheel_value     = 0;
     unsigned         btn             = BUTTON_NONE;
     /* old wheel values */
     static unsigned old_wheel_value = 0;
@@ -112,8 +102,6 @@
         return;
     }

-    wheel_value = (dbop_din >> 13) & (1<<1|1<<0);
-
     if (old_wheel_value == wheel_tbl[0][wheel_value])
         btn = BUTTON_SCROLL_FWD;
     else if (old_wheel_value == wheel_tbl[1][wheel_value])
@@ -158,11 +146,7 @@
             last_wheel_post = current_tick;
         }
     }
-    if (accel > 0
-#ifdef SANSA_E200V2
-         && !read_missed /* decrement only if reading buttons was successful */
-#endif         
-        )
+    if (accel > 0)
         accel--;

     old_wheel_value = wheel_value;
@@ -174,175 +158,73 @@
     return hold_button;
 }

-static void button_delay(void)
-{
-    int i = BUTTON_DELAY;
-    while(i--) asm volatile ("nop\n");
-}
-
 unsigned short button_read_dbop(void)
 {
-#ifdef SANSA_FUZE
-    /* skip home and power reading if lcd_button_support was blocked,
-     * since the dbop bit 15 is invalid then, and use the old value instead
-     * -20 (arbitary value) indicates valid home&power button read 
-     * (fuze only) */
-    int old_home_power = -20;
-#endif
-    if(!lcd_button_support())
-    {
-#if defined(SANSA_FUZE)
-        old_home_power = (_dbop_din & (1<<15|1<<8));
-#elif defined(SANSA_E200V2)
-        read_missed = true;
-#endif
-    }
-
-#ifdef SANSA_E200V2
-    if (!read_missed)   /* read buttons only if lcd_button_support was not blocked */
-#endif
-    {
-        /* Set up dbop for input */
-        DBOP_CTRL |= (1<<19);                /* Tri-state DBOP on read cycle */
-        DBOP_CTRL &= ~(1<<16);               /* disable output (1:write enabled) */
-        DBOP_TIMPOL_01 = 0xe167e167;         /* Set Timing & Polarity regs 0 & 1 */
-        DBOP_TIMPOL_23 = 0xe167006e;         /* Set Timing & Polarity regs 2 & 3 */
-
-        button_delay();
-        DBOP_CTRL |= (1<<15);                /* start read */
-        while (!(DBOP_STAT & (1<<16)));      /* wait for valid data */
-
-        _dbop_din = DBOP_DIN;                /* Read dbop data*/
-
-        /* Reset dbop for output */
-        DBOP_TIMPOL_01 = 0x6e167;            /* Set Timing & Polarity regs 0 & 1 */
-        DBOP_TIMPOL_23 = 0xa167e06f;         /* Set Timing & Polarity regs 2 & 3 */
-        DBOP_CTRL |= (1<<16);                /* Enable output (0:write disable)  */
-        DBOP_CTRL &= ~(1<<19);               /* Tri-state when no active write */
-    }
-
-#ifdef SANSA_FUZE
-    /* write back old values if blocked */
-    if (old_home_power != -20)
-    {
-        _dbop_din |= old_home_power & 1<<15;
-        _dbop_din &= 0xfeff|(old_home_power & 1<<8);
-    }
-#endif
-
+    unsigned dbop_din = dbop_read_input();
 #if defined(HAVE_SCROLLWHEEL) && !defined(BOOTLOADER)
-    /* read wheel on bit 13 & 14, but sent to the button queue seperately */
-        scrollwheel(_dbop_din);
+    /* scroll wheel handling */
+    scrollwheel((dbop_din >> 13) & (1<<1|1<<0));
 #endif
-
-#ifdef SANSA_E200V2
-    read_missed = false;
-#endif
-
-    return _dbop_din;
+    return dbop_din;
 }

-/* for the debug menu */
-unsigned short button_dbop_data(void)
-{
-    return _dbop_din;
-}
-
-static int button_gpio(void)
-{
-    int btn = BUTTON_NONE;
-    if(hold_button)
-        return btn;
-
-    /* disable DBOP output while changing GPIO pins that share lines with it */
-    DBOP_CTRL &= ~(1<<16);
-    button_delay();
-    
-    /* set afsel, so that we can read our buttons */
-    GPIOC_AFSEL &= ~(1<<2|1<<3|1<<4|1<<5|1<<6);
-    /* set dir so we can read our buttons (but reset the C pins first) */
-    GPIOB_DIR &= ~(1<<4);
-    GPIOC_DIR |= (1<<2|1<<3|1<<4|1<<5|1<<6);
-    GPIOC_PIN(2) = (1<<2);
-    GPIOC_PIN(3) = (1<<3);
-    GPIOC_PIN(4) = (1<<4);
-    GPIOC_PIN(5) = (1<<5);
-    GPIOC_PIN(6) = (1<<6);
-
-    GPIOC_DIR &= ~(1<<2|1<<3|1<<4|1<<5|1<<6);
-
-    /* small delay needed to read buttons correctly */
-    button_delay();
-
-    /* direct GPIO connections */
-    if (!GPIOC_PIN(3))
-        btn |= BUTTON_LEFT;
-    if (!GPIOC_PIN(2))
-        btn |= BUTTON_UP;
-    if (!GPIOC_PIN(6))
-        btn |= BUTTON_DOWN;
-    if (!GPIOC_PIN(5))
-        btn |= BUTTON_RIGHT;
-    if (!GPIOC_PIN(4))
-        btn |= BUTTON_SELECT;
-    /* return to settings needed for lcd */
-    GPIOC_DIR |= (1<<2|1<<3|1<<4|1<<5|1<<6);
-    GPIOC_AFSEL |= (1<<2|1<<3|1<<4|1<<5|1<<6);
-    
-    DBOP_CTRL |= (1<<16);               /* enable output again */
-    return btn;
-}
-
 /*
  * Get button pressed from hardware
  */
 int button_read_device(void)
 {
-    int btn = BUTTON_NONE;
-    unsigned short dbop = button_read_dbop();
 #ifdef SANSA_FUZE
     static unsigned power_counter = 0;
 #endif
-    /* hold button */
-    if(dbop & (1<<12))
+    unsigned short dbop_din;
+    int btn = BUTTON_NONE;
+
+    dbop_din = button_read_dbop();
+
+    /* hold button handling */
+    hold_button = ((dbop_din & (1<<12)) != 0);
+#ifndef BOOTLOADER
+    /* light handling */
+    if (hold_button != hold_button_old)
     {
+        hold_button_old = hold_button;
+        backlight_hold_changed(hold_button);
+    }
+#endif /* BOOTLOADER */
+    if (hold_button) {
 #ifdef SANSA_FUZE
         power_counter = HZ;
 #endif
-        hold_button = true;
+        return 0;
     }
-    else
-    {
-        hold_button = false;
+
+    /* push button handling */
+    if ((dbop_din & (1 << 2)) == 0)
+        btn |= BUTTON_UP;
+    if ((dbop_din & (1 << 3)) == 0)
+        btn |= BUTTON_LEFT;
+    if ((dbop_din & (1 << 4)) == 0)
+        btn |= BUTTON_SELECT;
+    if ((dbop_din & (1 << 5)) == 0)
+        btn |= BUTTON_RIGHT;
+    if ((dbop_din & (1 << 6)) == 0)
+        btn |= BUTTON_DOWN;
+    if ((dbop_din & (1 << 8)) != 0)
+        btn |= BUTTON_POWER;
+    if ((dbop_din & (1 << 15)) == 0)
+        btn |= DBOP_BIT15_BUTTON;
+
 #ifdef SANSA_FUZE
     /* read power on bit 8, but not if hold button was just released, since
      * you basically always hit power due to the slider mechanism after releasing
      * (fuze only)
-     * hold (wait 1 sec) */
-        if (power_counter)
+     */
+    if (power_counter > 0) {
             power_counter--;
+        btn &= ~BUTTON_POWER;
+    }
 #endif
-        if (dbop & (1<<8)
-#ifdef SANSA_FUZE
-            && !power_counter
-#endif
-            )
-            btn |= BUTTON_POWER;
-    /* read home on bit 15 */
-        if (!(dbop & (1<<15)))
-            btn |= DBOP_BIT15_BUTTON;

-        btn |= button_gpio();
-    }
-
-#ifndef BOOTLOADER
-    /* light handling */
-    if (hold_button != hold_button_old)
-    {
-        hold_button_old = hold_button;
-        backlight_hold_changed(hold_button);
-    }
-#endif /* BOOTLOADER */
-
     return btn;
 }
+
Index: firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c
===================================================================
--- firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c	(revision 24186)
+++ firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c	(working copy)
@@ -28,6 +28,7 @@
 #include "debug.h"
 #include "system.h"
 #include "clock-target.h"
+#include "dbop-as3525.h"

 /* The controller is unknown, but some registers appear to be the same as the
    HD66789R */
@@ -92,7 +93,6 @@
 static unsigned short r_disp_control_rev = R_DISP_CONTROL_NORMAL;

 static const int xoffset = 20;
-static volatile bool lcd_busy = false;

 static inline void lcd_delay(int x)
 {
@@ -379,8 +379,6 @@
     yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
     yuv_src[2] = src[2] + (yuv_src[1] - src[1]);

-    lcd_busy = true;
-
 #ifdef HAVE_LCD_FLIP
     lcd_write_reg(R_ENTRY_MODE,
         display_flipped ? R_ENTRY_MODE_VIDEO_FLIPPED : R_ENTRY_MODE_VIDEO_NORMAL
@@ -423,8 +421,6 @@
         }
         while (--height > 0);
     }
-
-    lcd_busy = false;
 }

 /* Update the display.
@@ -434,8 +430,6 @@
     if (!display_on)
         return;

-    lcd_busy = true;
-
     lcd_write_reg(R_ENTRY_MODE, r_entry_mode);

     lcd_window_x(0, LCD_WIDTH - 1);
@@ -444,8 +438,6 @@
     lcd_write_cmd(R_WRITE_DATA_2_GRAM);

     lcd_write_data((fb_data*)lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT);
-
-    lcd_busy = false;
 }

 /* Update a fraction of the display. */
@@ -475,8 +467,6 @@
     if (y >= ymax)
         return; /* nothing left to do */

-    lcd_busy = true;
-
     lcd_write_reg(R_ENTRY_MODE, r_entry_mode);

     lcd_window_x(x, xmax);
@@ -493,26 +483,4 @@
         ptr += LCD_WIDTH;
     }
     while (--height >= 0);
-
-    lcd_busy = false;
 }
-
-/* writes one red pixel outside the visible area, needed for correct
- * dbop reads */
-bool lcd_button_support(void)
-{
-    if (lcd_busy)
-        return false;
-
-    lcd_write_reg(R_ENTRY_MODE, r_entry_mode);
-
-    /* Set start position and window */
-    lcd_window_x(-1, 0);
-    lcd_window_y(-1, 0);
-
-    lcd_write_cmd(R_WRITE_DATA_2_GRAM);
-
-    lcd_write_value16(0xf<<12);
-
-    return true;
-}