Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2008 Intel Corporation <hong.liu@intel.com>
0003  * Copyright 2008 Red Hat <mjg@redhat.com>
0004  *
0005  * Permission is hereby granted, free of charge, to any person obtaining
0006  * a copy of this software and associated documentation files (the
0007  * "Software"), to deal in the Software without restriction, including
0008  * without limitation the rights to use, copy, modify, merge, publish,
0009  * distribute, sub license, and/or sell copies of the Software, and to
0010  * permit persons to whom the Software is furnished to do so, subject to
0011  * the following conditions:
0012  *
0013  * The above copyright notice and this permission notice (including the
0014  * next paragraph) shall be included in all copies or substantial
0015  * portions of the Software.
0016  *
0017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
0018  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
0020  * NON-INFRINGEMENT.  IN NO EVENT SHALL INTEL AND/OR ITS SUPPLIERS BE
0021  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
0022  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0023  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0024  * SOFTWARE.
0025  *
0026  */
0027 
0028 #include <linux/acpi.h>
0029 #include <linux/dmi.h>
0030 #include <linux/firmware.h>
0031 #include <acpi/video.h>
0032 
0033 #include <drm/drm_edid.h>
0034 
0035 #include "i915_drv.h"
0036 #include "intel_acpi.h"
0037 #include "intel_backlight.h"
0038 #include "intel_display_types.h"
0039 #include "intel_opregion.h"
0040 #include "intel_pci_config.h"
0041 
0042 #define OPREGION_HEADER_OFFSET 0
0043 #define OPREGION_ACPI_OFFSET   0x100
0044 #define   ACPI_CLID 0x01ac /* current lid state indicator */
0045 #define   ACPI_CDCK 0x01b0 /* current docking state indicator */
0046 #define OPREGION_SWSCI_OFFSET  0x200
0047 #define OPREGION_ASLE_OFFSET   0x300
0048 #define OPREGION_VBT_OFFSET    0x400
0049 #define OPREGION_ASLE_EXT_OFFSET    0x1C00
0050 
0051 #define OPREGION_SIGNATURE "IntelGraphicsMem"
0052 #define MBOX_ACPI       BIT(0)  /* Mailbox #1 */
0053 #define MBOX_SWSCI      BIT(1)  /* Mailbox #2 (obsolete from v2.x) */
0054 #define MBOX_ASLE       BIT(2)  /* Mailbox #3 */
0055 #define MBOX_ASLE_EXT       BIT(4)  /* Mailbox #5 */
0056 #define MBOX_BACKLIGHT      BIT(5)  /* Mailbox #2 (valid from v3.x) */
0057 
0058 #define PCON_HEADLESS_SKU   BIT(13)
0059 
0060 struct opregion_header {
0061     u8 signature[16];
0062     u32 size;
0063     struct {
0064         u8 rsvd;
0065         u8 revision;
0066         u8 minor;
0067         u8 major;
0068     }  __packed over;
0069     u8 bios_ver[32];
0070     u8 vbios_ver[16];
0071     u8 driver_ver[16];
0072     u32 mboxes;
0073     u32 driver_model;
0074     u32 pcon;
0075     u8 dver[32];
0076     u8 rsvd[124];
0077 } __packed;
0078 
0079 /* OpRegion mailbox #1: public ACPI methods */
0080 struct opregion_acpi {
0081     u32 drdy;       /* driver readiness */
0082     u32 csts;       /* notification status */
0083     u32 cevt;       /* current event */
0084     u8 rsvd1[20];
0085     u32 didl[8];    /* supported display devices ID list */
0086     u32 cpdl[8];    /* currently presented display list */
0087     u32 cadl[8];    /* currently active display list */
0088     u32 nadl[8];    /* next active devices list */
0089     u32 aslp;       /* ASL sleep time-out */
0090     u32 tidx;       /* toggle table index */
0091     u32 chpd;       /* current hotplug enable indicator */
0092     u32 clid;       /* current lid state*/
0093     u32 cdck;       /* current docking state */
0094     u32 sxsw;       /* Sx state resume */
0095     u32 evts;       /* ASL supported events */
0096     u32 cnot;       /* current OS notification */
0097     u32 nrdy;       /* driver status */
0098     u32 did2[7];    /* extended supported display devices ID list */
0099     u32 cpd2[7];    /* extended attached display devices list */
0100     u8 rsvd2[4];
0101 } __packed;
0102 
0103 /* OpRegion mailbox #2: SWSCI */
0104 struct opregion_swsci {
0105     u32 scic;       /* SWSCI command|status|data */
0106     u32 parm;       /* command parameters */
0107     u32 dslp;       /* driver sleep time-out */
0108     u8 rsvd[244];
0109 } __packed;
0110 
0111 /* OpRegion mailbox #3: ASLE */
0112 struct opregion_asle {
0113     u32 ardy;       /* driver readiness */
0114     u32 aslc;       /* ASLE interrupt command */
0115     u32 tche;       /* technology enabled indicator */
0116     u32 alsi;       /* current ALS illuminance reading */
0117     u32 bclp;       /* backlight brightness to set */
0118     u32 pfit;       /* panel fitting state */
0119     u32 cblv;       /* current brightness level */
0120     u16 bclm[20];   /* backlight level duty cycle mapping table */
0121     u32 cpfm;       /* current panel fitting mode */
0122     u32 epfm;       /* enabled panel fitting modes */
0123     u8 plut[74];    /* panel LUT and identifier */
0124     u32 pfmb;       /* PWM freq and min brightness */
0125     u32 cddv;       /* color correction default values */
0126     u32 pcft;       /* power conservation features */
0127     u32 srot;       /* supported rotation angles */
0128     u32 iuer;       /* IUER events */
0129     u64 fdss;
0130     u32 fdsp;
0131     u32 stat;
0132     u64 rvda;   /* Physical (2.0) or relative from opregion (2.1+)
0133              * address of raw VBT data. */
0134     u32 rvds;   /* Size of raw vbt data */
0135     u8 rsvd[58];
0136 } __packed;
0137 
0138 /* OpRegion mailbox #5: ASLE ext */
0139 struct opregion_asle_ext {
0140     u32 phed;   /* Panel Header */
0141     u8 bddc[256];   /* Panel EDID */
0142     u8 rsvd[764];
0143 } __packed;
0144 
0145 /* Driver readiness indicator */
0146 #define ASLE_ARDY_READY     (1 << 0)
0147 #define ASLE_ARDY_NOT_READY (0 << 0)
0148 
0149 /* ASLE Interrupt Command (ASLC) bits */
0150 #define ASLC_SET_ALS_ILLUM      (1 << 0)
0151 #define ASLC_SET_BACKLIGHT      (1 << 1)
0152 #define ASLC_SET_PFIT           (1 << 2)
0153 #define ASLC_SET_PWM_FREQ       (1 << 3)
0154 #define ASLC_SUPPORTED_ROTATION_ANGLES  (1 << 4)
0155 #define ASLC_BUTTON_ARRAY       (1 << 5)
0156 #define ASLC_CONVERTIBLE_INDICATOR  (1 << 6)
0157 #define ASLC_DOCKING_INDICATOR      (1 << 7)
0158 #define ASLC_ISCT_STATE_CHANGE      (1 << 8)
0159 #define ASLC_REQ_MSK            0x1ff
0160 /* response bits */
0161 #define ASLC_ALS_ILLUM_FAILED       (1 << 10)
0162 #define ASLC_BACKLIGHT_FAILED       (1 << 12)
0163 #define ASLC_PFIT_FAILED        (1 << 14)
0164 #define ASLC_PWM_FREQ_FAILED        (1 << 16)
0165 #define ASLC_ROTATION_ANGLES_FAILED (1 << 18)
0166 #define ASLC_BUTTON_ARRAY_FAILED    (1 << 20)
0167 #define ASLC_CONVERTIBLE_FAILED     (1 << 22)
0168 #define ASLC_DOCKING_FAILED     (1 << 24)
0169 #define ASLC_ISCT_STATE_FAILED      (1 << 26)
0170 
0171 /* Technology enabled indicator */
0172 #define ASLE_TCHE_ALS_EN    (1 << 0)
0173 #define ASLE_TCHE_BLC_EN    (1 << 1)
0174 #define ASLE_TCHE_PFIT_EN   (1 << 2)
0175 #define ASLE_TCHE_PFMB_EN   (1 << 3)
0176 
0177 /* ASLE backlight brightness to set */
0178 #define ASLE_BCLP_VALID                (1<<31)
0179 #define ASLE_BCLP_MSK          (~(1<<31))
0180 
0181 /* ASLE panel fitting request */
0182 #define ASLE_PFIT_VALID         (1<<31)
0183 #define ASLE_PFIT_CENTER (1<<0)
0184 #define ASLE_PFIT_STRETCH_TEXT (1<<1)
0185 #define ASLE_PFIT_STRETCH_GFX (1<<2)
0186 
0187 /* PWM frequency and minimum brightness */
0188 #define ASLE_PFMB_BRIGHTNESS_MASK (0xff)
0189 #define ASLE_PFMB_BRIGHTNESS_VALID (1<<8)
0190 #define ASLE_PFMB_PWM_MASK (0x7ffffe00)
0191 #define ASLE_PFMB_PWM_VALID (1<<31)
0192 
0193 #define ASLE_CBLV_VALID         (1<<31)
0194 
0195 /* IUER */
0196 #define ASLE_IUER_DOCKING       (1 << 7)
0197 #define ASLE_IUER_CONVERTIBLE       (1 << 6)
0198 #define ASLE_IUER_ROTATION_LOCK_BTN (1 << 4)
0199 #define ASLE_IUER_VOLUME_DOWN_BTN   (1 << 3)
0200 #define ASLE_IUER_VOLUME_UP_BTN     (1 << 2)
0201 #define ASLE_IUER_WINDOWS_BTN       (1 << 1)
0202 #define ASLE_IUER_POWER_BTN     (1 << 0)
0203 
0204 #define ASLE_PHED_EDID_VALID_MASK   0x3
0205 
0206 /* Software System Control Interrupt (SWSCI) */
0207 #define SWSCI_SCIC_INDICATOR        (1 << 0)
0208 #define SWSCI_SCIC_MAIN_FUNCTION_SHIFT  1
0209 #define SWSCI_SCIC_MAIN_FUNCTION_MASK   (0xf << 1)
0210 #define SWSCI_SCIC_SUB_FUNCTION_SHIFT   8
0211 #define SWSCI_SCIC_SUB_FUNCTION_MASK    (0xff << 8)
0212 #define SWSCI_SCIC_EXIT_PARAMETER_SHIFT 8
0213 #define SWSCI_SCIC_EXIT_PARAMETER_MASK  (0xff << 8)
0214 #define SWSCI_SCIC_EXIT_STATUS_SHIFT    5
0215 #define SWSCI_SCIC_EXIT_STATUS_MASK (7 << 5)
0216 #define SWSCI_SCIC_EXIT_STATUS_SUCCESS  1
0217 
0218 #define SWSCI_FUNCTION_CODE(main, sub) \
0219     ((main) << SWSCI_SCIC_MAIN_FUNCTION_SHIFT | \
0220      (sub) << SWSCI_SCIC_SUB_FUNCTION_SHIFT)
0221 
0222 /* SWSCI: Get BIOS Data (GBDA) */
0223 #define SWSCI_GBDA          4
0224 #define SWSCI_GBDA_SUPPORTED_CALLS  SWSCI_FUNCTION_CODE(SWSCI_GBDA, 0)
0225 #define SWSCI_GBDA_REQUESTED_CALLBACKS  SWSCI_FUNCTION_CODE(SWSCI_GBDA, 1)
0226 #define SWSCI_GBDA_BOOT_DISPLAY_PREF    SWSCI_FUNCTION_CODE(SWSCI_GBDA, 4)
0227 #define SWSCI_GBDA_PANEL_DETAILS    SWSCI_FUNCTION_CODE(SWSCI_GBDA, 5)
0228 #define SWSCI_GBDA_TV_STANDARD      SWSCI_FUNCTION_CODE(SWSCI_GBDA, 6)
0229 #define SWSCI_GBDA_INTERNAL_GRAPHICS    SWSCI_FUNCTION_CODE(SWSCI_GBDA, 7)
0230 #define SWSCI_GBDA_SPREAD_SPECTRUM  SWSCI_FUNCTION_CODE(SWSCI_GBDA, 10)
0231 
0232 /* SWSCI: System BIOS Callbacks (SBCB) */
0233 #define SWSCI_SBCB          6
0234 #define SWSCI_SBCB_SUPPORTED_CALLBACKS  SWSCI_FUNCTION_CODE(SWSCI_SBCB, 0)
0235 #define SWSCI_SBCB_INIT_COMPLETION  SWSCI_FUNCTION_CODE(SWSCI_SBCB, 1)
0236 #define SWSCI_SBCB_PRE_HIRES_SET_MODE   SWSCI_FUNCTION_CODE(SWSCI_SBCB, 3)
0237 #define SWSCI_SBCB_POST_HIRES_SET_MODE  SWSCI_FUNCTION_CODE(SWSCI_SBCB, 4)
0238 #define SWSCI_SBCB_DISPLAY_SWITCH   SWSCI_FUNCTION_CODE(SWSCI_SBCB, 5)
0239 #define SWSCI_SBCB_SET_TV_FORMAT    SWSCI_FUNCTION_CODE(SWSCI_SBCB, 6)
0240 #define SWSCI_SBCB_ADAPTER_POWER_STATE  SWSCI_FUNCTION_CODE(SWSCI_SBCB, 7)
0241 #define SWSCI_SBCB_DISPLAY_POWER_STATE  SWSCI_FUNCTION_CODE(SWSCI_SBCB, 8)
0242 #define SWSCI_SBCB_SET_BOOT_DISPLAY SWSCI_FUNCTION_CODE(SWSCI_SBCB, 9)
0243 #define SWSCI_SBCB_SET_PANEL_DETAILS    SWSCI_FUNCTION_CODE(SWSCI_SBCB, 10)
0244 #define SWSCI_SBCB_SET_INTERNAL_GFX SWSCI_FUNCTION_CODE(SWSCI_SBCB, 11)
0245 #define SWSCI_SBCB_POST_HIRES_TO_DOS_FS SWSCI_FUNCTION_CODE(SWSCI_SBCB, 16)
0246 #define SWSCI_SBCB_SUSPEND_RESUME   SWSCI_FUNCTION_CODE(SWSCI_SBCB, 17)
0247 #define SWSCI_SBCB_SET_SPREAD_SPECTRUM  SWSCI_FUNCTION_CODE(SWSCI_SBCB, 18)
0248 #define SWSCI_SBCB_POST_VBE_PM      SWSCI_FUNCTION_CODE(SWSCI_SBCB, 19)
0249 #define SWSCI_SBCB_ENABLE_DISABLE_AUDIO SWSCI_FUNCTION_CODE(SWSCI_SBCB, 21)
0250 
0251 #define MAX_DSLP    1500
0252 
0253 static int check_swsci_function(struct drm_i915_private *i915, u32 function)
0254 {
0255     struct opregion_swsci *swsci = i915->opregion.swsci;
0256     u32 main_function, sub_function;
0257 
0258     if (!swsci)
0259         return -ENODEV;
0260 
0261     main_function = (function & SWSCI_SCIC_MAIN_FUNCTION_MASK) >>
0262         SWSCI_SCIC_MAIN_FUNCTION_SHIFT;
0263     sub_function = (function & SWSCI_SCIC_SUB_FUNCTION_MASK) >>
0264         SWSCI_SCIC_SUB_FUNCTION_SHIFT;
0265 
0266     /* Check if we can call the function. See swsci_setup for details. */
0267     if (main_function == SWSCI_SBCB) {
0268         if ((i915->opregion.swsci_sbcb_sub_functions &
0269              (1 << sub_function)) == 0)
0270             return -EINVAL;
0271     } else if (main_function == SWSCI_GBDA) {
0272         if ((i915->opregion.swsci_gbda_sub_functions &
0273              (1 << sub_function)) == 0)
0274             return -EINVAL;
0275     }
0276 
0277     return 0;
0278 }
0279 
0280 static int swsci(struct drm_i915_private *dev_priv,
0281          u32 function, u32 parm, u32 *parm_out)
0282 {
0283     struct opregion_swsci *swsci = dev_priv->opregion.swsci;
0284     struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
0285     u32 scic, dslp;
0286     u16 swsci_val;
0287     int ret;
0288 
0289     ret = check_swsci_function(dev_priv, function);
0290     if (ret)
0291         return ret;
0292 
0293     /* Driver sleep timeout in ms. */
0294     dslp = swsci->dslp;
0295     if (!dslp) {
0296         /* The spec says 2ms should be the default, but it's too small
0297          * for some machines. */
0298         dslp = 50;
0299     } else if (dslp > MAX_DSLP) {
0300         /* Hey bios, trust must be earned. */
0301         DRM_INFO_ONCE("ACPI BIOS requests an excessive sleep of %u ms, "
0302                   "using %u ms instead\n", dslp, MAX_DSLP);
0303         dslp = MAX_DSLP;
0304     }
0305 
0306     /* The spec tells us to do this, but we are the only user... */
0307     scic = swsci->scic;
0308     if (scic & SWSCI_SCIC_INDICATOR) {
0309         drm_dbg(&dev_priv->drm, "SWSCI request already in progress\n");
0310         return -EBUSY;
0311     }
0312 
0313     scic = function | SWSCI_SCIC_INDICATOR;
0314 
0315     swsci->parm = parm;
0316     swsci->scic = scic;
0317 
0318     /* Ensure SCI event is selected and event trigger is cleared. */
0319     pci_read_config_word(pdev, SWSCI, &swsci_val);
0320     if (!(swsci_val & SWSCI_SCISEL) || (swsci_val & SWSCI_GSSCIE)) {
0321         swsci_val |= SWSCI_SCISEL;
0322         swsci_val &= ~SWSCI_GSSCIE;
0323         pci_write_config_word(pdev, SWSCI, swsci_val);
0324     }
0325 
0326     /* Use event trigger to tell bios to check the mail. */
0327     swsci_val |= SWSCI_GSSCIE;
0328     pci_write_config_word(pdev, SWSCI, swsci_val);
0329 
0330     /* Poll for the result. */
0331 #define C (((scic = swsci->scic) & SWSCI_SCIC_INDICATOR) == 0)
0332     if (wait_for(C, dslp)) {
0333         drm_dbg(&dev_priv->drm, "SWSCI request timed out\n");
0334         return -ETIMEDOUT;
0335     }
0336 
0337     scic = (scic & SWSCI_SCIC_EXIT_STATUS_MASK) >>
0338         SWSCI_SCIC_EXIT_STATUS_SHIFT;
0339 
0340     /* Note: scic == 0 is an error! */
0341     if (scic != SWSCI_SCIC_EXIT_STATUS_SUCCESS) {
0342         drm_dbg(&dev_priv->drm, "SWSCI request error %u\n", scic);
0343         return -EIO;
0344     }
0345 
0346     if (parm_out)
0347         *parm_out = swsci->parm;
0348 
0349     return 0;
0350 
0351 #undef C
0352 }
0353 
0354 #define DISPLAY_TYPE_CRT            0
0355 #define DISPLAY_TYPE_TV             1
0356 #define DISPLAY_TYPE_EXTERNAL_FLAT_PANEL    2
0357 #define DISPLAY_TYPE_INTERNAL_FLAT_PANEL    3
0358 
0359 int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
0360                   bool enable)
0361 {
0362     struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
0363     u32 parm = 0;
0364     u32 type = 0;
0365     u32 port;
0366     int ret;
0367 
0368     /* don't care about old stuff for now */
0369     if (!HAS_DDI(dev_priv))
0370         return 0;
0371 
0372     /* Avoid port out of bounds checks if SWSCI isn't there. */
0373     ret = check_swsci_function(dev_priv, SWSCI_SBCB_DISPLAY_POWER_STATE);
0374     if (ret)
0375         return ret;
0376 
0377     if (intel_encoder->type == INTEL_OUTPUT_DSI)
0378         port = 0;
0379     else
0380         port = intel_encoder->port;
0381 
0382     if (port == PORT_E)  {
0383         port = 0;
0384     } else {
0385         parm |= 1 << port;
0386         port++;
0387     }
0388 
0389     /*
0390      * The port numbering and mapping here is bizarre. The now-obsolete
0391      * swsci spec supports ports numbered [0..4]. Port E is handled as a
0392      * special case, but port F and beyond are not. The functionality is
0393      * supposed to be obsolete for new platforms. Just bail out if the port
0394      * number is out of bounds after mapping.
0395      */
0396     if (port > 4) {
0397         drm_dbg_kms(&dev_priv->drm,
0398                 "[ENCODER:%d:%s] port %c (index %u) out of bounds for display power state notification\n",
0399                 intel_encoder->base.base.id, intel_encoder->base.name,
0400                 port_name(intel_encoder->port), port);
0401         return -EINVAL;
0402     }
0403 
0404     if (!enable)
0405         parm |= 4 << 8;
0406 
0407     switch (intel_encoder->type) {
0408     case INTEL_OUTPUT_ANALOG:
0409         type = DISPLAY_TYPE_CRT;
0410         break;
0411     case INTEL_OUTPUT_DDI:
0412     case INTEL_OUTPUT_DP:
0413     case INTEL_OUTPUT_HDMI:
0414     case INTEL_OUTPUT_DP_MST:
0415         type = DISPLAY_TYPE_EXTERNAL_FLAT_PANEL;
0416         break;
0417     case INTEL_OUTPUT_EDP:
0418     case INTEL_OUTPUT_DSI:
0419         type = DISPLAY_TYPE_INTERNAL_FLAT_PANEL;
0420         break;
0421     default:
0422         drm_WARN_ONCE(&dev_priv->drm, 1,
0423                   "unsupported intel_encoder type %d\n",
0424                   intel_encoder->type);
0425         return -EINVAL;
0426     }
0427 
0428     parm |= type << (16 + port * 3);
0429 
0430     return swsci(dev_priv, SWSCI_SBCB_DISPLAY_POWER_STATE, parm, NULL);
0431 }
0432 
0433 static const struct {
0434     pci_power_t pci_power_state;
0435     u32 parm;
0436 } power_state_map[] = {
0437     { PCI_D0,   0x00 },
0438     { PCI_D1,   0x01 },
0439     { PCI_D2,   0x02 },
0440     { PCI_D3hot,    0x04 },
0441     { PCI_D3cold,   0x04 },
0442 };
0443 
0444 int intel_opregion_notify_adapter(struct drm_i915_private *dev_priv,
0445                   pci_power_t state)
0446 {
0447     int i;
0448 
0449     if (!HAS_DDI(dev_priv))
0450         return 0;
0451 
0452     for (i = 0; i < ARRAY_SIZE(power_state_map); i++) {
0453         if (state == power_state_map[i].pci_power_state)
0454             return swsci(dev_priv, SWSCI_SBCB_ADAPTER_POWER_STATE,
0455                      power_state_map[i].parm, NULL);
0456     }
0457 
0458     return -EINVAL;
0459 }
0460 
0461 static u32 asle_set_backlight(struct drm_i915_private *dev_priv, u32 bclp)
0462 {
0463     struct intel_connector *connector;
0464     struct drm_connector_list_iter conn_iter;
0465     struct opregion_asle *asle = dev_priv->opregion.asle;
0466     struct drm_device *dev = &dev_priv->drm;
0467 
0468     drm_dbg(&dev_priv->drm, "bclp = 0x%08x\n", bclp);
0469 
0470     if (acpi_video_get_backlight_type() == acpi_backlight_native) {
0471         drm_dbg_kms(&dev_priv->drm,
0472                 "opregion backlight request ignored\n");
0473         return 0;
0474     }
0475 
0476     if (!(bclp & ASLE_BCLP_VALID))
0477         return ASLC_BACKLIGHT_FAILED;
0478 
0479     bclp &= ASLE_BCLP_MSK;
0480     if (bclp > 255)
0481         return ASLC_BACKLIGHT_FAILED;
0482 
0483     drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
0484 
0485     /*
0486      * Update backlight on all connectors that support backlight (usually
0487      * only one).
0488      */
0489     drm_dbg_kms(&dev_priv->drm, "updating opregion backlight %d/255\n",
0490             bclp);
0491     drm_connector_list_iter_begin(dev, &conn_iter);
0492     for_each_intel_connector_iter(connector, &conn_iter)
0493         intel_backlight_set_acpi(connector->base.state, bclp, 255);
0494     drm_connector_list_iter_end(&conn_iter);
0495     asle->cblv = DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID;
0496 
0497     drm_modeset_unlock(&dev->mode_config.connection_mutex);
0498 
0499 
0500     return 0;
0501 }
0502 
0503 static u32 asle_set_als_illum(struct drm_i915_private *dev_priv, u32 alsi)
0504 {
0505     /* alsi is the current ALS reading in lux. 0 indicates below sensor
0506        range, 0xffff indicates above sensor range. 1-0xfffe are valid */
0507     drm_dbg(&dev_priv->drm, "Illum is not supported\n");
0508     return ASLC_ALS_ILLUM_FAILED;
0509 }
0510 
0511 static u32 asle_set_pwm_freq(struct drm_i915_private *dev_priv, u32 pfmb)
0512 {
0513     drm_dbg(&dev_priv->drm, "PWM freq is not supported\n");
0514     return ASLC_PWM_FREQ_FAILED;
0515 }
0516 
0517 static u32 asle_set_pfit(struct drm_i915_private *dev_priv, u32 pfit)
0518 {
0519     /* Panel fitting is currently controlled by the X code, so this is a
0520        noop until modesetting support works fully */
0521     drm_dbg(&dev_priv->drm, "Pfit is not supported\n");
0522     return ASLC_PFIT_FAILED;
0523 }
0524 
0525 static u32 asle_set_supported_rotation_angles(struct drm_i915_private *dev_priv, u32 srot)
0526 {
0527     drm_dbg(&dev_priv->drm, "SROT is not supported\n");
0528     return ASLC_ROTATION_ANGLES_FAILED;
0529 }
0530 
0531 static u32 asle_set_button_array(struct drm_i915_private *dev_priv, u32 iuer)
0532 {
0533     if (!iuer)
0534         drm_dbg(&dev_priv->drm,
0535             "Button array event is not supported (nothing)\n");
0536     if (iuer & ASLE_IUER_ROTATION_LOCK_BTN)
0537         drm_dbg(&dev_priv->drm,
0538             "Button array event is not supported (rotation lock)\n");
0539     if (iuer & ASLE_IUER_VOLUME_DOWN_BTN)
0540         drm_dbg(&dev_priv->drm,
0541             "Button array event is not supported (volume down)\n");
0542     if (iuer & ASLE_IUER_VOLUME_UP_BTN)
0543         drm_dbg(&dev_priv->drm,
0544             "Button array event is not supported (volume up)\n");
0545     if (iuer & ASLE_IUER_WINDOWS_BTN)
0546         drm_dbg(&dev_priv->drm,
0547             "Button array event is not supported (windows)\n");
0548     if (iuer & ASLE_IUER_POWER_BTN)
0549         drm_dbg(&dev_priv->drm,
0550             "Button array event is not supported (power)\n");
0551 
0552     return ASLC_BUTTON_ARRAY_FAILED;
0553 }
0554 
0555 static u32 asle_set_convertible(struct drm_i915_private *dev_priv, u32 iuer)
0556 {
0557     if (iuer & ASLE_IUER_CONVERTIBLE)
0558         drm_dbg(&dev_priv->drm,
0559             "Convertible is not supported (clamshell)\n");
0560     else
0561         drm_dbg(&dev_priv->drm,
0562             "Convertible is not supported (slate)\n");
0563 
0564     return ASLC_CONVERTIBLE_FAILED;
0565 }
0566 
0567 static u32 asle_set_docking(struct drm_i915_private *dev_priv, u32 iuer)
0568 {
0569     if (iuer & ASLE_IUER_DOCKING)
0570         drm_dbg(&dev_priv->drm, "Docking is not supported (docked)\n");
0571     else
0572         drm_dbg(&dev_priv->drm,
0573             "Docking is not supported (undocked)\n");
0574 
0575     return ASLC_DOCKING_FAILED;
0576 }
0577 
0578 static u32 asle_isct_state(struct drm_i915_private *dev_priv)
0579 {
0580     drm_dbg(&dev_priv->drm, "ISCT is not supported\n");
0581     return ASLC_ISCT_STATE_FAILED;
0582 }
0583 
0584 static void asle_work(struct work_struct *work)
0585 {
0586     struct intel_opregion *opregion =
0587         container_of(work, struct intel_opregion, asle_work);
0588     struct drm_i915_private *dev_priv =
0589         container_of(opregion, struct drm_i915_private, opregion);
0590     struct opregion_asle *asle = dev_priv->opregion.asle;
0591     u32 aslc_stat = 0;
0592     u32 aslc_req;
0593 
0594     if (!asle)
0595         return;
0596 
0597     aslc_req = asle->aslc;
0598 
0599     if (!(aslc_req & ASLC_REQ_MSK)) {
0600         drm_dbg(&dev_priv->drm,
0601             "No request on ASLC interrupt 0x%08x\n", aslc_req);
0602         return;
0603     }
0604 
0605     if (aslc_req & ASLC_SET_ALS_ILLUM)
0606         aslc_stat |= asle_set_als_illum(dev_priv, asle->alsi);
0607 
0608     if (aslc_req & ASLC_SET_BACKLIGHT)
0609         aslc_stat |= asle_set_backlight(dev_priv, asle->bclp);
0610 
0611     if (aslc_req & ASLC_SET_PFIT)
0612         aslc_stat |= asle_set_pfit(dev_priv, asle->pfit);
0613 
0614     if (aslc_req & ASLC_SET_PWM_FREQ)
0615         aslc_stat |= asle_set_pwm_freq(dev_priv, asle->pfmb);
0616 
0617     if (aslc_req & ASLC_SUPPORTED_ROTATION_ANGLES)
0618         aslc_stat |= asle_set_supported_rotation_angles(dev_priv,
0619                             asle->srot);
0620 
0621     if (aslc_req & ASLC_BUTTON_ARRAY)
0622         aslc_stat |= asle_set_button_array(dev_priv, asle->iuer);
0623 
0624     if (aslc_req & ASLC_CONVERTIBLE_INDICATOR)
0625         aslc_stat |= asle_set_convertible(dev_priv, asle->iuer);
0626 
0627     if (aslc_req & ASLC_DOCKING_INDICATOR)
0628         aslc_stat |= asle_set_docking(dev_priv, asle->iuer);
0629 
0630     if (aslc_req & ASLC_ISCT_STATE_CHANGE)
0631         aslc_stat |= asle_isct_state(dev_priv);
0632 
0633     asle->aslc = aslc_stat;
0634 }
0635 
0636 void intel_opregion_asle_intr(struct drm_i915_private *dev_priv)
0637 {
0638     if (dev_priv->opregion.asle)
0639         schedule_work(&dev_priv->opregion.asle_work);
0640 }
0641 
0642 #define ACPI_EV_DISPLAY_SWITCH (1<<0)
0643 #define ACPI_EV_LID            (1<<1)
0644 #define ACPI_EV_DOCK           (1<<2)
0645 
0646 /*
0647  * The only video events relevant to opregion are 0x80. These indicate either a
0648  * docking event, lid switch or display switch request. In Linux, these are
0649  * handled by the dock, button and video drivers.
0650  */
0651 static int intel_opregion_video_event(struct notifier_block *nb,
0652                       unsigned long val, void *data)
0653 {
0654     struct intel_opregion *opregion = container_of(nb, struct intel_opregion,
0655                                acpi_notifier);
0656     struct acpi_bus_event *event = data;
0657     struct opregion_acpi *acpi;
0658     int ret = NOTIFY_OK;
0659 
0660     if (strcmp(event->device_class, ACPI_VIDEO_CLASS) != 0)
0661         return NOTIFY_DONE;
0662 
0663     acpi = opregion->acpi;
0664 
0665     if (event->type == 0x80 && ((acpi->cevt & 1) == 0))
0666         ret = NOTIFY_BAD;
0667 
0668     acpi->csts = 0;
0669 
0670     return ret;
0671 }
0672 
0673 /*
0674  * Initialise the DIDL field in opregion. This passes a list of devices to
0675  * the firmware. Values are defined by section B.4.2 of the ACPI specification
0676  * (version 3)
0677  */
0678 
0679 static void set_did(struct intel_opregion *opregion, int i, u32 val)
0680 {
0681     if (i < ARRAY_SIZE(opregion->acpi->didl)) {
0682         opregion->acpi->didl[i] = val;
0683     } else {
0684         i -= ARRAY_SIZE(opregion->acpi->didl);
0685 
0686         if (WARN_ON(i >= ARRAY_SIZE(opregion->acpi->did2)))
0687             return;
0688 
0689         opregion->acpi->did2[i] = val;
0690     }
0691 }
0692 
0693 static void intel_didl_outputs(struct drm_i915_private *dev_priv)
0694 {
0695     struct intel_opregion *opregion = &dev_priv->opregion;
0696     struct intel_connector *connector;
0697     struct drm_connector_list_iter conn_iter;
0698     int i = 0, max_outputs;
0699 
0700     /*
0701      * In theory, did2, the extended didl, gets added at opregion version
0702      * 3.0. In practice, however, we're supposed to set it for earlier
0703      * versions as well, since a BIOS that doesn't understand did2 should
0704      * not look at it anyway. Use a variable so we can tweak this if a need
0705      * arises later.
0706      */
0707     max_outputs = ARRAY_SIZE(opregion->acpi->didl) +
0708         ARRAY_SIZE(opregion->acpi->did2);
0709 
0710     intel_acpi_device_id_update(dev_priv);
0711 
0712     drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
0713     for_each_intel_connector_iter(connector, &conn_iter) {
0714         if (i < max_outputs)
0715             set_did(opregion, i, connector->acpi_device_id);
0716         i++;
0717     }
0718     drm_connector_list_iter_end(&conn_iter);
0719 
0720     drm_dbg_kms(&dev_priv->drm, "%d outputs detected\n", i);
0721 
0722     if (i > max_outputs)
0723         drm_err(&dev_priv->drm,
0724             "More than %d outputs in connector list\n",
0725             max_outputs);
0726 
0727     /* If fewer than max outputs, the list must be null terminated */
0728     if (i < max_outputs)
0729         set_did(opregion, i, 0);
0730 }
0731 
0732 static void intel_setup_cadls(struct drm_i915_private *dev_priv)
0733 {
0734     struct intel_opregion *opregion = &dev_priv->opregion;
0735     struct intel_connector *connector;
0736     struct drm_connector_list_iter conn_iter;
0737     int i = 0;
0738 
0739     /*
0740      * Initialize the CADL field from the connector device ids. This is
0741      * essentially the same as copying from the DIDL. Technically, this is
0742      * not always correct as display outputs may exist, but not active. This
0743      * initialization is necessary for some Clevo laptops that check this
0744      * field before processing the brightness and display switching hotkeys.
0745      *
0746      * Note that internal panels should be at the front of the connector
0747      * list already, ensuring they're not left out.
0748      */
0749     drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
0750     for_each_intel_connector_iter(connector, &conn_iter) {
0751         if (i >= ARRAY_SIZE(opregion->acpi->cadl))
0752             break;
0753         opregion->acpi->cadl[i++] = connector->acpi_device_id;
0754     }
0755     drm_connector_list_iter_end(&conn_iter);
0756 
0757     /* If fewer than 8 active devices, the list must be null terminated */
0758     if (i < ARRAY_SIZE(opregion->acpi->cadl))
0759         opregion->acpi->cadl[i] = 0;
0760 }
0761 
0762 static void swsci_setup(struct drm_i915_private *dev_priv)
0763 {
0764     struct intel_opregion *opregion = &dev_priv->opregion;
0765     bool requested_callbacks = false;
0766     u32 tmp;
0767 
0768     /* Sub-function code 0 is okay, let's allow them. */
0769     opregion->swsci_gbda_sub_functions = 1;
0770     opregion->swsci_sbcb_sub_functions = 1;
0771 
0772     /* We use GBDA to ask for supported GBDA calls. */
0773     if (swsci(dev_priv, SWSCI_GBDA_SUPPORTED_CALLS, 0, &tmp) == 0) {
0774         /* make the bits match the sub-function codes */
0775         tmp <<= 1;
0776         opregion->swsci_gbda_sub_functions |= tmp;
0777     }
0778 
0779     /*
0780      * We also use GBDA to ask for _requested_ SBCB callbacks. The driver
0781      * must not call interfaces that are not specifically requested by the
0782      * bios.
0783      */
0784     if (swsci(dev_priv, SWSCI_GBDA_REQUESTED_CALLBACKS, 0, &tmp) == 0) {
0785         /* here, the bits already match sub-function codes */
0786         opregion->swsci_sbcb_sub_functions |= tmp;
0787         requested_callbacks = true;
0788     }
0789 
0790     /*
0791      * But we use SBCB to ask for _supported_ SBCB calls. This does not mean
0792      * the callback is _requested_. But we still can't call interfaces that
0793      * are not requested.
0794      */
0795     if (swsci(dev_priv, SWSCI_SBCB_SUPPORTED_CALLBACKS, 0, &tmp) == 0) {
0796         /* make the bits match the sub-function codes */
0797         u32 low = tmp & 0x7ff;
0798         u32 high = tmp & ~0xfff; /* bit 11 is reserved */
0799         tmp = (high << 4) | (low << 1) | 1;
0800 
0801         /* best guess what to do with supported wrt requested */
0802         if (requested_callbacks) {
0803             u32 req = opregion->swsci_sbcb_sub_functions;
0804             if ((req & tmp) != req)
0805                 drm_dbg(&dev_priv->drm,
0806                     "SWSCI BIOS requested (%08x) SBCB callbacks that are not supported (%08x)\n",
0807                     req, tmp);
0808             /* XXX: for now, trust the requested callbacks */
0809             /* opregion->swsci_sbcb_sub_functions &= tmp; */
0810         } else {
0811             opregion->swsci_sbcb_sub_functions |= tmp;
0812         }
0813     }
0814 
0815     drm_dbg(&dev_priv->drm,
0816         "SWSCI GBDA callbacks %08x, SBCB callbacks %08x\n",
0817         opregion->swsci_gbda_sub_functions,
0818         opregion->swsci_sbcb_sub_functions);
0819 }
0820 
0821 static int intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
0822 {
0823     DRM_DEBUG_KMS("Falling back to manually reading VBT from "
0824               "VBIOS ROM for %s\n", id->ident);
0825     return 1;
0826 }
0827 
0828 static const struct dmi_system_id intel_no_opregion_vbt[] = {
0829     {
0830         .callback = intel_no_opregion_vbt_callback,
0831         .ident = "ThinkCentre A57",
0832         .matches = {
0833             DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
0834             DMI_MATCH(DMI_PRODUCT_NAME, "97027RG"),
0835         },
0836     },
0837     { }
0838 };
0839 
0840 static int intel_load_vbt_firmware(struct drm_i915_private *dev_priv)
0841 {
0842     struct intel_opregion *opregion = &dev_priv->opregion;
0843     const struct firmware *fw = NULL;
0844     const char *name = dev_priv->params.vbt_firmware;
0845     int ret;
0846 
0847     if (!name || !*name)
0848         return -ENOENT;
0849 
0850     ret = request_firmware(&fw, name, dev_priv->drm.dev);
0851     if (ret) {
0852         drm_err(&dev_priv->drm,
0853             "Requesting VBT firmware \"%s\" failed (%d)\n",
0854             name, ret);
0855         return ret;
0856     }
0857 
0858     if (intel_bios_is_valid_vbt(fw->data, fw->size)) {
0859         opregion->vbt_firmware = kmemdup(fw->data, fw->size, GFP_KERNEL);
0860         if (opregion->vbt_firmware) {
0861             drm_dbg_kms(&dev_priv->drm,
0862                     "Found valid VBT firmware \"%s\"\n", name);
0863             opregion->vbt = opregion->vbt_firmware;
0864             opregion->vbt_size = fw->size;
0865             ret = 0;
0866         } else {
0867             ret = -ENOMEM;
0868         }
0869     } else {
0870         drm_dbg_kms(&dev_priv->drm, "Invalid VBT firmware \"%s\"\n",
0871                 name);
0872         ret = -EINVAL;
0873     }
0874 
0875     release_firmware(fw);
0876 
0877     return ret;
0878 }
0879 
0880 int intel_opregion_setup(struct drm_i915_private *dev_priv)
0881 {
0882     struct intel_opregion *opregion = &dev_priv->opregion;
0883     struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
0884     u32 asls, mboxes;
0885     char buf[sizeof(OPREGION_SIGNATURE)];
0886     int err = 0;
0887     void *base;
0888     const void *vbt;
0889     u32 vbt_size;
0890 
0891     BUILD_BUG_ON(sizeof(struct opregion_header) != 0x100);
0892     BUILD_BUG_ON(sizeof(struct opregion_acpi) != 0x100);
0893     BUILD_BUG_ON(sizeof(struct opregion_swsci) != 0x100);
0894     BUILD_BUG_ON(sizeof(struct opregion_asle) != 0x100);
0895     BUILD_BUG_ON(sizeof(struct opregion_asle_ext) != 0x400);
0896 
0897     pci_read_config_dword(pdev, ASLS, &asls);
0898     drm_dbg(&dev_priv->drm, "graphic opregion physical addr: 0x%x\n",
0899         asls);
0900     if (asls == 0) {
0901         drm_dbg(&dev_priv->drm, "ACPI OpRegion not supported!\n");
0902         return -ENOTSUPP;
0903     }
0904 
0905     INIT_WORK(&opregion->asle_work, asle_work);
0906 
0907     base = memremap(asls, OPREGION_SIZE, MEMREMAP_WB);
0908     if (!base)
0909         return -ENOMEM;
0910 
0911     memcpy(buf, base, sizeof(buf));
0912 
0913     if (memcmp(buf, OPREGION_SIGNATURE, 16)) {
0914         drm_dbg(&dev_priv->drm, "opregion signature mismatch\n");
0915         err = -EINVAL;
0916         goto err_out;
0917     }
0918     opregion->header = base;
0919     opregion->lid_state = base + ACPI_CLID;
0920 
0921     drm_dbg(&dev_priv->drm, "ACPI OpRegion version %u.%u.%u\n",
0922         opregion->header->over.major,
0923         opregion->header->over.minor,
0924         opregion->header->over.revision);
0925 
0926     mboxes = opregion->header->mboxes;
0927     if (mboxes & MBOX_ACPI) {
0928         drm_dbg(&dev_priv->drm, "Public ACPI methods supported\n");
0929         opregion->acpi = base + OPREGION_ACPI_OFFSET;
0930         /*
0931          * Indicate we handle monitor hotplug events ourselves so we do
0932          * not need ACPI notifications for them. Disabling these avoids
0933          * triggering the AML code doing the notifation, which may be
0934          * broken as Windows also seems to disable these.
0935          */
0936         opregion->acpi->chpd = 1;
0937     }
0938 
0939     if (mboxes & MBOX_SWSCI) {
0940         u8 major = opregion->header->over.major;
0941 
0942         if (major >= 3) {
0943             drm_err(&dev_priv->drm, "SWSCI Mailbox #2 present for opregion v3.x, ignoring\n");
0944         } else {
0945             if (major >= 2)
0946                 drm_dbg(&dev_priv->drm, "SWSCI Mailbox #2 present for opregion v2.x\n");
0947             drm_dbg(&dev_priv->drm, "SWSCI supported\n");
0948             opregion->swsci = base + OPREGION_SWSCI_OFFSET;
0949             swsci_setup(dev_priv);
0950         }
0951     }
0952 
0953     if (mboxes & MBOX_ASLE) {
0954         drm_dbg(&dev_priv->drm, "ASLE supported\n");
0955         opregion->asle = base + OPREGION_ASLE_OFFSET;
0956 
0957         opregion->asle->ardy = ASLE_ARDY_NOT_READY;
0958     }
0959 
0960     if (mboxes & MBOX_ASLE_EXT) {
0961         drm_dbg(&dev_priv->drm, "ASLE extension supported\n");
0962         opregion->asle_ext = base + OPREGION_ASLE_EXT_OFFSET;
0963     }
0964 
0965     if (mboxes & MBOX_BACKLIGHT) {
0966         drm_dbg(&dev_priv->drm, "Mailbox #2 for backlight present\n");
0967     }
0968 
0969     if (intel_load_vbt_firmware(dev_priv) == 0)
0970         goto out;
0971 
0972     if (dmi_check_system(intel_no_opregion_vbt))
0973         goto out;
0974 
0975     if (opregion->header->over.major >= 2 && opregion->asle &&
0976         opregion->asle->rvda && opregion->asle->rvds) {
0977         resource_size_t rvda = opregion->asle->rvda;
0978 
0979         /*
0980          * opregion 2.0: rvda is the physical VBT address.
0981          *
0982          * opregion 2.1+: rvda is unsigned, relative offset from
0983          * opregion base, and should never point within opregion.
0984          */
0985         if (opregion->header->over.major > 2 ||
0986             opregion->header->over.minor >= 1) {
0987             drm_WARN_ON(&dev_priv->drm, rvda < OPREGION_SIZE);
0988 
0989             rvda += asls;
0990         }
0991 
0992         opregion->rvda = memremap(rvda, opregion->asle->rvds,
0993                       MEMREMAP_WB);
0994 
0995         vbt = opregion->rvda;
0996         vbt_size = opregion->asle->rvds;
0997         if (intel_bios_is_valid_vbt(vbt, vbt_size)) {
0998             drm_dbg_kms(&dev_priv->drm,
0999                     "Found valid VBT in ACPI OpRegion (RVDA)\n");
1000             opregion->vbt = vbt;
1001             opregion->vbt_size = vbt_size;
1002             goto out;
1003         } else {
1004             drm_dbg_kms(&dev_priv->drm,
1005                     "Invalid VBT in ACPI OpRegion (RVDA)\n");
1006             memunmap(opregion->rvda);
1007             opregion->rvda = NULL;
1008         }
1009     }
1010 
1011     vbt = base + OPREGION_VBT_OFFSET;
1012     /*
1013      * The VBT specification says that if the ASLE ext mailbox is not used
1014      * its area is reserved, but on some CHT boards the VBT extends into the
1015      * ASLE ext area. Allow this even though it is against the spec, so we
1016      * do not end up rejecting the VBT on those boards (and end up not
1017      * finding the LCD panel because of this).
1018      */
1019     vbt_size = (mboxes & MBOX_ASLE_EXT) ?
1020         OPREGION_ASLE_EXT_OFFSET : OPREGION_SIZE;
1021     vbt_size -= OPREGION_VBT_OFFSET;
1022     if (intel_bios_is_valid_vbt(vbt, vbt_size)) {
1023         drm_dbg_kms(&dev_priv->drm,
1024                 "Found valid VBT in ACPI OpRegion (Mailbox #4)\n");
1025         opregion->vbt = vbt;
1026         opregion->vbt_size = vbt_size;
1027     } else {
1028         drm_dbg_kms(&dev_priv->drm,
1029                 "Invalid VBT in ACPI OpRegion (Mailbox #4)\n");
1030     }
1031 
1032 out:
1033     return 0;
1034 
1035 err_out:
1036     memunmap(base);
1037     return err;
1038 }
1039 
1040 static int intel_use_opregion_panel_type_callback(const struct dmi_system_id *id)
1041 {
1042     DRM_INFO("Using panel type from OpRegion on %s\n", id->ident);
1043     return 1;
1044 }
1045 
1046 static const struct dmi_system_id intel_use_opregion_panel_type[] = {
1047     {
1048         .callback = intel_use_opregion_panel_type_callback,
1049         .ident = "Conrac GmbH IX45GM2",
1050         .matches = {DMI_MATCH(DMI_SYS_VENDOR, "Conrac GmbH"),
1051                 DMI_MATCH(DMI_PRODUCT_NAME, "IX45GM2"),
1052         },
1053     },
1054     { }
1055 };
1056 
1057 int
1058 intel_opregion_get_panel_type(struct drm_i915_private *dev_priv)
1059 {
1060     u32 panel_details;
1061     int ret;
1062 
1063     ret = swsci(dev_priv, SWSCI_GBDA_PANEL_DETAILS, 0x0, &panel_details);
1064     if (ret)
1065         return ret;
1066 
1067     ret = (panel_details >> 8) & 0xff;
1068     if (ret > 0x10) {
1069         drm_dbg_kms(&dev_priv->drm,
1070                 "Invalid OpRegion panel type 0x%x\n", ret);
1071         return -EINVAL;
1072     }
1073 
1074     /* fall back to VBT panel type? */
1075     if (ret == 0x0) {
1076         drm_dbg_kms(&dev_priv->drm, "No panel type in OpRegion\n");
1077         return -ENODEV;
1078     }
1079 
1080     /*
1081      * So far we know that some machined must use it, others must not use it.
1082      * There doesn't seem to be any way to determine which way to go, except
1083      * via a quirk list :(
1084      */
1085     if (!dmi_check_system(intel_use_opregion_panel_type)) {
1086         drm_dbg_kms(&dev_priv->drm,
1087                 "Ignoring OpRegion panel type (%d)\n", ret - 1);
1088         return -ENODEV;
1089     }
1090 
1091     return ret - 1;
1092 }
1093 
1094 /**
1095  * intel_opregion_get_edid - Fetch EDID from ACPI OpRegion mailbox #5
1096  * @intel_connector: eDP connector
1097  *
1098  * This reads the ACPI Opregion mailbox #5 to extract the EDID that is passed
1099  * to it.
1100  *
1101  * Returns:
1102  * The EDID in the OpRegion, or NULL if there is none or it's invalid.
1103  *
1104  */
1105 struct edid *intel_opregion_get_edid(struct intel_connector *intel_connector)
1106 {
1107     struct drm_connector *connector = &intel_connector->base;
1108     struct drm_i915_private *i915 = to_i915(connector->dev);
1109     struct intel_opregion *opregion = &i915->opregion;
1110     const void *in_edid;
1111     const struct edid *edid;
1112     struct edid *new_edid;
1113     int len;
1114 
1115     if (!opregion->asle_ext)
1116         return NULL;
1117 
1118     in_edid = opregion->asle_ext->bddc;
1119 
1120     /* Validity corresponds to number of 128-byte blocks */
1121     len = (opregion->asle_ext->phed & ASLE_PHED_EDID_VALID_MASK) * 128;
1122     if (!len || !memchr_inv(in_edid, 0, len))
1123         return NULL;
1124 
1125     edid = in_edid;
1126 
1127     if (len < EDID_LENGTH * (1 + edid->extensions)) {
1128         drm_dbg_kms(&i915->drm, "Invalid EDID in ACPI OpRegion (Mailbox #5): too short\n");
1129         return NULL;
1130     }
1131     new_edid = drm_edid_duplicate(edid);
1132     if (!new_edid)
1133         return NULL;
1134     if (!drm_edid_is_valid(new_edid)) {
1135         kfree(new_edid);
1136         drm_dbg_kms(&i915->drm, "Invalid EDID in ACPI OpRegion (Mailbox #5)\n");
1137         return NULL;
1138     }
1139     return new_edid;
1140 }
1141 
1142 bool intel_opregion_headless_sku(struct drm_i915_private *i915)
1143 {
1144     struct intel_opregion *opregion = &i915->opregion;
1145     struct opregion_header *header = opregion->header;
1146 
1147     if (!header || header->over.major < 2 ||
1148         (header->over.major == 2 && header->over.minor < 3))
1149         return false;
1150 
1151     return opregion->header->pcon & PCON_HEADLESS_SKU;
1152 }
1153 
1154 void intel_opregion_register(struct drm_i915_private *i915)
1155 {
1156     struct intel_opregion *opregion = &i915->opregion;
1157 
1158     if (!opregion->header)
1159         return;
1160 
1161     if (opregion->acpi) {
1162         opregion->acpi_notifier.notifier_call =
1163             intel_opregion_video_event;
1164         register_acpi_notifier(&opregion->acpi_notifier);
1165     }
1166 
1167     intel_opregion_resume(i915);
1168 }
1169 
1170 void intel_opregion_resume(struct drm_i915_private *i915)
1171 {
1172     struct intel_opregion *opregion = &i915->opregion;
1173 
1174     if (!opregion->header)
1175         return;
1176 
1177     if (opregion->acpi) {
1178         intel_didl_outputs(i915);
1179         intel_setup_cadls(i915);
1180 
1181         /*
1182          * Notify BIOS we are ready to handle ACPI video ext notifs.
1183          * Right now, all the events are handled by the ACPI video
1184          * module. We don't actually need to do anything with them.
1185          */
1186         opregion->acpi->csts = 0;
1187         opregion->acpi->drdy = 1;
1188     }
1189 
1190     if (opregion->asle) {
1191         opregion->asle->tche = ASLE_TCHE_BLC_EN;
1192         opregion->asle->ardy = ASLE_ARDY_READY;
1193     }
1194 
1195     /* Some platforms abuse the _DSM to enable MUX */
1196     intel_dsm_get_bios_data_funcs_supported(i915);
1197 
1198     intel_opregion_notify_adapter(i915, PCI_D0);
1199 }
1200 
1201 void intel_opregion_suspend(struct drm_i915_private *i915, pci_power_t state)
1202 {
1203     struct intel_opregion *opregion = &i915->opregion;
1204 
1205     if (!opregion->header)
1206         return;
1207 
1208     intel_opregion_notify_adapter(i915, state);
1209 
1210     if (opregion->asle)
1211         opregion->asle->ardy = ASLE_ARDY_NOT_READY;
1212 
1213     cancel_work_sync(&i915->opregion.asle_work);
1214 
1215     if (opregion->acpi)
1216         opregion->acpi->drdy = 0;
1217 }
1218 
1219 void intel_opregion_unregister(struct drm_i915_private *i915)
1220 {
1221     struct intel_opregion *opregion = &i915->opregion;
1222 
1223     intel_opregion_suspend(i915, PCI_D1);
1224 
1225     if (!opregion->header)
1226         return;
1227 
1228     if (opregion->acpi_notifier.notifier_call) {
1229         unregister_acpi_notifier(&opregion->acpi_notifier);
1230         opregion->acpi_notifier.notifier_call = NULL;
1231     }
1232 
1233     /* just clear all opregion memory pointers now */
1234     memunmap(opregion->header);
1235     if (opregion->rvda) {
1236         memunmap(opregion->rvda);
1237         opregion->rvda = NULL;
1238     }
1239     if (opregion->vbt_firmware) {
1240         kfree(opregion->vbt_firmware);
1241         opregion->vbt_firmware = NULL;
1242     }
1243     opregion->header = NULL;
1244     opregion->acpi = NULL;
1245     opregion->swsci = NULL;
1246     opregion->asle = NULL;
1247     opregion->asle_ext = NULL;
1248     opregion->vbt = NULL;
1249     opregion->lid_state = NULL;
1250 }