blob: fbeda654c633a79807995e64ad367a06411d7b9b [file] [log] [blame]
// 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 SRC_GRAPHICS_DISPLAY_DRIVERS_INTEL_I915_REGISTERS_DPLL_H_
#define SRC_GRAPHICS_DISPLAY_DRIVERS_INTEL_I915_REGISTERS_DPLL_H_
#include <assert.h>
#include <hwreg/bitfields.h>
#include "src/graphics/display/drivers/intel-i915/registers-ddi.h"
namespace registers {
static constexpr uint32_t kDpllCount = 4;
enum Dpll {
DPLL_INVALID = -1,
DPLL_0 = 0,
DPLL_1,
DPLL_2,
DPLL_3,
};
static const Dpll kDplls[kDpllCount] = {
DPLL_0,
DPLL_1,
DPLL_2,
DPLL_3,
};
// DPLL_CTRL1
class DpllControl1 : public hwreg::RegisterBase<DpllControl1, uint32_t> {
public:
enum class LinkRate : uint8_t {
k2700Mhz = 0, // DisplayPort 5.4 GHz (VCO 8100)
k1350Mhz = 1, // DisplayPort 2.7 GHz (VCO 8100)
k810Mhz = 2, // DisplayPort 1.62 GHz (VCO 8100)
k1620Mhz = 3, // DisplayPort 3.24 GHz (VCO 8100)
k1080Mhz = 4, // DisplayPort 2.16 GHz (VCO 8640)
k2160Mhz = 5, // DisplayPort 4.32 GHz (VCO 8640)
};
hwreg::BitfieldRef<uint32_t> dpll_hdmi_mode(Dpll dpll) {
int bit = dpll * 6 + 5;
return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit);
}
hwreg::BitfieldRef<uint32_t> dpll_ssc_enable(Dpll dpll) {
int bit = dpll * 6 + 4;
return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit);
}
hwreg::BitfieldRef<uint32_t> dpll_link_rate(Dpll dpll) {
int bit = dpll * 6 + 1;
return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit + 2, bit);
}
LinkRate GetLinkRate(Dpll dpll) { return static_cast<LinkRate>(dpll_link_rate(dpll).get()); }
void SetLinkRate(Dpll dpll, LinkRate rate) {
dpll_link_rate(dpll).set(static_cast<std::underlying_type_t<LinkRate>>(rate));
}
hwreg::BitfieldRef<uint32_t> dpll_override(Dpll dpll) {
int bit = dpll * 6;
return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit);
}
static auto Get() { return hwreg::RegisterAddr<DpllControl1>(0x6c058); }
};
// DPLL_CTRL2
class DpllControl2 : public hwreg::RegisterBase<DpllControl2, uint32_t> {
public:
hwreg::BitfieldRef<uint32_t> ddi_clock_off(Ddi ddi) {
int bit = 15 + ddi;
return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit);
}
hwreg::BitfieldRef<uint32_t> ddi_clock_select(Ddi ddi) {
int bit = ddi * 3 + 1;
return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit + 1, bit);
}
hwreg::BitfieldRef<uint32_t> ddi_select_override(Ddi ddi) {
int bit = ddi * 3;
return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit);
}
static auto Get() { return hwreg::RegisterAddr<DpllControl2>(0x6c05c); }
};
// DPLL_CFGCR1
class DpllConfig1 : public hwreg::RegisterBase<DpllConfig1, uint32_t> {
public:
DEF_BIT(31, frequency_enable);
DEF_FIELD(23, 9, dco_fraction);
DEF_FIELD(8, 0, dco_integer);
static auto Get(Dpll dpll) {
ZX_ASSERT(dpll == DPLL_1 || dpll == DPLL_2 || dpll == DPLL_3);
return hwreg::RegisterAddr<DpllConfig1>(0x6c040 + ((dpll - 1) * 8));
}
};
// DPLL_CFGCR2
class DpllConfig2 : public hwreg::RegisterBase<DpllConfig2, uint32_t> {
public:
DEF_FIELD(15, 8, qdiv_ratio);
DEF_BIT(7, qdiv_mode);
DEF_FIELD(6, 5, kdiv_ratio);
static constexpr uint8_t kKdiv5 = 0;
static constexpr uint8_t kKdiv2 = 1;
static constexpr uint8_t kKdiv3 = 2;
static constexpr uint8_t kKdiv1 = 3;
DEF_FIELD(4, 2, pdiv_ratio);
static constexpr uint8_t kPdiv1 = 0;
static constexpr uint8_t kPdiv2 = 1;
static constexpr uint8_t kPdiv3 = 2;
static constexpr uint8_t kPdiv7 = 4;
DEF_FIELD(1, 0, central_freq);
static constexpr uint8_t k9600Mhz = 0;
static constexpr uint8_t k9000Mhz = 1;
static constexpr uint8_t k8400Mhz = 3;
static auto Get(int dpll) {
ZX_ASSERT(dpll == DPLL_1 || dpll == DPLL_2 || dpll == DPLL_3);
return hwreg::RegisterAddr<DpllConfig2>(0x6c044 + ((dpll - 1) * 8));
}
};
// Virtual register which unifies the dpll enable bits (which are spread
// across 4 registers)
class DpllEnable : public hwreg::RegisterBase<DpllEnable, uint32_t> {
public:
DEF_BIT(31, enable_dpll);
static auto Get(Dpll dpll) {
if (dpll == 0) {
return hwreg::RegisterAddr<DpllEnable>(0x46010); // LCPLL1_CTL
} else if (dpll == 1) {
return hwreg::RegisterAddr<DpllEnable>(0x46014); // LCPLL2_CTL
} else if (dpll == 2) {
return hwreg::RegisterAddr<DpllEnable>(0x46040); // WRPLL_CTL1
} else { // dpll == 3
return hwreg::RegisterAddr<DpllEnable>(0x46060); // WRPLL_CTL2
}
}
};
// DPLL_STATUS
class DpllStatus : public hwreg::RegisterBase<DpllStatus, uint32_t> {
public:
hwreg::BitfieldRef<uint32_t> dpll_lock(Dpll dpll) {
int bit = dpll * 8;
return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit);
}
static auto Get() { return hwreg::RegisterAddr<DpllStatus>(0x6c060); }
};
// LCPLL1_CTL
class Lcpll1Control : public hwreg::RegisterBase<Lcpll1Control, uint32_t> {
public:
DEF_BIT(30, pll_lock);
static auto Get() { return hwreg::RegisterAddr<Lcpll1Control>(0x46010); }
};
} // namespace registers
#endif // SRC_GRAPHICS_DISPLAY_DRIVERS_INTEL_I915_REGISTERS_DPLL_H_