drm/i915: Rename i915_opregion.c to intel_opregion.c
authorChris Wilson <chris@chris-wilson.co.uk>
Tue, 24 Aug 2010 08:02:58 +0000 (09:02 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Wed, 8 Sep 2010 09:13:31 +0000 (10:13 +0100)
It's part of the generic Intel driver infrastructure so rename it in
prepreparation for using it for VBT.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_opregion.c [deleted file]
drivers/gpu/drm/i915/intel_opregion.c [new file with mode: 0644]

index 5c8e53458edbfee1c37e54b7b982d49e747d563e..345ca52d6e84d915b975bf8e9c7d3573eae172ee 100644 (file)
@@ -32,7 +32,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
          dvo_tfp410.o \
          dvo_sil164.o
 
-i915-$(CONFIG_ACPI)    += i915_opregion.o
+i915-$(CONFIG_ACPI)    += intel_opregion.o
 i915-$(CONFIG_COMPAT)   += i915_ioc32.o
 
 obj-$(CONFIG_DRM_I915)  += i915.o
index 04aada08a6f937f65d7a022667913d0198f9b7ad..980061ff5c80bf37b39eaf16f3576f8143ebc891 100644 (file)
@@ -1054,18 +1054,18 @@ extern int i915_save_state(struct drm_device *dev);
 extern int i915_restore_state(struct drm_device *dev);
 
 #ifdef CONFIG_ACPI
-/* i915_opregion.c */
+/* 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 void opregion_asle_intr(struct drm_device *dev);
-extern void ironlake_opregion_gse_intr(struct drm_device *dev);
-extern void opregion_enable_asle(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 opregion_asle_intr(struct drm_device *dev) { return; }
-static inline void ironlake_opregion_gse_intr(struct drm_device *dev) { return; }
-static inline void opregion_enable_asle(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; }
 #endif
 
 /* modesetting */
index 59457e83b011aa3bbac119faf6836a66df7affa5..3afd6e5662d189e95112f59133330bc3acf3abba 100644 (file)
@@ -347,7 +347,7 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
 
 
        if (de_iir & DE_GSE)
-               ironlake_opregion_gse_intr(dev);
+               intel_opregion_gse_intr(dev);
 
        if (de_iir & DE_PLANEA_FLIP_DONE) {
                intel_prepare_page_flip(dev, 0);
@@ -1065,7 +1065,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
                if ((pipea_stats & PIPE_LEGACY_BLC_EVENT_STATUS) ||
                    (pipeb_stats & PIPE_LEGACY_BLC_EVENT_STATUS) ||
                    (iir & I915_ASLE_INTERRUPT))
-                       opregion_asle_intr(dev);
+                       intel_opregion_asle_intr(dev);
 
                /* With MSI, interrupts are only generated when iir
                 * transitions from zero to nonzero.  If another bit got
@@ -1252,7 +1252,7 @@ void i915_enable_interrupt (struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        if (!HAS_PCH_SPLIT(dev))
-               opregion_enable_asle(dev);
+               intel_opregion_enable_asle(dev);
        dev_priv->irq_enabled = 1;
 }
 
@@ -1570,7 +1570,7 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
                I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
        }
 
-       opregion_enable_asle(dev);
+       intel_opregion_enable_asle(dev);
 
        return 0;
 }
diff --git a/drivers/gpu/drm/i915/i915_opregion.c b/drivers/gpu/drm/i915/i915_opregion.c
deleted file mode 100644 (file)
index ea5d3fe..0000000
+++ /dev/null
@@ -1,562 +0,0 @@
-/*
- * Copyright 2008 Intel Corporation <hong.liu@intel.com>
- * Copyright 2008 Red Hat <mjg@redhat.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT.  IN NO EVENT SHALL INTEL AND/OR ITS SUPPLIERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-
-#include <linux/acpi.h>
-#include <acpi/video.h>
-
-#include "drmP.h"
-#include "i915_drm.h"
-#include "i915_drv.h"
-
-#define PCI_ASLE 0xe4
-#define PCI_LBPC 0xf4
-#define PCI_ASLS 0xfc
-
-#define OPREGION_SZ            (8*1024)
-#define OPREGION_HEADER_OFFSET 0
-#define OPREGION_ACPI_OFFSET   0x100
-#define OPREGION_SWSCI_OFFSET  0x200
-#define OPREGION_ASLE_OFFSET   0x300
-#define OPREGION_VBT_OFFSET    0x1000
-
-#define OPREGION_SIGNATURE "IntelGraphicsMem"
-#define MBOX_ACPI      (1<<0)
-#define MBOX_SWSCI     (1<<1)
-#define MBOX_ASLE      (1<<2)
-
-struct opregion_header {
-       u8 signature[16];
-       u32 size;
-       u32 opregion_ver;
-       u8 bios_ver[32];
-       u8 vbios_ver[16];
-       u8 driver_ver[16];
-       u32 mboxes;
-       u8 reserved[164];
-} __attribute__((packed));
-
-/* OpRegion mailbox #1: public ACPI methods */
-struct opregion_acpi {
-       u32 drdy;       /* driver readiness */
-       u32 csts;       /* notification status */
-       u32 cevt;       /* current event */
-       u8 rsvd1[20];
-       u32 didl[8];    /* supported display devices ID list */
-       u32 cpdl[8];    /* currently presented display list */
-       u32 cadl[8];    /* currently active display list */
-       u32 nadl[8];    /* next active devices list */
-       u32 aslp;       /* ASL sleep time-out */
-       u32 tidx;       /* toggle table index */
-       u32 chpd;       /* current hotplug enable indicator */
-       u32 clid;       /* current lid state*/
-       u32 cdck;       /* current docking state */
-       u32 sxsw;       /* Sx state resume */
-       u32 evts;       /* ASL supported events */
-       u32 cnot;       /* current OS notification */
-       u32 nrdy;       /* driver status */
-       u8 rsvd2[60];
-} __attribute__((packed));
-
-/* OpRegion mailbox #2: SWSCI */
-struct opregion_swsci {
-       u32 scic;       /* SWSCI command|status|data */
-       u32 parm;       /* command parameters */
-       u32 dslp;       /* driver sleep time-out */
-       u8 rsvd[244];
-} __attribute__((packed));
-
-/* OpRegion mailbox #3: ASLE */
-struct opregion_asle {
-       u32 ardy;       /* driver readiness */
-       u32 aslc;       /* ASLE interrupt command */
-       u32 tche;       /* technology enabled indicator */
-       u32 alsi;       /* current ALS illuminance reading */
-       u32 bclp;       /* backlight brightness to set */
-       u32 pfit;       /* panel fitting state */
-       u32 cblv;       /* current brightness level */
-       u16 bclm[20];   /* backlight level duty cycle mapping table */
-       u32 cpfm;       /* current panel fitting mode */
-       u32 epfm;       /* enabled panel fitting modes */
-       u8 plut[74];    /* panel LUT and identifier */
-       u32 pfmb;       /* PWM freq and min brightness */
-       u8 rsvd[102];
-} __attribute__((packed));
-
-/* ASLE irq request bits */
-#define ASLE_SET_ALS_ILLUM     (1 << 0)
-#define ASLE_SET_BACKLIGHT     (1 << 1)
-#define ASLE_SET_PFIT          (1 << 2)
-#define ASLE_SET_PWM_FREQ      (1 << 3)
-#define ASLE_REQ_MSK           0xf
-
-/* response bits of ASLE irq request */
-#define ASLE_ALS_ILLUM_FAILED  (1<<10)
-#define ASLE_BACKLIGHT_FAILED  (1<<12)
-#define ASLE_PFIT_FAILED       (1<<14)
-#define ASLE_PWM_FREQ_FAILED   (1<<16)
-
-/* ASLE backlight brightness to set */
-#define ASLE_BCLP_VALID                (1<<31)
-#define ASLE_BCLP_MSK          (~(1<<31))
-
-/* ASLE panel fitting request */
-#define ASLE_PFIT_VALID         (1<<31)
-#define ASLE_PFIT_CENTER (1<<0)
-#define ASLE_PFIT_STRETCH_TEXT (1<<1)
-#define ASLE_PFIT_STRETCH_GFX (1<<2)
-
-/* PWM frequency and minimum brightness */
-#define ASLE_PFMB_BRIGHTNESS_MASK (0xff)
-#define ASLE_PFMB_BRIGHTNESS_VALID (1<<8)
-#define ASLE_PFMB_PWM_MASK (0x7ffffe00)
-#define ASLE_PFMB_PWM_VALID (1<<31)
-
-#define ASLE_CBLV_VALID         (1<<31)
-
-#define ACPI_OTHER_OUTPUT (0<<8)
-#define ACPI_VGA_OUTPUT (1<<8)
-#define ACPI_TV_OUTPUT (2<<8)
-#define ACPI_DIGITAL_OUTPUT (3<<8)
-#define ACPI_LVDS_OUTPUT (4<<8)
-
-static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct opregion_asle *asle = dev_priv->opregion.asle;
-       u32 blc_pwm_ctl, blc_pwm_ctl2;
-       u32 max_backlight, level, shift;
-
-       if (!(bclp & ASLE_BCLP_VALID))
-               return ASLE_BACKLIGHT_FAILED;
-
-       bclp &= ASLE_BCLP_MSK;
-       if (bclp < 0 || bclp > 255)
-               return ASLE_BACKLIGHT_FAILED;
-
-       blc_pwm_ctl = I915_READ(BLC_PWM_CTL);
-       blc_pwm_ctl2 = I915_READ(BLC_PWM_CTL2);
-
-       if (IS_I965G(dev) && (blc_pwm_ctl2 & BLM_COMBINATION_MODE))
-               pci_write_config_dword(dev->pdev, PCI_LBPC, bclp);
-       else {
-               if (IS_PINEVIEW(dev)) {
-                       blc_pwm_ctl &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1);
-                       max_backlight = (blc_pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK) >> 
-                                       BACKLIGHT_MODULATION_FREQ_SHIFT;
-                       shift = BACKLIGHT_DUTY_CYCLE_SHIFT + 1;
-               } else {
-                       blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK;
-                       max_backlight = ((blc_pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK) >> 
-                                       BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
-                       shift = BACKLIGHT_DUTY_CYCLE_SHIFT;
-               }
-               level = (bclp * max_backlight) / 255;
-               I915_WRITE(BLC_PWM_CTL, blc_pwm_ctl | (level << shift));
-       }
-       asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID;
-
-       return 0;
-}
-
-static u32 asle_set_als_illum(struct drm_device *dev, u32 alsi)
-{
-       /* alsi is the current ALS reading in lux. 0 indicates below sensor
-          range, 0xffff indicates above sensor range. 1-0xfffe are valid */
-       return 0;
-}
-
-static u32 asle_set_pwm_freq(struct drm_device *dev, u32 pfmb)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       if (pfmb & ASLE_PFMB_PWM_VALID) {
-               u32 blc_pwm_ctl = I915_READ(BLC_PWM_CTL);
-               u32 pwm = pfmb & ASLE_PFMB_PWM_MASK;
-               blc_pwm_ctl &= BACKLIGHT_DUTY_CYCLE_MASK;
-               pwm = pwm >> 9;
-               /* FIXME - what do we do with the PWM? */
-       }
-       return 0;
-}
-
-static u32 asle_set_pfit(struct drm_device *dev, u32 pfit)
-{
-       /* Panel fitting is currently controlled by the X code, so this is a
-          noop until modesetting support works fully */
-       if (!(pfit & ASLE_PFIT_VALID))
-               return ASLE_PFIT_FAILED;
-       return 0;
-}
-
-void opregion_asle_intr(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct opregion_asle *asle = dev_priv->opregion.asle;
-       u32 asle_stat = 0;
-       u32 asle_req;
-
-       if (!asle)
-               return;
-
-       asle_req = asle->aslc & ASLE_REQ_MSK;
-
-       if (!asle_req) {
-               DRM_DEBUG_DRIVER("non asle set request??\n");
-               return;
-       }
-
-       if (asle_req & ASLE_SET_ALS_ILLUM)
-               asle_stat |= asle_set_als_illum(dev, asle->alsi);
-
-       if (asle_req & ASLE_SET_BACKLIGHT)
-               asle_stat |= asle_set_backlight(dev, asle->bclp);
-
-       if (asle_req & ASLE_SET_PFIT)
-               asle_stat |= asle_set_pfit(dev, asle->pfit);
-
-       if (asle_req & ASLE_SET_PWM_FREQ)
-               asle_stat |= asle_set_pwm_freq(dev, asle->pfmb);
-
-       asle->aslc = asle_stat;
-}
-
-static u32 asle_set_backlight_ironlake(struct drm_device *dev, u32 bclp)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct opregion_asle *asle = dev_priv->opregion.asle;
-       u32 cpu_pwm_ctl, pch_pwm_ctl2;
-       u32 max_backlight, level;
-
-       if (!(bclp & ASLE_BCLP_VALID))
-               return ASLE_BACKLIGHT_FAILED;
-
-       bclp &= ASLE_BCLP_MSK;
-       if (bclp < 0 || bclp > 255)
-               return ASLE_BACKLIGHT_FAILED;
-
-       cpu_pwm_ctl = I915_READ(BLC_PWM_CPU_CTL);
-       pch_pwm_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
-       /* get the max PWM frequency */
-       max_backlight = (pch_pwm_ctl2 >> 16) & BACKLIGHT_DUTY_CYCLE_MASK;
-       /* calculate the expected PMW frequency */
-       level = (bclp * max_backlight) / 255;
-       /* reserve the high 16 bits */
-       cpu_pwm_ctl &= ~(BACKLIGHT_DUTY_CYCLE_MASK);
-       /* write the updated PWM frequency */
-       I915_WRITE(BLC_PWM_CPU_CTL, cpu_pwm_ctl | level);
-
-       asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID;
-
-       return 0;
-}
-
-void ironlake_opregion_gse_intr(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct opregion_asle *asle = dev_priv->opregion.asle;
-       u32 asle_stat = 0;
-       u32 asle_req;
-
-       if (!asle)
-               return;
-
-       asle_req = asle->aslc & ASLE_REQ_MSK;
-
-       if (!asle_req) {
-               DRM_DEBUG_DRIVER("non asle set request??\n");
-               return;
-       }
-
-       if (asle_req & ASLE_SET_ALS_ILLUM) {
-               DRM_DEBUG_DRIVER("Illum is not supported\n");
-               asle_stat |= ASLE_ALS_ILLUM_FAILED;
-       }
-
-       if (asle_req & ASLE_SET_BACKLIGHT)
-               asle_stat |= asle_set_backlight_ironlake(dev, asle->bclp);
-
-       if (asle_req & ASLE_SET_PFIT) {
-               DRM_DEBUG_DRIVER("Pfit is not supported\n");
-               asle_stat |= ASLE_PFIT_FAILED;
-       }
-
-       if (asle_req & ASLE_SET_PWM_FREQ) {
-               DRM_DEBUG_DRIVER("PWM freq is not supported\n");
-               asle_stat |= ASLE_PWM_FREQ_FAILED;
-       }
-
-       asle->aslc = asle_stat;
-}
-#define ASLE_ALS_EN    (1<<0)
-#define ASLE_BLC_EN    (1<<1)
-#define ASLE_PFIT_EN   (1<<2)
-#define ASLE_PFMB_EN   (1<<3)
-
-void opregion_enable_asle(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct opregion_asle *asle = dev_priv->opregion.asle;
-
-       if (asle) {
-               if (IS_MOBILE(dev)) {
-                       unsigned long irqflags;
-
-                       spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
-                       intel_enable_asle(dev);
-                       spin_unlock_irqrestore(&dev_priv->user_irq_lock,
-                                              irqflags);
-               }
-
-               asle->tche = ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN |
-                       ASLE_PFMB_EN;
-               asle->ardy = 1;
-       }
-}
-
-#define ACPI_EV_DISPLAY_SWITCH (1<<0)
-#define ACPI_EV_LID            (1<<1)
-#define ACPI_EV_DOCK           (1<<2)
-
-static struct intel_opregion *system_opregion;
-
-static int intel_opregion_video_event(struct notifier_block *nb,
-                                     unsigned long val, void *data)
-{
-       /* The only video events relevant to opregion are 0x80. These indicate
-          either a docking event, lid switch or display switch request. In
-          Linux, these are handled by the dock, button and video drivers.
-          We might want to fix the video driver to be opregion-aware in
-          future, but right now we just indicate to the firmware that the
-          request has been handled */
-
-       struct opregion_acpi *acpi;
-
-       if (!system_opregion)
-               return NOTIFY_DONE;
-
-       acpi = system_opregion->acpi;
-       acpi->csts = 0;
-
-       return NOTIFY_OK;
-}
-
-static struct notifier_block intel_opregion_notifier = {
-       .notifier_call = intel_opregion_video_event,
-};
-
-/*
- * Initialise the DIDL field in opregion. This passes a list of devices to
- * the firmware. Values are defined by section B.4.2 of the ACPI specification
- * (version 3)
- */
-
-static void intel_didl_outputs(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_opregion *opregion = &dev_priv->opregion;
-       struct drm_connector *connector;
-       acpi_handle handle;
-       struct acpi_device *acpi_dev, *acpi_cdev, *acpi_video_bus = NULL;
-       unsigned long long device_id;
-       acpi_status status;
-       int i = 0;
-
-       handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev);
-       if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &acpi_dev)))
-               return;
-
-       if (acpi_is_video_device(acpi_dev))
-               acpi_video_bus = acpi_dev;
-       else {
-               list_for_each_entry(acpi_cdev, &acpi_dev->children, node) {
-                       if (acpi_is_video_device(acpi_cdev)) {
-                               acpi_video_bus = acpi_cdev;
-                               break;
-                       }
-               }
-       }
-
-       if (!acpi_video_bus) {
-               printk(KERN_WARNING "No ACPI video bus found\n");
-               return;
-       }
-
-       list_for_each_entry(acpi_cdev, &acpi_video_bus->children, node) {
-               if (i >= 8) {
-                       dev_printk (KERN_ERR, &dev->pdev->dev,
-                                   "More than 8 outputs detected\n");
-                       return;
-               }
-               status =
-                       acpi_evaluate_integer(acpi_cdev->handle, "_ADR",
-                                               NULL, &device_id);
-               if (ACPI_SUCCESS(status)) {
-                       if (!device_id)
-                               goto blind_set;
-                       opregion->acpi->didl[i] = (u32)(device_id & 0x0f0f);
-                       i++;
-               }
-       }
-
-end:
-       /* If fewer than 8 outputs, the list must be null terminated */
-       if (i < 8)
-               opregion->acpi->didl[i] = 0;
-       return;
-
-blind_set:
-       i = 0;
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-               int output_type = ACPI_OTHER_OUTPUT;
-               if (i >= 8) {
-                       dev_printk (KERN_ERR, &dev->pdev->dev,
-                                   "More than 8 outputs detected\n");
-                       return;
-               }
-               switch (connector->connector_type) {
-               case DRM_MODE_CONNECTOR_VGA:
-               case DRM_MODE_CONNECTOR_DVIA:
-                       output_type = ACPI_VGA_OUTPUT;
-                       break;
-               case DRM_MODE_CONNECTOR_Composite:
-               case DRM_MODE_CONNECTOR_SVIDEO:
-               case DRM_MODE_CONNECTOR_Component:
-               case DRM_MODE_CONNECTOR_9PinDIN:
-                       output_type = ACPI_TV_OUTPUT;
-                       break;
-               case DRM_MODE_CONNECTOR_DVII:
-               case DRM_MODE_CONNECTOR_DVID:
-               case DRM_MODE_CONNECTOR_DisplayPort:
-               case DRM_MODE_CONNECTOR_HDMIA:
-               case DRM_MODE_CONNECTOR_HDMIB:
-                       output_type = ACPI_DIGITAL_OUTPUT;
-                       break;
-               case DRM_MODE_CONNECTOR_LVDS:
-                       output_type = ACPI_LVDS_OUTPUT;
-                       break;
-               }
-               opregion->acpi->didl[i] |= (1<<31) | output_type | i;
-               i++;
-       }
-       goto end;
-}
-
-int intel_opregion_init(struct drm_device *dev, int resume)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_opregion *opregion = &dev_priv->opregion;
-       void *base;
-       u32 asls, mboxes;
-       int err = 0;
-
-       pci_read_config_dword(dev->pdev, PCI_ASLS, &asls);
-       DRM_DEBUG_DRIVER("graphic opregion physical addr: 0x%x\n", asls);
-       if (asls == 0) {
-               DRM_DEBUG_DRIVER("ACPI OpRegion not supported!\n");
-               return -ENOTSUPP;
-       }
-
-       base = ioremap(asls, OPREGION_SZ);
-       if (!base)
-               return -ENOMEM;
-
-       opregion->header = base;
-       if (memcmp(opregion->header->signature, OPREGION_SIGNATURE, 16)) {
-               DRM_DEBUG_DRIVER("opregion signature mismatch\n");
-               err = -EINVAL;
-               goto err_out;
-       }
-
-       mboxes = opregion->header->mboxes;
-       if (mboxes & MBOX_ACPI) {
-               DRM_DEBUG_DRIVER("Public ACPI methods supported\n");
-               opregion->acpi = base + OPREGION_ACPI_OFFSET;
-               if (drm_core_check_feature(dev, DRIVER_MODESET))
-                       intel_didl_outputs(dev);
-       } else {
-               DRM_DEBUG_DRIVER("Public ACPI methods not supported\n");
-               err = -ENOTSUPP;
-               goto err_out;
-       }
-       opregion->enabled = 1;
-
-       if (mboxes & MBOX_SWSCI) {
-               DRM_DEBUG_DRIVER("SWSCI supported\n");
-               opregion->swsci = base + OPREGION_SWSCI_OFFSET;
-       }
-       if (mboxes & MBOX_ASLE) {
-               DRM_DEBUG_DRIVER("ASLE supported\n");
-               opregion->asle = base + OPREGION_ASLE_OFFSET;
-               opregion_enable_asle(dev);
-       }
-
-       if (!resume)
-               acpi_video_register();
-
-
-       /* Notify BIOS we are ready to handle ACPI video ext notifs.
-        * Right now, all the events are handled by the ACPI video module.
-        * We don't actually need to do anything with them. */
-       opregion->acpi->csts = 0;
-       opregion->acpi->drdy = 1;
-
-       system_opregion = opregion;
-       register_acpi_notifier(&intel_opregion_notifier);
-
-       return 0;
-
-err_out:
-       iounmap(opregion->header);
-       opregion->header = NULL;
-       acpi_video_register();
-       return err;
-}
-
-void intel_opregion_free(struct drm_device *dev, int suspend)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_opregion *opregion = &dev_priv->opregion;
-
-       if (!opregion->enabled)
-               return;
-
-       if (!suspend)
-               acpi_video_unregister();
-
-       opregion->acpi->drdy = 0;
-
-       system_opregion = NULL;
-       unregister_acpi_notifier(&intel_opregion_notifier);
-
-       /* just clear all opregion memory pointers now */
-       iounmap(opregion->header);
-       opregion->header = NULL;
-       opregion->acpi = NULL;
-       opregion->swsci = NULL;
-       opregion->asle = NULL;
-
-       opregion->enabled = 0;
-}
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
new file mode 100644 (file)
index 0000000..97d5329
--- /dev/null
@@ -0,0 +1,563 @@
+/*
+ * Copyright 2008 Intel Corporation <hong.liu@intel.com>
+ * Copyright 2008 Red Hat <mjg@redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT.  IN NO EVENT SHALL INTEL AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/acpi.h>
+#include <acpi/video.h>
+
+#include "drmP.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+#define PCI_ASLE 0xe4
+#define PCI_LBPC 0xf4
+#define PCI_ASLS 0xfc
+
+#define OPREGION_SZ            (8*1024)
+#define OPREGION_HEADER_OFFSET 0
+#define OPREGION_ACPI_OFFSET   0x100
+#define OPREGION_SWSCI_OFFSET  0x200
+#define OPREGION_ASLE_OFFSET   0x300
+#define OPREGION_VBT_OFFSET    0x1000
+
+#define OPREGION_SIGNATURE "IntelGraphicsMem"
+#define MBOX_ACPI      (1<<0)
+#define MBOX_SWSCI     (1<<1)
+#define MBOX_ASLE      (1<<2)
+
+struct opregion_header {
+       u8 signature[16];
+       u32 size;
+       u32 opregion_ver;
+       u8 bios_ver[32];
+       u8 vbios_ver[16];
+       u8 driver_ver[16];
+       u32 mboxes;
+       u8 reserved[164];
+} __attribute__((packed));
+
+/* OpRegion mailbox #1: public ACPI methods */
+struct opregion_acpi {
+       u32 drdy;       /* driver readiness */
+       u32 csts;       /* notification status */
+       u32 cevt;       /* current event */
+       u8 rsvd1[20];
+       u32 didl[8];    /* supported display devices ID list */
+       u32 cpdl[8];    /* currently presented display list */
+       u32 cadl[8];    /* currently active display list */
+       u32 nadl[8];    /* next active devices list */
+       u32 aslp;       /* ASL sleep time-out */
+       u32 tidx;       /* toggle table index */
+       u32 chpd;       /* current hotplug enable indicator */
+       u32 clid;       /* current lid state*/
+       u32 cdck;       /* current docking state */
+       u32 sxsw;       /* Sx state resume */
+       u32 evts;       /* ASL supported events */
+       u32 cnot;       /* current OS notification */
+       u32 nrdy;       /* driver status */
+       u8 rsvd2[60];
+} __attribute__((packed));
+
+/* OpRegion mailbox #2: SWSCI */
+struct opregion_swsci {
+       u32 scic;       /* SWSCI command|status|data */
+       u32 parm;       /* command parameters */
+       u32 dslp;       /* driver sleep time-out */
+       u8 rsvd[244];
+} __attribute__((packed));
+
+/* OpRegion mailbox #3: ASLE */
+struct opregion_asle {
+       u32 ardy;       /* driver readiness */
+       u32 aslc;       /* ASLE interrupt command */
+       u32 tche;       /* technology enabled indicator */
+       u32 alsi;       /* current ALS illuminance reading */
+       u32 bclp;       /* backlight brightness to set */
+       u32 pfit;       /* panel fitting state */
+       u32 cblv;       /* current brightness level */
+       u16 bclm[20];   /* backlight level duty cycle mapping table */
+       u32 cpfm;       /* current panel fitting mode */
+       u32 epfm;       /* enabled panel fitting modes */
+       u8 plut[74];    /* panel LUT and identifier */
+       u32 pfmb;       /* PWM freq and min brightness */
+       u8 rsvd[102];
+} __attribute__((packed));
+
+/* ASLE irq request bits */
+#define ASLE_SET_ALS_ILLUM     (1 << 0)
+#define ASLE_SET_BACKLIGHT     (1 << 1)
+#define ASLE_SET_PFIT          (1 << 2)
+#define ASLE_SET_PWM_FREQ      (1 << 3)
+#define ASLE_REQ_MSK           0xf
+
+/* response bits of ASLE irq request */
+#define ASLE_ALS_ILLUM_FAILED  (1<<10)
+#define ASLE_BACKLIGHT_FAILED  (1<<12)
+#define ASLE_PFIT_FAILED       (1<<14)
+#define ASLE_PWM_FREQ_FAILED   (1<<16)
+
+/* ASLE backlight brightness to set */
+#define ASLE_BCLP_VALID                (1<<31)
+#define ASLE_BCLP_MSK          (~(1<<31))
+
+/* ASLE panel fitting request */
+#define ASLE_PFIT_VALID         (1<<31)
+#define ASLE_PFIT_CENTER (1<<0)
+#define ASLE_PFIT_STRETCH_TEXT (1<<1)
+#define ASLE_PFIT_STRETCH_GFX (1<<2)
+
+/* PWM frequency and minimum brightness */
+#define ASLE_PFMB_BRIGHTNESS_MASK (0xff)
+#define ASLE_PFMB_BRIGHTNESS_VALID (1<<8)
+#define ASLE_PFMB_PWM_MASK (0x7ffffe00)
+#define ASLE_PFMB_PWM_VALID (1<<31)
+
+#define ASLE_CBLV_VALID         (1<<31)
+
+#define ACPI_OTHER_OUTPUT (0<<8)
+#define ACPI_VGA_OUTPUT (1<<8)
+#define ACPI_TV_OUTPUT (2<<8)
+#define ACPI_DIGITAL_OUTPUT (3<<8)
+#define ACPI_LVDS_OUTPUT (4<<8)
+
+static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct opregion_asle *asle = dev_priv->opregion.asle;
+       u32 blc_pwm_ctl, blc_pwm_ctl2;
+       u32 max_backlight, level, shift;
+
+       if (!(bclp & ASLE_BCLP_VALID))
+               return ASLE_BACKLIGHT_FAILED;
+
+       bclp &= ASLE_BCLP_MSK;
+       if (bclp < 0 || bclp > 255)
+               return ASLE_BACKLIGHT_FAILED;
+
+       blc_pwm_ctl = I915_READ(BLC_PWM_CTL);
+       blc_pwm_ctl2 = I915_READ(BLC_PWM_CTL2);
+
+       if (IS_I965G(dev) && (blc_pwm_ctl2 & BLM_COMBINATION_MODE))
+               pci_write_config_dword(dev->pdev, PCI_LBPC, bclp);
+       else {
+               if (IS_PINEVIEW(dev)) {
+                       blc_pwm_ctl &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1);
+                       max_backlight = (blc_pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK) >> 
+                                       BACKLIGHT_MODULATION_FREQ_SHIFT;
+                       shift = BACKLIGHT_DUTY_CYCLE_SHIFT + 1;
+               } else {
+                       blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK;
+                       max_backlight = ((blc_pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK) >> 
+                                       BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
+                       shift = BACKLIGHT_DUTY_CYCLE_SHIFT;
+               }
+               level = (bclp * max_backlight) / 255;
+               I915_WRITE(BLC_PWM_CTL, blc_pwm_ctl | (level << shift));
+       }
+       asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID;
+
+       return 0;
+}
+
+static u32 asle_set_als_illum(struct drm_device *dev, u32 alsi)
+{
+       /* alsi is the current ALS reading in lux. 0 indicates below sensor
+          range, 0xffff indicates above sensor range. 1-0xfffe are valid */
+       return 0;
+}
+
+static u32 asle_set_pwm_freq(struct drm_device *dev, u32 pfmb)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       if (pfmb & ASLE_PFMB_PWM_VALID) {
+               u32 blc_pwm_ctl = I915_READ(BLC_PWM_CTL);
+               u32 pwm = pfmb & ASLE_PFMB_PWM_MASK;
+               blc_pwm_ctl &= BACKLIGHT_DUTY_CYCLE_MASK;
+               pwm = pwm >> 9;
+               /* FIXME - what do we do with the PWM? */
+       }
+       return 0;
+}
+
+static u32 asle_set_pfit(struct drm_device *dev, u32 pfit)
+{
+       /* Panel fitting is currently controlled by the X code, so this is a
+          noop until modesetting support works fully */
+       if (!(pfit & ASLE_PFIT_VALID))
+               return ASLE_PFIT_FAILED;
+       return 0;
+}
+
+void intel_opregion_asle_intr(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct opregion_asle *asle = dev_priv->opregion.asle;
+       u32 asle_stat = 0;
+       u32 asle_req;
+
+       if (!asle)
+               return;
+
+       asle_req = asle->aslc & ASLE_REQ_MSK;
+
+       if (!asle_req) {
+               DRM_DEBUG_DRIVER("non asle set request??\n");
+               return;
+       }
+
+       if (asle_req & ASLE_SET_ALS_ILLUM)
+               asle_stat |= asle_set_als_illum(dev, asle->alsi);
+
+       if (asle_req & ASLE_SET_BACKLIGHT)
+               asle_stat |= asle_set_backlight(dev, asle->bclp);
+
+       if (asle_req & ASLE_SET_PFIT)
+               asle_stat |= asle_set_pfit(dev, asle->pfit);
+
+       if (asle_req & ASLE_SET_PWM_FREQ)
+               asle_stat |= asle_set_pwm_freq(dev, asle->pfmb);
+
+       asle->aslc = asle_stat;
+}
+
+static u32 asle_set_backlight_ironlake(struct drm_device *dev, u32 bclp)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct opregion_asle *asle = dev_priv->opregion.asle;
+       u32 cpu_pwm_ctl, pch_pwm_ctl2;
+       u32 max_backlight, level;
+
+       if (!(bclp & ASLE_BCLP_VALID))
+               return ASLE_BACKLIGHT_FAILED;
+
+       bclp &= ASLE_BCLP_MSK;
+       if (bclp < 0 || bclp > 255)
+               return ASLE_BACKLIGHT_FAILED;
+
+       cpu_pwm_ctl = I915_READ(BLC_PWM_CPU_CTL);
+       pch_pwm_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
+       /* get the max PWM frequency */
+       max_backlight = (pch_pwm_ctl2 >> 16) & BACKLIGHT_DUTY_CYCLE_MASK;
+       /* calculate the expected PMW frequency */
+       level = (bclp * max_backlight) / 255;
+       /* reserve the high 16 bits */
+       cpu_pwm_ctl &= ~(BACKLIGHT_DUTY_CYCLE_MASK);
+       /* write the updated PWM frequency */
+       I915_WRITE(BLC_PWM_CPU_CTL, cpu_pwm_ctl | level);
+
+       asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID;
+
+       return 0;
+}
+
+/* Only present on Ironlake+ */
+void intel_opregion_gse_intr(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct opregion_asle *asle = dev_priv->opregion.asle;
+       u32 asle_stat = 0;
+       u32 asle_req;
+
+       if (!asle)
+               return;
+
+       asle_req = asle->aslc & ASLE_REQ_MSK;
+
+       if (!asle_req) {
+               DRM_DEBUG_DRIVER("non asle set request??\n");
+               return;
+       }
+
+       if (asle_req & ASLE_SET_ALS_ILLUM) {
+               DRM_DEBUG_DRIVER("Illum is not supported\n");
+               asle_stat |= ASLE_ALS_ILLUM_FAILED;
+       }
+
+       if (asle_req & ASLE_SET_BACKLIGHT)
+               asle_stat |= asle_set_backlight_ironlake(dev, asle->bclp);
+
+       if (asle_req & ASLE_SET_PFIT) {
+               DRM_DEBUG_DRIVER("Pfit is not supported\n");
+               asle_stat |= ASLE_PFIT_FAILED;
+       }
+
+       if (asle_req & ASLE_SET_PWM_FREQ) {
+               DRM_DEBUG_DRIVER("PWM freq is not supported\n");
+               asle_stat |= ASLE_PWM_FREQ_FAILED;
+       }
+
+       asle->aslc = asle_stat;
+}
+#define ASLE_ALS_EN    (1<<0)
+#define ASLE_BLC_EN    (1<<1)
+#define ASLE_PFIT_EN   (1<<2)
+#define ASLE_PFMB_EN   (1<<3)
+
+void intel_opregion_enable_asle(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct opregion_asle *asle = dev_priv->opregion.asle;
+
+       if (asle) {
+               if (IS_MOBILE(dev)) {
+                       unsigned long irqflags;
+
+                       spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
+                       intel_enable_asle(dev);
+                       spin_unlock_irqrestore(&dev_priv->user_irq_lock,
+                                              irqflags);
+               }
+
+               asle->tche = ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN |
+                       ASLE_PFMB_EN;
+               asle->ardy = 1;
+       }
+}
+
+#define ACPI_EV_DISPLAY_SWITCH (1<<0)
+#define ACPI_EV_LID            (1<<1)
+#define ACPI_EV_DOCK           (1<<2)
+
+static struct intel_opregion *system_opregion;
+
+static int intel_opregion_video_event(struct notifier_block *nb,
+                                     unsigned long val, void *data)
+{
+       /* The only video events relevant to opregion are 0x80. These indicate
+          either a docking event, lid switch or display switch request. In
+          Linux, these are handled by the dock, button and video drivers.
+          We might want to fix the video driver to be opregion-aware in
+          future, but right now we just indicate to the firmware that the
+          request has been handled */
+
+       struct opregion_acpi *acpi;
+
+       if (!system_opregion)
+               return NOTIFY_DONE;
+
+       acpi = system_opregion->acpi;
+       acpi->csts = 0;
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block intel_opregion_notifier = {
+       .notifier_call = intel_opregion_video_event,
+};
+
+/*
+ * Initialise the DIDL field in opregion. This passes a list of devices to
+ * the firmware. Values are defined by section B.4.2 of the ACPI specification
+ * (version 3)
+ */
+
+static void intel_didl_outputs(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_opregion *opregion = &dev_priv->opregion;
+       struct drm_connector *connector;
+       acpi_handle handle;
+       struct acpi_device *acpi_dev, *acpi_cdev, *acpi_video_bus = NULL;
+       unsigned long long device_id;
+       acpi_status status;
+       int i = 0;
+
+       handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev);
+       if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &acpi_dev)))
+               return;
+
+       if (acpi_is_video_device(acpi_dev))
+               acpi_video_bus = acpi_dev;
+       else {
+               list_for_each_entry(acpi_cdev, &acpi_dev->children, node) {
+                       if (acpi_is_video_device(acpi_cdev)) {
+                               acpi_video_bus = acpi_cdev;
+                               break;
+                       }
+               }
+       }
+
+       if (!acpi_video_bus) {
+               printk(KERN_WARNING "No ACPI video bus found\n");
+               return;
+       }
+
+       list_for_each_entry(acpi_cdev, &acpi_video_bus->children, node) {
+               if (i >= 8) {
+                       dev_printk (KERN_ERR, &dev->pdev->dev,
+                                   "More than 8 outputs detected\n");
+                       return;
+               }
+               status =
+                       acpi_evaluate_integer(acpi_cdev->handle, "_ADR",
+                                               NULL, &device_id);
+               if (ACPI_SUCCESS(status)) {
+                       if (!device_id)
+                               goto blind_set;
+                       opregion->acpi->didl[i] = (u32)(device_id & 0x0f0f);
+                       i++;
+               }
+       }
+
+end:
+       /* If fewer than 8 outputs, the list must be null terminated */
+       if (i < 8)
+               opregion->acpi->didl[i] = 0;
+       return;
+
+blind_set:
+       i = 0;
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               int output_type = ACPI_OTHER_OUTPUT;
+               if (i >= 8) {
+                       dev_printk (KERN_ERR, &dev->pdev->dev,
+                                   "More than 8 outputs detected\n");
+                       return;
+               }
+               switch (connector->connector_type) {
+               case DRM_MODE_CONNECTOR_VGA:
+               case DRM_MODE_CONNECTOR_DVIA:
+                       output_type = ACPI_VGA_OUTPUT;
+                       break;
+               case DRM_MODE_CONNECTOR_Composite:
+               case DRM_MODE_CONNECTOR_SVIDEO:
+               case DRM_MODE_CONNECTOR_Component:
+               case DRM_MODE_CONNECTOR_9PinDIN:
+                       output_type = ACPI_TV_OUTPUT;
+                       break;
+               case DRM_MODE_CONNECTOR_DVII:
+               case DRM_MODE_CONNECTOR_DVID:
+               case DRM_MODE_CONNECTOR_DisplayPort:
+               case DRM_MODE_CONNECTOR_HDMIA:
+               case DRM_MODE_CONNECTOR_HDMIB:
+                       output_type = ACPI_DIGITAL_OUTPUT;
+                       break;
+               case DRM_MODE_CONNECTOR_LVDS:
+                       output_type = ACPI_LVDS_OUTPUT;
+                       break;
+               }
+               opregion->acpi->didl[i] |= (1<<31) | output_type | i;
+               i++;
+       }
+       goto end;
+}
+
+int intel_opregion_init(struct drm_device *dev, int resume)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_opregion *opregion = &dev_priv->opregion;
+       void *base;
+       u32 asls, mboxes;
+       int err = 0;
+
+       pci_read_config_dword(dev->pdev, PCI_ASLS, &asls);
+       DRM_DEBUG_DRIVER("graphic opregion physical addr: 0x%x\n", asls);
+       if (asls == 0) {
+               DRM_DEBUG_DRIVER("ACPI OpRegion not supported!\n");
+               return -ENOTSUPP;
+       }
+
+       base = ioremap(asls, OPREGION_SZ);
+       if (!base)
+               return -ENOMEM;
+
+       opregion->header = base;
+       if (memcmp(opregion->header->signature, OPREGION_SIGNATURE, 16)) {
+               DRM_DEBUG_DRIVER("opregion signature mismatch\n");
+               err = -EINVAL;
+               goto err_out;
+       }
+
+       mboxes = opregion->header->mboxes;
+       if (mboxes & MBOX_ACPI) {
+               DRM_DEBUG_DRIVER("Public ACPI methods supported\n");
+               opregion->acpi = base + OPREGION_ACPI_OFFSET;
+               if (drm_core_check_feature(dev, DRIVER_MODESET))
+                       intel_didl_outputs(dev);
+       } else {
+               DRM_DEBUG_DRIVER("Public ACPI methods not supported\n");
+               err = -ENOTSUPP;
+               goto err_out;
+       }
+       opregion->enabled = 1;
+
+       if (mboxes & MBOX_SWSCI) {
+               DRM_DEBUG_DRIVER("SWSCI supported\n");
+               opregion->swsci = base + OPREGION_SWSCI_OFFSET;
+       }
+       if (mboxes & MBOX_ASLE) {
+               DRM_DEBUG_DRIVER("ASLE supported\n");
+               opregion->asle = base + OPREGION_ASLE_OFFSET;
+               intel_opregion_enable_asle(dev);
+       }
+
+       if (!resume)
+               acpi_video_register();
+
+
+       /* Notify BIOS we are ready to handle ACPI video ext notifs.
+        * Right now, all the events are handled by the ACPI video module.
+        * We don't actually need to do anything with them. */
+       opregion->acpi->csts = 0;
+       opregion->acpi->drdy = 1;
+
+       system_opregion = opregion;
+       register_acpi_notifier(&intel_opregion_notifier);
+
+       return 0;
+
+err_out:
+       iounmap(opregion->header);
+       opregion->header = NULL;
+       acpi_video_register();
+       return err;
+}
+
+void intel_opregion_free(struct drm_device *dev, int suspend)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_opregion *opregion = &dev_priv->opregion;
+
+       if (!opregion->enabled)
+               return;
+
+       if (!suspend)
+               acpi_video_unregister();
+
+       opregion->acpi->drdy = 0;
+
+       system_opregion = NULL;
+       unregister_acpi_notifier(&intel_opregion_notifier);
+
+       /* just clear all opregion memory pointers now */
+       iounmap(opregion->header);
+       opregion->header = NULL;
+       opregion->acpi = NULL;
+       opregion->swsci = NULL;
+       opregion->asle = NULL;
+
+       opregion->enabled = 0;
+}