// Copyright 2016 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 <string.h>

#include <ddk/binding.h>
#include <ddk/device.h>
#include <ddk/driver.h>
#include <ddk/protocol/intelgpucore.h>
#include <ddk/protocol/pci.h>
#include <ddk/protocol/pci-lib.h>
#include <hw/inout.h>

#include <assert.h>
#include <fbl/unique_ptr.h>
#include <inttypes.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <zircon/syscalls.h>
#include <zircon/types.h>
#include <lib/zx/vmar.h>
#include <lib/zx/vmo.h>

#include "dp-display.h"
#include "hdmi-display.h"
#include "intel-i915.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"
#include "registers.h"
#include "tiling.h"

#define INTEL_I915_BROADWELL_DID (0x1616)

#define INTEL_I915_REG_WINDOW_SIZE (0x1000000u)
#define INTEL_I915_FB_WINDOW_SIZE (0x10000000u)

#define BACKLIGHT_CTRL_OFFSET (0xc8250)
#define BACKLIGHT_CTRL_BIT ((uint32_t)(1u << 31))

#define FLAGS_BACKLIGHT 1

namespace {
static zx_pixel_format_t supported_formats[2] = {
    ZX_PIXEL_FORMAT_ARGB_8888, ZX_PIXEL_FORMAT_RGB_x888
};

static cursor_info_t cursor_infos[3] = {
    { .width = 64, .height = 64, .format = ZX_PIXEL_FORMAT_ARGB_8888 },
    { .width = 128, .height = 128, .format = ZX_PIXEL_FORMAT_ARGB_8888 },
    { .width = 256, .height = 256, .format = ZX_PIXEL_FORMAT_ARGB_8888 },
};

static zx_status_t read_pci_config_16(void* ctx, uint16_t addr, uint16_t* value_out) {
    return static_cast<i915::Controller*>(ctx)->ReadPciConfig16(addr, value_out);
}

static zx_status_t map_pci_mmio(void* ctx, uint32_t pci_bar, void** addr_out, uint64_t* size_out) {
    return static_cast<i915::Controller*>(ctx)->MapPciMmio(pci_bar, addr_out, size_out);
}

static zx_status_t unmap_pci_mmio(void* ctx, uint32_t pci_bar) {
    return static_cast<i915::Controller*>(ctx)->UnmapPciMmio(pci_bar);
}

static zx_status_t get_pci_bti(void* ctx, uint32_t index, zx_handle_t* bti_out) {
    return static_cast<i915::Controller*>(ctx)->GetPciBti(index, bti_out);
}

static zx_status_t register_interrupt_callback(void* ctx,
                                               const zx_intel_gpu_core_interrupt_t* callback,
                                               uint32_t interrupt_mask) {
    return static_cast<i915::Controller*>(ctx)
            ->RegisterInterruptCallback(callback, interrupt_mask);
}

static zx_status_t unregister_interrupt_callback(void* ctx) {
    return static_cast<i915::Controller*>(ctx)->UnregisterInterruptCallback();
}

static uint64_t gtt_get_size(void* ctx) {
    return static_cast<i915::Controller*>(ctx)->GttGetSize();
}

static zx_status_t gtt_alloc(void* ctx, uint64_t page_count, uint64_t* addr_out) {
    return static_cast<i915::Controller*>(ctx)->GttAlloc(page_count, addr_out);
}

static zx_status_t gtt_free(void* ctx, uint64_t addr) {
    return static_cast<i915::Controller*>(ctx)->GttFree(addr);
}

static zx_status_t gtt_clear(void* ctx, uint64_t addr) {
    return static_cast<i915::Controller*>(ctx)->GttClear(addr);
}

static zx_status_t gtt_insert(void* ctx, uint64_t addr, zx_handle_t buffer, uint64_t page_offset,
                              uint64_t page_count) {
    return static_cast<i915::Controller*>(ctx)->GttInsert(addr, buffer, page_offset, page_count);
}

static zx_intel_gpu_core_protocol_ops_t i915_gpu_core_protocol_ops = {
    .read_pci_config16 = read_pci_config_16,
    .map_pci_mmio = map_pci_mmio,
    .unmap_pci_mmio = unmap_pci_mmio,
    .get_pci_bti = get_pci_bti,
    .register_interrupt_callback = register_interrupt_callback,
    .unregister_interrupt_callback = unregister_interrupt_callback,
    .gtt_get_size = gtt_get_size,
    .gtt_alloc = gtt_alloc,
    .gtt_free = gtt_free,
    .gtt_clear = gtt_clear,
    .gtt_insert = gtt_insert
};

static void gpu_release(void* ctx) {
    static_cast<i915::Controller*>(ctx)->GpuRelease();
}

static zx_protocol_device_t i915_gpu_core_device_proto = {};

static uint32_t get_bus_count(void* ctx) {
    return static_cast<i915::Controller*>(ctx)->GetBusCount();
}

static zx_status_t get_max_transfer_size(void* ctx, uint32_t bus_id, size_t* out_size) {
    return static_cast<i915::Controller*>(ctx)->GetMaxTransferSize(bus_id, out_size);
}

static zx_status_t set_bitrate(void* ctx, uint32_t bus_id, uint32_t bitrate) {
    return static_cast<i915::Controller*>(ctx)->SetBitrate(bus_id, bitrate);
}

static zx_status_t transact(void* ctx, uint32_t bus_id, const i2c_impl_op_t* ops, size_t count) {
    return static_cast<i915::Controller*>(ctx)->Transact(bus_id, ops, count);
}

static i2c_impl_protocol_ops_t i2c_ops = {
    .get_bus_count = get_bus_count,
    .get_max_transfer_size = get_max_transfer_size,
    .set_bitrate = set_bitrate,
    .transact = transact,
};

static int finish_init(void* arg) {
    static_cast<i915::Controller*>(arg)->FinishInit();
    return 0;
}

const display_config_t* find_config(uint64_t display_id,
                                    const display_config_t** display_configs,
                                    size_t display_count) {
    for (size_t i = 0; i < display_count; i++) {
        if (display_configs[i]->display_id == display_id) {
            return display_configs[i];
        }
    }
    return nullptr;
}

static void get_posttransform_width(const layer_t& layer, uint32_t* width, uint32_t* height) {
    const primary_layer_t* primary = &layer.cfg.primary;
    if (primary->transform_mode == FRAME_TRANSFORM_IDENTITY
            || primary->transform_mode == FRAME_TRANSFORM_ROT_180
            || primary->transform_mode == FRAME_TRANSFORM_REFLECT_X
            || primary->transform_mode == FRAME_TRANSFORM_REFLECT_Y) {
        *width = primary->src_frame.width;
        *height = primary->src_frame.height;
    } else {
        *width = primary->src_frame.height;
        *height = primary->src_frame.width;
    }
}

} // namespace

namespace i915 {

bool Controller::CompareDpllStates(const dpll_state_t& a, const dpll_state_t& b) {
    if (a.is_hdmi != b.is_hdmi) {
        return false;
    } else if (a.is_hdmi) {
        return a.hdmi.dco_int == b.hdmi.dco_int && a.hdmi.dco_frac == b.hdmi.dco_frac
                && a.hdmi.q == b.hdmi.q && a.hdmi.q_mode == b.hdmi.q_mode
                && a.hdmi.k == b.hdmi.k && a.hdmi.p == b.hdmi.p && a.hdmi.cf == b.hdmi.cf;
    } else {
        return a.dp_rate == b.dp_rate;
    }
}

void Controller::EnableBacklight(bool enable) {
    if (flags_ & FLAGS_BACKLIGHT) {
        uint32_t tmp = mmio_space()->Read32(BACKLIGHT_CTRL_OFFSET);

        if (enable) {
            tmp |= BACKLIGHT_CTRL_BIT;
        } else {
            tmp &= ~BACKLIGHT_CTRL_BIT;
        }

        mmio_space()->Write32(BACKLIGHT_CTRL_OFFSET, tmp);
    }
}

void Controller::HandleHotplug(registers::Ddi ddi, bool long_pulse) {
    LOG_TRACE("Hotplug detected on ddi %d (long_pulse=%d)\n", ddi, long_pulse);
    fbl::unique_ptr<DisplayDevice> device = nullptr;
    DisplayDevice* added_device = nullptr;
    uint64_t display_removed = INVALID_DISPLAY_ID;

    fbl::AutoLock lock(&display_lock_);

    for (size_t i = 0; i < display_devices_.size(); i++) {
        if (display_devices_[i]->ddi() == ddi) {
            if (display_devices_[i]->HandleHotplug(long_pulse)) {
                LOG_SPEW("hotplug handled by device\n");
                return;
            }
            device = display_devices_.erase(i);
            break;
        }
    }
    if (device) { // Existing device was unplugged
        LOG_INFO("Display %ld unplugged\n", device->id());
        display_removed = device->id();
        // Make sure the display's resources get freed before reallocating the pipe buffers
        device.reset();
    } else { // New device was plugged in
        fbl::unique_ptr<DisplayDevice> device = QueryDisplay(ddi);
        if (!device || !device->Init()) {
            LOG_INFO("failed to init hotplug display\n");
        } else {
            DisplayDevice* device_ptr = device.get();
            if (AddDisplay(fbl::move(device)) == ZX_OK) {
                added_device = device_ptr;
            }
        }
    }

    if (dc_intf_.is_valid() && (added_device || display_removed != INVALID_DISPLAY_ID)) {
        CallOnDisplaysChanged(&added_device, added_device != nullptr ? 1 : 0,
                             &display_removed, display_removed != INVALID_DISPLAY_ID);
    }
}

void Controller::HandlePipeVsync(registers::Pipe pipe, zx_time_t timestamp) {
    fbl::AutoLock lock(&display_lock_);

    if (!dc_intf_.is_valid()) {
        return;
    }

    uint64_t id = INVALID_DISPLAY_ID;
    // Plane 3 and the cursor are mutually exclusive, so this won't overflow.
    uint64_t handles[3];
    size_t handle_count = 0;
    if (pipes_[pipe].in_use()) {
        id = pipes_[pipe].attached_display_id();

        registers::PipeRegs regs(pipe);
        for (int i = 0; i < 3; i++) {
            auto live_surface = regs.PlaneSurfaceLive(i).ReadFrom(mmio_space());
            uint64_t handle = live_surface.surface_base_addr() << live_surface.kPageShift;
            if (handle) {
                handles[handle_count++] = handle;
            }
        }

        auto live_surface = regs.CursorSurfaceLive().ReadFrom(mmio_space());
        uint64_t handle = live_surface.surface_base_addr() << live_surface.kPageShift;
        if (handle) {
            handles[handle_count++] = handle;
        }
    }

    if (id != INVALID_DISPLAY_ID && handle_count) {
        dc_intf_.OnDisplayVsync(id, timestamp, handles, handle_count);
    }
}

DisplayDevice* Controller::FindDevice(uint64_t display_id) {
    for (auto& d : display_devices_) {
        if (d->id() == display_id) {
            return d.get();
        }
    }
    return nullptr;
}

bool Controller::BringUpDisplayEngine(bool resume) {
    // Enable PCH Reset Handshake
    auto nde_rstwrn_opt = registers::NorthDERestetWarning::Get().ReadFrom(mmio_space());
    nde_rstwrn_opt.set_rst_pch_handshake_enable(1);
    nde_rstwrn_opt.WriteTo(mmio_space());

    // Wait for Power Well 0 distribution
    if (!WAIT_ON_US(registers::FuseStatus::Get().ReadFrom(mmio_space()).pg0_dist_status(), 5)) {
        LOG_ERROR("Power Well 0 distribution failed\n");
        return false;
    }

    if (resume) {
        power_.Resume();
    } else {
        cd_clk_power_well_ = power_.GetCdClockPowerWellRef();
    }

    // Enable CDCLK PLL to 337.5mhz if the BIOS didn't already enable it. If it needs to be
    // something special (i.e. for eDP), assume that the BIOS already enabled it.
    auto dpll_enable = registers::DpllEnable::Get(registers::DPLL_0).ReadFrom(mmio_space());
    if (!dpll_enable.enable_dpll()) {
        // Set the cd_clk frequency to the minimum
        auto cd_clk = registers::CdClockCtl::Get().ReadFrom(mmio_space());
        cd_clk.set_cd_freq_select(cd_clk.kFreqSelect3XX);
        cd_clk.set_cd_freq_decimal(cd_clk.kFreqDecimal3375);
        cd_clk.WriteTo(mmio_space());

        // Configure DPLL0
        auto dpll_ctl1 = registers::DpllControl1::Get().ReadFrom(mmio_space());
        dpll_ctl1.dpll_link_rate(registers::DPLL_0).set(dpll_ctl1.kLinkRate810Mhz);
        dpll_ctl1.dpll_override(registers::DPLL_0).set(1);
        dpll_ctl1.dpll_hdmi_mode(registers::DPLL_0).set(0);
        dpll_ctl1.dpll_ssc_enable(registers::DPLL_0).set(0);
        dpll_ctl1.WriteTo(mmio_space());

        // Enable DPLL0 and wait for it
        dpll_enable.set_enable_dpll(1);
        dpll_enable.WriteTo(mmio_space());
        if (!WAIT_ON_MS(registers::Lcpll1Control::Get().ReadFrom(mmio_space()).pll_lock(), 5)) {
            LOG_ERROR("Failed to configure dpll0\n");
            return false;
        }

        // Do the magic sequence for Changing CD Clock Frequency specified on
        // intel-gfx-prm-osrc-skl-vol12-display.pdf p.135
        constexpr uint32_t kGtDriverMailboxInterface = 0x138124;
        constexpr uint32_t kGtDriverMailboxData0 = 0x138128;
        constexpr uint32_t kGtDriverMailboxData1 = 0x13812c;
        mmio_space()->Write32(kGtDriverMailboxData0, 0x3);
        mmio_space()->Write32(kGtDriverMailboxData1, 0x0);
        mmio_space()->Write32(kGtDriverMailboxInterface, 0x80000007);

        int count = 0;
        for (;;) {
            if (!WAIT_ON_US(mmio_space()->Read32(kGtDriverMailboxInterface) & 0x80000000, 150)) {
                LOG_ERROR("GT Driver Mailbox driver busy\n");
                return false;
            }
            if (mmio_space()->Read32(kGtDriverMailboxData0) & 0x1) {
                break;
            }
            if (count++ == 3) {
                LOG_ERROR("Failed to set cd_clk\n");
                return false;
            }
            zx_nanosleep(zx_deadline_after(ZX_MSEC(1)));
        }

        cd_clk.WriteTo(mmio_space());

        mmio_space()->Write32(kGtDriverMailboxData0, 0x3);
        mmio_space()->Write32(kGtDriverMailboxData1, 0x0);
        mmio_space()->Write32(kGtDriverMailboxInterface, 0x80000007);
    }

    // Enable and wait for DBUF
    auto dbuf_ctl = registers::DbufCtl::Get().ReadFrom(mmio_space());
    dbuf_ctl.set_power_request(1);
    dbuf_ctl.WriteTo(mmio_space());

    if (!WAIT_ON_US(registers::DbufCtl::Get().ReadFrom(mmio_space()).power_state(), 10)) {
        LOG_ERROR("Failed to enable DBUF\n");
        return false;
    }

    // We never use VGA, so just disable it at startup
    constexpr uint16_t kSequencerIdx = 0x3c4;
    constexpr uint16_t kSequencerData = 0x3c5;
    constexpr uint8_t kClockingModeIdx = 1;
    constexpr uint8_t kClockingModeScreenOff = (1 << 5);
    zx_status_t status = zx_ioports_request(get_root_resource(), kSequencerIdx, 2);
    if (status != ZX_OK) {
        LOG_ERROR("Failed to map vga ports\n");
        return false;
    }
    outp(kSequencerIdx, kClockingModeIdx);
    uint8_t clocking_mode = inp(kSequencerData);
    if (!(clocking_mode & kClockingModeScreenOff)) {
        outp(kSequencerIdx, inp(kSequencerData) | kClockingModeScreenOff);
        zx_nanosleep(zx_deadline_after(ZX_MSEC(100)));

        auto vga_ctl = registers::VgaCtl::Get().ReadFrom(mmio_space());
        vga_ctl.set_vga_display_disable(1);
        vga_ctl.WriteTo(mmio_space());
    }

    for (unsigned i = 0; i < registers::kPipeCount; i++) {
        ResetPipe(registers::kPipes[i]);

        registers::PipeRegs pipe_regs(registers::kPipes[i]);

        // Disable the scalers (double buffered on PipeScalerWinSize), since
        // we don't know what state they are in at boot.
        pipe_regs.PipeScalerCtrl(0).ReadFrom(mmio_space()).set_enable(0).WriteTo(mmio_space());
        pipe_regs.PipeScalerWinSize(0).ReadFrom(mmio_space()).WriteTo(mmio_space());
        if (i != registers::PIPE_C) {
            pipe_regs.PipeScalerCtrl(1).ReadFrom(mmio_space()).set_enable(0).WriteTo(mmio_space());
            pipe_regs.PipeScalerWinSize(1).ReadFrom(mmio_space()).WriteTo(mmio_space());
        }

        // Disable the cursor watermark
        for (int wm_num = 0; wm_num < 8; wm_num++) {
            auto wm = pipe_regs.PlaneWatermark(0, wm_num).FromValue(0);
            wm.WriteTo(mmio_space());
        }

        // Disable the primary plane watermarks and reset their buffer allocation
        for (unsigned plane_num = 0; plane_num < registers::kImagePlaneCount; plane_num++) {
            for (int wm_num = 0; wm_num < 8; wm_num++) {
                auto wm = pipe_regs.PlaneWatermark(plane_num + 1, wm_num).FromValue(0);
                wm.WriteTo(mmio_space());
            }
        }
    }

    return true;
}

void Controller::ResetPipe(registers::Pipe pipe) {
    registers::PipeRegs pipe_regs(pipe);

    // Disable planes, bottom color, and cursor
    for (int i = 0; i < 3; i++ ) {
        pipe_regs.PlaneControl(i).FromValue(0).WriteTo(mmio_space());
        pipe_regs.PlaneSurface(i).FromValue(0).WriteTo(mmio_space());
    }
    auto cursor_ctrl = pipe_regs.CursorCtrl().ReadFrom(mmio_space());
    cursor_ctrl.set_mode_select(cursor_ctrl.kDisabled);
    cursor_ctrl.WriteTo(mmio_space());
    pipe_regs.CursorBase().FromValue(0).WriteTo(mmio_space());
    pipe_regs.PipeBottomColor().FromValue(0).WriteTo(mmio_space());

    ZX_DEBUG_ASSERT(mtx_trylock(&display_lock_) == thrd_busy);
    for (unsigned plane_num = 0; plane_num < registers::kImagePlaneCount; plane_num++) {
        plane_buffers_[pipe][plane_num].start = registers::PlaneBufCfg::kBufferCount;
    }
}

bool Controller::ResetTrans(registers::Trans trans) {
    registers::TranscoderRegs trans_regs(trans);

    // Disable transcoder and wait it to stop
    auto trans_conf = trans_regs.Conf().ReadFrom(mmio_space());
    trans_conf.set_transcoder_enable(0);
    trans_conf.WriteTo(mmio_space());
    if (!WAIT_ON_MS(!trans_regs.Conf().ReadFrom(mmio_space()).transcoder_state(), 60)) {
        LOG_ERROR("Failed to reset transcoder\n");
        return false;
    }

    // Disable transcoder ddi select and clock select
    auto trans_ddi_ctl = trans_regs.DdiFuncControl().ReadFrom(mmio_space());
    trans_ddi_ctl.set_trans_ddi_function_enable(0);
    trans_ddi_ctl.set_ddi_select(0);
    trans_ddi_ctl.WriteTo(mmio_space());

    if (trans != registers::TRANS_EDP) {
        auto trans_clk_sel = trans_regs.ClockSelect().ReadFrom(mmio_space());
        trans_clk_sel.set_trans_clock_select(0);
        trans_clk_sel.WriteTo(mmio_space());
    }

    return true;
}

bool Controller::ResetDdi(registers::Ddi ddi) {
    registers::DdiRegs ddi_regs(ddi);

    // Disable the port
    auto ddi_buf_ctl = ddi_regs.DdiBufControl().ReadFrom(mmio_space());
    bool was_enabled = ddi_buf_ctl.ddi_buffer_enable();
    ddi_buf_ctl.set_ddi_buffer_enable(0);
    ddi_buf_ctl.WriteTo(mmio_space());

    auto ddi_dp_tp_ctl = ddi_regs.DdiDpTransportControl().ReadFrom(mmio_space());
    ddi_dp_tp_ctl.set_transport_enable(0);
    ddi_dp_tp_ctl.set_dp_link_training_pattern(ddi_dp_tp_ctl.kTrainingPattern1);
    ddi_dp_tp_ctl.WriteTo(mmio_space());

    if (was_enabled && !WAIT_ON_MS(ddi_regs.DdiBufControl().ReadFrom(mmio_space()).ddi_idle_status(), 8)) {
        LOG_ERROR("Port failed to go idle\n");
        return false;
    }

    // Disable IO power
    auto pwc2 = registers::PowerWellControl2::Get().ReadFrom(mmio_space());
    pwc2.ddi_io_power_request(ddi).set(0);
    pwc2.WriteTo(mmio_space());

    // Remove the PLL mapping and disable the PLL (we don't share PLLs)
    auto dpll_ctrl2 = registers::DpllControl2::Get().ReadFrom(mmio_space());
    if (!dpll_ctrl2.ddi_clock_off(ddi).get()) {
        dpll_ctrl2.ddi_clock_off(ddi).set(1);
        dpll_ctrl2.WriteTo(mmio_space());

        registers::Dpll dpll = static_cast<registers::Dpll>(dpll_ctrl2.ddi_clock_select(ddi).get());
        // Don't underflow if we're resetting at initialization
        dplls_[dpll].use_count =
                static_cast<uint8_t>(dplls_[dpll].use_count > 0 ? dplls_[dpll].use_count - 1 : 0);
        // We don't want to disable DPLL0, since that drives cdclk.
        if (dplls_[dpll].use_count == 0 && dpll != registers::DPLL_0) {
            auto dpll_enable = registers::DpllEnable::Get(dpll).ReadFrom(mmio_space());
            dpll_enable.set_enable_dpll(0);
            dpll_enable.WriteTo(mmio_space());
        }
    }

    return true;
}

registers::Dpll Controller::SelectDpll(bool is_edp, const dpll_state_t& state) {
    registers::Dpll res = registers::DPLL_INVALID;
    if (is_edp) {
        ZX_ASSERT(!state.is_hdmi);
        if (dplls_[0].use_count == 0 || dplls_[0].state.dp_rate == state.dp_rate) {
            res = registers::DPLL_0;
        }
    } else {
        for (unsigned i = registers::kDpllCount - 1; i > 0; i--) {
            if (dplls_[i].use_count == 0) {
                res = static_cast<registers::Dpll>(i);
            } else if (CompareDpllStates(dplls_[i].state, state)) {
                res = static_cast<registers::Dpll>(i);
                break;
            }
        }
    }

    if (res != registers::DPLL_INVALID) {
        dplls_[res].state = state;
        dplls_[res].use_count++;
        LOG_SPEW("Selected DPLL %d\n", res);
    } else {
        LOG_WARN("Failed to allocate DPLL\n");
    }

    return res;
}

const dpll_state_t* Controller::GetDpllState(registers::Dpll dpll) {
    if (dplls_[dpll].use_count) {
        return &dplls_[dpll].state;
    }
    return nullptr;
}

fbl::unique_ptr<DisplayDevice> Controller::QueryDisplay(registers::Ddi ddi) {
    fbl::AllocChecker ac;
    if (igd_opregion_.SupportsDp(ddi)) {
        LOG_SPEW("Checking for displayport monitor\n");
        auto dp_disp = fbl::make_unique_checked<DpDisplay>(&ac, this, next_id_, ddi);
        if (ac.check() && reinterpret_cast<DisplayDevice*>(dp_disp.get())->Query()) {
            return dp_disp;
        }
    }
    if (igd_opregion_.SupportsHdmi(ddi) || igd_opregion_.SupportsDvi(ddi)) {
        LOG_SPEW("Checking for hdmi monitor\n");
        auto hdmi_disp = fbl::make_unique_checked<HdmiDisplay>(&ac, this, next_id_, ddi);
        if (ac.check() && reinterpret_cast<DisplayDevice*>(hdmi_disp.get())->Query()) {
            return hdmi_disp;
        }
    }

    return nullptr;
}

bool Controller::LoadHardwareState(registers::Ddi ddi, DisplayDevice* device) {
    registers::DdiRegs regs(ddi);

    if (!registers::PowerWellControl2::Get().ReadFrom(mmio_space()).ddi_io_power_state(ddi).get()
            || !regs.DdiBufControl().ReadFrom(mmio_space()).ddi_buffer_enable()) {
        return false;
    }

    auto pipe = registers::PIPE_INVALID;
    if (ddi == registers::DDI_A) {
        registers::TranscoderRegs regs(registers::TRANS_EDP);
        auto ddi_func_ctrl = regs.DdiFuncControl().ReadFrom(mmio_space());

        if (ddi_func_ctrl.edp_input_select() == ddi_func_ctrl.kPipeA) {
            pipe = registers::PIPE_A;
        } else if (ddi_func_ctrl.edp_input_select() == ddi_func_ctrl.kPipeB) {
            pipe = registers::PIPE_B;
        } else if (ddi_func_ctrl.edp_input_select() == ddi_func_ctrl.kPipeC) {
            pipe = registers::PIPE_C;
        }
    } else {
        for (unsigned j = 0; j < registers::kPipeCount; j++) {
            auto transcoder = registers::kTrans[j];
            registers::TranscoderRegs regs(transcoder);
            if (regs.ClockSelect().ReadFrom(mmio_space()).trans_clock_select() == ddi + 1u
                    && regs.DdiFuncControl().ReadFrom(mmio_space()).ddi_select() == ddi) {
                pipe = registers::kPipes[j];
                break;
            }
        }
    }

    if (pipe == registers::PIPE_INVALID) {
        return false;
    }

    auto dpll_ctrl2 = registers::DpllControl2::Get().ReadFrom(mmio_space());
    if (dpll_ctrl2.ddi_clock_off(ddi).get()) {
        return false;
    }

    auto dpll = static_cast<registers::Dpll>(dpll_ctrl2.ddi_clock_select(ddi).get());
    auto dpll_enable = registers::DpllEnable::Get(dpll).ReadFrom(mmio_space());
    if (!dpll_enable.enable_dpll()) {
        return false;
    }

    auto dpll_ctrl1 = registers::DpllControl1::Get().ReadFrom(mmio_space());
    dplls_[dpll].use_count++;
    dplls_[dpll].state.is_hdmi = dpll_ctrl1.dpll_hdmi_mode(dpll).get();
    if (dplls_[dpll].state.is_hdmi) {
        auto dpll_cfg1 = registers::DpllConfig1::Get(dpll).ReadFrom(mmio_space());
        auto dpll_cfg2 = registers::DpllConfig2::Get(dpll).ReadFrom(mmio_space());

        dplls_[dpll].state.hdmi = {
            .dco_int = static_cast<uint16_t>(dpll_cfg1.dco_integer()),
            .dco_frac = static_cast<uint16_t>(dpll_cfg1.dco_fraction()),
            .q = static_cast<uint8_t>(dpll_cfg2.qdiv_ratio()),
            .q_mode = static_cast<uint8_t>(dpll_cfg2.qdiv_mode()),
            .k = static_cast<uint8_t>(dpll_cfg2.kdiv_ratio()),
            .p = static_cast<uint8_t>(dpll_cfg2.pdiv_ratio()),
            .cf = static_cast<uint8_t>(dpll_cfg2.central_freq()),
        };
    } else {
        dplls_[dpll].state.dp_rate = dpll_ctrl1.dpll_link_rate(dpll).get();
    }

    device->AttachPipe(&pipes_[pipe]);

    device->LoadActiveMode();

    return true;
}

void Controller::InitDisplays() {
    fbl::AutoLock lock(&display_lock_);
    BringUpDisplayEngine(false);

    for (uint32_t i = 0; i < registers::kDdiCount; i++) {
        auto disp_device = QueryDisplay(registers::kDdis[i]);
        if (disp_device) {
            AddDisplay(fbl::move(disp_device));
        }
    }

    if (display_devices_.size() == 0) {
        LOG_INFO("No displays detected\n");
    }

    for (unsigned i = 0; i < registers::kDpllCount; i++) {
        dplls_[i].use_count = 0;
    }

    // Make a note of what needs to be reset, so we can finish querying the hardware state
    // before touching it, and so we can make sure transcoders are reset before ddis.
    bool ddi_needs_reset[registers::kDdiCount] = {};
    DisplayDevice* device_needs_init[registers::kDdiCount] = {};
    for (unsigned i = 0; i < registers::kDdiCount; i++) {
        auto ddi = registers::kDdis[i];
        DisplayDevice* device = nullptr;
        for (auto& d : display_devices_) {
            if (d->ddi() == ddi) {
                device = d.get();
                break;
            }
        }

        if (device == nullptr) {
            ddi_needs_reset[ddi] = true;
        } else {
            if (!LoadHardwareState(ddi, device)) {
                ddi_needs_reset[ddi] = true;
                device_needs_init[ddi] = device;
            } else {
                device->InitBacklight();
            }
        }
    }

    // Reset any transcoders which aren't in use
    for (unsigned i = 0; i < registers::kTransCount; i++) {
        auto transcoder = registers::kTrans[i];
        auto pipe = registers::PIPE_INVALID;
        for (auto& p : pipes_) {
            if (p.in_use() && p.transcoder() == transcoder) {
                pipe = p.pipe();
                break;
            }
        }

        if (pipe == registers::PIPE_INVALID) {
            ResetTrans(transcoder);
        }
    }

    // Reset any ddis which don't have a restored display. If we failed to restore a
    // display, try to initialize it here.
    for (unsigned i = 0; i < registers::kDdiCount; i++) {
        if (!ddi_needs_reset[i]) {
            continue;
        }
        ResetDdi(static_cast<registers::Ddi>(i));

        DisplayDevice* device = device_needs_init[i];
        if (device && !device->Init()) {
            for (unsigned i = 0; i < display_devices_.size(); i++) {
                if (display_devices_[i].get() == device) {
                    display_devices_.erase(i);
                    break;
                }
            }
        }
    }
}

zx_status_t Controller::AddDisplay(fbl::unique_ptr<DisplayDevice>&& display) {
    fbl::AllocChecker ac;
    display_devices_.reserve(display_devices_.size() + 1, &ac);

    if (ac.check()) {
        display_devices_.push_back(fbl::move(display), &ac);
        assert(ac.check());

        fbl::unique_ptr<DisplayDevice>& new_device = display_devices_[display_devices_.size() - 1];
        LOG_INFO("Display %ld connected\n", new_device->id());
    } else {
        LOG_WARN("Failed to add display device\n");
        return ZX_ERR_NO_MEMORY;
    }

    next_id_++;
    return ZX_OK;
}

void Controller::CallOnDisplaysChanged(DisplayDevice** added, size_t added_count,
                                       uint64_t* removed, size_t removed_count) {
    added_display_args_t added_args[added_count];
    added_display_info_t added_info[added_count];
    size_t added_actual;
    for (unsigned i = 0; i < added_count; i++) {
        added_args[i].display_id = added[i]->id();
        added_args[i].edid_present = true;
        added_args[i].panel.i2c_bus_id = added[i]->i2c_bus_id();
        added_args[i].pixel_format_list = supported_formats;
        added_args[i].pixel_format_count = static_cast<uint32_t>(fbl::count_of(supported_formats));
        added_args[i].cursor_info_list = cursor_infos;
        added_args[i].cursor_info_count = static_cast<uint32_t>(fbl::count_of(cursor_infos));
    }
    dc_intf_.OnDisplaysChanged(added_args, added_count, removed, removed_count,
                               added_info, added_count, &added_actual);
    ZX_DEBUG_ASSERT(added_count == added_actual);
    for (unsigned i = 0; i < added_actual; i++) {
        added[i]->set_is_hdmi(added_info[i].is_hdmi_out);
    }
}

// DisplayControllerImpl methods

void Controller::DisplayControllerImplSetDisplayControllerInterface(
    const display_controller_interface_t* intf) {

    fbl::AutoLock lock(&display_lock_);
    dc_intf_ = ddk::DisplayControllerInterfaceProxy(intf);

    if (ready_for_callback_ && display_devices_.size()) {
        DisplayDevice* added_displays[registers::kDdiCount];
        uint32_t size = static_cast<uint32_t>(display_devices_.size());
        for (unsigned i = 0; i < size; i++) {
            added_displays[i] = display_devices_[i].get();
        }
        CallOnDisplaysChanged(added_displays, size, NULL, 0);
    }
}

zx_status_t Controller::DisplayControllerImplImportVmoImage(image_t* image, zx_handle_t vmo,
                                                            size_t offset) {
    if (!(image->type == IMAGE_TYPE_SIMPLE || image->type == IMAGE_TYPE_X_TILED
                || image->type == IMAGE_TYPE_Y_LEGACY_TILED
                || image->type == IMAGE_TYPE_YF_TILED)) {
        return ZX_ERR_INVALID_ARGS;
    }
    if (offset % PAGE_SIZE != 0) {
        return ZX_ERR_INVALID_ARGS;
    }

    fbl::AutoLock lock(&gtt_lock_);
    fbl::AllocChecker ac;
    imported_images_.reserve(imported_images_.size() + 1, &ac);
    if (!ac.check()) {
        return ZX_ERR_NO_MEMORY;
    }

    uint32_t length = width_in_tiles(image->type, image->width, image->pixel_format) *
            height_in_tiles(image->type, image->height, image->pixel_format) *
            get_tile_byte_size(image->type);

    uint32_t align;
    if (image->type == IMAGE_TYPE_SIMPLE) {
        align = registers::PlaneSurface::kLinearAlignment;
    } else if (image->type == IMAGE_TYPE_X_TILED) {
        align = registers::PlaneSurface::kXTilingAlignment;
    } else {
        align = registers::PlaneSurface::kYTilingAlignment;
    }
    fbl::unique_ptr<GttRegion> gtt_region;
    zx_status_t status = gtt_.AllocRegion(length, align, &gtt_region);
    if (status != ZX_OK) {
        return status;
    }

    // The vsync logic requires that images not have base == 0
    if (gtt_region->base() == 0) {
        fbl::unique_ptr<GttRegion> alt_gtt_region;
        zx_status_t status = gtt_.AllocRegion(length, align, &alt_gtt_region);
        if (status != ZX_OK) {
            return status;
        }
        gtt_region = fbl::move(alt_gtt_region);
    }

    status = gtt_region->PopulateRegion(vmo, offset / PAGE_SIZE, length);
    if (status != ZX_OK) {
        return status;
    }

    image->handle = gtt_region->base();
    imported_images_.push_back(fbl::move(gtt_region));
    return ZX_OK;
}

void Controller::DisplayControllerImplReleaseImage(image_t* image) {
    fbl::AutoLock lock(&gtt_lock_);
    for (unsigned i = 0; i < imported_images_.size(); i++) {
        if (imported_images_[i]->base() == image->handle) {
            imported_images_.erase(i);
            return;
        }
    }
}

const fbl::unique_ptr<GttRegion>& Controller::GetGttRegion(uint64_t handle) {
    fbl::AutoLock lock(&gtt_lock_);
    for (auto& region : imported_images_) {
        if (region->base() == handle) {
            return region;
        }
    }
    ZX_ASSERT(false);
}

bool Controller::GetPlaneLayer(registers::Pipe pipe, uint32_t plane,
                               const display_config_t** configs, size_t display_count,
                               const layer_t** layer_out) {
    if (!pipes_[pipe].in_use()) {
        return false;
    }
    uint64_t disp_id = pipes_[pipe].attached_display_id();

    for (unsigned i = 0; i < display_count; i++) {
        const display_config_t* config = configs[i];
        if (config->display_id != disp_id) {
            continue;
        }
        bool has_color_layer = config->layer_count &&
                               config->layer_list[0]->type == LAYER_TYPE_COLOR;
        for (unsigned j = 0; j < config->layer_count; j++) {
            if (config->layer_list[j]->type == LAYER_TYPE_PRIMARY) {
                if (plane != (config->layer_list[j]->z_index - has_color_layer)) {
                    continue;
                }
            } else if (config->layer_list[j]->type == LAYER_TYPE_CURSOR) {
                // Since the config is validated, we know the cursor is the
                // highest plane, so we don't care about the layer's z_index.
                if (plane != registers::kCursorPlane) {
                    continue;
                }
            } else if (config->layer_list[j]->type == LAYER_TYPE_COLOR) {
                // color layers aren't a plane
                continue;
            } else {
                ZX_ASSERT(false);
            }
            *layer_out = config->layer_list[j];
            return true;
        }
    }
    return false;
}

uint16_t Controller::CalculateBuffersPerPipe(size_t display_count) {
    ZX_ASSERT(display_count < registers::kPipeCount);
    return static_cast<uint16_t>(registers::PlaneBufCfg::kBufferCount / display_count);
}

bool Controller::CalculateMinimumAllocations(const display_config_t** display_configs,
                                             size_t display_count,
                                             uint16_t min_allocs[registers::kPipeCount]
                                                                [registers::kImagePlaneCount]) {
    // This fn ignores layers after kImagePlaneCount. Displays with too many layers already
    // failed in ::CheckConfiguration, so it doesn't matter if we incorrectly say they pass here.
    bool success = true;
    for (unsigned pipe_num = 0; pipe_num < registers::kPipeCount; pipe_num++) {
        registers::Pipe pipe = registers::kPipes[pipe_num];
        uint32_t total = 0;

        for (unsigned plane_num = 0; plane_num < registers::kImagePlaneCount; plane_num++) {
            const layer_t* layer;
            if (!GetPlaneLayer(pipe, plane_num, display_configs, display_count, &layer)) {
                min_allocs[pipe_num][plane_num] = 0;
                continue;
            }

            if (layer->type == LAYER_TYPE_CURSOR) {
                min_allocs[pipe_num][plane_num] = 8;
                continue;
            }

            ZX_ASSERT(layer->type == LAYER_TYPE_PRIMARY);
            const primary_layer_t* primary = &layer->cfg.primary;

            if (primary->image.type == IMAGE_TYPE_SIMPLE
                    || primary->image.type == IMAGE_TYPE_X_TILED) {
                min_allocs[pipe_num][plane_num] = 8;
            } else {
                uint32_t plane_source_width;
                uint32_t min_scan_lines;
                uint32_t bytes_per_pixel = ZX_PIXEL_FORMAT_BYTES(primary->image.pixel_format);
                if (primary->transform_mode == FRAME_TRANSFORM_IDENTITY
                        || primary->transform_mode == FRAME_TRANSFORM_ROT_180) {
                    plane_source_width = primary->src_frame.width;
                    min_scan_lines = 8;
                } else {
                    plane_source_width = primary->src_frame.height;
                    min_scan_lines = 32 / bytes_per_pixel;
                }
                min_allocs[pipe_num][plane_num] = static_cast<uint16_t>(
                        ((fbl::round_up(4u * plane_source_width * bytes_per_pixel, 512u) / 512u) *
                        (min_scan_lines / 4)) + 3);
                if (min_allocs[pipe_num][plane_num] < 8) {
                    min_allocs[pipe_num][plane_num] = 8;
                }

            }
            total += min_allocs[pipe_num][plane_num];
        }

        if (total && total > CalculateBuffersPerPipe(display_count)) {
            min_allocs[pipe_num][0] = UINT16_MAX;
            success = false;
        }
    }

    return success;
}

void Controller::UpdateAllocations(const uint16_t min_allocs[registers::kPipeCount]
                                                            [registers::kImagePlaneCount],
                                   const uint64_t data_rate[registers::kPipeCount]
                                                           [registers::kImagePlaneCount]) {
    uint16_t allocs[registers::kPipeCount][registers::kImagePlaneCount];

    for (unsigned pipe_num = 0; pipe_num < registers::kPipeCount; pipe_num++) {
        uint64_t total_data_rate = 0;
        for (unsigned plane_num = 0; plane_num < registers::kImagePlaneCount; plane_num++) {
            total_data_rate += data_rate[pipe_num][plane_num];
        }
        if (total_data_rate == 0) {
            for (unsigned plane_num = 0; plane_num < registers::kImagePlaneCount; plane_num++) {
                allocs[pipe_num][plane_num] = 0;
            }
            continue;
        }

        // Allocate buffers based on the percentage of the total pixel bandwidth they take. If
        // that percentage isn't enough for a plane, give that plane its minimum allocation and
        // then try again.
        double buffers_per_pipe = pipe_buffers_[pipe_num].end - pipe_buffers_[pipe_num].start;
        bool forced_alloc[registers::kImagePlaneCount] = {};
        bool done = false;
        while (!done) {
            for (unsigned plane_num = 0; plane_num < registers::kImagePlaneCount; plane_num++) {
                if (forced_alloc[plane_num]) {
                    continue;
                }

                double blocks = buffers_per_pipe *
                        static_cast<double>(data_rate[pipe_num][plane_num]) /
                        static_cast<double>(total_data_rate);
                allocs[pipe_num][plane_num] = static_cast<uint16_t>(blocks);
            }

            done = true;

            for (unsigned plane_num = 0; plane_num < registers::kImagePlaneCount; plane_num++) {
                if (allocs[pipe_num][plane_num] < min_allocs[pipe_num][plane_num]) {
                    done = false;
                    allocs[pipe_num][plane_num] = min_allocs[pipe_num][plane_num];
                    forced_alloc[plane_num] = true;
                    total_data_rate -= data_rate[pipe_num][plane_num];
                    buffers_per_pipe -= allocs[pipe_num][plane_num];
                }
            }
        }
    }

    // Do the actual allocation, using the buffers that are asigned to each pipe.
    for (unsigned pipe_num = 0; pipe_num < registers::kPipeCount; pipe_num++) {
        uint16_t start = pipe_buffers_[pipe_num].start;
        for (unsigned plane_num = 0; plane_num < registers::kImagePlaneCount; plane_num++) {
            auto cur = &plane_buffers_[pipe_num][plane_num];

            if (allocs[pipe_num][plane_num] == 0) {
                cur->start = registers::PlaneBufCfg::kBufferCount;
                cur->end = static_cast<uint16_t>(cur->start + 1);
            } else {
                cur->start = start;
                cur->end = static_cast<uint16_t>(start + allocs[pipe_num][plane_num]);
            }
            start = static_cast<uint16_t>(start + allocs[pipe_num][plane_num]);

            registers::Pipe pipe = registers::kPipes[pipe_num];
            registers::PipeRegs pipe_regs(pipe);

            // These are latched on the surface address register, so we don't yet need to
            // worry about overlaps when updating planes during a pipe allocation.
            auto buf_cfg = pipe_regs.PlaneBufCfg(plane_num + 1).FromValue(0);
            buf_cfg.set_buffer_start(cur->start);
            buf_cfg.set_buffer_end(cur->end - 1);
            buf_cfg.WriteTo(mmio_space());

            // TODO(stevensd): Real watermark programming
            auto wm0 = pipe_regs.PlaneWatermark(plane_num + 1, 0).FromValue(0);
            wm0.set_enable(cur->start != registers::PlaneBufCfg::kBufferCount);
            wm0.set_blocks(cur->end - cur->start);
            wm0.WriteTo(mmio_space());

            // Give the buffers to both the cursor plane and plane 2, since
            // only one will actually be active.
            if (plane_num == registers::kCursorPlane) {
                auto buf_cfg = pipe_regs.PlaneBufCfg(0).FromValue(0);
                buf_cfg.set_buffer_start(cur->start);
                buf_cfg.set_buffer_end(cur->end - 1);
                buf_cfg.WriteTo(mmio_space());

                auto wm0 = pipe_regs.PlaneWatermark(0, 0).FromValue(0);
                wm0.set_enable(cur->start != registers::PlaneBufCfg::kBufferCount);
                wm0.set_blocks(cur->end - cur->start);
                wm0.WriteTo(mmio_space());
            }
        }
    }
}

void Controller::ReallocatePlaneBuffers(const display_config_t** display_configs,
                                        size_t display_count, bool reallocate_pipes) {
    if (display_count == 0) {
        // Deal with reallocation later, when there are actually displays
        return;
    }

    uint16_t min_allocs[registers::kPipeCount][registers::kImagePlaneCount];
    if (!CalculateMinimumAllocations(display_configs, display_count, min_allocs)) {
        // The allocation should have been checked, so this shouldn't fail
        ZX_ASSERT(false);
    }

    // Calculate the data rates and store the minimum allocations
    uint64_t data_rate[registers::kPipeCount][registers::kImagePlaneCount];
    for (unsigned pipe_num = 0; pipe_num < registers::kPipeCount; pipe_num++) {
        registers::Pipe pipe = registers::kPipes[pipe_num];
        for (unsigned plane_num = 0; plane_num < registers::kImagePlaneCount; plane_num++) {
            const layer_t* layer;
            if (!GetPlaneLayer(pipe, plane_num, display_configs, display_count, &layer)) {
                data_rate[pipe_num][plane_num] = 0;
            } else if (layer->type == LAYER_TYPE_PRIMARY) {
                const primary_layer_t* primary = &layer->cfg.primary;

                uint32_t scaled_width = primary->src_frame.width * primary->src_frame.width
                        / primary->dest_frame.width;
                uint32_t scaled_height = primary->src_frame.height * primary->src_frame.height
                        / primary->dest_frame.height;
                data_rate[pipe_num][plane_num] = scaled_width * scaled_height *
                        ZX_PIXEL_FORMAT_BYTES(primary->image.pixel_format);
            } else if (layer->type == LAYER_TYPE_CURSOR) {
                // Use a tiny data rate so the cursor gets the minimum number of buffers
                data_rate[pipe_num][plane_num] = 1;
            } else {
                // Other layers don't use pipe/planes, so GetPlaneLayer should have returned false
                ZX_ASSERT(false);
            }
        }
    }

    if (initial_alloc_) {
        initial_alloc_ = false;
        reallocate_pipes = true;
    }

    buffer_allocation_t active_allocation[registers::kPipeCount];
    if (reallocate_pipes) {
        // Allocate buffers to each pipe, but save the old allocation to use
        // when progressively updating the allocation.
        memcpy(active_allocation, pipe_buffers_, sizeof(active_allocation));

        uint16_t buffers_per_pipe = CalculateBuffersPerPipe(display_count);
        int active_pipes = 0;
        for (unsigned pipe_num = 0; pipe_num < registers::kPipeCount; pipe_num++) {
            if (pipes_[pipe_num].in_use()) {
                pipe_buffers_[pipe_num].start =
                        static_cast<uint16_t>(buffers_per_pipe * active_pipes);
                pipe_buffers_[pipe_num].end =
                        static_cast<uint16_t>(pipe_buffers_[pipe_num].start + buffers_per_pipe);
                active_pipes++;
            } else {
                pipe_buffers_[pipe_num].start = pipe_buffers_[pipe_num].end = 0;
            }
            LOG_SPEW("Pipe %d buffers: [%d, %d)\n", pipe_num,
                     pipe_buffers_[pipe_num].start, pipe_buffers_[pipe_num].end);
        }
    }

    // It's not necessary to flush the buffer changes since the pipe allocs didn't change
    UpdateAllocations(min_allocs, data_rate);

    if (reallocate_pipes) {
        DoPipeBufferReallocation(active_allocation);
    }
}

void Controller::DoPipeBufferReallocation(
        buffer_allocation_t active_allocation[registers::kPipeCount]) {
    // Given that the order of the allocations is fixed, an allocation X_i is contained completely
    // within its old allocation if {new len of allocations preceding X_i} >= {start of old X_i} and
    // {new len of allocations preceding X_i + new len of X_i} <= {end of old X_i}. For any i,
    // if condition 1 holds, either condition 2 is true and we're done, or condition 2 doesn't
    // and condition 1 holds for i + 1. Since condition 1 holds for i == 0 and because condition
    // 2 holds for the last allocation (since the allocation is valid), it is guaranteed that
    // at least one allocation is entirely within its old allocation. The remaining buffers
    // are guaranteed to be re-allocatable recursively in the same manner. Therefore the loop will
    // make progress every iteration.
    bool done = false;
    while (!done) {
        done = true;
        for (unsigned pipe_num = 0; pipe_num < registers::kPipeCount; pipe_num++) {
            auto active_alloc = active_allocation + pipe_num;
            auto goal_alloc = pipe_buffers_ + pipe_num;

            if (active_alloc->start == goal_alloc->start &&
                    active_alloc->end == goal_alloc->end) {
                continue;
            }

            // Look through all the other active pipe allocations for overlap
            bool overlap = false;
            if (goal_alloc->start != goal_alloc->end) {
                for (unsigned other_pipe = 0; other_pipe < registers::kPipeCount; other_pipe++) {
                    if (other_pipe == pipe_num) {
                        continue;
                    }

                    auto other_active = active_allocation + other_pipe;
                    if (other_active->start == other_active->end) {
                        continue;
                    }

                    if ((other_active->start <= goal_alloc->start
                                && goal_alloc->start < other_active->end)
                            || (other_active->start < goal_alloc->end
                                && goal_alloc->end <= other_active->end)) {
                        overlap = true;
                        break;
                    }
                }
            }

            if (!overlap) {
                // Flush the pipe allocation, wait for it to be active, and update
                // what is current active.
                registers::PipeRegs pipe_regs(registers::kPipes[pipe_num]);
                for (unsigned j = 0; j < registers::kImagePlaneCount; j++) {
                    pipe_regs.PlaneSurface(j).ReadFrom(mmio_space()).WriteTo(mmio_space());
                }
                pipe_regs.CursorBase().ReadFrom(mmio_space()).WriteTo(mmio_space());

                // TODO(stevensd): Wait for vsync instead of sleeping
                // TODO(stevesnd): Parallelize/reduce the number of vsyncs we wait for
                zx_nanosleep(zx_deadline_after(ZX_MSEC(33)));

                *active_alloc = *goal_alloc;
            } else {
                done = false;
            }
        }
    }
}

bool Controller::CheckDisplayLimits(const display_config_t** display_configs,
                                    size_t display_count, uint32_t** layer_cfg_results) {
    for (unsigned i = 0; i < display_count; i++) {
        const display_config_t* config = display_configs[i];

        // The intel display controller doesn't support these flags
        if (config->mode.flags
                & (MODE_FLAG_ALTERNATING_VBLANK | MODE_FLAG_DOUBLE_CLOCKED)) {
            return false;
        }

        DisplayDevice* display = FindDevice(config->display_id);
        if (display == nullptr) {
            continue;
        }

        // Pipes don't support height of more than 4096. They support a width of up to
        // 2^14 - 1. However, planes don't support a width of more than 8192 and we need
        // to always be able to accept a single plane, fullscreen configuration.
        if (config->mode.v_addressable > 4096 || config->mode.h_addressable > 8192) {
            return false;
        }

        uint64_t max_pipe_pixel_rate;
        auto cd_freq = registers::CdClockCtl::Get().ReadFrom(mmio_space()).cd_freq_decimal();
        if (cd_freq == registers::CdClockCtl::kFreqDecimal30857) {
            max_pipe_pixel_rate = 308570000;
        } else if (cd_freq == registers::CdClockCtl::kFreqDecimal3375) {
            max_pipe_pixel_rate = 337500000;
        } else if (cd_freq == registers::CdClockCtl::kFreqDecimal432) {
            max_pipe_pixel_rate = 432000000;
        } else if (cd_freq == registers::CdClockCtl::kFreqDecimal450) {
            max_pipe_pixel_rate = 450000000;
        } else if (cd_freq == registers::CdClockCtl::kFreqDecimal540) {
            max_pipe_pixel_rate = 540000000;
        } else if (cd_freq == registers::CdClockCtl::kFreqDecimal61714) {
            max_pipe_pixel_rate = 617140000;
        } else if (cd_freq == registers::CdClockCtl::kFreqDecimal675) {
            max_pipe_pixel_rate = 675000000;
        } else {
            ZX_ASSERT(false);
        }

        // Either the pipe pixel rate or the link pixel rate can't support a simple
        // configuration at this display resolution.
        if (max_pipe_pixel_rate < config->mode.pixel_clock_10khz * 10000
                || !display->CheckPixelRate(config->mode.pixel_clock_10khz * 10000)) {
            return false;
        }

        // Compute the maximum pipe pixel rate with the desired scaling. If the max rate
        // is too low, then make the client do any downscaling itself.
        double min_plane_ratio = 1.0;
        for (unsigned i = 0; i < config->layer_count; i++) {
            if (config->layer_list[i]->type != LAYER_TYPE_PRIMARY) {
                continue;
            }
            primary_layer_t* primary = &config->layer_list[i]->cfg.primary;
            uint32_t src_width, src_height;
            get_posttransform_width(*config->layer_list[i], &src_width, &src_height);

            double downscale = fbl::max(1.0, 1.0 * src_height / primary->dest_frame.height)
                    * fbl::max(1.0, 1.0 * src_width / primary->dest_frame.width);
            double plane_ratio = 1.0 / downscale;
            min_plane_ratio = fbl::min(plane_ratio, min_plane_ratio);
        }

        max_pipe_pixel_rate = static_cast<uint64_t>(
                min_plane_ratio * static_cast<double>(max_pipe_pixel_rate));
        if (max_pipe_pixel_rate < config->mode.pixel_clock_10khz * 10000) {
            for (unsigned j = 0; j < config->layer_count; j++) {
                if (config->layer_list[j]->type != LAYER_TYPE_PRIMARY) {
                    continue;
                }
                primary_layer_t* primary = &config->layer_list[j]->cfg.primary;
                uint32_t src_width, src_height;
                get_posttransform_width(*config->layer_list[j], &src_width, &src_height);

                if (src_height > primary->dest_frame.height
                        || src_width > primary->dest_frame.width) {
                    layer_cfg_results[i][j] |= CLIENT_FRAME_SCALE;
                }
            }
        }

        // TODO(stevensd): Check maximum memory read bandwidth, watermark
    }

    return true;
}

uint32_t Controller::DisplayControllerImplCheckConfiguration(
        const display_config_t** display_config, size_t display_count,
        uint32_t** layer_cfg_result, size_t* layer_cfg_result_count) {
    fbl::AutoLock lock(&display_lock_);

    if (display_count == 0) {
        // All displays off is supported
        return CONFIG_DISPLAY_OK;
    }

    uint64_t pipe_alloc[registers::kPipeCount];
    if (!CalculatePipeAllocation(display_config, display_count, pipe_alloc)) {
        return CONFIG_DISPLAY_TOO_MANY;
    }

    if (!CheckDisplayLimits(display_config, display_count, layer_cfg_result)) {
        return CONFIG_DISPLAY_UNSUPPORTED_MODES;
    }

    for (unsigned i = 0; i < display_count; i++) {
        auto* config = display_config[i];
        DisplayDevice* display = nullptr;
        for (auto& d : display_devices_) {
            if (d->id() == config->display_id) {
                display = d.get();
                break;
            }
        }
        if (display == nullptr) {
            LOG_INFO("Got config with no display - assuming hotplug and skipping\n");
            continue;
        }

        bool merge_all = false;
        if (config->layer_count > 3) {
            merge_all = config->layer_count > 4 || config->layer_list[0]->type != LAYER_TYPE_COLOR;
        }
        if (!merge_all && config->cc_flags) {
            if (config->cc_flags & COLOR_CONVERSION_PREOFFSET) {
                for (int i = 0; i < 3; i++) {
                    merge_all |= config->cc_preoffsets[i] <= -1;
                    merge_all |= config->cc_preoffsets[i] >= 1;
                }
            }
            if (config->cc_flags & COLOR_CONVERSION_POSTOFFSET) {
                for (int i = 0; i < 3; i++) {
                    merge_all |= config->cc_postoffsets[i] <= -1;
                    merge_all |= config->cc_postoffsets[i] >= 1;
                }
            }
        }

        uint32_t total_scalers_needed = 0;
        for (unsigned j = 0; j < config->layer_count; j++) {
            switch (config->layer_list[j]->type) {
            case LAYER_TYPE_PRIMARY: {
                primary_layer_t* primary = &config->layer_list[j]->cfg.primary;
                if (primary->transform_mode == FRAME_TRANSFORM_ROT_90
                        || primary->transform_mode == FRAME_TRANSFORM_ROT_270) {
                    // Linear and x tiled images don't support 90/270 rotation
                    if (primary->image.type == IMAGE_TYPE_SIMPLE
                            || primary->image.type == IMAGE_TYPE_X_TILED) {
                        layer_cfg_result[i][j] |= CLIENT_TRANSFORM;
                    }
                } else if (primary->transform_mode != FRAME_TRANSFORM_IDENTITY
                        && primary->transform_mode != FRAME_TRANSFORM_ROT_180) {
                    // Cover unsupported rotations
                    layer_cfg_result[i][j] |= CLIENT_TRANSFORM;
                }

                uint32_t src_width, src_height;
                get_posttransform_width(*config->layer_list[j], &src_width, &src_height);

                // If the plane is too wide, force the client to do all composition
                // and just give us a simple configuration.
                uint32_t max_width;
                if (primary->image.type == IMAGE_TYPE_SIMPLE
                        || primary->image.type == IMAGE_TYPE_X_TILED) {
                    max_width = 8192;
                } else {
                    max_width = 4096;
                }
                if (src_width > max_width) {
                    merge_all = true;
                }

                if (primary->dest_frame.width != src_width
                        || primary->dest_frame.height != src_height) {
                    float ratio = registers::PipeScalerCtrl::k7x5MaxRatio;
                    uint32_t max_width =
                            static_cast<uint32_t>(static_cast<float>(src_width) * ratio);
                    uint32_t max_height =
                            static_cast<uint32_t>(static_cast<float>(src_height) * ratio);
                    uint32_t scalers_needed = 1;
                    // The 7x5 scaler (i.e. 2 scaler resources) is required if the src width is
                    // >2048 and the required vertical scaling is greater than 1.99.
                    if (primary->src_frame.width > 2048) {
                        float ratio = registers::PipeScalerCtrl::kDynamicMaxVerticalRatio2049;
                        uint32_t max_dynamic_height =
                                static_cast<uint32_t>(static_cast<float>(src_height) * ratio);
                        if (max_dynamic_height < primary->dest_frame.height) {
                            scalers_needed = 2;
                        }
                    }

                    // Verify that there are enough scaler resources
                    // Verify that the scaler input isn't too large or too small
                    // Verify that the required scaling ratio isn't too large
                    bool using_c = pipe_alloc[registers::PIPE_C] == display->id();
                    if ((total_scalers_needed + scalers_needed) >
                            (using_c ? registers::PipeScalerCtrl::kPipeCScalersAvailable
                                : registers::PipeScalerCtrl::kPipeABScalersAvailable)
                            || src_width > registers::PipeScalerCtrl::kMaxSrcWidthPx
                            || src_width < registers::PipeScalerCtrl::kMinSrcSizePx
                            || src_height < registers::PipeScalerCtrl::kMinSrcSizePx
                            || max_width < primary->dest_frame.width
                            || max_height < primary->dest_frame.height) {
                        layer_cfg_result[i][j] |= CLIENT_FRAME_SCALE;
                    } else {
                        total_scalers_needed += scalers_needed;
                    }
                }
                break;
            }
            case LAYER_TYPE_CURSOR: {
                if (j != config->layer_count - 1) {
                    layer_cfg_result[i][j] |= CLIENT_USE_PRIMARY;
                }
                const image_t* image = &config->layer_list[j]->cfg.cursor.image;
                if (image->type != IMAGE_TYPE_SIMPLE) {
                    layer_cfg_result[i][j] |= CLIENT_USE_PRIMARY;
                }
                bool found = false;
                for (unsigned x = 0; x < fbl::count_of(cursor_infos) && !found; x++) {
                    found = image->width == cursor_infos[x].width
                            && image->height == cursor_infos[x].height
                            && image->pixel_format == cursor_infos[x].format;
                }
                if (!found) {
                    layer_cfg_result[i][j] |= CLIENT_USE_PRIMARY;
                }
                break;
            }
            case LAYER_TYPE_COLOR: {
                if (j != 0) {
                    layer_cfg_result[i][j] |= CLIENT_USE_PRIMARY;
                }
                zx_pixel_format_t format = config->layer_list[j]->cfg.color.format;
                if (format != ZX_PIXEL_FORMAT_RGB_x888
                        && format != ZX_PIXEL_FORMAT_ARGB_8888) {
                    layer_cfg_result[i][j] |= CLIENT_USE_PRIMARY;
                }
                break;
            }
            default:
                layer_cfg_result[i][j] |= CLIENT_USE_PRIMARY;
            }
        }

        if (merge_all) {
            layer_cfg_result[i][0] = CLIENT_MERGE_BASE;
            for (unsigned j = 1; j < config->layer_count; j++) {
                layer_cfg_result[i][j] = CLIENT_MERGE_SRC;
            }
        }
    }

    // CalculateMinimumAllocations ignores layers after kImagePlaneCount. That's fine, since
    // that case already fails from an earlier check.
    uint16_t arr[registers::kPipeCount][registers::kImagePlaneCount];
    if (!CalculateMinimumAllocations(display_config, display_count, arr)) {
        // Find any displays whose allocation fails and set the return code. Overwrite
        // any previous errors, since they get solved by the merge.
        for (unsigned pipe_num = 0; pipe_num < registers::kPipeCount; pipe_num++) {
            if (arr[pipe_num][0] != UINT16_MAX) {
                continue;
            }
            ZX_ASSERT(pipes_[pipe_num].in_use()); // If the allocation failed, it should be in use
            uint64_t display_id = pipes_[pipe_num].attached_display_id();
            for (unsigned i = 0; i < display_count; i++) {
                if (display_config[i]->display_id != display_id) {
                    continue;
                }
                layer_cfg_result[i][0] = CLIENT_MERGE_BASE;
                for (unsigned j = 1; j < display_config[i]->layer_count; j++) {
                    layer_cfg_result[i][j] = CLIENT_MERGE_SRC;
                }
                break;
            }
        }
    }

    return CONFIG_DISPLAY_OK;
}

bool Controller::CalculatePipeAllocation(const display_config_t** display_config,
                                         size_t display_count,
                                         uint64_t alloc[registers::kPipeCount]) {
    if (display_count > registers::kPipeCount) {
        return false;
    }
    memset(alloc, 0, sizeof(uint64_t) * registers::kPipeCount);
    // Keep any allocated pipes on the same display
    for (unsigned i = 0; i < display_count; i++) {
        DisplayDevice* display = FindDevice(display_config[i]->display_id);
        if (display != nullptr && display->pipe() != nullptr) {
            alloc[display->pipe()->pipe()] = display_config[i]->display_id;
        }
    }
    // Give unallocated pipes to displays that need them
    for (unsigned i = 0; i < display_count; i++) {
        DisplayDevice* display = FindDevice(display_config[i]->display_id);
        if (display != nullptr && display->pipe() == nullptr) {
            for (unsigned pipe_num = 0; pipe_num < registers::kPipeCount; pipe_num++) {
                if (!alloc[pipe_num]) {
                    alloc[pipe_num] = display_config[i]->display_id;
                    break;
                }
            }
        }
    }
    return true;
}

bool Controller::ReallocatePipes(const display_config_t** display_config, size_t display_count) {
    if (display_count == 0) {
        // If we were given an empty config, just wait until there's
        // a real config before doing anything.
        return false;
    }

    uint64_t pipe_alloc[registers::kPipeCount];
    if (!CalculatePipeAllocation(display_config, display_count, pipe_alloc)) {
        // Reallocations should only happen for validated configurations, so the
        // pipe allocation should always succeed.
        ZX_ASSERT(false);
        return false;
    }

    bool pipe_change = false;
    for (unsigned i = 0; i < display_devices_.size(); i++) {
        auto& display = display_devices_[i];
        const display_config_t* config = find_config(display->id(), display_config, display_count);

        Pipe* pipe = nullptr;
        if (config) {
            pipe = display->pipe();
            if (pipe == nullptr) {
                for (unsigned i = 0; i < registers::kPipeCount; i++) {
                    if (pipe_alloc[i] == display->id()) {
                        pipe = pipes_ + i;
                        break;
                    }
                }
            }
        }

        if (display->AttachPipe(pipe)) {
            pipe_change = true;
        }
    }

    return pipe_change;
}

void Controller::DisplayControllerImplApplyConfiguration(const display_config_t** display_config,
                                                         size_t display_count) {
    uint64_t fake_vsyncs[registers::kDdiCount];
    uint32_t fake_vsync_count = 0;

    fbl::AutoLock lock(&display_lock_);

    bool pipe_change = ReallocatePipes(display_config, display_count);
    ReallocatePlaneBuffers(display_config, display_count, pipe_change);

    for (unsigned i = 0; i < display_devices_.size(); i++) {
        auto& display = display_devices_[i];
        const display_config_t* config =
                find_config(display->id(), display_config, display_count);

        if (config != nullptr) {
            display->ApplyConfiguration(config);
        } else {
            if (display->pipe()) {
                ResetPipe(display->pipe()->pipe());
            }
        }

        // The hardware only gives vsyncs if at least one plane is enabled, so
        // fake one if we need to, to inform the client that we're done with the
        // images.
        if (!config || config->layer_count == 0) {
            fake_vsyncs[fake_vsync_count++] = display->id();
        }
    }

    if (dc_intf_.is_valid()) {
        zx_time_t now = fake_vsync_count ? zx_clock_get(ZX_CLOCK_MONOTONIC) : 0;
        for (unsigned i = 0; i < fake_vsync_count; i++) {
            dc_intf_.OnDisplayVsync(fake_vsyncs[i], now, nullptr, 0);
        }
    }
}

uint32_t Controller::DisplayControllerImplComputeLinearStride(uint32_t width,
                                                              zx_pixel_format_t format) {
    return fbl::round_up(width,
            get_tile_byte_width(IMAGE_TYPE_SIMPLE, format) / ZX_PIXEL_FORMAT_BYTES(format));
}

zx_status_t Controller::DisplayControllerImplAllocateVmo(uint64_t size, zx_handle_t* vmo_out) {
    return zx_vmo_create(size, 0, vmo_out);
}

// Intel GPU core methods

zx_status_t Controller::ReadPciConfig16(uint16_t addr, uint16_t* value_out) {
    return pci_config_read16(&pci_, addr, value_out);
}

zx_status_t Controller::MapPciMmio(uint32_t pci_bar, void** addr_out, uint64_t* size_out) {
    if (pci_bar > PCI_MAX_BAR_COUNT) {
        return ZX_ERR_INVALID_ARGS;
    }
    fbl::AutoLock lock(&bar_lock_);
    if (mapped_bars_[pci_bar].count == 0) {
        zx_status_t status = pci_map_bar_buffer(&pci_, pci_bar, ZX_CACHE_POLICY_UNCACHED_DEVICE,
                                                &mapped_bars_[pci_bar].mmio);
        if (status != ZX_OK) {
            return status;
        }
    }
    *addr_out = mapped_bars_[pci_bar].mmio.vaddr;
    *size_out = mapped_bars_[pci_bar].mmio.size;
    mapped_bars_[pci_bar].count++;
    return ZX_OK;
}

zx_status_t Controller::UnmapPciMmio(uint32_t pci_bar) {
    if (pci_bar > PCI_MAX_BAR_COUNT) {
        return ZX_ERR_INVALID_ARGS;
    }
    fbl::AutoLock lock(&bar_lock_);
    if (mapped_bars_[pci_bar].count == 0) {
        return ZX_OK;
    }
    if (--mapped_bars_[pci_bar].count == 0) {
        mmio_buffer_release(&mapped_bars_[pci_bar].mmio);
    }
    return ZX_OK;
}

zx_status_t Controller::GetPciBti(uint32_t index, zx_handle_t* bti_out) {
    return pci_get_bti(&pci_, index, bti_out);
}

zx_status_t Controller::RegisterInterruptCallback(const zx_intel_gpu_core_interrupt_t* callback,
                                                  uint32_t interrupt_mask) {
    return interrupts_.SetInterruptCallback(callback, interrupt_mask);
}

zx_status_t Controller::UnregisterInterruptCallback() {
    constexpr zx_intel_gpu_core_interrupt_t kNoCallback = {nullptr, nullptr};
    interrupts_.SetInterruptCallback(&kNoCallback, 0);
    return ZX_OK;
}

uint64_t Controller::GttGetSize() {
    fbl::AutoLock lock(&gtt_lock_);
    return gtt_.size();
}

zx_status_t Controller::GttAlloc(uint64_t page_count, uint64_t* addr_out) {
    uint64_t length = page_count * PAGE_SIZE;
    fbl::AutoLock lock(&gtt_lock_);
    if (length > gtt_.size()) {
        return ZX_ERR_INVALID_ARGS;
    }
    fbl::unique_ptr<GttRegion> region;
    zx_status_t status = gtt_.AllocRegion(static_cast<uint32_t>(page_count * PAGE_SIZE),
                                          PAGE_SIZE, &region);
    if (status != ZX_OK) {
        return status;
    }
    *addr_out = region->base();

    imported_gtt_regions_.push_back(fbl::move(region));
    return ZX_OK;
}

zx_status_t Controller::GttFree(uint64_t addr) {
    fbl::AutoLock lock(&gtt_lock_);
    for (unsigned i = 0; i < imported_gtt_regions_.size(); i++) {
        if (imported_gtt_regions_[i]->base() == addr) {
            imported_gtt_regions_.erase(i)->ClearRegion(true);
            return ZX_OK;
        }
    }
    return ZX_ERR_INVALID_ARGS;
}

zx_status_t Controller::GttClear(uint64_t addr) {
    fbl::AutoLock lock(&gtt_lock_);
    for (unsigned i = 0; i < imported_gtt_regions_.size(); i++) {
        if (imported_gtt_regions_[i]->base() == addr) {
            imported_gtt_regions_[i]->ClearRegion(true);
            return ZX_OK;
        }
    }
    return ZX_ERR_INVALID_ARGS;
}

zx_status_t Controller::GttInsert(uint64_t addr, zx_handle_t buffer,
                                  uint64_t page_offset, uint64_t page_count) {
    fbl::AutoLock lock(&gtt_lock_);
    for (unsigned i = 0; i < imported_gtt_regions_.size(); i++) {
        if (imported_gtt_regions_[i]->base() == addr) {
            return imported_gtt_regions_[i]->PopulateRegion(buffer, page_offset,
                                                            page_count * PAGE_SIZE,
                                                            true /* writable */);
        }
    }
    return ZX_ERR_INVALID_ARGS;
}

void Controller::GpuRelease() {
    gpu_released_ = true;
    if (display_released_) {
        delete this;
    }
}

// I2C methods

uint32_t Controller::GetBusCount() {
    return registers::kDdiCount * 2;
}

static constexpr size_t kMaxTxSize = 255;
zx_status_t Controller::GetMaxTransferSize(uint32_t bus_id, size_t* out_size) {
    *out_size = kMaxTxSize;
    return ZX_OK;
}

zx_status_t Controller::SetBitrate(uint32_t bus_id, uint32_t bitrate) {
    // no-op for now
    return ZX_OK;
}

zx_status_t Controller::Transact(uint32_t bus_id, const i2c_impl_op_t* ops, size_t count) {
    for (unsigned i = 0; i < count; i++) {
        if (ops[i].data_size > kMaxTxSize) {
            return ZX_ERR_INVALID_ARGS;
        }
    }
    if (!ops[count - 1].stop) {
        return ZX_ERR_INVALID_ARGS;
    }

    if (bus_id < registers::kDdiCount) {
        return gmbus_i2cs_[bus_id].I2cTransact(ops, count);
    } else if (bus_id < 2 * registers::kDdiCount) {
        bus_id -= registers::kDdiCount;
        return dp_auxs_[bus_id].I2cTransact(ops, count);
    } else {
        return ZX_ERR_NOT_FOUND;
    }
}

bool Controller::DpcdRead(registers::Ddi ddi, uint32_t addr, uint8_t* buf, size_t size) {
    return dp_auxs_[ddi].DpcdRead(addr, buf, size);
}

bool Controller::DpcdWrite(registers::Ddi ddi, uint32_t addr, const uint8_t* buf, size_t size) {
    return dp_auxs_[ddi].DpcdWrite(addr, buf, size);
}

// Ddk methods

void Controller::DdkUnbind() {
    device_remove(zxdev());
    device_remove(zx_gpu_dev_);

    fbl::AutoLock lock(&display_lock_);
    display_devices_.reset();
}

void Controller::DdkRelease() {
    display_released_ = true;
    if (gpu_released_) {
        delete this;
    }
}

zx_status_t Controller::DdkGetProtocol(uint32_t proto_id, void* out) {
    if (proto_id == ZX_PROTOCOL_DISPLAY_CONTROLLER_IMPL) {
        auto ops = static_cast<display_controller_impl_protocol_t*>(out);
        ops->ctx = this;
        ops->ops = static_cast<display_controller_impl_protocol_ops_t*>(ddk_proto_ops_);
    } else if (proto_id == ZX_PROTOCOL_I2C_IMPL) {
        auto ops = static_cast<i2c_impl_protocol_t*>(out);
        ops->ctx = this;
        ops->ops = &i2c_ops;
    } else {
        return ZX_ERR_NOT_SUPPORTED;
    }
    return ZX_OK;
}

zx_status_t Controller::DdkSuspend(uint32_t hint) {
    if ((hint & DEVICE_SUSPEND_REASON_MASK) == DEVICE_SUSPEND_FLAG_MEXEC) {
        uint32_t format, width, height, stride;
        if (zx_framebuffer_get_info(get_root_resource(), &format, &width,
                                    &height, &stride) != ZX_OK) {
            return ZX_OK;
        }

        // The bootloader framebuffer is most likely at the start of the display
        // controller's bar 2. Try to get that buffer working again across the
        // mexec by mapping gfx stolen memory to gaddr 0.

        auto bdsm_reg = registers::BaseDsm::Get().FromValue(0);
        zx_status_t status =
                pci_config_read32(&pci_, bdsm_reg.kAddr, bdsm_reg.reg_value_ptr());
        if (status != ZX_OK) {
            LOG_TRACE("Failed to read dsm base\n");
            return ZX_OK;
        }

        // The Intel docs say that the first page should be reserved for the gfx
        // hardware, but a lot of BIOSes seem to ignore that.
        uintptr_t fb = bdsm_reg.base_phys_addr() << bdsm_reg.base_phys_addr_shift;
        uint32_t fb_size = stride * height * ZX_PIXEL_FORMAT_BYTES(format);

        {
            fbl::AutoLock lock(&gtt_lock_);
            gtt_.SetupForMexec(fb, fb_size);
        }

        // Try to map the framebuffer and clear it. If not, oh well.
        mmio_buffer_t mmio;
        if (pci_map_bar_buffer(&pci_, 2, ZX_CACHE_POLICY_WRITE_COMBINING, &mmio) == ZX_OK) {
            memset(mmio.vaddr, 0, fb_size);
            mmio_buffer_release(&mmio);
        }

        {
            fbl::AutoLock lock(&display_lock_);
            for (auto& display : display_devices_) {
                if (display->pipe() == nullptr) {
                    continue;
                }
                // TODO(ZX-1413): Reset/scale the display to ensure the buffer displays properly
                registers::PipeRegs pipe_regs(display->pipe()->pipe());

                auto plane_stride = pipe_regs.PlaneSurfaceStride(0).ReadFrom(mmio_space());
                plane_stride.set_stride(width_in_tiles(IMAGE_TYPE_SIMPLE, width, format));
                plane_stride.WriteTo(mmio_space());

                auto plane_surface = pipe_regs.PlaneSurface(0).ReadFrom(mmio_space());
                plane_surface.set_surface_base_addr(0);
                plane_surface.WriteTo(mmio_space());
            }
        }
    }
    return ZX_OK;
}

zx_status_t Controller::DdkResume(uint32_t hint) {
    fbl::AutoLock lock(&display_lock_);
    BringUpDisplayEngine(true);

    registers::PanelPowerDivisor::Get().FromValue(pp_divisor_val_).WriteTo(mmio_space());
    registers::PanelPowerOffDelay::Get().FromValue(pp_off_delay_val_).WriteTo(mmio_space());
    registers::PanelPowerOnDelay::Get().FromValue(pp_on_delay_val_).WriteTo(mmio_space());
    registers::SouthBacklightCtl1::Get().FromValue(0)
            .set_polarity(sblc_polarity_).WriteTo(mmio_space());
    registers::SouthBacklightCtl2::Get().FromValue(sblc_ctrl2_val_).WriteTo(mmio_space());
    registers::SChicken1::Get().FromValue(schicken1_val_).WriteTo(mmio_space());

    registers::DdiRegs(registers::DDI_A).DdiBufControl().ReadFrom(mmio_space())
            .set_ddi_a_lane_capability_control(ddi_a_lane_capability_control_)
            .WriteTo(mmio_space());

    for (auto& disp : display_devices_) {
        if (!disp->Resume()) {
            LOG_ERROR("Failed to resume display\n");
        }
    }

    interrupts_.Resume();

    return ZX_OK;
}

// TODO(stevensd): Move this back into ::Bind once long-running binds don't
// break devmgr's suspend/mexec.
void Controller::FinishInit() {
    LOG_TRACE("i915: initializing displays\n");

    for (auto& pipe : pipes_) {
        pipe.Init();
    }

    InitDisplays();

    {
        fbl::AutoLock lock(&display_lock_);
        uint32_t size = static_cast<uint32_t>(display_devices_.size());
        if (size && dc_intf_.is_valid()) {
            DisplayDevice* added_displays[registers::kDdiCount];
            for (unsigned i = 0; i < size; i++) {
                added_displays[i] = display_devices_[i].get();
            }
            CallOnDisplaysChanged(added_displays, size, NULL, 0);
        }

        ready_for_callback_ = true;
    }

    interrupts_.FinishInit();

    // TODO remove when the gfxconsole moves to user space
    EnableBacklight(true);

    LOG_TRACE("i915: initialization done\n");
}

zx_status_t Controller::Bind(fbl::unique_ptr<i915::Controller>* controller_ptr) {
    LOG_TRACE("Binding to display controller\n");

    if (device_get_protocol(parent_, ZX_PROTOCOL_PCI, &pci_)) {
        return ZX_ERR_NOT_SUPPORTED;
    }

    pci_config_read16(&pci_, PCI_CONFIG_DEVICE_ID, &device_id_);
    LOG_TRACE("Device id %x\n", device_id_);
    if (device_id_ == INTEL_I915_BROADWELL_DID) {
        // TODO: this should be based on the specific target
        flags_ |= FLAGS_BACKLIGHT;
    }

    zx_status_t status = igd_opregion_.Init(&pci_);
    if (status != ZX_OK) {
        LOG_ERROR("Failed to init VBT (%d)\n", status);
        return status;
    }

    LOG_TRACE("Mapping registers\n");
    // map register window
    void* regs;
    uint64_t size;
    status = MapPciMmio(0u, &regs, &size);
    if (status != ZX_OK) {
        LOG_ERROR("Failed to map bar 0: %d\n", status);
        return status;
    }

    {
        fbl::AutoLock lock(&bar_lock_);
        fbl::AllocChecker ac;
        mmio_space_ = ddk::MmioBuffer(mapped_bars_[0].mmio);
    }

    for (unsigned i = 0; i < registers::kDdiCount; i++) {
        gmbus_i2cs_[i].set_mmio_space(mmio_space());
        dp_auxs_[i].set_mmio_space(mmio_space());
    }

    pp_divisor_val_ = registers::PanelPowerDivisor::Get().ReadFrom(mmio_space()).reg_value();
    pp_off_delay_val_ =
            registers::PanelPowerOffDelay::Get().ReadFrom(mmio_space()).reg_value();
    pp_on_delay_val_  = registers::PanelPowerOnDelay::Get().ReadFrom(mmio_space()).reg_value();
    sblc_ctrl2_val_ = registers::SouthBacklightCtl2::Get().ReadFrom(mmio_space()).reg_value();
    schicken1_val_ = registers::SChicken1::Get().ReadFrom(mmio_space()).reg_value();

    sblc_polarity_ = registers::SouthBacklightCtl1::Get().ReadFrom(mmio_space()).polarity();
    ddi_a_lane_capability_control_ = registers::DdiRegs(registers::DDI_A).DdiBufControl()
            .ReadFrom(mmio_space()).ddi_a_lane_capability_control();

    LOG_TRACE("Initialzing hotplug\n");
    status = interrupts_.Init(this);
    if (status != ZX_OK) {
        LOG_ERROR("Failed to init hotplugging\n");
        return status;
    }

    LOG_TRACE("Mapping gtt\n");
    {
        fbl::AutoLock lock(&gtt_lock_);
        if ((status = gtt_.Init(this)) != ZX_OK) {
            LOG_ERROR("Failed to init gtt (%d)\n", status);
            return status;
        }
    }

    status = DdkAdd("intel_i915");
    if (status != ZX_OK) {
        LOG_ERROR("Failed to add controller device\n");
        return status;
    }
    // DevMgr now owns this pointer, release it to avoid destroying the object
    // when device goes out of scope.
    __UNUSED auto ptr = controller_ptr->release();

    i915_gpu_core_device_proto.version = DEVICE_OPS_VERSION;
    i915_gpu_core_device_proto.release = gpu_release;
    // zx_gpu_dev_ is removed when unbind is called for zxdev() (in ::DdkUnbind),
    // so it's not necessary to give it its own unbind method.

    device_add_args_t args = {};
    args.version = DEVICE_ADD_ARGS_VERSION;
    args.name = "intel-gpu-core";
    args.ctx = this;
    args.ops = &i915_gpu_core_device_proto;
    args.proto_id = ZX_PROTOCOL_INTEL_GPU_CORE;
    args.proto_ops = &i915_gpu_core_protocol_ops;
    status = device_add(zxdev(), &args, &zx_gpu_dev_);
    if (status != ZX_OK) {
        LOG_ERROR("Failed to publish gpu core device (%d)\n", status);
        device_remove(zxdev());
        return status;
    }

    LOG_TRACE("bind done\n");

    thrd_t init_thread;
    status = thrd_create_with_name(&init_thread, finish_init, this, "i915-init-thread");
    if (status != ZX_OK) {
        LOG_ERROR("Failed to create init thread\n");
        device_remove(zxdev());
        return status;
    }
    init_thrd_started_ = true;

    return ZX_OK;
}

Controller::Controller(zx_device_t* parent)
    : DeviceType(parent), power_(this) {
    mtx_init(&display_lock_, mtx_plain);
    mtx_init(&gtt_lock_, mtx_plain);
    mtx_init(&bar_lock_, mtx_plain);
}

Controller::~Controller() {
    if (init_thrd_started_) {
        thrd_join(init_thread_, nullptr);
    }

    interrupts_.Destroy();
    if (mmio_space()) {
        EnableBacklight(false);

        for (unsigned i = 0; i < registers::kPipeCount; i++) {
            fbl::AutoLock lock(&display_lock_);
            pipes_[i].Reset();
        }
    }
    // Drop our own reference to bar 0. No-op if we failed before we mapped it.
    mmio_space_->reset();
    UnmapPciMmio(0u);
    // Release anything leaked by the gpu-core client.
    fbl::AutoLock lock(&bar_lock_);
    for (unsigned i = 0; i < PCI_MAX_BAR_COUNT; i++) {
        if (mapped_bars_[i].count) {
            LOG_INFO("Leaked bar %d\n", i);
            mapped_bars_[i].count = 1;
            UnmapPciMmio(i);
        }
    }
}

} // namespace i915

zx_status_t intel_i915_bind(void* ctx, zx_device_t* parent) {
    fbl::AllocChecker ac;
    fbl::unique_ptr<i915::Controller> controller(new (&ac) i915::Controller(parent));
    if (!ac.check()) {
        return ZX_ERR_NO_MEMORY;
    }

    return controller->Bind(&controller);
}
