Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 44834a67 authored by Chris Wilson's avatar Chris Wilson
Browse files

drm/i915: Use the VBT from OpRegion when available (v3)



It is recommended that we use the Video BIOS tables that were copied
into the OpRegion during POST when initialising the driver. This saves
us from having to furtle around inside the ROM ourselves and possibly
allows the vBIOS to adjust the tables prior to initialisation.

On some systems, such as the Samsung N210, there is no accessible VBIOS
and the only means of finding the VBT is through the OpRegion.

v2: Rearrange the code so that ASLE is enabled along with ACPI
v3: Enable OpRegion parsing even without ACPI

Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Matthew Garrett <mjg@redhat.com>
parent 3b617967
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -26,13 +26,13 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
	  intel_dvo.o \
	  intel_ringbuffer.o \
	  intel_overlay.o \
	  intel_opregion.o \
	  dvo_ch7xxx.o \
	  dvo_ch7017.o \
	  dvo_ivch.o \
	  dvo_tfp410.o \
	  dvo_sil164.o

i915-$(CONFIG_ACPI)	+= intel_opregion.o
i915-$(CONFIG_COMPAT)   += i915_ioc32.o

obj-$(CONFIG_DRM_I915)  += i915.o
+21 −0
Original line number Diff line number Diff line
@@ -718,6 +718,26 @@ static int i915_gfxec(struct seq_file *m, void *unused)
	return 0;
}

static int i915_opregion(struct seq_file *m, void *unused)
{
	struct drm_info_node *node = (struct drm_info_node *) m->private;
	struct drm_device *dev = node->minor->dev;
	drm_i915_private_t *dev_priv = dev->dev_private;
	struct intel_opregion *opregion = &dev_priv->opregion;
	int ret;

	ret = mutex_lock_interruptible(&dev->struct_mutex);
	if (ret)
		return ret;

	if (opregion->header)
		seq_write(m, opregion->header, OPREGION_SIZE);

	mutex_unlock(&dev->struct_mutex);

	return 0;
}

static int
i915_wedged_open(struct inode *inode,
		 struct file *filp)
@@ -845,6 +865,7 @@ static struct drm_info_list i915_debugfs_list[] = {
	{"i915_gfxec", i915_gfxec, 0},
	{"i915_fbc_status", i915_fbc_status, 0},
	{"i915_sr_status", i915_sr_status, 0},
	{"i915_opregion", i915_opregion, 0},
};
#define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)

+7 −2
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#include <linux/pnp.h>
#include <linux/vga_switcheroo.h>
#include <linux/slab.h>
#include <acpi/video.h>

extern int intel_max_stolen; /* from AGP driver */

@@ -2166,6 +2167,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)

	/* Try to make sure MCHBAR is enabled before poking at it */
	intel_setup_mchbar(dev);
	intel_opregion_setup(dev);

	i915_gem_load(dev);

@@ -2221,7 +2223,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
	}

	/* Must be done after probing outputs */
	intel_opregion_init(dev, 0);
	intel_opregion_init(dev);
	acpi_video_register();

	setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed,
		    (unsigned long) dev);
@@ -2271,6 +2274,8 @@ int i915_driver_unload(struct drm_device *dev)
		dev_priv->mm.gtt_mtrr = -1;
	}

	acpi_video_unregister();

	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
		intel_modeset_cleanup(dev);

@@ -2299,7 +2304,7 @@ int i915_driver_unload(struct drm_device *dev)
	if (dev_priv->regs != NULL)
		iounmap(dev_priv->regs);

	intel_opregion_free(dev, 0);
	intel_opregion_fini(dev);

	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
		/* Flush any outstanding unpin_work. */
+4 −3
Original line number Diff line number Diff line
@@ -236,7 +236,7 @@ static int i915_drm_freeze(struct drm_device *dev)

	i915_save_state(dev);

	intel_opregion_free(dev, 1);
	intel_opregion_fini(dev);

	/* Modeset on resume, not lid events */
	dev_priv->modeset_on_lid = 0;
@@ -276,8 +276,7 @@ static int i915_drm_thaw(struct drm_device *dev)
	int error = 0;

	i915_restore_state(dev);

	intel_opregion_init(dev, 1);
	intel_opregion_setup(dev);

	/* KMS EnterVT equivalent */
	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
@@ -293,6 +292,8 @@ static int i915_drm_thaw(struct drm_device *dev)
		drm_helper_resume_force_mode(dev);
	}

	intel_opregion_init(dev);

	dev_priv->modeset_on_lid = 0;

	return error;
+8 −6
Original line number Diff line number Diff line
@@ -110,8 +110,9 @@ struct intel_opregion {
	struct opregion_acpi *acpi;
	struct opregion_swsci *swsci;
	struct opregion_asle *asle;
	int enabled;
	void *vbt;
};
#define OPREGION_SIZE            (8*1024)

struct intel_overlay;
struct intel_overlay_error_state;
@@ -1053,16 +1054,17 @@ extern int i915_restore_state(struct drm_device *dev);
extern int i915_save_state(struct drm_device *dev);
extern int i915_restore_state(struct drm_device *dev);

#ifdef CONFIG_ACPI
/* intel_opregion.c */
extern int intel_opregion_init(struct drm_device *dev, int resume);
extern void intel_opregion_free(struct drm_device *dev, int suspend);
extern int intel_opregion_setup(struct drm_device *dev);
#ifdef CONFIG_ACPI
extern void intel_opregion_init(struct drm_device *dev);
extern void intel_opregion_fini(struct drm_device *dev);
extern void intel_opregion_asle_intr(struct drm_device *dev);
extern void intel_opregion_gse_intr(struct drm_device *dev);
extern void intel_opregion_enable_asle(struct drm_device *dev);
#else
static inline int intel_opregion_init(struct drm_device *dev, int resume) { return 0; }
static inline void intel_opregion_free(struct drm_device *dev, int suspend) { return; }
static inline void intel_opregion_init(struct drm_device *dev) { return; }
static inline void intel_opregion_fini(struct drm_device *dev) { return; }
static inline void intel_opregion_asle_intr(struct drm_device *dev) { return; }
static inline void intel_opregion_gse_intr(struct drm_device *dev) { return; }
static inline void intel_opregion_enable_asle(struct drm_device *dev) { return; }
Loading