int32_t I2S_Input()

in IndustrialDeviceController/Software/MT3620_IDC_RTApp/lib/I2S.c [343:456]


int32_t I2S_Input(
    I2S *handle, I2S_Format format, unsigned channels, unsigned bits, unsigned rate,
    bool (*callback)(void *data, uintptr_t size))
{
    if (!handle) {
        return ERROR_PARAMETER;
    }
    if (!handle->open) {
        return ERROR_HANDLE_CLOSED;
    }
    unsigned id = handle->id;

    bool            enable = (format != I2S_FORMAT_NONE);
    bool            tdm    = false;
    mt3620_i2s_sr_t sr     = MT3620_I2S_SR_48K;
    if (enable) {
        if (channels == 0) {
            return ERROR_PARAMETER;
        }

        switch (format) {
        case I2S_FORMAT_I2S:
            if (channels > 2) {
                return ERROR_PARAMETER;
            }
            break;

        case I2S_FORMAT_TDM:
            if ((channels > 4) || (channels % 2)) {
                return ERROR_UNSUPPORTED;
            }
            tdm = true;
            break;

        default:
            return ERROR_PARAMETER;
        }

        if (bits != 16) {
            return ERROR_UNSUPPORTED;
        }

        sr = I2S_SampleRate(rate);
        if (sr >= MT3620_I2S_SR_COUNT) {
            return ERROR_UNSUPPORTED;
        }
    }

    mt3620_i2s_global_control_t global_control = { .mask = mt3620_i2s[id]->global_control };
    if (enable) {
        global_control.ul_empty_value_en = false;
        global_control.clk_sel_in        = MT3620_I2S_CLK_SEL_EXTERNAL;
        mt3620_i2s[id]->global_control = global_control.mask;
    }

    mt3620_i2s_ul_control_t ul_control = { .mask = mt3620_i2s[id]->ul_control };
    ul_control.en = enable;
    if (enable) {
        ul_control.wlen        = MT3620_I2S_WLEN_16BIT;
        ul_control.src         = MT3620_I2S_SRC_SLAVE;
        ul_control.fmt         = (tdm ? MT3620_I2S_FMT_TDM : MT3620_I2S_FMT_I2S);
        ul_control.wsinv       = tdm;
        ul_control.sr          = sr;
        ul_control.bit_per_s   = (tdm && (channels == 4) ? 1 : 0);
        ul_control.ws_rsync    = true;  // Functional Spec recommends this be on.
        ul_control.down_rate   = false; // TODO: Figure out when this should be used.
        ul_control.msb_offset  = 0;
        ul_control.update_word = 8;
        ul_control.ch_per_s    = (tdm && (channels == 4) ? 1 : 0);
        ul_control.lr_swap     = false;
    }
    mt3620_i2s[id]->ul_control = ul_control.mask;

    if (enable) {
        // Enable DMA.
        mt3620_dma_global->ch_en_set = (1U << MT3620_I2S_DMA_RX(id));
        MT3620_DMA_FIELD_WRITE(MT3620_I2S_DMA_RX(id), start, str, false);
        mt3620_dma_con_t dma_con_rx = { .mask = mt3620_dma[MT3620_I2S_DMA_RX(id)].con };
        dma_con_rx.dir   = 1;
        dma_con_rx.iten  = true;
        dma_con_rx.dreq  = true;
        dma_con_rx.size  = (channels == 1 ? 1 : 2);
        mt3620_dma[MT3620_I2S_DMA_RX(id)].con = dma_con_rx.mask;
        mt3620_dma[MT3620_I2S_DMA_RX(id)].fixaddr = (void *)mt3620_i2s_fifo[id];
        mt3620_dma[MT3620_I2S_DMA_RX(id)].pgmaddr = (void *)I2S_Buffer[id][1];
        mt3620_dma[MT3620_I2S_DMA_RX(id)].swptr   = 0;
        mt3620_dma[MT3620_I2S_DMA_RX(id)].ffsize  = (I2S_BUFFER_SIZE >> dma_con_rx.size);
        mt3620_dma[MT3620_I2S_DMA_RX(id)].count   = ((mt3620_dma[MT3620_I2S_DMA_RX(id)].ffsize * 3) / 4);
    } else {
        MT3620_DMA_FIELD_WRITE(MT3620_I2S_DMA_RX(id), start, str, false);
        mt3620_dma_global->ch_en_clr = (1U << MT3620_I2S_DMA_RX(id));
    }

    // Enable DMA handshakes for master mode.
    mt3620_i2s_dma_if_control_t dma_if_control = { .mask = mt3620_i2s[id]->dma_if_control };
    dma_if_control.ul_dmareq_mi_num = (enable ? 1 : 0);
    dma_if_control.ul_ahb_early_en  = enable;
    dma_if_control.ul_dma_mode_sel  = enable;
    mt3620_i2s[id]->dma_if_control = dma_if_control.mask;

    // Enable I2S.
    global_control.en = (enable || handle->out.enable);
    global_control.ulfifo_en = enable;
    mt3620_i2s[id]->global_control = global_control.mask;

    handle->in.enable   = enable;
    handle->in.callback = callback;

    if (enable) {
        MT3620_DMA_FIELD_WRITE(MT3620_I2S_DMA_RX(id), start, str, true);
    }

    return ERROR_NONE;
}