// 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 <audio-proto-utils/format-utils.h>
#include <ddk/debug.h>
#include <ddk/device.h>
#include <ddk/protocol/composite.h>
#include <ddk/protocol/platform-device-lib.h>
#include <lib/zx/vmar.h>
#include <limits>
#include <string.h>
#include <utility>
#include <zircon/device/audio.h>

#include "dispatcher-pool/dispatcher-thread-pool.h"
#include "tas57xx.h"
#include "tdm-audio-stream.h"

namespace audio {
namespace gauss {

enum {
    COMPONENT_PDEV,
    COMPONENT_I2C,
    COMPONENT_COUNT,
};

// Device FIDL thunks
fuchsia_hardware_audio_Device_ops_t TdmOutputStream::AUDIO_FIDL_THUNKS {
    .GetChannel = [](void* ctx, fidl_txn_t* txn) -> zx_status_t {
                        return reinterpret_cast<TdmOutputStream*>(ctx)->GetChannel(txn);
                   },
};

#define RegOffset(field) offsetof(aml_tdm_regs_t, field)

TdmOutputStream::~TdmOutputStream() {}

// static
zx_status_t TdmOutputStream::Create(zx_device_t* parent) {
    auto domain = dispatcher::ExecutionDomain::Create();
    if (domain == nullptr) {
        return ZX_ERR_NO_MEMORY;
    }
    auto stream = fbl::AdoptRef(
        new TdmOutputStream(parent, std::move(domain)));

    composite_protocol_t composite;
    zx_status_t res = device_get_protocol(parent, ZX_PROTOCOL_COMPOSITE, &composite);
    if (res != ZX_OK) {
        zxlogf(ERROR, "Could not get composite protocol\n");
        return res;
    }

    zx_device_t* components[COMPONENT_COUNT]; 
    size_t actual;
    composite_get_components(&composite, components, fbl::count_of(components), &actual);
    if (actual != countof(components)) {
        zxlogf(ERROR, "could not get components\n");
        return ZX_ERR_NOT_SUPPORTED;
    }

    res = device_get_protocol(components[COMPONENT_PDEV], ZX_PROTOCOL_PDEV, &stream->pdev_);
    if (res != ZX_OK) {
        return res;
    }

    res = pdev_get_bti(&stream->pdev_, 0, stream->bti_.reset_and_get_address());
    if (res != ZX_OK) {
        return res;
    }

    mmio_buffer_t mmio;
    res = pdev_map_mmio_buffer(&stream->pdev_, 0, ZX_CACHE_POLICY_UNCACHED_DEVICE, &mmio);

    if (res != ZX_OK) {
        zxlogf(ERROR, "tdm-output-driver: failed to map mmio.\n");
        return res;
    }
    stream->mmio_ = ddk::MmioBuffer(mmio);

    stream->SetModuleClocks();

    //Sleep to let clocks stabilize in amps.
    zx_nanosleep(zx_deadline_after(ZX_MSEC(20)));

    res = device_get_protocol(components[COMPONENT_I2C], ZX_PROTOCOL_I2C, &stream->i2c_);
    if ( res != ZX_OK) {
        zxlogf(ERROR,"tdm-output-driver: failed to acquire i2c\n");
        return res;
    }

    stream->left_sub_ = Tas57xx::Create(&stream->i2c_, 0);
    if (!stream->left_sub_) {
        return ZX_ERR_NO_RESOURCES;
    }

    stream->right_sub_ = Tas57xx::Create(&stream->i2c_, 1);
    if (!stream->right_sub_) {
        return ZX_ERR_NO_RESOURCES;
    }
    stream->tweeters_ = Tas57xx::Create(&stream->i2c_, 2);
    if (!stream->tweeters_) {
        return ZX_ERR_NO_RESOURCES;
    }

    /*TODO(hollande) - right now we are getting the irq via pdev, but would also like
                       a way to push down which tdm block and frddr blocks to use. will hard
                       code to TDMC and FRDDRC for now.
    */

    stream->notify_timer_ = dispatcher::Timer::Create();
    dispatcher::Timer::ProcessHandler thandler(
            [tdm = stream](dispatcher::Timer * timer)->zx_status_t {
                OBTAIN_EXECUTION_DOMAIN_TOKEN(t, tdm->default_domain_);
                return tdm->ProcessRingNotification();
            });

    stream->notify_timer_->Activate(stream->default_domain_, std::move(thandler));

    res = stream->Bind("tdm-output-driver");
    // if successful, we need to leak the stream reference since it holds this object
    //  and would otherwise go away once leaving scope of Create.
    //  Note: clang and gcc feel differently about different ways of doing this
    //        operation, below is a compromisse to appease both simultaneously.
    if (res == ZX_OK) {
        __UNUSED auto dummy = stream.leak_ref();
    }

    return ZX_OK;
}

zx_status_t TdmOutputStream::Bind(const char* devname) {
    ZX_DEBUG_ASSERT(!supported_formats_.size());

    zx_status_t res = AddFormats(&supported_formats_);
    if (res != ZX_OK) {
        zxlogf(ERROR,"Failed to add formats\n");
        return res;
    }

    left_sub_->Standby();
    left_sub_->Reset();
    left_sub_->Init(0);
    left_sub_->SetGain(current_gain_);
    left_sub_->ExitStandby();

    right_sub_->Standby();
    right_sub_->Reset();
    right_sub_->Init(1);
    right_sub_->SetGain(current_gain_);
    right_sub_->ExitStandby();

    tweeters_->Standby();
    tweeters_->Reset();
    tweeters_->Init(0);
    tweeters_->SetGain(current_gain_);
    tweeters_->ExitStandby();

    return TdmAudioStreamBase::DdkAdd(devname);
}

void TdmOutputStream::ReleaseRingBufferLocked() {
    io_buffer_release(&ring_buffer_);
}

zx_status_t TdmOutputStream::AddFormats(
        fbl::Vector<audio_stream_format_range_t>* supported_formats) {
    if (!supported_formats)
        return ZX_ERR_INVALID_ARGS;

    // Record the min/max number of channels.
    audio_stream_format_range_t range;
    range.min_channels = 2;
    range.max_channels = 2;
    range.sample_formats = AUDIO_SAMPLE_FORMAT_16BIT;
    range.min_frames_per_second = 48000;
    range.max_frames_per_second = 48000;

    fbl::AllocChecker ac;
    supported_formats->reserve(1, &ac);
    if (!ac.check()) {
        return ZX_ERR_NO_MEMORY;
    }
    range.flags = ASF_RANGE_FLAG_FPS_CONTINUOUS;

    supported_formats->push_back(range);

    return ZX_OK;
}

void TdmOutputStream::DdkUnbind() {
    // Close all of our client event sources if we have not already.
    default_domain_->Deactivate();
    // Quiet the data being output on tdm
    mmio_->ClearBits32(1 << 31, RegOffset(tdmout[TDM_OUT_C].ctl0));
    // TODO(hollande) - implement more thorough teardown/reset of the hw state.

    // Unpublish our device node.
    DdkRemove();
}

void TdmOutputStream::DdkRelease() {
    // Ensure execution domain has successfully deactivated.
    ZX_DEBUG_ASSERT(!default_domain_ || default_domain_->deactivated());
    // Reclaim our reference from the driver framework and let it go out of
    // scope.  If this is our last reference (it should be), we will destruct
    // immediately afterwards.
    auto thiz = fbl::internal::MakeRefPtrNoAdopt(this);
}

zx_status_t TdmOutputStream::GetChannel(fidl_txn_t* txn) {
    fbl::AutoLock lock(&lock_);

    // Attempt to allocate a new driver channel and bind it to us.  If we don't
    // already have an stream_channel_, flag this channel is the privileged
    // connection (The connection which is allowed to do things like change
    // formats).
    bool privileged = (stream_channel_ == nullptr);
    auto channel = dispatcher::Channel::Create();
    if (channel == nullptr)
        return ZX_ERR_NO_MEMORY;

    dispatcher::Channel::ProcessHandler phandler(
        [ stream = fbl::WrapRefPtr(this), privileged ](dispatcher::Channel * channel)->zx_status_t {
            OBTAIN_EXECUTION_DOMAIN_TOKEN(t, stream->default_domain_);
            return stream->ProcessStreamChannel(channel, privileged);
        });

    dispatcher::Channel::ChannelClosedHandler chandler;
    if (privileged) {
        chandler = dispatcher::Channel::ChannelClosedHandler(
            [stream = fbl::WrapRefPtr(this)](const dispatcher::Channel* channel)->void {
                OBTAIN_EXECUTION_DOMAIN_TOKEN(t, stream->default_domain_);
                stream->DeactivateStreamChannel(channel);
            });
    }

    zx::channel client_endpoint;
    zx_status_t res = channel->Activate(&client_endpoint,
                                        default_domain_,
                                        std::move(phandler),
                                        std::move(chandler));
    if (res == ZX_OK) {
        if (privileged) {
            ZX_DEBUG_ASSERT(stream_channel_ == nullptr);
            stream_channel_ = channel;
        }

        return fuchsia_hardware_audio_DeviceGetChannel_reply(txn, client_endpoint.release());
    }

    return res;
}

#define HREQ(_cmd, _payload, _handler, _allow_noack, ...)             \
    case _cmd:                                                        \
        if (req_size != sizeof(req._payload)) {                       \
            zxlogf(ERROR, "Bad " #_cmd                                \
                          " response length (%u != %zu)\n",           \
                   req_size, sizeof(req._payload));                   \
            return ZX_ERR_INVALID_ARGS;                               \
        }                                                             \
        if (!_allow_noack && (req.hdr.cmd & AUDIO_FLAG_NO_ACK)) {     \
            zxlogf(ERROR, "NO_ACK flag not allowed for " #_cmd "\n"); \
            return ZX_ERR_INVALID_ARGS;                               \
        }                                                             \
        return _handler(channel, req._payload, ##__VA_ARGS__);
zx_status_t TdmOutputStream::ProcessStreamChannel(dispatcher::Channel* channel, bool privileged) {
    ZX_DEBUG_ASSERT(channel != nullptr);
    fbl::AutoLock lock(&lock_);

    union {
        audio_proto::CmdHdr hdr;
        audio_proto::StreamGetFmtsReq get_formats;
        audio_proto::StreamSetFmtReq set_format;
        audio_proto::GetGainReq get_gain;
        audio_proto::SetGainReq set_gain;
        audio_proto::PlugDetectReq plug_detect;
        audio_proto::GetUniqueIdReq get_unique_id;
        audio_proto::GetStringReq get_string;
        // TODO(hollande): add more commands here
    } req;

    static_assert(sizeof(req) <= 256,
                  "Request buffer is getting to be too large to hold on the stack!");

    uint32_t req_size;
    zx_status_t res = channel->Read(&req, sizeof(req), &req_size);
    if (res != ZX_OK)
        return res;

    if ((req_size < sizeof(req.hdr) ||
         (req.hdr.transaction_id == AUDIO_INVALID_TRANSACTION_ID)))
        return ZX_ERR_INVALID_ARGS;

    // Strip the NO_ACK flag from the request before selecting the dispatch target.
    auto cmd = static_cast<audio_proto::Cmd>(req.hdr.cmd & ~AUDIO_FLAG_NO_ACK);
    switch (cmd) {
        HREQ(AUDIO_STREAM_CMD_GET_FORMATS, get_formats, OnGetStreamFormatsLocked, false);
        HREQ(AUDIO_STREAM_CMD_SET_FORMAT, set_format, OnSetStreamFormatLocked, false, privileged);
        HREQ(AUDIO_STREAM_CMD_GET_GAIN, get_gain, OnGetGainLocked, false);
        HREQ(AUDIO_STREAM_CMD_SET_GAIN, set_gain, OnSetGainLocked, true);
        HREQ(AUDIO_STREAM_CMD_PLUG_DETECT, plug_detect, OnPlugDetectLocked, true);
        HREQ(AUDIO_STREAM_CMD_GET_UNIQUE_ID, get_unique_id, OnGetUniqueIdLocked, false);
        HREQ(AUDIO_STREAM_CMD_GET_STRING, get_string, OnGetStringLocked, false);
    default:
        zxlogf(ERROR, "Unrecognized stream command 0x%04x\n", req.hdr.cmd);
        return ZX_ERR_NOT_SUPPORTED;
    }
}

zx_status_t TdmOutputStream::ProcessRingBufferChannel(dispatcher::Channel* channel) {
    ZX_DEBUG_ASSERT(channel != nullptr);
    fbl::AutoLock lock(&lock_);

    union {
        audio_proto::CmdHdr hdr;
        audio_proto::RingBufGetFifoDepthReq get_fifo_depth;
        audio_proto::RingBufGetBufferReq get_buffer;
        audio_proto::RingBufStartReq rb_start;
        audio_proto::RingBufStopReq rb_stop;
        // TODO(almasrymina): add more commands here
    } req;

    static_assert(sizeof(req) <= 256,
                  "Request buffer is getting to be too large to hold on the stack!");

    uint32_t req_size;
    zx_status_t res = channel->Read(&req, sizeof(req), &req_size);
    if (res != ZX_OK)
        return res;

    if ((req_size < sizeof(req.hdr) ||
         (req.hdr.transaction_id == AUDIO_INVALID_TRANSACTION_ID)))
        return ZX_ERR_INVALID_ARGS;

    // Strip the NO_ACK flag from the request before selecting the dispatch target.
    auto cmd = static_cast<audio_proto::Cmd>(req.hdr.cmd & ~AUDIO_FLAG_NO_ACK);
    switch (cmd) {
        HREQ(AUDIO_RB_CMD_GET_FIFO_DEPTH, get_fifo_depth, OnGetFifoDepthLocked, false);
        HREQ(AUDIO_RB_CMD_GET_BUFFER, get_buffer, OnGetBufferLocked, false);
        HREQ(AUDIO_RB_CMD_START, rb_start, OnStartLocked, false);
        HREQ(AUDIO_RB_CMD_STOP, rb_stop, OnStopLocked, false);
    default:
        zxlogf(ERROR, "Unrecognized ring buffer command 0x%04x\n", req.hdr.cmd);
        return ZX_ERR_NOT_SUPPORTED;
    }

    return ZX_ERR_NOT_SUPPORTED;
}
#undef HREQ

zx_status_t TdmOutputStream::OnGetStreamFormatsLocked(
        dispatcher::Channel* channel,
        const audio_proto::StreamGetFmtsReq& req) const {
    ZX_DEBUG_ASSERT(channel != nullptr);
    uint16_t formats_sent = 0;
    audio_proto::StreamGetFmtsResp resp = { };

    if (supported_formats_.size() > std::numeric_limits<uint16_t>::max()) {
        zxlogf(ERROR,
                "Too many formats (%zu) to send during AUDIO_STREAM_CMD_GET_FORMATS request!\n",
               supported_formats_.size());
        return ZX_ERR_INTERNAL;
    }

    resp.hdr = req.hdr;
    resp.format_range_count = static_cast<uint16_t>(supported_formats_.size());

    do {
        uint16_t todo, payload_sz;
        zx_status_t res;

        todo = fbl::min<uint16_t>(static_cast<uint16_t>(supported_formats_.size() - formats_sent),
                                  AUDIO_STREAM_CMD_GET_FORMATS_MAX_RANGES_PER_RESPONSE);
        payload_sz = static_cast<uint16_t>(sizeof(resp.format_ranges[0]) * todo);

        resp.first_format_range_ndx = formats_sent;
        ::memcpy(resp.format_ranges, supported_formats_.get() + formats_sent, payload_sz);

        res = channel->Write(&resp, sizeof(resp));
        if (res != ZX_OK) {
            zxlogf(ERROR, "Failed to send get stream formats response (res %d)\n", res);
            return res;
        }

        formats_sent = (uint16_t)(formats_sent + todo);
    } while (formats_sent < supported_formats_.size());

    return ZX_OK;
}

zx_status_t TdmOutputStream::OnSetStreamFormatLocked(dispatcher::Channel* channel,
                                                     const audio_proto::StreamSetFmtReq& req,
                                                     bool privileged) {
    ZX_DEBUG_ASSERT(channel != nullptr);

    zx::channel client_rb_channel;
    audio_proto::StreamSetFmtResp resp = { };
    bool found_one = false;

    resp.hdr = req.hdr;

    // Only the privileged stream channel is allowed to change the format.
    if (!privileged) {
        ZX_DEBUG_ASSERT(channel == stream_channel_.get());
        resp.result = ZX_ERR_ACCESS_DENIED;
        goto finished;
    }

    // Check the format for compatibility
    for (const auto& fmt : supported_formats_) {
        if (audio::utils::FormatIsCompatible(req.frames_per_second,
                                             req.channels,
                                             req.sample_format,
                                             fmt)) {
            found_one = true;
            break;
        }
    }

    if (!found_one) {
        resp.result = ZX_ERR_INVALID_ARGS;
        goto finished;
    }

    // Determine the frame size.
    frame_size_ = audio::utils::ComputeFrameSize(req.channels, req.sample_format);
    if (!frame_size_) {
        zxlogf(ERROR, "Failed to compute frame size (ch %hu fmt 0x%08x)\n", req.channels,
               req.sample_format);
        resp.result = ZX_ERR_INTERNAL;
        goto finished;
    }

    // Looks like we are going ahead with this format change.  Tear down any
    // exiting ring buffer interface before proceeding.
    if (rb_channel_ != nullptr) {
        rb_channel_->Deactivate();
        rb_channel_.reset();
    }

    //A fifo is 256x64bit, B/C fifos are 128x64bit
    //  We are using the C fifo.
    fifo_bytes_ = kFifoDepth * 8;    // each fifo entry is 64bits wide

    // Create a new ring buffer channel which can be used to move bulk data and
    // bind it to us.
    rb_channel_ = dispatcher::Channel::Create();
    if (rb_channel_ == nullptr) {
        resp.result = ZX_ERR_NO_MEMORY;
    } else {
        dispatcher::Channel::ProcessHandler phandler(
            [stream = fbl::WrapRefPtr(this)](dispatcher::Channel * channel)->zx_status_t {
                OBTAIN_EXECUTION_DOMAIN_TOKEN(t, stream->default_domain_);
                return stream->ProcessRingBufferChannel(channel);
            });

        dispatcher::Channel::ChannelClosedHandler chandler(
            [stream = fbl::WrapRefPtr(this)](const dispatcher::Channel* channel)->void {
                OBTAIN_EXECUTION_DOMAIN_TOKEN(t, stream->default_domain_);
                stream->DeactivateRingBufferChannel(channel);
            });

        resp.result = rb_channel_->Activate(&client_rb_channel,
                                            default_domain_,
                                            std::move(phandler),
                                            std::move(chandler));
        if (resp.result != ZX_OK) {
            rb_channel_.reset();
        }
    }

finished:
    if (resp.result == ZX_OK) {
        // TODO(johngro): Report the actual external delay.
        resp.external_delay_nsec = 0;
        return channel->Write(&resp, sizeof(resp), std::move(client_rb_channel));
    } else {
        return channel->Write(&resp, sizeof(resp));
    }
}

zx_status_t TdmOutputStream::OnGetGainLocked(dispatcher::Channel* channel,
                                             const audio_proto::GetGainReq& req) const {
    ZX_DEBUG_ASSERT(channel != nullptr);
    audio_proto::GetGainResp resp = { };

    resp.hdr = req.hdr;
    resp.cur_mute = false;
    resp.cur_gain = current_gain_;
    resp.can_mute = false;
    resp.min_gain = -103.0;
    resp.max_gain = 20.0;
    resp.gain_step = 0.5;

    return channel->Write(&resp, sizeof(resp));
}

zx_status_t TdmOutputStream::OnSetGainLocked(dispatcher::Channel* channel,
                                             const audio_proto::SetGainReq& req) {
    ZX_DEBUG_ASSERT(channel != nullptr);
    if (req.hdr.cmd & AUDIO_FLAG_NO_ACK)
        return ZX_OK;

    audio_proto::SetGainResp resp = { };
    resp.hdr = req.hdr;


    bool illegal_mute = (req.flags & AUDIO_SGF_MUTE_VALID) && (req.flags & AUDIO_SGF_MUTE);
    bool illegal_gain = (req.flags & AUDIO_SGF_GAIN_VALID) && (!left_sub_->ValidGain(req.gain));

    if (!illegal_gain) {
        left_sub_->SetGain(req.gain);
        right_sub_->SetGain(req.gain);
        tweeters_->SetGain(req.gain);
        left_sub_->GetGain(&current_gain_);
    }

    resp.cur_mute = false;
    resp.cur_gain = current_gain_;
    resp.result = (illegal_mute || illegal_gain)
                      ? ZX_ERR_INVALID_ARGS
                      : ZX_OK;

    return channel->Write(&resp, sizeof(resp));
}

zx_status_t TdmOutputStream::OnPlugDetectLocked(dispatcher::Channel* channel,
                                                const audio_proto::PlugDetectReq& req) {
    if (req.hdr.cmd & AUDIO_FLAG_NO_ACK)
        return ZX_OK;

    audio_proto::PlugDetectResp resp = { };
    resp.hdr = req.hdr;
    resp.flags = static_cast<audio_pd_notify_flags_t>(AUDIO_PDNF_HARDWIRED |
                                                      AUDIO_PDNF_PLUGGED);
    return channel->Write(&resp, sizeof(resp));
}

zx_status_t TdmOutputStream::OnGetUniqueIdLocked(dispatcher::Channel* channel,
                                                 const audio_proto::GetUniqueIdReq& req) const {
    audio_proto::GetUniqueIdResp resp;

    static const audio_stream_unique_id_t spkr_id = AUDIO_STREAM_UNIQUE_ID_BUILTIN_SPEAKERS;
    resp.hdr = req.hdr;
    resp.unique_id = spkr_id;

    return channel->Write(&resp, sizeof(resp));
}

zx_status_t TdmOutputStream::OnGetStringLocked(dispatcher::Channel* channel,
                                               const audio_proto::GetStringReq& req) const {
    audio_proto::GetStringResp resp;

    resp.hdr = req.hdr;
    resp.id = req.id;

    const char* str;
    switch (req.id) {
        case AUDIO_STREAM_STR_ID_MANUFACTURER: str = "Gauss"; break;
        case AUDIO_STREAM_STR_ID_PRODUCT:      str = "Builtin Speakers"; break;
        default:                               str = nullptr; break;
    }

    if (str == nullptr) {
        resp.result = ZX_ERR_NOT_FOUND;
        resp.strlen = 0;
    } else {
        int res = snprintf(reinterpret_cast<char*>(resp.str), sizeof(resp.str), "%s", str);
        ZX_DEBUG_ASSERT(res >= 0);
        resp.result = ZX_OK;
        resp.strlen = fbl::min<uint32_t>(res, sizeof(resp.str) - 1);
    }

    return channel->Write(&resp, sizeof(resp));
}

zx_status_t TdmOutputStream::OnGetFifoDepthLocked(
        dispatcher::Channel* channel,
        const audio_proto::RingBufGetFifoDepthReq& req) const {
    audio_proto::RingBufGetFifoDepthResp resp = { };

    resp.hdr = req.hdr;
    resp.result = ZX_OK;
    resp.fifo_depth = fifo_bytes_;

    return channel->Write(&resp, sizeof(resp));
}

zx_status_t TdmOutputStream::SetModuleClocks() {

    /* enable mclk c
       select mpll2 as source - 245758771.206Hz
       divide clock source by 2 to get tdm mclk
       divide mclk by 10 to get 12287938.5603 Hz SCLK
       SCLK is 256 x fs => 47999.7600012 frames per sec
    */
    mmio_->Write32((1 << 31) | (2 << 24) | (9), RegOffset(mclk_ctl[MCLK_C]));

    // configure mst_sclk_gen
    mmio_->Write32((0x03 << 30) | (1 << 20) | (0 << 10) | 255, RegOffset(sclk_ctl[MCLK_C].ctl0));
    mmio_->Write32(0x1, RegOffset(sclk_ctl[MCLK_C].ctl1));

    mmio_->Write32((0x03 << 30) | (2 << 24) | (2 << 20), RegOffset(clk_tdmout_ctl[TDM_OUT_C]));

    // Enable clock gates for PDM and TDM blocks
    mmio_->SetBits32((1 << 8) | (1 << 11), RegOffset(clk_gate_en));
    return ZX_OK;
}

zx_status_t TdmOutputStream::OnGetBufferLocked(dispatcher::Channel* channel,
                                               const audio_proto::RingBufGetBufferReq& req) {
    audio_proto::RingBufGetBufferResp resp = { };
    zx::vmo client_rb_handle;
    uint32_t client_rights;

    resp.hdr = req.hdr;
    resp.result = ZX_ERR_INTERNAL;

    // Unmap and release any previous ring buffer.
    ReleaseRingBufferLocked();

    // Compute the ring buffer size.  It needs to be at least as big
    // as the virtual fifo depth.
    ZX_DEBUG_ASSERT(frame_size_ && ((fifo_bytes_ % frame_size_) == 0));
    ZX_DEBUG_ASSERT(fifo_bytes_ && ((fifo_bytes_ % fifo_bytes_) == 0));
    ring_buffer_size_ = req.min_ring_buffer_frames;
    ring_buffer_size_ *= frame_size_;
    if (ring_buffer_size_ < fifo_bytes_)
        ring_buffer_size_ = fbl::round_up(fifo_bytes_, frame_size_);

    // TODO - (hollande) Make this work with non contig vmo
    resp.result = io_buffer_init(&ring_buffer_, bti_.get(), ring_buffer_size_,
                                 IO_BUFFER_RW | IO_BUFFER_CONTIG);
    if (resp.result != ZX_OK) {
        zxlogf(ERROR, "Failed to create ring buffer (size %u, res %d)\n", ring_buffer_size_,
               resp.result);
        goto finished;
    }
    ring_buffer_phys_ = (uint32_t)io_buffer_phys(&ring_buffer_);
    ring_buffer_virt_ = io_buffer_virt(&ring_buffer_);

    uint32_t bytes_per_notification;
    if (req.notifications_per_ring) {
        bytes_per_notification = ring_buffer_size_ / req.notifications_per_ring;
    } else {
        bytes_per_notification = 0;
    }
    //TODO - (hollande) calculate this with current rate;
    us_per_notification_ = (1000 * bytes_per_notification) /(48 * frame_size_);

    // Create the client's handle to the ring buffer vmo and set it back to them.
    client_rights = ZX_RIGHT_TRANSFER | ZX_RIGHT_MAP | ZX_RIGHT_READ | ZX_RIGHT_WRITE;

    zx_handle_t vmo_copy;
    resp.result = zx_handle_duplicate(ring_buffer_.vmo_handle, client_rights, &vmo_copy);
    if (resp.result != ZX_OK) {
        zxlogf(ERROR, "Failed to duplicate ring buffer handle (res %d)\n", resp.result);
        goto finished;
    }
    client_rb_handle.reset(vmo_copy);
    resp.num_ring_buffer_frames = ring_buffer_size_ / frame_size_;

finished:
    zx_status_t res;
    if (resp.result == ZX_OK) {
        ZX_DEBUG_ASSERT(client_rb_handle.is_valid());
        res = channel->Write(&resp, sizeof(resp), std::move(client_rb_handle));
    } else {
        res = channel->Write(&resp, sizeof(resp));
    }

    if (res != ZX_OK) {
        zxlogf(ERROR,"Error in ring buffer creation\n");
        ReleaseRingBufferLocked();
    }

    return res;
}

zx_status_t TdmOutputStream::ProcessRingNotification() {

    if (running_) {
        notify_timer_->Arm(zx_deadline_after(ZX_USEC(us_per_notification_)));
    } else {
        notify_timer_->Cancel();
    }

    audio_proto::RingBufPositionNotify resp = { };
    resp.hdr.cmd = AUDIO_RB_POSITION_NOTIFY;

    resp.ring_buffer_pos = mmio_->Read32(RegOffset(frddr[2].status2)) - ring_buffer_phys_;

    fbl::AutoLock lock(&lock_);
    if (rb_channel_) {
        return rb_channel_->Write(&resp, sizeof(resp));
    } else {
        zxlogf(ERROR,"RingBufferNotification Failed - rb channel closed\n");
        //return ok so the Timer can live on for later use.
        return ZX_OK;
    }
}

zx_status_t TdmOutputStream::OnStartLocked(dispatcher::Channel* channel,
                                           const audio_proto::RingBufStartReq& req) {

    running_ = true;
    if (us_per_notification_ > 0) {
        notify_timer_->Arm(zx_deadline_after(ZX_USEC(us_per_notification_)));
    }

    audio_proto::RingBufStartResp resp = { };

    resp.hdr = req.hdr;
    resp.result = ZX_OK;

    mmio_->SetBits32((1 << 31) | (1 << 6), RegOffset(arb_ctl));

    mmio_->Write32((2 << 0), RegOffset(frddr[2].ctl0));
    // Set fifo depth and threshold to half the depth
    mmio_->Write32((kFifoDepth << 24) | ((kFifoDepth / 2) << 16) | (0 << 8),
                   RegOffset(frddr[2].ctl1));

    mmio_->Write32((uint32_t)ring_buffer_phys_, RegOffset(frddr[2].start_addr));
    mmio_->Write32((uint32_t)(ring_buffer_phys_ + ring_buffer_size_ - 8),
                   RegOffset(frddr[2].finish_addr));

    mmio_->Write32((1 << 15) | (7 << 5 ) | (31 << 0), RegOffset(tdmout[TDM_OUT_C].ctl0));

    mmio_->Write32((15 << 8) | (2 << 24) | (2  << 4), RegOffset(tdmout[TDM_OUT_C].ctl1));

    mmio_->Write32(0x00000003, RegOffset(tdmout[TDM_OUT_C].mask[0]));
    mmio_->Write32(0x00000010, RegOffset(tdmout[TDM_OUT_C].swap));
    mmio_->Write32(0x00000000, RegOffset(tdmout[TDM_OUT_C].mask_val));
    mmio_->Write32(0x00000000, RegOffset(tdmout[TDM_OUT_C].mute_val));

    //reset the module
    mmio_->ClearBits32(3 << 28, RegOffset(tdmout[TDM_OUT_C].ctl0));
    mmio_->SetBits32(1 << 29, RegOffset(tdmout[TDM_OUT_C].ctl0));
    mmio_->SetBits32(1 << 28, RegOffset(tdmout[TDM_OUT_C].ctl0));

    //enable frddr
    mmio_->SetBits32(1 << 31, RegOffset(frddr[TDM_OUT_C].ctl0));

    //enable tdmout
    mmio_->SetBits32(1 << 31, RegOffset(tdmout[TDM_OUT_C].ctl0));

    resp.start_time = zx_clock_get_monotonic();
    return channel->Write(&resp, sizeof(resp));
}

zx_status_t TdmOutputStream::OnStopLocked(dispatcher::Channel* channel,
                                          const audio_proto::RingBufStopReq& req) {
    notify_timer_->Cancel();
    mmio_->ClearBits32(1 << 31, RegOffset(tdmout[TDM_OUT_C].ctl0));
    running_ = false;
    audio_proto::RingBufStopResp resp = { };
    resp.hdr = req.hdr;
    resp.result = ZX_OK;
    return channel->Write(&resp, sizeof(resp));
}

void TdmOutputStream::DeactivateStreamChannel(const dispatcher::Channel* channel) {
    fbl::AutoLock lock(&lock_);

    ZX_DEBUG_ASSERT(stream_channel_.get() == channel);
    ZX_DEBUG_ASSERT(rb_channel_.get() != channel);
    stream_channel_.reset();
}

void TdmOutputStream::DeactivateRingBufferChannel(const dispatcher::Channel* channel) {
    notify_timer_->Cancel();
    fbl::AutoLock lock(&lock_);

    ZX_DEBUG_ASSERT(stream_channel_.get() != channel);
    ZX_DEBUG_ASSERT(rb_channel_.get() == channel);

    rb_channel_.reset();
}

} // namespace gauss
} // namespace audio

extern "C" zx_status_t gauss_tdm_bind(void* ctx, zx_device_t* device, void** cookie) {
    audio::gauss::TdmOutputStream::Create(device);
    return ZX_OK;
}

extern "C" void gauss_tdm_release(void*) {
    dispatcher::ThreadPool::ShutdownAll();
}
