Codec.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  1. /*
  2. * Copyright (c) 2023, Jelle Raaijmakers <jelle@gmta.nl>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "Codec.h"
  7. #include <AK/Array.h>
  8. #include <Kernel/Devices/Audio/IntelHDA/Controller.h>
  9. namespace Kernel::Audio::IntelHDA {
  10. // 7.3.4.7: Supported PCM Size, Rates
  11. struct BitRateEncoding {
  12. u8 flag;
  13. u8 bit_rate;
  14. };
  15. static constexpr Array<BitRateEncoding, 5> bit_rate_encodings { {
  16. // clang-format off
  17. { 0x1, 8 },
  18. { 0x2, 16 },
  19. { 0x4, 20 },
  20. { 0x8, 24 },
  21. { 0x10, 32 },
  22. // clang-format on
  23. } };
  24. struct SampleRateEncoding {
  25. u16 flag;
  26. u32 sample_rate;
  27. };
  28. static constexpr Array<SampleRateEncoding, 12> sample_rate_encodings { {
  29. // clang-format off
  30. { 0x1, 8'000 },
  31. { 0x2, 11'025 },
  32. { 0x4, 16'000 },
  33. { 0x8, 22'050 },
  34. { 0x10, 32'000 },
  35. { 0x20, 44'100 },
  36. { 0x40, 48'000 },
  37. { 0x80, 88'200 },
  38. { 0x100, 96'000 },
  39. { 0x200, 176'400 },
  40. { 0x400, 192'000 },
  41. { 0x800, 384'000 },
  42. // clang-format on
  43. } };
  44. ErrorOr<void> Codec::register_node(NonnullRefPtr<Node> node)
  45. {
  46. auto set_result = TRY(m_nodes_by_node_id.try_set(node->node_id(), node));
  47. VERIFY(set_result == HashSetResult::InsertedNewEntry);
  48. return {};
  49. }
  50. ErrorOr<void> Node::initialize()
  51. {
  52. return codec().register_node(*this);
  53. }
  54. ErrorOr<u32> Node::command(CodecControlVerb verb, u16 payload)
  55. {
  56. auto& node_codec = codec();
  57. return node_codec.controller().send_command(node_codec.codec_address(), m_node_id, verb, payload);
  58. }
  59. ErrorOr<u32> Node::parameter(GetParameterId get_parameter_id)
  60. {
  61. return command(CodecControlVerb::GetParameter, to_underlying(get_parameter_id));
  62. }
  63. ErrorOr<void> Node::set_power_state(PowerState power_state)
  64. {
  65. // 7.3.3.10: Power State
  66. TRY(command(CodecControlVerb::SetPowerState, to_underlying(power_state)));
  67. return {};
  68. }
  69. template<typename T>
  70. void NodeWithChildren<T>::for_each_child_node(Function<void(T const&, bool)> callback) const
  71. {
  72. auto number_of_child_nodes = m_child_nodes.size();
  73. for (size_t child_index = 0; child_index < number_of_child_nodes; ++child_index)
  74. callback(m_child_nodes[child_index], child_index == number_of_child_nodes - 1);
  75. }
  76. template<typename T>
  77. ErrorOr<void> NodeWithChildren<T>::initialize()
  78. {
  79. TRY(Node::initialize());
  80. return populate_child_nodes();
  81. }
  82. template<typename T>
  83. ErrorOr<void> NodeWithChildren<T>::populate_child_nodes()
  84. {
  85. VERIFY(m_child_nodes.is_empty());
  86. // 7.3.4.3: Subordinate Node Count
  87. auto subordinate_node_count = TRY(parameter(GetParameterId::SubordinateNodeCount));
  88. u8 starting_node_number = (subordinate_node_count >> 16) & 0xff;
  89. u8 total_number_of_nodes = subordinate_node_count & 0xff;
  90. TRY(m_child_nodes.try_ensure_capacity(total_number_of_nodes));
  91. for (int subnode_index = 0; subnode_index < total_number_of_nodes; ++subnode_index)
  92. m_child_nodes.unchecked_append(TRY(Node::create<T>(*this, starting_node_number + subnode_index)));
  93. return {};
  94. }
  95. StringView WidgetNode::widget_type_name() const
  96. {
  97. switch (m_widget_type) {
  98. case WidgetType::AudioInput:
  99. return "Audio Input"sv;
  100. case WidgetType::AudioMixer:
  101. return "Audio Mixer"sv;
  102. case WidgetType::AudioOutput:
  103. return "Audio Output"sv;
  104. case WidgetType::AudioSelector:
  105. return "Audio Selector"sv;
  106. case WidgetType::BeepGenerator:
  107. return "Beep Generator"sv;
  108. case WidgetType::PinComplex:
  109. return "Pin Complex"sv;
  110. case WidgetType::Power:
  111. return "Power"sv;
  112. case WidgetType::VendorDefined:
  113. return "Vendor Defined"sv;
  114. case WidgetType::VolumeKnob:
  115. return "Volume Knob"sv;
  116. }
  117. return "Reserved"sv;
  118. }
  119. ErrorOr<void> WidgetNode::initialize()
  120. {
  121. TRY(Node::initialize());
  122. // 7.3.4.6: Audio Widget Capabilities
  123. auto widget_capabilities = TRY(parameter(GetParameterId::AudioWidgetCapabilities));
  124. m_widget_type = static_cast<WidgetType>((widget_capabilities >> 20) & 0xf);
  125. m_channel_count = (((widget_capabilities >> 15) & 0xe) | (widget_capabilities & 0x1)) + 1;
  126. m_power_control_supported = (widget_capabilities & WidgetCapabilityFlag::PowerControlSupported) > 0;
  127. m_connection_list_present = (widget_capabilities & WidgetCapabilityFlag::ConnectionListPresent) > 0;
  128. m_format_override = (widget_capabilities & WidgetCapabilityFlag::FormatOverride) > 0;
  129. m_amp_param_override = (widget_capabilities & WidgetCapabilityFlag::AmpParamOverride) > 0;
  130. m_output_amp_present = (widget_capabilities & WidgetCapabilityFlag::OutputAmpPresent) > 0;
  131. m_input_amp_present = (widget_capabilities & WidgetCapabilityFlag::InputAmpPresent) > 0;
  132. if (supports_stream()) {
  133. // 7.3.3.11: Converter Stream, Channel
  134. auto stream_channel = TRY(command(CodecControlVerb::GetConverterStreamChannel, 0));
  135. m_selected_stream = (stream_channel >> 4) & 0xf;
  136. m_selected_channel = stream_channel & 0xf;
  137. TRY(populate_supported_pcm_size_rates());
  138. TRY(populate_supported_stream_formats());
  139. }
  140. // 7.3.4.10: Amplifier Capabilities
  141. auto read_amp_capabilities = [](Node& node, GetParameterId type) -> ErrorOr<AmplifierCapabilities> {
  142. auto capabilities = TRY(node.parameter(type));
  143. return AmplifierCapabilities {
  144. .muting_supported = ((capabilities >> 31) & 0x1) > 0,
  145. .step_size = static_cast<u8>((capabilities >> 16) & 0x7f),
  146. .number_of_steps = static_cast<u8>(((capabilities >> 8) & 0x7f) + 1),
  147. .offset = static_cast<u8>(capabilities & 0x7f),
  148. };
  149. };
  150. Node& amp_params_node = amp_param_override() ? *this : *parent_node();
  151. if (output_amp_present())
  152. m_output_amp_capabilities = TRY(read_amp_capabilities(amp_params_node, GetParameterId::OutputAmplifierCapabilities));
  153. if (input_amp_present())
  154. m_input_amp_capabilities = TRY(read_amp_capabilities(amp_params_node, GetParameterId::InputAmplifierCapabilities));
  155. if (widget_type() == WidgetType::PinComplex) {
  156. // 7.3.4.9: Pin Capabilities
  157. auto pin_capabilities = TRY(parameter(GetParameterId::PinCapabilities));
  158. m_pin_complex_input_supported = (pin_capabilities & PinCapabilityFlag::InputCapable) > 0;
  159. m_pin_complex_output_supported = (pin_capabilities & PinCapabilityFlag::OutputCapable) > 0;
  160. TRY(populate_pin_configuration_default());
  161. }
  162. // Connection list
  163. if (connection_list_present())
  164. TRY(populate_connection_list());
  165. return {};
  166. }
  167. ErrorOr<NonnullOwnPtr<KString>> WidgetNode::to_string()
  168. {
  169. StringBuilder builder;
  170. TRY(builder.try_appendff("WidgetNode(node_id={}, type={})", node_id(), widget_type_name()));
  171. return KString::try_create(builder.string_view());
  172. }
  173. void WidgetNode::debug_dump(StringView group_spine, bool is_last) const
  174. {
  175. dbgln("{} {} Widget (node #{}):", group_spine, is_last ? "└"sv : "├"sv, node_id());
  176. auto spine = is_last ? " "sv : "│"sv;
  177. dbgln("{} {} ├ Type: {} ({:#x})", group_spine, spine, widget_type_name(), to_underlying(widget_type()));
  178. dbgln("{} {} ├ Channel count: {}", group_spine, spine, channel_count());
  179. dbgln("{} {} ├ Power control supported: {}", group_spine, spine, m_power_control_supported ? "yes"sv : "no"sv);
  180. if (supports_stream()) {
  181. dbgln("{} {} ├ Selected stream: {}", group_spine, spine, selected_stream());
  182. if (channel_count() == 1)
  183. dbgln("{} {} ├ Selected channel: {}", group_spine, spine, selected_channel());
  184. else
  185. dbgln("{} {} ├ Selected channels: {}-{}", group_spine, spine, selected_channel(), selected_channel() + channel_count() - 1);
  186. dbgln("{} {} ├ Format override: {}", group_spine, spine, format_override() ? "yes"sv : "no"sv);
  187. dbgln("{} {} ├ Supported PCM bit sizes:", group_spine, spine);
  188. for (auto supported_size : supported_pcm_sizes())
  189. dbgln("{} {} │ • {}", group_spine, spine, supported_size);
  190. dbgln("{} {} ├ Supported PCM rates:", group_spine, spine);
  191. for (auto supported_rate : supported_pcm_rates())
  192. dbgln("{} {} │ • {}Hz", group_spine, spine, supported_rate);
  193. dbgln("{} {} ├ Supported stream formats:", group_spine, spine);
  194. if (has_flag(supported_stream_formats(), StreamFormatFlag::PCM))
  195. dbgln("{} {} │ • PCM", group_spine, spine);
  196. if (has_flag(supported_stream_formats(), StreamFormatFlag::Float32))
  197. dbgln("{} {} │ • Float32", group_spine, spine);
  198. if (has_flag(supported_stream_formats(), StreamFormatFlag::AC3))
  199. dbgln("{} {} │ • AC3", group_spine, spine);
  200. }
  201. dbgln("{} {} ├ Amplifier parameters override: {}", group_spine, spine, amp_param_override() ? "yes"sv : "no"sv);
  202. dbgln("{} {} ├ Output amplifier present: {}", group_spine, spine, output_amp_present() ? "yes"sv : "no"sv);
  203. if (output_amp_present()) {
  204. auto amp_capabilities = output_amp_capabilities();
  205. dbgln("{} {} │ ├ Muting supported: {}", group_spine, spine, amp_capabilities.muting_supported ? "yes"sv : "no"sv);
  206. dbgln("{} {} │ ├ Step size: {}", group_spine, spine, amp_capabilities.step_size);
  207. dbgln("{} {} │ ├ Number of steps: {}", group_spine, spine, amp_capabilities.number_of_steps);
  208. dbgln("{} {} │ └ Offset: {}", group_spine, spine, amp_capabilities.offset);
  209. }
  210. dbgln("{} {} ├ Input amplifier present: {}", group_spine, spine, input_amp_present() ? "yes"sv : "no"sv);
  211. if (input_amp_present()) {
  212. auto amp_capabilities = input_amp_capabilities();
  213. dbgln("{} {} │ ├ Muting supported: {}", group_spine, spine, amp_capabilities.muting_supported ? "yes"sv : "no"sv);
  214. dbgln("{} {} │ ├ Step size: {}", group_spine, spine, amp_capabilities.step_size);
  215. dbgln("{} {} │ ├ Number of steps: {}", group_spine, spine, amp_capabilities.number_of_steps);
  216. dbgln("{} {} │ └ Offset: {}", group_spine, spine, amp_capabilities.offset);
  217. }
  218. if (widget_type() == WidgetType::PinComplex) {
  219. dbgln("{} {} ├ Pin complex input supported: {}", group_spine, spine, pin_complex_input_supported());
  220. dbgln("{} {} ├ Pin complex output supported: {}", group_spine, spine, pin_complex_output_supported());
  221. dbgln("{} {} ├ Pin configuration default:", group_spine, spine);
  222. dbgln("{} {} │ ├ Sequence: {}", group_spine, spine, m_pin_configuration_default.sequence);
  223. dbgln("{} {} │ ├ Default association: {}", group_spine, spine, m_pin_configuration_default.default_association);
  224. dbgln("{} {} │ ├ Jack detect override: {}", group_spine, spine,
  225. ((static_cast<u8>(m_pin_configuration_default.misc) & to_underlying(PinMiscFlag::JackDetectOverride)) > 0) ? "yes"sv : "no"sv);
  226. dbgln("{} {} │ ├ Color: {}", group_spine, spine, pin_color_name());
  227. dbgln("{} {} │ ├ Connection type: {}", group_spine, spine, pin_connection_type_name());
  228. dbgln("{} {} │ ├ Default device: {}", group_spine, spine, pin_default_device_name());
  229. dbgln("{} {} │ ├ Location: {}, {}", group_spine, spine, pin_gross_location_name(), pin_geometric_location_name());
  230. dbgln("{} {} │ └ Port connectivity: {}", group_spine, spine, pin_port_connectivity_name());
  231. }
  232. dbgln("{} {} └ Connection list:{}", group_spine, spine, connection_list_present() ? ""sv : " absent"sv);
  233. if (connection_list_present()) {
  234. auto selected_node_id = connection_selected_node_id();
  235. auto all_active = !supports_connection_select_control();
  236. for (auto connection_entry : connection_list()) {
  237. dbgln("{} {} • Node #{}{}", group_spine, spine, connection_entry,
  238. all_active || connection_entry == selected_node_id ? " (active)"sv : ""sv);
  239. }
  240. }
  241. }
  242. ErrorOr<void> WidgetNode::set_amplifier_gain_mute(SetAmplifierGainMute settings)
  243. {
  244. // 7.3.3.7: Amplifier Gain/Mute
  245. VERIFY(input_amp_present() || output_amp_present());
  246. u16 set_amp_gain_payload = ((output_amp_present() ? 1 : 0) << 15)
  247. | ((input_amp_present() ? 1 : 0) << 15)
  248. | ((settings.set_left ? 1 : 0) << 13)
  249. | ((settings.set_right ? 1 : 0) << 12)
  250. | ((settings.connection_index & 0xf) << 8)
  251. | ((settings.mute ? 1 : 0) << 7)
  252. | (settings.gain & 0x7f);
  253. TRY(command(CodecControlVerb::SetAmplifierGainMute, set_amp_gain_payload));
  254. return {};
  255. }
  256. ErrorOr<void> WidgetNode::set_connection_select(u8 connection_index)
  257. {
  258. // 7.3.3.2: Connection Select Control
  259. VERIFY(connection_list_present());
  260. VERIFY(connection_index < connection_list().size());
  261. TRY(command(CodecControlVerb::SetConnectionSelectControl, connection_index));
  262. return {};
  263. }
  264. ErrorOr<void> WidgetNode::set_converter_stream_and_channel(u8 stream_index, u8 channel_index)
  265. {
  266. // 7.3.3.11: Converter Stream, Channel
  267. VERIFY(widget_type() == WidgetType::AudioInput || widget_type() == WidgetType::AudioOutput);
  268. u16 stream_channel_payload = ((stream_index & 0xf) << 4) | (channel_index & 0xf);
  269. TRY(command(CodecControlVerb::SetConverterStreamChannel, stream_channel_payload));
  270. return {};
  271. }
  272. ErrorOr<void> WidgetNode::set_pin_control(PinControl pin_control)
  273. {
  274. // 7.3.3.13: Pin Widget Control
  275. VERIFY(widget_type() == WidgetType::PinComplex);
  276. VERIFY(!pin_control.output_enabled || pin_complex_output_supported());
  277. VERIFY(!pin_control.input_enabled || pin_complex_input_supported());
  278. u8 payload = ((pin_control.low_impedance_amplifier_enabled ? 1 : 0) << 7)
  279. | ((pin_control.output_enabled ? 1 : 0) << 6)
  280. | ((pin_control.input_enabled ? 1 : 0) << 5)
  281. | (pin_control.voltage_reference_enable & 0x7);
  282. TRY(command(CodecControlVerb::SetPinWidgetControl, payload));
  283. return {};
  284. }
  285. bool WidgetNode::supports_stream() const
  286. {
  287. return widget_type() == WidgetType::AudioInput
  288. || widget_type() == WidgetType::AudioOutput;
  289. }
  290. bool WidgetNode::supports_connection_select_control() const
  291. {
  292. return widget_type() == WidgetType::AudioInput
  293. || widget_type() == WidgetType::AudioSelector
  294. || widget_type() == WidgetType::PinComplex;
  295. }
  296. ErrorOr<FormatParameters> WidgetNode::get_converter_format()
  297. {
  298. // 7.3.3.8: Converter Format
  299. VERIFY(widget_type() == WidgetType::AudioInput || widget_type() == WidgetType::AudioOutput);
  300. u16 format = TRY(command(CodecControlVerb::GetConverterFormat, 0)) & 0xffffu;
  301. return decode_format(format);
  302. }
  303. ErrorOr<void> WidgetNode::set_converter_format(FormatParameters format)
  304. {
  305. // 7.3.3.8: Converter Format
  306. VERIFY(widget_type() == WidgetType::AudioInput || widget_type() == WidgetType::AudioOutput);
  307. u16 format_payload = TRY(encode_format(format));
  308. TRY(command(CodecControlVerb::SetConverterFormat, format_payload));
  309. return {};
  310. }
  311. ErrorOr<void> WidgetNode::populate_supported_pcm_size_rates()
  312. {
  313. VERIFY(m_supported_pcm_sizes.is_empty() && m_supported_pcm_rates.is_empty());
  314. // 7.3.4.7: Supported PCM Size, Rates
  315. Node& stream_support_node = format_override() ? *this : *parent_node();
  316. auto supported_pcm_size_and_rates = TRY(stream_support_node.parameter(GetParameterId::SupportedPCMSizeRates));
  317. auto pcm_sizes = (supported_pcm_size_and_rates >> 16) & 0x1f;
  318. TRY(m_supported_pcm_sizes.try_ensure_capacity(popcount(pcm_sizes)));
  319. for (auto bit_rate_encoding : bit_rate_encodings) {
  320. if ((pcm_sizes & bit_rate_encoding.flag) > 0)
  321. m_supported_pcm_sizes.unchecked_append(bit_rate_encoding.bit_rate);
  322. }
  323. auto pcm_rates = supported_pcm_size_and_rates & 0x7ff;
  324. TRY(m_supported_pcm_rates.try_ensure_capacity(popcount(pcm_rates)));
  325. for (auto sample_rate_encoding : sample_rate_encodings) {
  326. if ((pcm_rates & sample_rate_encoding.flag) > 0)
  327. m_supported_pcm_rates.unchecked_append(sample_rate_encoding.sample_rate);
  328. }
  329. return {};
  330. }
  331. ErrorOr<void> WidgetNode::populate_supported_stream_formats()
  332. {
  333. VERIFY(m_supported_stream_formats == 0);
  334. // 7.3.4.8: Supported Stream Formats
  335. Node& stream_support_node = format_override() ? *this : *parent_node();
  336. auto supported_stream_formats = TRY(stream_support_node.parameter(GetParameterId::SupportedStreamFormats));
  337. if ((supported_stream_formats & 0x1) > 0)
  338. m_supported_stream_formats |= StreamFormatFlag::PCM;
  339. if ((supported_stream_formats & 0x2) > 0)
  340. m_supported_stream_formats |= StreamFormatFlag::Float32;
  341. if ((supported_stream_formats & 0x4) > 0)
  342. m_supported_stream_formats |= StreamFormatFlag::AC3;
  343. return {};
  344. }
  345. ErrorOr<void> WidgetNode::populate_connection_list()
  346. {
  347. VERIFY(connection_list_present());
  348. VERIFY(m_connection_list.is_empty());
  349. // 7.3.4.11: Connection List Length
  350. auto connection_list_length_info = TRY(parameter(GetParameterId::ConnectionListLength));
  351. bool long_form = (connection_list_length_info >> 7) & 0x1;
  352. u8 connection_list_length = connection_list_length_info & 0x7f;
  353. u8 entries_per_request = long_form ? 2 : 4;
  354. // 7.3.3.3: Get Connection List Entry
  355. for (u8 entry_offset = 0; entry_offset < connection_list_length; entry_offset += entries_per_request) {
  356. auto entries = TRY(command(CodecControlVerb::GetConnectionListEntry, entry_offset));
  357. for (u8 entry_index = 0; entry_index < min(entries_per_request, static_cast<int>(connection_list_length) - entry_offset); ++entry_index) {
  358. u16 entry = entries & (long_form ? 0xffff : 0xff);
  359. TRY(m_connection_list.try_append(entry));
  360. entries >>= (32 / entries_per_request);
  361. }
  362. }
  363. // 7.1.3: Widget Interconnection Rules
  364. // "Connection_List_Length = 1 means there is only one (hard-wired) input possible and,
  365. // therefore, there is no Connection_Selector field. The actual connection is read
  366. // from the Connection List as usual."
  367. if (connection_list_length == 1) {
  368. m_connection_index = 0;
  369. } else {
  370. // 7.3.3.2: Connection Select Control
  371. auto connection_selection_control = TRY(command(CodecControlVerb::GetConnectionSelectControl, 0));
  372. m_connection_index = connection_selection_control & 0xff;
  373. }
  374. return {};
  375. }
  376. ErrorOr<void> WidgetNode::populate_pin_configuration_default()
  377. {
  378. VERIFY(widget_type() == WidgetType::PinComplex);
  379. u32 configuration_default = TRY(command(CodecControlVerb::GetConfigurationDefault, 0));
  380. m_pin_configuration_default.sequence = configuration_default & 0xf;
  381. m_pin_configuration_default.default_association = (configuration_default >> 4) & 0xf;
  382. m_pin_configuration_default.misc = static_cast<PinMiscFlag>((configuration_default >> 8) & 0xf);
  383. m_pin_configuration_default.color = static_cast<PinColor>((configuration_default >> 12) & 0xf);
  384. m_pin_configuration_default.connection_type = static_cast<PinConnectionType>((configuration_default >> 16) & 0xf);
  385. m_pin_configuration_default.default_device = static_cast<PinDefaultDevice>((configuration_default >> 20) & 0xf);
  386. m_pin_configuration_default.geometric_location = static_cast<PinGeometricLocation>((configuration_default >> 24) & 0xf);
  387. m_pin_configuration_default.gross_location = static_cast<PinGrossLocation>((configuration_default >> 28) & 0x3);
  388. m_pin_configuration_default.port_connectivity = static_cast<PinPortConnectivity>(configuration_default >> 30);
  389. return {};
  390. }
  391. StringView WidgetNode::pin_color_name() const
  392. {
  393. auto underlying_color = to_underlying(m_pin_configuration_default.color);
  394. if (underlying_color >= 0xa && underlying_color <= 0xd)
  395. return "Reserved"sv;
  396. switch (m_pin_configuration_default.color) {
  397. case PinColor::Unknown:
  398. return "Unknown"sv;
  399. case PinColor::Black:
  400. return "Black"sv;
  401. case PinColor::Grey:
  402. return "Grey"sv;
  403. case PinColor::Blue:
  404. return "Blue"sv;
  405. case PinColor::Green:
  406. return "Green"sv;
  407. case PinColor::Red:
  408. return "Red"sv;
  409. case PinColor::Orange:
  410. return "Orange"sv;
  411. case PinColor::Yellow:
  412. return "Yellow"sv;
  413. case PinColor::Purple:
  414. return "Purple"sv;
  415. case PinColor::Pink:
  416. return "Pink"sv;
  417. case PinColor::White:
  418. return "White"sv;
  419. case PinColor::Other:
  420. return "Other"sv;
  421. }
  422. VERIFY_NOT_REACHED();
  423. }
  424. StringView WidgetNode::pin_connection_type_name() const
  425. {
  426. switch (m_pin_configuration_default.connection_type) {
  427. case PinConnectionType::Unknown:
  428. return "Unknown"sv;
  429. case PinConnectionType::EighthStereoMono:
  430. return "1/8\" Stereo/Mono"sv;
  431. case PinConnectionType::FourthStereoMono:
  432. return "1/4\" Stereo/Mono"sv;
  433. case PinConnectionType::ATAPIInternal:
  434. return "ATAPI Internal"sv;
  435. case PinConnectionType::RCA:
  436. return "RCA"sv;
  437. case PinConnectionType::Optical:
  438. return "Optical"sv;
  439. case PinConnectionType::OtherDigital:
  440. return "Other Digital"sv;
  441. case PinConnectionType::OtherAnalog:
  442. return "Other Analog"sv;
  443. case PinConnectionType::MultichannelAnalog:
  444. return "Multichannel Analog"sv;
  445. case PinConnectionType::XLRProfessional:
  446. return "XLR / Professional"sv;
  447. case PinConnectionType::RJ11:
  448. return "RJ-11 (Modem)"sv;
  449. case PinConnectionType::Combination:
  450. return "Combination"sv;
  451. case PinConnectionType::Other:
  452. return "Other"sv;
  453. }
  454. VERIFY_NOT_REACHED();
  455. }
  456. StringView WidgetNode::pin_default_device_name() const
  457. {
  458. switch (m_pin_configuration_default.default_device) {
  459. case PinDefaultDevice::LineOut:
  460. return "Line Out"sv;
  461. case PinDefaultDevice::Speaker:
  462. return "Speaker"sv;
  463. case PinDefaultDevice::HPOut:
  464. return "Headphones"sv;
  465. case PinDefaultDevice::CD:
  466. return "CD"sv;
  467. case PinDefaultDevice::SPDIFOut:
  468. return "S/PDIF Out"sv;
  469. case PinDefaultDevice::DigitalOtherOut:
  470. return "Digital Other Out"sv;
  471. case PinDefaultDevice::ModemLineSide:
  472. return "Modem Line Side"sv;
  473. case PinDefaultDevice::ModemHandsetSide:
  474. return "Modem Handset Side"sv;
  475. case PinDefaultDevice::LineIn:
  476. return "Line In"sv;
  477. case PinDefaultDevice::AUX:
  478. return "AUX"sv;
  479. case PinDefaultDevice::MicIn:
  480. return "Mic In"sv;
  481. case PinDefaultDevice::Telephony:
  482. return "Telephony"sv;
  483. case PinDefaultDevice::SPDIFIn:
  484. return "S/PDIF In"sv;
  485. case PinDefaultDevice::DigitalOtherIn:
  486. return "Digital Other In"sv;
  487. case PinDefaultDevice::Reserved:
  488. return "Reserved"sv;
  489. case PinDefaultDevice::Other:
  490. return "Other"sv;
  491. }
  492. VERIFY_NOT_REACHED();
  493. }
  494. StringView WidgetNode::pin_gross_location_name() const
  495. {
  496. switch (m_pin_configuration_default.gross_location) {
  497. case PinGrossLocation::ExternalOnPrimaryChassis:
  498. return "External on Primary Chassis"sv;
  499. case PinGrossLocation::Internal:
  500. return "Internal"sv;
  501. case PinGrossLocation::SeparateChassis:
  502. return "Separate Chassis"sv;
  503. case PinGrossLocation::Other:
  504. return "Other"sv;
  505. }
  506. VERIFY_NOT_REACHED();
  507. }
  508. StringView WidgetNode::pin_geometric_location_name() const
  509. {
  510. // 7.3.3.31: Configuration Default - special cases
  511. if (m_pin_configuration_default.geometric_location == PinGeometricLocation::Special1) {
  512. if (m_pin_configuration_default.gross_location == PinGrossLocation::ExternalOnPrimaryChassis)
  513. return "Rear Panel"sv;
  514. if (m_pin_configuration_default.gross_location == PinGrossLocation::Internal)
  515. return "Riser"sv;
  516. if (m_pin_configuration_default.gross_location == PinGrossLocation::Other)
  517. return "Mobile Lid (Inside)"sv;
  518. } else if (m_pin_configuration_default.geometric_location == PinGeometricLocation::Special2) {
  519. if (m_pin_configuration_default.gross_location == PinGrossLocation::ExternalOnPrimaryChassis)
  520. return "Drive Bay"sv;
  521. if (m_pin_configuration_default.gross_location == PinGrossLocation::Internal)
  522. return "Digital Display"sv;
  523. if (m_pin_configuration_default.gross_location == PinGrossLocation::Other)
  524. return "Mobile Lid (Outside)"sv;
  525. } else if (m_pin_configuration_default.geometric_location == PinGeometricLocation::Special3) {
  526. if (m_pin_configuration_default.gross_location == PinGrossLocation::Internal)
  527. return "ATAPI"sv;
  528. }
  529. switch (m_pin_configuration_default.geometric_location) {
  530. case PinGeometricLocation::NotApplicable:
  531. return "N/A"sv;
  532. case PinGeometricLocation::Rear:
  533. return "Rear"sv;
  534. case PinGeometricLocation::Front:
  535. return "Front"sv;
  536. case PinGeometricLocation::Left:
  537. return "Left"sv;
  538. case PinGeometricLocation::Right:
  539. return "Right"sv;
  540. case PinGeometricLocation::Top:
  541. return "Top"sv;
  542. case PinGeometricLocation::Bottom:
  543. return "Bottom"sv;
  544. case PinGeometricLocation::Special1:
  545. case PinGeometricLocation::Special2:
  546. case PinGeometricLocation::Special3:
  547. return "Special"sv;
  548. }
  549. VERIFY_NOT_REACHED();
  550. }
  551. StringView WidgetNode::pin_port_connectivity_name() const
  552. {
  553. switch (m_pin_configuration_default.port_connectivity) {
  554. case PinPortConnectivity::Jack:
  555. return "Jack"sv;
  556. case PinPortConnectivity::NoConnection:
  557. return "No Physical Connection"sv;
  558. case PinPortConnectivity::FixedFunction:
  559. return "Fixed Function Device"sv;
  560. case PinPortConnectivity::JackAndFixedFunction:
  561. return "Jack and Fixed Function Device"sv;
  562. }
  563. VERIFY_NOT_REACHED();
  564. }
  565. StringView FunctionGroupNode::function_group_type_name() const
  566. {
  567. switch (m_function_group_type) {
  568. case FunctionGroupType::AudioFunctionGroup:
  569. return "Audio Function Group"sv;
  570. case FunctionGroupType::ModemFunctionGroup:
  571. return "Modem Function Group"sv;
  572. case FunctionGroupType::VendorFunctionGroup:
  573. return "Vendor Function Group"sv;
  574. case FunctionGroupType::Reserved:
  575. return "Reserved"sv;
  576. }
  577. VERIFY_NOT_REACHED();
  578. }
  579. ErrorOr<void> FunctionGroupNode::initialize()
  580. {
  581. TRY(NodeWithChildren<WidgetNode>::initialize());
  582. // 7.3.4.4: Function Group Type
  583. auto function_group_type = TRY(parameter(GetParameterId::FunctionGroupType));
  584. if (function_group_type == 0x1)
  585. m_function_group_type = FunctionGroupType::AudioFunctionGroup;
  586. else if (function_group_type == 0x2)
  587. m_function_group_type = FunctionGroupType::ModemFunctionGroup;
  588. else if (function_group_type >= 0x80)
  589. m_function_group_type = FunctionGroupType::VendorFunctionGroup;
  590. else
  591. m_function_group_type = FunctionGroupType::Reserved;
  592. return {};
  593. }
  594. ErrorOr<NonnullOwnPtr<KString>> FunctionGroupNode::to_string()
  595. {
  596. StringBuilder builder;
  597. TRY(builder.try_appendff("FunctionGroupNode(node_id={})", node_id()));
  598. return KString::try_create(builder.string_view());
  599. }
  600. void FunctionGroupNode::debug_dump(bool is_last) const
  601. {
  602. dbgln("{} Function group (node #{}):", is_last ? "└"sv : "├"sv, node_id());
  603. auto spine = is_last ? " "sv : "│"sv;
  604. dbgln("{} ├ Function group type: {} ({:#x})", spine, function_group_type_name(), to_underlying(function_group_type()));
  605. for_each_child_node([&spine](WidgetNode const& widget_node, bool is_last) -> void {
  606. widget_node.debug_dump(spine, is_last);
  607. });
  608. }
  609. ErrorOr<void> RootNode::initialize()
  610. {
  611. TRY(NodeWithChildren<FunctionGroupNode>::initialize());
  612. // 7.3.4.1: Vendor ID
  613. auto vendor_id_response = TRY(parameter(GetParameterId::VendorID));
  614. m_vendor_id = (vendor_id_response >> 16) & 0xffff;
  615. m_device_id = vendor_id_response & 0xffff;
  616. // 7.3.4.2: Revision ID
  617. auto revision_id_response = TRY(parameter(GetParameterId::RevisionID));
  618. m_major_revision = (revision_id_response >> 20) & 0xf;
  619. m_minor_revision = (revision_id_response >> 16) & 0xf;
  620. if (m_major_revision != 1 || m_minor_revision != 0)
  621. return ENOTSUP;
  622. return {};
  623. }
  624. ErrorOr<NonnullOwnPtr<KString>> RootNode::to_string()
  625. {
  626. StringBuilder builder;
  627. TRY(builder.try_appendff("RootNode(node_id={})", node_id()));
  628. return KString::try_create(builder.string_view());
  629. }
  630. void RootNode::debug_dump() const
  631. {
  632. dbgln("Root (node #{}):", node_id());
  633. dbgln("├ Codec vendor: {:#04x}, device: {:#04x}", vendor_id(), device_id());
  634. dbgln("├ Codec HDA compatibility: {}.{}", major_revision(), minor_revision());
  635. for_each_child_node([](FunctionGroupNode const& fg_node, bool is_last) -> void {
  636. fg_node.debug_dump(is_last);
  637. });
  638. }
  639. }