// 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.

#ifndef SRC_DEVICES_LIB_AMLOGIC_INCLUDE_SOC_AML_COMMON_AML_PDM_AUDIO_H_
#define SRC_DEVICES_LIB_AMLOGIC_INCLUDE_SOC_AML_COMMON_AML_PDM_AUDIO_H_

#include <assert.h>
#include <lib/mmio/mmio.h>

#include <memory>
#include <utility>

#include <soc/aml-common/aml-audio-regs.h>
#include <soc/aml-common/aml-audio.h>
/*
    Presently assumes stereo input with both streams multiplexed on the same
    PDM input line. (TODO: support up to 8 channels to refactor gauss to use this)
*/

class AmlPdmDevice {
 public:
  DISALLOW_COPY_ASSIGN_AND_MOVE(AmlPdmDevice);

  static std::unique_ptr<AmlPdmDevice> Create(
      ddk::MmioBuffer pdm_mmio, ddk::MmioBuffer audio_mmio, ee_audio_mclk_src_t pdm_clk_src,
      uint32_t sclk_div, uint32_t dclk_div, aml_toddr_t toddr_dev,
      metadata::AmlVersion version = metadata::AmlVersion::kS905D2G);

  // Sets the buffer/length pointers for dma engine
  //  must resize in lower 32-bits of address space
  zx_status_t SetBuffer(zx_paddr_t buf, size_t len);

  // Get HW alignment required in the buffer in bytes.
  static uint32_t GetBufferAlignment() { return 8; }

  /*
      Returns offset of dma pointer in the ring buffer
  */
  uint32_t GetRingPosition();

  /*
      Resets state of dma mechanisms and starts clocking data
      in from pdm bus with data written to start of ring buffer
  */
  uint64_t Start();

  /*
      Stops clocking stat in off PDM bus
      (physical pdm bus signals remain active)
  */
  void Stop();

  /*
      Synchronize the state of PDM bus signals with fifo/dma engine
  */
  void Sync();

  virtual void SetMute(uint8_t mute_mask);

  /*
      shuts down toddr, stops writing data to ring buffer
  */
  void Shutdown();

  uint32_t fifo_depth() const { return fifo_depth_; }

  virtual void ConfigPdmIn(uint8_t mask);

  void SetRate(uint32_t frames_per_second);

 protected:
  AmlPdmDevice(ddk::MmioBuffer pdm_mmio, ddk::MmioBuffer audio_mmio, ee_audio_mclk_src_t clk_src,
               uint32_t sysclk_div, uint32_t dclk_div, aml_toddr_t toddr, uint32_t fifo_depth,
               metadata::AmlVersion version)
      : fifo_depth_(fifo_depth),
        toddr_ch_(toddr),
        clk_src_(clk_src),
        sysclk_div_(sysclk_div),
        dclk_div_(dclk_div),
        toddr_base_(GetToddrBase(toddr)),
        pdm_mmio_(std::move(pdm_mmio)),
        audio_mmio_(std::move(audio_mmio)),
        version_(version) {}

  virtual ~AmlPdmDevice() = default;

 private:
  friend class std::default_delete<AmlPdmDevice>;

  /* Get the register block offset for our ddr block */
  static zx_off_t GetToddrBase(aml_toddr_t ch) {
    switch (ch) {
      case TODDR_A:
        return EE_AUDIO_TODDR_A_CTRL0;
      case TODDR_B:
        return EE_AUDIO_TODDR_B_CTRL0;
      case TODDR_C:
        return EE_AUDIO_TODDR_C_CTRL0;
    }
    // We should never get here, but if we do, make it hard to ignore
    ZX_PANIC("Invalid toddr channel specified!\n");
    return 0;
  }

  void AudioClkEna(uint32_t audio_blk_mask);
  void AudioClkDis(uint32_t audio_blk_mask);
  void InitRegs();
  void TODDREnable();
  void TODDRDisable();
  void PdmInDisable();
  void PdmInEnable();
  void ConfigFilters(uint32_t frames_per_second);

  /* Get the register block offset for our ddr block */
  zx_off_t GetToddrOffset(zx_off_t off) { return toddr_base_ + off; }
  const uint32_t fifo_depth_;   // in bytes.
  const aml_toddr_t toddr_ch_;  // fromddr channel used by this instance
  const ee_audio_mclk_src_t clk_src_;
  const uint32_t sysclk_div_;
  const uint32_t dclk_div_;
  const zx_off_t toddr_base_;  // base offset of frddr ch used by this instance
  const ddk::MmioBuffer pdm_mmio_;
  const ddk::MmioBuffer audio_mmio_;
  const metadata::AmlVersion version_;
};

#endif  // SRC_DEVICES_LIB_AMLOGIC_INCLUDE_SOC_AML_COMMON_AML_PDM_AUDIO_H_
