/*
 * 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);
}

volatile bool rx_watermark_seen = false;
uint32_t rx_watermark_seen_futex = 0;

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);
    // 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);

    rx_watermark_seen = true;
    futex_wake(&rx_watermark_seen_futex, 1);
  }
}
bool i2s_rx_watermark_seen(void) {
  bool was_seen = rx_watermark_seen;
  if (was_seen) {
    rx_watermark_seen = false;
  }
  return was_seen;
}

void i2s_wait_for_rx_watermark(void) {
  // NB: this is conservative; we only have one consumer so could
  //   just do: if (!i2s_rx_watermark_seen()) futex_wait(...).
  uint32_t last = rx_watermark_seen_futex;
  while (!i2s_rx_watermark_seen()) {
    Debug::Assert(futex_wait(&rx_watermark_seen_futex, last) == 0,
                  "futex_wait");
    last = rx_watermark_seen_futex;
  }
}

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);
}
