| // 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 <ddktl/device-internal.h> |
| #include <ddktl/device.h> |
| #include <ddktl/protocol/empty-protocol.h> |
| #include <fbl/mutex.h> |
| #include <fbl/vector.h> |
| #include <fuchsia/hardware/audio/c/fidl.h> |
| |
| #include <atomic> |
| #include <utility> |
| |
| #include "a113-ddr.h" |
| #include "a113-pdm.h" |
| #include "audio-proto/audio-proto.h" |
| #include "dispatcher-pool/dispatcher-channel.h" |
| #include "dispatcher-pool/dispatcher-execution-domain.h" |
| |
| #include "a113-ddr.h" |
| #include "a113-pdm.h" |
| #include "vmo_helper.h" |
| |
| namespace audio { |
| namespace gauss { |
| |
| class GaussPdmInputStream; |
| using GaussPdmInputStreamBase = |
| ddk::Device<GaussPdmInputStream, ddk::Messageable, ddk::Unbindable>; |
| |
| class GaussPdmInputStream : public GaussPdmInputStreamBase, |
| public ddk::EmptyProtocol<ZX_PROTOCOL_AUDIO_INPUT>, |
| public fbl::RefCounted<GaussPdmInputStream> { |
| public: |
| static zx_status_t Create(zx_device_t* parent); |
| |
| // DDK device implementation |
| void DdkUnbind(); |
| void DdkRelease(); |
| zx_status_t DdkMessage(fidl_msg_t* msg, fidl_txn_t* txn) { |
| return fuchsia_hardware_audio_Device_dispatch(this, txn, msg, &AUDIO_FIDL_THUNKS); |
| } |
| |
| private: |
| friend class fbl::RefPtr<GaussPdmInputStream>; |
| |
| GaussPdmInputStream( |
| zx_device_t* parent, |
| fbl::RefPtr<dispatcher::ExecutionDomain>&& default_domain) |
| : GaussPdmInputStreamBase(parent), |
| default_domain_(std::move(default_domain)) {} |
| |
| virtual ~GaussPdmInputStream(); |
| |
| // Device FIDL implementation |
| zx_status_t GetChannel(fidl_txn_t* txn); |
| |
| int IrqThread(); |
| |
| zx_status_t Bind(const char* devname, zx_device_t* parent); |
| |
| // Thunks for dispatching stream channel events. |
| zx_status_t ProcessStreamChannel(dispatcher::Channel* channel, |
| bool privileged); |
| |
| void DeactivateStreamChannel(const dispatcher::Channel* channel); |
| |
| zx_status_t OnGetStreamFormats(dispatcher::Channel* channel, |
| const audio_proto::StreamGetFmtsReq& req); |
| |
| zx_status_t OnSetStreamFormat(dispatcher::Channel* channel, |
| const audio_proto::StreamSetFmtReq& req, |
| bool privileged); |
| |
| zx_status_t OnGetGain(dispatcher::Channel* channel, |
| const audio_proto::GetGainReq& req); |
| |
| zx_status_t OnSetGain(dispatcher::Channel* channel, |
| const audio_proto::SetGainReq& req); |
| |
| zx_status_t OnPlugDetect(dispatcher::Channel* channel, |
| const audio_proto::PlugDetectReq& req); |
| |
| zx_status_t OnGetUniqueId(dispatcher::Channel* channel, const audio_proto::GetUniqueIdReq& req); |
| zx_status_t OnGetString(dispatcher::Channel* channel, const audio_proto::GetStringReq& req); |
| |
| // Thunks for dispatching ring buffer channel events. |
| zx_status_t ProcessRingBufferChannel(dispatcher::Channel* channel); |
| |
| void DeactivateRingBufferChannel(const dispatcher::Channel* channel); |
| |
| // Stream command handlers |
| // Ring buffer command handlers |
| zx_status_t OnGetFifoDepth(dispatcher::Channel* channel, |
| const audio_proto::RingBufGetFifoDepthReq& req) |
| __TA_REQUIRES(lock_); |
| |
| zx_status_t OnGetBuffer(dispatcher::Channel* channel, |
| const audio_proto::RingBufGetBufferReq& req) |
| __TA_REQUIRES(lock_); |
| |
| zx_status_t OnStart(dispatcher::Channel* channel, |
| const audio_proto::RingBufStartReq& req) |
| __TA_REQUIRES(lock_); |
| |
| zx_status_t OnStop(dispatcher::Channel* channel, |
| const audio_proto::RingBufStopReq& req) |
| __TA_REQUIRES(lock_); |
| |
| static fuchsia_hardware_audio_Device_ops_t AUDIO_FIDL_THUNKS; |
| |
| fbl::Mutex lock_; |
| |
| // Dispatcher framework state |
| fbl::RefPtr<dispatcher::Channel> stream_channel_; |
| fbl::RefPtr<dispatcher::Channel> rb_channel_ __TA_GUARDED(lock_); |
| fbl::RefPtr<dispatcher::ExecutionDomain> default_domain_; |
| |
| fbl::Vector<audio_stream_format_range_t> supported_formats_; |
| |
| uint32_t frame_size_; |
| |
| VmoHelper<false> vmo_helper_; |
| |
| // TODO(almasrymina): hardcoded. |
| uint32_t frame_rate_ = 48000; |
| |
| a113_audio_device_t audio_device_; |
| thrd_t irqthrd_; |
| |
| uint32_t fifo_depth_ = 0x200; |
| |
| std::atomic<size_t> ring_buffer_size_; |
| std::atomic<uint32_t> notifications_per_ring_; |
| }; |
| |
| } // namespace gauss |
| } // namespace audio |