xref: /OK3568_Linux_fs/kernel/drivers/gpu/drm/gma500/opregion.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright 2011 Intel Corporation
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person obtaining a
5*4882a593Smuzhiyun  * copy of this software and associated documentation files (the "Software"),
6*4882a593Smuzhiyun  * to deal in the Software without restriction, including without limitation
7*4882a593Smuzhiyun  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*4882a593Smuzhiyun  * and/or sell copies of the Software, and to permit persons to whom the
9*4882a593Smuzhiyun  * Software is furnished to do so, subject to the following conditions:
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * The above copyright notice and this permission notice (including the next
12*4882a593Smuzhiyun  * paragraph) shall be included in all copies or substantial portions of the
13*4882a593Smuzhiyun  * Software.
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*4882a593Smuzhiyun  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*4882a593Smuzhiyun  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*4882a593Smuzhiyun  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*4882a593Smuzhiyun  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*4882a593Smuzhiyun  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21*4882a593Smuzhiyun  * DEALINGS IN THE SOFTWARE.
22*4882a593Smuzhiyun  *
23*4882a593Smuzhiyun  */
24*4882a593Smuzhiyun #include <linux/acpi.h>
25*4882a593Smuzhiyun #include "psb_drv.h"
26*4882a593Smuzhiyun #include "psb_intel_reg.h"
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #define PCI_ASLE 0xe4
29*4882a593Smuzhiyun #define PCI_ASLS 0xfc
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #define OPREGION_HEADER_OFFSET 0
32*4882a593Smuzhiyun #define OPREGION_ACPI_OFFSET   0x100
33*4882a593Smuzhiyun #define   ACPI_CLID 0x01ac /* current lid state indicator */
34*4882a593Smuzhiyun #define   ACPI_CDCK 0x01b0 /* current docking state indicator */
35*4882a593Smuzhiyun #define OPREGION_SWSCI_OFFSET  0x200
36*4882a593Smuzhiyun #define OPREGION_ASLE_OFFSET   0x300
37*4882a593Smuzhiyun #define OPREGION_VBT_OFFSET    0x400
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun #define OPREGION_SIGNATURE "IntelGraphicsMem"
40*4882a593Smuzhiyun #define MBOX_ACPI      (1<<0)
41*4882a593Smuzhiyun #define MBOX_SWSCI     (1<<1)
42*4882a593Smuzhiyun #define MBOX_ASLE      (1<<2)
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun struct opregion_header {
45*4882a593Smuzhiyun 	u8 signature[16];
46*4882a593Smuzhiyun 	u32 size;
47*4882a593Smuzhiyun 	u32 opregion_ver;
48*4882a593Smuzhiyun 	u8 bios_ver[32];
49*4882a593Smuzhiyun 	u8 vbios_ver[16];
50*4882a593Smuzhiyun 	u8 driver_ver[16];
51*4882a593Smuzhiyun 	u32 mboxes;
52*4882a593Smuzhiyun 	u8 reserved[164];
53*4882a593Smuzhiyun } __packed;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun /* OpRegion mailbox #1: public ACPI methods */
56*4882a593Smuzhiyun struct opregion_acpi {
57*4882a593Smuzhiyun 	u32 drdy;	/* driver readiness */
58*4882a593Smuzhiyun 	u32 csts;	/* notification status */
59*4882a593Smuzhiyun 	u32 cevt;	/* current event */
60*4882a593Smuzhiyun 	u8 rsvd1[20];
61*4882a593Smuzhiyun 	u32 didl[8];	/* supported display devices ID list */
62*4882a593Smuzhiyun 	u32 cpdl[8];	/* currently presented display list */
63*4882a593Smuzhiyun 	u32 cadl[8];	/* currently active display list */
64*4882a593Smuzhiyun 	u32 nadl[8];	/* next active devices list */
65*4882a593Smuzhiyun 	u32 aslp;	/* ASL sleep time-out */
66*4882a593Smuzhiyun 	u32 tidx;	/* toggle table index */
67*4882a593Smuzhiyun 	u32 chpd;	/* current hotplug enable indicator */
68*4882a593Smuzhiyun 	u32 clid;	/* current lid state*/
69*4882a593Smuzhiyun 	u32 cdck;	/* current docking state */
70*4882a593Smuzhiyun 	u32 sxsw;	/* Sx state resume */
71*4882a593Smuzhiyun 	u32 evts;	/* ASL supported events */
72*4882a593Smuzhiyun 	u32 cnot;	/* current OS notification */
73*4882a593Smuzhiyun 	u32 nrdy;	/* driver status */
74*4882a593Smuzhiyun 	u8 rsvd2[60];
75*4882a593Smuzhiyun } __packed;
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun /* OpRegion mailbox #2: SWSCI */
78*4882a593Smuzhiyun struct opregion_swsci {
79*4882a593Smuzhiyun 	/*FIXME: add it later*/
80*4882a593Smuzhiyun } __packed;
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun /* OpRegion mailbox #3: ASLE */
83*4882a593Smuzhiyun struct opregion_asle {
84*4882a593Smuzhiyun 	u32 ardy;	/* driver readiness */
85*4882a593Smuzhiyun 	u32 aslc;	/* ASLE interrupt command */
86*4882a593Smuzhiyun 	u32 tche;	/* technology enabled indicator */
87*4882a593Smuzhiyun 	u32 alsi;	/* current ALS illuminance reading */
88*4882a593Smuzhiyun 	u32 bclp;	/* backlight brightness to set */
89*4882a593Smuzhiyun 	u32 pfit;	/* panel fitting state */
90*4882a593Smuzhiyun 	u32 cblv;	/* current brightness level */
91*4882a593Smuzhiyun 	u16 bclm[20];	/* backlight level duty cycle mapping table */
92*4882a593Smuzhiyun 	u32 cpfm;	/* current panel fitting mode */
93*4882a593Smuzhiyun 	u32 epfm;	/* enabled panel fitting modes */
94*4882a593Smuzhiyun 	u8 plut[74];	/* panel LUT and identifier */
95*4882a593Smuzhiyun 	u32 pfmb;	/* PWM freq and min brightness */
96*4882a593Smuzhiyun 	u8 rsvd[102];
97*4882a593Smuzhiyun } __packed;
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun /* ASLE irq request bits */
100*4882a593Smuzhiyun #define ASLE_SET_ALS_ILLUM     (1 << 0)
101*4882a593Smuzhiyun #define ASLE_SET_BACKLIGHT     (1 << 1)
102*4882a593Smuzhiyun #define ASLE_SET_PFIT          (1 << 2)
103*4882a593Smuzhiyun #define ASLE_SET_PWM_FREQ      (1 << 3)
104*4882a593Smuzhiyun #define ASLE_REQ_MSK           0xf
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun /* response bits of ASLE irq request */
107*4882a593Smuzhiyun #define ASLE_ALS_ILLUM_FAILED   (1<<10)
108*4882a593Smuzhiyun #define ASLE_BACKLIGHT_FAILED   (1<<12)
109*4882a593Smuzhiyun #define ASLE_PFIT_FAILED        (1<<14)
110*4882a593Smuzhiyun #define ASLE_PWM_FREQ_FAILED    (1<<16)
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun /* ASLE backlight brightness to set */
113*4882a593Smuzhiyun #define ASLE_BCLP_VALID                (1<<31)
114*4882a593Smuzhiyun #define ASLE_BCLP_MSK          (~(1<<31))
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun /* ASLE panel fitting request */
117*4882a593Smuzhiyun #define ASLE_PFIT_VALID         (1<<31)
118*4882a593Smuzhiyun #define ASLE_PFIT_CENTER (1<<0)
119*4882a593Smuzhiyun #define ASLE_PFIT_STRETCH_TEXT (1<<1)
120*4882a593Smuzhiyun #define ASLE_PFIT_STRETCH_GFX (1<<2)
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun /* response bits of ASLE irq request */
123*4882a593Smuzhiyun #define ASLE_ALS_ILLUM_FAILED	(1<<10)
124*4882a593Smuzhiyun #define ASLE_BACKLIGHT_FAILED	(1<<12)
125*4882a593Smuzhiyun #define ASLE_PFIT_FAILED	(1<<14)
126*4882a593Smuzhiyun #define ASLE_PWM_FREQ_FAILED	(1<<16)
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun /* ASLE backlight brightness to set */
129*4882a593Smuzhiyun #define ASLE_BCLP_VALID                (1<<31)
130*4882a593Smuzhiyun #define ASLE_BCLP_MSK          (~(1<<31))
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun /* ASLE panel fitting request */
133*4882a593Smuzhiyun #define ASLE_PFIT_VALID         (1<<31)
134*4882a593Smuzhiyun #define ASLE_PFIT_CENTER (1<<0)
135*4882a593Smuzhiyun #define ASLE_PFIT_STRETCH_TEXT (1<<1)
136*4882a593Smuzhiyun #define ASLE_PFIT_STRETCH_GFX (1<<2)
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun /* PWM frequency and minimum brightness */
139*4882a593Smuzhiyun #define ASLE_PFMB_BRIGHTNESS_MASK (0xff)
140*4882a593Smuzhiyun #define ASLE_PFMB_BRIGHTNESS_VALID (1<<8)
141*4882a593Smuzhiyun #define ASLE_PFMB_PWM_MASK (0x7ffffe00)
142*4882a593Smuzhiyun #define ASLE_PFMB_PWM_VALID (1<<31)
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun #define ASLE_CBLV_VALID         (1<<31)
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun static struct psb_intel_opregion *system_opregion;
147*4882a593Smuzhiyun 
asle_set_backlight(struct drm_device * dev,u32 bclp)148*4882a593Smuzhiyun static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun 	struct drm_psb_private *dev_priv = dev->dev_private;
151*4882a593Smuzhiyun 	struct opregion_asle *asle = dev_priv->opregion.asle;
152*4882a593Smuzhiyun 	struct backlight_device *bd = dev_priv->backlight_device;
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	DRM_DEBUG_DRIVER("asle set backlight %x\n", bclp);
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun 	if (!(bclp & ASLE_BCLP_VALID))
157*4882a593Smuzhiyun 		return ASLE_BACKLIGHT_FAILED;
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	if (bd == NULL)
160*4882a593Smuzhiyun 		return ASLE_BACKLIGHT_FAILED;
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	bclp &= ASLE_BCLP_MSK;
163*4882a593Smuzhiyun 	if (bclp > 255)
164*4882a593Smuzhiyun 		return ASLE_BACKLIGHT_FAILED;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	gma_backlight_set(dev, bclp * bd->props.max_brightness / 255);
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 	asle->cblv = (bclp * 0x64) / 0xff | ASLE_CBLV_VALID;
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	return 0;
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun 
psb_intel_opregion_asle_work(struct work_struct * work)173*4882a593Smuzhiyun static void psb_intel_opregion_asle_work(struct work_struct *work)
174*4882a593Smuzhiyun {
175*4882a593Smuzhiyun 	struct psb_intel_opregion *opregion =
176*4882a593Smuzhiyun 		container_of(work, struct psb_intel_opregion, asle_work);
177*4882a593Smuzhiyun 	struct drm_psb_private *dev_priv =
178*4882a593Smuzhiyun 		container_of(opregion, struct drm_psb_private, opregion);
179*4882a593Smuzhiyun 	struct opregion_asle *asle = opregion->asle;
180*4882a593Smuzhiyun 	u32 asle_stat = 0;
181*4882a593Smuzhiyun 	u32 asle_req;
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	if (!asle)
184*4882a593Smuzhiyun 		return;
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun 	asle_req = asle->aslc & ASLE_REQ_MSK;
187*4882a593Smuzhiyun 	if (!asle_req) {
188*4882a593Smuzhiyun 		DRM_DEBUG_DRIVER("non asle set request??\n");
189*4882a593Smuzhiyun 		return;
190*4882a593Smuzhiyun 	}
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	if (asle_req & ASLE_SET_BACKLIGHT)
193*4882a593Smuzhiyun 		asle_stat |= asle_set_backlight(dev_priv->dev, asle->bclp);
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun 	asle->aslc = asle_stat;
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun 
psb_intel_opregion_asle_intr(struct drm_device * dev)199*4882a593Smuzhiyun void psb_intel_opregion_asle_intr(struct drm_device *dev)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun 	struct drm_psb_private *dev_priv = dev->dev_private;
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	if (dev_priv->opregion.asle)
204*4882a593Smuzhiyun 		schedule_work(&dev_priv->opregion.asle_work);
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun #define ASLE_ALS_EN    (1<<0)
208*4882a593Smuzhiyun #define ASLE_BLC_EN    (1<<1)
209*4882a593Smuzhiyun #define ASLE_PFIT_EN   (1<<2)
210*4882a593Smuzhiyun #define ASLE_PFMB_EN   (1<<3)
211*4882a593Smuzhiyun 
psb_intel_opregion_enable_asle(struct drm_device * dev)212*4882a593Smuzhiyun void psb_intel_opregion_enable_asle(struct drm_device *dev)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun 	struct drm_psb_private *dev_priv = dev->dev_private;
215*4882a593Smuzhiyun 	struct opregion_asle *asle = dev_priv->opregion.asle;
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	if (asle && system_opregion ) {
218*4882a593Smuzhiyun 		/* Don't do this on Medfield or other non PC like devices, they
219*4882a593Smuzhiyun 		   use the bit for something different altogether */
220*4882a593Smuzhiyun 		psb_enable_pipestat(dev_priv, 0, PIPE_LEGACY_BLC_EVENT_ENABLE);
221*4882a593Smuzhiyun 		psb_enable_pipestat(dev_priv, 1, PIPE_LEGACY_BLC_EVENT_ENABLE);
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 		asle->tche = ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN
224*4882a593Smuzhiyun 								| ASLE_PFMB_EN;
225*4882a593Smuzhiyun 		asle->ardy = 1;
226*4882a593Smuzhiyun 	}
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun #define ACPI_EV_DISPLAY_SWITCH (1<<0)
230*4882a593Smuzhiyun #define ACPI_EV_LID            (1<<1)
231*4882a593Smuzhiyun #define ACPI_EV_DOCK           (1<<2)
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 
psb_intel_opregion_video_event(struct notifier_block * nb,unsigned long val,void * data)234*4882a593Smuzhiyun static int psb_intel_opregion_video_event(struct notifier_block *nb,
235*4882a593Smuzhiyun 					  unsigned long val, void *data)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun 	/* The only video events relevant to opregion are 0x80. These indicate
238*4882a593Smuzhiyun 	   either a docking event, lid switch or display switch request. In
239*4882a593Smuzhiyun 	   Linux, these are handled by the dock, button and video drivers.
240*4882a593Smuzhiyun 	   We might want to fix the video driver to be opregion-aware in
241*4882a593Smuzhiyun 	   future, but right now we just indicate to the firmware that the
242*4882a593Smuzhiyun 	   request has been handled */
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	struct opregion_acpi *acpi;
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	if (!system_opregion)
247*4882a593Smuzhiyun 		return NOTIFY_DONE;
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun 	acpi = system_opregion->acpi;
250*4882a593Smuzhiyun 	acpi->csts = 0;
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	return NOTIFY_OK;
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun static struct notifier_block psb_intel_opregion_notifier = {
256*4882a593Smuzhiyun 	.notifier_call = psb_intel_opregion_video_event,
257*4882a593Smuzhiyun };
258*4882a593Smuzhiyun 
psb_intel_opregion_init(struct drm_device * dev)259*4882a593Smuzhiyun void psb_intel_opregion_init(struct drm_device *dev)
260*4882a593Smuzhiyun {
261*4882a593Smuzhiyun 	struct drm_psb_private *dev_priv = dev->dev_private;
262*4882a593Smuzhiyun 	struct psb_intel_opregion *opregion = &dev_priv->opregion;
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	if (!opregion->header)
265*4882a593Smuzhiyun 		return;
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	if (opregion->acpi) {
268*4882a593Smuzhiyun 		/* Notify BIOS we are ready to handle ACPI video ext notifs.
269*4882a593Smuzhiyun 		 * Right now, all the events are handled by the ACPI video
270*4882a593Smuzhiyun 		 * module. We don't actually need to do anything with them. */
271*4882a593Smuzhiyun 		opregion->acpi->csts = 0;
272*4882a593Smuzhiyun 		opregion->acpi->drdy = 1;
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 		system_opregion = opregion;
275*4882a593Smuzhiyun 		register_acpi_notifier(&psb_intel_opregion_notifier);
276*4882a593Smuzhiyun 	}
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun 
psb_intel_opregion_fini(struct drm_device * dev)279*4882a593Smuzhiyun void psb_intel_opregion_fini(struct drm_device *dev)
280*4882a593Smuzhiyun {
281*4882a593Smuzhiyun 	struct drm_psb_private *dev_priv = dev->dev_private;
282*4882a593Smuzhiyun 	struct psb_intel_opregion *opregion = &dev_priv->opregion;
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	if (!opregion->header)
285*4882a593Smuzhiyun 		return;
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 	if (opregion->acpi) {
288*4882a593Smuzhiyun 		opregion->acpi->drdy = 0;
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 		system_opregion = NULL;
291*4882a593Smuzhiyun 		unregister_acpi_notifier(&psb_intel_opregion_notifier);
292*4882a593Smuzhiyun 	}
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 	cancel_work_sync(&opregion->asle_work);
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	/* just clear all opregion memory pointers now */
297*4882a593Smuzhiyun 	iounmap(opregion->header);
298*4882a593Smuzhiyun 	opregion->header = NULL;
299*4882a593Smuzhiyun 	opregion->acpi = NULL;
300*4882a593Smuzhiyun 	opregion->swsci = NULL;
301*4882a593Smuzhiyun 	opregion->asle = NULL;
302*4882a593Smuzhiyun 	opregion->vbt = NULL;
303*4882a593Smuzhiyun }
304*4882a593Smuzhiyun 
psb_intel_opregion_setup(struct drm_device * dev)305*4882a593Smuzhiyun int psb_intel_opregion_setup(struct drm_device *dev)
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun 	struct drm_psb_private *dev_priv = dev->dev_private;
308*4882a593Smuzhiyun 	struct psb_intel_opregion *opregion = &dev_priv->opregion;
309*4882a593Smuzhiyun 	u32 opregion_phy, mboxes;
310*4882a593Smuzhiyun 	void __iomem *base;
311*4882a593Smuzhiyun 	int err = 0;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	pci_read_config_dword(dev->pdev, PCI_ASLS, &opregion_phy);
314*4882a593Smuzhiyun 	if (opregion_phy == 0) {
315*4882a593Smuzhiyun 		DRM_DEBUG_DRIVER("ACPI Opregion not supported\n");
316*4882a593Smuzhiyun 		return -ENOTSUPP;
317*4882a593Smuzhiyun 	}
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 	INIT_WORK(&opregion->asle_work, psb_intel_opregion_asle_work);
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 	DRM_DEBUG("OpRegion detected at 0x%8x\n", opregion_phy);
322*4882a593Smuzhiyun 	base = acpi_os_ioremap(opregion_phy, 8*1024);
323*4882a593Smuzhiyun 	if (!base)
324*4882a593Smuzhiyun 		return -ENOMEM;
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	if (memcmp(base, OPREGION_SIGNATURE, 16)) {
327*4882a593Smuzhiyun 		DRM_DEBUG_DRIVER("opregion signature mismatch\n");
328*4882a593Smuzhiyun 		err = -EINVAL;
329*4882a593Smuzhiyun 		goto err_out;
330*4882a593Smuzhiyun 	}
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	opregion->header = base;
333*4882a593Smuzhiyun 	opregion->vbt = base + OPREGION_VBT_OFFSET;
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	opregion->lid_state = base + ACPI_CLID;
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	mboxes = opregion->header->mboxes;
338*4882a593Smuzhiyun 	if (mboxes & MBOX_ACPI) {
339*4882a593Smuzhiyun 		DRM_DEBUG_DRIVER("Public ACPI methods supported\n");
340*4882a593Smuzhiyun 		opregion->acpi = base + OPREGION_ACPI_OFFSET;
341*4882a593Smuzhiyun 	}
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	if (mboxes & MBOX_ASLE) {
344*4882a593Smuzhiyun 		DRM_DEBUG_DRIVER("ASLE supported\n");
345*4882a593Smuzhiyun 		opregion->asle = base + OPREGION_ASLE_OFFSET;
346*4882a593Smuzhiyun 	}
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	return 0;
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun err_out:
351*4882a593Smuzhiyun 	iounmap(base);
352*4882a593Smuzhiyun 	return err;
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun 
355