18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright 2011 Intel Corporation 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 58c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 68c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation 78c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 88c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 98c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice (including the next 128c2ecf20Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 138c2ecf20Sopenharmony_ci * Software. 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 168c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 178c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 188c2ecf20Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 198c2ecf20Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 208c2ecf20Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 218c2ecf20Sopenharmony_ci * DEALINGS IN THE SOFTWARE. 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci */ 248c2ecf20Sopenharmony_ci#include <linux/acpi.h> 258c2ecf20Sopenharmony_ci#include "psb_drv.h" 268c2ecf20Sopenharmony_ci#include "psb_intel_reg.h" 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define PCI_ASLE 0xe4 298c2ecf20Sopenharmony_ci#define PCI_ASLS 0xfc 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#define OPREGION_HEADER_OFFSET 0 328c2ecf20Sopenharmony_ci#define OPREGION_ACPI_OFFSET 0x100 338c2ecf20Sopenharmony_ci#define ACPI_CLID 0x01ac /* current lid state indicator */ 348c2ecf20Sopenharmony_ci#define ACPI_CDCK 0x01b0 /* current docking state indicator */ 358c2ecf20Sopenharmony_ci#define OPREGION_SWSCI_OFFSET 0x200 368c2ecf20Sopenharmony_ci#define OPREGION_ASLE_OFFSET 0x300 378c2ecf20Sopenharmony_ci#define OPREGION_VBT_OFFSET 0x400 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#define OPREGION_SIGNATURE "IntelGraphicsMem" 408c2ecf20Sopenharmony_ci#define MBOX_ACPI (1<<0) 418c2ecf20Sopenharmony_ci#define MBOX_SWSCI (1<<1) 428c2ecf20Sopenharmony_ci#define MBOX_ASLE (1<<2) 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cistruct opregion_header { 458c2ecf20Sopenharmony_ci u8 signature[16]; 468c2ecf20Sopenharmony_ci u32 size; 478c2ecf20Sopenharmony_ci u32 opregion_ver; 488c2ecf20Sopenharmony_ci u8 bios_ver[32]; 498c2ecf20Sopenharmony_ci u8 vbios_ver[16]; 508c2ecf20Sopenharmony_ci u8 driver_ver[16]; 518c2ecf20Sopenharmony_ci u32 mboxes; 528c2ecf20Sopenharmony_ci u8 reserved[164]; 538c2ecf20Sopenharmony_ci} __packed; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci/* OpRegion mailbox #1: public ACPI methods */ 568c2ecf20Sopenharmony_cistruct opregion_acpi { 578c2ecf20Sopenharmony_ci u32 drdy; /* driver readiness */ 588c2ecf20Sopenharmony_ci u32 csts; /* notification status */ 598c2ecf20Sopenharmony_ci u32 cevt; /* current event */ 608c2ecf20Sopenharmony_ci u8 rsvd1[20]; 618c2ecf20Sopenharmony_ci u32 didl[8]; /* supported display devices ID list */ 628c2ecf20Sopenharmony_ci u32 cpdl[8]; /* currently presented display list */ 638c2ecf20Sopenharmony_ci u32 cadl[8]; /* currently active display list */ 648c2ecf20Sopenharmony_ci u32 nadl[8]; /* next active devices list */ 658c2ecf20Sopenharmony_ci u32 aslp; /* ASL sleep time-out */ 668c2ecf20Sopenharmony_ci u32 tidx; /* toggle table index */ 678c2ecf20Sopenharmony_ci u32 chpd; /* current hotplug enable indicator */ 688c2ecf20Sopenharmony_ci u32 clid; /* current lid state*/ 698c2ecf20Sopenharmony_ci u32 cdck; /* current docking state */ 708c2ecf20Sopenharmony_ci u32 sxsw; /* Sx state resume */ 718c2ecf20Sopenharmony_ci u32 evts; /* ASL supported events */ 728c2ecf20Sopenharmony_ci u32 cnot; /* current OS notification */ 738c2ecf20Sopenharmony_ci u32 nrdy; /* driver status */ 748c2ecf20Sopenharmony_ci u8 rsvd2[60]; 758c2ecf20Sopenharmony_ci} __packed; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci/* OpRegion mailbox #2: SWSCI */ 788c2ecf20Sopenharmony_cistruct opregion_swsci { 798c2ecf20Sopenharmony_ci /*FIXME: add it later*/ 808c2ecf20Sopenharmony_ci} __packed; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci/* OpRegion mailbox #3: ASLE */ 838c2ecf20Sopenharmony_cistruct opregion_asle { 848c2ecf20Sopenharmony_ci u32 ardy; /* driver readiness */ 858c2ecf20Sopenharmony_ci u32 aslc; /* ASLE interrupt command */ 868c2ecf20Sopenharmony_ci u32 tche; /* technology enabled indicator */ 878c2ecf20Sopenharmony_ci u32 alsi; /* current ALS illuminance reading */ 888c2ecf20Sopenharmony_ci u32 bclp; /* backlight brightness to set */ 898c2ecf20Sopenharmony_ci u32 pfit; /* panel fitting state */ 908c2ecf20Sopenharmony_ci u32 cblv; /* current brightness level */ 918c2ecf20Sopenharmony_ci u16 bclm[20]; /* backlight level duty cycle mapping table */ 928c2ecf20Sopenharmony_ci u32 cpfm; /* current panel fitting mode */ 938c2ecf20Sopenharmony_ci u32 epfm; /* enabled panel fitting modes */ 948c2ecf20Sopenharmony_ci u8 plut[74]; /* panel LUT and identifier */ 958c2ecf20Sopenharmony_ci u32 pfmb; /* PWM freq and min brightness */ 968c2ecf20Sopenharmony_ci u8 rsvd[102]; 978c2ecf20Sopenharmony_ci} __packed; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci/* ASLE irq request bits */ 1008c2ecf20Sopenharmony_ci#define ASLE_SET_ALS_ILLUM (1 << 0) 1018c2ecf20Sopenharmony_ci#define ASLE_SET_BACKLIGHT (1 << 1) 1028c2ecf20Sopenharmony_ci#define ASLE_SET_PFIT (1 << 2) 1038c2ecf20Sopenharmony_ci#define ASLE_SET_PWM_FREQ (1 << 3) 1048c2ecf20Sopenharmony_ci#define ASLE_REQ_MSK 0xf 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci/* response bits of ASLE irq request */ 1078c2ecf20Sopenharmony_ci#define ASLE_ALS_ILLUM_FAILED (1<<10) 1088c2ecf20Sopenharmony_ci#define ASLE_BACKLIGHT_FAILED (1<<12) 1098c2ecf20Sopenharmony_ci#define ASLE_PFIT_FAILED (1<<14) 1108c2ecf20Sopenharmony_ci#define ASLE_PWM_FREQ_FAILED (1<<16) 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci/* ASLE backlight brightness to set */ 1138c2ecf20Sopenharmony_ci#define ASLE_BCLP_VALID (1<<31) 1148c2ecf20Sopenharmony_ci#define ASLE_BCLP_MSK (~(1<<31)) 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci/* ASLE panel fitting request */ 1178c2ecf20Sopenharmony_ci#define ASLE_PFIT_VALID (1<<31) 1188c2ecf20Sopenharmony_ci#define ASLE_PFIT_CENTER (1<<0) 1198c2ecf20Sopenharmony_ci#define ASLE_PFIT_STRETCH_TEXT (1<<1) 1208c2ecf20Sopenharmony_ci#define ASLE_PFIT_STRETCH_GFX (1<<2) 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci/* response bits of ASLE irq request */ 1238c2ecf20Sopenharmony_ci#define ASLE_ALS_ILLUM_FAILED (1<<10) 1248c2ecf20Sopenharmony_ci#define ASLE_BACKLIGHT_FAILED (1<<12) 1258c2ecf20Sopenharmony_ci#define ASLE_PFIT_FAILED (1<<14) 1268c2ecf20Sopenharmony_ci#define ASLE_PWM_FREQ_FAILED (1<<16) 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci/* ASLE backlight brightness to set */ 1298c2ecf20Sopenharmony_ci#define ASLE_BCLP_VALID (1<<31) 1308c2ecf20Sopenharmony_ci#define ASLE_BCLP_MSK (~(1<<31)) 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci/* ASLE panel fitting request */ 1338c2ecf20Sopenharmony_ci#define ASLE_PFIT_VALID (1<<31) 1348c2ecf20Sopenharmony_ci#define ASLE_PFIT_CENTER (1<<0) 1358c2ecf20Sopenharmony_ci#define ASLE_PFIT_STRETCH_TEXT (1<<1) 1368c2ecf20Sopenharmony_ci#define ASLE_PFIT_STRETCH_GFX (1<<2) 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci/* PWM frequency and minimum brightness */ 1398c2ecf20Sopenharmony_ci#define ASLE_PFMB_BRIGHTNESS_MASK (0xff) 1408c2ecf20Sopenharmony_ci#define ASLE_PFMB_BRIGHTNESS_VALID (1<<8) 1418c2ecf20Sopenharmony_ci#define ASLE_PFMB_PWM_MASK (0x7ffffe00) 1428c2ecf20Sopenharmony_ci#define ASLE_PFMB_PWM_VALID (1<<31) 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci#define ASLE_CBLV_VALID (1<<31) 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cistatic struct psb_intel_opregion *system_opregion; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_cistatic u32 asle_set_backlight(struct drm_device *dev, u32 bclp) 1498c2ecf20Sopenharmony_ci{ 1508c2ecf20Sopenharmony_ci struct drm_psb_private *dev_priv = dev->dev_private; 1518c2ecf20Sopenharmony_ci struct opregion_asle *asle = dev_priv->opregion.asle; 1528c2ecf20Sopenharmony_ci struct backlight_device *bd = dev_priv->backlight_device; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci DRM_DEBUG_DRIVER("asle set backlight %x\n", bclp); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci if (!(bclp & ASLE_BCLP_VALID)) 1578c2ecf20Sopenharmony_ci return ASLE_BACKLIGHT_FAILED; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci if (bd == NULL) 1608c2ecf20Sopenharmony_ci return ASLE_BACKLIGHT_FAILED; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci bclp &= ASLE_BCLP_MSK; 1638c2ecf20Sopenharmony_ci if (bclp > 255) 1648c2ecf20Sopenharmony_ci return ASLE_BACKLIGHT_FAILED; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci gma_backlight_set(dev, bclp * bd->props.max_brightness / 255); 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci asle->cblv = (bclp * 0x64) / 0xff | ASLE_CBLV_VALID; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci return 0; 1718c2ecf20Sopenharmony_ci} 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_cistatic void psb_intel_opregion_asle_work(struct work_struct *work) 1748c2ecf20Sopenharmony_ci{ 1758c2ecf20Sopenharmony_ci struct psb_intel_opregion *opregion = 1768c2ecf20Sopenharmony_ci container_of(work, struct psb_intel_opregion, asle_work); 1778c2ecf20Sopenharmony_ci struct drm_psb_private *dev_priv = 1788c2ecf20Sopenharmony_ci container_of(opregion, struct drm_psb_private, opregion); 1798c2ecf20Sopenharmony_ci struct opregion_asle *asle = opregion->asle; 1808c2ecf20Sopenharmony_ci u32 asle_stat = 0; 1818c2ecf20Sopenharmony_ci u32 asle_req; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci if (!asle) 1848c2ecf20Sopenharmony_ci return; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci asle_req = asle->aslc & ASLE_REQ_MSK; 1878c2ecf20Sopenharmony_ci if (!asle_req) { 1888c2ecf20Sopenharmony_ci DRM_DEBUG_DRIVER("non asle set request??\n"); 1898c2ecf20Sopenharmony_ci return; 1908c2ecf20Sopenharmony_ci } 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci if (asle_req & ASLE_SET_BACKLIGHT) 1938c2ecf20Sopenharmony_ci asle_stat |= asle_set_backlight(dev_priv->dev, asle->bclp); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci asle->aslc = asle_stat; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci} 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_civoid psb_intel_opregion_asle_intr(struct drm_device *dev) 2008c2ecf20Sopenharmony_ci{ 2018c2ecf20Sopenharmony_ci struct drm_psb_private *dev_priv = dev->dev_private; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci if (dev_priv->opregion.asle) 2048c2ecf20Sopenharmony_ci schedule_work(&dev_priv->opregion.asle_work); 2058c2ecf20Sopenharmony_ci} 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci#define ASLE_ALS_EN (1<<0) 2088c2ecf20Sopenharmony_ci#define ASLE_BLC_EN (1<<1) 2098c2ecf20Sopenharmony_ci#define ASLE_PFIT_EN (1<<2) 2108c2ecf20Sopenharmony_ci#define ASLE_PFMB_EN (1<<3) 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_civoid psb_intel_opregion_enable_asle(struct drm_device *dev) 2138c2ecf20Sopenharmony_ci{ 2148c2ecf20Sopenharmony_ci struct drm_psb_private *dev_priv = dev->dev_private; 2158c2ecf20Sopenharmony_ci struct opregion_asle *asle = dev_priv->opregion.asle; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci if (asle && system_opregion ) { 2188c2ecf20Sopenharmony_ci /* Don't do this on Medfield or other non PC like devices, they 2198c2ecf20Sopenharmony_ci use the bit for something different altogether */ 2208c2ecf20Sopenharmony_ci psb_enable_pipestat(dev_priv, 0, PIPE_LEGACY_BLC_EVENT_ENABLE); 2218c2ecf20Sopenharmony_ci psb_enable_pipestat(dev_priv, 1, PIPE_LEGACY_BLC_EVENT_ENABLE); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci asle->tche = ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN 2248c2ecf20Sopenharmony_ci | ASLE_PFMB_EN; 2258c2ecf20Sopenharmony_ci asle->ardy = 1; 2268c2ecf20Sopenharmony_ci } 2278c2ecf20Sopenharmony_ci} 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci#define ACPI_EV_DISPLAY_SWITCH (1<<0) 2308c2ecf20Sopenharmony_ci#define ACPI_EV_LID (1<<1) 2318c2ecf20Sopenharmony_ci#define ACPI_EV_DOCK (1<<2) 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_cistatic int psb_intel_opregion_video_event(struct notifier_block *nb, 2358c2ecf20Sopenharmony_ci unsigned long val, void *data) 2368c2ecf20Sopenharmony_ci{ 2378c2ecf20Sopenharmony_ci /* The only video events relevant to opregion are 0x80. These indicate 2388c2ecf20Sopenharmony_ci either a docking event, lid switch or display switch request. In 2398c2ecf20Sopenharmony_ci Linux, these are handled by the dock, button and video drivers. 2408c2ecf20Sopenharmony_ci We might want to fix the video driver to be opregion-aware in 2418c2ecf20Sopenharmony_ci future, but right now we just indicate to the firmware that the 2428c2ecf20Sopenharmony_ci request has been handled */ 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci struct opregion_acpi *acpi; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci if (!system_opregion) 2478c2ecf20Sopenharmony_ci return NOTIFY_DONE; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci acpi = system_opregion->acpi; 2508c2ecf20Sopenharmony_ci acpi->csts = 0; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci return NOTIFY_OK; 2538c2ecf20Sopenharmony_ci} 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_cistatic struct notifier_block psb_intel_opregion_notifier = { 2568c2ecf20Sopenharmony_ci .notifier_call = psb_intel_opregion_video_event, 2578c2ecf20Sopenharmony_ci}; 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_civoid psb_intel_opregion_init(struct drm_device *dev) 2608c2ecf20Sopenharmony_ci{ 2618c2ecf20Sopenharmony_ci struct drm_psb_private *dev_priv = dev->dev_private; 2628c2ecf20Sopenharmony_ci struct psb_intel_opregion *opregion = &dev_priv->opregion; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci if (!opregion->header) 2658c2ecf20Sopenharmony_ci return; 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci if (opregion->acpi) { 2688c2ecf20Sopenharmony_ci /* Notify BIOS we are ready to handle ACPI video ext notifs. 2698c2ecf20Sopenharmony_ci * Right now, all the events are handled by the ACPI video 2708c2ecf20Sopenharmony_ci * module. We don't actually need to do anything with them. */ 2718c2ecf20Sopenharmony_ci opregion->acpi->csts = 0; 2728c2ecf20Sopenharmony_ci opregion->acpi->drdy = 1; 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci system_opregion = opregion; 2758c2ecf20Sopenharmony_ci register_acpi_notifier(&psb_intel_opregion_notifier); 2768c2ecf20Sopenharmony_ci } 2778c2ecf20Sopenharmony_ci} 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_civoid psb_intel_opregion_fini(struct drm_device *dev) 2808c2ecf20Sopenharmony_ci{ 2818c2ecf20Sopenharmony_ci struct drm_psb_private *dev_priv = dev->dev_private; 2828c2ecf20Sopenharmony_ci struct psb_intel_opregion *opregion = &dev_priv->opregion; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci if (!opregion->header) 2858c2ecf20Sopenharmony_ci return; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci if (opregion->acpi) { 2888c2ecf20Sopenharmony_ci opregion->acpi->drdy = 0; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci system_opregion = NULL; 2918c2ecf20Sopenharmony_ci unregister_acpi_notifier(&psb_intel_opregion_notifier); 2928c2ecf20Sopenharmony_ci } 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci cancel_work_sync(&opregion->asle_work); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci /* just clear all opregion memory pointers now */ 2978c2ecf20Sopenharmony_ci iounmap(opregion->header); 2988c2ecf20Sopenharmony_ci opregion->header = NULL; 2998c2ecf20Sopenharmony_ci opregion->acpi = NULL; 3008c2ecf20Sopenharmony_ci opregion->swsci = NULL; 3018c2ecf20Sopenharmony_ci opregion->asle = NULL; 3028c2ecf20Sopenharmony_ci opregion->vbt = NULL; 3038c2ecf20Sopenharmony_ci} 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ciint psb_intel_opregion_setup(struct drm_device *dev) 3068c2ecf20Sopenharmony_ci{ 3078c2ecf20Sopenharmony_ci struct drm_psb_private *dev_priv = dev->dev_private; 3088c2ecf20Sopenharmony_ci struct psb_intel_opregion *opregion = &dev_priv->opregion; 3098c2ecf20Sopenharmony_ci u32 opregion_phy, mboxes; 3108c2ecf20Sopenharmony_ci void __iomem *base; 3118c2ecf20Sopenharmony_ci int err = 0; 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci pci_read_config_dword(dev->pdev, PCI_ASLS, &opregion_phy); 3148c2ecf20Sopenharmony_ci if (opregion_phy == 0) { 3158c2ecf20Sopenharmony_ci DRM_DEBUG_DRIVER("ACPI Opregion not supported\n"); 3168c2ecf20Sopenharmony_ci return -ENOTSUPP; 3178c2ecf20Sopenharmony_ci } 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci INIT_WORK(&opregion->asle_work, psb_intel_opregion_asle_work); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci DRM_DEBUG("OpRegion detected at 0x%8x\n", opregion_phy); 3228c2ecf20Sopenharmony_ci base = acpi_os_ioremap(opregion_phy, 8*1024); 3238c2ecf20Sopenharmony_ci if (!base) 3248c2ecf20Sopenharmony_ci return -ENOMEM; 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci if (memcmp(base, OPREGION_SIGNATURE, 16)) { 3278c2ecf20Sopenharmony_ci DRM_DEBUG_DRIVER("opregion signature mismatch\n"); 3288c2ecf20Sopenharmony_ci err = -EINVAL; 3298c2ecf20Sopenharmony_ci goto err_out; 3308c2ecf20Sopenharmony_ci } 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci opregion->header = base; 3338c2ecf20Sopenharmony_ci opregion->vbt = base + OPREGION_VBT_OFFSET; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci opregion->lid_state = base + ACPI_CLID; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci mboxes = opregion->header->mboxes; 3388c2ecf20Sopenharmony_ci if (mboxes & MBOX_ACPI) { 3398c2ecf20Sopenharmony_ci DRM_DEBUG_DRIVER("Public ACPI methods supported\n"); 3408c2ecf20Sopenharmony_ci opregion->acpi = base + OPREGION_ACPI_OFFSET; 3418c2ecf20Sopenharmony_ci } 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci if (mboxes & MBOX_ASLE) { 3448c2ecf20Sopenharmony_ci DRM_DEBUG_DRIVER("ASLE supported\n"); 3458c2ecf20Sopenharmony_ci opregion->asle = base + OPREGION_ASLE_OFFSET; 3468c2ecf20Sopenharmony_ci } 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci return 0; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_cierr_out: 3518c2ecf20Sopenharmony_ci iounmap(base); 3528c2ecf20Sopenharmony_ci return err; 3538c2ecf20Sopenharmony_ci} 3548c2ecf20Sopenharmony_ci 355