// 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 <limits>
#include <memory>
#include <utility>

#include <ddk/debug.h>
#include <fbl/alloc_checker.h>
#include <soc/aml-common/aml-tdm-audio.h>

// static
std::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, AmlVersion version) {
  // 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 = std::unique_ptr<AmlTdmDevice>(
      new (&ac) AmlTdmDevice(std::move(mmio), src, tdm_dev, frddr_dev, mclk, fifo_depth, version));
  if (!ac.check()) {
    return nullptr;
  }

  return tdm;
}

void AmlTdmDevice::Initialize() {
  // 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);

  zx_off_t mclk_a = {};
  switch (version_) {
    case AmlVersion::kS905D2G:
      mclk_a = EE_AUDIO_MCLK_A_CTRL;
      break;
    case AmlVersion::kS905D3G:
      mclk_a = EE_AUDIO_MCLK_A_CTRL_D3G;
      break;
  }
  // 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 = mclk_a + (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
  switch (version_) {
    case AmlVersion::kS905D2G:
      mmio_.Write32(tdm_ch_ | (1 << 3), GetFrddrOffset(FRDDR_CTRL0_OFFS));
      break;
    case AmlVersion::kS905D3G:
      mmio_.Write32(tdm_ch_ | (1 << 4), GetFrddrOffset(FRDDR_CTRL2_OFFS_D3G));
      break;
  }
  // 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.
  uint32_t pad1 = {};
  switch (version_) {
    case AmlVersion::kS905D2G:
      pad1 = EE_AUDIO_MST_PAD_CTRL1;
      break;
    case AmlVersion::kS905D3G:
      pad1 = EE_AUDIO_MST_PAD_CTRL1_D3G;
      break;
  }
  switch (tdm_ch_) {
    case TDM_OUT_A:
      mmio_.Write32((mclk_ch_ << 16) | (mclk_ch_ << 0), pad1);
      break;
    case TDM_OUT_B:
      mmio_.Write32((mclk_ch_ << 20) | (mclk_ch_ << 4), pad1);
      break;
    case TDM_OUT_C:
      mmio_.Write32((mclk_ch_ << 24) | (mclk_ch_ << 8), pad1);
      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 mclk_a = {};
  switch (version_) {
    case AmlVersion::kS905D2G:
      mclk_a = EE_AUDIO_MCLK_A_CTRL;
      break;
    case AmlVersion::kS905D3G:
      mclk_a = EE_AUDIO_MCLK_A_CTRL_D3G;
      break;
  }
  zx_off_t ptr = mclk_a + (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)
*/
zx_status_t AmlTdmDevice::SetSclkDiv(uint32_t sdiv, uint32_t lrduty, uint32_t lrdiv,
                                     bool sclk_invert_ph0) {
  if (sdiv == 0) {
    // 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)
    return ZX_ERR_INVALID_ARGS;
  }
  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
  // Invert sclk.
  mmio_.Write32(sclk_invert_ph0 << 0,
                EE_AUDIO_MST_A_SCLK_CTRL1 + (2 * mclk_ch_ * sizeof(uint32_t)));
  return ZX_OK;
}

zx_status_t AmlTdmDevice::SetMClkPad(aml_tdm_mclk_pad_t mclk_pad) {
  switch (mclk_pad) {
    case MCLK_PAD_0:
      switch (version_) {
        case AmlVersion::kS905D2G:
          mmio_.Write32(mclk_ch_, EE_AUDIO_MST_PAD_CTRL0);
          break;
        case AmlVersion::kS905D3G:
          mmio_.Write32((mclk_ch_ << 8) | (1 << 15), EE_AUDIO_MST_PAD_CTRL0);  // Bit 15 to enable.
          break;
      }
      break;
    case MCLK_PAD_1:
      switch (version_) {
        case AmlVersion::kS905D2G:
          mmio_.Write32(mclk_ch_ << 4, EE_AUDIO_MST_PAD_CTRL0);
          break;
        case AmlVersion::kS905D3G:
          mmio_.Write32((mclk_ch_ << 24) | (1 << 31), EE_AUDIO_MST_PAD_CTRL0);  // Bit 31 to enable.
          break;
      }
      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) {
  switch (version_) {
    case AmlVersion::kS905D2G: {
      uint32_t reg0 = bits_per_slot | (num_slots << 5) | (bit_offset << 15) | (mix_mask << 20);
      mmio_.Write32(reg0, GetTdmOffset(TDMOUT_CTRL0_OFFS));
    } break;
    case AmlVersion::kS905D3G: {
      uint32_t reg0 =
          bits_per_slot | (num_slots << 5) | (bit_offset << 15) | (1 << 31);  // Bit 31 to enable.
      mmio_.Write32(reg0, GetTdmOffset(TDMOUT_CTRL0_OFFS));
      uint32_t reg2 = (mix_mask << 0);
      mmio_.Write32(reg2, GetTdmOffset(TDMOUT_CTRL2_OFFS_D3G));
    } break;
  }

  uint32_t 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 enable_mask, uint32_t mute_mask) {
  switch (lane) {
    case 0:
      mmio_.Write32(enable_mask, GetTdmOffset(TDMOUT_MASK0_OFFS));
      mmio_.Write32(mute_mask, GetTdmOffset(TDMOUT_MUTE0_OFFS));
      break;
    case 1:
      mmio_.Write32(enable_mask, GetTdmOffset(TDMOUT_MASK1_OFFS));
      mmio_.Write32(mute_mask, GetTdmOffset(TDMOUT_MUTE1_OFFS));
      break;
    case 2:
      mmio_.Write32(enable_mask, GetTdmOffset(TDMOUT_MASK2_OFFS));
      mmio_.Write32(mute_mask, GetTdmOffset(TDMOUT_MUTE2_OFFS));
      break;
    case 3:
      mmio_.Write32(enable_mask, GetTdmOffset(TDMOUT_MASK3_OFFS));
      mmio_.Write32(mute_mask, GetTdmOffset(TDMOUT_MUTE3_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
}
