gma500: intel_bios updates
authorAlan Cox <alan@linux.intel.com>
Wed, 25 Apr 2012 13:37:14 +0000 (14:37 +0100)
committerDave Airlie <airlied@redhat.com>
Fri, 27 Apr 2012 08:23:47 +0000 (09:23 +0100)
Pull in various i915 bits that we will need to begin tackling the LVDS detect
and ACPI events. We try and drift towards the i915 version of the code with
the long term goal that at least some of it can one day be unified.

Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/gma500/intel_bios.c
drivers/gpu/drm/gma500/intel_bios.h
drivers/gpu/drm/gma500/intel_opregion.c
drivers/gpu/drm/gma500/psb_drv.h

index 51ea6df125f201976bbccf61c6e5b88a624d660e..479e4497d26ce19257425898342298e660d27311 100644 (file)
@@ -26,6 +26,8 @@
 #include "psb_intel_reg.h"
 #include "intel_bios.h"
 
+#define        SLAVE_ADDR1     0x70
+#define        SLAVE_ADDR2     0x72
 
 static void *find_section(struct bdb_header *bdb, int section_id)
 {
@@ -52,6 +54,16 @@ static void *find_section(struct bdb_header *bdb, int section_id)
        return NULL;
 }
 
+static u16
+get_blocksize(void *p)
+{
+       u16 *block_ptr, block_size;
+
+       block_ptr = (u16 *)((char *)p - 2);
+       block_size = *block_ptr;
+       return block_size;
+}
+
 static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
                        struct lvds_dvo_timing *dvo_timing)
 {
@@ -75,6 +87,16 @@ static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
        panel_fixed_mode->clock = dvo_timing->clock * 10;
        panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
 
+       if (dvo_timing->hsync_positive)
+               panel_fixed_mode->flags |= DRM_MODE_FLAG_PHSYNC;
+       else
+               panel_fixed_mode->flags |= DRM_MODE_FLAG_NHSYNC;
+
+       if (dvo_timing->vsync_positive)
+               panel_fixed_mode->flags |= DRM_MODE_FLAG_PVSYNC;
+       else
+               panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC;
+
        /* Some VBTs have bogus h/vtotal values */
        if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
                panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
@@ -217,6 +239,97 @@ static void parse_general_features(struct drm_psb_private *dev_priv,
        }
 }
 
+static void
+parse_sdvo_device_mapping(struct drm_psb_private *dev_priv,
+                         struct bdb_header *bdb)
+{
+       struct sdvo_device_mapping *p_mapping;
+       struct bdb_general_definitions *p_defs;
+       struct child_device_config *p_child;
+       int i, child_device_num, count;
+       u16     block_size;
+
+       p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
+       if (!p_defs) {
+               DRM_DEBUG_KMS("No general definition block is found, unable to construct sdvo mapping.\n");
+               return;
+       }
+       /* judge whether the size of child device meets the requirements.
+        * If the child device size obtained from general definition block
+        * is different with sizeof(struct child_device_config), skip the
+        * parsing of sdvo device info
+        */
+       if (p_defs->child_dev_size != sizeof(*p_child)) {
+               /* different child dev size . Ignore it */
+               DRM_DEBUG_KMS("different child size is found. Invalid.\n");
+               return;
+       }
+       /* get the block size of general definitions */
+       block_size = get_blocksize(p_defs);
+       /* get the number of child device */
+       child_device_num = (block_size - sizeof(*p_defs)) /
+                               sizeof(*p_child);
+       count = 0;
+       for (i = 0; i < child_device_num; i++) {
+               p_child = &(p_defs->devices[i]);
+               if (!p_child->device_type) {
+                       /* skip the device block if device type is invalid */
+                       continue;
+               }
+               if (p_child->slave_addr != SLAVE_ADDR1 &&
+                       p_child->slave_addr != SLAVE_ADDR2) {
+                       /*
+                        * If the slave address is neither 0x70 nor 0x72,
+                        * it is not a SDVO device. Skip it.
+                        */
+                       continue;
+               }
+               if (p_child->dvo_port != DEVICE_PORT_DVOB &&
+                       p_child->dvo_port != DEVICE_PORT_DVOC) {
+                       /* skip the incorrect SDVO port */
+                       DRM_DEBUG_KMS("Incorrect SDVO port. Skip it\n");
+                       continue;
+               }
+               DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on"
+                               " %s port\n",
+                               p_child->slave_addr,
+                               (p_child->dvo_port == DEVICE_PORT_DVOB) ?
+                                       "SDVOB" : "SDVOC");
+               p_mapping = &(dev_priv->sdvo_mappings[p_child->dvo_port - 1]);
+               if (!p_mapping->initialized) {
+                       p_mapping->dvo_port = p_child->dvo_port;
+                       p_mapping->slave_addr = p_child->slave_addr;
+                       p_mapping->dvo_wiring = p_child->dvo_wiring;
+                       p_mapping->ddc_pin = p_child->ddc_pin;
+                       p_mapping->i2c_pin = p_child->i2c_pin;
+                       p_mapping->initialized = 1;
+                       DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n",
+                                     p_mapping->dvo_port,
+                                     p_mapping->slave_addr,
+                                     p_mapping->dvo_wiring,
+                                     p_mapping->ddc_pin,
+                                     p_mapping->i2c_pin);
+               } else {
+                       DRM_DEBUG_KMS("Maybe one SDVO port is shared by "
+                                        "two SDVO device.\n");
+               }
+               if (p_child->slave2_addr) {
+                       /* Maybe this is a SDVO device with multiple inputs */
+                       /* And the mapping info is not added */
+                       DRM_DEBUG_KMS("there exists the slave2_addr. Maybe this"
+                               " is a SDVO device with multiple inputs.\n");
+               }
+               count++;
+       }
+
+       if (!count) {
+               /* No SDVO device info is found */
+               DRM_DEBUG_KMS("No SDVO device info is found in VBT\n");
+       }
+       return;
+}
+
+
 static void
 parse_driver_features(struct drm_psb_private *dev_priv,
                      struct bdb_header *bdb)
@@ -234,6 +347,72 @@ parse_driver_features(struct drm_psb_private *dev_priv,
                dev_priv->dplla_96mhz = false;
 }
 
+static void
+parse_device_mapping(struct drm_psb_private *dev_priv,
+                      struct bdb_header *bdb)
+{
+       struct bdb_general_definitions *p_defs;
+       struct child_device_config *p_child, *child_dev_ptr;
+       int i, child_device_num, count;
+       u16     block_size;
+
+       p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
+       if (!p_defs) {
+               DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n");
+               return;
+       }
+       /* judge whether the size of child device meets the requirements.
+        * If the child device size obtained from general definition block
+        * is different with sizeof(struct child_device_config), skip the
+        * parsing of sdvo device info
+        */
+       if (p_defs->child_dev_size != sizeof(*p_child)) {
+               /* different child dev size . Ignore it */
+               DRM_DEBUG_KMS("different child size is found. Invalid.\n");
+               return;
+       }
+       /* get the block size of general definitions */
+       block_size = get_blocksize(p_defs);
+       /* get the number of child device */
+       child_device_num = (block_size - sizeof(*p_defs)) /
+                               sizeof(*p_child);
+       count = 0;
+       /* get the number of child devices that are present */
+       for (i = 0; i < child_device_num; i++) {
+               p_child = &(p_defs->devices[i]);
+               if (!p_child->device_type) {
+                       /* skip the device block if device type is invalid */
+                       continue;
+               }
+               count++;
+       }
+       if (!count) {
+               DRM_DEBUG_KMS("no child dev is parsed from VBT\n");
+               return;
+       }
+       dev_priv->child_dev = kcalloc(count, sizeof(*p_child), GFP_KERNEL);
+       if (!dev_priv->child_dev) {
+               DRM_DEBUG_KMS("No memory space for child devices\n");
+               return;
+       }
+
+       dev_priv->child_dev_num = count;
+       count = 0;
+       for (i = 0; i < child_device_num; i++) {
+               p_child = &(p_defs->devices[i]);
+               if (!p_child->device_type) {
+                       /* skip the device block if device type is invalid */
+                       continue;
+               }
+               child_dev_ptr = dev_priv->child_dev + count;
+               count++;
+               memcpy((void *)child_dev_ptr, (void *)p_child,
+                                       sizeof(*p_child));
+       }
+       return;
+}
+
+
 /**
  * psb_intel_init_bios - initialize VBIOS settings & find VBT
  * @dev: DRM device
@@ -253,39 +432,54 @@ bool psb_intel_init_bios(struct drm_device *dev)
        struct drm_psb_private *dev_priv = dev->dev_private;
        struct pci_dev *pdev = dev->pdev;
        struct vbt_header *vbt = NULL;
-       struct bdb_header *bdb;
-       u8 __iomem *bios;
+       struct bdb_header *bdb = NULL;
+       u8 __iomem *bios = NULL;
        size_t size;
        int i;
 
-       bios = pci_map_rom(pdev, &size);
-       if (!bios)
-               return -1;
+       /* XXX Should this validation be moved to intel_opregion.c? */
+       if (dev_priv->opregion.vbt) {
+               struct vbt_header *vbt = dev_priv->opregion.vbt;
+               if (memcmp(vbt->signature, "$VBT", 4) == 0) {
+                       DRM_DEBUG_KMS("Using VBT from OpRegion: %20s\n",
+                                        vbt->signature);
+                       bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset);
+               } else
+                       dev_priv->opregion.vbt = NULL;
+       }
 
-       /* Scour memory looking for the VBT signature */
-       for (i = 0; i + 4 < size; i++) {
-               if (!memcmp(bios + i, "$VBT", 4)) {
-                       vbt = (struct vbt_header *)(bios + i);
-                       break;
+       if (bdb == NULL) {
+               bios = pci_map_rom(pdev, &size);
+               if (!bios)
+                       return -1;
+
+               /* Scour memory looking for the VBT signature */
+               for (i = 0; i + 4 < size; i++) {
+                       if (!memcmp(bios + i, "$VBT", 4)) {
+                               vbt = (struct vbt_header *)(bios + i);
+                               break;
+                       }
                }
-       }
 
-       if (!vbt) {
-               dev_err(dev->dev, "VBT signature missing\n");
-               pci_unmap_rom(pdev, bios);
-               return -1;
+               if (!vbt) {
+                       dev_err(dev->dev, "VBT signature missing\n");
+                       pci_unmap_rom(pdev, bios);
+                       return -1;
+               }
+               bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset);
        }
 
-       bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset);
-
-       /* Grab useful general definitions */
+       /* Grab useful general dxefinitions */
        parse_general_features(dev_priv, bdb);
        parse_driver_features(dev_priv, bdb);
        parse_lfp_panel_data(dev_priv, bdb);
        parse_sdvo_panel_data(dev_priv, bdb);
+       parse_sdvo_device_mapping(dev_priv, bdb);
+       parse_device_mapping(dev_priv, bdb);
        parse_backlight_data(dev_priv, bdb);
 
-       pci_unmap_rom(pdev, bios);
+       if (bios)
+               pci_unmap_rom(pdev, bios);
 
        return 0;
 }
index c67979ef6f0a2d93b49372ff55428db11e7a896a..0a738663eb5adc4f82a7c32df6c586ed04b51d71 100644 (file)
@@ -127,9 +127,93 @@ struct bdb_general_features {
        /* bits 5 */
        u8 int_crt_support:1;
        u8 int_tv_support:1;
-       u8 rsvd11:6; /* finish byte */
+       u8 int_efp_support:1;
+       u8 dp_ssc_enb:1;        /* PCH attached eDP supports SSC */
+       u8 dp_ssc_freq:1;       /* SSC freq for PCH attached eDP */
+       u8 rsvd11:3; /* finish byte */
 } __attribute__((packed));
 
+/* pre-915 */
+#define GPIO_PIN_DVI_LVDS      0x03 /* "DVI/LVDS DDC GPIO pins" */
+#define GPIO_PIN_ADD_I2C       0x05 /* "ADDCARD I2C GPIO pins" */
+#define GPIO_PIN_ADD_DDC       0x04 /* "ADDCARD DDC GPIO pins" */
+#define GPIO_PIN_ADD_DDC_I2C   0x06 /* "ADDCARD DDC/I2C GPIO pins" */
+
+/* Pre 915 */
+#define DEVICE_TYPE_NONE       0x00
+#define DEVICE_TYPE_CRT                0x01
+#define DEVICE_TYPE_TV         0x09
+#define DEVICE_TYPE_EFP                0x12
+#define DEVICE_TYPE_LFP                0x22
+/* On 915+ */
+#define DEVICE_TYPE_CRT_DPMS           0x6001
+#define DEVICE_TYPE_CRT_DPMS_HOTPLUG   0x4001
+#define DEVICE_TYPE_TV_COMPOSITE       0x0209
+#define DEVICE_TYPE_TV_MACROVISION     0x0289
+#define DEVICE_TYPE_TV_RF_COMPOSITE    0x020c
+#define DEVICE_TYPE_TV_SVIDEO_COMPOSITE        0x0609
+#define DEVICE_TYPE_TV_SCART           0x0209
+#define DEVICE_TYPE_TV_CODEC_HOTPLUG_PWR 0x6009
+#define DEVICE_TYPE_EFP_HOTPLUG_PWR    0x6012
+#define DEVICE_TYPE_EFP_DVI_HOTPLUG_PWR        0x6052
+#define DEVICE_TYPE_EFP_DVI_I          0x6053
+#define DEVICE_TYPE_EFP_DVI_D_DUAL     0x6152
+#define DEVICE_TYPE_EFP_DVI_D_HDCP     0x60d2
+#define DEVICE_TYPE_OPENLDI_HOTPLUG_PWR        0x6062
+#define DEVICE_TYPE_OPENLDI_DUALPIX    0x6162
+#define DEVICE_TYPE_LFP_PANELLINK      0x5012
+#define DEVICE_TYPE_LFP_CMOS_PWR       0x5042
+#define DEVICE_TYPE_LFP_LVDS_PWR       0x5062
+#define DEVICE_TYPE_LFP_LVDS_DUAL      0x5162
+#define DEVICE_TYPE_LFP_LVDS_DUAL_HDCP 0x51e2
+
+#define DEVICE_CFG_NONE                0x00
+#define DEVICE_CFG_12BIT_DVOB  0x01
+#define DEVICE_CFG_12BIT_DVOC  0x02
+#define DEVICE_CFG_24BIT_DVOBC 0x09
+#define DEVICE_CFG_24BIT_DVOCB 0x0a
+#define DEVICE_CFG_DUAL_DVOB   0x11
+#define DEVICE_CFG_DUAL_DVOC   0x12
+#define DEVICE_CFG_DUAL_DVOBC  0x13
+#define DEVICE_CFG_DUAL_LINK_DVOBC     0x19
+#define DEVICE_CFG_DUAL_LINK_DVOCB     0x1a
+
+#define DEVICE_WIRE_NONE       0x00
+#define DEVICE_WIRE_DVOB       0x01
+#define DEVICE_WIRE_DVOC       0x02
+#define DEVICE_WIRE_DVOBC      0x03
+#define DEVICE_WIRE_DVOBB      0x05
+#define DEVICE_WIRE_DVOCC      0x06
+#define DEVICE_WIRE_DVOB_MASTER 0x0d
+#define DEVICE_WIRE_DVOC_MASTER 0x0e
+
+#define DEVICE_PORT_DVOA       0x00 /* none on 845+ */
+#define DEVICE_PORT_DVOB       0x01
+#define DEVICE_PORT_DVOC       0x02
+
+struct child_device_config {
+       u16 handle;
+       u16 device_type;
+       u8  device_id[10]; /* ascii string */
+       u16 addin_offset;
+       u8  dvo_port; /* See Device_PORT_* above */
+       u8  i2c_pin;
+       u8  slave_addr;
+       u8  ddc_pin;
+       u16 edid_ptr;
+       u8  dvo_cfg; /* See DEVICE_CFG_* above */
+       u8  dvo2_port;
+       u8  i2c2_pin;
+       u8  slave2_addr;
+       u8  ddc2_pin;
+       u8  capabilities;
+       u8  dvo_wiring;/* See DEVICE_WIRE_* above */
+       u8  dvo2_wiring;
+       u16 extended_type;
+       u8  dvo_function;
+} __attribute__((packed));
+
+
 struct bdb_general_definitions {
        /* DDC GPIO */
        u8 crt_ddc_gmbus_pin;
@@ -144,13 +228,18 @@ struct bdb_general_definitions {
        u8 boot_display[2];
        u8 child_dev_size;
 
-       /* device info */
-       u8 tv_or_lvds_info[33];
-       u8 dev1[33];
-       u8 dev2[33];
-       u8 dev3[33];
-       u8 dev4[33];
-       /* may be another device block here on some platforms */
+       /*
+        * Device info:
+        * If TV is present, it'll be at devices[0].
+        * LVDS will be next, either devices[0] or [1], if present.
+        * On some platforms the number of device is 6. But could be as few as
+        * 4 if both TV and LVDS are missing.
+        * And the device num is related with the size of general definition
+        * block. It is obtained by using the following formula:
+        * number = (block_size - sizeof(bdb_general_definitions))/
+        *           sizeof(child_device_config);
+        */
+       struct child_device_config devices[0];
 };
 
 struct bdb_lvds_options {
@@ -466,4 +555,21 @@ extern void psb_intel_destroy_bios(struct drm_device *dev);
 #define   SWF14_APM_STANDBY    0x1
 #define   SWF14_APM_RESTORE    0x0
 
+/* Add the device class for LFP, TV, HDMI */
+#define         DEVICE_TYPE_INT_LFP    0x1022
+#define         DEVICE_TYPE_INT_TV     0x1009
+#define         DEVICE_TYPE_HDMI       0x60D2
+#define         DEVICE_TYPE_DP         0x68C6
+#define         DEVICE_TYPE_eDP        0x78C6
+
+/* define the DVO port for HDMI output type */
+#define                DVO_B           1
+#define                DVO_C           2
+#define                DVO_D           3
+
+/* define the PORT for DP output type */
+#define                PORT_IDPB       7
+#define                PORT_IDPC       8
+#define                PORT_IDPD       9
+
 #endif /* _I830_BIOS_H_ */
index d946bc1b17bf05999126ae719a8e250d65d4056c..7041f40affff97b85aab5292fcd6f0159e48a00f 100644 (file)
 
 #include "psb_drv.h"
 
+#define PCI_ASLE 0xe4
+#define PCI_ASLS 0xfc
+
+#define OPREGION_HEADER_OFFSET 0
+#define OPREGION_ACPI_OFFSET   0x100
+#define   ACPI_CLID 0x01ac /* current lid state indicator */
+#define   ACPI_CDCK 0x01b0 /* current docking state indicator */
+#define OPREGION_SWSCI_OFFSET  0x200
+#define OPREGION_ASLE_OFFSET   0x300
+#define OPREGION_VBT_OFFSET    0x400
+
+#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;
@@ -36,21 +52,94 @@ struct opregion_header {
        u8 reserved[164];
 } __packed;
 
-struct opregion_apci {
-       /*FIXME: add it later*/
-} __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 {
-       /*FIXME: add it later*/
-} __packed;
+       u32 scic;       /* SWSCI command|status|data */
+       u32 parm;       /* command parameters */
+       u32 dslp;       /* driver sleep time-out */
+       u8 rsvd[244];
+} __attribute__((packed));
 
-struct opregion_acpi {
-       /*FIXME: add it later*/
-} __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)
 
 int gma_intel_opregion_init(struct drm_device *dev)
 {
        struct drm_psb_private *dev_priv = dev->dev_private;
+       struct psb_intel_opregion *opregion = &dev_priv->opregion;
        u32 opregion_phy;
        void *base;
        u32 *lid_state;
@@ -64,18 +153,26 @@ int gma_intel_opregion_init(struct drm_device *dev)
        base = ioremap(opregion_phy, 8*1024);
        if (!base)
                return -ENOMEM;
+       /* FIXME: should use _io ops - ditto on i915 */
+       if (memcmp(base, OPREGION_SIGNATURE, 16)) {
+               DRM_ERROR("opregion signature mismatch\n");
+               iounmap(base);
+               return -EINVAL;
+       }
 
        lid_state = base + 0x01ac;
 
        dev_priv->lid_state = lid_state;
        dev_priv->lid_last_state = readl(lid_state);
+       opregion->header = base;
+       opregion->vbt = base + OPREGION_VBT_OFFSET;
        return 0;
 }
 
 int gma_intel_opregion_exit(struct drm_device *dev)
 {
        struct drm_psb_private *dev_priv = dev->dev_private;
-       if (dev_priv->lid_state)
-               iounmap(dev_priv->lid_state);
+       if (dev_priv->opregion.header)
+               iounmap(dev_priv->opregion.header);
        return 0;
 }
index 4c50969fd193edf6059b0123f270f2d358392e88..64de248558b2bb360afceef21347fba2e817293e 100644 (file)
@@ -257,6 +257,7 @@ struct psb_intel_opregion {
        struct opregion_acpi *acpi;
        struct opregion_swsci *swsci;
        struct opregion_asle *asle;
+       void *vbt;
        int enabled;
 };
 
@@ -494,6 +495,9 @@ struct psb_ops;
 struct drm_psb_private {
        struct drm_device *dev;
        const struct psb_ops *ops;
+       
+       struct child_device_config *child_dev;
+       int child_dev_num;
 
        struct psb_gtt gtt;