// 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 "max98927.h"

#include <ddk/binding.h>
#include <ddk/debug.h>
#include <ddk/driver.h>
#include <ddk/platform-defs.h>
#include <lib/device-protocol/i2c.h>
#include <endian.h>
#include <fbl/alloc_checker.h>
#include <fuchsia/hardware/audiocodec/c/fidl.h>
#include <lib/fidl-utils/bind.h>
#include <zircon/assert.h>
#include "max98927-registers.h"

namespace audio {
namespace max98927 {

uint8_t Max98927Device::ReadReg(uint16_t addr) {
  uint16_t buf = htobe16(addr);
  uint8_t val = 0;
  zx_status_t status = i2c_write_read_sync(&i2c_, &buf, sizeof(buf), &val, sizeof(val));
  if (status != ZX_OK) {
    zxlogf(ERROR, "max98927: could not read reg addr: 0x%04X  status: %d\n", addr, status);
    return -1;
  }

  zxlogf(SPEW, "max98927: register 0x%04x read 0x%02x\n", addr, val);
  return val;
}

void Max98927Device::WriteReg(uint16_t addr, uint8_t val) {
  uint8_t buf[3];
  uint16_t* p = reinterpret_cast<uint16_t*>(buf);
  *p = htobe16(addr);
  buf[2] = val;
  zx_status_t status = i2c_write_sync(&i2c_, buf, sizeof(buf));
  if (status != ZX_OK) {
    zxlogf(ERROR, "alc5514: could not write reg addr/val: 0x%04x/0x%02x  status: %d\n", addr, val,
           status);
  }
  zxlogf(SPEW, "max98927: register 0x%04x write 0x%02x\n", addr, val);
}

void Max98927Device::DumpRegs() {
  constexpr uint16_t first = INTERRUPT_RAW_1;
  constexpr uint16_t last = GLOBAL_ENABLE;

  // read all registers
  // segments followed by write data (first register)
  // the address pointer is automatically incremented after each byte read
  uint16_t buf = htobe16(first);
  uint8_t out[last];
  zx_status_t status = i2c_write_read_sync(&i2c_, &buf, sizeof(buf), out, sizeof(out));
  if (status != ZX_OK) {
    zxlogf(ERROR, "max98927: could not read regs status: %d\n", status);
  }

  zxlogf(INFO, "max98927: register dump\n");
  for (uint16_t i = 0; i < last; i++) {
    zxlogf(INFO, "    [%04x]: 0x%02x\n", i + 1, out[i]);
  }
}

zx_status_t Max98927Device::FidlSetEnabled(bool enable) {
  if (enable) {
    Enable();
  } else {
    Disable();
  }
  return ZX_OK;
}

zx_status_t Max98927Device::DdkMessage(fidl_msg_t* msg, fidl_txn_t* txn) {
  using Binder = fidl::Binder<Max98927Device>;
  static const fuchsia_hardware_audiocodec_Device_ops_t kOps = {
      .SetEnabled = Binder::BindMember<&Max98927Device::FidlSetEnabled>,
  };
  return fuchsia_hardware_audiocodec_Device_dispatch(this, txn, msg, &kOps);
}

void Max98927Device::DdkUnbind() {}

void Max98927Device::DdkRelease() { delete this; }

void Max98927Device::Test() {
  // PCM config - slave mode
  WriteReg(PCM_MASTER_MODE, 0);

  // PCM config - 48kHz 16-bits
  WriteReg(PCM_SAMPLE_RATE_SETUP_1, PCM_SAMPLE_RATE_SETUP_1_DIG_IF_SR(0x8));
  WriteReg(PCM_SAMPLE_RATE_SETUP_2,
           PCM_SAMPLE_RATE_SETUP_2_SPK_SR(0x8) | PCM_SAMPLE_RATE_SETUP_2_IVADC_SR(0x8));
  WriteReg(PCM_MODE_CFG, PCM_MODE_CFG_CHANSZ_16BITS | 0x3);
  WriteReg(PCM_CLOCK_SETUP, 0x2);

  // Enable TX channels
  WriteReg(PCM_RX_EN_A, 0x3);

  // Set speaker source to tone generator
  WriteReg(SPK_SRC_SEL, SPK_SRC_SEL_TONE_GEN);

  // Generate a tone. Must do before AMP_ENABLE.AMP_ENABLE_EN and BROWNOUT_EN.AMP_DSP_EN.
  WriteReg(TONE_GEN_DC_CFG, 0x6);  // fs/64 @ 48kHz = 750Hz

  zxlogf(INFO, "max98927: playing test tone...\n");

  // Enable for 2 secs. The datasheet recommends GLOBAL_ENABLE then AMP_ENABLE, but
  // the part errors when the bits are toggled in that order.
  WriteReg(AMP_ENABLE, AMP_ENABLE_EN);
  WriteReg(GLOBAL_ENABLE, GLOBAL_ENABLE_EN);

  zx_nanosleep(zx_deadline_after(ZX_SEC(2)));

  WriteReg(GLOBAL_ENABLE, 0);
  WriteReg(AMP_ENABLE, 0);

  // Disable tone generator and rx paths.
  WriteReg(TONE_GEN_DC_CFG, 0);
  WriteReg(PCM_RX_EN_A, 0);

  zxlogf(INFO, "max98927: test tone done\n");
}

void Max98927Device::Enable() {
  // PCM config - slave mode
  WriteReg(PCM_MASTER_MODE, 0);

  // PCM config - 48kHz 16-bits TDM0
  WriteReg(PCM_SAMPLE_RATE_SETUP_1, PCM_SAMPLE_RATE_SETUP_1_DIG_IF_SR(0x8));
  WriteReg(PCM_SAMPLE_RATE_SETUP_2,
           PCM_SAMPLE_RATE_SETUP_2_SPK_SR(0x8) | PCM_SAMPLE_RATE_SETUP_2_IVADC_SR(0x8));
  WriteReg(PCM_MODE_CFG, PCM_MODE_CFG_CHANSZ_16BITS | PCM_MODE_CFG_FORMAT_TDM0);
  WriteReg(PCM_CLOCK_SETUP, 0x6);

  // Enable TX channels
  WriteReg(PCM_RX_EN_A, 0x3);

  // Set speaker source to DAI
  WriteReg(SPK_SRC_SEL, 0);

  // The datasheet recommends GLOBAL_ENABLE then AMP_ENABLE, but
  // the part errors when the bits are toggled in that order.
  WriteReg(AMP_ENABLE, AMP_ENABLE_EN);
  WriteReg(GLOBAL_ENABLE, GLOBAL_ENABLE_EN);
}

void Max98927Device::Disable() {
  // Disable TX channels
  WriteReg(PCM_RX_EN_A, 0);

  WriteReg(GLOBAL_ENABLE, 0);
  WriteReg(AMP_ENABLE, 0);
}

zx_status_t Max98927Device::Initialize() {
  // Reset device
  WriteReg(SOFTWARE_RESET, SOFTWARE_RESET_RST);

  // Set outputs to HiZ
  WriteReg(PCM_TX_HIZ_CTRL_A, 0xFF);
  WriteReg(PCM_TX_HIZ_CTRL_B, 0xFF);

  // Default monomix output is (channel 0 + channel 1) / 2
  // Default monomix input channel 0 is PCM RX channel 0
  WriteReg(PCM_SPK_MONOMIX_A, PCM_SPK_MONOMIX_A_CFG_OUTPUT_0_1 | PCM_SPK_MONOMIX_B_CFG_CH0_SRC(0));
  // Default monomix input channel 1 is PCM RX channel 1
  WriteReg(PCM_SPK_MONOMIX_B, PCM_SPK_MONOMIX_B_CFG_CH1_SRC(1));

  // Default volume (+6dB dB)
  WriteReg(AMP_VOL_CTRL, 0x34 + 24);
  WriteReg(SPK_GAIN, SPK_GAIN_PCM(SPK_GAIN_3DB));

  // Enable DC blocking filter
  WriteReg(AMP_DSP_CFG, AMP_DSP_CFG_DCBLK_EN);

  // Enable IMON/VMON DC blocker
  WriteReg(MEAS_DSP_CFG, MEAS_DSP_CFG_I_DCBLK(MEAS_DSP_CFG_FREQ_3_7HZ) |
                             MEAS_DSP_CFG_V_DCBLK(MEAS_DSP_CFG_FREQ_3_7HZ) | MEAS_DSP_CFG_DITH_EN |
                             MEAS_DSP_CFG_I_DCBLK_EN | MEAS_DSP_CFG_V_DCBLK_EN);

  // Boost output voltage & current limit
  WriteReg(BOOST_CTRL_0, 0x1C);  // 10.00V
  WriteReg(BOOST_CTRL_1, 0x3E);  // 4.00A

  // Measurement ADC config
  WriteReg(MEAS_ADC_CFG, MEAS_ADC_CFG_CH2_EN);
  WriteReg(MEAS_ADC_BASE_DIV_MSB, 0);
  WriteReg(MEAS_ADC_BASE_DIV_LSB, 0x24);

  // Brownout level
  WriteReg(BROWNOUT_LVL4_AMP1_CTRL1, 0x06);  // -6dBFS

  // Envelope tracker configuration
  WriteReg(ENV_TRACKER_VOUT_HEADROOM, 0x08);  // 1.000V
  WriteReg(ENV_TRACKER_CTRL, ENV_TRACKER_CTRL_EN);
  WriteReg(ENV_TRACKER_BOOST_VOUT_RB, 0x10);  // 8.500V

  // TODO: figure out vmon-slot-no and imon-slot-no

  // Set interleave mode
  WriteReg(PCM_TX_CH_SRC_B, PCM_TX_CH_SRC_B_INTERLEAVE);

  return ZX_OK;
}

zx_status_t Max98927Device::Bind() {
  zx_status_t st = device_get_protocol(parent(), ZX_PROTOCOL_I2C, &i2c_);
  if (st != ZX_OK) {
    zxlogf(ERROR, "max98927: could not get I2C protocol: %d\n", st);
    return st;
  }

  st = Initialize();
  if (st != ZX_OK) {
    return st;
  }

  // Power on by default...
  Enable();

  return DdkAdd("max98927");
}

zx_status_t Max98927Device::Create(void* ctx, zx_device_t* parent) {
  fbl::AllocChecker ac;
  fbl::unique_ptr<Max98927Device> dev(new (&ac) Max98927Device(parent));
  if (!ac.check()) {
    zxlogf(ERROR, "max98927: out of memory attempting to allocate device\n");
    return ZX_ERR_NO_MEMORY;
  }

  zx_status_t st = dev->Bind();
  if (st == ZX_OK) {
    // devmgr is now in charge of the memory for dev
    __UNUSED auto ptr = dev.release();
    return st;
  }

  return ZX_OK;
}

static constexpr zx_driver_ops_t driver_ops = []() {
  zx_driver_ops_t ops = {};
  ops.version = DRIVER_OPS_VERSION;
  ops.bind = Max98927Device::Create;
  return ops;
}();

}  // namespace max98927
}  // namespace audio

// clang-format off
ZIRCON_DRIVER_BEGIN(max98927, audio::max98927::driver_ops, "zircon", "0.1", 3)
    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_I2C),
    BI_ABORT_IF(NE, BIND_ACPI_HID_0_3, 0x4d583938), // 'MX98'
    BI_MATCH_IF(EQ, BIND_ACPI_HID_4_7, 0x39323700), // '927\0'
ZIRCON_DRIVER_END(max98927)
    // clang-format on
