// SPDX-License-Identifier: MIT
/*
 * Copyright © 2023 Intel Corporation
 */

#include <linux/pci.h>
#include <linux/pnp.h>
#include <linux/vgaarb.h>

#include <drm/drm_managed.h>
#include <drm/intel/i915_drm.h>

#include "../display/intel_display_core.h" /* FIXME */

#include "i915_drv.h"
#include "intel_gmch.h"
#include "intel_pci_config.h"

static void intel_gmch_bridge_release(struct drm_device *dev, void *bridge)
{
	pci_dev_put(bridge);
}

int intel_gmch_bridge_setup(struct drm_i915_private *i915)
{
	int domain = pci_domain_nr(to_pci_dev(i915->drm.dev)->bus);

	i915->gmch.pdev = pci_get_domain_bus_and_slot(domain, 0, PCI_DEVFN(0, 0));
	if (!i915->gmch.pdev) {
		drm_err(&i915->drm, "bridge device not found\n");
		return -EIO;
	}

	return drmm_add_action_or_reset(&i915->drm, intel_gmch_bridge_release,
					i915->gmch.pdev);
}

static int mchbar_reg(struct drm_i915_private *i915)
{
	return GRAPHICS_VER(i915) >= 4 ? MCHBAR_I965 : MCHBAR_I915;
}

/* Allocate space for the MCH regs if needed, return nonzero on error */
static int
intel_alloc_mchbar_resource(struct drm_i915_private *i915)
{
	u32 temp_lo, temp_hi = 0;
	u64 mchbar_addr;
	int ret;

	if (GRAPHICS_VER(i915) >= 4)
		pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915) + 4, &temp_hi);
	pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915), &temp_lo);
	mchbar_addr = ((u64)temp_hi << 32) | temp_lo;

	/* If ACPI doesn't have it, assume we need to allocate it ourselves */
	if (IS_ENABLED(CONFIG_PNP) && mchbar_addr &&
	    pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE))
		return 0;

	/* Get some space for it */
	i915->gmch.mch_res.name = "i915 MCHBAR";
	i915->gmch.mch_res.flags = IORESOURCE_MEM;
	ret = pci_bus_alloc_resource(i915->gmch.pdev->bus,
				     &i915->gmch.mch_res,
				     MCHBAR_SIZE, MCHBAR_SIZE,
				     PCIBIOS_MIN_MEM,
				     0, pcibios_align_resource,
				     i915->gmch.pdev);
	if (ret) {
		drm_dbg(&i915->drm, "failed bus alloc: %d\n", ret);
		i915->gmch.mch_res.start = 0;
		return ret;
	}

	if (GRAPHICS_VER(i915) >= 4)
		pci_write_config_dword(i915->gmch.pdev, mchbar_reg(i915) + 4,
				       upper_32_bits(i915->gmch.mch_res.start));

	pci_write_config_dword(i915->gmch.pdev, mchbar_reg(i915),
			       lower_32_bits(i915->gmch.mch_res.start));
	return 0;
}

/* Setup MCHBAR if possible, return true if we should disable it again */
void intel_gmch_bar_setup(struct drm_i915_private *i915)
{
	u32 temp;
	bool enabled;

	if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
		return;

	i915->gmch.mchbar_need_disable = false;

	if (IS_I915G(i915) || IS_I915GM(i915)) {
		pci_read_config_dword(i915->gmch.pdev, DEVEN, &temp);
		enabled = !!(temp & DEVEN_MCHBAR_EN);
	} else {
		pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915), &temp);
		enabled = temp & 1;
	}

	/* If it's already enabled, don't have to do anything */
	if (enabled)
		return;

	if (intel_alloc_mchbar_resource(i915))
		return;

	i915->gmch.mchbar_need_disable = true;

	/* Space is allocated or reserved, so enable it. */
	if (IS_I915G(i915) || IS_I915GM(i915)) {
		pci_write_config_dword(i915->gmch.pdev, DEVEN,
				       temp | DEVEN_MCHBAR_EN);
	} else {
		pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915), &temp);
		pci_write_config_dword(i915->gmch.pdev, mchbar_reg(i915), temp | 1);
	}
}

void intel_gmch_bar_teardown(struct drm_i915_private *i915)
{
	if (i915->gmch.mchbar_need_disable) {
		if (IS_I915G(i915) || IS_I915GM(i915)) {
			u32 deven_val;

			pci_read_config_dword(i915->gmch.pdev, DEVEN,
					      &deven_val);
			deven_val &= ~DEVEN_MCHBAR_EN;
			pci_write_config_dword(i915->gmch.pdev, DEVEN,
					       deven_val);
		} else {
			u32 mchbar_val;

			pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915),
					      &mchbar_val);
			mchbar_val &= ~1;
			pci_write_config_dword(i915->gmch.pdev, mchbar_reg(i915),
					       mchbar_val);
		}
	}

	if (i915->gmch.mch_res.start)
		release_resource(&i915->gmch.mch_res);
}

int intel_gmch_vga_set_state(struct drm_i915_private *i915, bool enable_decode)
{
	unsigned int reg = DISPLAY_VER(i915) >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL;
	u16 gmch_ctrl;

	if (pci_read_config_word(i915->gmch.pdev, reg, &gmch_ctrl)) {
		drm_err(&i915->drm, "failed to read control word\n");
		return -EIO;
	}

	if (!!(gmch_ctrl & INTEL_GMCH_VGA_DISABLE) == !enable_decode)
		return 0;

	if (enable_decode)
		gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE;
	else
		gmch_ctrl |= INTEL_GMCH_VGA_DISABLE;

	if (pci_write_config_word(i915->gmch.pdev, reg, gmch_ctrl)) {
		drm_err(&i915->drm, "failed to write control word\n");
		return -EIO;
	}

	return 0;
}

unsigned int intel_gmch_vga_set_decode(struct pci_dev *pdev, bool enable_decode)
{
	struct drm_i915_private *i915 = pdev_to_i915(pdev);

	intel_gmch_vga_set_state(i915, enable_decode);

	if (enable_decode)
		return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
		       VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
	else
		return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
}
