// 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.

#ifndef ZIRCON_SYSTEM_UAPP_IHDA_CODEC_STATE_H_
#define ZIRCON_SYSTEM_UAPP_IHDA_CODEC_STATE_H_

#include <stddef.h>
#include <stdint.h>
#include <zircon/assert.h>
#include <zircon/types.h>

#include <memory>

#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 = std::unique_ptr<AudioWidgetState>;

struct FunctionGroupState;
struct AudioFunctionGroupState;
using FunctionGroupStatePtr = std::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_;
  std::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;
  std::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_;
  std::unique_ptr<FunctionGroupStatePtr[]> fn_groups_;
};

}  // namespace intel_hda
}  // namespace audio

#endif  // ZIRCON_SYSTEM_UAPP_IHDA_CODEC_STATE_H_
