// Copyright 2018 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 <ddk/debug.h>
#include <limits>
#include <soc/aml-common/aml-tdm-audio.h>
#include <utility>

//static
fbl::unique_ptr<AmlTdmDevice> AmlTdmDevice::Create(ddk::MmioBuffer mmio,
                                                   ee_audio_mclk_src_t src,
                                                   aml_tdm_out_t tdm_dev,
                                                   aml_frddr_t frddr_dev,
                                                   aml_tdm_mclk_t mclk) {

    // FRDDR A has 256 64-bit lines in the FIFO, B and C have 128.
    uint32_t fifo_depth = 128 * 8; // in bytes.
    if (frddr_dev == FRDDR_A) {
        fifo_depth = 256 * 8;
    }

    fbl::AllocChecker ac;
    auto tdm = fbl::unique_ptr<AmlTdmDevice>(
        new (&ac) AmlTdmDevice(std::move(mmio), src, tdm_dev, frddr_dev, mclk, fifo_depth));
    if (!ac.check()) {
        return nullptr;
    }

    tdm->InitRegs();

    return tdm;
}

void AmlTdmDevice::InitRegs() {
    //Enable the audio domain clocks used by this instance.
    AudioClkEna((EE_AUDIO_CLK_GATE_TDMOUTA << tdm_ch_) |
                (EE_AUDIO_CLK_GATE_FRDDRA << frddr_ch_) |
                EE_AUDIO_CLK_GATE_ARB);

    //Set chosen mclk channels input to selected source
    //Since this is init, set the divider to max value assuming it will
    //    be set to proper value later (slower is safer from circuit standpoint)
    //Leave disabled for now.
    zx_off_t ptr = EE_AUDIO_MCLK_A_CTRL + (mclk_ch_ * sizeof(uint32_t));
    mmio_.Write32((clk_src_ << 24) | 0xffff, ptr);

    //Set the sclk and lrclk sources to the chosen mclk channel
    ptr = EE_AUDIO_CLK_TDMOUT_A_CTL + tdm_ch_ * sizeof(uint32_t);
    mmio_.Write32((0x03 << 30) | (mclk_ch_ << 24) | (mclk_ch_ << 20), ptr);

    //Enable DDR ARB, and enable this ddr channels bit.
    mmio_.SetBits32((1 << 31) | (1 << (4 + frddr_ch_)), EE_AUDIO_ARB_CTRL);

    //Disable the FRDDR Channel
    //Only use one buffer
    //Interrupts off
    //ack delay = 0
    //set destination tdm block and enable that selection
    mmio_.Write32(tdm_ch_ | (1 << 3), GetFrddrOffset(FRDDR_CTRL0_OFFS));
    //use entire fifo, start transfer request when fifo is at 1/2 full
    //set the magic force end bit(12) to cause fetch from start
    //    -this only happens when the bit is set from 0->1 (edge)
    // fifo depth needs to be configured in terms of 64-bit lines.
    mmio_.Write32((1 << 12) | (((fifo_depth_ / 8) - 1) << 24) |
                  ((((fifo_depth_ / 8) / 2) - 1) << 16),
                  GetFrddrOffset(FRDDR_CTRL1_OFFS));

    //Value to be inserted in a slot if it is muted
    mmio_.Write32(0x00000000, GetTdmOffset(TDMOUT_MUTE_VAL_OFFS));
    //Value to be inserted in a slot if it is masked
    mmio_.Write32(0x00000000, GetTdmOffset(TDMOUT_MASK_VAL_OFFS));

    mmio_.Write32(0x00000000, GetTdmOffset(TDMOUT_MUTE0_OFFS)); // Disable lane 0 muting.
    mmio_.Write32(0x00000000, GetTdmOffset(TDMOUT_MUTE1_OFFS)); // Disable lane 1 muting.
    mmio_.Write32(0x00000000, GetTdmOffset(TDMOUT_MUTE2_OFFS)); // Disable lane 2 muting.
    mmio_.Write32(0x00000000, GetTdmOffset(TDMOUT_MUTE3_OFFS)); // Disable lane 3 muting.

    // Datasheets state that PAD_CTRL1 controls sclk and lrclk source selection (which mclk),
    // it does this per pad (0, 1, 2).  These pads are tied to the TDM channel in use
    // (this is not specified in the datasheets but confirmed empirically) such that TDM_OUT_A
    // corresponds to pad 0, TDM_OUT_B to pad 1, and TDM_OUT_C to pad 2.
    switch (tdm_ch_) {
    case TDM_OUT_A:
        mmio_.Write32((mclk_ch_ << 16) | (mclk_ch_ << 0), EE_AUDIO_MST_PAD_CTRL1);
        break;
    case TDM_OUT_B:
        mmio_.Write32((mclk_ch_ << 20) | (mclk_ch_ << 4), EE_AUDIO_MST_PAD_CTRL1);
        break;
    case TDM_OUT_C:
        mmio_.Write32((mclk_ch_ << 24) | (mclk_ch_ << 8), EE_AUDIO_MST_PAD_CTRL1);
        break;
    }
}

/* Notes
    -div is desired divider minus 1. (want /100? write 99)
*/
zx_status_t AmlTdmDevice::SetMclkDiv(uint32_t div) {
    //check that divider is in range
    ZX_DEBUG_ASSERT(div < (1 << kMclkDivBits));

    zx_off_t ptr = EE_AUDIO_MCLK_A_CTRL + (mclk_ch_ * sizeof(uint32_t));
    //disable and clear out old divider value
    mmio_.ClearBits32((1 << 31) | ((1 << kMclkDivBits) - 1), ptr);

    mmio_.SetBits32((1 << 31) | (clk_src_ << 24) | (div & ((1 << kMclkDivBits) - 1)), ptr);
    return ZX_OK;
}

uint32_t AmlTdmDevice::GetRingPosition() {
    return mmio_.Read32(GetFrddrOffset(FRDDR_STATUS2_OFFS)) -
           mmio_.Read32(GetFrddrOffset(FRDDR_START_ADDR_OFFS));
}
/* Notes:
    -sdiv is desired divider -1 (Want a divider of 10? write a value of 9)
    -sclk needs to be at least 2x mclk.  writing a value of 0 (/1) to sdiv
        will result in no sclk being generated on the sclk pin.  However, it
        appears that it is running properly as a lrclk is still generated at
        an expected rate (lrclk is derived from sclk)
*/
zx_status_t AmlTdmDevice::SetSclkDiv(uint32_t sdiv,
                                     uint32_t lrduty,
                                     uint32_t lrdiv) {
    ZX_DEBUG_ASSERT(sdiv < (1 << kSclkDivBits));
    ZX_DEBUG_ASSERT(lrdiv < (1 << kLRclkDivBits));
    //lrduty is in sclk cycles, so must be less than lrdiv
    ZX_DEBUG_ASSERT(lrduty < lrdiv);

    zx_off_t ptr = EE_AUDIO_MST_A_SCLK_CTRL0 + (2 * mclk_ch_ * sizeof(uint32_t));
    mmio_.Write32((0x3 << 30) |        //Enable the channel
                  (sdiv << 20) |       //sclk divider sclk=mclk/sdiv
                  (lrduty << 10) |     //lrclk duty cycle in sclk cycles
                  (lrdiv << 0),        //lrclk = sclk/lrdiv
                  ptr);
    mmio_.Write32(0, ptr + sizeof(uint32_t)); //Clear delay lines for phases
    return ZX_OK;
}

zx_status_t AmlTdmDevice::SetMClkPad(aml_tdm_mclk_pad_t mclk_pad) {
    switch (mclk_pad) {
    case MCLK_PAD_0:
        mmio_.Write32(mclk_ch_, EE_AUDIO_MST_PAD_CTRL0);
        break;
    case MCLK_PAD_1:
        mmio_.Write32(mclk_ch_, EE_AUDIO_MST_PAD_CTRL1);
        break;
    default:
        return ZX_ERR_INVALID_ARGS;
    }
    return ZX_OK;
}

void AmlTdmDevice::AudioClkEna(uint32_t audio_blk_mask) {
    mmio_.SetBits32(audio_blk_mask, EE_AUDIO_CLK_GATE_EN);
}

void AmlTdmDevice::AudioClkDis(uint32_t audio_blk_mask) {
    mmio_.ClearBits32(audio_blk_mask, EE_AUDIO_CLK_GATE_EN);
}

zx_status_t AmlTdmDevice::SetBuffer(zx_paddr_t buf, size_t len) {
    //Ensure ring buffer resides in lower memory (dma pointers are 32-bit)
    //    and len is at least 8 (size of each dma operation)
    if (((buf + len - 1) > std::numeric_limits<uint32_t>::max()) || (len < 8)) {
        return ZX_ERR_INVALID_ARGS;
    }

    //Write32 the start and end pointers.  Each fetch is 64-bits, so end pointer
    //    is pointer to the last 64-bit fetch (inclusive)
    mmio_.Write32(static_cast<uint32_t>(buf), GetFrddrOffset(FRDDR_START_ADDR_OFFS));
    mmio_.Write32(static_cast<uint32_t>(buf + len - 8),
                  GetFrddrOffset(FRDDR_FINISH_ADDR_OFFS));
    return ZX_OK;
}

/*
    bit_offset - bit position in frame where first slot will appear
                    (position 0 is concurrent with frame sync)
    num_slots - number of slots per frame minus one
    bits_per_slot - width of each slot minus one
    bits_per_sample - number of bits in sample minus one
    mix_mask - lanes to mix L+R.
*/
void AmlTdmDevice::ConfigTdmOutSlot(uint8_t bit_offset, uint8_t num_slots,
                                    uint8_t bits_per_slot, uint8_t bits_per_sample,
                                    uint8_t mix_mask) {

    uint32_t reg = bits_per_slot | (num_slots << 5) | (bit_offset << 15) | (mix_mask << 20);
    mmio_.Write32(reg, GetTdmOffset(TDMOUT_CTRL0_OFFS));

    reg = (bits_per_sample << 8) | (frddr_ch_ << 24);
    if (bits_per_sample <= 8) {
        // 8 bit sample, left justify in frame, split 64-bit dma fetch into 8 samples
        reg |= (0 << 4);
    } else if (bits_per_sample <= 16) {
        // 16 bit sample, left justify in frame, split 64-bit dma fetch into 4 samples
        reg |= (2 << 4);
    } else {
        // 32/24 bit sample, left justify in slot, split 64-bit dma fetch into 2 samples
        reg |= (4 << 4);
    }
    mmio_.Write32(reg, GetTdmOffset(TDMOUT_CTRL1_OFFS));
}

zx_status_t AmlTdmDevice::ConfigTdmOutLane(size_t lane, uint32_t mask) {
    switch (lane) {
    case 0:
        mmio_.Write32(mask, GetTdmOffset(TDMOUT_MASK0_OFFS));
        break;
    case 1:
        mmio_.Write32(mask, GetTdmOffset(TDMOUT_MASK1_OFFS));
        break;
    case 2:
        mmio_.Write32(mask, GetTdmOffset(TDMOUT_MASK2_OFFS));
        break;
    case 3:
        mmio_.Write32(mask, GetTdmOffset(TDMOUT_MASK3_OFFS));
        break;
    default:
        return ZX_ERR_INVALID_ARGS;
    }
    return ZX_OK;
}

void AmlTdmDevice::ConfigTdmOutSwaps(uint32_t swaps) {
    mmio_.Write32(swaps, GetTdmOffset(TDMOUT_SWAP_OFFS));
}

// Stops the tdm from clocking data out of fifo onto bus
void AmlTdmDevice::TdmOutDisable() {
    mmio_.ClearBits32(1 << 31, GetTdmOffset(TDMOUT_CTRL0_OFFS));
}
// Enables the tdm to clock data out of fifo onto bus
void AmlTdmDevice::TdmOutEnable() {
    mmio_.SetBits32(1 << 31, GetTdmOffset(TDMOUT_CTRL0_OFFS));
}

void AmlTdmDevice::FRDDREnable() {
    //Set the load bit, will make sure things start from beginning of buffer
    mmio_.SetBits32(1 << 12, GetFrddrOffset(FRDDR_CTRL1_OFFS));
    mmio_.SetBits32(1 << 31, GetFrddrOffset(FRDDR_CTRL0_OFFS));
}

void AmlTdmDevice::FRDDRDisable() {
    // Clear the load bit (this is the bit that forces the initial fetch of
    //    start address into current ptr)
    mmio_.ClearBits32(1 << 12, GetFrddrOffset(FRDDR_CTRL1_OFFS));
    // Disable the frddr channel
    mmio_.ClearBits32(1 << 31, GetFrddrOffset(FRDDR_CTRL0_OFFS));
}

void AmlTdmDevice::Sync() {
    mmio_.ClearBits32(3 << 28, GetTdmOffset(TDMOUT_CTRL0_OFFS));
    mmio_.SetBits32(1 << 29, GetTdmOffset(TDMOUT_CTRL0_OFFS));
    mmio_.SetBits32(1 << 28, GetTdmOffset(TDMOUT_CTRL0_OFFS));
}

// Resets frddr mechanisms to start at beginning of buffer
//   starts the frddr (this will fill the fifo)
//   starts the tdm to clock out data on the bus
// returns the start time
uint64_t AmlTdmDevice::Start() {
    uint64_t a, b;

    Sync();
    FRDDREnable();
    a = zx_clock_get_monotonic();
    TdmOutEnable();
    b = zx_clock_get_monotonic();
    return ((b - a) >> 1) + a;
}

void AmlTdmDevice::Stop() {
    TdmOutDisable();
    FRDDRDisable();
}

void AmlTdmDevice::Shutdown() {
    Stop();

    // Disable the output signals
    zx_off_t ptr = EE_AUDIO_CLK_TDMOUT_A_CTL + tdm_ch_ * sizeof(uint32_t);
    mmio_.ClearBits32(0x03 << 30, ptr);

    // Disable the audio domain clocks used by this instance.
    AudioClkDis((EE_AUDIO_CLK_GATE_TDMOUTA << tdm_ch_) |
                (EE_AUDIO_CLK_GATE_FRDDRA << frddr_ch_));

    //Note: We are leaving the ARB unit clocked as well as MCLK and
    //  SCLK generation units since it is possible they are used by
    //  some other audio driver outside of this instance
}
