blob: 92e01b1a30099785c5ff4dea4702844f4e937be3 [file] [log] [blame]
// Copyright 2022 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.
#include "src/graphics/display/drivers/intel-i915/ddi-physical-layer-manager.h"
#include <lib/ddk/debug.h>
#include <zircon/assert.h>
#include "src/graphics/display/drivers/intel-i915/ddi-physical-layer.h"
#include "src/graphics/display/drivers/intel-i915/hardware-common.h"
#include "src/graphics/display/drivers/intel-i915/intel-i915.h"
namespace i915 {
DdiReference::DdiReference() = default;
DdiReference::DdiReference(DdiPhysicalLayer* phy) : phy_(phy) {
ZX_DEBUG_ASSERT(phy_);
phy_->AddRef();
}
DdiReference::~DdiReference() {
if (phy_) {
phy_->Release();
}
}
DdiReference::DdiReference(DdiReference&& rhs) noexcept {
phy_ = rhs.phy_;
rhs.phy_ = nullptr;
}
DdiReference& DdiReference::operator=(DdiReference&& rhs) noexcept {
if (phy_) {
phy_->Release();
}
phy_ = rhs.phy_;
rhs.phy_ = nullptr;
return *this;
}
DdiPhysicalLayer::PhysicalLayerInfo DdiReference::GetPhysicalLayerInfo() const {
ZX_DEBUG_ASSERT(phy_);
return phy_->GetPhysicalLayerInfo();
}
DdiReference DdiManager::GetDdiReference(DdiId ddi_id) {
auto ddi_state_iter = ddi_map_.find(ddi_id);
ZX_DEBUG_ASSERT_MSG(ddi_state_iter != ddi_map_.end(),
"DdiManager: DDI %d is not available. Cannot request reference for DDI.",
ddi_id);
DdiPhysicalLayer* phy = ddi_state_iter->second.get();
// If there's no existing reference to the PHY, we'll need to enable the PHY
// first.
ZX_DEBUG_ASSERT(phy);
if (phy->Enable()) {
return DdiReference(phy);
}
return DdiReference();
}
DdiManagerSkylake::DdiManagerSkylake() {
for (const DdiId ddi_id : DdiIds<registers::Platform::kSkylake>()) {
ddi_map()[ddi_id] = std::make_unique<DdiSkylake>(ddi_id);
}
}
DdiManagerTigerLake::DdiManagerTigerLake(Controller* controller)
: DdiManagerTigerLake(controller->power(), controller->mmio_space(),
controller->igd_opregion()) {}
DdiManagerTigerLake::DdiManagerTigerLake(Power* power, fdf::MmioBuffer* mmio_space,
const IgdOpRegion& igd_opregion) {
for (const DdiId ddi_id : DdiIds<registers::Platform::kTigerLake>()) {
if (!igd_opregion.HasDdi(ddi_id)) {
zxlogf(TRACE, "DDI %d not initialized because it's omitted in VBT.", ddi_id);
continue;
}
if (ddi_id >= DdiId::DDI_A && ddi_id <= DdiId::DDI_C) {
auto ddi = std::make_unique<ComboDdiTigerLake>(ddi_id, mmio_space);
// TODO(https://fxbug.dev/42066037): Create an initialization API in the base class.
if (!ddi->Initialize()) {
zxlogf(ERROR, "Failed to initialize DDI %d. It will remain unused.", ddi_id);
continue;
}
auto [it, emplace_success] = ddi_map().try_emplace(ddi_id, std::move(ddi));
ZX_DEBUG_ASSERT_MSG(emplace_success, "DDI %d already in map", ddi_id);
continue;
}
if (ddi_id >= DdiId::DDI_TC_1 && ddi_id <= DdiId::DDI_TC_6) {
// Type-C DDI
const bool is_static_port = !igd_opregion.IsTypeC(ddi_id);
ddi_map()[ddi_id] =
std::make_unique<TypeCDdiTigerLake>(ddi_id, power, mmio_space, is_static_port);
continue;
}
ZX_DEBUG_ASSERT_MSG(false, "Unhandled DDI list entry - DDI %d", ddi_id);
}
}
} // namespace i915