/*
 * Copyright 2023 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Barebones i2s for soundstream. Only supports recording and
 * without any buffering. The caller must manage the rx fifo
 * carefully to avoid data loss.
 */
#include "i2s.h"

#include <fail-simulator-on-error.h>
#include <futex.h>
#include <interrupt.h>
#include <locks.h>
#include <thread.h>

#include <debug.hh>
#include <platform/sencha/platform-i2s.hh>

#include "hw/top_matcha/sw/autogen/top_matcha.h"
#include "i2s_regs.h"

/// Expose debugging features unconditionally for this compartment.
using Debug = ConditionalDebug<false, "I2S">;

#include "compat.h"

typedef uint32_t i2s_mmio_t[TOP_MATCHA_I2S0_SIZE_BYTES / sizeof(uint32_t)];

static dif_i2s_t i2s;
static void i2s_irq_acknowledge(i2s_irq_t irq_id);

#define CHECK_INIT() CHECK(i2s.base_addr.base != 0)

static CountingSemaphoreState startup = { 0, 1 };

void i2s_init(void) {
  CHECK_DIF_OK(dif_i2s_init(
      mmio_region_from_addr((uintptr_t)MMIO_CAPABILITY(i2s_mmio_t, i2s)),
      &i2s));
  semaphore_put(&startup);
}

// NB: could be atomic but not needed for our usage.
volatile bool rx_watermark_seen = false;

void i2s_isr(void) {
  Timeout t = {0, UnlimitedTimeout};
  semaphore_get(&t, &startup);
  Debug::log("i2s_isr: i2s {} (Thread {})", i2s.base_addr.base, thread_id_get());

  const uint32_t *rxWatermarkFutex = interrupt_futex_get(
      STATIC_SEALED_VALUE(i2sRxWatermarkInterruptCapability));
  uint32_t last = *rxWatermarkFutex;
  for (;;) {
    Debug::Assert(futex_wait(rxWatermarkFutex, last) == 0, "futex_wait");
    last = *rxWatermarkFutex;
    Debug::log("i2s_isr: i2s {} last {})", i2s.base_addr.base, last);
    rx_watermark_seen = true;
    // Acknowledge and disable the interrupt; it will be
    // re-enabled after the RX FIFO is drained.
    i2s_irq_acknowledge(kI2sIrqRxWatermark);
    i2s_irq_set_enabled(kI2sIrqRxWatermark, /*enabled=*/false);
    CHECK(interrupt_complete(
        STATIC_SEALED_VALUE(i2sRxWatermarkInterruptCapability)) == 0);
  }
}
bool i2s_rx_watermark_seen(void) {
  // return atomic_swap(&rx_watermark_seen, false);
  bool was_seen = rx_watermark_seen;
  if (was_seen) {
    rx_watermark_seen = false;
  }
  return was_seen;
}

void i2s_wait_for_rx_watermark(void) {
  const uint32_t *rxWatermarkFutex = interrupt_futex_get(
      STATIC_SEALED_VALUE(i2sRxWatermarkInterruptCapability));
  uint32_t last = *rxWatermarkFutex;
  while (!i2s_rx_watermark_seen()) {
    Debug::Assert(futex_wait(rxWatermarkFutex, last) == 0, "futex_wait");
    last = *rxWatermarkFutex;
  }
}

static void i2s_irq_acknowledge(i2s_irq_t irq_id) {
  CHECK_INIT();
  CHECK_DIF_OK(dif_i2s_irq_acknowledge(&i2s, irq_id));
}

void i2s_irq_acknowledge_all() {
  CHECK_INIT();
  CHECK_DIF_OK(dif_i2s_irq_acknowledge_all(&i2s));
}

void i2s_irq_set_enabled(i2s_irq_t irq_id, bool enabled) {
  CHECK_INIT();
  CHECK_DIF_OK(dif_i2s_irq_set_enabled(
      &i2s, irq_id, enabled ? kDifToggleEnabled : kDifToggleDisabled));
}

// Clear RX FIFO
void i2s_rxfifo_clear(void) {
  CHECK_INIT();
  uint32_t reg_val;
  reg_val = mmio_region_read32(i2s.base_addr, I2S_FIFO_CTRL_REG_OFFSET);
  reg_val = bitfield_bit32_write(reg_val, I2S_FIFO_CTRL_RXRST_BIT, 1);
  mmio_region_write32(i2s.base_addr, I2S_FIFO_CTRL_REG_OFFSET, reg_val);
}

bool i2s_rxfifo_is_empty(void) {
  CHECK_INIT();
  bool empty;
  CHECK_DIF_OK(dif_i2s_rxfifo_empty(&i2s, &empty));
  return empty;
}

// Configure and enable recording
void i2s_record_begin(void) {
  CHECK_INIT();
  uint32_t reg_val = mmio_region_read32(i2s.base_addr, I2S_CTRL_REG_OFFSET);
  reg_val = bitfield_bit32_write(reg_val, I2S_CTRL_RX_BIT, 1);
  reg_val = bitfield_field32_write(reg_val, I2S_CTRL_NCO_RX_FIELD,
                                   24);  // divide by 24
  mmio_region_write32(i2s.base_addr, I2S_CTRL_REG_OFFSET, reg_val);
}

uint32_t i2s_get_rdata(void) {
  CHECK_INIT();
  return mmio_region_read32(i2s.base_addr, I2S_RDATA_REG_OFFSET);
}

// Disable recording
void i2s_record_end(void) {
  CHECK_INIT();
  uint32_t reg_val = mmio_region_read32(i2s.base_addr, I2S_CTRL_REG_OFFSET);
  reg_val = bitfield_bit32_write(reg_val, I2S_CTRL_RX_BIT, 0);
  mmio_region_write32(i2s.base_addr, I2S_CTRL_REG_OFFSET, reg_val);
}
