// 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.

#pragma once

#include <ddk/device.h>
#include <fbl/macros.h>
#include <fbl/ref_ptr.h>
#include <limits.h>
#include <lib/fzl/vmar-manager.h>
#include <lib/zx/bti.h>
#include <lib/zx/channel.h>
#include <lib/zx/vmo.h>
#include <zircon/types.h>

#include <dispatcher-pool/dispatcher-channel.h>

namespace audio {
namespace intel_hda {

// Constants

// HDA controllers can have at most 30 stream contexts.
constexpr size_t MAX_STREAMS_PER_CONTROLLER = 30;

// CORB/RIRB should take no more than a page
constexpr size_t MAPPED_CORB_RIRB_SIZE = PAGE_SIZE;

// Individual BDLs should be 1 page each
constexpr size_t MAPPED_BDL_SIZE = PAGE_SIZE;

#define _SIC_ static inline constexpr
template <typename T> _SIC_ T  OR(T x, T y) { return static_cast<T>(x | y); }
template <typename T> _SIC_ T AND(T x, T y) { return static_cast<T>(x & y); }
#undef _SIC_

// Static container for the driver wide VMARs that we stash all of our register
// mappings in, in order to make efficient use of kernel PTEs
class DriverVmars {
  public:
    static zx_status_t Initialize();
    static void Shutdown();
    static const fbl::RefPtr<fzl::VmarManager>& registers() {
        return registers_;
    }
  private:
    static fbl::RefPtr<fzl::VmarManager> registers_;
};

struct StreamFormat {
    // Stream format bitfields documented in section 3.7.1
    static constexpr uint16_t FLAG_NON_PCM = (1u << 15);

    constexpr StreamFormat() { }
    explicit constexpr StreamFormat(uint16_t raw_data) : raw_data_(raw_data) { }

    uint32_t BASE() const { return (raw_data_ & (1u << 14)) ? 44100 : 48000; }
    uint32_t CHAN() const { return (raw_data_ & 0xF) + 1; }
    uint32_t DIV()  const { return ((raw_data_ >> 8) & 0x7) + 1; }
    uint32_t MULT() const {
        uint32_t bits = (raw_data_ >> 11) & 0x7;
        if (bits >= 4)
            return 0;
        return bits + 1;
    }
    uint32_t BITS_NDX() const { return (raw_data_ >> 4) & 0x7; }
    uint32_t BITS() const {
        switch (BITS_NDX()) {
        case 0: return 8u;
        case 1: return 16u;
        case 2: return 20u;
        case 3: return 24u;
        case 4: return 32u;
        default: return 0u;
        }
    }

    bool     is_pcm()        const { return (raw_data_ & FLAG_NON_PCM) == 0; }
    uint32_t sample_rate()   const { return (BASE() * MULT()) / DIV(); }
    uint32_t channels()      const { return CHAN(); }
    uint32_t bits_per_chan() const { return BITS(); }

    uint32_t bytes_per_frame() const {
        uint32_t ret = CHAN();
        switch (BITS_NDX()) {
        case 0: return ret;
        case 1: return ret << 1;
        case 2:
        case 3:
        case 4: return ret << 2;
        default: return 0u;
        }

    }

    bool SanityCheck() const {
        if (raw_data_ == 0x8000)
            return true;

        if (raw_data_ & 0x8080)
            return false;

        return (BITS() && MULT());
    }

    uint16_t raw_data_ = 0;
};

// Boilerplate code to handle an IOCTL request to create a channel from an
// application.  Assuming that the request passes all of the sanity checks,
// attempts to create a channel and bind it to this owner using the supplied
// dispatching behavior, then send the other end of the channel back to the
// application.
zx_status_t HandleDeviceIoctl(uint32_t op,
                              void* out_buf,
                              size_t out_len,
                              size_t* out_actual,
                              const fbl::RefPtr<dispatcher::ExecutionDomain>& domain,
                              dispatcher::Channel::ProcessHandler phandler,
                              dispatcher::Channel::ChannelClosedHandler chandler);


// Attempts to create and activate a channel using the supplied dispatcher
// bindings and binding it to this ExeuctionDomain in the process.  Callers must
// take ownership of the remote channel endpoint, but may choose to ignore the
// local channel endpoint by passing nullptr for local_endpoint_out.  Upon
// success, a reference to the created dispatcher::Channel will be held by the
// channel's ExeuctionDomain (as a result of the activation operation)
zx_status_t CreateAndActivateChannel(const fbl::RefPtr<dispatcher::ExecutionDomain>& domain,
                                     dispatcher::Channel::ProcessHandler phandler,
                                     dispatcher::Channel::ChannelClosedHandler chandler,
                                     fbl::RefPtr<dispatcher::Channel>* local_endpoint_out,
                                     zx::channel* remote_endpoint_out);

}  // namespace intel_hda
}  // namespace audio
