LCOV - code coverage report
Current view: top level - dev/pci/drm/i915 - intel_opregion.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 241 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 18 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2008 Intel Corporation <hong.liu@intel.com>
       3             :  * Copyright 2008 Red Hat <mjg@redhat.com>
       4             :  *
       5             :  * Permission is hereby granted, free of charge, to any person obtaining
       6             :  * a copy of this software and associated documentation files (the
       7             :  * "Software"), to deal in the Software without restriction, including
       8             :  * without limitation the rights to use, copy, modify, merge, publish,
       9             :  * distribute, sub license, and/or sell copies of the Software, and to
      10             :  * permit persons to whom the Software is furnished to do so, subject to
      11             :  * the following conditions:
      12             :  *
      13             :  * The above copyright notice and this permission notice (including the
      14             :  * next paragraph) shall be included in all copies or substantial
      15             :  * portions of the Software.
      16             :  *
      17             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
      18             :  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      19             :  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
      20             :  * NON-INFRINGEMENT.  IN NO EVENT SHALL INTEL AND/OR ITS SUPPLIERS BE
      21             :  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
      22             :  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
      23             :  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      24             :  * SOFTWARE.
      25             :  *
      26             :  */
      27             : 
      28             : #ifdef __linux__
      29             : #include <linux/acpi.h>
      30             : #include <acpi/video.h>
      31             : #endif
      32             : 
      33             : #include <dev/pci/drm/drmP.h>
      34             : #include <dev/pci/drm/i915_drm.h>
      35             : #include "i915_drv.h"
      36             : #include "intel_drv.h"
      37             : 
      38             : #define PCI_ASLE                0xe4
      39             : #define PCI_ASLS                0xfc
      40             : #define PCI_SWSCI               0xe8
      41             : #define PCI_SWSCI_SCISEL        (1 << 15)
      42             : #define PCI_SWSCI_GSSCIE        (1 << 0)
      43             : 
      44             : #define OPREGION_HEADER_OFFSET 0
      45             : #define OPREGION_ACPI_OFFSET   0x100
      46             : #define   ACPI_CLID 0x01ac /* current lid state indicator */
      47             : #define   ACPI_CDCK 0x01b0 /* current docking state indicator */
      48             : #define OPREGION_SWSCI_OFFSET  0x200
      49             : #define OPREGION_ASLE_OFFSET   0x300
      50             : #define OPREGION_VBT_OFFSET    0x400
      51             : 
      52             : #define OPREGION_SIGNATURE "IntelGraphicsMem"
      53             : #define MBOX_ACPI      (1<<0)
      54             : #define MBOX_SWSCI     (1<<1)
      55             : #define MBOX_ASLE      (1<<2)
      56             : #define MBOX_ASLE_EXT  (1<<4)
      57             : 
      58             : struct opregion_header {
      59             :         u8 signature[16];
      60             :         u32 size;
      61             :         u32 opregion_ver;
      62             :         u8 bios_ver[32];
      63             :         u8 vbios_ver[16];
      64             :         u8 driver_ver[16];
      65             :         u32 mboxes;
      66             :         u32 driver_model;
      67             :         u32 pcon;
      68             :         u8 dver[32];
      69             :         u8 rsvd[124];
      70             : } __packed;
      71             : 
      72             : /* OpRegion mailbox #1: public ACPI methods */
      73             : struct opregion_acpi {
      74             :         u32 drdy;       /* driver readiness */
      75             :         u32 csts;       /* notification status */
      76             :         u32 cevt;       /* current event */
      77             :         u8 rsvd1[20];
      78             :         u32 didl[8];    /* supported display devices ID list */
      79             :         u32 cpdl[8];    /* currently presented display list */
      80             :         u32 cadl[8];    /* currently active display list */
      81             :         u32 nadl[8];    /* next active devices list */
      82             :         u32 aslp;       /* ASL sleep time-out */
      83             :         u32 tidx;       /* toggle table index */
      84             :         u32 chpd;       /* current hotplug enable indicator */
      85             :         u32 clid;       /* current lid state*/
      86             :         u32 cdck;       /* current docking state */
      87             :         u32 sxsw;       /* Sx state resume */
      88             :         u32 evts;       /* ASL supported events */
      89             :         u32 cnot;       /* current OS notification */
      90             :         u32 nrdy;       /* driver status */
      91             :         u32 did2[7];    /* extended supported display devices ID list */
      92             :         u32 cpd2[7];    /* extended attached display devices list */
      93             :         u8 rsvd2[4];
      94             : } __packed;
      95             : 
      96             : /* OpRegion mailbox #2: SWSCI */
      97             : struct opregion_swsci {
      98             :         u32 scic;       /* SWSCI command|status|data */
      99             :         u32 parm;       /* command parameters */
     100             :         u32 dslp;       /* driver sleep time-out */
     101             :         u8 rsvd[244];
     102             : } __packed;
     103             : 
     104             : /* OpRegion mailbox #3: ASLE */
     105             : struct opregion_asle {
     106             :         u32 ardy;       /* driver readiness */
     107             :         u32 aslc;       /* ASLE interrupt command */
     108             :         u32 tche;       /* technology enabled indicator */
     109             :         u32 alsi;       /* current ALS illuminance reading */
     110             :         u32 bclp;       /* backlight brightness to set */
     111             :         u32 pfit;       /* panel fitting state */
     112             :         u32 cblv;       /* current brightness level */
     113             :         u16 bclm[20];   /* backlight level duty cycle mapping table */
     114             :         u32 cpfm;       /* current panel fitting mode */
     115             :         u32 epfm;       /* enabled panel fitting modes */
     116             :         u8 plut[74];    /* panel LUT and identifier */
     117             :         u32 pfmb;       /* PWM freq and min brightness */
     118             :         u32 cddv;       /* color correction default values */
     119             :         u32 pcft;       /* power conservation features */
     120             :         u32 srot;       /* supported rotation angles */
     121             :         u32 iuer;       /* IUER events */
     122             :         u64 fdss;
     123             :         u32 fdsp;
     124             :         u32 stat;
     125             :         u8 rsvd[70];
     126             : } __packed;
     127             : 
     128             : /* Driver readiness indicator */
     129             : #define ASLE_ARDY_READY         (1 << 0)
     130             : #define ASLE_ARDY_NOT_READY     (0 << 0)
     131             : 
     132             : /* ASLE Interrupt Command (ASLC) bits */
     133             : #define ASLC_SET_ALS_ILLUM              (1 << 0)
     134             : #define ASLC_SET_BACKLIGHT              (1 << 1)
     135             : #define ASLC_SET_PFIT                   (1 << 2)
     136             : #define ASLC_SET_PWM_FREQ               (1 << 3)
     137             : #define ASLC_SUPPORTED_ROTATION_ANGLES  (1 << 4)
     138             : #define ASLC_BUTTON_ARRAY               (1 << 5)
     139             : #define ASLC_CONVERTIBLE_INDICATOR      (1 << 6)
     140             : #define ASLC_DOCKING_INDICATOR          (1 << 7)
     141             : #define ASLC_ISCT_STATE_CHANGE          (1 << 8)
     142             : #define ASLC_REQ_MSK                    0x1ff
     143             : /* response bits */
     144             : #define ASLC_ALS_ILLUM_FAILED           (1 << 10)
     145             : #define ASLC_BACKLIGHT_FAILED           (1 << 12)
     146             : #define ASLC_PFIT_FAILED                (1 << 14)
     147             : #define ASLC_PWM_FREQ_FAILED            (1 << 16)
     148             : #define ASLC_ROTATION_ANGLES_FAILED     (1 << 18)
     149             : #define ASLC_BUTTON_ARRAY_FAILED        (1 << 20)
     150             : #define ASLC_CONVERTIBLE_FAILED         (1 << 22)
     151             : #define ASLC_DOCKING_FAILED             (1 << 24)
     152             : #define ASLC_ISCT_STATE_FAILED          (1 << 26)
     153             : 
     154             : /* Technology enabled indicator */
     155             : #define ASLE_TCHE_ALS_EN        (1 << 0)
     156             : #define ASLE_TCHE_BLC_EN        (1 << 1)
     157             : #define ASLE_TCHE_PFIT_EN       (1 << 2)
     158             : #define ASLE_TCHE_PFMB_EN       (1 << 3)
     159             : 
     160             : /* ASLE backlight brightness to set */
     161             : #define ASLE_BCLP_VALID                (1<<31)
     162             : #define ASLE_BCLP_MSK          (~(1<<31))
     163             : 
     164             : /* ASLE panel fitting request */
     165             : #define ASLE_PFIT_VALID         (1<<31)
     166             : #define ASLE_PFIT_CENTER (1<<0)
     167             : #define ASLE_PFIT_STRETCH_TEXT (1<<1)
     168             : #define ASLE_PFIT_STRETCH_GFX (1<<2)
     169             : 
     170             : /* PWM frequency and minimum brightness */
     171             : #define ASLE_PFMB_BRIGHTNESS_MASK (0xff)
     172             : #define ASLE_PFMB_BRIGHTNESS_VALID (1<<8)
     173             : #define ASLE_PFMB_PWM_MASK (0x7ffffe00)
     174             : #define ASLE_PFMB_PWM_VALID (1<<31)
     175             : 
     176             : #define ASLE_CBLV_VALID         (1<<31)
     177             : 
     178             : /* IUER */
     179             : #define ASLE_IUER_DOCKING               (1 << 7)
     180             : #define ASLE_IUER_CONVERTIBLE           (1 << 6)
     181             : #define ASLE_IUER_ROTATION_LOCK_BTN     (1 << 4)
     182             : #define ASLE_IUER_VOLUME_DOWN_BTN       (1 << 3)
     183             : #define ASLE_IUER_VOLUME_UP_BTN         (1 << 2)
     184             : #define ASLE_IUER_WINDOWS_BTN           (1 << 1)
     185             : #define ASLE_IUER_POWER_BTN             (1 << 0)
     186             : 
     187             : /* Software System Control Interrupt (SWSCI) */
     188             : #define SWSCI_SCIC_INDICATOR            (1 << 0)
     189             : #define SWSCI_SCIC_MAIN_FUNCTION_SHIFT  1
     190             : #define SWSCI_SCIC_MAIN_FUNCTION_MASK   (0xf << 1)
     191             : #define SWSCI_SCIC_SUB_FUNCTION_SHIFT   8
     192             : #define SWSCI_SCIC_SUB_FUNCTION_MASK    (0xff << 8)
     193             : #define SWSCI_SCIC_EXIT_PARAMETER_SHIFT 8
     194             : #define SWSCI_SCIC_EXIT_PARAMETER_MASK  (0xff << 8)
     195             : #define SWSCI_SCIC_EXIT_STATUS_SHIFT    5
     196             : #define SWSCI_SCIC_EXIT_STATUS_MASK     (7 << 5)
     197             : #define SWSCI_SCIC_EXIT_STATUS_SUCCESS  1
     198             : 
     199             : #define SWSCI_FUNCTION_CODE(main, sub) \
     200             :         ((main) << SWSCI_SCIC_MAIN_FUNCTION_SHIFT | \
     201             :          (sub) << SWSCI_SCIC_SUB_FUNCTION_SHIFT)
     202             : 
     203             : /* SWSCI: Get BIOS Data (GBDA) */
     204             : #define SWSCI_GBDA                      4
     205             : #define SWSCI_GBDA_SUPPORTED_CALLS      SWSCI_FUNCTION_CODE(SWSCI_GBDA, 0)
     206             : #define SWSCI_GBDA_REQUESTED_CALLBACKS  SWSCI_FUNCTION_CODE(SWSCI_GBDA, 1)
     207             : #define SWSCI_GBDA_BOOT_DISPLAY_PREF    SWSCI_FUNCTION_CODE(SWSCI_GBDA, 4)
     208             : #define SWSCI_GBDA_PANEL_DETAILS        SWSCI_FUNCTION_CODE(SWSCI_GBDA, 5)
     209             : #define SWSCI_GBDA_TV_STANDARD          SWSCI_FUNCTION_CODE(SWSCI_GBDA, 6)
     210             : #define SWSCI_GBDA_INTERNAL_GRAPHICS    SWSCI_FUNCTION_CODE(SWSCI_GBDA, 7)
     211             : #define SWSCI_GBDA_SPREAD_SPECTRUM      SWSCI_FUNCTION_CODE(SWSCI_GBDA, 10)
     212             : 
     213             : /* SWSCI: System BIOS Callbacks (SBCB) */
     214             : #define SWSCI_SBCB                      6
     215             : #define SWSCI_SBCB_SUPPORTED_CALLBACKS  SWSCI_FUNCTION_CODE(SWSCI_SBCB, 0)
     216             : #define SWSCI_SBCB_INIT_COMPLETION      SWSCI_FUNCTION_CODE(SWSCI_SBCB, 1)
     217             : #define SWSCI_SBCB_PRE_HIRES_SET_MODE   SWSCI_FUNCTION_CODE(SWSCI_SBCB, 3)
     218             : #define SWSCI_SBCB_POST_HIRES_SET_MODE  SWSCI_FUNCTION_CODE(SWSCI_SBCB, 4)
     219             : #define SWSCI_SBCB_DISPLAY_SWITCH       SWSCI_FUNCTION_CODE(SWSCI_SBCB, 5)
     220             : #define SWSCI_SBCB_SET_TV_FORMAT        SWSCI_FUNCTION_CODE(SWSCI_SBCB, 6)
     221             : #define SWSCI_SBCB_ADAPTER_POWER_STATE  SWSCI_FUNCTION_CODE(SWSCI_SBCB, 7)
     222             : #define SWSCI_SBCB_DISPLAY_POWER_STATE  SWSCI_FUNCTION_CODE(SWSCI_SBCB, 8)
     223             : #define SWSCI_SBCB_SET_BOOT_DISPLAY     SWSCI_FUNCTION_CODE(SWSCI_SBCB, 9)
     224             : #define SWSCI_SBCB_SET_PANEL_DETAILS    SWSCI_FUNCTION_CODE(SWSCI_SBCB, 10)
     225             : #define SWSCI_SBCB_SET_INTERNAL_GFX     SWSCI_FUNCTION_CODE(SWSCI_SBCB, 11)
     226             : #define SWSCI_SBCB_POST_HIRES_TO_DOS_FS SWSCI_FUNCTION_CODE(SWSCI_SBCB, 16)
     227             : #define SWSCI_SBCB_SUSPEND_RESUME       SWSCI_FUNCTION_CODE(SWSCI_SBCB, 17)
     228             : #define SWSCI_SBCB_SET_SPREAD_SPECTRUM  SWSCI_FUNCTION_CODE(SWSCI_SBCB, 18)
     229             : #define SWSCI_SBCB_POST_VBE_PM          SWSCI_FUNCTION_CODE(SWSCI_SBCB, 19)
     230             : #define SWSCI_SBCB_ENABLE_DISABLE_AUDIO SWSCI_FUNCTION_CODE(SWSCI_SBCB, 21)
     231             : 
     232             : #define ACPI_OTHER_OUTPUT (0<<8)
     233             : #define ACPI_VGA_OUTPUT (1<<8)
     234             : #define ACPI_TV_OUTPUT (2<<8)
     235             : #define ACPI_DIGITAL_OUTPUT (3<<8)
     236             : #define ACPI_LVDS_OUTPUT (4<<8)
     237             : 
     238             : #define MAX_DSLP        1500
     239             : 
     240             : #ifdef CONFIG_ACPI
     241           0 : static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
     242             : {
     243           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     244           0 :         struct opregion_swsci *swsci = dev_priv->opregion.swsci;
     245             :         u32 main_function, sub_function, scic;
     246           0 :         u16 pci_swsci;
     247             :         u32 dslp;
     248             : 
     249           0 :         if (!swsci)
     250           0 :                 return -ENODEV;
     251             : 
     252           0 :         main_function = (function & SWSCI_SCIC_MAIN_FUNCTION_MASK) >>
     253             :                 SWSCI_SCIC_MAIN_FUNCTION_SHIFT;
     254           0 :         sub_function = (function & SWSCI_SCIC_SUB_FUNCTION_MASK) >>
     255             :                 SWSCI_SCIC_SUB_FUNCTION_SHIFT;
     256             : 
     257             :         /* Check if we can call the function. See swsci_setup for details. */
     258           0 :         if (main_function == SWSCI_SBCB) {
     259           0 :                 if ((dev_priv->opregion.swsci_sbcb_sub_functions &
     260           0 :                      (1 << sub_function)) == 0)
     261           0 :                         return -EINVAL;
     262           0 :         } else if (main_function == SWSCI_GBDA) {
     263           0 :                 if ((dev_priv->opregion.swsci_gbda_sub_functions &
     264           0 :                      (1 << sub_function)) == 0)
     265           0 :                         return -EINVAL;
     266             :         }
     267             : 
     268             :         /* Driver sleep timeout in ms. */
     269           0 :         dslp = swsci->dslp;
     270           0 :         if (!dslp) {
     271             :                 /* The spec says 2ms should be the default, but it's too small
     272             :                  * for some machines. */
     273             :                 dslp = 50;
     274           0 :         } else if (dslp > MAX_DSLP) {
     275             :                 /* Hey bios, trust must be earned. */
     276             :                 DRM_INFO_ONCE("ACPI BIOS requests an excessive sleep of %u ms, "
     277             :                               "using %u ms instead\n", dslp, MAX_DSLP);
     278             :                 dslp = MAX_DSLP;
     279           0 :         }
     280             : 
     281             :         /* The spec tells us to do this, but we are the only user... */
     282           0 :         scic = swsci->scic;
     283           0 :         if (scic & SWSCI_SCIC_INDICATOR) {
     284             :                 DRM_DEBUG_DRIVER("SWSCI request already in progress\n");
     285           0 :                 return -EBUSY;
     286             :         }
     287             : 
     288           0 :         scic = function | SWSCI_SCIC_INDICATOR;
     289             : 
     290           0 :         swsci->parm = parm;
     291           0 :         swsci->scic = scic;
     292             : 
     293             :         /* Ensure SCI event is selected and event trigger is cleared. */
     294           0 :         pci_read_config_word(dev->pdev, PCI_SWSCI, &pci_swsci);
     295           0 :         if (!(pci_swsci & PCI_SWSCI_SCISEL) || (pci_swsci & PCI_SWSCI_GSSCIE)) {
     296           0 :                 pci_swsci |= PCI_SWSCI_SCISEL;
     297           0 :                 pci_swsci &= ~PCI_SWSCI_GSSCIE;
     298           0 :                 pci_write_config_word(dev->pdev, PCI_SWSCI, pci_swsci);
     299           0 :         }
     300             : 
     301             :         /* Use event trigger to tell bios to check the mail. */
     302           0 :         pci_swsci |= PCI_SWSCI_GSSCIE;
     303           0 :         pci_write_config_word(dev->pdev, PCI_SWSCI, pci_swsci);
     304             : 
     305             :         /* Poll for the result. */
     306             : #define C (((scic = swsci->scic) & SWSCI_SCIC_INDICATOR) == 0)
     307           0 :         if (wait_for(C, dslp)) {
     308             :                 DRM_DEBUG_DRIVER("SWSCI request timed out\n");
     309           0 :                 return -ETIMEDOUT;
     310             :         }
     311             : 
     312           0 :         scic = (scic & SWSCI_SCIC_EXIT_STATUS_MASK) >>
     313             :                 SWSCI_SCIC_EXIT_STATUS_SHIFT;
     314             : 
     315             :         /* Note: scic == 0 is an error! */
     316           0 :         if (scic != SWSCI_SCIC_EXIT_STATUS_SUCCESS) {
     317             :                 DRM_DEBUG_DRIVER("SWSCI request error %u\n", scic);
     318           0 :                 return -EIO;
     319             :         }
     320             : 
     321           0 :         if (parm_out)
     322           0 :                 *parm_out = swsci->parm;
     323             : 
     324           0 :         return 0;
     325             : 
     326             : #undef C
     327           0 : }
     328             : 
     329             : #define DISPLAY_TYPE_CRT                        0
     330             : #define DISPLAY_TYPE_TV                         1
     331             : #define DISPLAY_TYPE_EXTERNAL_FLAT_PANEL        2
     332             : #define DISPLAY_TYPE_INTERNAL_FLAT_PANEL        3
     333             : 
     334           0 : int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
     335             :                                   bool enable)
     336             : {
     337           0 :         struct drm_device *dev = intel_encoder->base.dev;
     338             :         u32 parm = 0;
     339             :         u32 type = 0;
     340             :         u32 port;
     341             : 
     342             :         /* don't care about old stuff for now */
     343           0 :         if (!HAS_DDI(dev))
     344           0 :                 return 0;
     345             : 
     346           0 :         if (intel_encoder->type == INTEL_OUTPUT_DSI)
     347           0 :                 port = 0;
     348             :         else
     349           0 :                 port = intel_ddi_get_encoder_port(intel_encoder);
     350             : 
     351           0 :         if (port == PORT_E)  {
     352             :                 port = 0;
     353           0 :         } else {
     354           0 :                 parm |= 1 << port;
     355           0 :                 port++;
     356             :         }
     357             : 
     358           0 :         if (!enable)
     359           0 :                 parm |= 4 << 8;
     360             : 
     361           0 :         switch (intel_encoder->type) {
     362             :         case INTEL_OUTPUT_ANALOG:
     363             :                 type = DISPLAY_TYPE_CRT;
     364           0 :                 break;
     365             :         case INTEL_OUTPUT_UNKNOWN:
     366             :         case INTEL_OUTPUT_DISPLAYPORT:
     367             :         case INTEL_OUTPUT_HDMI:
     368             :         case INTEL_OUTPUT_DP_MST:
     369             :                 type = DISPLAY_TYPE_EXTERNAL_FLAT_PANEL;
     370           0 :                 break;
     371             :         case INTEL_OUTPUT_EDP:
     372             :         case INTEL_OUTPUT_DSI:
     373             :                 type = DISPLAY_TYPE_INTERNAL_FLAT_PANEL;
     374           0 :                 break;
     375             :         default:
     376           0 :                 WARN_ONCE(1, "unsupported intel_encoder type %d\n",
     377             :                           intel_encoder->type);
     378           0 :                 return -EINVAL;
     379             :         }
     380             : 
     381           0 :         parm |= type << (16 + port * 3);
     382             : 
     383           0 :         return swsci(dev, SWSCI_SBCB_DISPLAY_POWER_STATE, parm, NULL);
     384           0 : }
     385             : 
     386             : static const struct {
     387             :         pci_power_t pci_power_state;
     388             :         u32 parm;
     389             : } power_state_map[] = {
     390             :         { PCI_D0,       0x00 },
     391             :         { PCI_D1,       0x01 },
     392             :         { PCI_D2,       0x02 },
     393             :         { PCI_D3hot,    0x04 },
     394             :         { PCI_D3cold,   0x04 },
     395             : };
     396             : 
     397           0 : int intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state)
     398             : {
     399             :         int i;
     400             : 
     401           0 :         if (!HAS_DDI(dev))
     402           0 :                 return 0;
     403             : 
     404           0 :         for (i = 0; i < ARRAY_SIZE(power_state_map); i++) {
     405           0 :                 if (state == power_state_map[i].pci_power_state)
     406           0 :                         return swsci(dev, SWSCI_SBCB_ADAPTER_POWER_STATE,
     407           0 :                                      power_state_map[i].parm, NULL);
     408             :         }
     409             : 
     410           0 :         return -EINVAL;
     411           0 : }
     412             : 
     413           0 : static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
     414             : {
     415           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     416             :         struct intel_connector *intel_connector;
     417           0 :         struct opregion_asle *asle = dev_priv->opregion.asle;
     418             : 
     419             :         DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp);
     420             : 
     421             : #ifdef __linux__
     422             :         if (acpi_video_get_backlight_type() == acpi_backlight_native) {
     423             :                 DRM_DEBUG_KMS("opregion backlight request ignored\n");
     424             :                 return 0;
     425             :         }
     426             : #endif
     427             : 
     428           0 :         if (!(bclp & ASLE_BCLP_VALID))
     429           0 :                 return ASLC_BACKLIGHT_FAILED;
     430             : 
     431           0 :         bclp &= ASLE_BCLP_MSK;
     432           0 :         if (bclp > 255)
     433           0 :                 return ASLC_BACKLIGHT_FAILED;
     434             : 
     435           0 :         drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
     436             : 
     437             :         /*
     438             :          * Update backlight on all connectors that support backlight (usually
     439             :          * only one).
     440             :          */
     441             :         DRM_DEBUG_KMS("updating opregion backlight %d/255\n", bclp);
     442           0 :         list_for_each_entry(intel_connector, &dev->mode_config.connector_list, base.head)
     443           0 :                 intel_panel_set_backlight_acpi(intel_connector, bclp, 255);
     444           0 :         asle->cblv = DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID;
     445             : 
     446           0 :         drm_modeset_unlock(&dev->mode_config.connection_mutex);
     447             : 
     448             : 
     449           0 :         return 0;
     450           0 : }
     451             : 
     452           0 : static u32 asle_set_als_illum(struct drm_device *dev, u32 alsi)
     453             : {
     454             :         /* alsi is the current ALS reading in lux. 0 indicates below sensor
     455             :            range, 0xffff indicates above sensor range. 1-0xfffe are valid */
     456             :         DRM_DEBUG_DRIVER("Illum is not supported\n");
     457           0 :         return ASLC_ALS_ILLUM_FAILED;
     458             : }
     459             : 
     460           0 : static u32 asle_set_pwm_freq(struct drm_device *dev, u32 pfmb)
     461             : {
     462             :         DRM_DEBUG_DRIVER("PWM freq is not supported\n");
     463           0 :         return ASLC_PWM_FREQ_FAILED;
     464             : }
     465             : 
     466           0 : static u32 asle_set_pfit(struct drm_device *dev, u32 pfit)
     467             : {
     468             :         /* Panel fitting is currently controlled by the X code, so this is a
     469             :            noop until modesetting support works fully */
     470             :         DRM_DEBUG_DRIVER("Pfit is not supported\n");
     471           0 :         return ASLC_PFIT_FAILED;
     472             : }
     473             : 
     474           0 : static u32 asle_set_supported_rotation_angles(struct drm_device *dev, u32 srot)
     475             : {
     476             :         DRM_DEBUG_DRIVER("SROT is not supported\n");
     477           0 :         return ASLC_ROTATION_ANGLES_FAILED;
     478             : }
     479             : 
     480           0 : static u32 asle_set_button_array(struct drm_device *dev, u32 iuer)
     481             : {
     482             :         if (!iuer)
     483             :                 DRM_DEBUG_DRIVER("Button array event is not supported (nothing)\n");
     484           0 :         if (iuer & ASLE_IUER_ROTATION_LOCK_BTN)
     485             :                 DRM_DEBUG_DRIVER("Button array event is not supported (rotation lock)\n");
     486           0 :         if (iuer & ASLE_IUER_VOLUME_DOWN_BTN)
     487             :                 DRM_DEBUG_DRIVER("Button array event is not supported (volume down)\n");
     488           0 :         if (iuer & ASLE_IUER_VOLUME_UP_BTN)
     489             :                 DRM_DEBUG_DRIVER("Button array event is not supported (volume up)\n");
     490           0 :         if (iuer & ASLE_IUER_WINDOWS_BTN)
     491             :                 DRM_DEBUG_DRIVER("Button array event is not supported (windows)\n");
     492           0 :         if (iuer & ASLE_IUER_POWER_BTN)
     493             :                 DRM_DEBUG_DRIVER("Button array event is not supported (power)\n");
     494             : 
     495           0 :         return ASLC_BUTTON_ARRAY_FAILED;
     496             : }
     497             : 
     498           0 : static u32 asle_set_convertible(struct drm_device *dev, u32 iuer)
     499             : {
     500           0 :         if (iuer & ASLE_IUER_CONVERTIBLE)
     501             :                 DRM_DEBUG_DRIVER("Convertible is not supported (clamshell)\n");
     502             :         else
     503             :                 DRM_DEBUG_DRIVER("Convertible is not supported (slate)\n");
     504             : 
     505           0 :         return ASLC_CONVERTIBLE_FAILED;
     506             : }
     507             : 
     508           0 : static u32 asle_set_docking(struct drm_device *dev, u32 iuer)
     509             : {
     510           0 :         if (iuer & ASLE_IUER_DOCKING)
     511             :                 DRM_DEBUG_DRIVER("Docking is not supported (docked)\n");
     512             :         else
     513             :                 DRM_DEBUG_DRIVER("Docking is not supported (undocked)\n");
     514             : 
     515           0 :         return ASLC_DOCKING_FAILED;
     516             : }
     517             : 
     518           0 : static u32 asle_isct_state(struct drm_device *dev)
     519             : {
     520             :         DRM_DEBUG_DRIVER("ISCT is not supported\n");
     521           0 :         return ASLC_ISCT_STATE_FAILED;
     522             : }
     523             : 
     524           0 : static void asle_work(struct work_struct *work)
     525             : {
     526             :         struct intel_opregion *opregion =
     527           0 :                 container_of(work, struct intel_opregion, asle_work);
     528             :         struct drm_i915_private *dev_priv =
     529           0 :                 container_of(opregion, struct drm_i915_private, opregion);
     530           0 :         struct drm_device *dev = dev_priv->dev;
     531           0 :         struct opregion_asle *asle = dev_priv->opregion.asle;
     532             :         u32 aslc_stat = 0;
     533             :         u32 aslc_req;
     534             : 
     535           0 :         if (!asle)
     536           0 :                 return;
     537             : 
     538           0 :         aslc_req = asle->aslc;
     539             : 
     540           0 :         if (!(aslc_req & ASLC_REQ_MSK)) {
     541             :                 DRM_DEBUG_DRIVER("No request on ASLC interrupt 0x%08x\n",
     542             :                                  aslc_req);
     543           0 :                 return;
     544             :         }
     545             : 
     546           0 :         if (aslc_req & ASLC_SET_ALS_ILLUM)
     547           0 :                 aslc_stat |= asle_set_als_illum(dev, asle->alsi);
     548             : 
     549           0 :         if (aslc_req & ASLC_SET_BACKLIGHT)
     550           0 :                 aslc_stat |= asle_set_backlight(dev, asle->bclp);
     551             : 
     552           0 :         if (aslc_req & ASLC_SET_PFIT)
     553           0 :                 aslc_stat |= asle_set_pfit(dev, asle->pfit);
     554             : 
     555           0 :         if (aslc_req & ASLC_SET_PWM_FREQ)
     556           0 :                 aslc_stat |= asle_set_pwm_freq(dev, asle->pfmb);
     557             : 
     558           0 :         if (aslc_req & ASLC_SUPPORTED_ROTATION_ANGLES)
     559           0 :                 aslc_stat |= asle_set_supported_rotation_angles(dev,
     560           0 :                                                         asle->srot);
     561             : 
     562           0 :         if (aslc_req & ASLC_BUTTON_ARRAY)
     563           0 :                 aslc_stat |= asle_set_button_array(dev, asle->iuer);
     564             : 
     565           0 :         if (aslc_req & ASLC_CONVERTIBLE_INDICATOR)
     566           0 :                 aslc_stat |= asle_set_convertible(dev, asle->iuer);
     567             : 
     568           0 :         if (aslc_req & ASLC_DOCKING_INDICATOR)
     569           0 :                 aslc_stat |= asle_set_docking(dev, asle->iuer);
     570             : 
     571           0 :         if (aslc_req & ASLC_ISCT_STATE_CHANGE)
     572           0 :                 aslc_stat |= asle_isct_state(dev);
     573             : 
     574           0 :         asle->aslc = aslc_stat;
     575           0 : }
     576             : 
     577           0 : void intel_opregion_asle_intr(struct drm_device *dev)
     578             : {
     579           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     580             : 
     581           0 :         if (dev_priv->opregion.asle)
     582           0 :                 schedule_work(&dev_priv->opregion.asle_work);
     583           0 : }
     584             : 
     585             : #define ACPI_EV_DISPLAY_SWITCH (1<<0)
     586             : #define ACPI_EV_LID            (1<<1)
     587             : #define ACPI_EV_DOCK           (1<<2)
     588             : 
     589             : static struct intel_opregion *system_opregion;
     590             : 
     591             : #ifdef notyet
     592             : 
     593             : static int intel_opregion_video_event(struct notifier_block *nb,
     594             :                                       unsigned long val, void *data)
     595             : {
     596             :         /* The only video events relevant to opregion are 0x80. These indicate
     597             :            either a docking event, lid switch or display switch request. In
     598             :            Linux, these are handled by the dock, button and video drivers.
     599             :         */
     600             : 
     601             :         struct acpi_bus_event *event = data;
     602             :         struct opregion_acpi *acpi;
     603             :         int ret = NOTIFY_OK;
     604             : 
     605             :         if (strcmp(event->device_class, ACPI_VIDEO_CLASS) != 0)
     606             :                 return NOTIFY_DONE;
     607             : 
     608             :         if (!system_opregion)
     609             :                 return NOTIFY_DONE;
     610             : 
     611             :         acpi = system_opregion->acpi;
     612             : 
     613             :         if (event->type == 0x80 && ((acpi->cevt & 1) == 0))
     614             :                 ret = NOTIFY_BAD;
     615             : 
     616             :         acpi->csts = 0;
     617             : 
     618             :         return ret;
     619             : }
     620             : 
     621             : static struct notifier_block intel_opregion_notifier = {
     622             :         .notifier_call = intel_opregion_video_event,
     623             : };
     624             : 
     625             : /*
     626             :  * Initialise the DIDL field in opregion. This passes a list of devices to
     627             :  * the firmware. Values are defined by section B.4.2 of the ACPI specification
     628             :  * (version 3)
     629             :  */
     630             : 
     631             : static u32 get_did(struct intel_opregion *opregion, int i)
     632             : {
     633             :         u32 did;
     634             : 
     635             :         if (i < ARRAY_SIZE(opregion->acpi->didl)) {
     636             :                 did = opregion->acpi->didl[i];
     637             :         } else {
     638             :                 i -= ARRAY_SIZE(opregion->acpi->didl);
     639             : 
     640             :                 if (WARN_ON(i >= ARRAY_SIZE(opregion->acpi->did2)))
     641             :                         return 0;
     642             : 
     643             :                 did = opregion->acpi->did2[i];
     644             :         }
     645             : 
     646             :         return did;
     647             : }
     648             : 
     649             : static void set_did(struct intel_opregion *opregion, int i, u32 val)
     650             : {
     651             :         if (i < ARRAY_SIZE(opregion->acpi->didl)) {
     652             :                 opregion->acpi->didl[i] = val;
     653             :         } else {
     654             :                 i -= ARRAY_SIZE(opregion->acpi->didl);
     655             : 
     656             :                 if (WARN_ON(i >= ARRAY_SIZE(opregion->acpi->did2)))
     657             :                         return;
     658             : 
     659             :                 opregion->acpi->did2[i] = val;
     660             :         }
     661             : }
     662             : 
     663             : static void intel_didl_outputs(struct drm_device *dev)
     664             : {
     665             :         struct drm_i915_private *dev_priv = dev->dev_private;
     666             :         struct intel_opregion *opregion = &dev_priv->opregion;
     667             :         struct drm_connector *connector;
     668             :         acpi_handle handle;
     669             :         struct acpi_device *acpi_dev, *acpi_cdev, *acpi_video_bus = NULL;
     670             :         unsigned long long device_id;
     671             :         acpi_status status;
     672             :         u32 temp, max_outputs;
     673             :         int i = 0;
     674             : 
     675             :         handle = ACPI_HANDLE(&dev->pdev->dev);
     676             :         if (!handle || acpi_bus_get_device(handle, &acpi_dev))
     677             :                 return;
     678             : 
     679             :         if (acpi_is_video_device(handle))
     680             :                 acpi_video_bus = acpi_dev;
     681             :         else {
     682             :                 list_for_each_entry(acpi_cdev, &acpi_dev->children, node) {
     683             :                         if (acpi_is_video_device(acpi_cdev->handle)) {
     684             :                                 acpi_video_bus = acpi_cdev;
     685             :                                 break;
     686             :                         }
     687             :                 }
     688             :         }
     689             : 
     690             :         if (!acpi_video_bus) {
     691             :                 DRM_DEBUG_KMS("No ACPI video bus found\n");
     692             :                 return;
     693             :         }
     694             : 
     695             :         /*
     696             :          * In theory, did2, the extended didl, gets added at opregion version
     697             :          * 3.0. In practice, however, we're supposed to set it for earlier
     698             :          * versions as well, since a BIOS that doesn't understand did2 should
     699             :          * not look at it anyway. Use a variable so we can tweak this if a need
     700             :          * arises later.
     701             :          */
     702             :         max_outputs = ARRAY_SIZE(opregion->acpi->didl) +
     703             :                 ARRAY_SIZE(opregion->acpi->did2);
     704             : 
     705             :         list_for_each_entry(acpi_cdev, &acpi_video_bus->children, node) {
     706             :                 if (i >= max_outputs) {
     707             :                         DRM_DEBUG_KMS("More than %u outputs detected via ACPI\n",
     708             :                                       max_outputs);
     709             :                         return;
     710             :                 }
     711             :                 status = acpi_evaluate_integer(acpi_cdev->handle, "_ADR",
     712             :                                                NULL, &device_id);
     713             :                 if (ACPI_SUCCESS(status)) {
     714             :                         if (!device_id)
     715             :                                 goto blind_set;
     716             :                         set_did(opregion, i++, (u32)(device_id & 0x0f0f));
     717             :                 }
     718             :         }
     719             : 
     720             : end:
     721             :         DRM_DEBUG_KMS("%d outputs detected\n", i);
     722             : 
     723             :         /* If fewer than max outputs, the list must be null terminated */
     724             :         if (i < max_outputs)
     725             :                 set_did(opregion, i, 0);
     726             :         return;
     727             : 
     728             : blind_set:
     729             :         i = 0;
     730             :         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
     731             :                 int output_type = ACPI_OTHER_OUTPUT;
     732             :                 if (i >= max_outputs) {
     733             :                         DRM_DEBUG_KMS("More than %u outputs in connector list\n",
     734             :                                       max_outputs);
     735             :                         return;
     736             :                 }
     737             :                 switch (connector->connector_type) {
     738             :                 case DRM_MODE_CONNECTOR_VGA:
     739             :                 case DRM_MODE_CONNECTOR_DVIA:
     740             :                         output_type = ACPI_VGA_OUTPUT;
     741             :                         break;
     742             :                 case DRM_MODE_CONNECTOR_Composite:
     743             :                 case DRM_MODE_CONNECTOR_SVIDEO:
     744             :                 case DRM_MODE_CONNECTOR_Component:
     745             :                 case DRM_MODE_CONNECTOR_9PinDIN:
     746             :                         output_type = ACPI_TV_OUTPUT;
     747             :                         break;
     748             :                 case DRM_MODE_CONNECTOR_DVII:
     749             :                 case DRM_MODE_CONNECTOR_DVID:
     750             :                 case DRM_MODE_CONNECTOR_DisplayPort:
     751             :                 case DRM_MODE_CONNECTOR_HDMIA:
     752             :                 case DRM_MODE_CONNECTOR_HDMIB:
     753             :                         output_type = ACPI_DIGITAL_OUTPUT;
     754             :                         break;
     755             :                 case DRM_MODE_CONNECTOR_LVDS:
     756             :                         output_type = ACPI_LVDS_OUTPUT;
     757             :                         break;
     758             :                 }
     759             :                 temp = get_did(opregion, i);
     760             :                 set_did(opregion, i, temp | (1 << 31) | output_type | i);
     761             :                 i++;
     762             :         }
     763             :         goto end;
     764             : }
     765             : 
     766             : static void intel_setup_cadls(struct drm_device *dev)
     767             : {
     768             :         struct drm_i915_private *dev_priv = dev->dev_private;
     769             :         struct intel_opregion *opregion = &dev_priv->opregion;
     770             :         int i = 0;
     771             :         u32 disp_id;
     772             : 
     773             :         /* Initialize the CADL field by duplicating the DIDL values.
     774             :          * Technically, this is not always correct as display outputs may exist,
     775             :          * but not active. This initialization is necessary for some Clevo
     776             :          * laptops that check this field before processing the brightness and
     777             :          * display switching hotkeys. Just like DIDL, CADL is NULL-terminated if
     778             :          * there are less than eight devices. */
     779             :         do {
     780             :                 disp_id = get_did(opregion, i);
     781             :                 opregion->acpi->cadl[i] = disp_id;
     782             :         } while (++i < 8 && disp_id != 0);
     783             : }
     784             : 
     785             : #endif
     786             : 
     787           0 : void intel_opregion_init(struct drm_device *dev)
     788             : {
     789           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     790           0 :         struct intel_opregion *opregion = &dev_priv->opregion;
     791             : 
     792           0 :         if (!opregion->header)
     793           0 :                 return;
     794             : 
     795           0 :         if (opregion->acpi) {
     796             : #ifdef notyet
     797             :                 intel_didl_outputs(dev);
     798             :                 intel_setup_cadls(dev);
     799             : #endif
     800             : 
     801             :                 /* Notify BIOS we are ready to handle ACPI video ext notifs.
     802             :                  * Right now, all the events are handled by the ACPI video module.
     803             :                  * We don't actually need to do anything with them. */
     804           0 :                 opregion->acpi->csts = 0;
     805           0 :                 opregion->acpi->drdy = 1;
     806             : 
     807           0 :                 system_opregion = opregion;
     808             : #ifdef notyet
     809             :                 register_acpi_notifier(&intel_opregion_notifier);
     810             : #endif
     811           0 :         }
     812             : 
     813           0 :         if (opregion->asle) {
     814           0 :                 opregion->asle->tche = ASLE_TCHE_BLC_EN;
     815           0 :                 opregion->asle->ardy = ASLE_ARDY_READY;
     816           0 :         }
     817           0 : }
     818             : 
     819           0 : void intel_opregion_fini(struct drm_device *dev)
     820             : {
     821           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     822           0 :         struct intel_opregion *opregion = &dev_priv->opregion;
     823             : 
     824           0 :         if (!opregion->header)
     825           0 :                 return;
     826             : 
     827           0 :         if (opregion->asle)
     828           0 :                 opregion->asle->ardy = ASLE_ARDY_NOT_READY;
     829             : 
     830           0 :         cancel_work_sync(&dev_priv->opregion.asle_work);
     831             : 
     832           0 :         if (opregion->acpi) {
     833           0 :                 opregion->acpi->drdy = 0;
     834             : 
     835           0 :                 system_opregion = NULL;
     836             : #ifdef notyet
     837             :                 unregister_acpi_notifier(&intel_opregion_notifier);
     838             : #endif
     839           0 :         }
     840             : 
     841             :         /* just clear all opregion memory pointers now */
     842             : #ifdef __linux__
     843             :         memunmap(opregion->header);
     844             : #else
     845           0 :         bus_space_unmap(dev_priv->bst, dev_priv->opregion_ioh, OPREGION_SIZE);
     846             : #endif
     847           0 :         opregion->header = NULL;
     848           0 :         opregion->acpi = NULL;
     849           0 :         opregion->swsci = NULL;
     850           0 :         opregion->asle = NULL;
     851           0 :         opregion->vbt = NULL;
     852           0 :         opregion->lid_state = NULL;
     853           0 : }
     854             : 
     855           0 : static void swsci_setup(struct drm_device *dev)
     856             : {
     857           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     858           0 :         struct intel_opregion *opregion = &dev_priv->opregion;
     859             :         bool requested_callbacks = false;
     860           0 :         u32 tmp;
     861             : 
     862             :         /* Sub-function code 0 is okay, let's allow them. */
     863           0 :         opregion->swsci_gbda_sub_functions = 1;
     864           0 :         opregion->swsci_sbcb_sub_functions = 1;
     865             : 
     866             :         /* We use GBDA to ask for supported GBDA calls. */
     867           0 :         if (swsci(dev, SWSCI_GBDA_SUPPORTED_CALLS, 0, &tmp) == 0) {
     868             :                 /* make the bits match the sub-function codes */
     869           0 :                 tmp <<= 1;
     870           0 :                 opregion->swsci_gbda_sub_functions |= tmp;
     871           0 :         }
     872             : 
     873             :         /*
     874             :          * We also use GBDA to ask for _requested_ SBCB callbacks. The driver
     875             :          * must not call interfaces that are not specifically requested by the
     876             :          * bios.
     877             :          */
     878           0 :         if (swsci(dev, SWSCI_GBDA_REQUESTED_CALLBACKS, 0, &tmp) == 0) {
     879             :                 /* here, the bits already match sub-function codes */
     880           0 :                 opregion->swsci_sbcb_sub_functions |= tmp;
     881             :                 requested_callbacks = true;
     882           0 :         }
     883             : 
     884             :         /*
     885             :          * But we use SBCB to ask for _supported_ SBCB calls. This does not mean
     886             :          * the callback is _requested_. But we still can't call interfaces that
     887             :          * are not requested.
     888             :          */
     889           0 :         if (swsci(dev, SWSCI_SBCB_SUPPORTED_CALLBACKS, 0, &tmp) == 0) {
     890             :                 /* make the bits match the sub-function codes */
     891           0 :                 u32 low = tmp & 0x7ff;
     892           0 :                 u32 high = tmp & ~0xfff; /* bit 11 is reserved */
     893           0 :                 tmp = (high << 4) | (low << 1) | 1;
     894             : 
     895             :                 /* best guess what to do with supported wrt requested */
     896           0 :                 if (requested_callbacks) {
     897           0 :                         u32 req = opregion->swsci_sbcb_sub_functions;
     898           0 :                         if ((req & tmp) != req)
     899             :                                 DRM_DEBUG_DRIVER("SWSCI BIOS requested (%08x) SBCB callbacks that are not supported (%08x)\n", req, tmp);
     900             :                         /* XXX: for now, trust the requested callbacks */
     901             :                         /* opregion->swsci_sbcb_sub_functions &= tmp; */
     902           0 :                 } else {
     903           0 :                         opregion->swsci_sbcb_sub_functions |= tmp;
     904             :                 }
     905           0 :         }
     906             : 
     907             :         DRM_DEBUG_DRIVER("SWSCI GBDA callbacks %08x, SBCB callbacks %08x\n",
     908             :                          opregion->swsci_gbda_sub_functions,
     909             :                          opregion->swsci_sbcb_sub_functions);
     910           0 : }
     911             : #else /* CONFIG_ACPI */
     912             : static inline void swsci_setup(struct drm_device *dev) {}
     913             : #endif  /* CONFIG_ACPI */
     914             : 
     915           0 : int intel_opregion_setup(struct drm_device *dev)
     916             : {
     917           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     918           0 :         struct intel_opregion *opregion = &dev_priv->opregion;
     919           0 :         u32 asls, mboxes;
     920           0 :         char buf[sizeof(OPREGION_SIGNATURE)];
     921             :         int err = 0;
     922             :         void *base;
     923             : 
     924             :         BUILD_BUG_ON(sizeof(struct opregion_header) != 0x100);
     925             :         BUILD_BUG_ON(sizeof(struct opregion_acpi) != 0x100);
     926             :         BUILD_BUG_ON(sizeof(struct opregion_swsci) != 0x100);
     927             :         BUILD_BUG_ON(sizeof(struct opregion_asle) != 0x100);
     928             : 
     929           0 :         pci_read_config_dword(dev->pdev, PCI_ASLS, &asls);
     930             :         DRM_DEBUG_DRIVER("graphic opregion physical addr: 0x%x\n", asls);
     931           0 :         if (asls == 0) {
     932             :                 DRM_DEBUG_DRIVER("ACPI OpRegion not supported!\n");
     933           0 :                 return -ENOTSUPP;
     934             :         }
     935             : 
     936             : #ifdef CONFIG_ACPI
     937           0 :         INIT_WORK(&opregion->asle_work, asle_work);
     938             : #endif
     939             : 
     940             : #ifdef __linux
     941             :         base = memremap(asls, OPREGION_SIZE, MEMREMAP_WB);
     942             :         if (!base)
     943             :                 return -ENOMEM;
     944             : #else
     945           0 :         if (bus_space_map(dev_priv->bst, asls, OPREGION_SIZE,
     946           0 :             BUS_SPACE_MAP_LINEAR, &dev_priv->opregion_ioh))
     947           0 :                 return -ENOMEM;
     948           0 :         base = bus_space_vaddr(dev_priv->bst, dev_priv->opregion_ioh);
     949             : #endif
     950             : 
     951           0 :         memcpy(buf, base, sizeof(buf));
     952             : 
     953           0 :         if (memcmp(buf, OPREGION_SIGNATURE, 16)) {
     954             :                 DRM_DEBUG_DRIVER("opregion signature mismatch\n");
     955             :                 err = -EINVAL;
     956             :                 goto err_out;
     957             :         }
     958           0 :         opregion->header = base;
     959           0 :         opregion->vbt = base + OPREGION_VBT_OFFSET;
     960             : 
     961           0 :         opregion->lid_state = base + ACPI_CLID;
     962             : 
     963           0 :         mboxes = opregion->header->mboxes;
     964           0 :         if (mboxes & MBOX_ACPI) {
     965             :                 DRM_DEBUG_DRIVER("Public ACPI methods supported\n");
     966           0 :                 opregion->acpi = base + OPREGION_ACPI_OFFSET;
     967           0 :         }
     968             : 
     969           0 :         if (mboxes & MBOX_SWSCI) {
     970             :                 DRM_DEBUG_DRIVER("SWSCI supported\n");
     971           0 :                 opregion->swsci = base + OPREGION_SWSCI_OFFSET;
     972           0 :                 swsci_setup(dev);
     973           0 :         }
     974           0 :         if (mboxes & MBOX_ASLE) {
     975             :                 DRM_DEBUG_DRIVER("ASLE supported\n");
     976           0 :                 opregion->asle = base + OPREGION_ASLE_OFFSET;
     977             : 
     978           0 :                 opregion->asle->ardy = ASLE_ARDY_NOT_READY;
     979           0 :         }
     980             : 
     981           0 :         return 0;
     982             : 
     983             : err_out:
     984             : #ifdef __linux__
     985             :         memunmap(base);
     986             : #else
     987           0 :         bus_space_unmap(dev_priv->bst, dev_priv->opregion_ioh, OPREGION_SIZE);
     988             : #endif
     989           0 :         return err;
     990           0 : }

Generated by: LCOV version 1.13