blob: 3a1edd65de941d738ed81720fb7b1a5dd81e2b97 [file] [log] [blame]
// Copyright 2023 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/amlogic-display/clock-regs.h"
#include <zircon/assert.h>
#include "src/graphics/display/drivers/amlogic-display/fixed-point-util.h"
namespace amlogic_display {
int HdmiClockTreeControl::PatternSize() const {
if (bypass_pattern_generators()) {
return 0;
}
switch (pattern_generator_mode_selection()) {
case HdmiClockTreePatternGeneratorModeSource::kRepeated12BitPattern:
return 12;
case HdmiClockTreePatternGeneratorModeSource::kRepeated14BitPattern:
return 14;
case HdmiClockTreePatternGeneratorModeSource::kRepeated15BitPattern:
return 15;
case HdmiClockTreePatternGeneratorModeSource::kFixed25BitPattern:
return 25;
}
}
uint32_t HdmiClockTreeControl::Pattern() const {
if (bypass_pattern_generators()) {
return 0;
}
switch (pattern_generator_mode_selection()) {
case HdmiClockTreePatternGeneratorModeSource::kRepeated12BitPattern:
case HdmiClockTreePatternGeneratorModeSource::kRepeated14BitPattern:
case HdmiClockTreePatternGeneratorModeSource::kRepeated15BitPattern: {
uint32_t mask = (1 << PatternSize()) - 1;
return pattern_generator_state() & mask;
}
case HdmiClockTreePatternGeneratorModeSource::kFixed25BitPattern:
return 0b111'000'111'000'111'000'1111'000;
}
}
HdmiClockTreeControl& HdmiClockTreeControl::SetFrequencyDividerRatio(uint32_t divider_ratio_u28_4) {
ZX_DEBUG_ASSERT(std::find(kSupportedFrequencyDividerRatios.begin(),
kSupportedFrequencyDividerRatios.end(),
divider_ratio_u28_4) != kSupportedFrequencyDividerRatios.end());
// All register field values are from Amlogic-provided code.
switch (divider_ratio_u28_4) {
case ToU28_4(1.0):
return set_bypass_pattern_generators(true)
.set_pattern_generator_mode_selection(
HdmiClockTreePatternGeneratorModeSource::kRepeated12BitPattern)
.set_pattern_generator_state(0b111'111'111'111'111);
case ToU28_4(2.0):
return set_bypass_pattern_generators(false)
.set_pattern_generator_mode_selection(
HdmiClockTreePatternGeneratorModeSource::kRepeated12BitPattern)
.set_pattern_generator_state(0b10'10'10'10'10'10);
case ToU28_4(2.5):
return set_bypass_pattern_generators(false)
.set_pattern_generator_mode_selection(
HdmiClockTreePatternGeneratorModeSource::kRepeated15BitPattern)
.set_pattern_generator_state(0b10'100'10'100'10'100);
case ToU28_4(3.0):
return set_bypass_pattern_generators(false)
.set_pattern_generator_mode_selection(
HdmiClockTreePatternGeneratorModeSource::kRepeated12BitPattern)
.set_pattern_generator_state(0b110'110'110'110);
case ToU28_4(3.5):
return set_bypass_pattern_generators(false)
.set_pattern_generator_mode_selection(
HdmiClockTreePatternGeneratorModeSource::kRepeated14BitPattern)
.set_pattern_generator_state(0b110'110'1100'1100);
case ToU28_4(3.75):
return set_bypass_pattern_generators(false)
.set_pattern_generator_mode_selection(
HdmiClockTreePatternGeneratorModeSource::kRepeated15BitPattern)
.set_pattern_generator_state(0b1100'1100'1100'110);
case ToU28_4(4.0):
return set_bypass_pattern_generators(false)
.set_pattern_generator_mode_selection(
HdmiClockTreePatternGeneratorModeSource::kRepeated12BitPattern)
.set_pattern_generator_state(0b1100'1100'1100);
case ToU28_4(5.0):
return set_bypass_pattern_generators(false)
.set_pattern_generator_mode_selection(
HdmiClockTreePatternGeneratorModeSource::kRepeated15BitPattern)
.set_pattern_generator_state(0b11100'11100'11100);
case ToU28_4(6.0):
return set_bypass_pattern_generators(false)
.set_pattern_generator_mode_selection(
HdmiClockTreePatternGeneratorModeSource::kRepeated12BitPattern)
.set_pattern_generator_state(0b111000'111000);
case ToU28_4(6.25):
return set_bypass_pattern_generators(false)
.set_pattern_generator_mode_selection(
HdmiClockTreePatternGeneratorModeSource::kFixed25BitPattern)
.set_pattern_generator_state(0);
case ToU28_4(7.0):
return set_bypass_pattern_generators(false)
.set_pattern_generator_mode_selection(
HdmiClockTreePatternGeneratorModeSource::kRepeated14BitPattern)
.set_pattern_generator_state(0b1111000'1111000);
case ToU28_4(7.5):
return set_bypass_pattern_generators(false)
.set_pattern_generator_mode_selection(
HdmiClockTreePatternGeneratorModeSource::kRepeated15BitPattern)
.set_pattern_generator_state(0b1111000'11110000);
case ToU28_4(12.0):
return set_bypass_pattern_generators(false)
.set_pattern_generator_mode_selection(
HdmiClockTreePatternGeneratorModeSource::kRepeated12BitPattern)
.set_pattern_generator_state(0b111111000000);
case ToU28_4(14.0):
return set_bypass_pattern_generators(false)
.set_pattern_generator_mode_selection(
HdmiClockTreePatternGeneratorModeSource::kRepeated14BitPattern)
.set_pattern_generator_state(0b11111110000000);
case ToU28_4(15.0):
return set_bypass_pattern_generators(false)
.set_pattern_generator_mode_selection(
HdmiClockTreePatternGeneratorModeSource::kRepeated15BitPattern)
.set_pattern_generator_state(0b111111110000000);
break;
}
ZX_ASSERT_MSG(false, "Invalid predefined division ratio: 0x%x (%.2f)", divider_ratio_u28_4,
U28_4ToDouble(divider_ratio_u28_4));
}
} // namespace amlogic_display