| // 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 <zircon/assert.h> |
| #include <zircon/types.h> |
| #include <fbl/unique_ptr.h> |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #include <intel-hda/utils/codec-caps.h> |
| #include <intel-hda/utils/codec-commands.h> |
| #include <intel-hda/utils/codec-state.h> |
| |
| namespace audio { |
| namespace intel_hda { |
| |
| struct AudioWidgetState; |
| using AudioWidgetStatePtr = fbl::unique_ptr<AudioWidgetState>; |
| |
| struct FunctionGroupState; |
| struct AudioFunctionGroupState; |
| using FunctionGroupStatePtr = fbl::unique_ptr<FunctionGroupState>; |
| |
| struct PowerState { |
| // Section 7.3.4.12 : Supported Power States |
| uint32_t supported_states_; |
| |
| // Section 7.3.3.10 : Current power state |
| uint8_t set_; |
| uint8_t active_; |
| bool error_; |
| bool clock_stop_ok_; |
| bool settings_reset_; |
| }; |
| |
| // Section 7.3.3.14. Present only in nodes (function groups and widgets) whose |
| // capabilities indicate the ability to send unsolicited responses. |
| struct UnsolicitedResponseState { |
| bool enabled() const { return (raw_data_ & 0x80) != 0; } |
| uint8_t tag() const { return static_cast<uint8_t>(raw_data_ & 0x3f); } |
| uint8_t raw_data_; |
| }; |
| |
| struct AudioWidgetState { |
| struct StreamFormat { |
| // Stream format bitfields documented in section 3.7.1 |
| static constexpr uint16_t FLAG_NON_PCM = (1u << 15); |
| |
| uint32_t BASE() const { return (raw_data_ & (1u << 14)) ? 44100 : 48000; } |
| uint32_t CHAN() const { return (raw_data_ & 0xF) + 1; } |
| uint32_t DIV() const { return ((raw_data_ >> 8) & 0x7) + 1; } |
| uint32_t MULT() const { |
| uint32_t bits = (raw_data_ >> 11) & 0x7; |
| if (bits >= 4) |
| return 0; |
| return bits + 1; |
| } |
| uint32_t BITS() const { |
| switch ((raw_data_ >> 4) & 0x7) { |
| case 0: return 8u; |
| case 1: return 16u; |
| case 2: return 20u; |
| case 3: return 24u; |
| case 4: return 32u; |
| default: return 0u; |
| } |
| } |
| |
| bool is_pcm() const { return (raw_data_ & FLAG_NON_PCM) == 0; } |
| uint32_t sample_rate() const { return (BASE() * MULT()) / DIV(); } |
| uint32_t channels() const { return CHAN(); } |
| uint32_t bits_per_chan() const { return BITS(); } |
| |
| uint16_t raw_data_; |
| }; |
| |
| struct AmpState { |
| uint8_t gain[2]; |
| bool mute[2]; |
| }; |
| |
| struct ConnListEntry { |
| bool range_; |
| uint16_t nid_; |
| AmpState amp_state_; |
| }; |
| |
| explicit AudioWidgetState(const AudioWidgetCaps& caps) : caps_(caps) { } |
| |
| const AudioWidgetCaps caps_; |
| const AudioFunctionGroupState* afg_ = nullptr; |
| uint16_t nid_; |
| |
| // Note: to simplify life, the widget struct contains the union of all of |
| // the different field which may be needed for any type of audio widget. |
| // Not all of the fields will be meaningful depending on the widget type. |
| uint32_t pcm_size_rate_; // Section 7.3.4.7 : Supported PCM sizes and rates |
| uint32_t pcm_formats_; // Section 7.3.4.8 : Supported PCM formats |
| uint32_t pin_caps_ = 0; // Section 7.3.4.9 : Pin Capabilities |
| StreamFormat cur_format_; |
| |
| // Section 7.3.3.11 : Stream tag and channel routing for converters. |
| uint8_t stream_tag_; |
| uint8_t stream_chan_; |
| |
| // Section 7.3.4.10 : Amplifier capabilities |
| AmpCaps input_amp_caps_; |
| AmpCaps output_amp_caps_; |
| |
| // Section 7.3.3.7 : Amplifier Gain/Mute state |
| AmpState input_amp_state_; |
| AmpState output_amp_state_; |
| |
| // Sections 7.3.3.2, 7.3.3.3 & 7.3.4.11 : Connection List |
| bool long_form_conn_list_; |
| uint8_t conn_list_len_; |
| fbl::unique_ptr<ConnListEntry[]> conn_list_; |
| uint16_t connected_nid_; |
| uint8_t connected_nid_ndx_; |
| |
| // Sections 7.3.4.12 & 7.3.3.10. |
| PowerState power_; |
| |
| // Section 7.3.4.13 : Processing Capabilities |
| bool can_bypass_processing_; |
| uint8_t processing_coefficient_count_; |
| |
| // Section 7.3.4.15 : Volume Knob Capabilities |
| bool vol_knob_is_delta_; |
| uint8_t vol_knob_steps_; |
| |
| // Section 7.3.3.31. Present only in pin complexes |
| ConfigDefaults cfg_defaults_; |
| |
| // Section 7.3.3.12. Present only in pin complexes |
| PinWidgetCtrlState pin_widget_ctrl_; |
| |
| // Section 7.3.3.14. |
| UnsolicitedResponseState unsol_resp_ctrl_; |
| |
| // Section 7.3.3.15 |
| // |
| // Only valid for pin complexes, only run if the pin complex supports |
| // presence detect and the config defaults do not indicate a jack detect |
| // override. |
| PinSenseState pin_sense_; |
| bool pin_sense_valid_ = false; |
| |
| // Section 7.3.3.16 : External amp power down state |
| EAPDState eapd_state_; |
| }; |
| |
| struct FunctionGroupState { |
| virtual ~FunctionGroupState() { } |
| |
| enum class Type : uint8_t { |
| AUDIO = 0x01, |
| MODEM = 0x02, |
| VENDOR_START = 0x80, |
| VENDOR_END = 0xFF, |
| }; |
| |
| // Section 7.3.3.30 |
| struct ImplementationID { |
| uint32_t BoardImplID() const { return (raw_data_ >> 8) & 0xFFFFFF; } |
| uint16_t BoardMfrID() const { return static_cast<uint16_t>(raw_data_ >> 16); } |
| uint8_t BoardSKU() const { return static_cast<uint8_t>((raw_data_ >> 8) & 0xFF); } |
| uint8_t AssemblyID() const { return static_cast<uint8_t>(raw_data_ & 0xFF); } |
| uint32_t raw_data_; |
| }; |
| |
| const Type type_; |
| bool can_send_unsolicited_; |
| uint16_t nid_; |
| ImplementationID impl_id_; |
| UnsolicitedResponseState unsol_resp_ctrl_; |
| |
| protected: |
| explicit FunctionGroupState(Type type) |
| : type_(type) { } |
| }; |
| |
| struct AudioFunctionGroupState : public FunctionGroupState { |
| AudioFunctionGroupState() : FunctionGroupState(Type::AUDIO) { } |
| |
| AudioFunctionGroupCaps caps_; |
| uint32_t default_pcm_size_rate_; // Section 7.3.4.7 : Supported PCM sizes and rates |
| uint32_t default_pcm_formats_; // Section 7.3.4.8 : Supported PCM formats |
| |
| // Section 7.3.4.10 : Amplifier capabilities |
| AmpCaps default_input_amp_caps_; |
| AmpCaps default_output_amp_caps_; |
| |
| // Sections 7.3.4.12 & 7.3.3.10. |
| PowerState power_; |
| |
| // Section 7.3.4.14 : GPIO Counts |
| bool gpio_can_wake_; |
| bool gpio_can_send_unsolicited_; |
| uint8_t gpio_count_; |
| uint8_t gpo_count_; |
| uint8_t gpi_count_; |
| |
| uint8_t widget_count_ = 0; |
| uint8_t widget_starting_id_ = 0; |
| fbl::unique_ptr<AudioWidgetStatePtr[]> widgets_; |
| }; |
| |
| struct ModemFunctionGroupState : public FunctionGroupState { |
| ModemFunctionGroupState() : FunctionGroupState(Type::MODEM) { } |
| }; |
| |
| struct VendorFunctionGroupState : public FunctionGroupState { |
| explicit VendorFunctionGroupState(Type type) |
| : FunctionGroupState(type) { |
| ZX_DEBUG_ASSERT((type >= Type::VENDOR_START) && |
| (type <= Type::VENDOR_START)); |
| } |
| }; |
| |
| struct CodecState { |
| void reset() { fn_groups_.reset(); } |
| |
| uint16_t vendor_id_; |
| uint16_t device_id_; |
| |
| uint8_t major_rev_; |
| uint8_t minor_rev_; |
| uint8_t vendor_rev_id_; |
| uint8_t vendor_stepping_id_; |
| |
| uint8_t fn_group_count_; |
| uint8_t fn_group_starting_id_; |
| fbl::unique_ptr<FunctionGroupStatePtr[]> fn_groups_; |
| }; |
| |
| } // namespace audio |
| } // namespace intel_hda |