| // 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 <lib/fpromise/result.h> |
| #include <lib/fpromise/single_threaded_executor.h> |
| #include <lib/inspect/cpp/inspector.h> |
| #include <lib/inspect/cpp/reader.h> |
| |
| #include <gtest/gtest.h> |
| |
| #include "src/graphics/display/drivers/intel-i915/dp-display.h" |
| #include "src/graphics/display/drivers/intel-i915/fake-dpcd-channel.h" |
| |
| namespace i915 { |
| |
| namespace { |
| |
| using testing::FakeDpcdChannel; |
| using testing::kDefaultLaneCount; |
| using testing::kMaxLinkRateTableEntries; |
| |
| TEST(DpCapabilitiesTest, NoSupportedLinkRates) { |
| FakeDpcdChannel fake_dpcd; |
| |
| const fpromise::result<DpCapabilities> cap = DpCapabilities::Read(&fake_dpcd); |
| EXPECT_TRUE(cap.is_error()); |
| } |
| |
| // Tests that invalid lane counts are rejected. |
| TEST(DpCapabilitiesTest, InvalidMaxLaneCount) { |
| FakeDpcdChannel fake_dpcd; |
| fake_dpcd.SetMaxLinkRate(dpcd::LinkBw::k1620Mbps); |
| |
| fake_dpcd.SetMaxLaneCount(0); |
| EXPECT_TRUE(DpCapabilities::Read(&fake_dpcd).is_error()); |
| |
| fake_dpcd.SetMaxLaneCount(3); |
| EXPECT_TRUE(DpCapabilities::Read(&fake_dpcd).is_error()); |
| |
| fake_dpcd.SetMaxLaneCount(5); |
| EXPECT_TRUE(DpCapabilities::Read(&fake_dpcd).is_error()); |
| } |
| |
| // Tests that the basic set of getters work for non-EDP. |
| TEST(DpCapabilitiesTest, BasicFields) { |
| FakeDpcdChannel fake_dpcd; |
| |
| fake_dpcd.SetDpcdRevision(dpcd::Revision::k1_4); |
| fake_dpcd.SetMaxLaneCount(kDefaultLaneCount); |
| fake_dpcd.SetMaxLinkRate(dpcd::LinkBw::k1620Mbps); |
| fake_dpcd.SetSinkCount(1); |
| |
| const fpromise::result<DpCapabilities> cap = DpCapabilities::Read(&fake_dpcd); |
| ASSERT_TRUE(cap.is_ok()); |
| EXPECT_EQ(dpcd::Revision::k1_4, cap.value().dpcd_revision()); |
| EXPECT_EQ(kDefaultLaneCount, cap.value().max_lane_count()); |
| EXPECT_EQ(1u, cap.value().sink_count()); |
| EXPECT_EQ(1u, cap.value().supported_link_rates_mbps().size()); |
| |
| // eDP capabilities should be unavailable. |
| EXPECT_EQ(std::nullopt, cap.value().edp_revision()); |
| EXPECT_FALSE(cap.value().backlight_aux_power()); |
| EXPECT_FALSE(cap.value().backlight_aux_brightness()); |
| } |
| |
| // Tests that eDP registers are processed when supported. |
| TEST(DpCapabilitiesTest, EdpRegisters) { |
| FakeDpcdChannel fake_dpcd; |
| fake_dpcd.SetDefaults(); |
| fake_dpcd.SetEdpCapable(dpcd::EdpRevision::k1_2); |
| |
| const fpromise::result<DpCapabilities> cap = DpCapabilities::Read(&fake_dpcd); |
| ASSERT_TRUE(cap.is_ok()); |
| EXPECT_EQ(std::optional{dpcd::EdpRevision::k1_2}, cap.value().edp_revision()); |
| EXPECT_FALSE(cap.value().backlight_aux_power()); |
| EXPECT_FALSE(cap.value().backlight_aux_brightness()); |
| } |
| |
| TEST(DpCapabilitiesTest, EdpBacklight) { |
| FakeDpcdChannel fake_dpcd; |
| fake_dpcd.SetDefaults(); |
| fake_dpcd.SetEdpCapable(dpcd::EdpRevision::k1_2); |
| |
| dpcd::EdpGeneralCap1 gc; |
| gc.set_tcon_backlight_adjustment_cap(1); |
| gc.set_backlight_aux_enable_cap(1); |
| fake_dpcd.registers[dpcd::DPCD_EDP_GENERAL_CAP1] = gc.reg_value(); |
| |
| dpcd::EdpBacklightCap bc; |
| bc.set_brightness_aux_set_cap(1); |
| fake_dpcd.registers[dpcd::DPCD_EDP_BACKLIGHT_CAP] = bc.reg_value(); |
| |
| const fpromise::result<DpCapabilities> cap = DpCapabilities::Read(&fake_dpcd); |
| ASSERT_TRUE(cap.is_ok()); |
| EXPECT_TRUE(cap.value().backlight_aux_power()); |
| EXPECT_TRUE(cap.value().backlight_aux_brightness()); |
| } |
| |
| // Tests that the list of supported link rates is populated correctly using the "Max Link Rate" |
| // method. |
| TEST(DpCapabilitiesTest, MaxLinkRate1620NoEdp) { |
| FakeDpcdChannel fake_dpcd; |
| fake_dpcd.SetDefaults(); |
| fake_dpcd.SetMaxLinkRate(dpcd::LinkBw::k1620Mbps); |
| |
| const fpromise::result<DpCapabilities> cap = DpCapabilities::Read(&fake_dpcd); |
| ASSERT_TRUE(cap.is_ok()); |
| EXPECT_FALSE(cap.value().use_link_rate_table()); |
| ASSERT_EQ(1u, cap.value().supported_link_rates_mbps().size()); |
| EXPECT_EQ(1620u, cap.value().supported_link_rates_mbps()[0]); |
| } |
| |
| // Tests that the list of supported link rates is populated correctly using the "Max Link Rate" |
| // method. |
| TEST(DpCapabilitiesTest, MaxLinkRate2700NoEdp) { |
| FakeDpcdChannel fake_dpcd; |
| fake_dpcd.SetDefaults(); |
| fake_dpcd.SetMaxLinkRate(dpcd::LinkBw::k2700Mbps); |
| |
| const fpromise::result<DpCapabilities> cap = DpCapabilities::Read(&fake_dpcd); |
| ASSERT_TRUE(cap.is_ok()); |
| EXPECT_FALSE(cap.value().use_link_rate_table()); |
| ASSERT_EQ(2u, cap.value().supported_link_rates_mbps().size()); |
| EXPECT_EQ(1620u, cap.value().supported_link_rates_mbps()[0]); |
| EXPECT_EQ(2700u, cap.value().supported_link_rates_mbps()[1]); |
| } |
| |
| // Tests that the list of supported link rates is populated correctly using the "Max Link Rate" |
| // method. |
| TEST(DpCapabilitiesTest, MaxLinkRate5400NoEdp) { |
| FakeDpcdChannel fake_dpcd; |
| fake_dpcd.SetDefaults(); |
| fake_dpcd.SetMaxLinkRate(dpcd::LinkBw::k5400Mbps); |
| |
| const fpromise::result<DpCapabilities> cap = DpCapabilities::Read(&fake_dpcd); |
| ASSERT_TRUE(cap.is_ok()); |
| EXPECT_FALSE(cap.value().use_link_rate_table()); |
| ASSERT_EQ(3u, cap.value().supported_link_rates_mbps().size()); |
| EXPECT_EQ(1620u, cap.value().supported_link_rates_mbps()[0]); |
| EXPECT_EQ(2700u, cap.value().supported_link_rates_mbps()[1]); |
| EXPECT_EQ(5400u, cap.value().supported_link_rates_mbps()[2]); |
| } |
| |
| // Tests that the list of supported link rates is populated correctly using the "Max Link Rate" |
| // method. |
| TEST(DpCapabilitiesTest, MaxLinkRate8100NoEdp) { |
| FakeDpcdChannel fake_dpcd; |
| fake_dpcd.SetDefaults(); |
| fake_dpcd.SetMaxLinkRate(dpcd::LinkBw::k8100Mbps); |
| |
| const fpromise::result<DpCapabilities> cap = DpCapabilities::Read(&fake_dpcd); |
| ASSERT_TRUE(cap.is_ok()); |
| EXPECT_FALSE(cap.value().use_link_rate_table()); |
| ASSERT_EQ(4u, cap.value().supported_link_rates_mbps().size()); |
| EXPECT_EQ(1620u, cap.value().supported_link_rates_mbps()[0]); |
| EXPECT_EQ(2700u, cap.value().supported_link_rates_mbps()[1]); |
| EXPECT_EQ(5400u, cap.value().supported_link_rates_mbps()[2]); |
| EXPECT_EQ(8100u, cap.value().supported_link_rates_mbps()[3]); |
| } |
| |
| // Tests that link rate discovery falls back to MAX_LINK_RATE if eDP v1.4 is supported but the |
| // link rate table is empty. |
| TEST(DpCapabilitiesTest, FallbackToMaxLinkRateWhenLinkRateTableIsEmpty) { |
| FakeDpcdChannel fake_dpcd; |
| fake_dpcd.SetDefaults(); |
| fake_dpcd.SetEdpCapable(dpcd::EdpRevision::k1_4); |
| fake_dpcd.SetMaxLinkRate(dpcd::LinkBw::k1620Mbps); |
| |
| const fpromise::result<DpCapabilities> cap = DpCapabilities::Read(&fake_dpcd); |
| ASSERT_TRUE(cap.is_ok()); |
| EXPECT_FALSE(cap.value().use_link_rate_table()); |
| EXPECT_FALSE(cap.value().supported_link_rates_mbps().empty()); |
| } |
| |
| // Tests that the list of supported link rates is populated correctly when using the "Link Rate |
| // Table" method. |
| TEST(DpCapabilitiesTest, LinkRateTableOneEntry) { |
| FakeDpcdChannel fake_dpcd; |
| fake_dpcd.SetDefaults(); |
| fake_dpcd.SetEdpCapable(dpcd::EdpRevision::k1_4); |
| fake_dpcd.SetMaxLinkRate(0); // Not supported |
| |
| fake_dpcd.PopulateLinkRateTable({100}); // 100 * 200kHz ==> 20MHz |
| |
| const fpromise::result<DpCapabilities> cap = DpCapabilities::Read(&fake_dpcd); |
| ASSERT_TRUE(cap.is_ok()); |
| EXPECT_TRUE(cap.value().use_link_rate_table()); |
| EXPECT_EQ(1u, cap.value().supported_link_rates_mbps().size()); |
| EXPECT_EQ(20u, cap.value().supported_link_rates_mbps()[0]); |
| } |
| |
| // Tests that the list of supported link rates is populated correctly when using the "Link Rate |
| // Table" method. |
| TEST(DpCapabilitiesTest, LinkRateTableSomeEntries) { |
| FakeDpcdChannel fake_dpcd; |
| fake_dpcd.SetDefaults(); |
| fake_dpcd.SetEdpCapable(dpcd::EdpRevision::k1_4); |
| fake_dpcd.SetMaxLinkRate(0); // Not supported |
| |
| // 100 * 200kHz ==> 20MHz |
| // 200 * 200kHz ==> 40MHz |
| // 300 * 200kHz ==> 60MHz |
| fake_dpcd.PopulateLinkRateTable({100, 200, 300}); |
| |
| const fpromise::result<DpCapabilities> cap = DpCapabilities::Read(&fake_dpcd); |
| ASSERT_TRUE(cap.is_ok()); |
| EXPECT_TRUE(cap.value().use_link_rate_table()); |
| EXPECT_EQ(3u, cap.value().supported_link_rates_mbps().size()); |
| EXPECT_EQ(std::vector<uint32_t>({20, 40, 60}), cap.value().supported_link_rates_mbps()); |
| } |
| |
| // Tests that the list of supported link rates is populated correctly when using the "Link Rate |
| // Table" method. |
| TEST(DpCapabilitiesTest, LinkRateTableMaxEntries) { |
| FakeDpcdChannel fake_dpcd; |
| fake_dpcd.SetDefaults(); |
| fake_dpcd.SetEdpCapable(dpcd::EdpRevision::k1_4); |
| fake_dpcd.SetMaxLinkRate(0); // Not supported |
| |
| // Link rate table entries are stored in units of 200kHz (or kbps). The DpCapabilities data |
| // structure stores them in units of Mbps. 1 Mbps = 5 * 200kbps. |
| constexpr uint16_t kConversionFactor = 5; |
| std::vector<uint16_t> input; |
| std::vector<uint32_t> output; |
| for (unsigned i = 1; i <= kMaxLinkRateTableEntries; i++) { |
| input.push_back(static_cast<uint16_t>(kConversionFactor * i)); |
| output.push_back(i); |
| } |
| fake_dpcd.PopulateLinkRateTable(std::move(input)); |
| |
| const fpromise::result<DpCapabilities> cap = DpCapabilities::Read(&fake_dpcd); |
| ASSERT_TRUE(cap.is_ok()); |
| EXPECT_TRUE(cap.value().use_link_rate_table()); |
| EXPECT_EQ(kMaxLinkRateTableEntries, cap.value().supported_link_rates_mbps().size()); |
| EXPECT_EQ(output, cap.value().supported_link_rates_mbps()); |
| } |
| |
| // Tests that the list of supported link rates is populated based on the "Link Rate Table" method |
| // when both the table and the MAX_LINK_RATE register hold valid values (which is optional but |
| // allowed by the eDP specification). |
| TEST(DpCapabilitiesTest, LinkRateTableUsedWhenMaxLinkRateIsAlsoPresent) { |
| FakeDpcdChannel fake_dpcd; |
| fake_dpcd.SetDefaults(); |
| fake_dpcd.SetEdpCapable(dpcd::EdpRevision::k1_4); |
| fake_dpcd.SetMaxLinkRate(dpcd::LinkBw::k2700Mbps); |
| |
| // Link rate table entries are stored in units of 200kHz (or kbps). The DpCapabilities data |
| // structure stores them in units of Mbps. 1 Mbps = 5 * 200kbps. |
| constexpr uint16_t kConversionFactor = 5; |
| constexpr uint32_t kExpectedLinkRate = 5400; |
| fake_dpcd.PopulateLinkRateTable({kExpectedLinkRate * kConversionFactor}); |
| |
| const fpromise::result<DpCapabilities> cap = DpCapabilities::Read(&fake_dpcd); |
| ASSERT_TRUE(cap.is_ok()); |
| EXPECT_TRUE(cap.value().use_link_rate_table()); |
| EXPECT_EQ(1u, cap.value().supported_link_rates_mbps().size()); |
| EXPECT_EQ(kExpectedLinkRate, cap.value().supported_link_rates_mbps()[0]); |
| } |
| |
| // Tests that the DP capabilities can be inspected and the DP capability values |
| // are correctly propagated to the inspect node. |
| TEST(DpCapabilitiesTest, Inspect) { |
| FakeDpcdChannel fake_dpcd; |
| fake_dpcd.SetDefaults(); |
| fake_dpcd.SetMaxLinkRate(dpcd::LinkBw::k2700Mbps); |
| |
| const fpromise::result<DpCapabilities> cap = DpCapabilities::Read(&fake_dpcd); |
| ASSERT_TRUE(cap.is_ok()); |
| |
| inspect::Inspector inspector; |
| cap.value().PublishToInspect(&inspector.GetRoot()); |
| |
| fpromise::single_threaded_executor executor; |
| executor.schedule_task( |
| inspect::ReadFromInspector(inspector).then([&](fpromise::result<inspect::Hierarchy>& result) { |
| ASSERT_TRUE(result.is_ok()); |
| auto& node = result.value().node(); |
| |
| auto dpcd_revision = node.get_property<inspect::StringPropertyValue>("dpcd_revision"); |
| ASSERT_TRUE(dpcd_revision); |
| EXPECT_STREQ("DPCD r1.4", dpcd_revision->value().c_str()); |
| |
| auto edp_revision = node.get_property<inspect::StringPropertyValue>("edp_revision"); |
| ASSERT_TRUE(edp_revision); |
| EXPECT_STREQ("not supported", edp_revision->value().c_str()); |
| |
| auto sink_count = node.get_property<inspect::UintPropertyValue>("sink_count"); |
| ASSERT_TRUE(sink_count); |
| EXPECT_EQ(testing::kDefaultSinkCount, sink_count->value()); |
| |
| auto max_lane_count = node.get_property<inspect::UintPropertyValue>("max_lane_count"); |
| ASSERT_TRUE(max_lane_count); |
| EXPECT_EQ(testing::kDefaultLaneCount, max_lane_count->value()); |
| |
| auto supported_link_rates_list = |
| node.get_property<inspect::UintArrayValue>("supported_link_rates_mbps_per_lane"); |
| ASSERT_TRUE(supported_link_rates_list); |
| ASSERT_EQ(2u, supported_link_rates_list->value().size()); |
| EXPECT_EQ(1620u, supported_link_rates_list->value()[0]); |
| EXPECT_EQ(2700u, supported_link_rates_list->value()[1]); |
| })); |
| executor.run(); |
| } |
| |
| } // namespace |
| |
| } // namespace i915 |