blob: da18b2bf0f4a72ba8cb6c560d21cfa33e7751aca [file] [log] [blame]
// Copyright 2018 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 <ddk/protocol/intel-hda-codec.h>
#include <ddk/protocol/intel-hda-dsp.h>
#include <fbl/mutex.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
#include <zircon/thread_annotations.h>
#include <stdint.h>
#include <string.h>
#include <dispatcher-pool/dispatcher-channel.h>
#include <dispatcher-pool/dispatcher-execution-domain.h>
#include <intel-hda/utils/intel-hda-proto.h>
#include <intel-hda/utils/intel-hda-registers.h>
#include <intel-hda/utils/utils.h>
#include "debug-logging.h"
#include "intel-hda-stream.h"
namespace audio {
namespace intel_hda {
class IntelHDAController;
class IntelHDADSP : public fbl::RefCounted<IntelHDADSP> {
public:
static fbl::RefPtr<IntelHDADSP> Create(IntelHDAController& controller,
hda_pp_registers_t* pp_regs,
const fbl::RefPtr<RefCountedBti>& pci_bti);
const char* log_prefix() const { return log_prefix_; }
void ProcessIRQ();
private:
friend class fbl::RefPtr<IntelHDADSP>;
static zx_protocol_device_t DSP_DEVICE_THUNKS;
static ihda_codec_protocol_ops_t CODEC_PROTO_THUNKS;
static ihda_dsp_protocol_ops_t DSP_PROTO_THUNKS;
IntelHDADSP(IntelHDAController& controller,
hda_pp_registers_t* pp_regs,
const fbl::RefPtr<RefCountedBti>& pci_bti);
~IntelHDADSP() { };
hda_pp_registers_t* pp_regs() const {
return pp_regs_;
}
zx_status_t PublishDevice();
// Device interface
zx_status_t DeviceGetProtocol(uint32_t proto_id, void* protocol);
zx_status_t DeviceIoctl(uint32_t op, void* out_buf, size_t out_len, size_t* out_actual);
void DeviceUnbind();
// ZX_PROTOCOL_IHDA_DSP interface
void GetDevInfo(zx_pcie_device_info_t* out_info);
zx_status_t GetMmio(zx_handle_t* out_vmo, size_t* out_size);
zx_status_t GetBti(zx_handle_t* out_handle);
void Enable();
void Disable();
zx_status_t IrqEnable(const ihda_dsp_irq_t* callback);
void IrqDisable();
// ZX_PROTOCOL_IHDA_CODEC Interface
zx_status_t CodecGetDispatcherChannel(zx_handle_t* channel_out);
// Thunks for interacting with clients and codec drivers.
zx_status_t ProcessClientRequest(dispatcher::Channel* channel, bool is_driver_channel);
void ProcessClientDeactivate(const dispatcher::Channel* channel);
zx_status_t ProcessRequestStream(dispatcher::Channel* channel,
const ihda_proto::RequestStreamReq& req);
zx_status_t ProcessReleaseStream(dispatcher::Channel* channel,
const ihda_proto::ReleaseStreamReq& req);
zx_status_t ProcessSetStreamFmt(dispatcher::Channel* channel,
const ihda_proto::SetStreamFmtReq& req);
// Reference to our owner.
IntelHDAController& controller_;
fbl::Mutex dsp_lock_;
ihda_dsp_irq_t irq_callback_ TA_GUARDED(dsp_lock_) = {nullptr, nullptr};
// Driver connection state
fbl::Mutex codec_driver_channel_lock_;
fbl::RefPtr<dispatcher::Channel> codec_driver_channel_ TA_GUARDED(codec_driver_channel_lock_);
// Log prefix storage
char log_prefix_[LOG_PREFIX_STORAGE] = { 0 };
// Published device node.
zx_device_t* dev_node_ = nullptr;
// Pipe processintg registers
hda_pp_registers_t* pp_regs_ = nullptr;
// A handle to the Bus Transaction Initiator for the controller.
fbl::RefPtr<RefCountedBti> pci_bti_;
// Dispatcher framework state.
fbl::RefPtr<dispatcher::ExecutionDomain> default_domain_;
// Active DMA streams
fbl::Mutex active_streams_lock_;
IntelHDAStream::Tree active_streams_ TA_GUARDED(active_streams_lock_);
};
} // namespace intel_hda
} // namespace audio