blob: 356bd6fe8e5de0e90b0149bbda4bc1d50c7ef091 [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 <fbl/ref_ptr.h>
#include <lib/simple-audio-stream/simple-audio-stream.h>
#include <zircon/device/audio.h>
#include "vim-audio-utils.h"
// Fwd Decls
extern "C" {
struct vim2_display;
}
namespace audio {
namespace vim2 {
class Vim2SpdifAudioStream : public SimpleAudioStream {
public:
DISALLOW_COPY_ASSIGN_AND_MOVE(Vim2SpdifAudioStream);
static void Disable(const Registers& regs);
uint64_t display_id() const { return display_id_; }
protected:
friend class fbl::RefPtr<Vim2SpdifAudioStream>;
friend class SimpleAudioStream;
Vim2SpdifAudioStream(const vim2_display* display,
fbl::RefPtr<Registers> regs,
fbl::RefPtr<RefCountedVmo> ring_buffer_vmo,
fzl::PinnedVmo pinned_ring_buffer,
uint64_t display_id);
~Vim2SpdifAudioStream() override {
Shutdown();
}
zx_status_t Init() __TA_REQUIRES(domain_->token()) override;
void ShutdownHook() __TA_REQUIRES(domain_->token()) override;
void RingBufferShutdown() __TA_REQUIRES(domain_->token()) override;
zx_status_t ChangeFormat(const audio_proto::StreamSetFmtReq& req)
__TA_REQUIRES(domain_->token()) override;
zx_status_t SetGain(const audio_proto::SetGainReq& req)
__TA_REQUIRES(domain_->token()) override;
zx_status_t GetBuffer(const audio_proto::RingBufGetBufferReq& req,
uint32_t* out_num_rb_frames,
zx::vmo* out_buffer) __TA_REQUIRES(domain_->token()) override;
zx_status_t Start(uint64_t* out_start_time) __TA_REQUIRES(domain_->token()) override;
zx_status_t Stop() __TA_REQUIRES(domain_->token()) override;
private:
zx_status_t CreateFormatList() __TA_REQUIRES(domain_->token());
void Enable();
void SetupBuffer();
void SetMode(uint32_t frame_rate, audio_sample_format_t fmt);
void Mute(bool muted);
// TODO(johngro) : it is unfortunate that we need to maintain an unmanaged
// pointer back to our display in order to configure it properly when
// setting audio modes. In a perfect world, however, we would really not
// know much of anything about us. Instead, we would be able to properly
// represent composite device drivers, and this audio code would be running
// on its own in a separate devhost and acting as a DAI driver for various
// codec drivers. In this world, HDMI driver would serve as a codec driver,
// and it would get first crack at the call to "set format", which would
// allow it configure the audio clock recover and audio info-frame as part
// of the process of requesting the proper DAI stream to feed the HDMI
// transmitter unit in the chip.
//
// Until that day comes, however, we need a small callback hook into the
// display driver to set this up when the high level code asks us to do so.
// In order to do that, we need to hold the context pointer to the display
// driver instance, which will be passed to us at construction time. Since
// we have no managed pointers, it is the HDMI driver's responsibility to
// make certain that its scope outlives our.
//
const struct vim2_display* const display_;
const uint64_t display_id_;
fbl::RefPtr<Registers> regs_;
fbl::RefPtr<RefCountedVmo> ring_buffer_vmo_;
fzl::PinnedVmo pinned_ring_buffer_;
uint32_t usable_buffer_size_ = 0;
};
} // namespace vim2
} // namespace audio