// Copyright 2017 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 <endian.h>
#include <zircon/assert.h>
#include <fbl/algorithm.h>
#include <fbl/auto_lock.h>
#include <string.h>

#include <intel-hda/utils/intel-hda-registers.h>

#include "debug-logging.h"
#include "intel-hda-codec.h"
#include "intel-hda-controller.h"

namespace audio {
namespace intel_hda {

void IntelHDAController::WakeupIrqHandler() {
    LOG(SPEW, "Waking up IRQ handler\n");
    ZX_DEBUG_ASSERT(irq_wakeup_event_ != nullptr);
    irq_wakeup_event_->Signal();
}

fbl::RefPtr<IntelHDACodec> IntelHDAController::GetCodec(uint id) {
    ZX_DEBUG_ASSERT(id < countof(codecs_));
    fbl::AutoLock codec_lock(&codec_lock_);
    return codecs_[id];
}

void IntelHDAController::SnapshotRIRB() {
    fbl::AutoLock rirb_lock(&rirb_lock_);

    ZX_DEBUG_ASSERT(rirb_ && rirb_entry_count_ && rirb_mask_);
    uint8_t rirbsts = REG_RD(&regs()->rirbsts);

    unsigned int rirb_wr_ptr = REG_RD(&regs()->rirbwp) & rirb_mask_;
    unsigned int pending     = (rirb_entry_count_ + rirb_wr_ptr - rirb_rd_ptr_) & rirb_mask_;

    // Copy the current state of the RIRB into our snapshot memory.  Note: we
    // loop at most up to 2 times in order to deal with the case where the
    // active region of the ring buffer wraps around the end.
    //
    // TODO(johngro) : Make sure to invalidate cache for the memory region
    // occupied by the RIRB before we copy into our snapshot if we are running
    // on an architecure where cache coherency is not automatically managed for
    // us via. something like snooping, or by a un-cached policy set on our
    // mapped pages in the MMU. */
    rirb_snapshot_cnt_ = 0;
    while (pending) {
         /* Intel HDA ring buffers are strange, see comments in
          * intel_hda_codec_send_cmd. */
        unsigned int tmp_rd = (rirb_rd_ptr_ + 1) & rirb_mask_;
        unsigned int todo   = fbl::min(pending, (rirb_entry_count_ - tmp_rd));

        memcpy(rirb_snapshot_ + rirb_snapshot_cnt_,
               rirb_ + tmp_rd,
               sizeof(rirb_snapshot_[0]) * todo);

        rirb_rd_ptr_ = (rirb_rd_ptr_ + todo) & rirb_mask_;
        rirb_snapshot_cnt_ += todo;
        pending -= todo;
    }

    REG_WR(&regs()->rirbsts, rirbsts);

    ZX_DEBUG_ASSERT(!pending);

    LOG(SPEW, "RIRB has %u pending responses; WP is @%u\n", rirb_snapshot_cnt_, rirb_wr_ptr);

    if (rirbsts & HDA_REG_RIRBSTS_OIS) {
        // TODO(johngro) : Implement retry behavior for codec command and
        // control.
        //
        // The OIS bit in the RIRBSTS register indicates that hardware has
        // encountered a overrun while attempting to write to the Response Input
        // Ring Buffer.  IOW - responses were received, but the controller was
        // unable to write to system memory in time, and some of the responses
        // were lost.  This should *really* never happen.  If it does, all bets
        // are pretty much off.  Every command verb sent is supposed to receive
        // a response from the codecs; if a response is dropped it can easily
        // wedge a codec's command and control state machine.
        //
        // This problem is not limited to HW being unable to write to system
        // memory in time.  There is no HW read pointer for the RIRB.  The
        // implication of this is that HW has no way to know that it has overrun
        // SW if SW is not keeping up.  If this was to happen, there would be no
        // way for the system to know, it would just look like a large number of
        // responses were lost.
        //
        // In either case, the only mitigation we could possibly implement would
        // be a reasonable retry system at the codec driver level.
        //
        // Right now, we just log the error, ack the IRQ and move on.
        LOG(ERROR, "CRITICAL ERROR: controller overrun detected while "
                   "attempting to write to response input ring buffer.\n");
    }
}

void IntelHDAController::ProcessRIRB() {
    fbl::AutoLock rirb_lock(&rirb_lock_);
    ZX_DEBUG_ASSERT(rirb_snapshot_cnt_ < HDA_RIRB_MAX_ENTRIES);
    ZX_DEBUG_ASSERT(rirb_snapshot_cnt_ < rirb_entry_count_);

    for (unsigned int i = 0; i < rirb_snapshot_cnt_; ++i) {
        auto& resp = rirb_snapshot_[i];
        resp.OnReceived();  // Fixup endianness

        /* Figure out the codec this came from */
        uint32_t caddr = resp.caddr();

        /* Sanity checks */
        if (caddr >= countof(codecs_)) {
            LOG(ERROR, "Received %ssolicited response with illegal codec address (%u) "
                       "[0x%08x, 0x%08x]\n",
                       resp.unsolicited() ? "un" : "", caddr, resp.data, resp.data_ex);
            continue;
        }

        auto codec = GetCodec(caddr);
        if (!codec) {
            LOG(ERROR, "Received %ssolicited response for non-existent codec address (%u) "
                       "[0x%08x, 0x%08x]\n",
                       resp.unsolicited() ? "un" : "", caddr, resp.data, resp.data_ex);
            continue;
        }

        LOG(TRACE, "RX[%2u]: 0x%08x%s\n",
                   caddr, resp.data, resp.unsolicited() ? " (unsolicited)" : "");

        if (!resp.unsolicited()) {
            fbl::unique_ptr<CodecCmdJob> job;

            {
                fbl::AutoLock corb_lock(&corb_lock_);

                // If this was a solicited response, there needs to be an in-flight
                // job waiting at the head of the in-flight queue which triggered
                // it.
                if (in_flight_corb_jobs_.is_empty()) {
                    LOG(ERROR,
                        "Received solicited response for codec address (%u) [0x%08x, 0x%08x] "
                        "but no in-flight job is waiting for it\n",
                        caddr, resp.data, resp.data_ex);
                    continue;
                }

                // Grab the front of the in-flight queue.
                job = in_flight_corb_jobs_.pop_front();
            }

            // Sanity checks complete.  Pass the response and the job which
            // triggered it on to the codec.
            codec->ProcessSolicitedResponse(resp, fbl::move(job));
        } else {
            auto codec = GetCodec(caddr);
            if (!codec) {
                LOG(ERROR,
                    "Received unsolicited response for non-existent codec address (%u) "
                    "[0x%08x, 0x%08x]\n", caddr, resp.data, resp.data_ex);
                continue;
            }

            codec->ProcessUnsolicitedResponse(resp);
        }
    }

    rirb_snapshot_cnt_ = 0;
}

void IntelHDAController::SendCodecCmdLocked(CodecCommand cmd) {
    ZX_DEBUG_ASSERT(corb_space_ > 0);

    // Write the command into the ring buffer and update the SW shadow of the
    // write pointer.  We will update the HW write pointer later on when we
    // commit the new CORB commands.
    //
    // Note: Intel's ring buffers are a bit wonky.  See Section 4.4.1.4, but the
    // general idea is that to send a command, you do *not* write the command at
    // WP and then bump the WP.  Instead you write the command to (WP + 1) %
    // RING_SIZE, then update WP to be (WP + 1) % RING_SIZE.  IOW - The write
    // pointer always points to the last command written, not the place where
    // the next command will go.  This behavior holds in the RIRB direction as
    // well.
    corb_wr_ptr_ = (corb_wr_ptr_ + 1) & corb_mask_;
    corb_[corb_wr_ptr_].data = htole32(cmd.data);
    corb_space_--;
}

zx_status_t IntelHDAController::QueueCodecCmd(fbl::unique_ptr<CodecCmdJob>&& job) {
    ZX_DEBUG_ASSERT(job != nullptr);
    LOG(TRACE, "TX: Codec ID %u Node ID %hu Verb 0x%05x\n",
               job->codec_id(), job->nid(), job->verb().val);

    // Enter the lock, then check out the state of the ring buffer.  If the
    // buffer is full, or if there are already commands backed up into the
    // pending queue, just add the job to the end of the pending queue.
    // Otherwise, actually write the command into the CORB, add the job to the
    // end of the in-flight queue, and wakeup the IRQ thread.
    //
    fbl::AutoLock corb_lock(&corb_lock_);
    ZX_DEBUG_ASSERT(corb_wr_ptr_ < corb_entry_count_);
    ZX_DEBUG_ASSERT(corb_);

    if (!corb_space_) {
        // If we have no space in the CORB, there must be some jobs which are
        // currently in-flight.
        ZX_DEBUG_ASSERT(!in_flight_corb_jobs_.is_empty());
        pending_corb_jobs_.push_back(fbl::move(job));
    } else {
        // Alternatively, if there is space in the CORB, the pending job queue
        // had better be empty.
        ZX_DEBUG_ASSERT(pending_corb_jobs_.is_empty());
        SendCodecCmdLocked(job->command());
        in_flight_corb_jobs_.push_back(fbl::move(job));
    }

    CommitCORBLocked();

    return ZX_OK;
}

void IntelHDAController::ProcessCORB() {
    fbl::AutoLock corb_lock(&corb_lock_);

    // Check IRQ status for the CORB
    uint8_t corbsts = REG_RD(&regs()->corbsts);
    REG_WR(&regs()->corbsts, corbsts);

    if (corbsts & HDA_REG_CORBSTS_MEI) {
        // TODO(johngro) : Implement proper controller reset behavior.
        //
        // The MEI bit in CORBSTS indicates some form memory error detected by
        // the controller while attempting to read from system memory.  This is
        // Extremely Bad and should never happen.  If it does, the TRM suggests
        // that all bets are off, and the only reasonable action is to
        // completely shutdown and reset the controller.
        //
        // Right now, we do not implement this behavior.  Instead we log, then
        // assert in debug builds.  In release builds, we simply ack the
        // interrupt and move on.
        //
        LOG(ERROR, "CRITICAL ERROR: controller encountered an unrecoverable "
                   "error attempting to read from system memory!\n");
        ZX_DEBUG_ASSERT(false);
    }

    // Figure out how much space we have in the CORB
    ComputeCORBSpaceLocked();

    // While we have room in the CORB, and still have commands which are waiting
    // to be sent out, move commands from the pending queue into the in-flight
    // queue.
    LOG(SPEW, "CORB has space for %u commands; WP is @%u\n", corb_space_, corb_wr_ptr_);
    while (corb_space_ && !pending_corb_jobs_.is_empty()) {
        auto job = pending_corb_jobs_.pop_front();

        SendCodecCmdLocked(job->command());

        in_flight_corb_jobs_.push_back(fbl::move(job));
    }
    LOG(SPEW, "Update CORB WP; WP is @%u\n", corb_wr_ptr_);

    // Update the CORB write pointer.
    CommitCORBLocked();
}

void IntelHDAController::ComputeCORBSpaceLocked() {
    ZX_DEBUG_ASSERT(corb_entry_count_ && corb_mask_);
    ZX_DEBUG_ASSERT(corb_wr_ptr_ == REG_RD(&regs()->corbwp));

    unsigned int corb_rd_ptr = REG_RD(&regs()->corbrp) & corb_mask_;
    unsigned int corb_used   = (corb_entry_count_ + corb_wr_ptr_ - corb_rd_ptr) & corb_mask_;

    /* The way the Intel HDA command ring buffers work, it is impossible to ever
     * be using more than N - 1 of the ring buffer entries.  Our available
     * space should be the ring buffer size, minus the amt currently used, minus 1 */
    ZX_DEBUG_ASSERT(corb_entry_count_   >  corb_used);
    ZX_DEBUG_ASSERT(corb_max_in_flight_ >= corb_used);
    corb_space_ = corb_max_in_flight_ - corb_used;
}

void IntelHDAController::CommitCORBLocked() {
    // TODO(johngro) : Make sure to force a write back of the cache for the
    // dirty portions of the CORB before we update the write pointer if we are
    // running on an architecure where cache coherency is not automatically
    // managed for us via. snooping or by an explicit uncached or write-thru
    // policy set on our mapped pages in the MMU.
    ZX_DEBUG_ASSERT(regs());
    ZX_DEBUG_ASSERT(corb_entry_count_ && corb_mask_);
    ZX_DEBUG_ASSERT(corb_wr_ptr_ < corb_entry_count_);
    REG_WR(&regs()->corbwp, corb_wr_ptr_);
}

void IntelHDAController::ProcessStreamIRQ(uint32_t intsts) {
    for (uint32_t i = 0; intsts; i++, intsts >>= 1) {
        if (intsts & 0x1) {
            ZX_DEBUG_ASSERT(i < countof(all_streams_));
            ZX_DEBUG_ASSERT(all_streams_[i] != nullptr);
            all_streams_[i]->ProcessStreamIRQ();
        }
    }
}

void IntelHDAController::ProcessControllerIRQ() {
    // Start by checking for codec wake events.
    uint16_t statests = REG_RD(&regs()->statests) & HDA_REG_STATESTS_MASK;
    if (statests) {
        REG_WR(&regs()->statests, statests);
        uint32_t tmp = statests;
        for (uint8_t i = 0u; statests && (i < countof(codecs_)); ++i, tmp >>= 1) {
            if (!(tmp & 1u))
                continue;

            // TODO(johngro) : How is a codec supposed to signal a hot unplug
            // event?  Docs clearly indicate that they can be hot plugged, and
            // that you detect hot plug events by enabling wake events and
            // checking the STATESTS register when you receive one, but they
            // don't seem to give any indication of how to detect that a codec
            // has been unplugged.
            if (codecs_[i] == nullptr) {
                codecs_[i] = IntelHDACodec::Create(*this, i);

                // If we successfully created our codec, attempt to start it up.
                // If it fails to start, release our reference to the codec.
                if ((codecs_[i] != nullptr) && (codecs_[i]->Startup() != ZX_OK)) {
                    codecs_[i] = nullptr;
                }
            } else {
                codecs_[i]->ProcessWakeupEvt();
            }
        }
    }
}

zx_status_t IntelHDAController::HandleIrq() {
    if (GetState() != State::OPERATING) {
        LOG(WARN, "IRQ Handler shutting down due to invalid state (%u)!\n",
            static_cast<uint32_t>(GetState()));
        return ZX_ERR_BAD_STATE;
    }

    // Take a snapshot of any pending responses ASAP in order to minimize
    // the chance of an RIRB overflow.  We will process the responses which
    // we snapshot-ed in a short while after we are done handling other
    // important IRQ tasks.
    SnapshotRIRB();

    // Fetch the interrupt status word and dispatch as appropriate
    uint32_t intsts = REG_RD(&regs()->intsts);

    if (intsts & HDA_REG_INTCTL_SIE_MASK)
        ProcessStreamIRQ(intsts & HDA_REG_INTCTL_SIE_MASK);

    if (intsts & HDA_REG_INTCTL_CIE)
        ProcessControllerIRQ();

    if (dsp_ != nullptr) {
        dsp_->ProcessIRQ();
    }

    ProcessRIRB();
    ProcessCORB();

    return ZX_OK;
}

}  // namespace intel_hda
}  // namespace audio
