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 #pragma once 6 7 #include <hwreg/bitfields.h> 8 9 namespace registers { 10 11 // Number of DDIs that the hardware provides. 12 constexpr uint32_t kDdiCount = 5; 13 14 enum Ddi { 15 DDI_A, DDI_B, DDI_C, DDI_D, DDI_E 16 }; 17 18 static const Ddi kDdis[kDdiCount] = { 19 DDI_A, DDI_B, DDI_C, DDI_D, DDI_E, 20 }; 21 22 // South Display Engine Interrupt Bit Definition + SINTERRUPT 23 class SdeInterruptBase : public hwreg::RegisterBase<SdeInterruptBase, uint32_t> { 24 public: 25 static constexpr uint32_t kSdeIntMask = 0xc4004; 26 static constexpr uint32_t kSdeIntIdentity = 0xc4008; 27 static constexpr uint32_t kSdeIntEnable = 0xc400c; 28 ddi_bit(Ddi ddi)29 hwreg::BitfieldRef<uint32_t> ddi_bit(Ddi ddi) { 30 uint32_t bit; 31 switch (ddi) { 32 case DDI_A: 33 bit = 24; 34 break; 35 case DDI_B: 36 case DDI_C: 37 case DDI_D: 38 bit = 20 + ddi; 39 break; 40 case DDI_E: 41 bit = 25; 42 break; 43 default: 44 bit = -1; 45 } 46 return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit); 47 } 48 Get(uint32_t offset)49 static auto Get(uint32_t offset) { return hwreg::RegisterAddr<SdeInterruptBase>(offset); } 50 }; 51 52 // SHOTPLUG_CTL + SHOTPLUG_CTL2 53 class HotplugCtrl : public hwreg::RegisterBase<HotplugCtrl, uint32_t> { 54 public: hpd_enable(Ddi ddi)55 hwreg::BitfieldRef<uint32_t> hpd_enable(Ddi ddi) { 56 uint32_t bit = ddi_to_first_bit(ddi) + kHpdEnableBitSubOffset; 57 return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit); 58 } 59 hpd_long_pulse(Ddi ddi)60 hwreg::BitfieldRef<uint32_t> hpd_long_pulse(Ddi ddi) { 61 uint32_t bit = ddi_to_first_bit(ddi) + kHpdLongPulseBitSubOffset; 62 return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit); 63 } 64 hpd_short_pulse(Ddi ddi)65 hwreg::BitfieldRef<uint32_t> hpd_short_pulse(Ddi ddi) { 66 uint32_t bit = ddi_to_first_bit(ddi) + kHpdShortPulseBitSubOffset; 67 return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit); 68 } 69 Get(Ddi ddi)70 static auto Get(Ddi ddi) { 71 return hwreg::RegisterAddr<HotplugCtrl>(ddi == DDI_E ? kOffset2 : kOffset); 72 } 73 74 private: 75 static constexpr uint32_t kOffset = 0xc4030; 76 static constexpr uint32_t kOffset2 = 0xc403c; 77 78 static constexpr uint32_t kHpdShortPulseBitSubOffset = 0; 79 static constexpr uint32_t kHpdLongPulseBitSubOffset = 1; 80 static constexpr uint32_t kHpdEnableBitSubOffset = 4; 81 ddi_to_first_bit(Ddi ddi)82 static uint32_t ddi_to_first_bit(Ddi ddi) { 83 switch (ddi) { 84 case DDI_A: 85 return 24; 86 case DDI_B: 87 case DDI_C: 88 case DDI_D: 89 return 8 * (ddi - 1); 90 case DDI_E: 91 return 0; 92 default: 93 return -1; 94 } 95 } 96 }; 97 98 // SFUSE_STRAP 99 class SouthFuseStrap : public hwreg::RegisterBase<SouthFuseStrap, uint32_t> { 100 public: 101 DEF_BIT(2, port_b_present); 102 DEF_BIT(1, port_c_present); 103 DEF_BIT(0, port_d_present); 104 Get()105 static auto Get() { return hwreg::RegisterAddr<SouthFuseStrap>(0xc2014); } 106 }; 107 108 // DDI_BUF_CTL 109 class DdiBufControl : public hwreg::RegisterBase<DdiBufControl, uint32_t> { 110 public: 111 static constexpr uint32_t kBaseAddr = 0x64000; 112 113 DEF_BIT(31, ddi_buffer_enable); 114 DEF_FIELD(27, 24, dp_vswing_emp_sel); 115 DEF_BIT(16, port_reversal); 116 DEF_BIT(7, ddi_idle_status); 117 DEF_BIT(4, ddi_a_lane_capability_control); 118 DEF_FIELD(3, 1, dp_port_width_selection); 119 DEF_BIT(0, init_display_detected); 120 }; 121 122 // High byte of DDI_BUF_TRANS 123 class DdiBufTransHi : public hwreg::RegisterBase<DdiBufTransHi, uint32_t> { 124 public: 125 DEF_FIELD(20, 16, vref); 126 DEF_FIELD(10, 0, vswing); 127 }; 128 129 // Low byte of DDI_BUF_TRANS 130 class DdiBufTransLo : public hwreg::RegisterBase<DdiBufTransLo, uint32_t> { 131 public: 132 DEF_BIT(31, balance_leg_enable); 133 DEF_FIELD(17, 0, deemphasis_level); 134 }; 135 136 // DISPIO_CR_TX_BMU_CR0 137 class DisplayIoCtrlRegTxBmu : public hwreg::RegisterBase<DisplayIoCtrlRegTxBmu, uint32_t> { 138 public: 139 DEF_FIELD(27, 23, disable_balance_leg); 140 tx_balance_leg_select(Ddi ddi)141 hwreg::BitfieldRef<uint32_t> tx_balance_leg_select(Ddi ddi) { 142 int bit = 8 + 3 * ddi; 143 return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit + 2, bit); 144 } 145 Get()146 static auto Get() { return hwreg::RegisterAddr<DisplayIoCtrlRegTxBmu>(0x6c00c); } 147 }; 148 149 // DDI_AUX_CTL 150 class DdiAuxControl : public hwreg::RegisterBase<DdiAuxControl, uint32_t> { 151 public: 152 static constexpr uint32_t kBaseAddr = 0x64010; 153 154 DEF_BIT(31, send_busy); 155 DEF_BIT(30, done); 156 DEF_BIT(29, interrupt_on_done); 157 DEF_BIT(28, timeout); 158 DEF_FIELD(27, 26, timeout_timer_value); 159 DEF_BIT(25, rcv_error); 160 DEF_FIELD(24, 20, message_size); 161 DEF_FIELD(4, 0, sync_pulse_count); 162 }; 163 164 // DDI_AUX_DATA 165 class DdiAuxData : public hwreg::RegisterBase<DdiAuxData, uint32_t> { 166 public: 167 // There are 5 32-bit words at this register's address. 168 static constexpr uint32_t kBaseAddr = 0x64014; 169 }; 170 171 // DP_TP_CTL 172 class DdiDpTransportControl : public hwreg::RegisterBase<DdiDpTransportControl, uint32_t> { 173 public: 174 static constexpr uint32_t kBaseAddr = 0x64040; 175 176 DEF_BIT(31, transport_enable); 177 DEF_BIT(27, transport_mode_select); 178 DEF_BIT(25, force_act); 179 DEF_BIT(18, enhanced_framing_enable); 180 181 DEF_FIELD(10, 8, dp_link_training_pattern); 182 static constexpr int kTrainingPattern1 = 0; 183 static constexpr int kTrainingPattern2 = 1; 184 static constexpr int kIdlePattern = 2; 185 static constexpr int kSendPixelData = 3; 186 187 DEF_BIT(6, alternate_sr_enable); 188 }; 189 190 // An instance of DdiRegs represents the registers for a particular DDI. 191 class DdiRegs { 192 public: DdiRegs(Ddi ddi)193 DdiRegs(Ddi ddi) : ddi_number_((int) ddi) { } 194 DdiBufControl()195 hwreg::RegisterAddr<registers::DdiBufControl> DdiBufControl() { 196 return GetReg<registers::DdiBufControl>(); 197 } DdiAuxControl()198 hwreg::RegisterAddr<registers::DdiAuxControl> DdiAuxControl() { 199 return GetReg<registers::DdiAuxControl>(); 200 } DdiAuxData()201 hwreg::RegisterAddr<registers::DdiAuxData> DdiAuxData() { return GetReg<registers::DdiAuxData>(); } DdiDpTransportControl()202 hwreg::RegisterAddr<registers::DdiDpTransportControl> DdiDpTransportControl() { 203 return GetReg<registers::DdiDpTransportControl>(); 204 } DdiBufTransHi(int index)205 hwreg::RegisterAddr<registers::DdiBufTransHi> DdiBufTransHi(int index) { 206 return hwreg::RegisterAddr<registers::DdiBufTransHi>(0x64e00 + 0x60 * ddi_number_ + 8 * index + 4); 207 } DdiBufTransLo(int index)208 hwreg::RegisterAddr<registers::DdiBufTransLo> DdiBufTransLo(int index) { 209 return hwreg::RegisterAddr<registers::DdiBufTransLo>(0x64e00 + 0x60 * ddi_number_ + 8 * index); 210 } 211 212 private: GetReg()213 template <class RegType> hwreg::RegisterAddr<RegType> GetReg() { 214 return hwreg::RegisterAddr<RegType>(RegType::kBaseAddr + 0x100 * ddi_number_); 215 } 216 217 uint32_t ddi_number_; 218 }; 219 220 } // namespace registers 221