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 #include "qemu-stream.h"
6
7 #include <fbl/vector.h>
8
9 #include <utility>
10
11 namespace audio {
12 namespace intel_hda {
13 namespace codecs {
14
15 static constexpr uint8_t UNITY_GAIN = 74;
16 static const audio_stream_unique_id_t microphone_id = AUDIO_STREAM_UNIQUE_ID_BUILTIN_MICROPHONE;
17 static const audio_stream_unique_id_t speaker_id = AUDIO_STREAM_UNIQUE_ID_BUILTIN_SPEAKERS;
18
QemuStream(uint32_t stream_id,bool is_input,uint16_t converter_nid)19 QemuStream::QemuStream(uint32_t stream_id, bool is_input, uint16_t converter_nid)
20 : IntelHDAStreamBase(stream_id, is_input),
21 converter_nid_(converter_nid) {
22 SetPersistentUniqueId(is_input ? microphone_id : speaker_id);
23 }
24
DisableConverterLocked(bool force_all)25 zx_status_t QemuStream::DisableConverterLocked(bool force_all) {
26 const CodecVerb DISABLE_CONVERTER_VERBS[] = {
27 SET_AMPLIFIER_GAIN_MUTE(true, 0, is_input(), !is_input()),
28 SET_CONVERTER_STREAM_CHAN(IHDA_INVALID_STREAM_TAG, 0),
29 };
30
31 return RunCmdListLocked(DISABLE_CONVERTER_VERBS, countof(DISABLE_CONVERTER_VERBS), force_all);
32 }
33
RunCmdListLocked(const CodecVerb * list,size_t count,bool force_all)34 zx_status_t QemuStream::RunCmdListLocked(const CodecVerb* list, size_t count, bool force_all) {
35 ZX_DEBUG_ASSERT(list);
36
37 zx_status_t total_res = ZX_OK;
38 for (size_t i = 0; i < count; ++i) {
39 const auto& verb = list[i];
40
41 zx_status_t res = SendCodecCommandLocked(converter_nid_, verb, Ack::NO);
42 if ((res != ZX_OK) && !force_all)
43 return res;
44
45 if (total_res == ZX_OK)
46 total_res = res;
47 }
48
49 return total_res;
50 }
51
OnActivateLocked()52 zx_status_t QemuStream::OnActivateLocked() {
53 fbl::Vector<audio_proto::FormatRange> supported_formats;
54
55 audio_proto::FormatRange range;
56 range.sample_formats = AUDIO_SAMPLE_FORMAT_16BIT;
57 range.min_channels = 1;
58 range.max_channels = 2;
59 range.min_frames_per_second = 16000;
60 range.max_frames_per_second = 96000;
61 range.flags = ASF_RANGE_FLAG_FPS_48000_FAMILY | ASF_RANGE_FLAG_FPS_44100_FAMILY;
62
63 fbl::AllocChecker ac;
64 supported_formats.push_back(range, &ac);
65 if (!ac.check())
66 return ZX_ERR_NO_MEMORY;
67
68 SetSupportedFormatsLocked(std::move(supported_formats));
69
70 return DisableConverterLocked();
71 }
72
OnDeactivateLocked()73 void QemuStream::OnDeactivateLocked() {
74 DisableConverterLocked(true);
75 }
76
BeginChangeStreamFormatLocked(const audio_proto::StreamSetFmtReq & fmt)77 zx_status_t QemuStream::BeginChangeStreamFormatLocked(const audio_proto::StreamSetFmtReq& fmt) {
78 return DisableConverterLocked();
79 }
80
FinishChangeStreamFormatLocked(uint16_t encoded_fmt)81 zx_status_t QemuStream::FinishChangeStreamFormatLocked(uint16_t encoded_fmt) {
82 const CodecVerb ENABLE_CONVERTER_VERBS[] = {
83 SET_CONVERTER_FORMAT(encoded_fmt),
84 SET_CONVERTER_STREAM_CHAN(dma_stream_tag(), 0),
85 SET_AMPLIFIER_GAIN_MUTE(false, UNITY_GAIN, is_input(), !is_input()),
86 };
87
88 return RunCmdListLocked(ENABLE_CONVERTER_VERBS, countof(ENABLE_CONVERTER_VERBS));
89 }
90
OnGetStringLocked(const audio_proto::GetStringReq & req,audio_proto::GetStringResp * out_resp)91 void QemuStream::OnGetStringLocked(const audio_proto::GetStringReq& req,
92 audio_proto::GetStringResp* out_resp) {
93 ZX_DEBUG_ASSERT(out_resp);
94 const char* str = nullptr;
95
96 switch (req.id) {
97 case AUDIO_STREAM_STR_ID_MANUFACTURER:
98 str = "QEMU";
99 break;
100
101 case AUDIO_STREAM_STR_ID_PRODUCT:
102 str = is_input() ? "Builtin Microphone" : "Builtin Speakers";
103 break;
104
105 default:
106 IntelHDAStreamBase::OnGetStringLocked(req, out_resp);
107 return;
108 }
109
110 int res = snprintf(reinterpret_cast<char*>(out_resp->str), sizeof(out_resp->str), "%s",
111 str ? str : "<unassigned>");
112 ZX_DEBUG_ASSERT(res >= 0);
113 out_resp->result = ZX_OK;
114 out_resp->strlen = fbl::min<uint32_t>(res, sizeof(out_resp->str) - 1);
115 out_resp->id = req.id;
116 }
117
118
119 } // namespace codecs
120 } // namespace intel_hda
121 } // namespace audio
122