1// Copyright 2018 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#pragma once
6
7#include <ddk/device.h>
8#include <ddk/protocol/intel-hda-codec.h>
9#include <ddk/protocol/intel-hda-dsp.h>
10#include <fbl/mutex.h>
11#include <fbl/ref_counted.h>
12#include <fbl/ref_ptr.h>
13#include <zircon/thread_annotations.h>
14#include <stdint.h>
15#include <string.h>
16
17#include <dispatcher-pool/dispatcher-channel.h>
18#include <dispatcher-pool/dispatcher-execution-domain.h>
19#include <intel-hda/utils/intel-hda-proto.h>
20#include <intel-hda/utils/intel-hda-registers.h>
21#include <intel-hda/utils/utils.h>
22
23#include "debug-logging.h"
24#include "intel-hda-stream.h"
25
26namespace audio {
27namespace intel_hda {
28
29class IntelHDAController;
30
31class IntelHDADSP : public fbl::RefCounted<IntelHDADSP> {
32public:
33    static fbl::RefPtr<IntelHDADSP> Create(IntelHDAController& controller,
34                                           hda_pp_registers_t* pp_regs,
35                                           const fbl::RefPtr<RefCountedBti>& pci_bti);
36
37    const char* log_prefix() const { return log_prefix_; }
38
39    void ProcessIRQ();
40
41private:
42    friend class fbl::RefPtr<IntelHDADSP>;
43
44    static zx_protocol_device_t DSP_DEVICE_THUNKS;
45    static ihda_codec_protocol_ops_t CODEC_PROTO_THUNKS;
46    static ihda_dsp_protocol_ops_t DSP_PROTO_THUNKS;
47
48    IntelHDADSP(IntelHDAController& controller,
49                hda_pp_registers_t* pp_regs,
50                const fbl::RefPtr<RefCountedBti>& pci_bti);
51    ~IntelHDADSP() { };
52
53    hda_pp_registers_t* pp_regs() const {
54        return pp_regs_;
55    }
56
57    zx_status_t PublishDevice();
58
59    // Device interface
60    zx_status_t DeviceGetProtocol(uint32_t proto_id, void* protocol);
61    zx_status_t DeviceIoctl(uint32_t op, void* out_buf, size_t out_len, size_t* out_actual);
62    void DeviceUnbind();
63
64    // ZX_PROTOCOL_IHDA_DSP interface
65    void GetDevInfo(zx_pcie_device_info_t* out_info);
66    zx_status_t GetMmio(zx_handle_t* out_vmo, size_t* out_size);
67    zx_status_t GetBti(zx_handle_t* out_handle);
68    void Enable();
69    void Disable();
70    zx_status_t IrqEnable(ihda_dsp_irq_callback_t* callback, void* cookie);
71    void IrqDisable();
72
73    // ZX_PROTOCOL_IHDA_CODEC Interface
74    zx_status_t CodecGetDispatcherChannel(zx_handle_t* channel_out);
75
76    // Thunks for interacting with clients and codec drivers.
77    zx_status_t ProcessClientRequest(dispatcher::Channel* channel, bool is_driver_channel);
78    void ProcessClientDeactivate(const dispatcher::Channel* channel);
79    zx_status_t ProcessRequestStream(dispatcher::Channel* channel,
80                                     const ihda_proto::RequestStreamReq& req);
81    zx_status_t ProcessReleaseStream(dispatcher::Channel* channel,
82                                     const ihda_proto::ReleaseStreamReq& req);
83    zx_status_t ProcessSetStreamFmt(dispatcher::Channel* channel,
84                                    const ihda_proto::SetStreamFmtReq& req);
85
86    // Reference to our owner.
87    IntelHDAController& controller_;
88
89    fbl::Mutex dsp_lock_;
90    ihda_dsp_irq_callback_t* irq_callback_ TA_GUARDED(dsp_lock_) = nullptr;
91    void* irq_cookie_ TA_GUARDED(dsp_lock_) = nullptr;
92
93    // Driver connection state
94    fbl::Mutex codec_driver_channel_lock_;
95    fbl::RefPtr<dispatcher::Channel> codec_driver_channel_ TA_GUARDED(codec_driver_channel_lock_);
96
97    // Log prefix storage
98    char log_prefix_[LOG_PREFIX_STORAGE] = { 0 };
99
100    // Published device node.
101    zx_device_t* dev_node_ = nullptr;
102
103    // Pipe processintg registers
104    hda_pp_registers_t* pp_regs_ = nullptr;
105
106    // A handle to the Bus Transaction Initiator for the controller.
107    fbl::RefPtr<RefCountedBti> pci_bti_;
108
109    // Dispatcher framework state.
110    fbl::RefPtr<dispatcher::ExecutionDomain> default_domain_;
111
112    // Active DMA streams
113    fbl::Mutex          active_streams_lock_;
114    IntelHDAStream::Tree active_streams_ TA_GUARDED(active_streams_lock_);
115};
116
117}  // namespace intel_hda
118}  // namespace audio
119