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 <fbl/ref_ptr.h> 8#include <lib/simple-audio-stream/simple-audio-stream.h> 9#include <zircon/device/audio.h> 10 11#include "vim-audio-utils.h" 12 13// Fwd Decls 14extern "C" { 15 struct vim2_display; 16} 17 18namespace audio { 19namespace vim2 { 20 21class Vim2SpdifAudioStream : public SimpleAudioStream { 22 public: 23 DISALLOW_COPY_ASSIGN_AND_MOVE(Vim2SpdifAudioStream); 24 static void Disable(const Registers& regs); 25 26 uint64_t display_id() const { return display_id_; } 27 28 protected: 29 friend class fbl::RefPtr<Vim2SpdifAudioStream>; 30 friend class SimpleAudioStream; 31 32 Vim2SpdifAudioStream(const vim2_display* display, 33 fbl::RefPtr<Registers> regs, 34 fbl::RefPtr<RefCountedVmo> ring_buffer_vmo, 35 fzl::PinnedVmo pinned_ring_buffer, 36 uint64_t display_id); 37 38 ~Vim2SpdifAudioStream() override { 39 Shutdown(); 40 } 41 42 zx_status_t Init() __TA_REQUIRES(domain_->token()) override; 43 void ShutdownHook() __TA_REQUIRES(domain_->token()) override; 44 void RingBufferShutdown() __TA_REQUIRES(domain_->token()) override; 45 46 zx_status_t ChangeFormat(const audio_proto::StreamSetFmtReq& req) 47 __TA_REQUIRES(domain_->token()) override; 48 zx_status_t SetGain(const audio_proto::SetGainReq& req) 49 __TA_REQUIRES(domain_->token()) override; 50 51 zx_status_t GetBuffer(const audio_proto::RingBufGetBufferReq& req, 52 uint32_t* out_num_rb_frames, 53 zx::vmo* out_buffer) __TA_REQUIRES(domain_->token()) override; 54 zx_status_t Start(uint64_t* out_start_time) __TA_REQUIRES(domain_->token()) override; 55 zx_status_t Stop() __TA_REQUIRES(domain_->token()) override; 56 57 private: 58 zx_status_t CreateFormatList() __TA_REQUIRES(domain_->token()); 59 60 void Enable(); 61 void SetupBuffer(); 62 void SetMode(uint32_t frame_rate, audio_sample_format_t fmt); 63 void Mute(bool muted); 64 65 // TODO(johngro) : it is unfortunate that we need to maintain an unmanaged 66 // pointer back to our display in order to configure it properly when 67 // setting audio modes. In a perfect world, however, we would really not 68 // know much of anything about us. Instead, we would be able to properly 69 // represent composite device drivers, and this audio code would be running 70 // on its own in a separate devhost and acting as a DAI driver for various 71 // codec drivers. In this world, HDMI driver would serve as a codec driver, 72 // and it would get first crack at the call to "set format", which would 73 // allow it configure the audio clock recover and audio info-frame as part 74 // of the process of requesting the proper DAI stream to feed the HDMI 75 // transmitter unit in the chip. 76 // 77 // Until that day comes, however, we need a small callback hook into the 78 // display driver to set this up when the high level code asks us to do so. 79 // In order to do that, we need to hold the context pointer to the display 80 // driver instance, which will be passed to us at construction time. Since 81 // we have no managed pointers, it is the HDMI driver's responsibility to 82 // make certain that its scope outlives our. 83 // 84 const struct vim2_display* const display_; 85 const uint64_t display_id_; 86 87 fbl::RefPtr<Registers> regs_; 88 fbl::RefPtr<RefCountedVmo> ring_buffer_vmo_; 89 fzl::PinnedVmo pinned_ring_buffer_; 90 uint32_t usable_buffer_size_ = 0; 91}; 92 93} // namespace vim2 94} // namespace audio 95