1// Copyright 2017 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 <ddktl/device-internal.h>
8#include <ddktl/device.h>
9#include <fbl/mutex.h>
10#include <fbl/vector.h>
11
12#include "a113-ddr.h"
13#include "a113-pdm.h"
14#include "audio-proto/audio-proto.h"
15#include "dispatcher-pool/dispatcher-channel.h"
16#include "dispatcher-pool/dispatcher-execution-domain.h"
17
18#include "a113-ddr.h"
19#include "a113-pdm.h"
20#include "vmo_helper.h"
21
22namespace audio {
23namespace gauss {
24
25struct PdmInputStreamProtocol : public ddk::internal::base_protocol {
26    explicit PdmInputStreamProtocol() {
27        ddk_proto_id_ = ZX_PROTOCOL_AUDIO_INPUT;
28    }
29};
30
31class GaussPdmInputStream;
32using GaussPdmInputStreamBase =
33    ddk::Device<GaussPdmInputStream, ddk::Ioctlable, ddk::Unbindable>;
34
35class GaussPdmInputStream : public GaussPdmInputStreamBase,
36                            public PdmInputStreamProtocol,
37                            public fbl::RefCounted<GaussPdmInputStream> {
38public:
39    static zx_status_t Create(zx_device_t* parent);
40
41    // DDK device implementation
42    void DdkUnbind();
43    void DdkRelease();
44    zx_status_t DdkIoctl(uint32_t op, const void* in_buf, size_t in_len,
45                         void* out_buf, size_t out_len, size_t* out_actual);
46
47private:
48    friend class fbl::RefPtr<GaussPdmInputStream>;
49
50    GaussPdmInputStream(
51        zx_device_t* parent,
52        fbl::RefPtr<dispatcher::ExecutionDomain>&& default_domain)
53        : GaussPdmInputStreamBase(parent),
54          default_domain_(fbl::move(default_domain)) {}
55
56    virtual ~GaussPdmInputStream();
57
58    int IrqThread();
59
60    zx_status_t Bind(const char* devname, zx_device_t* parent);
61
62    // Thunks for dispatching stream channel events.
63    zx_status_t ProcessStreamChannel(dispatcher::Channel* channel,
64                                     bool privileged);
65
66    void DeactivateStreamChannel(const dispatcher::Channel* channel);
67
68    zx_status_t OnGetStreamFormats(dispatcher::Channel* channel,
69                                   const audio_proto::StreamGetFmtsReq& req);
70
71    zx_status_t OnSetStreamFormat(dispatcher::Channel* channel,
72                                  const audio_proto::StreamSetFmtReq& req,
73                                  bool privileged);
74
75    zx_status_t OnGetGain(dispatcher::Channel* channel,
76                          const audio_proto::GetGainReq& req);
77
78    zx_status_t OnSetGain(dispatcher::Channel* channel,
79                          const audio_proto::SetGainReq& req);
80
81    zx_status_t OnPlugDetect(dispatcher::Channel* channel,
82                             const audio_proto::PlugDetectReq& req);
83
84    zx_status_t OnGetUniqueId(dispatcher::Channel* channel, const audio_proto::GetUniqueIdReq& req);
85    zx_status_t OnGetString(dispatcher::Channel* channel, const audio_proto::GetStringReq& req);
86
87    // Thunks for dispatching ring buffer channel events.
88    zx_status_t ProcessRingBufferChannel(dispatcher::Channel* channel);
89
90    void DeactivateRingBufferChannel(const dispatcher::Channel* channel);
91
92    // Stream command handlers
93    // Ring buffer command handlers
94    zx_status_t OnGetFifoDepth(dispatcher::Channel* channel,
95                               const audio_proto::RingBufGetFifoDepthReq& req)
96        __TA_REQUIRES(lock_);
97
98    zx_status_t OnGetBuffer(dispatcher::Channel* channel,
99                            const audio_proto::RingBufGetBufferReq& req)
100        __TA_REQUIRES(lock_);
101
102    zx_status_t OnStart(dispatcher::Channel* channel,
103                        const audio_proto::RingBufStartReq& req)
104        __TA_REQUIRES(lock_);
105
106    zx_status_t OnStop(dispatcher::Channel* channel,
107                       const audio_proto::RingBufStopReq& req)
108        __TA_REQUIRES(lock_);
109
110    fbl::Mutex lock_;
111
112    // Dispatcher framework state
113    fbl::RefPtr<dispatcher::Channel> stream_channel_;
114    fbl::RefPtr<dispatcher::Channel> rb_channel_ __TA_GUARDED(lock_);
115    fbl::RefPtr<dispatcher::ExecutionDomain> default_domain_;
116
117    fbl::Vector<audio_stream_format_range_t> supported_formats_;
118
119    uint32_t frame_size_;
120
121    VmoHelper<false> vmo_helper_;
122
123    // TODO(almasrymina): hardcoded.
124    uint32_t frame_rate_ = 48000;
125
126    a113_audio_device_t audio_device_;
127    thrd_t irqthrd_;
128
129    uint32_t fifo_depth_ = 0x200;
130
131    fbl::atomic<size_t> ring_buffer_size_;
132    fbl::atomic<uint32_t> notifications_per_ring_;
133};
134
135} // namespace gauss
136} // namespace audio
137