// 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/dpll-config.h"

#include <lib/stdcompat/span.h>
#include <zircon/assert.h>

#include <cstdint>
#include <cstdlib>
#include <limits>

namespace i915 {

cpp20::span<const int8_t> DpllSupportedFrequencyDividersKabyLake() {
  // This list merges the odd and even dividers in  the "Pseudocode to Find HDMI
  // and DVI DPLL Programming" section in the display engine PRMs.
  //
  // The register-level reference sugggests that there are valid dividers that
  // are not listed here. For example, any multiple of 4 below 1024 can be
  // achieved using K (P0) = 2, Q (P1) = 1-255, P (P2) = 2.
  //
  // Kaby Lake: IHD-OS-KBL-Vol 12-1.17 pages 135-136
  // Skylake: IHD-OS-SKL-Vol 12-05.16 pages 132-133
  static constexpr int8_t kDividers[] = {3,  4,  5,  6,  7,  8,  9,  10, 12, 14, 15, 16, 18, 20,
                                         21, 24, 28, 30, 32, 36, 40, 42, 44, 48, 52, 54, 56, 60,
                                         64, 66, 68, 70, 72, 76, 78, 80, 84, 88, 90, 92, 96, 98};
  return kDividers;
}

cpp20::span<const int8_t> DpllSupportedFrequencyDividersTigerLake() {
  // Tiger Lake: IHD-OS-TGL-Vol 12-1.22-Rev2.0 pages 181-182

  // TODO(costan): These aren't ordered anymore.
  static constexpr int8_t kDividers[] = {
      2,  4,  6,  8,  10, 12, 14, 16, 18, 20, 24, 28, 30, 32, 36, 40,  42,  44, 48, 50, 52, 54, 56,
      60, 64, 66, 68, 70, 72, 76, 78, 80, 84, 88, 90, 92, 96, 98, 100, 102, 3,  5,  7,  9,  15, 21};

  return kDividers;
}

DpllOscillatorConfig CreateDpllOscillatorConfigKabyLake(int32_t afe_clock_khz) {
  ZX_ASSERT(afe_clock_khz > 0);

  // The implementation conceptually follows the big `For` loop in the
  // "Pseudocode to Find HDMI and DVI DPLL Programming" section in the display
  // engine PRMs.
  //
  // Kaby Lake: IHD-OS-KBL-Vol 12-1.17 pages 135-136
  // Skylake: IHD-OS-SKL-Vol 12-05.16 pages 132-133

  static constexpr int32_t kCenterFrequenciesKhz[] = {8'400'000, 9'000'000, 9'600'000};

  DpllOscillatorConfig result;
  int32_t min_deviation = std::numeric_limits<int32_t>::max();

  const cpp20::span<const int8_t> supported_dividers = DpllSupportedFrequencyDividersKabyLake();

  // The PRM asks that we prefer even frequency dividers so strongly that we'll
  // chose any acceptable DPLL configuration with an even divider over any
  // configuration with an old divider.
  static constexpr bool kWantEvenDivider[] = {true, false};
  for (const bool& want_even_divider : kWantEvenDivider) {
    for (const int32_t& center_frequency_khz : kCenterFrequenciesKhz) {
      // The DCO frequency must be within [-6%, +1%] of the center DCO
      // frequency. We compute the ends of this range below.
      //
      // The DCO frequencies are all in the Mhz range, so the divisions below
      // are exact. `max_frequency_khz` and `min_frequency_khz` are at most
      // 9,696,000.
      const int32_t max_frequency_khz = center_frequency_khz + (center_frequency_khz / 100);
      const int32_t min_frequency_khz = center_frequency_khz - 6 * (center_frequency_khz / 100);

      // The PLL output (AFE clock) frequency is the DCO (Digitally-Controlled
      // Oscillator) frequency divided by the frequency divider. More compactly,
      //     AFE clock frequency = DCO frequency / divider
      //
      // Rearranging terms gives us the following equations we'll use below.
      //     DCO frequency = AFE clock frequency * divider
      //     divider = DCO frequency / AFE clock frequency
      //
      // The target AFE clock frequency is fixed (given to this function), and
      // there is an acceptable range of the DCO frequencies. This leads to an
      // acceptable range of dividers, computed below.
      //
      // All supported dividers are integers. In order to stay within the range,
      // we must round down the maximum divider and round up the minimum
      // divider.
      const int32_t max_divider = max_frequency_khz / afe_clock_khz;
      const int32_t min_divider = (min_frequency_khz + afe_clock_khz - 1) / afe_clock_khz;
      if (max_divider < supported_dividers.front() || min_divider > supported_dividers.back()) {
        continue;
      }

      // Iterate over all supported frequency divider values, and save the value
      // that gives the lowest deviation from the DCO center frequency. The
      // number of supported dividers is small enough that binary search
      // wouldn't yield a meaningful improvement.
      for (const int8_t& candidate_divider : supported_dividers) {
        if (candidate_divider > max_divider) {
          break;
        }
        if (candidate_divider < min_divider) {
          continue;
        }
        const bool is_divider_even = (candidate_divider % 2) == 0;
        if (is_divider_even != want_even_divider) {
          continue;
        }

        // The multiplication will not overflow (causing UB) because the result
        // is guaranteed to fall in the range of `min_frequency_khz` and
        // `max_frequency_khz`. This is because of the range checks on
        // `candidate_divider` above.
        const int32_t frequency_khz = static_cast<int32_t>(candidate_divider * afe_clock_khz);
        ZX_DEBUG_ASSERT(frequency_khz >= min_frequency_khz);
        ZX_DEBUG_ASSERT(frequency_khz <= max_frequency_khz);

        // `dco_frequency_khz` is within [-6%, +1%] of `dco_frequency_khz`, so
        // the maximum `absolute_difference` is 6% of the highest DCO center
        // frequency, which is 5,760,000.
        const int32_t absolute_deviation = std::abs(frequency_khz - center_frequency_khz);

        // We follow the pseudocode in spirit, by computing the ratio between
        // the frequency difference and the center frequency. We avoid using
        // floating-point computation by scaling the difference by 1,000,000
        // before the division.
        //
        // The range for `absolute_deviation` dictates that the multiplication
        // below uses 64-bit integers. At the same time, the division result
        // will be at most 6% of 1,000,000, which fits comfortably in a 32-bit
        // integer.
        const int32_t relative_deviation =
            static_cast<int32_t>((int64_t{1'000'000} * absolute_deviation) / center_frequency_khz);
        if (relative_deviation < min_deviation) {
          min_deviation = relative_deviation;
          result = DpllOscillatorConfig{
              .center_frequency_khz = center_frequency_khz,
              .frequency_khz = frequency_khz,
              .frequency_divider = candidate_divider,
          };
        }
      }
    }

    if (result.frequency_divider != 0) {
      break;
    }
  }

  return result;
}

DpllOscillatorConfig CreateDpllOscillatorConfigForHdmiTigerLake(int32_t afe_clock_khz) {
  ZX_ASSERT(afe_clock_khz > 0);

  // The implementation conceptually follows the big `foreach` loop in the
  // the "Pseudo-code for HDMI Mode DPLL Programming" section in the display
  // engine PRMs.
  //
  // Tiger Lake: IHD-OS-TGL-Vol 12-1.22-Rev2.0 pages 181-182

  static constexpr int32_t kMinFrequencyKhz = 7'998'000;
  static constexpr int32_t kMaxFrequencyKhz = 10'000'000;
  static constexpr int32_t kCenterFrequencyKhz = 8'999'000;

  DpllOscillatorConfig result;
  int32_t min_deviation = std::numeric_limits<int32_t>::max();

  const cpp20::span<const int8_t> supported_dividers = DpllSupportedFrequencyDividersTigerLake();

  // The PLL output (AFE clock) frequency is the DCO (Digitally-Controlled
  // Oscillator) frequency divided by the frequency divider. More compactly,
  //     AFE clock frequency = DCO frequency / divider
  //
  // Rearranging terms gives us the following equations we'll use below.
  //     DCO frequency = AFE clock frequency * divider
  //     divider = DCO frequency / AFE clock frequency
  //
  // The target AFE clock frequency is fixed (given to this function), and
  // there is an acceptable range of the DCO frequencies. This leads to an
  // acceptable range of dividers, computed below.
  //
  // All supported dividers are integers. In order to stay within the range,
  // we must round down the maximum divider and round up the minimum
  // divider.
  const int32_t max_divider = kMaxFrequencyKhz / afe_clock_khz;
  const int32_t min_divider = (kMinFrequencyKhz + afe_clock_khz - 1) / afe_clock_khz;

  // Iterate over all supported frequency divider values, and save the value
  // that gives the lowest deviation from the DCO center frequency. The
  // number of supported dividers is small enough that binary search
  // wouldn't yield a meaningful improvement.
  for (const int8_t& candidate_divider : supported_dividers) {
    if (candidate_divider < min_divider || candidate_divider > max_divider) {
      continue;
    }

    // The multiplication will not overflow (causing UB) because the result
    // is guaranteed to fall in the range of `min_frequency_khz` and
    // `max_frequency_khz`. This is because of the range checks on
    // `candidate_divider` above.
    const int32_t frequency_khz = static_cast<int32_t>(candidate_divider * afe_clock_khz);
    ZX_DEBUG_ASSERT(frequency_khz >= kMinFrequencyKhz);
    ZX_DEBUG_ASSERT(frequency_khz <= kMaxFrequencyKhz);

    // `dco_frequency_khz` is within [-12%, +12%] of `dco_frequency_khz`, so
    // the maximum `absolute_difference` is 12% of the highest DCO center
    // frequency, which is 1,152,000.
    const int32_t absolute_deviation = std::abs(frequency_khz - kCenterFrequencyKhz);

    if (absolute_deviation < min_deviation) {
      min_deviation = absolute_deviation;
      result = DpllOscillatorConfig{
          .center_frequency_khz = kCenterFrequencyKhz,
          .frequency_khz = frequency_khz,
          .frequency_divider = candidate_divider,
      };
    }
  }

  return result;
}

DpllOscillatorConfig CreateDpllOscillatorConfigForDisplayPortTigerLake(int32_t afe_clock_khz) {
  ZX_ASSERT(afe_clock_khz > 0);

  DpllOscillatorConfig result = CreateDpllOscillatorConfigForHdmiTigerLake(afe_clock_khz);

  // These are the only cases where the HDMI algorithm deviates from the
  // DisplayPort table.
  if (afe_clock_khz == 1'350'000 || afe_clock_khz == 810'000 || afe_clock_khz == 1'620'000) {
    result.frequency_khz = 8'100'000;
    ZX_DEBUG_ASSERT(result.frequency_khz % afe_clock_khz == 0);
    result.frequency_divider = static_cast<int8_t>(result.frequency_khz / afe_clock_khz);
  }

  return result;
}

DpllFrequencyDividerConfig CreateDpllFrequencyDividerConfigKabyLake(int8_t dco_divider) {
  // The implementation conceptually follows the `getMultiplier()` function in
  // the "Pseudocode to Find HDMI and DVI DPLL Programming" section in the
  // display engine PRMs.
  //
  // Kaby Lake: IHD-OS-KBL-Vol 12-1.17 pages 135-136
  // Skylake: IHD-OS-SKL-Vol 12-05.16 pages 132-133

  if (dco_divider % 2 == 0) {
    const int8_t dco_divider_half = static_cast<int8_t>(dco_divider / 2);

    // The pseudocode has one if whose predicate is a big "or" clause comparing
    // the half-divider with all valid P2 (K) divider values. The loop below is
    // equivalent.
    static constexpr int8_t kP2DividerValues[] = {1, 2, 3, 5};
    for (const int8_t& p2_divider : kP2DividerValues) {
      if (dco_divider_half == p2_divider) {
        return {.p0_p_divider = 2, .p1_q_divider = 1, .p2_k_divider = dco_divider_half};
      }
    }

    // The pseudocode has a few if branches checking if the half-divider is
    // evenly divided by any valid P0 (P) divider values. The loop below is
    // equivalent.
    static constexpr int8_t kP0DividerValues[] = {2, 3, 7};
    for (const int8_t& p0_divider : kP0DividerValues) {
      if ((dco_divider_half % p0_divider) == 0) {
        return {.p0_p_divider = p0_divider,
                .p1_q_divider = static_cast<int8_t>(dco_divider_half / p0_divider),
                .p2_k_divider = 2};
      }
    }
    ZX_ASSERT_MSG(false, "Unhandled divider %d", dco_divider);
  }

  if (dco_divider == 3 || dco_divider == 9) {
    return {
        .p0_p_divider = 3, .p1_q_divider = 1, .p2_k_divider = static_cast<int8_t>(dco_divider / 3)};
  }
  // The pseudocode uses the P0 (P) divider for 5 and 7. That is incorrect,
  // because the P0 divider can only do 1/2/3/7.
  //
  // Taking a step back, there is a single solution that meets all the (P, Q, K)
  // constraints for all odd dividers that include 5 or 7 in their prime factor
  // decomposition. Q must be 1 because we can't set K to 2. So the 5 / 7 prime
  // factor must be set in P / K.
  if (dco_divider == 5 || dco_divider == 15 || dco_divider == 35) {
    return {
        .p0_p_divider = static_cast<int8_t>(dco_divider / 5), .p1_q_divider = 1, .p2_k_divider = 5};
  }
  if (dco_divider == 7 || dco_divider == 21) {
    return {
        .p0_p_divider = 7, .p1_q_divider = 1, .p2_k_divider = static_cast<int8_t>(dco_divider / 7)};
  }
  ZX_ASSERT_MSG(false, "Unhandled divider %d", dco_divider);
}

DpllFrequencyDividerConfig CreateDpllFrequencyDividerConfigTigerLake(int8_t dco_divider) {
  // The implementation conceptually follows the "Good divider found" block in
  // the "Pseudo-code for HDMI Mode DPLL Programming" section in the display
  // engine PRMs.
  //
  // Tiger Lake: IHD-OS-TGL-Vol 12-1.22-Rev2.0 pages 181-182

  if (dco_divider % 2 == 0) {
    const int8_t dco_divider_half = static_cast<int8_t>(dco_divider / 2);

    if (dco_divider == 2) {
      return {.p0_p_divider = 2, .p1_q_divider = 1, .p2_k_divider = 1};
    }

    // The pseudocode has a few if branches checking for valid P0 (P) divider
    // values. The comparisons check the divider directly against P0 values, or
    // against 2x the P0 (P) divider values. The difference only matters for
    // P0 = 2.
    //
    // The loop below is equivalent. It uses Kaby Lake / Skylake PRM approach of
    // checking the half-divider against P0 (P) values directly, which is
    // clearer.
    static constexpr int8_t kP0DividerValues[] = {2, 3, 5, 7};
    for (const int8_t& p0_divider : kP0DividerValues) {
      if ((dco_divider_half % p0_divider) == 0) {
        return {.p0_p_divider = p0_divider,
                .p1_q_divider = static_cast<int8_t>(dco_divider_half / p0_divider),
                .p2_k_divider = 2};
      }
    }

    ZX_ASSERT_MSG(false, "Unhandled divider %d", dco_divider);
  }

  if (dco_divider == 3 || dco_divider == 5 || dco_divider == 7) {
    return {.p0_p_divider = dco_divider, .p1_q_divider = 1, .p2_k_divider = 1};
  }
  ZX_ASSERT_MSG(dco_divider % 3 == 0, "Unhandled divider %d", dco_divider);
  return {
      .p0_p_divider = static_cast<int8_t>(dco_divider / 3), .p1_q_divider = 1, .p2_k_divider = 3};
}

}  // namespace i915
