diff options
Diffstat (limited to 'chip/mt_scp/mt8183/audio_codec_wov.c')
-rw-r--r-- | chip/mt_scp/mt8183/audio_codec_wov.c | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/chip/mt_scp/mt8183/audio_codec_wov.c b/chip/mt_scp/mt8183/audio_codec_wov.c new file mode 100644 index 0000000000..0a4684f909 --- /dev/null +++ b/chip/mt_scp/mt8183/audio_codec_wov.c @@ -0,0 +1,106 @@ +/* + * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "audio_codec.h" +#include "hooks.h" +#include "memmap.h" +#include "registers.h" +#include "task.h" +#include "util.h" + +/* VIF FIFO irq is triggered above this level */ +#define WOV_TRIGGER_LEVEL 160 + +int audio_codec_wov_enable_notifier(void) +{ + SCP_VIF_FIFO_DATA_THRE = WOV_TRIGGER_LEVEL + 1; + SCP_VIF_FIFO_EN |= VIF_FIFO_IRQ_EN; + + task_enable_irq(SCP_IRQ_MAD_FIFO); + + return EC_SUCCESS; +} + +int audio_codec_wov_disable_notifier(void) +{ + SCP_VIF_FIFO_EN &= ~VIF_FIFO_IRQ_EN; + + task_disable_irq(SCP_IRQ_MAD_FIFO); + + return EC_SUCCESS; +} + +int audio_codec_wov_enable(void) +{ + SCP_VIF_FIFO_EN = 0; + + SCP_RXIF_CFG0 = (RXIF_CFG0_RESET_VAL & ~RXIF_RGDL2_MASK) | + RXIF_RGDL2_DMIC_16K; + SCP_RXIF_CFG1 = RXIF_CFG1_RESET_VAL; + + SCP_VIF_FIFO_EN |= VIF_FIFO_RSTN; + + return EC_SUCCESS; +} + +int audio_codec_wov_disable(void) +{ + SCP_VIF_FIFO_EN = 0; + + return EC_SUCCESS; +} + +static size_t wov_fifo_level(void) +{ + uint32_t fifo_status = SCP_VIF_FIFO_STATUS; + + if (!(fifo_status & VIF_FIFO_VALID)) + return 0; + + if (fifo_status & VIF_FIFO_FULL) + return VIF_FIFO_MAX; + + return VIF_FIFO_LEVEL(fifo_status); +} + +int32_t audio_codec_wov_read(void *buf, uint32_t count) +{ + int16_t *out = buf; + uint8_t gain = 1; + + if (IS_ENABLED(CONFIG_AUDIO_CODEC_DMIC_SOFTWARE_GAIN)) + audio_codec_dmic_get_gain_idx(0, &gain); + + count >>= 1; + + while (count-- && wov_fifo_level()) { + if (IS_ENABLED(CONFIG_AUDIO_CODEC_DMIC_SOFTWARE_GAIN)) + *out++ = audio_codec_s16_scale_and_clip( + SCP_VIF_FIFO_DATA, gain); + else + *out++ = SCP_VIF_FIFO_DATA; + } + + return (void *)out - buf; +} + +static void wov_fifo_interrupt_handler(void) +{ +#ifdef HAS_TASK_WOV + task_wake(TASK_ID_WOV); +#endif + + audio_codec_wov_disable_notifier(); + + /* Read to clear */ + SCP_VIF_FIFO_IRQ_STATUS; +} +DECLARE_IRQ(SCP_IRQ_MAD_FIFO, wov_fifo_interrupt_handler, 2); + +int audio_codec_memmap_ap_to_ec(uintptr_t ap_addr, uintptr_t *ec_addr) +{ + return memmap_ap_to_scp(ap_addr, ec_addr); +} |