// 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.

#include <ddk/driver.h>
#include <lib/edid/edid.h>

#include "intel-i915.h"
#include "hdmi-display.h"
#include "macros.h"
#include "pci-ids.h"
#include "registers.h"
#include "registers-ddi.h"
#include "registers-dpll.h"
#include "registers-pipe.h"
#include "registers-transcoder.h"

// I2c functions

namespace {
// Recommended DDI buffer translation programming values

struct ddi_buf_trans_entry {
    uint32_t high_dword;
    uint32_t low_dword;
};

const ddi_buf_trans_entry hdmi_ddi_buf_trans_skl_uhs[11] {
    { 0x000000ac, 0x00000018 },
    { 0x0000009d, 0x00005012 },
    { 0x00000088, 0x00007011 },
    { 0x000000a1, 0x00000018 },
    { 0x00000098, 0x00000018 },
    { 0x00000088, 0x00004013 },
    { 0x000000cd, 0x80006012 },
    { 0x000000df, 0x00000018 },
    { 0x000000cd, 0x80003015 },
    { 0x000000c0, 0x80003015 },
    { 0x000000c0, 0x80000018 },
};

const ddi_buf_trans_entry hdmi_ddi_buf_trans_skl_y[11] {
    { 0x000000a1, 0x00000018 },
    { 0x000000df, 0x00005012 },
    { 0x000000cb, 0x80007011 },
    { 0x000000a4, 0x00000018 },
    { 0x0000009d, 0x00000018 },
    { 0x00000080, 0x00004013 },
    { 0x000000c0, 0x80006012 },
    { 0x0000008a, 0x00000018 },
    { 0x000000c0, 0x80003015 },
    { 0x000000c0, 0x80003015 },
    { 0x000000c0, 0x80000018 },
};

int ddi_to_pin(registers::Ddi ddi) {
    if (ddi == registers::DDI_B) {
        return registers::GMBus0::kDdiBPin;
    } else if (ddi == registers::DDI_C) {
        return registers::GMBus0::kDdiCPin;
    } else if (ddi == registers::DDI_D) {
        return registers::GMBus0::kDdiDPin;
    }
    return -1;
}

void write_gmbus3(hwreg::RegisterIo* mmio_space, uint8_t* buf, uint32_t size, uint32_t idx) {
    int cur_byte = 0;
    uint32_t val = 0;
    while (idx < size && cur_byte < 4) {
        val |= buf[idx++] << (8 * cur_byte++);
    }
    registers::GMBus3::Get().FromValue(val).WriteTo(mmio_space);
}

void read_gmbus3(hwreg::RegisterIo* mmio_space, uint8_t* buf, uint32_t size, uint32_t idx) {
    int cur_byte = 0;
    uint32_t val = registers::GMBus3::Get().ReadFrom(mmio_space).reg_value();
    while (idx < size && cur_byte++ < 4) {
        buf[idx++] = val & 0xff;
        val >>= 8;
    }
}

static constexpr uint8_t kI2cClockUs = 10; // 100 kHz

// For bit banging i2c over the gpio pins
bool i2c_scl(hwreg::RegisterIo* mmio_space, registers::Ddi ddi, bool hi) {
    auto gpio = registers::GpioCtl::Get(ddi).FromValue(0);

    if (!hi) {
        gpio.set_clock_direction_val(1);
        gpio.set_clock_mask(1);
    }
    gpio.set_clock_direction_mask(1);

    gpio.WriteTo(mmio_space);
    gpio.ReadFrom(mmio_space); // Posting read

    // Handle the case where something on the bus is holding the clock
    // low. Timeout after 1ms.
    if (hi) {
        int count = 0;
        do {
            if (count != 0) {
                zx_nanosleep(zx_deadline_after(ZX_USEC(kI2cClockUs)));
            }
            gpio.ReadFrom(mmio_space);
        } while (count++ < 100 && hi != gpio.clock_in());
        if (hi != gpio.clock_in()) {
            return false;
        }
    }
    zx_nanosleep(zx_deadline_after(ZX_USEC(kI2cClockUs / 2)));
    return true;
}

// For bit banging i2c over the gpio pins
void i2c_sda(hwreg::RegisterIo* mmio_space, registers::Ddi ddi, bool hi) {
    auto gpio = registers::GpioCtl::Get(ddi).FromValue(0);

    if (!hi) {
        gpio.set_data_direction_val(1);
        gpio.set_data_mask(1);
    }
    gpio.set_data_direction_mask(1);

    gpio.WriteTo(mmio_space);
    gpio.ReadFrom(mmio_space); // Posting read

    zx_nanosleep(zx_deadline_after(ZX_USEC(kI2cClockUs / 2)));
}

// For bit banging i2c over the gpio pins
bool i2c_send_byte(hwreg::RegisterIo* mmio_space, registers::Ddi ddi, uint8_t byte) {
    // Set the bits from MSB to LSB
    for (int i = 7; i >= 0; i--) {
        i2c_sda(mmio_space, ddi, (byte >> i) & 0x1);

        i2c_scl(mmio_space, ddi, 1);

        // Leave the data line where it is for the rest of the cycle
        zx_nanosleep(zx_deadline_after(ZX_USEC(kI2cClockUs / 2)));

        i2c_scl(mmio_space, ddi, 0);
    }

    // Release the data line and check for an ack
    i2c_sda(mmio_space, ddi, 1);
    i2c_scl(mmio_space, ddi, 1);

    bool ack = !registers::GpioCtl::Get(ddi).ReadFrom(mmio_space).data_in();

    // Sleep for the rest of the cycle
    zx_nanosleep(zx_deadline_after(ZX_USEC(kI2cClockUs / 2)));

    i2c_scl(mmio_space, ddi, 0);

    return ack;
}

} // namespace

namespace i915 {

HdmiDisplay::HdmiDisplay(Controller* controller, uint64_t id, registers::Ddi ddi)
        : DisplayDevice(controller, id, ddi) { }

// Per the GMBUS Controller Programming Interface section of the Intel docs, GMBUS does not
// directly support segment pointer addressing. Instead, the segment pointer needs to be
// set by bit-banging the GPIO pins.
bool HdmiDisplay::SetDdcSegment(uint8_t segment_num) {
    // Reset the clock and data lines
    i2c_scl(mmio_space(), ddi(), 0);
    i2c_sda(mmio_space(), ddi(), 0);

    if (!i2c_scl(mmio_space(), ddi(), 1)) {
        return false;
    }
    i2c_sda(mmio_space(), ddi(), 1);
    // Wait for the rest of the cycle
    zx_nanosleep(zx_deadline_after(ZX_USEC(kI2cClockUs / 2)));

    // Send a start condition
    i2c_sda(mmio_space(), ddi(), 0);
    i2c_scl(mmio_space(), ddi(), 0);

    // Send the segment register index and the segment number
    uint8_t segment_write_command = kDdcSegmentI2cAddress << 1;
    if (!i2c_send_byte(mmio_space(), ddi(), segment_write_command)
            || !i2c_send_byte(mmio_space(), ddi(), segment_num)) {
        return false;
    }

    // Set the data and clock lines high to prepare for the GMBus start
    i2c_sda(mmio_space(), ddi(), 1);
    return i2c_scl(mmio_space(), ddi(), 1);
}

bool HdmiDisplay::DdcRead(uint8_t segment, uint8_t offset, uint8_t* buf, uint8_t len) {
    registers::GMBus0::Get().FromValue(0).WriteTo(mmio_space());

    int retries = 0;
    int i = 0;
    while (i < 3) {
        bool success;
        if (i == 0) {
            success = segment == 0 || SetDdcSegment(segment);
        } else {
            if (i == 1) {
                auto gmbus0 = registers::GMBus0::Get().FromValue(0);
                gmbus0.set_pin_pair_select(ddi_to_pin(ddi()));
                gmbus0.WriteTo(mmio_space());

                success = GMBusWrite(kDdcDataI2cAddress, &offset, 1);
            } else {
                success = GMBusRead(kDdcDataI2cAddress, buf, len);
            }
            if (success) {
                if (!WAIT_ON_MS(registers::GMBus2::Get().ReadFrom(mmio_space()).wait(), 10)) {
                    LOG_TRACE("Transition to wait phase timed out\n");
                    success = false;
                }
            }
        }
        if (!success) {
            if (retries++ > 1) {
                LOG_TRACE("Too many block read failures\n");
                return false;
            }
            LOG_SPEW("Block read failed at step %d\n", i);
            i = 0;
            if (!I2cClearNack()) {
                LOG_TRACE("Failed to clear nack\n");
                return false;
            }
        } else {
            i++;
        }
    }

    return I2cFinish() && i == 3;
}

bool HdmiDisplay::GMBusWrite(uint8_t addr, uint8_t* buf, uint8_t size) {
    unsigned idx = 0;
    write_gmbus3(mmio_space(), buf, size, idx);
    idx += 4;

    auto gmbus1 = registers::GMBus1::Get().FromValue(0);
    gmbus1.set_sw_ready(1);
    gmbus1.set_bus_cycle_wait(1);
    gmbus1.set_total_byte_count(size);
    gmbus1.set_slave_register_addr(addr);
    gmbus1.WriteTo(mmio_space());

    while (idx < size) {
        if (!I2cWaitForHwReady()) {
            return false;
        }

        write_gmbus3(mmio_space(), buf, size, idx);
        idx += 4;
    }
    // One more wait to ensure we're ready when we leave the function
    return I2cWaitForHwReady();
}

bool HdmiDisplay::GMBusRead(uint8_t addr, uint8_t* buf, uint8_t size) {
    auto gmbus1 = registers::GMBus1::Get().FromValue(0);
    gmbus1.set_sw_ready(1);
    gmbus1.set_bus_cycle_wait(1);
    gmbus1.set_total_byte_count(size);
    gmbus1.set_slave_register_addr(addr);
    gmbus1.set_read_op(1);
    gmbus1.WriteTo(mmio_space());

    unsigned idx = 0;
    while (idx < size) {
        if (!I2cWaitForHwReady()) {
            return false;
        }

        read_gmbus3(mmio_space(), buf, size, idx);
        idx += 4;
    }

    return true;
}

bool HdmiDisplay::I2cFinish() {
    auto gmbus1 = registers::GMBus1::Get().FromValue(0);
    gmbus1.set_bus_cycle_stop(1);
    gmbus1.set_sw_ready(1);
    gmbus1.WriteTo(mmio_space());

    bool idle = WAIT_ON_MS(!registers::GMBus2::Get().ReadFrom(mmio_space()).active(), 100);

    auto gmbus0 = registers::GMBus0::Get().FromValue(0);
    gmbus0.set_pin_pair_select(0);
    gmbus0.WriteTo(mmio_space());

    if (!idle) {
        LOG_TRACE("hdmi: GMBus i2c failed to go idle\n");
    }
    return idle;
}

bool HdmiDisplay::I2cWaitForHwReady() {
    auto gmbus2 = registers::GMBus2::Get().FromValue(0);
    if (!WAIT_ON_MS({ gmbus2.ReadFrom(mmio_space()); gmbus2.nack() || gmbus2.hw_ready(); }, 50)) {
        LOG_TRACE("hdmi: GMBus i2c wait for hwready timeout\n");
        return false;
    }
    if (gmbus2.nack()) {
        LOG_TRACE("hdmi: GMBus i2c got nack\n");
        return false;
    }
    return true;
}

bool HdmiDisplay::I2cClearNack() {
    I2cFinish();

    if (!WAIT_ON_MS(!registers::GMBus2::Get().ReadFrom(mmio_space()).active(), 10)) {
        LOG_TRACE("hdmi: GMBus i2c failed to clear active nack\n");
        return false;
    }

    // Set/clear sw clear int to reset the bus
    auto gmbus1 = registers::GMBus1::Get().FromValue(0);
    gmbus1.set_sw_clear_int(1);
    gmbus1.WriteTo(mmio_space());
    gmbus1.set_sw_clear_int(0);
    gmbus1.WriteTo(mmio_space());

    // Reset GMBus0
    auto gmbus0 = registers::GMBus0::Get().FromValue(0);
    gmbus0.WriteTo(mmio_space());

    return true;
}

} // namespace i915

// Modesetting functions

namespace {

// See the section on HDMI/DVI programming in intel-gfx-prm-osrc-skl-vol12-display.pdf
// for documentation on this algorithm.
static bool calculate_params(uint32_t symbol_clock_khz,
                             uint64_t* dco_freq_khz, uint32_t* dco_central_freq_khz,
                             uint8_t* p0, uint8_t* p1, uint8_t* p2) {
    uint8_t even_candidates[36] = {
        4, 6, 8, 10, 12, 14, 16, 18, 20, 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
    };
    uint8_t odd_candidates[7] = { 3, 5, 7, 9, 15, 21, 35 };
    uint32_t candidate_freqs[3] = { 8400000, 9000000, 9600000 };
    uint32_t chosen_central_freq = 0;
    uint8_t chosen_divisor = 0;
    uint64_t afe_clock = symbol_clock_khz * 5;
    uint32_t best_deviation = 60; // Deviation in .1% intervals

    for (int parity = 0; parity < 2; parity++) {
        uint8_t* candidates;
        uint8_t num_candidates;
        if (parity) {
            candidates = odd_candidates;
            num_candidates = sizeof(odd_candidates) / sizeof(*odd_candidates);
        } else {
            candidates = even_candidates;
            num_candidates = sizeof(even_candidates) / sizeof(*even_candidates);
        }

        for (unsigned i = 0; i < sizeof(candidate_freqs) / sizeof(*candidate_freqs); i++) {
            uint32_t candidate_freq = candidate_freqs[i];
            for (unsigned j = 0; j < num_candidates; j++) {
                uint8_t candidate_divisor = candidates[j];
                uint64_t dco_freq = candidate_divisor * afe_clock;
                if (dco_freq > candidate_freq) {
                    uint32_t deviation = static_cast<uint32_t>(
                            1000 * (dco_freq - candidate_freq) / candidate_freq);
                    // positive deviation must be < 1%
                    if (deviation < 10 && deviation < best_deviation) {
                        best_deviation = deviation;
                        chosen_central_freq = candidate_freq;
                        chosen_divisor = candidate_divisor;
                    }
                } else {
                    uint32_t deviation = static_cast<uint32_t>(
                            1000 * (candidate_freq - dco_freq) / candidate_freq);
                    if (deviation < best_deviation) {
                        best_deviation = deviation;
                        chosen_central_freq = candidate_freq;
                        chosen_divisor = candidate_divisor;
                    }
                }
            }
        }
        if (chosen_divisor) {
            break;
        }
    }
    if (!chosen_divisor) {
        return false;
    }
    *p0 = *p1 = *p2 = 1;
    if (chosen_divisor % 2 == 0) {
        uint8_t chosen_divisor1 = chosen_divisor / 2;
        if (chosen_divisor1 == 1 || chosen_divisor1 == 2
                || chosen_divisor1 == 3 || chosen_divisor1 == 5) {
            *p0 = 2;
            *p2 = chosen_divisor1;
        } else if (chosen_divisor1 % 2 == 0) {
            *p0 = 2;
            *p1 = chosen_divisor1 / 2;
            *p2 = 2;
        } else if (chosen_divisor1 % 3 == 0) {
            *p0 = 3;
            *p1 = chosen_divisor1 / 3;
            *p2 = 2;
        } else if (chosen_divisor1 % 7 == 0) {
            *p0 = 7;
            *p1 = chosen_divisor1 / 7;
            *p2 = 2;
        }
    } else if (chosen_divisor == 3 || chosen_divisor == 9) {
        *p0 = 3;
        *p2 = chosen_divisor / 3;
    } else if (chosen_divisor == 5 || chosen_divisor == 7) {
        *p0 = chosen_divisor;
    } else if (chosen_divisor == 15) {
        *p0 = 3;
        *p2 = 5;
    } else if (chosen_divisor == 21) {
        *p0 = 7;
        *p2 = 3;
    } else if (chosen_divisor == 35) {
        *p0 = 7;
        *p2 = 5;
    }
    *dco_freq_khz = chosen_divisor * afe_clock;
    *dco_central_freq_khz = chosen_central_freq;
    return true;
}

} // namespace

namespace i915 {

bool HdmiDisplay::QueryDevice(edid::Edid* edid) {
    // HDMI isn't supported on these DDIs
    if (ddi_to_pin(ddi()) == -1) {
        return false;
    }

    // Reset the GMBus registers and disable GMBus interrupts
    registers::GMBus0::Get().FromValue(0).WriteTo(mmio_space());
    registers::GMBus4::Get().FromValue(0).WriteTo(mmio_space());

    const char* edid_err;
    if (!edid->Init(this, &edid_err)) {
        LOG_TRACE("hdmi edid init failed \"%s\"\n", edid_err);
        return false;
    } else if (!edid->CheckForHdmi(&is_hdmi_display_)) {
        LOG_TRACE("Failed to find valid timing and hdmi\n");
        return false;
    }
    LOG_TRACE("Found a %s monitor\n", is_hdmi_display_ ? "hdmi" : "dvi");

    return true;
}

bool HdmiDisplay::ConfigureDdi() {
    registers::Dpll dpll = controller()->SelectDpll(false /* is_edp */, true /* is_hdmi */,
                                                    mode().pixel_clock_10khz);
    if (dpll == registers::DPLL_INVALID) {
        return false;
    }

    auto dpll_enable = registers::DpllEnable::Get(dpll).ReadFrom(mmio_space());
    if (!dpll_enable.enable_dpll()) {
        // Set the the DPLL control settings
        auto dpll_ctrl1 = registers::DpllControl1::Get().ReadFrom(mmio_space());
        dpll_ctrl1.dpll_hdmi_mode(dpll).set(1);
        dpll_ctrl1.dpll_override(dpll).set(1);
        dpll_ctrl1.dpll_ssc_enable(dpll).set(0);
        dpll_ctrl1.WriteTo(mmio_space());
        dpll_ctrl1.ReadFrom(mmio_space());

        // Calculate and the HDMI DPLL parameters
        uint8_t p0, p1, p2;
        uint32_t dco_central_freq_khz;
        uint64_t dco_freq_khz;
        if (!calculate_params(mode().pixel_clock_10khz * 10,
                              &dco_freq_khz, &dco_central_freq_khz, &p0, &p1, &p2)) {
            LOG_ERROR("hdmi: failed to calculate clock params\n");
            return false;
        }

        // Set the DCO frequency
        auto dpll_cfg1 = registers::DpllConfig1::Get(dpll).FromValue(0);
        uint16_t dco_int = static_cast<uint16_t>((dco_freq_khz / 1000) / 24);
        uint16_t dco_frac = static_cast<uint16_t>(
                ((dco_freq_khz * (1 << 15) / 24) - ((dco_int * 1000L) * (1 << 15))) / 1000);
        dpll_cfg1.set_frequency_enable(1);
        dpll_cfg1.set_dco_integer(dco_int);
        dpll_cfg1.set_dco_fraction(dco_frac);
        dpll_cfg1.WriteTo(mmio_space());
        dpll_cfg1.ReadFrom(mmio_space());

        // Set the divisors and central frequency
        auto dpll_cfg2 = registers::DpllConfig2::Get(dpll).FromValue(0);
        dpll_cfg2.set_qdiv_ratio(p1);
        dpll_cfg2.set_qdiv_mode(p1 != 1);
        if (p2 == 5) {
            dpll_cfg2.set_kdiv_ratio(dpll_cfg2.kKdiv5);
        } else if (p2 == 2) {
            dpll_cfg2.set_kdiv_ratio(dpll_cfg2.kKdiv2);
        } else if (p2 == 3) {
            dpll_cfg2.set_kdiv_ratio(dpll_cfg2.kKdiv3);
        } else { // p2 == 1
            dpll_cfg2.set_kdiv_ratio(dpll_cfg2.kKdiv1);
        }
        if (p0 == 1) {
            dpll_cfg2.set_pdiv_ratio(dpll_cfg2.kPdiv1);
        } else if (p0 == 2) {
            dpll_cfg2.set_pdiv_ratio(dpll_cfg2.kPdiv2);
        } else if (p0 == 3) {
            dpll_cfg2.set_pdiv_ratio(dpll_cfg2.kPdiv3);
        } else { // p0 == 7
            dpll_cfg2.set_pdiv_ratio(dpll_cfg2.kPdiv7);
        }
        if (dco_central_freq_khz == 9600000) {
            dpll_cfg2.set_central_freq(dpll_cfg2.k9600Mhz);
        } else if (dco_central_freq_khz == 9000000) {
            dpll_cfg2.set_central_freq(dpll_cfg2.k9000Mhz);
        } else { // dco_central_freq == 8400000
            dpll_cfg2.set_central_freq(dpll_cfg2.k8400Mhz);
        }
        dpll_cfg2.WriteTo(mmio_space());
        dpll_cfg2.ReadFrom(mmio_space()); // Posting read

        // Enable and wait for the DPLL
        dpll_enable.set_enable_dpll(1);
        dpll_enable.WriteTo(mmio_space());
        if (!WAIT_ON_MS(registers::DpllStatus
                ::Get().ReadFrom(mmio_space()).dpll_lock(dpll).get(), 5)) {
            LOG_ERROR("hdmi: DPLL failed to lock\n");
            return false;
        }
    }

    // Direct the DPLL to the DDI
    auto dpll_ctrl2 = registers::DpllControl2::Get().ReadFrom(mmio_space());
    dpll_ctrl2.ddi_select_override(ddi()).set(1);
    dpll_ctrl2.ddi_clock_off(ddi()).set(0);
    dpll_ctrl2.ddi_clock_select(ddi()).set(dpll);
    dpll_ctrl2.WriteTo(mmio_space());

    // Enable DDI IO power and wait for it
    auto pwc2 = registers::PowerWellControl2::Get().ReadFrom(mmio_space());
    pwc2.ddi_io_power_request(ddi()).set(1);
    pwc2.WriteTo(mmio_space());
    if (!WAIT_ON_US(registers::PowerWellControl2
            ::Get().ReadFrom(mmio_space()).ddi_io_power_state(ddi()).get(), 20)) {
        LOG_ERROR("hdmi: failed to enable IO power for ddi\n");
        return false;
    }

    return true;
}

bool HdmiDisplay::PipeConfigPreamble(registers::Pipe pipe, registers::Trans trans) {
    registers::TranscoderRegs trans_regs(trans);

    // Configure Transcoder Clock Select
    auto trans_clk_sel = trans_regs.ClockSelect().ReadFrom(mmio_space());
    trans_clk_sel.set_trans_clock_select(ddi() + 1);
    trans_clk_sel.WriteTo(mmio_space());

    return true;
}

bool HdmiDisplay::PipeConfigEpilogue(registers::Pipe pipe, registers::Trans trans) {
    registers::TranscoderRegs trans_regs(trans);

    auto ddi_func = trans_regs.DdiFuncControl().ReadFrom(mmio_space());
    ddi_func.set_trans_ddi_function_enable(1);
    ddi_func.set_ddi_select(ddi());
    ddi_func.set_trans_ddi_mode_select(is_hdmi_display_ ? ddi_func.kModeHdmi : ddi_func.kModeDvi);
    ddi_func.set_bits_per_color(ddi_func.k8bbc);
    ddi_func.set_sync_polarity((!!(mode().flags & MODE_FLAG_VSYNC_POSITIVE)) << 1
                                | (!!(mode().flags & MODE_FLAG_HSYNC_POSITIVE)));
    ddi_func.set_port_sync_mode_enable(0);
    ddi_func.set_dp_vc_payload_allocate(0);
    ddi_func.WriteTo(mmio_space());

    auto trans_conf = trans_regs.Conf().ReadFrom(mmio_space());
    trans_conf.set_transcoder_enable(1);
    trans_conf.set_interlaced_mode(!!(mode().flags & MODE_FLAG_INTERLACED));
    trans_conf.WriteTo(mmio_space());

    // Configure voltage swing and related IO settings.
    registers::DdiRegs ddi_regs(ddi());
    auto ddi_buf_trans_hi = ddi_regs.DdiBufTransHi(9).ReadFrom(mmio_space());
    auto ddi_buf_trans_lo = ddi_regs.DdiBufTransLo(9).ReadFrom(mmio_space());
    auto disio_cr_tx_bmu = registers::DisplayIoCtrlRegTxBmu::Get().ReadFrom(mmio_space());

    // kUseDefaultIdx always fails the idx-in-bounds check, so no additional handling is needed
    uint8_t idx = controller()->igd_opregion().GetHdmiBufferTranslationIndex(ddi());
    uint8_t i_boost_override = controller()->igd_opregion().GetIBoost(ddi(), false /* is_dp */);

    const ddi_buf_trans_entry* entries;
    uint8_t default_iboost;
    if (is_skl_y(controller()->device_id()) || is_kbl_y(controller()->device_id())) {
        entries = hdmi_ddi_buf_trans_skl_y;
        if (idx >= fbl::count_of(hdmi_ddi_buf_trans_skl_y)) {
            idx = 8; // Default index
        }
        default_iboost = 3;
    } else {
        entries = hdmi_ddi_buf_trans_skl_uhs;
        if (idx >= fbl::count_of(hdmi_ddi_buf_trans_skl_uhs)) {
            idx = 8; // Default index
        }
        default_iboost = 1;
    }

    ddi_buf_trans_hi.set_reg_value(entries[idx].high_dword);
    ddi_buf_trans_lo.set_reg_value(entries[idx].low_dword);
    if (i_boost_override) {
        ddi_buf_trans_lo.set_balance_leg_enable(1);
    }
    disio_cr_tx_bmu.set_disable_balance_leg(0);
    disio_cr_tx_bmu.tx_balance_leg_select(ddi()).set(
            i_boost_override ? i_boost_override : default_iboost);

    ddi_buf_trans_hi.WriteTo(mmio_space());
    ddi_buf_trans_lo.WriteTo(mmio_space());
    disio_cr_tx_bmu.WriteTo(mmio_space());

    // Configure and enable DDI_BUF_CTL
    auto ddi_buf_ctl = ddi_regs.DdiBufControl().ReadFrom(mmio_space());
    ddi_buf_ctl.set_ddi_buffer_enable(1);
    ddi_buf_ctl.WriteTo(mmio_space());

    return true;
}

bool HdmiDisplay::CheckDisplayLimits(const display_config_t* config) {
    uint32_t refresh_rate = Controller::DisplayModeToRefreshRate(&config->mode);
    uint32_t width = config->mode.h_addressable;
    uint32_t height = config->mode.v_addressable;

    // See comments in DpDisplay::CheckDisplayLimits for details about constants
    return (width <= 1920 && height <= 1200 && refresh_rate <= 60)
            || (is_hdmi_display_ && width <= 4096 && height <= 2160 && refresh_rate <= 30);
}

} // namespace i915
