| // 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 <hwreg/bitfields.h> |
| |
| namespace registers { |
| |
| // Number of DDIs that the hardware provides. |
| constexpr uint32_t kDdiCount = 5; |
| |
| enum Ddi { |
| DDI_A, DDI_B, DDI_C, DDI_D, DDI_E |
| }; |
| |
| static const Ddi kDdis[kDdiCount] = { |
| DDI_A, DDI_B, DDI_C, DDI_D, DDI_E, |
| }; |
| |
| // South Display Engine Interrupt Bit Definition + SINTERRUPT |
| class SdeInterruptBase : public hwreg::RegisterBase<SdeInterruptBase, uint32_t> { |
| public: |
| static constexpr uint32_t kSdeIntMask = 0xc4004; |
| static constexpr uint32_t kSdeIntIdentity = 0xc4008; |
| static constexpr uint32_t kSdeIntEnable = 0xc400c; |
| |
| hwreg::BitfieldRef<uint32_t> ddi_bit(Ddi ddi) { |
| uint32_t bit; |
| switch (ddi) { |
| case DDI_A: |
| bit = 24; |
| break; |
| case DDI_B: |
| case DDI_C: |
| case DDI_D: |
| bit = 20 + ddi; |
| break; |
| case DDI_E: |
| bit = 25; |
| break; |
| default: |
| bit = -1; |
| } |
| return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit); |
| } |
| |
| static auto Get(uint32_t offset) { return hwreg::RegisterAddr<SdeInterruptBase>(offset); } |
| }; |
| |
| // SHOTPLUG_CTL + SHOTPLUG_CTL2 |
| class HotplugCtrl : public hwreg::RegisterBase<HotplugCtrl, uint32_t> { |
| public: |
| hwreg::BitfieldRef<uint32_t> hpd_enable(Ddi ddi) { |
| uint32_t bit = ddi_to_first_bit(ddi) + kHpdEnableBitSubOffset; |
| return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit); |
| } |
| |
| hwreg::BitfieldRef<uint32_t> hpd_long_pulse(Ddi ddi) { |
| uint32_t bit = ddi_to_first_bit(ddi) + kHpdLongPulseBitSubOffset; |
| return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit); |
| } |
| |
| hwreg::BitfieldRef<uint32_t> hpd_short_pulse(Ddi ddi) { |
| uint32_t bit = ddi_to_first_bit(ddi) + kHpdShortPulseBitSubOffset; |
| return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit); |
| } |
| |
| static auto Get(Ddi ddi) { |
| return hwreg::RegisterAddr<HotplugCtrl>(ddi == DDI_E ? kOffset2 : kOffset); |
| } |
| |
| private: |
| static constexpr uint32_t kOffset = 0xc4030; |
| static constexpr uint32_t kOffset2 = 0xc403c; |
| |
| static constexpr uint32_t kHpdShortPulseBitSubOffset = 0; |
| static constexpr uint32_t kHpdLongPulseBitSubOffset = 1; |
| static constexpr uint32_t kHpdEnableBitSubOffset = 4; |
| |
| static uint32_t ddi_to_first_bit(Ddi ddi) { |
| switch (ddi) { |
| case DDI_A: |
| return 24; |
| case DDI_B: |
| case DDI_C: |
| case DDI_D: |
| return 8 * (ddi - 1); |
| case DDI_E: |
| return 0; |
| default: |
| return -1; |
| } |
| } |
| }; |
| |
| // SFUSE_STRAP |
| class SouthFuseStrap : public hwreg::RegisterBase<SouthFuseStrap, uint32_t> { |
| public: |
| DEF_BIT(2, port_b_present); |
| DEF_BIT(1, port_c_present); |
| DEF_BIT(0, port_d_present); |
| |
| static auto Get() { return hwreg::RegisterAddr<SouthFuseStrap>(0xc2014); } |
| }; |
| |
| // DDI_BUF_CTL |
| class DdiBufControl : public hwreg::RegisterBase<DdiBufControl, uint32_t> { |
| public: |
| static constexpr uint32_t kBaseAddr = 0x64000; |
| |
| DEF_BIT(31, ddi_buffer_enable); |
| DEF_FIELD(27, 24, dp_vswing_emp_sel); |
| DEF_BIT(16, port_reversal); |
| DEF_BIT(7, ddi_idle_status); |
| DEF_BIT(4, ddi_a_lane_capability_control); |
| DEF_FIELD(3, 1, dp_port_width_selection); |
| DEF_BIT(0, init_display_detected); |
| }; |
| |
| // High byte of DDI_BUF_TRANS |
| class DdiBufTransHi : public hwreg::RegisterBase<DdiBufTransHi, uint32_t> { |
| public: |
| DEF_FIELD(20, 16, vref); |
| DEF_FIELD(10, 0, vswing); |
| }; |
| |
| // Low byte of DDI_BUF_TRANS |
| class DdiBufTransLo : public hwreg::RegisterBase<DdiBufTransLo, uint32_t> { |
| public: |
| DEF_BIT(31, balance_leg_enable); |
| DEF_FIELD(17, 0, deemphasis_level); |
| }; |
| |
| // DISPIO_CR_TX_BMU_CR0 |
| class DisplayIoCtrlRegTxBmu : public hwreg::RegisterBase<DisplayIoCtrlRegTxBmu, uint32_t> { |
| public: |
| DEF_FIELD(27, 23, disable_balance_leg); |
| |
| hwreg::BitfieldRef<uint32_t> tx_balance_leg_select(Ddi ddi) { |
| int bit = 8 + 3 * ddi; |
| return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit + 2, bit); |
| } |
| |
| static auto Get() { return hwreg::RegisterAddr<DisplayIoCtrlRegTxBmu>(0x6c00c); } |
| }; |
| |
| // DDI_AUX_CTL |
| class DdiAuxControl : public hwreg::RegisterBase<DdiAuxControl, uint32_t> { |
| public: |
| static constexpr uint32_t kBaseAddr = 0x64010; |
| |
| DEF_BIT(31, send_busy); |
| DEF_BIT(30, done); |
| DEF_BIT(29, interrupt_on_done); |
| DEF_BIT(28, timeout); |
| DEF_FIELD(27, 26, timeout_timer_value); |
| DEF_BIT(25, rcv_error); |
| DEF_FIELD(24, 20, message_size); |
| DEF_FIELD(4, 0, sync_pulse_count); |
| }; |
| |
| // DDI_AUX_DATA |
| class DdiAuxData : public hwreg::RegisterBase<DdiAuxData, uint32_t> { |
| public: |
| // There are 5 32-bit words at this register's address. |
| static constexpr uint32_t kBaseAddr = 0x64014; |
| }; |
| |
| // DP_TP_CTL |
| class DdiDpTransportControl : public hwreg::RegisterBase<DdiDpTransportControl, uint32_t> { |
| public: |
| static constexpr uint32_t kBaseAddr = 0x64040; |
| |
| DEF_BIT(31, transport_enable); |
| DEF_BIT(27, transport_mode_select); |
| DEF_BIT(25, force_act); |
| DEF_BIT(18, enhanced_framing_enable); |
| |
| DEF_FIELD(10, 8, dp_link_training_pattern); |
| static constexpr int kTrainingPattern1 = 0; |
| static constexpr int kTrainingPattern2 = 1; |
| static constexpr int kIdlePattern = 2; |
| static constexpr int kSendPixelData = 3; |
| |
| DEF_BIT(6, alternate_sr_enable); |
| }; |
| |
| // An instance of DdiRegs represents the registers for a particular DDI. |
| class DdiRegs { |
| public: |
| DdiRegs(Ddi ddi) : ddi_number_((int) ddi) { } |
| |
| hwreg::RegisterAddr<registers::DdiBufControl> DdiBufControl() { |
| return GetReg<registers::DdiBufControl>(); |
| } |
| hwreg::RegisterAddr<registers::DdiAuxControl> DdiAuxControl() { |
| return GetReg<registers::DdiAuxControl>(); |
| } |
| hwreg::RegisterAddr<registers::DdiAuxData> DdiAuxData() { return GetReg<registers::DdiAuxData>(); } |
| hwreg::RegisterAddr<registers::DdiDpTransportControl> DdiDpTransportControl() { |
| return GetReg<registers::DdiDpTransportControl>(); |
| } |
| hwreg::RegisterAddr<registers::DdiBufTransHi> DdiBufTransHi(int index) { |
| return hwreg::RegisterAddr<registers::DdiBufTransHi>(0x64e00 + 0x60 * ddi_number_ + 8 * index + 4); |
| } |
| hwreg::RegisterAddr<registers::DdiBufTransLo> DdiBufTransLo(int index) { |
| return hwreg::RegisterAddr<registers::DdiBufTransLo>(0x64e00 + 0x60 * ddi_number_ + 8 * index); |
| } |
| |
| private: |
| template <class RegType> hwreg::RegisterAddr<RegType> GetReg() { |
| return hwreg::RegisterAddr<RegType>(RegType::kBaseAddr + 0x100 * ddi_number_); |
| } |
| |
| uint32_t ddi_number_; |
| }; |
| |
| } // namespace registers |