From 2e17dd17ee9777084b2f211f08c4231dd5f8b906 Mon Sep 17 00:00:00 2001
From: Uros Majstorovic <majstor@majstor.org>
Date: Sun, 16 Feb 2025 20:17:07 +0100
Subject: extended gpio implemented

---
 fw/fe310/eos/dev/app.c     |  25 ++
 fw/fe310/eos/dev/app.h     |   3 +
 fw/fe310/eos/dev/ctp.c     | 212 ++++++++++++++++
 fw/fe310/eos/dev/ctp.h     |   7 +
 fw/fe310/eos/dev/egpio.c   | 585 ++++++++++++++++++++++++++++++++++++++++++++-
 fw/fe310/eos/dev/egpio.h   | 151 ++++++++----
 fw/fe310/eos/dev/eve.c     | 213 ++++++++++-------
 fw/fe310/eos/dev/eve.h     |  33 ++-
 fw/fe310/eos/dev/hpamp.c   |  22 ++
 fw/fe310/eos/dev/hpamp.h   |   3 +
 fw/fe310/eos/dev/lcd.c     |  80 +++----
 fw/fe310/eos/dev/lcd.h     |   2 +-
 fw/fe310/eos/dev/spi.c     | 122 ++++++----
 fw/fe310/eos/dev/spi.h     |  12 +-
 fw/fe310/eos/dev/spi_cfg.h |  24 +-
 15 files changed, 1236 insertions(+), 258 deletions(-)
 create mode 100644 fw/fe310/eos/dev/app.c
 create mode 100644 fw/fe310/eos/dev/app.h
 create mode 100644 fw/fe310/eos/dev/ctp.c
 create mode 100644 fw/fe310/eos/dev/ctp.h
 create mode 100644 fw/fe310/eos/dev/hpamp.c
 create mode 100644 fw/fe310/eos/dev/hpamp.h

diff --git a/fw/fe310/eos/dev/app.c b/fw/fe310/eos/dev/app.c
new file mode 100644
index 0000000..3c215f4
--- /dev/null
+++ b/fw/fe310/eos/dev/app.c
@@ -0,0 +1,25 @@
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "eos.h"
+
+#include "hpamp.h"
+#include "app.h"
+
+#ifdef EOS_DEBUG
+#include <stdio.h>
+#endif
+
+void eos_app_hp_change(int hp_det) {
+    if (hp_det) {
+        int rv;
+
+        rv = eos_hpamp_init();
+        if (rv) {
+#ifdef EOS_DEBUG
+            printf("I2S HP CHANGE: PCM1770 INIT ERR:%d\n", rv);
+#endif
+            return;
+        }
+    }
+}
diff --git a/fw/fe310/eos/dev/app.h b/fw/fe310/eos/dev/app.h
new file mode 100644
index 0000000..4ee2e8d
--- /dev/null
+++ b/fw/fe310/eos/dev/app.h
@@ -0,0 +1,3 @@
+#include <stdint.h>
+
+void eos_app_hp_change(int hp_det);
\ No newline at end of file
diff --git a/fw/fe310/eos/dev/ctp.c b/fw/fe310/eos/dev/ctp.c
new file mode 100644
index 0000000..fcc3c68
--- /dev/null
+++ b/fw/fe310/eos/dev/ctp.c
@@ -0,0 +1,212 @@
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "eos.h"
+
+#include "soc/pwr.h"
+#include "soc/i2s.h"
+#include "soc/timer.h"
+#include "eve/eve.h"
+#include "eve/eve_touch_engine.h"
+
+#include "egpio.h"
+#include "eve.h"
+#include "pwr.h"
+
+#include "drv/fxl6408.h"
+#include "drv/gt911.h"
+#include "ctp.h"
+
+#ifdef EOS_DEBUG
+#include <stdio.h>
+#endif
+
+int eos_ctp_init(void) {
+    uint8_t wakeup_cause;
+    int rv, rst;
+
+    wakeup_cause = eos_pwr_wakeup_cause();
+    rst = (wakeup_cause == EOS_PWR_WAKE_RST);
+    if (rst) {
+        rv = eos_ctp_reset();
+    } else {
+        rv = eos_ctp_wake();
+    }
+
+    return rv;
+}
+
+int eos_ctp_reset(void) {
+    int rv;
+
+    if (eos_i2s_running() || !eos_egpio_get_val(EGPIO_PIN_DISP_SEL) || !eos_egpio_get_val(EGPIO_PIN_CTP_SEL)) return EOS_ERR_BUSY;
+
+    rv = eos_egpio_intr_disable();
+    if (rv) return rv;
+
+    gt911_reset();
+
+    rv = eos_egpio_intr_set();
+    if (rv) return rv;
+
+    return EOS_OK;
+}
+
+int eos_ctp_sleep(void) {
+    int rv;
+
+    if (eos_i2s_running() || !eos_egpio_get_val(EGPIO_PIN_DISP_SEL) || !eos_egpio_get_val(EGPIO_PIN_CTP_SEL)) return EOS_ERR_BUSY;
+
+    rv = eos_egpio_intr_disable();
+    if (rv) return rv;
+
+    rv = gt911_sleep();
+    if (rv) return rv;
+
+    rv = eos_egpio_fxl_set_pin(EGPIO_PIN_CTP_INT, FXL6408_REG_PULL_DIR, 0);
+    if (rv) return rv;
+
+    return EOS_OK;
+}
+
+int eos_ctp_wake(void) {
+    int rv;
+
+    if (eos_i2s_running() || !eos_egpio_get_val(EGPIO_PIN_DISP_SEL) || !eos_egpio_get_val(EGPIO_PIN_CTP_SEL)) return EOS_ERR_BUSY;
+
+    rv = eos_egpio_fxl_set_pin(EGPIO_PIN_CTP_INT, FXL6408_REG_PULL_DIR, 1);
+    if (rv) return rv;
+
+    gt911_wake();
+
+    rv = eos_egpio_intr_set();
+    if (rv) return rv;
+
+    return EOS_OK;
+}
+
+int eos_ctp_give(void) {
+    int rv;
+
+    if (!eos_egpio_get_val(EGPIO_PIN_DISP_SEL)) return EOS_ERR_BUSY;
+    if (!eos_egpio_get_val(EGPIO_PIN_CTP_SEL)) return EOS_ERR;
+
+    rv = eos_egpio_intr_disable();
+    if (rv) return rv;
+
+    rv = eve_select();
+    if (rv) return rv;
+
+    rv = eos_egpio_set_val(EGPIO_PIN_CTP_SEL, 0);
+    if (rv) return rv;
+
+    eve_touch_set_engine(EVE_TOUCH_ENGINE_GOODIX);
+    eve_deselect();
+
+    rv = eos_egpio_intr_set();
+    if (rv) return rv;
+
+    return EOS_OK;
+}
+
+int eos_ctp_take(void) {
+    int rv;
+
+    if (eos_i2s_running() || !eos_egpio_get_val(EGPIO_PIN_DISP_SEL)) return EOS_ERR_BUSY;
+    if (eos_egpio_get_val(EGPIO_PIN_CTP_SEL)) return EOS_ERR;
+
+    rv = eos_egpio_intr_disable();
+    if (rv) return rv;
+
+    rv = eve_select();
+    if (rv) return rv;
+
+    eve_touch_set_engine(EVE_TOUCH_ENGINE_HOST);
+    eve_deselect();
+
+    rv = eos_egpio_set_val(EGPIO_PIN_CTP_SEL, 1);
+    if (rv) return rv;
+
+    gt911_reset();
+
+    rv = eos_egpio_intr_set();
+    if (rv) return rv;
+
+    return EOS_OK;
+}
+
+int eos_ctp_handle_intr(void) {
+    uint8_t status;
+    uint8_t points[GT911_SIZE_PBUF * GT911_MAX_POINTS];
+    static int clear_tag0 = 0;
+    int i, num_points;
+    int rv;
+    uint32_t start;
+
+    rv = gt911_get_status(&status);
+    if (rv) return rv;
+    if (!(status & 0x80)) return 0;
+
+    num_points = status & 0xf;
+    if (num_points > 5) {
+        rv = EOS_ERR;
+        goto handle_intr_fin;
+    }
+
+    rv = eve_select();
+    if (rv) goto handle_intr_fin;
+
+    start = eos_get_tick();
+    while (!eve_touch_ehost_ready()) {
+        if (eos_tdelta_ms(start) > EVE_CMD_EXEC_TO) break;
+    }
+
+    if (eos_tdelta_ms(start) > EVE_CMD_EXEC_TO) {
+        rv = EOS_ERR_TIMEOUT;
+        eve_deselect();
+        goto handle_intr_fin;
+    }
+
+    if (num_points) {
+        if (clear_tag0) {
+            eve_touch_clear_tag0();
+            clear_tag0 = 0;
+        }
+        rv = gt911_get_points(num_points, points);
+        if (rv) {
+            rv = EOS_ERR;
+            eve_deselect();
+            goto handle_intr_fin;
+        }
+
+        for (i=0; i<num_points; i++) {
+            uint8_t *point_buf;
+            uint8_t point_id;
+            uint16_t point_x;
+            uint16_t point_y;
+
+            point_buf = points + GT911_SIZE_PBUF * i;
+            point_id = point_buf[0];
+            point_x = point_buf[1] | (point_buf[2] << 8);
+            point_y = point_buf[3] | (point_buf[4] << 8);
+            eve_touch_ehost_enter(point_id, point_x, point_y);
+        }
+    } else {
+        eve_touch_ehost_enter(0, 0x8000, 0x8000);
+        clear_tag0 = 1;
+    }
+
+    eve_touch_ehost_end();
+    eve_deselect();
+
+handle_intr_fin:
+    gt911_set_status(0);
+    if (rv) {
+#ifdef EOS_DEBUG
+        printf("CTP HANDLE INTR ERR:%d\n", rv);
+#endif
+        return rv;
+    }
+
+    return 1;
+}
diff --git a/fw/fe310/eos/dev/ctp.h b/fw/fe310/eos/dev/ctp.h
new file mode 100644
index 0000000..72a0a75
--- /dev/null
+++ b/fw/fe310/eos/dev/ctp.h
@@ -0,0 +1,7 @@
+#include <stdint.h>
+
+int eos_ctp_init(void);
+int eos_ctp_reset(void);
+int eos_ctp_sleep(void);
+int eos_ctp_wake(void);
+int eos_ctp_handle_intr(void);
\ No newline at end of file
diff --git a/fw/fe310/eos/dev/egpio.c b/fw/fe310/eos/dev/egpio.c
index c17fe81..7358082 100644
--- a/fw/fe310/eos/dev/egpio.c
+++ b/fw/fe310/eos/dev/egpio.c
@@ -1,30 +1,595 @@
 #include <stdlib.h>
 #include <stdint.h>
 
+#include "encoding.h"
+#include "platform.h"
+#include "board.h"
+
 #include "eos.h"
-#include "soc/i2c.h"
+#include "event.h"
+
+#include "soc/interrupt.h"
+#include "soc/timer.h"
+#include "soc/pwr.h"
+#include "soc/i2s.h"
+#include "eve/eve.h"
+
+#include "batt.h"
+#include "sdcard.h"
+#include "ctp.h"
+#include "eve.h"
+#include "app.h"
 
-#include "fxl6408.h"
+#include "drv/fxl6408.h"
 #include "egpio.h"
 
-int eos_egpio_pin_get(uint8_t reg, uint8_t pin, uint8_t *val) {
+/* FXL chip only */
+static const uint8_t egpio_switch[2] = {
+    EGPIO_BIT_SDCARD_DET | EGPIO_BIT_BTN_WAKE,
+    EGPIO_BIT_MIC_MUTE | EGPIO_BIT_HP_NDET,
+};
+
+static uint8_t egpio_pinval[EGPIO_MAX_CHIP];
+static uint8_t egpio_alt_pin;
+static uint32_t wake_start;
+
+static eos_egpio_intr_handler_t egpio_intr_handler;
+static eos_egpio_ext_handler_t egpio_ext_handler;
+
+#define EGPIO_ALT_EVEAUDIO_DIS      0x01
+#define EGPIO_ALT_LSGAIN_SEL        0x02
+#define EGPIO_ALT_AUDIO_SEL         0x04
+
+#define BITSET(var, bit, val)       { var = (val) ? (var | (bit)) : (var & ~(bit)); }
+#define PINSWITCH(STPIN, SETPIN)    { \
+                                        int rv; \
+                                        BITSET(egpio_alt_pin, pin2alt_bit(STPIN), _eos_egpio_get_val(STPIN)); \
+                                        rv = _eos_egpio_set_val(SETPIN, !!(egpio_alt_pin & pin2alt_bit(SETPIN))); \
+                                        if (rv) return rv; \
+                                    }
+
+static uint8_t pin2alt_bit(uint8_t pin) {
+    switch (pin) {
+        case EGPIO_PIN_EVEAUDIO_DIS:
+            return EGPIO_ALT_EVEAUDIO_DIS;
+        case EGPIO_PIN_LSGAIN_SEL:
+            return EGPIO_ALT_LSGAIN_SEL;
+        case EGPIO_PIN_AUDIO_SEL:
+            return EGPIO_ALT_AUDIO_SEL;
+    }
+
+    return 0x00;
+}
+
+static int handle_egpio_intr(uint8_t chip_id, uint8_t intr) {
+    int rv;
+
+    switch (chip_id) {
+        case 0: {
+            if (intr & EGPIO_BIT_BAT_INT) {
+                uint8_t fault0, fault1;
+
+                rv = eos_batt_read_fault(&fault0, &fault1);
+                if (rv) return rv;
+
+                if (egpio_intr_handler) egpio_intr_handler(EGPIO_INT_TYPE_BAT, fault1, fault0);
+            }
+            if (intr & EGPIO_BIT_CTP_INT) {
+                eos_ctp_handle_intr();
+            }
+            if (intr & EGPIO_BIT_EVE_INT) {
+                eos_eve_handle_intr();
+            }
+            if (intr & EGPIO_BIT_BTN_WAKE) {
+                int btn_wake, tdelta;
+
+                btn_wake = eos_egpio_get_val(EGPIO_PIN_BTN_WAKE);
+                if (btn_wake == 0) {
+                    wake_start = eos_get_tick();
+                } else {
+                    tdelta = eos_tdelta_ms(wake_start);
+                }
+                if (egpio_intr_handler) egpio_intr_handler(EGPIO_INT_TYPE_WAKE, btn_wake, btn_wake ? tdelta : 0);
+            }
+            if (intr & EGPIO_BIT_SDCARD_DET) {
+                int sdc_det = eos_egpio_get_val(EGPIO_PIN_SDCARD_DET);
+
+                eos_sdc_insert(sdc_det);
+                if (egpio_intr_handler) egpio_intr_handler(EGPIO_INT_TYPE_SDCARD, sdc_det, 0);
+            }
+            break;
+        }
+
+        case 1: {
+            if (intr & EGPIO_BIT_MIC_MUTE) {
+                if (egpio_intr_handler) egpio_intr_handler(EGPIO_INT_TYPE_MUTE, eos_egpio_get_val(EGPIO_PIN_MIC_MUTE), 0);
+            }
+            if (intr & EGPIO_BIT_HP_NDET) {
+                int hp_det, i2s_running, app_audio;
+
+                hp_det = !eos_egpio_get_val(EGPIO_PIN_HP_NDET);
+                i2s_running = eos_i2s_running();
+                app_audio = !_eos_egpio_get_val(EGPIO_PIN_AUDIO_SEL);
+                if (i2s_running || app_audio) {
+                    if (i2s_running) {
+                        eos_i2s_hp_change(hp_det);
+                    } else {
+                        eos_app_hp_change(hp_det);
+                    }
+
+                    if (hp_det) {
+                        /* store LSGAIN_SEL pin and set EVEAUDIO_DIS pin */
+                        PINSWITCH(EGPIO_PIN_LSGAIN_SEL, EGPIO_PIN_EVEAUDIO_DIS);
+                    } else {
+                        /* store EVEAUDIO_DIS pin and set LSGAIN_SEL pin */
+                        PINSWITCH(EGPIO_PIN_EVEAUDIO_DIS, EGPIO_PIN_LSGAIN_SEL);
+                    }
+                }
+                if (egpio_intr_handler) egpio_intr_handler(EGPIO_INT_TYPE_HP, hp_det, 0);
+            }
+            break;
+        }
+    }
+
+    return EOS_OK;
+}
+
+static int handle_egpio_evt(uint8_t chip_id) {
+    uint8_t intr_reg, def_reg;
+    int rv;
+
+    rv = fxl6408_reg_read(chip_id, FXL6408_REG_INT_STATE, &intr_reg);
+    if (rv) return rv;;
+    if (!intr_reg) return 0;
+
+    if (intr_reg & egpio_switch[chip_id]) {
+        rv = fxl6408_reg_read(chip_id, FXL6408_REG_I_DEFAULT, &def_reg);
+        if (rv) return rv;
+
+        def_reg ^= (intr_reg & egpio_switch[chip_id]);
+
+        rv = fxl6408_reg_write(chip_id, FXL6408_REG_I_DEFAULT, def_reg);
+        if (rv) return rv;
+
+        egpio_pinval[chip_id] ^= (intr_reg & egpio_switch[chip_id]);
+    }
+
+    rv = handle_egpio_intr(chip_id, intr_reg);
+    if (rv) return rv;
+
+    return 1;
+}
+
+static void handle_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
+    type &= ~EOS_EVT_MASK;
+
+    switch (type) {
+        case EGPIO_ETYPE_INT: {
+            int rv;
+
+            rv = handle_egpio_evt(0);
+            if (rv < 0) goto handle_evt_fin;
+            if (GPIO_REG(GPIO_INPUT_VAL) & (1 << EGPIO_PIN_INT)) goto handle_evt_fin;
+
+            rv = handle_egpio_evt(1);
+            if (rv < 0) goto handle_evt_fin;
+            if (GPIO_REG(GPIO_INPUT_VAL) & (1 << EGPIO_PIN_INT)) goto handle_evt_fin;
+
+            if (egpio_ext_handler) rv = egpio_ext_handler();
+
+handle_evt_fin:
+            clear_csr(mstatus, MSTATUS_MIE);
+            GPIO_REG(GPIO_LOW_IP) = (1 << EGPIO_PIN_INT);
+            GPIO_REG(GPIO_LOW_IE) |= (1 << EGPIO_PIN_INT);
+            set_csr(mstatus, MSTATUS_MIE);
+            break;
+        }
+
+        case EGPIO_ETYPE_INT_CTP:
+        case EGPIO_ETYPE_INT_EVE: {
+            if (eos_egpio_get_val(EGPIO_PIN_CTP_SEL)) {
+                eos_ctp_handle_intr();
+            } else {
+                eos_eve_handle_intr();
+            }
+
+handle_evt_eve_fin:
+            clear_csr(mstatus, MSTATUS_MIE);
+            GPIO_REG(GPIO_LOW_IP) = (1 << EVE_PIN_INT);
+            GPIO_REG(GPIO_LOW_IE) |= (1 << EVE_PIN_INT);
+            set_csr(mstatus, MSTATUS_MIE);
+            break;
+        }
+    }
+}
+
+static void handle_intr(void) {
+    GPIO_REG(GPIO_LOW_IE) &= ~(1 << EGPIO_PIN_INT);
+    eos_evtq_push_isr(EOS_EVT_EGPIO | EGPIO_ETYPE_INT, NULL, 0);
+}
+
+static void handle_intr_eve(void) {
+    GPIO_REG(GPIO_LOW_IE) &= ~(1 << EVE_PIN_INT);
+    if (egpio_pinval[EGPIO_CHIP_FXL0] & EGPIO_PIN2BIT(EGPIO0_PIN_CTP_SEL)) {
+        eos_evtq_push_isr(EOS_EVT_EGPIO | EGPIO_ETYPE_INT_CTP, NULL, 0);
+    } else {
+        eos_evtq_push_isr(EOS_EVT_EGPIO | EGPIO_ETYPE_INT_EVE, NULL, 0);
+    }
+}
+
+int eos_egpio_init(void) {
+    uint8_t wakeup_cause, data, data_dir;
+    int rst, rv;
+
+    wakeup_cause = eos_pwr_wakeup_cause();
+    rst = (wakeup_cause == EOS_PWR_WAKE_RST);
+    if (rst) {
+        rv = fxl6408_reg_read(0, FXL6408_REG_ID_CTRL, &data);
+        if (rv) return rv;
+        rv = fxl6408_reg_read(1, FXL6408_REG_ID_CTRL, &data);
+        if (rv) return rv;
+
+        rv = fxl6408_reg_write(0, FXL6408_REG_INT_MASK, 0xff);
+        if (rv) return rv;
+        rv = fxl6408_reg_write(1, FXL6408_REG_INT_MASK, 0xff);
+        if (rv) return rv;
+
+        /* 1st chip */
+        data = EGPIO_BIT_CTP_SEL | EGPIO_BIT_EXP_IO0 | EGPIO_BIT_EXP_IO1;
+        rv = fxl6408_reg_write(0, FXL6408_REG_IO_DIR, data);
+        if (rv) return rv;
+
+        data = EGPIO_BIT_CTP_SEL;
+        rv = fxl6408_reg_write(0, FXL6408_REG_O_STATE, data);
+        if (rv) return rv;
+
+        data = EGPIO_BIT_EXP_IO0 | EGPIO_BIT_EXP_IO1;
+        rv = fxl6408_reg_write(0, FXL6408_REG_O_HIZ, data);
+        if (rv) return rv;
+
+        data = EGPIO_BIT_EVE_INT | EGPIO_BIT_SDCARD_DET | EGPIO_BIT_BTN_WAKE | EGPIO_BIT_BAT_INT | EGPIO_BIT_CTP_INT;
+        rv = fxl6408_reg_write(0, FXL6408_REG_PULL_ENA, data);
+        if (rv) return rv;
+
+        data = EGPIO_BIT_EVE_INT | EGPIO_BIT_SDCARD_DET | EGPIO_BIT_BTN_WAKE | EGPIO_BIT_BAT_INT | EGPIO_BIT_CTP_INT;
+        rv = fxl6408_reg_write(0, FXL6408_REG_PULL_DIR, data);
+        if (rv) return rv;
+
+        /* 2nd chip */
+        data = EGPIO_BIT_HPAMP_CS | EGPIO_BIT_AUDIO_SEL | EGPIO_BIT_USR0 | EGPIO_BIT_USR1 | EGPIO_BIT_USR2 | EGPIO_BIT_USR3;
+        rv = fxl6408_reg_write(1, FXL6408_REG_IO_DIR, data);
+        if (rv) return rv;
+
+        data = EGPIO_BIT_HPAMP_CS | EGPIO_BIT_AUDIO_SEL;
+        rv = fxl6408_reg_write(1, FXL6408_REG_O_STATE, data);
+        if (rv) return rv;
+
+        data = EGPIO_BIT_USR0 | EGPIO_BIT_USR1 | EGPIO_BIT_USR2 | EGPIO_BIT_USR3;
+        rv = fxl6408_reg_write(1, FXL6408_REG_O_HIZ, data);
+        if (rv) return rv;
+
+        data = 0;
+        rv = fxl6408_reg_write(1, FXL6408_REG_PULL_ENA, data);
+        if (rv) return rv;
+
+        data = 0;
+        rv = fxl6408_reg_write(1, FXL6408_REG_PULL_DIR, data);
+        if (rv) return rv;
+    }
+
+    rv = fxl6408_reg_read(0, FXL6408_REG_I_STATE, &data);
+    if (rv) return rv;
+    data &= egpio_switch[0];
+    egpio_pinval[EGPIO_CHIP_FXL0] = data;
+    data |= EGPIO_BIT_EVE_INT | EGPIO_BIT_BAT_INT | EGPIO_BIT_CTP_INT;
+    rv = fxl6408_reg_write(0, FXL6408_REG_I_DEFAULT, data);
+    if (rv) return rv;
+
+    rv = fxl6408_reg_read(0, FXL6408_REG_IO_DIR, &data_dir);
+    if (rv) return rv;
+    rv = fxl6408_reg_read(0, FXL6408_REG_O_STATE, &data);
+    if (rv) return rv;
+    egpio_pinval[EGPIO_CHIP_FXL0] |= (data & data_dir);
+
+    rv = fxl6408_reg_read(1, FXL6408_REG_I_STATE, &data);
+    if (rv) return rv;
+    data &= egpio_switch[1];
+    egpio_pinval[EGPIO_CHIP_FXL1] = data;
+    rv = fxl6408_reg_write(1, FXL6408_REG_I_DEFAULT, data);
+    if (rv) return rv;
+
+    rv = fxl6408_reg_read(1, FXL6408_REG_IO_DIR, &data_dir);
+    if (rv) return rv;
+    rv = fxl6408_reg_read(1, FXL6408_REG_O_STATE, &data);
+    if (rv) return rv;
+    egpio_pinval[EGPIO_CHIP_FXL1] |= (data & data_dir);
+
+    return EOS_OK;
+}
+
+int eos_egpio_run(void) {
+    uint8_t wakeup_cause, data;
+    int rst, rv;
+
+    eos_evtq_set_handler(EOS_EVT_EGPIO, handle_evt);
+
+    GPIO_REG(GPIO_INPUT_EN)     |=  (1 << EGPIO_PIN_INT);
+    clear_csr(mstatus, MSTATUS_MIE);
+    GPIO_REG(GPIO_LOW_IE)       |=  (1 << EGPIO_PIN_INT);
+    set_csr(mstatus, MSTATUS_MIE);
+    eos_intr_set(INT_GPIO_BASE + EGPIO_PIN_INT, IRQ_PRIORITY_EGPIO, handle_intr);
+
+    /* EVE_PIN_INT will be set in intr_set() below */
+    eos_intr_set(INT_GPIO_BASE + EVE_PIN_INT, IRQ_PRIORITY_EVE, handle_intr_eve);
+
+    wakeup_cause = eos_pwr_wakeup_cause();
+    rst = (wakeup_cause == EOS_PWR_WAKE_RST);
+    if (rst) {
+        /* turn on interrupts when all is configured */
+        data = ~(EGPIO_BIT_SDCARD_DET | EGPIO_BIT_BTN_WAKE | EGPIO_BIT_BAT_INT);
+        rv = fxl6408_reg_write(0, FXL6408_REG_INT_MASK, data);
+        if (rv) return rv;
+
+        data = ~(EGPIO_BIT_MIC_MUTE | EGPIO_BIT_HP_NDET);
+        rv = fxl6408_reg_write(1, FXL6408_REG_INT_MASK, data);
+        if (rv) return rv;
+    }
+
+    rv = eos_egpio_intr_set();
+    if (rv) return rv;
+
+    return EOS_OK;
+}
+
+void eos_egpio_eve_set(uint16_t gpio_reg) {
+    egpio_pinval[EGPIO_CHIP_EVE] = gpio_reg & 0xff;
+    if (gpio_reg & (1 << EVE_GPIO_DISP)) egpio_pinval[EGPIO_CHIP_EVE] |= EGPIO_PIN2BIT(EGPIO_PIN_DISP_SEL);
+}
+
+int _eos_egpio_intr_set(int i2s_running, int app_disp) {
+    uint8_t data;
+    int rv;
+
+    rv = fxl6408_reg_read(0, FXL6408_REG_INT_MASK, &data);
+    if (rv) return rv;
+
+    data &= ~(EGPIO_BIT_EVE_INT | EGPIO_BIT_CTP_INT);
+    if (app_disp) {
+        data |= (EGPIO_BIT_EVE_INT | EGPIO_BIT_CTP_INT);
+    } else if (!i2s_running) {
+        if (eos_egpio_get_val(EGPIO_PIN_CTP_SEL)) {
+            data |= EGPIO_BIT_CTP_INT;
+        } else {
+            data |= EGPIO_BIT_EVE_INT;
+        }
+    }
+
+    rv = fxl6408_reg_write(0, FXL6408_REG_INT_MASK, data);
+    if (rv) return rv;
+
+    GPIO_REG(GPIO_INPUT_EN) |= (1 << EVE_PIN_INT);
+    clear_csr(mstatus, MSTATUS_MIE);
+    if (app_disp || i2s_running) {
+        GPIO_REG(GPIO_LOW_IE) &= ~(1 << EVE_PIN_INT);
+    } else {
+        GPIO_REG(GPIO_LOW_IE) |=  (1 << EVE_PIN_INT);
+    }
+    set_csr(mstatus, MSTATUS_MIE);
+
+    return EOS_OK;
+}
+
+int eos_egpio_intr_set(void) {
+    return _eos_egpio_intr_set(eos_i2s_running(), !eos_egpio_get_val(EGPIO_PIN_DISP_SEL));
+}
+
+int eos_egpio_intr_disable(void) {
+    uint8_t data;
+    int rv;
+
+    rv = fxl6408_reg_read(0, FXL6408_REG_INT_MASK, &data);
+    if (rv) return rv;
+
+    data |= (EGPIO_BIT_EVE_INT | EGPIO_BIT_CTP_INT);
+
+    rv = fxl6408_reg_write(0, FXL6408_REG_INT_MASK, data);
+    if (rv) return rv;
+
+    clear_csr(mstatus, MSTATUS_MIE);
+    GPIO_REG(GPIO_LOW_IE)       &= ~(1 << EVE_PIN_INT);
+    set_csr(mstatus, MSTATUS_MIE);
+    GPIO_REG(GPIO_INPUT_EN)     &= ~(1 << EVE_PIN_INT);
+
+    return EOS_OK;
+}
+
+void eos_egpio_set_intr_handler(eos_egpio_intr_handler_t handler) {
+    egpio_intr_handler = handler;
+}
+
+void eos_egpio_set_ext_handler(eos_egpio_ext_handler_t handler) {
+    egpio_ext_handler = handler;
+}
+
+int eos_egpio_fxl_get_pin(uint8_t reg, uint8_t pin, uint8_t *val) {
     uint8_t chip_id;
     int rv;
 
-    chip_id = (pin & EGPIO_PIN_MASK_CHIP_ID) >> 4;
+    chip_id = EGPIO_PIN2CHIP(pin);
     pin &= EGPIO_PIN_MASK;
 
-    rv = eos_fxl6408_pin_get(chip_id, reg, pin, val);
+    rv = fxl6408_get_pin(chip_id, reg, pin, val);
     return rv;
 }
 
-int eos_egpio_pin_set(uint8_t reg, uint8_t pin, uint8_t val) {
+int eos_egpio_fxl_set_pin(uint8_t reg, uint8_t pin, uint8_t val) {
     uint8_t chip_id;
     int rv;
 
-    chip_id = (pin & EGPIO_PIN_MASK_CHIP_ID) >> 4;
+    chip_id = EGPIO_PIN2CHIP(pin);
     pin &= EGPIO_PIN_MASK;
 
-    rv = eos_fxl6408_pin_set(chip_id, reg, pin, val);
-    return rv;
-}
\ No newline at end of file
+    rv = fxl6408_set_pin(chip_id, reg, pin, val);
+    if (rv) return rv;
+
+    return EOS_OK;
+}
+
+int _eos_egpio_get_val(uint8_t pin) {
+    uint8_t chip_id;
+
+    chip_id = EGPIO_PIN2CHIP(pin);
+
+    return !!(egpio_pinval[chip_id] & EGPIO_PIN2BIT(pin));
+}
+
+int _eos_egpio_set_val(uint8_t pin, int val) {
+    uint8_t chip_id;
+    int rv;
+
+    val = !!val;
+    chip_id = EGPIO_PIN2CHIP(pin);
+    pin &= EGPIO_PIN_MASK;
+
+    if (chip_id == EGPIO_CHIP_EVE) {
+        rv = eve_select();
+        if (rv) return rv;
+
+        /* activate if needed */
+        eve_activate();
+
+        if (pin == EGPIOE_PIN_DISP) pin = EVE_GPIO_DISP;
+        eve_gpio_set(pin, val);
+
+        /* restore previous power state */
+        eve_deactivate();
+        eve_deselect();
+    } else {
+        rv = fxl6408_set_pin(chip_id, FXL6408_REG_O_STATE, pin, val);
+        if (rv) return rv;
+    }
+
+    BITSET(egpio_pinval[chip_id], EGPIO_PIN2BIT(pin), val);
+
+    return EOS_OK;
+}
+
+int eos_egpio_get_val(uint8_t pin) {
+    switch (pin) {
+        case EGPIO_PIN_AUDIO_SEL: {
+            if (eos_i2s_running()) {
+                return !!(egpio_alt_pin & pin2alt_bit(pin));
+            }
+            break;
+        }
+
+        case EGPIO_PIN_EVEAUDIO_DIS:
+        case EGPIO_PIN_LSGAIN_SEL: {
+            int lspk_on = (eos_i2s_running() || !_eos_egpio_get_val(EGPIO_PIN_AUDIO_SEL)) && eos_egpio_get_val(EGPIO_PIN_HP_NDET);
+
+            if ((pin == EGPIO_PIN_EVEAUDIO_DIS) && lspk_on) {
+                return !!(egpio_alt_pin & pin2alt_bit(pin));
+            }
+
+            if ((pin == EGPIO_PIN_LSGAIN_SEL) && !lspk_on) {
+                return !!(egpio_alt_pin & pin2alt_bit(pin));
+            }
+            break;
+        }
+    }
+
+    return _eos_egpio_get_val(pin);
+}
+
+int eos_egpio_set_val(uint8_t pin, int val) {
+    uint8_t chip_id;
+    int rv;
+
+    val = !!val;
+    switch (pin) {
+        case EGPIO_PIN_CTP_SEL: {
+            if (!eos_egpio_get_val(EGPIO_PIN_DISP_SEL)) {
+                return EOS_ERR_BUSY;
+            }
+            break;
+        }
+
+        case EGPIO_PIN_AUDIO_SEL: {
+            if (eos_i2s_running()) {
+                BITSET(egpio_alt_pin, pin2alt_bit(pin), val);
+                return EOS_OK;
+            }
+
+            if ((val != _eos_egpio_get_val(EGPIO_PIN_AUDIO_SEL)) && eos_egpio_get_val(EGPIO_PIN_HP_NDET)) {
+                if (val) {
+                    /* store LSGAIN_SEL pin and set EVEAUDIO_DIS pin */
+                    PINSWITCH(EGPIO_PIN_LSGAIN_SEL, EGPIO_PIN_EVEAUDIO_DIS);
+                } else {
+                    /* store EVEAUDIO_DIS pin and set LSGAIN_SEL pin */
+                    PINSWITCH(EGPIO_PIN_EVEAUDIO_DIS, EGPIO_PIN_LSGAIN_SEL);
+                }
+            }
+            break;
+        }
+
+        case EGPIO_PIN_EVEAUDIO_DIS:
+        case EGPIO_PIN_LSGAIN_SEL: {
+            int lspk_on = (eos_i2s_running() || !_eos_egpio_get_val(EGPIO_PIN_AUDIO_SEL)) && eos_egpio_get_val(EGPIO_PIN_HP_NDET);
+
+            if ((pin == EGPIO_PIN_EVEAUDIO_DIS) && lspk_on) {
+                BITSET(egpio_alt_pin, pin2alt_bit(pin), val);
+                return EOS_OK;
+            }
+
+            if ((pin == EGPIO_PIN_LSGAIN_SEL) && !lspk_on) {
+                BITSET(egpio_alt_pin, pin2alt_bit(pin), val);
+                return EOS_OK;
+            }
+            break;
+        }
+    }
+
+    rv = _eos_egpio_set_val(pin, val);
+    if (rv) return rv;
+
+    return EOS_OK;
+}
+
+int eos_egpio_i2s_start(void) {
+    uint8_t data;
+    int rv, audio_sel;
+
+    rv = _eos_egpio_intr_set(1, !eos_egpio_get_val(EGPIO_PIN_DISP_SEL));
+    if (rv) return rv;
+
+    audio_sel = _eos_egpio_get_val(EGPIO_PIN_AUDIO_SEL);
+    BITSET(egpio_alt_pin, pin2alt_bit(EGPIO_PIN_AUDIO_SEL), audio_sel);
+
+    rv = _eos_egpio_set_val(EGPIO_PIN_AUDIO_SEL, 1);
+    if (rv) return rv;
+
+    if (!audio_sel && eos_egpio_get_val(EGPIO_PIN_HP_NDET)) {
+        /* store EVEAUDIO_DIS pin and set LSGAIN_SEL pin */
+        PINSWITCH(EGPIO_PIN_EVEAUDIO_DIS, EGPIO_PIN_LSGAIN_SEL);
+    }
+
+    return EOS_OK;
+}
+
+int eos_egpio_i2s_stop(void) {
+    int rv, audio_sel;
+
+    rv = _eos_egpio_intr_set(0, !eos_egpio_get_val(EGPIO_PIN_DISP_SEL));
+    if (rv) return rv;
+
+    audio_sel = (egpio_alt_pin & pin2alt_bit(EGPIO_PIN_AUDIO_SEL));
+    if (!audio_sel && eos_egpio_get_val(EGPIO_PIN_HP_NDET)) {
+        /* store LSGAIN_SEL pin and set EVEAUDIO_DIS pin */
+        PINSWITCH(EGPIO_PIN_LSGAIN_SEL, EGPIO_PIN_EVEAUDIO_DIS);
+    }
+
+    rv = _eos_egpio_set_val(EGPIO_PIN_AUDIO_SEL, audio_sel);
+    if (rv) return rv;
+
+    return EOS_OK;
+}
diff --git a/fw/fe310/eos/dev/egpio.h b/fw/fe310/eos/dev/egpio.h
index e9573a7..7d20443 100644
--- a/fw/fe310/eos/dev/egpio.h
+++ b/fw/fe310/eos/dev/egpio.h
@@ -1,46 +1,115 @@
 #include <stdint.h>
 
-#define EGPIO0_EVE_INT          0x00    /* EVE interrrupt */
-#define EGPIO0_SDCARD_DET       0x01    /* SD Card detect */
-#define EGPIO0_EXP_IO0          0x02    /* expansion io 0 */
-#define EGPIO0_EXP_IO1          0x03    /* expansion io 1 */
-#define EGPIO0_BTN_WAKE         0x04    /* wake button */
-#define EGPIO0_BAT_INT          0x05    /* battery charger IC inetrrupt */
-#define EGPIO0_CTP_SEL          0x06    /* switch CTP connection: EVE_DISP:1 and CTP_SEL:0 - connected to EVE chip, EVE_DISP:1 and CTP_SEL:1 - connected to fe310 chip, EVE_DISP:0 and CTP_SEL:0 - connected to app module */
-#define EGPIO0_CTP_INT          0x07    /* CTP interrupt */
-
-#define EGPIO1_MIC_DIS          0x00    /* microphone disable */
-#define EGPIO1_HP_AMP_CS        0x01    /* SPI chip select for headphone amplifier (pcm1770) */
-#define EGPIO1_MIC_SEL          0x02    /* switch mic connection: 0 - connected to app module, 1 - connected to fe310 chip */
-#define EGPIO1_HP_DET           0x03    /* headphone detect */
-#define EGPIO1_USR0             0x04    /* user IO */
-#define EGPIO1_USR1             0x05
-#define EGPIO1_USR2             0x06
-#define EGPIO1_USR3             0x07
-
-#define EGPIO_CHIP_ID0          0x00
-#define EGPIO_CHIP_ID1          0x10
-
-#define EGPIO_PIN_EVE_INT       (EGPIO_CHIP_ID0 | EGPIO0_EVE_INT)
-#define EGPIO_PIN_SDCARD_DET    (EGPIO_CHIP_ID0 | EGPIO0_SDCARD_DET)
-#define EGPIO_PIN_EXP_IO0       (EGPIO_CHIP_ID0 | EGPIO0_EXP_IO0)
-#define EGPIO_PIN_EXP_IO1       (EGPIO_CHIP_ID0 | EGPIO0_EXP_IO1)
-#define EGPIO_PIN_BTN_WAKE      (EGPIO_CHIP_ID0 | EGPIO0_BTN_WAKE)
-#define EGPIO_PIN_BAT_INT       (EGPIO_CHIP_ID0 | EGPIO0_BAT_INT)
-#define EGPIO_PIN_CTP_SEL       (EGPIO_CHIP_ID0 | EGPIO0_CTP_SEL)
-#define EGPIO_PIN_CTP_INT       (EGPIO_CHIP_ID0 | EGPIO0_CTP_INT)
-
-#define EGPIO_PIN_MIC_DIS       (EGPIO_CHIP_ID1 | EGPIO1_MIC_DIS)
-#define EGPIO_PIN_HP_AMP_CS     (EGPIO_CHIP_ID1 | EGPIO1_HP_AMP_CS)
-#define EGPIO_PIN_MIC_SEL       (EGPIO_CHIP_ID1 | EGPIO1_MIC_SEL)
-#define EGPIO_PIN_HP_DET        (EGPIO_CHIP_ID1 | EGPIO1_HP_DET)
-#define EGPIO_PIN_USR0          (EGPIO_CHIP_ID1 | EGPIO1_USR0)
-#define EGPIO_PIN_USR1          (EGPIO_CHIP_ID1 | EGPIO1_USR1)
-#define EGPIO_PIN_USR2          (EGPIO_CHIP_ID1 | EGPIO1_USR2)
-#define EGPIO_PIN_USR3          (EGPIO_CHIP_ID1 | EGPIO1_USR3)
+#define EGPIO_ETYPE_INT         1
+#define EGPIO_ETYPE_INT_CTP     2
+#define EGPIO_ETYPE_INT_EVE     3
+
+#define EGPIO_INT_TYPE_BAT      1
+#define EGPIO_INT_TYPE_WAKE     2
+#define EGPIO_INT_TYPE_SDCARD   3
+#define EGPIO_INT_TYPE_MUTE     4
+#define EGPIO_INT_TYPE_HP       5
+
+#define EGPIO_CHIP_FXL0         0x00
+#define EGPIO_CHIP_FXL1         0x01
+#define EGPIO_CHIP_EVE          0x02
+
+#define EGPIO_MAX_CHIP          3
 
 #define EGPIO_PIN_MASK          0x07
-#define EGPIO_PIN_MASK_CHIP_ID  0x10
+#define EGPIO_PIN_MASK_CHIP     0x30
+
+#define EGPIO_PIN2BIT(X)        (1 << ((X) & EGPIO_PIN_MASK))
+#define EGPIO_PIN2CHIP(X)       (((X) & EGPIO_PIN_MASK_CHIP) >> 4)
+#define EGPIO_PIN(C,P)          (((C) << 4) | (P))
+
+#define EGPIO0_PIN_EVE_INT      0x00    /* EVE interrrupt */
+#define EGPIO0_PIN_SDCARD_DET   0x01    /* SD Card detect */
+#define EGPIO0_PIN_EXP_IO0      0x02    /* expansion io 0 */
+#define EGPIO0_PIN_EXP_IO1      0x03    /* expansion io 1 */
+#define EGPIO0_PIN_BTN_WAKE     0x04    /* wake button */
+#define EGPIO0_PIN_BAT_INT      0x05    /* battery charger IC inetrrupt */
+#define EGPIO0_PIN_CTP_SEL      0x06    /* switch CTP connection: EVE_DISP:1 and CTP_SEL:0 - connected to EVE chip, EVE_DISP:X and CTP_SEL:1 - connected to fe310 chip, EVE_DISP:0 and CTP_SEL:0 - connected to app module */
+#define EGPIO0_PIN_CTP_INT      0x07    /* CTP interrupt */
+
+#define EGPIO1_PIN_MIC_MUTE     0x00    /* microphone disable */
+#define EGPIO1_PIN_HPAMP_CS     0x01    /* SPI chip select for headphone amplifier (pcm1770) */
+#define EGPIO1_PIN_AUDIO_SEL    0x02    /* switch audio connection: 0 - connected to app module, 1 - connected to fe310 chip (only when i2s is off) */
+#define EGPIO1_PIN_HP_NDET      0x03    /* headphone detect: 0 - inserted, 1 - not inserted */
+#define EGPIO1_PIN_USR0         0x04    /* user IO */
+#define EGPIO1_PIN_USR1         0x05
+#define EGPIO1_PIN_USR2         0x06
+#define EGPIO1_PIN_USR3         0x07
+
+#define EGPIOE_PIN_DISP         0x07    /* EVE DISP GPIO */
+
+#define EGPIO_PIN_ALT           0x08
+
+#define EGPIO_PIN_EVE_INT       EGPIO_PIN(EGPIO_CHIP_FXL0, EGPIO0_PIN_EVE_INT)
+#define EGPIO_PIN_SDCARD_DET    EGPIO_PIN(EGPIO_CHIP_FXL0, EGPIO0_PIN_SDCARD_DET)
+#define EGPIO_PIN_EXP_IO0       EGPIO_PIN(EGPIO_CHIP_FXL0, EGPIO0_PIN_EXP_IO0)
+#define EGPIO_PIN_EXP_IO1       EGPIO_PIN(EGPIO_CHIP_FXL0, EGPIO0_PIN_EXP_IO1)
+#define EGPIO_PIN_BTN_WAKE      EGPIO_PIN(EGPIO_CHIP_FXL0, EGPIO0_PIN_BTN_WAKE)
+#define EGPIO_PIN_BAT_INT       EGPIO_PIN(EGPIO_CHIP_FXL0, EGPIO0_PIN_BAT_INT)
+#define EGPIO_PIN_CTP_SEL       EGPIO_PIN(EGPIO_CHIP_FXL0, EGPIO0_PIN_CTP_SEL)
+#define EGPIO_PIN_CTP_INT       EGPIO_PIN(EGPIO_CHIP_FXL0, EGPIO0_PIN_CTP_INT)
+
+#define EGPIO_PIN_MIC_MUTE      EGPIO_PIN(EGPIO_CHIP_FXL1, EGPIO1_PIN_MIC_MUTE)
+#define EGPIO_PIN_HPAMP_CS      EGPIO_PIN(EGPIO_CHIP_FXL1, EGPIO1_PIN_HPAMP_CS)
+#define EGPIO_PIN_AUDIO_SEL     EGPIO_PIN(EGPIO_CHIP_FXL1, EGPIO1_PIN_AUDIO_SEL)
+#define EGPIO_PIN_HP_NDET       EGPIO_PIN(EGPIO_CHIP_FXL1, EGPIO1_PIN_HP_NDET)
+#define EGPIO_PIN_USR0          EGPIO_PIN(EGPIO_CHIP_FXL1, EGPIO1_PIN_USR0)
+#define EGPIO_PIN_USR1          EGPIO_PIN(EGPIO_CHIP_FXL1, EGPIO1_PIN_USR1)
+#define EGPIO_PIN_USR2          EGPIO_PIN(EGPIO_CHIP_FXL1, EGPIO1_PIN_USR2)
+#define EGPIO_PIN_USR3          EGPIO_PIN(EGPIO_CHIP_FXL1, EGPIO1_PIN_USR3)
+
+/* EVE pins defined in eve.h */
+#define EGPIO_PIN_USR4          EGPIO_PIN(EGPIO_CHIP_EVE, EVE_GPIO_USR)
+#define EGPIO_PIN_EVEAUDIO_DIS  EGPIO_PIN(EGPIO_CHIP_EVE, EVE_GPIO_EVEAUDIO_DIS)
+#define EGPIO_PIN_LSGAIN_SEL    EGPIO_PIN(EGPIO_CHIP_EVE, EVE_GPIO_LSGAIN_SEL | EGPIO_PIN_ALT)
+#define EGPIO_PIN_LCD_EN        EGPIO_PIN(EGPIO_CHIP_EVE, EVE_GPIO_LCD_EN)
+#define EGPIO_PIN_CAM_EN        EGPIO_PIN(EGPIO_CHIP_EVE, EVE_GPIO_CAM_EN)
+#define EGPIO_PIN_DISP_SEL      EGPIO_PIN(EGPIO_CHIP_EVE, EGPIOE_PIN_DISP)
+
+#define EGPIO_BIT_EVE_INT       EGPIO_PIN2BIT(EGPIO0_PIN_EVE_INT)
+#define EGPIO_BIT_SDCARD_DET    EGPIO_PIN2BIT(EGPIO0_PIN_SDCARD_DET)
+#define EGPIO_BIT_EXP_IO0       EGPIO_PIN2BIT(EGPIO0_PIN_EXP_IO0)
+#define EGPIO_BIT_EXP_IO1       EGPIO_PIN2BIT(EGPIO0_PIN_EXP_IO1)
+#define EGPIO_BIT_BTN_WAKE      EGPIO_PIN2BIT(EGPIO0_PIN_BTN_WAKE)
+#define EGPIO_BIT_BAT_INT       EGPIO_PIN2BIT(EGPIO0_PIN_BAT_INT)
+#define EGPIO_BIT_CTP_SEL       EGPIO_PIN2BIT(EGPIO0_PIN_CTP_SEL)
+#define EGPIO_BIT_CTP_INT       EGPIO_PIN2BIT(EGPIO0_PIN_CTP_INT)
+
+#define EGPIO_BIT_MIC_MUTE      EGPIO_PIN2BIT(EGPIO1_PIN_MIC_MUTE)
+#define EGPIO_BIT_HPAMP_CS      EGPIO_PIN2BIT(EGPIO1_PIN_HPAMP_CS)
+#define EGPIO_BIT_AUDIO_SEL     EGPIO_PIN2BIT(EGPIO1_PIN_AUDIO_SEL)
+#define EGPIO_BIT_HP_NDET       EGPIO_PIN2BIT(EGPIO1_PIN_HP_NDET)
+#define EGPIO_BIT_USR0          EGPIO_PIN2BIT(EGPIO1_PIN_USR0)
+#define EGPIO_BIT_USR1          EGPIO_PIN2BIT(EGPIO1_PIN_USR1)
+#define EGPIO_BIT_USR2          EGPIO_PIN2BIT(EGPIO1_PIN_USR2)
+#define EGPIO_BIT_USR3          EGPIO_PIN2BIT(EGPIO1_PIN_USR3)
+
+typedef void (*eos_egpio_intr_handler_t) (uint8_t type, int data0, int data1);
+typedef int (*eos_egpio_ext_handler_t) (void);
+
+int eos_egpio_init(void);
+int eos_egpio_run(void);
+void eos_egpio_eve_set(uint16_t gpio_reg);
+int _eos_egpio_intr_set(int i2s_running, int app_running);
+int eos_egpio_intr_set(void);
+int eos_egpio_intr_enable(void);
+int eos_egpio_intr_disable(void);
+
+void eos_egpio_set_intr_handler(eos_egpio_intr_handler_t handler);
+void eos_egpio_set_ext_handler(eos_egpio_ext_handler_t handler);
+
+int eos_egpio_fxl_get_pin(uint8_t reg, uint8_t pin, uint8_t *val);
+int eos_egpio_fxl_set_pin(uint8_t reg, uint8_t pin, uint8_t val);
+
+int _eos_egpio_get_val(uint8_t pin);
+int _eos_egpio_set_val(uint8_t pin, int val);
+int eos_egpio_get_val(uint8_t pin);
+int eos_egpio_set_val(uint8_t pin, int val);
 
-int eos_egpio_pin_get(uint8_t reg, uint8_t pin, uint8_t *val);
-int eos_egpio_pin_set(uint8_t reg, uint8_t pin, uint8_t val);
+int eos_egpio_i2s_start(void);
+int eos_egpio_i2s_stop(void);
diff --git a/fw/fe310/eos/dev/eve.c b/fw/fe310/eos/dev/eve.c
index dd72b0f..dad7dfe 100644
--- a/fw/fe310/eos/dev/eve.c
+++ b/fw/fe310/eos/dev/eve.c
@@ -1,153 +1,192 @@
 #include <stdlib.h>
-#include <stdio.h>
-
-#include "platform.h"
+#include <stdint.h>
 
 #include "eos.h"
 #include "event.h"
 
-#include "board.h"
-
-#include "soc/interrupt.h"
 #include "soc/pwr.h"
-#include "soc/i2s.h"
+#include "soc/timer.h"
 
 #include "eve/eve.h"
 #include "eve/eve_touch_engine.h"
 
+#include "egpio.h"
+#include "spi.h"
+#include "aon.h"
+#include "pwr.h"
+
 #include "eve.h"
 
-#define EVE_POLL_INTERVAL   2
+#ifdef EOS_DEBUG
+#include <stdio.h>
+#endif
 
 static void handle_time(unsigned char type) {
-    eve_select();
-    eve_handle_time();
-    eve_deselect();
-}
+    int rv;
 
-static void handle_poll(unsigned char type) {
-    if (eos_eve_intr_enabled()) return;
+    rv = eve_select();
+    if (rv) return;
 
-    eve_select();
-    eve_handle_intr();
+    eve_handle_time();
     eve_deselect();
 }
 
-static void handle_intr_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
-    if (!eos_eve_intr_enabled()) return;
+int eos_eve_handle_intr(void) {
+    uint16_t intr_flags;
+    int rv;
+
+    rv = eve_select();
+    if (rv) return 0;
 
-    eve_select();
-    eve_handle_intr();
+    intr_flags = eve_handle_intr();
     eve_deselect();
 
-    GPIO_REG(GPIO_LOW_IE) |= (1 << EVE_PIN_INTR);
+    if (intr_flags == 0) return 0;
+    return 1;
 }
 
-static void handle_intr(void) {
-    GPIO_REG(GPIO_LOW_IE) &= ~(1 << EVE_PIN_INTR);
-    GPIO_REG(GPIO_LOW_IP) = (1 << EVE_PIN_INTR);
-    eos_evtq_push_isr(EOS_EVT_EVE | EVE_ETYPE_INTR, NULL, 0);
-}
+int eos_eve_init(void) {
+    uint8_t wakeup_cause;
+    uint16_t gpio_reg;
+    int rst, rv;
 
-int eos_eve_init(uint8_t wakeup_cause) {
-    int rst = (wakeup_cause == EOS_PWR_WAKE_RST);
-    int rv = EVE_OK;
+    rv = eve_select();
+    if (rv) return rv;
 
-    eve_select();
+    wakeup_cause = eos_pwr_wakeup_cause();
+    rst = (wakeup_cause == EOS_PWR_WAKE_RST);
     if (rst) {
         rv = eve_init();
-        if (!rv) {
-            eve_gpio_set_dir(EVE_GPIO_DIR);
-            eve_touch_init_engine();
-        }
+        if (rv) goto eve_init_fin;
+
+        eve_gpio_write(EVE_GPIO_DEFAULT);
+        eve_gpio_write_dir(EVE_GPIO_DIR);
+        eve_touch_init_engine(eos_egpio_get_val(EGPIO_PIN_CTP_SEL) ? EVE_TOUCH_ENGINE_HOST : EVE_TOUCH_ENGINE_GOODIX);
+        gpio_reg = EVE_GPIO_DEFAULT;
     } else {
+        uint8_t pwr_state;
+
+        pwr_state = eos_aon_load4eve();
+        eve_pwr_set_state(pwr_state);
+
         eve_activate();
+        gpio_reg = eve_gpio_read();
+        eve_cmd_set_offset();
+        if (gpio_reg & EVE_GPIO_DISP) {
+            eve_pwr_set_state(EVE_PSTATE_ACTIVE);
+        }
+        eve_deactivate();
     }
+
+eve_init_fin:
     eve_deselect();
 
-    if (rv) return EOS_ERR;
+    if (rv) return rv;
 
-    eve_touch_init();
+    eos_egpio_eve_set(gpio_reg);
 
-    eos_evtq_set_handler(EOS_EVT_EVE, handle_intr_evt);
+    eve_touch_init();
     eos_timer_set_handler(EOS_TIMER_ETYPE_UI, handle_time);
-    eos_intr_set_handler(INT_GPIO_BASE + EVE_PIN_INTR, handle_intr);
-    eos_intr_set_priority(INT_GPIO_BASE + EVE_PIN_INTR, IRQ_PRIORITY_EVE);
 
     return EOS_OK;
 }
 
-void eos_eve_calibrate(void) {
+int eos_eve_run(void) {
+    int rv;
+
+    if (eve_pwr_state() != EVE_PSTATE_ACTIVE) return EOS_ERR_BUSY;
+
+    rv = eve_select();
+    if (rv) return rv;
+
+    eve_touch_intr_enable();
+    eve_touch_start();
+    eve_intr_enable();
+    eve_clk_start();
+    eve_deselect();
+
+    return EOS_OK;
+}
+
+int eos_eve_sleep(void) {
+    int rv;
+
+    rv = eve_select();
+    if (rv) return rv;
+
+    eos_aon_save4eve(eve_pwr_state());
+    eve_clk_stop();
+    eve_intr_disable();
+    eve_touch_stop();
+    eve_touch_intr_disable();
+    eve_pwr_sleep();
+    eve_deselect();
+
+    return EOS_OK;
+}
+
+void eve_calibrate(void) {
+    int rv, d;
+#ifdef EOS_DEBUG
     uint32_t matrix[6];
-    int r;
+#endif
 
-    eve_select();
+    if (!eve_selected()) {
+#ifdef EOS_DEBUG
+        printf("EVE CALIBRATE: NOT SELECTED\n");
+#endif
+        return;
+    }
 
-    eve_brightness(0x40);
     eve_touch_set_extended(0);
 
     eve_cmd(CMD_TEXT, "hhhhs", EVE_HSIZE/2, EVE_VSIZE/2, 27, EVE_OPT_CENTER, "Please tap on the dot.");
     eve_cmd(CMD_CALIBRATE, "w", 0);
     eve_cmd_exec(0);
 
+    rv = EOS_OK;
     do {
-        r = eve_cmd_done();
-        if (r < 0) break;
+        d = eve_cmd_done();
+        if (d < 0) {
+            rv = d;
+            break;
+        }
         eve_deselect();
         eos_evtq_exec();
-        eve_select();
-    } while (!r);
+        rv = eve_select();
+        if (rv) {
+#ifdef EOS_DEBUG
+            printf("EVE CALIBRATE ERR:%d\n", rv);
+#endif
+            return;
+        }
+    } while (!d);
 
     eve_touch_set_extended(1);
-    eve_brightness(0);
 
-    eve_touch_get_matrix(matrix);
-    eve_deselect();
+#ifdef EOS_DEBUG
+    if (rv) {
+        printf("EVE CALIBRATE ERR:%d\n", rv);
+        return;
+    }
 
+    eve_touch_get_matrix(matrix);
     printf("TOUCH MATRIX:\n");
     printf("uint32_t touch_matrix[6] = {0x%x,0x%x,0x%x,0x%x,0x%x,0x%x}\n", matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
+#endif
 }
 
-void eos_eve_set_tmatrix(const uint32_t *matrix) {
-    eve_select();
-    eve_touch_set_matrix(matrix);
-    eve_deselect();
-}
-
-int eos_eve_run(uint8_t wakeup_cause) {
-    eve_select();
-    eve_touch_start();
-    eve_intr_enable();
-    eve_clk_start();
-    eve_deselect();
-
-    eos_eve_intr_enable();
-    return EOS_OK;
-}
+int eve_select(void) {
+    int rv;
 
-void eos_eve_intr_enable(void) {
-    GPIO_REG(GPIO_INPUT_EN)     |=  (1 << EVE_PIN_INTR);
-    GPIO_REG(GPIO_LOW_IE)       |=  (1 << EVE_PIN_INTR);
-
-    eos_intr_enable(INT_GPIO_BASE + EVE_PIN_INTR);
-    eos_timer_set_handler(EOS_TIMER_ETYPE_EVE, NULL);
+    rv = eos_spi_select(EOS_SPI_DEV_EVE);
+    return rv;
 }
 
-void eos_eve_intr_disable(void) {
-    eos_intr_disable(INT_GPIO_BASE + EVE_PIN_INTR);
-
-    GPIO_REG(GPIO_LOW_IE)       &= ~(1 << EVE_PIN_INTR);
-    GPIO_REG(GPIO_INPUT_EN)     &= ~(1 << EVE_PIN_INTR);
-    eos_timer_set_handler(EOS_TIMER_ETYPE_EVE, handle_poll);
+void eve_deselect(void) {
+    eos_spi_deselect();
 }
 
-int eos_eve_intr_enabled(void) {
-    return !!(GPIO_REG(GPIO_INPUT_EN) & (1 << EVE_PIN_INTR));
-}
-
-void eos_eve_poll(void) {
-    if (eos_eve_intr_enabled()) return;
-    if (eos_timer_get(EOS_TIMER_ETYPE_EVE) != EOS_TIMER_NONE) return;
-
-    eos_timer_set(EOS_TIMER_ETYPE_EVE, EVE_POLL_INTERVAL);
+int eve_selected(void) {
+    return (eos_spi_dev() == EOS_SPI_DEV_EVE);
 }
diff --git a/fw/fe310/eos/dev/eve.h b/fw/fe310/eos/dev/eve.h
index 1317bec..441cd5a 100644
--- a/fw/fe310/eos/dev/eve.h
+++ b/fw/fe310/eos/dev/eve.h
@@ -1,17 +1,24 @@
 #include <stdint.h>
 
-#define EVE_GPIO_DIR            0xf
+#define EVE_GPIO_DIR            0x800f
+#define EVE_GPIO_DEFAULT        0x2     /* EVEAUDIO_DIS */
+#define EVE_GPIO_MASK           0x800f
 
-#define EVE_GPIO_CAM            0
-#define EVE_GPIO_LCD_EN         1
-#define EVE_GPIO_GAIN           2
-#define EVE_GPIO_HAPT           3
+#define EVE_GPIO_USR            0
+#define EVE_GPIO_EVEAUDIO_DIS   1       /* only when lspk is off */
+#define EVE_GPIO_LSGAIN_SEL     1       /* only when lspk is on */
+#define EVE_GPIO_LCD_EN         2
+#define EVE_GPIO_CAM_EN         3
+#define EVE_GPIO_DISP           15
 
-int eos_eve_init(uint8_t wakeup_cause);
-void eos_eve_calibrate(void);
-void eos_eve_set_tmatrix(const uint32_t *matrix);
-int eos_eve_run(uint8_t wakeup_cause);
-void eos_eve_intr_enable(void);
-void eos_eve_intr_disable(void);
-int eos_eve_intr_enabled(void);
-void eos_eve_poll(void);
+int eos_eve_handle_intr(void);
+
+int eos_eve_init(void);
+int eos_eve_run(void);
+int eos_eve_sleep(void);
+int eos_eve_wake(void);
+
+void eve_calibrate(void);
+int eve_select(void);
+void eve_deselect(void);
+int eve_selected(void);
diff --git a/fw/fe310/eos/dev/hpamp.c b/fw/fe310/eos/dev/hpamp.c
new file mode 100644
index 0000000..10a95fa
--- /dev/null
+++ b/fw/fe310/eos/dev/hpamp.c
@@ -0,0 +1,22 @@
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "eos.h"
+
+#include "soc/spi.h"
+#include "spi.h"
+
+#include "drv/pcm1770.h"
+#include "hpamp.h"
+
+int eos_hpamp_init(void) {
+    int rv;
+
+    rv = eos_spi_select(EOS_SPI_DEV_HPAMP);
+    if (rv) return rv;
+
+    pcm1770_reg_write(0x03, 0x01);
+    eos_spi_deselect();
+
+    return EOS_OK;
+}
diff --git a/fw/fe310/eos/dev/hpamp.h b/fw/fe310/eos/dev/hpamp.h
new file mode 100644
index 0000000..07157bb
--- /dev/null
+++ b/fw/fe310/eos/dev/hpamp.h
@@ -0,0 +1,3 @@
+#include <stdint.h>
+
+int eos_hpamp_init(void);
diff --git a/fw/fe310/eos/dev/lcd.c b/fw/fe310/eos/dev/lcd.c
index 59215dc..6c005b9 100644
--- a/fw/fe310/eos/dev/lcd.c
+++ b/fw/fe310/eos/dev/lcd.c
@@ -2,48 +2,47 @@
 #include <stdint.h>
 
 #include "platform.h"
+#include "board.h"
 
 #include "eos.h"
 
-#include "board.h"
-
-#include "soc/timer.h"
+#include "soc/pwr.h"
 #include "soc/i2s.h"
+#include "soc/timer.h"
+
 #include "eve/eve.h"
 
+#include "egpio.h"
+#include "spi.h"
 #include "eve.h"
-#include "gt911.h"
-#include "ili9806e.h"
+#include "pwr.h"
 
+#include "drv/ili9806e.h"
 #include "lcd.h"
 
 static int lcd_enable(void) {
     int rv;
 
-    rv = eos_spi_select(EOS_SPI_DEV_EVE);
-    if (rv) return rv;
-
-    eve_gpio_set(EVE_GPIO_LCD_EN, 1);
-    eos_spi_deselect();
+    if (eos_i2s_running() || !eos_egpio_get_val(EGPIO_PIN_DISP_SEL)) return EOS_ERR_BUSY;
 
-    return EOS_OK;
+    rv = eos_egpio_set_val(EGPIO_PIN_LCD_EN, 1);
+    return rv;
 }
 
 static int lcd_disable(void) {
     int rv;
 
-    rv = eos_spi_select(EOS_SPI_DEV_EVE);
-    if (rv) return rv;
-
-    eve_gpio_set(EVE_GPIO_LCD_EN, 0);
-    eos_spi_deselect();
+    if (eos_i2s_running() || !eos_egpio_get_val(EGPIO_PIN_DISP_SEL)) return EOS_ERR_BUSY;
 
-    return EOS_OK;
+    rv = eos_egpio_set_val(EGPIO_PIN_LCD_EN, 0);
+    return rv;
 }
 
 static int lcd_select(void) {
     int rv;
 
+    if (eos_i2s_running() || !eos_egpio_get_val(EGPIO_PIN_DISP_SEL)) return EOS_ERR_BUSY;
+
     GPIO_REG(GPIO_OUTPUT_XOR)   |=  (1 << SPI_CSPIN_LCD);
     GPIO_REG(GPIO_OUTPUT_VAL)   |=  (1 << SPI_CSPIN_LCD);
     GPIO_REG(GPIO_OUTPUT_EN)    |=  (1 << SPI_CSPIN_LCD);
@@ -72,7 +71,7 @@ static int lcd_init(void) {
     rv = lcd_enable();
     if (rv) return rv;
 
-    eos_time_sleep(200);
+    eos_sleep(200);
 
     rv = lcd_select();
     if (rv) {
@@ -80,7 +79,7 @@ static int lcd_init(void) {
         return rv;
     }
 
-    rv = eos_ili9806e_init();
+    rv = ili9806e_init();
     if (rv == EOS_ERR_NOTFOUND) eve_lcd_absent();
     lcd_deselect();
 
@@ -94,51 +93,38 @@ static int lcd_sleep(void) {
     rv = lcd_select();
     if (rv) return rv;
 
-    eos_ili9806e_sleep();
+    ili9806e_sleep();
     lcd_deselect();
 
     rv = lcd_disable();
-    if (rv) return rv;
-
-    return EOS_OK;
+    return rv;
 }
 
-int eos_lcd_init(uint8_t wakeup_cause) {
-    int rv;
+int eos_lcd_init(void) {
+    uint8_t wakeup_cause;
+    int rv, rst;
 
-    rv = lcd_init();
-    if (rv) return rv;
-
-    rv = eos_gt911_init(wakeup_cause);
-    if (rv) return rv;
+    wakeup_cause = eos_pwr_wakeup_cause();
+    rst = (wakeup_cause == EOS_PWR_WAKE_RST);
+    if (rst) {
+        rv = lcd_init();
+    } else {
+        rv = eos_lcd_wake();
+    }
 
-    return EOS_OK;
+    return rv;
 }
 
 int eos_lcd_sleep(void) {
     int rv;
 
-    if (eos_i2s_running()) return EOS_ERR_BUSY;
-
-    /* There is a problem with GT911 and sleep */
-    // eos_gt911_sleep();
-
     rv = lcd_sleep();
-    if (rv) return rv;
-
-    return EOS_OK;
+    return rv;
 }
 
 int eos_lcd_wake(void) {
     int rv;
 
-    if (eos_i2s_running()) return EOS_ERR_BUSY;
-
     rv = lcd_init();
-    if (rv) return rv;
-
-    /* There is a problem with GT911 and sleep */
-    // eos_gt911_wake();
-
-    return EOS_OK;
+    return rv;
 }
diff --git a/fw/fe310/eos/dev/lcd.h b/fw/fe310/eos/dev/lcd.h
index 7ca2f7d..fafe2b4 100644
--- a/fw/fe310/eos/dev/lcd.h
+++ b/fw/fe310/eos/dev/lcd.h
@@ -1,5 +1,5 @@
 #include <stdint.h>
 
-int eos_lcd_init(uint8_t wakeup_cause);
+int eos_lcd_init(void);
 int eos_lcd_sleep(void);
 int eos_lcd_wake(void);
diff --git a/fw/fe310/eos/dev/spi.c b/fw/fe310/eos/dev/spi.c
index 12549fc..fef00e1 100644
--- a/fw/fe310/eos/dev/spi.c
+++ b/fw/fe310/eos/dev/spi.c
@@ -12,72 +12,112 @@
 
 #include "soc/interrupt.h"
 #include "soc/spi.h"
+#include "soc/spi_priv.h"
 
 #include "net.h"
+#include "egpio.h"
 
 #include "spi.h"
 #include "spi_cfg.h"
 
-static uint8_t spi_dev;
-static uint8_t spi_lock;
+#ifdef EOS_DEBUG
+#include <stdio.h>
+#endif
+
+static unsigned char spi_dstack[EOS_SPI_MAX_DSTACK];
+static unsigned char spi_dstack_len;
 static uint16_t spi_div[EOS_SPI_MAX_DEV];
 
-int eos_spi_dev_init(uint8_t wakeup_cause) {
+static uint8_t spi_dev(void) {
+    return spi_dstack_len ? spi_dstack[spi_dstack_len - 1] : EOS_SPI_DEV_NET;
+}
+
+static void spi_stop(unsigned char dev) {
+    if (dev == EOS_SPI_DEV_NET) {
+        eos_net_stop();
+    } else if (spi_cfg[dev].flags & SPI_DEV_FLAG_9BIT) {
+        eos_spi_enable();
+    } else {
+        eos_spi_stop();
+    }
+}
+
+static void spi_start(unsigned char dev) {
+    if (dev == EOS_SPI_DEV_NET) {
+        eos_net_start();
+    } else if (spi_cfg[dev].flags & SPI_DEV_FLAG_9BIT) {
+        eos_spi_configure(spi_div[dev], spi_cfg[dev].csid, spi_cfg[dev].cspin, spi_cfg[dev].evt);
+        eos_spi_disable();
+    } else {
+        eos_spi_start(spi_div[dev], spi_cfg[dev].csid, spi_cfg[dev].cspin, spi_cfg[dev].evt);
+    }
+}
+
+int eos_spi_dev_init(void) {
     int i;
 
     for (i=0; i<EOS_SPI_MAX_DEV; i++) {
         spi_div[i] = spi_cfg[i].div;
-        if (!(spi_cfg[i].flags & SPI_DEV_FLAG_CSFLOAT) && (spi_cfg[i].cspin != -1)) {
-            GPIO_REG(GPIO_OUTPUT_VAL)   |=  (1 << spi_cfg[i].cspin);
-            GPIO_REG(GPIO_OUTPUT_EN)    |=  (1 << spi_cfg[i].cspin);
-        }
+    }
+
+    for (i=0; i<EOS_SPI_MAX_DSTACK; i++) {
+        spi_dstack[i] = 0xff;
     }
 
     return EOS_OK;
 }
 
 int eos_spi_select(unsigned char dev) {
-    if (spi_lock) return EOS_ERR_BUSY;
+    int rv;
+    int dsel;
 
-    if (spi_cfg[spi_dev].flags & SPI_DEV_FLAG_9BIT) {
-        eos_spi_enable();
-    } else {
-        if (spi_dev == EOS_SPI_DEV_NET) {
-            eos_net_stop();
-        } else {
-            eos_spi_stop();
-        }
+    if (eos_spi_cs_get()) rv = EOS_ERR_BUSY;
+    if (!rv && (spi_dstack_len == EOS_SPI_MAX_DSTACK)) rv = EOS_ERR_FULL;
+
+    if (rv) {
+#ifdef EOS_DEBUG
+        printf("SPI SELECT DEV:%d ERR:%d\n", dev, rv);
+#endif
+        return rv;
     }
 
-    spi_dev = dev;
-    if (spi_cfg[dev].flags & SPI_DEV_FLAG_9BIT) {
-        eos_spi_configure(spi_div[dev], spi_cfg[dev].csid, spi_cfg[dev].cspin, spi_cfg[dev].evt);
-        eos_spi_disable();
-    } else {
-        if (dev == EOS_SPI_DEV_NET) {
-            eos_net_start();
-        } else {
-            eos_spi_start(spi_div[dev], spi_cfg[dev].csid, spi_cfg[dev].cspin, spi_cfg[dev].evt);
-        }
+    dsel = 1;
+    if (spi_dev() == dev) {
+        dev |= EOS_SPI_DEV_FLAG_NDSEL;
+        dsel = 0;
     }
 
+    if (dsel) spi_stop(spi_dev());
+
+    spi_dstack[spi_dstack_len] = dev;
+    spi_dstack_len++;
+
+    if (dsel) spi_start(dev);
+
     return EOS_OK;
 }
 
-int eos_spi_deselect(void) {
-    if (spi_lock) return EOS_ERR_BUSY;
-    if (spi_dev == EOS_SPI_DEV_NET) return EOS_ERR;
+void eos_spi_deselect(void) {
+    int rv;
+    int dsel;
 
-    if (spi_cfg[spi_dev].flags & SPI_DEV_FLAG_9BIT) {
-        eos_spi_enable();
-    } else {
-        eos_spi_stop();
+    if (eos_spi_cs_get()) rv = EOS_ERR_BUSY;
+    if (!rv && (spi_dstack_len == 0)) rv = EOS_ERR_EMPTY;
+
+    if (rv) {
+#ifdef EOS_DEBUG
+        printf("SPI DESELECT ERR:%d\n", rv);
+#endif
+        return;
     }
 
-    spi_dev = EOS_SPI_DEV_NET;
-    eos_net_start();
+    dsel = !(spi_dev() & EOS_SPI_DEV_FLAG_NDSEL);
+    if (dsel) spi_stop(spi_dev());
 
-    return EOS_OK;
+    spi_dstack_len--;
+    spi_dstack[spi_dstack_len] = 0xff;
+
+    if (dsel) spi_start(spi_dev());
 }
 
 void eos_spi_dev_configure(unsigned char dev) {
@@ -85,7 +125,7 @@ void eos_spi_dev_configure(unsigned char dev) {
 }
 
 uint8_t eos_spi_dev(void) {
-    return spi_dev;
+    return spi_dev();
 }
 
 uint16_t eos_spi_div(unsigned char dev) {
@@ -100,14 +140,6 @@ uint8_t eos_spi_cspin(unsigned char dev) {
     return spi_cfg[dev].cspin;
 }
 
-void eos_spi_lock(void) {
-    spi_lock = 1;
-}
-
-void eos_spi_unlock(void) {
-    spi_lock = 0;
-}
-
 void eos_spi_set_div(unsigned char dev, uint16_t div) {
     spi_div[dev] = div;
 }
diff --git a/fw/fe310/eos/dev/spi.h b/fw/fe310/eos/dev/spi.h
index c899e83..29315af 100644
--- a/fw/fe310/eos/dev/spi.h
+++ b/fw/fe310/eos/dev/spi.h
@@ -4,11 +4,15 @@
 #define EOS_SPI_DEV_EVE         1
 #define EOS_SPI_DEV_SDC         2
 #define EOS_SPI_DEV_CAM         3
-#define EOS_SPI_DEV_LCD         4
+#define EOS_SPI_DEV_HPAMP       4
+#define EOS_SPI_DEV_LCD         5
 
-int eos_spi_dev_init(uint8_t wakeup_cause);
+#define EOS_SPI_MAX_DSTACK      3
+#define EOS_SPI_DEV_FLAG_NDSEL  0x80
+
+int eos_spi_dev_init(void);
 int eos_spi_select(unsigned char dev);
-int eos_spi_deselect(void);
+void eos_spi_deselect(void);
 void eos_spi_dev_configure(unsigned char dev);
 
 uint8_t eos_spi_dev(void);
@@ -16,6 +20,4 @@ uint16_t eos_spi_div(unsigned char dev);
 uint8_t eos_spi_csid(unsigned char dev);
 uint8_t eos_spi_cspin(unsigned char dev);
 
-void eos_spi_lock(void);
-void eos_spi_unlock(void);
 void eos_spi_set_div(unsigned char dev, uint16_t div);
diff --git a/fw/fe310/eos/dev/spi_cfg.h b/fw/fe310/eos/dev/spi_cfg.h
index 6a5d7b4..6ef92aa 100644
--- a/fw/fe310/eos/dev/spi_cfg.h
+++ b/fw/fe310/eos/dev/spi_cfg.h
@@ -1,17 +1,16 @@
 #include <stdint.h>
 
-#define EOS_SPI_MAX_DEV         5
-
 typedef struct {
     uint16_t div;
-    int8_t csid;
-    int8_t cspin;
+    uint8_t csid;
+    uint8_t cspin;
     uint8_t flags;
     unsigned char evt;
 } SPIConfig;
 
-#define SPI_DEV_FLAG_9BIT       0x1
-#define SPI_DEV_FLAG_CSFLOAT    0x2
+#define SPI_DEV_FLAG_9BIT       0x01
+
+#define EOS_SPI_MAX_DEV         6
 
 static const SPIConfig spi_cfg[EOS_SPI_MAX_DEV] = {
     {   // DEV_NET
@@ -42,11 +41,18 @@ static const SPIConfig spi_cfg[EOS_SPI_MAX_DEV] = {
         .flags = 0,
         .evt = EOS_SPI_EVT_CAM,
     },
+    {   // DEV_HPAMP
+        .div = SPI_DIV_HPAMP,
+        .csid = SPI_CSID_HPAMP,
+        .cspin = SPI_CSPIN_HPAMP,
+        .flags = 0,
+        .evt = 0,
+    },
     {   // DEV_LCD 9bit spi
-        .div = 0,
-        .csid = -1,
+        .div = SPI_DIV_LCD,
+        .csid = SPI_CSID_LCD,
         .cspin = SPI_CSPIN_LCD,
-        .flags = SPI_DEV_FLAG_9BIT | SPI_DEV_FLAG_CSFLOAT,
+        .flags = SPI_DEV_FLAG_9BIT,
         .evt = 0,
     },
 };
-- 
cgit v1.2.3