// Copyright 2019 The Fuchsia 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 <limits>
#include <utility>

#include <ddk/debug.h>
#include <fbl/alloc_checker.h>
#include <soc/mt8167/mt8167-audio-in.h>
#include <soc/mt8167/mt8167-audio-regs.h>
#include <soc/mt8167/mt8167-clk-regs.h>

std::unique_ptr<MtAudioInDevice> MtAudioInDevice::Create(ddk::MmioBuffer mmio_audio,
                                                         ddk::MmioBuffer mmio_clk,
                                                         ddk::MmioBuffer mmio_pll,
                                                         MtI2sCh ch) {

    uint32_t fifo_depth = 0; // in bytes. TODO(andresoportus): Find out actual size.

    // TODO(andresoportus): Support other configurations.
    if (ch != I2S6) {
        return nullptr;
    }

    fbl::AllocChecker ac;
    auto dev = std::unique_ptr<MtAudioInDevice>(
        new (&ac) MtAudioInDevice(std::move(mmio_audio), std::move(mmio_clk),
                                  std::move(mmio_pll), fifo_depth));
    if (!ac.check()) {
        return nullptr;
    }

    dev->InitRegs();
    return dev;
}

void MtAudioInDevice::InitRegs() {
    // Enable the AFE module.
    AFE_DAC_CON0::Get().ReadFrom(&mmio_audio_).set_AFE_ON(1).WriteTo(&mmio_audio_);

    // Power up the AFE module by clearing the power down bit.
    AUDIO_TOP_CON0::Get().ReadFrom(&mmio_audio_).set_PDN_AFE(0).WriteTo(&mmio_audio_);

    // Route TDM_IN to afe_mem_if.
    AFE_CONN_TDMIN_CON::Get().FromValue(0).set_o_40_cfg(0).set_o_41_cfg(1).WriteTo(&mmio_audio_);

    // Audio Interface.
    auto tdm_in = AFE_TDM_IN_CON1::Get().FromValue(0);
    tdm_in.set_tdm_en(1).set_tdm_fmt(1).set_tdm_lrck_inv(1);                    // Enable, I2S, inv.
    tdm_in.set_tdm_wlen(1).set_LRCK_TDM_WIDTH(15);                              // 16 bits, 16 bits.
    tdm_in.set_fast_lrck_cycle_sel(0).set_tdm_channel(0).WriteTo(&mmio_audio_); // LRCK 16 BCK, 2ch.
}

zx_status_t MtAudioInDevice::SetRate(uint32_t frames_per_second) {
    // BCK = Aud1-Aud2 PLL / 8 / n = frames_per_second * 32.
    uint32_t n = 0;
    switch (frames_per_second) {
    case 11025:  // n = 16 * 44100 / 11025  = 64, BCK = 352.8 kHz.
    case 22050:  // n = 16 * 44100 / 22050  = 32, BCK = 705.6 KHz.
    case 44100:  // n = 16 * 44100 / 44100  = 16, BCK = 1.4112 MHz.
    case 88200:  // n = 16 * 44100 / 88200  =  8, BCK = 2.8224 MHz.
    case 176400: // n = 16 * 44100 / 176400 =  4, BCK = 5.6448 MHz.
        n = 16 * 44100 / frames_per_second;
        break;
    case 8000:   // n = 16 * 48000 / 8000   = 96, BCK = 256 KHz.
    case 12000:  // n = 16 * 48000 / 12000  = 64, BCK = 384 KHz.
    case 16000:  // n = 16 * 48000 / 16000  = 48, BCK = 512 KHz.
    case 24000:  // n = 16 * 48000 / 24000  = 32, BCK = 768 KHz.
    case 32000:  // n = 16 * 48000 / 32000  = 24, BCK = 1.024 MHz.
    case 48000:  // n = 16 * 48000 / 48000  = 16, BCK = 1.536 MHz.
    case 96000:  // n = 16 * 48000 / 96000  =  8, BCK = 3.072 MHz.
    case 192000: // n = 16 * 48000 / 192000 =  4, BCK = 6.144 MHz.
        n = 16 * 48000 / frames_per_second;
        break;
    default:
        return ZX_ERR_NOT_SUPPORTED;
    }
    CLK_SEL_11::Get().ReadFrom(&mmio_clk_).set_apll12_ck_div5b(n - 1).WriteTo(&mmio_clk_); // BCK.

    frames_per_second_ = frames_per_second;
    if (frames_per_second % 8000) {
        // Use aud1 clock.  Enable aud1 PLL.
        APLL1_CON0::Get().ReadFrom(&mmio_pll_).set_APLL1_EN(1).WriteTo(&mmio_pll_);
        // MCLK of I2S6 (TDM IN, i2s5 in 0-5 range) to hf_faud_1_ck (aud1).
        CLK_SEL_9::Get().ReadFrom(&mmio_clk_).set_apll_i2s5_mck_sel(0).WriteTo(&mmio_clk_);
        // MCK = 180.6336 MHz(Aud1 PLL) / 7+1 = 22.5792 MHz.
        CLK_SEL_11::Get().ReadFrom(&mmio_clk_).set_apll12_ck_div5(7).WriteTo(&mmio_clk_);
    } else {
        // Use aud2 clock.  Enable aud2 PLL.
        APLL2_CON0::Get().ReadFrom(&mmio_pll_).set_APLL2_EN(1).WriteTo(&mmio_pll_);
        // MCLK of I2S6 (TDM IN, i2s5 in 0-5 range) to hf_faud_2_ck (aud2).
        CLK_SEL_9::Get().ReadFrom(&mmio_clk_).set_apll_i2s5_mck_sel(1).WriteTo(&mmio_clk_);
        // MCK = 196.608 MHz(Aud2 PLL) / 7+1 = 24.576 MHz.
        CLK_SEL_11::Get().ReadFrom(&mmio_clk_).set_apll12_ck_div5(7).WriteTo(&mmio_clk_);
    }
    return ZX_OK;
}

uint32_t MtAudioInDevice::GetRingPosition() {
    return AFE_HDMI_IN_2CH_CUR::Get().ReadFrom(&mmio_audio_).reg_value() -
           AFE_HDMI_IN_2CH_BASE::Get().ReadFrom(&mmio_audio_).reg_value();
}

zx_status_t MtAudioInDevice::SetBuffer(zx_paddr_t buf, size_t len) {
    if ((buf % 16) || ((buf + len - 1) > std::numeric_limits<uint32_t>::max()) || (len < 16) ||
        (len % 16)) {
        return ZX_ERR_INVALID_ARGS;
    }

    // End is inclusive.
    AFE_HDMI_IN_2CH_BASE::Get().FromValue(static_cast<uint32_t>(buf)).WriteTo(&mmio_audio_);
    auto end = AFE_HDMI_IN_2CH_END::Get().FromValue(static_cast<uint32_t>(buf + len - 1));
    end.WriteTo(&mmio_audio_);
    return ZX_OK;
}

uint64_t MtAudioInDevice::Start() {
    // Power up by clearing the power down (pdn) bit.
    CLK_SEL_9::Get().ReadFrom(&mmio_clk_).set_apll12_div5_pdn(0).WriteTo(&mmio_clk_);  // MCK.
    CLK_SEL_9::Get().ReadFrom(&mmio_clk_).set_apll12_div5b_pdn(0).WriteTo(&mmio_clk_); // BCK.

    auto in = AFE_HDMI_IN_2CH_CON0::Get().ReadFrom(&mmio_audio_).set_AFE_HDMI_IN_2CH_OUT_ON(1);
    in.WriteTo(&mmio_audio_);
    return 0;
}

void MtAudioInDevice::Stop() {
    // Power down by setting the power down (pdn) bit.
    CLK_SEL_9::Get().ReadFrom(&mmio_clk_).set_apll12_div5_pdn(1).WriteTo(&mmio_clk_);  // MCK.
    CLK_SEL_9::Get().ReadFrom(&mmio_clk_).set_apll12_div5b_pdn(1).WriteTo(&mmio_clk_); // BCK.

    auto in = AFE_HDMI_IN_2CH_CON0::Get().ReadFrom(&mmio_audio_).set_AFE_HDMI_IN_2CH_OUT_ON(0);
    in.WriteTo(&mmio_audio_);
}

void MtAudioInDevice::Shutdown() {
    Stop();
    // Disable the AFE module.
    // TODO(andresoportus): Manage multiple drivers accessing same registers, e.g. Audio In and Out.
    AFE_DAC_CON0::Get().ReadFrom(&mmio_audio_).set_AFE_ON(0).WriteTo(&mmio_audio_);
}
