summaryrefslogtreecommitdiff
path: root/fw/fe310/eos/dev/egpio.c
diff options
context:
space:
mode:
authorUros Majstorovic <majstor@majstor.org>2025-02-16 20:17:07 +0100
committerUros Majstorovic <majstor@majstor.org>2025-02-16 20:17:07 +0100
commit2e17dd17ee9777084b2f211f08c4231dd5f8b906 (patch)
treef50ad99c62d81906082cbb28eb84d857ef7311c9 /fw/fe310/eos/dev/egpio.c
parent064631db87182694459056ceeb331506b553d0f0 (diff)
extended gpio implemented
Diffstat (limited to 'fw/fe310/eos/dev/egpio.c')
-rw-r--r--fw/fe310/eos/dev/egpio.c585
1 files changed, 575 insertions, 10 deletions
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;
+}