Subversion Repositories Kolibri OS

Rev

Rev 5354 | Rev 6103 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  29.  
  30. #include <linux/acpi.h>
  31. #include <acpi/video.h>
  32.  
  33. #include <drm/drmP.h>
  34. #include <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. static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
  242. {
  243.         struct drm_i915_private *dev_priv = dev->dev_private;
  244.         struct opregion_swsci *swsci = dev_priv->opregion.swsci;
  245.         u32 main_function, sub_function, scic;
  246.         u16 pci_swsci;
  247.         u32 dslp;
  248.  
  249.         if (!swsci)
  250.                 return -ENODEV;
  251.  
  252.         main_function = (function & SWSCI_SCIC_MAIN_FUNCTION_MASK) >>
  253.                 SWSCI_SCIC_MAIN_FUNCTION_SHIFT;
  254.         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.         if (main_function == SWSCI_SBCB) {
  259.                 if ((dev_priv->opregion.swsci_sbcb_sub_functions &
  260.                      (1 << sub_function)) == 0)
  261.                         return -EINVAL;
  262.         } else if (main_function == SWSCI_GBDA) {
  263.                 if ((dev_priv->opregion.swsci_gbda_sub_functions &
  264.                      (1 << sub_function)) == 0)
  265.                         return -EINVAL;
  266.         }
  267.  
  268.         /* Driver sleep timeout in ms. */
  269.         dslp = swsci->dslp;
  270.         if (!dslp) {
  271.                 /* The spec says 2ms should be the default, but it's too small
  272.                  * for some machines. */
  273.                 dslp = 50;
  274.         } 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.         }
  280.  
  281.         /* The spec tells us to do this, but we are the only user... */
  282.         scic = swsci->scic;
  283.         if (scic & SWSCI_SCIC_INDICATOR) {
  284.                 DRM_DEBUG_DRIVER("SWSCI request already in progress\n");
  285.                 return -EBUSY;
  286.         }
  287.  
  288.         scic = function | SWSCI_SCIC_INDICATOR;
  289.  
  290.         swsci->parm = parm;
  291.         swsci->scic = scic;
  292.  
  293.         /* Ensure SCI event is selected and event trigger is cleared. */
  294.         pci_read_config_word(dev->pdev, PCI_SWSCI, &pci_swsci);
  295.         if (!(pci_swsci & PCI_SWSCI_SCISEL) || (pci_swsci & PCI_SWSCI_GSSCIE)) {
  296.                 pci_swsci |= PCI_SWSCI_SCISEL;
  297.                 pci_swsci &= ~PCI_SWSCI_GSSCIE;
  298.                 pci_write_config_word(dev->pdev, PCI_SWSCI, pci_swsci);
  299.         }
  300.  
  301.         /* Use event trigger to tell bios to check the mail. */
  302.         pci_swsci |= PCI_SWSCI_GSSCIE;
  303.         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.         if (wait_for(C, dslp)) {
  308.                 DRM_DEBUG_DRIVER("SWSCI request timed out\n");
  309.                 return -ETIMEDOUT;
  310.         }
  311.  
  312.         scic = (scic & SWSCI_SCIC_EXIT_STATUS_MASK) >>
  313.                 SWSCI_SCIC_EXIT_STATUS_SHIFT;
  314.  
  315.         /* Note: scic == 0 is an error! */
  316.         if (scic != SWSCI_SCIC_EXIT_STATUS_SUCCESS) {
  317.                 DRM_DEBUG_DRIVER("SWSCI request error %u\n", scic);
  318.                 return -EIO;
  319.         }
  320.  
  321.         if (parm_out)
  322.                 *parm_out = swsci->parm;
  323.  
  324.         return 0;
  325.  
  326. #undef C
  327. }
  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. int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
  335.                                   bool enable)
  336. {
  337.         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.         if (!HAS_DDI(dev))
  344.                 return 0;
  345.  
  346.         if (intel_encoder->type == INTEL_OUTPUT_DSI)
  347.                 port = 0;
  348.         else
  349.                 port = intel_ddi_get_encoder_port(intel_encoder);
  350.  
  351.         if (port == PORT_E)  {
  352.                 port = 0;
  353.         } else {
  354.                 parm |= 1 << port;
  355.                 port++;
  356.         }
  357.  
  358.         if (!enable)
  359.                 parm |= 4 << 8;
  360.  
  361.         switch (intel_encoder->type) {
  362.         case INTEL_OUTPUT_ANALOG:
  363.                 type = DISPLAY_TYPE_CRT;
  364.                 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.                 break;
  371.         case INTEL_OUTPUT_EDP:
  372.         case INTEL_OUTPUT_DSI:
  373.                 type = DISPLAY_TYPE_INTERNAL_FLAT_PANEL;
  374.                 break;
  375.         default:
  376.                 WARN_ONCE(1, "unsupported intel_encoder type %d\n",
  377.                           intel_encoder->type);
  378.                 return -EINVAL;
  379.         }
  380.  
  381.         parm |= type << (16 + port * 3);
  382.  
  383.         return swsci(dev, SWSCI_SBCB_DISPLAY_POWER_STATE, parm, NULL);
  384. }
  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. int intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state)
  398. {
  399.         int i;
  400.  
  401.         if (!HAS_DDI(dev))
  402.                 return 0;
  403.  
  404.         for (i = 0; i < ARRAY_SIZE(power_state_map); i++) {
  405.                 if (state == power_state_map[i].pci_power_state)
  406.                         return swsci(dev, SWSCI_SBCB_ADAPTER_POWER_STATE,
  407.                                      power_state_map[i].parm, NULL);
  408.         }
  409.  
  410.         return -EINVAL;
  411. }
  412.  
  413. static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
  414. {
  415.         struct drm_i915_private *dev_priv = dev->dev_private;
  416.         struct intel_connector *intel_connector;
  417.         struct opregion_asle *asle = dev_priv->opregion.asle;
  418.  
  419.         DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp);
  420.  
  421.         if (acpi_video_get_backlight_type() == acpi_backlight_native) {
  422.                 DRM_DEBUG_KMS("opregion backlight request ignored\n");
  423.                 return 0;
  424.         }
  425.  
  426.         if (!(bclp & ASLE_BCLP_VALID))
  427.                 return ASLC_BACKLIGHT_FAILED;
  428.  
  429.         bclp &= ASLE_BCLP_MSK;
  430.         if (bclp > 255)
  431.                 return ASLC_BACKLIGHT_FAILED;
  432.  
  433.         drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
  434.  
  435.         /*
  436.          * Update backlight on all connectors that support backlight (usually
  437.          * only one).
  438.          */
  439.         DRM_DEBUG_KMS("updating opregion backlight %d/255\n", bclp);
  440.         list_for_each_entry(intel_connector, &dev->mode_config.connector_list, base.head)
  441.                 intel_panel_set_backlight_acpi(intel_connector, bclp, 255);
  442.         asle->cblv = DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID;
  443.  
  444.         drm_modeset_unlock(&dev->mode_config.connection_mutex);
  445.  
  446.  
  447.         return 0;
  448. }
  449.  
  450. static u32 asle_set_als_illum(struct drm_device *dev, u32 alsi)
  451. {
  452.         /* alsi is the current ALS reading in lux. 0 indicates below sensor
  453.            range, 0xffff indicates above sensor range. 1-0xfffe are valid */
  454.         DRM_DEBUG_DRIVER("Illum is not supported\n");
  455.         return ASLC_ALS_ILLUM_FAILED;
  456. }
  457.  
  458. static u32 asle_set_pwm_freq(struct drm_device *dev, u32 pfmb)
  459. {
  460.         DRM_DEBUG_DRIVER("PWM freq is not supported\n");
  461.         return ASLC_PWM_FREQ_FAILED;
  462. }
  463.  
  464. static u32 asle_set_pfit(struct drm_device *dev, u32 pfit)
  465. {
  466.         /* Panel fitting is currently controlled by the X code, so this is a
  467.            noop until modesetting support works fully */
  468.         DRM_DEBUG_DRIVER("Pfit is not supported\n");
  469.         return ASLC_PFIT_FAILED;
  470. }
  471.  
  472. static u32 asle_set_supported_rotation_angles(struct drm_device *dev, u32 srot)
  473. {
  474.         DRM_DEBUG_DRIVER("SROT is not supported\n");
  475.         return ASLC_ROTATION_ANGLES_FAILED;
  476. }
  477.  
  478. static u32 asle_set_button_array(struct drm_device *dev, u32 iuer)
  479. {
  480.         if (!iuer)
  481.                 DRM_DEBUG_DRIVER("Button array event is not supported (nothing)\n");
  482.         if (iuer & ASLE_IUER_ROTATION_LOCK_BTN)
  483.                 DRM_DEBUG_DRIVER("Button array event is not supported (rotation lock)\n");
  484.         if (iuer & ASLE_IUER_VOLUME_DOWN_BTN)
  485.                 DRM_DEBUG_DRIVER("Button array event is not supported (volume down)\n");
  486.         if (iuer & ASLE_IUER_VOLUME_UP_BTN)
  487.                 DRM_DEBUG_DRIVER("Button array event is not supported (volume up)\n");
  488.         if (iuer & ASLE_IUER_WINDOWS_BTN)
  489.                 DRM_DEBUG_DRIVER("Button array event is not supported (windows)\n");
  490.         if (iuer & ASLE_IUER_POWER_BTN)
  491.                 DRM_DEBUG_DRIVER("Button array event is not supported (power)\n");
  492.  
  493.         return ASLC_BUTTON_ARRAY_FAILED;
  494. }
  495.  
  496. static u32 asle_set_convertible(struct drm_device *dev, u32 iuer)
  497. {
  498.         if (iuer & ASLE_IUER_CONVERTIBLE)
  499.                 DRM_DEBUG_DRIVER("Convertible is not supported (clamshell)\n");
  500.         else
  501.                 DRM_DEBUG_DRIVER("Convertible is not supported (slate)\n");
  502.  
  503.         return ASLC_CONVERTIBLE_FAILED;
  504. }
  505.  
  506. static u32 asle_set_docking(struct drm_device *dev, u32 iuer)
  507. {
  508.         if (iuer & ASLE_IUER_DOCKING)
  509.                 DRM_DEBUG_DRIVER("Docking is not supported (docked)\n");
  510.         else
  511.                 DRM_DEBUG_DRIVER("Docking is not supported (undocked)\n");
  512.  
  513.         return ASLC_DOCKING_FAILED;
  514. }
  515.  
  516. static u32 asle_isct_state(struct drm_device *dev)
  517. {
  518.         DRM_DEBUG_DRIVER("ISCT is not supported\n");
  519.         return ASLC_ISCT_STATE_FAILED;
  520. }
  521.  
  522. static void asle_work(struct work_struct *work)
  523. {
  524.         struct intel_opregion *opregion =
  525.                 container_of(work, struct intel_opregion, asle_work);
  526.         struct drm_i915_private *dev_priv =
  527.                 container_of(opregion, struct drm_i915_private, opregion);
  528.         struct drm_device *dev = dev_priv->dev;
  529.         struct opregion_asle *asle = dev_priv->opregion.asle;
  530.         u32 aslc_stat = 0;
  531.         u32 aslc_req;
  532.  
  533.         if (!asle)
  534.                 return;
  535.  
  536.         aslc_req = asle->aslc;
  537.  
  538.         if (!(aslc_req & ASLC_REQ_MSK)) {
  539.                 DRM_DEBUG_DRIVER("No request on ASLC interrupt 0x%08x\n",
  540.                                  aslc_req);
  541.                 return;
  542.         }
  543.  
  544.         if (aslc_req & ASLC_SET_ALS_ILLUM)
  545.                 aslc_stat |= asle_set_als_illum(dev, asle->alsi);
  546.  
  547.         if (aslc_req & ASLC_SET_BACKLIGHT)
  548.                 aslc_stat |= asle_set_backlight(dev, asle->bclp);
  549.  
  550.         if (aslc_req & ASLC_SET_PFIT)
  551.                 aslc_stat |= asle_set_pfit(dev, asle->pfit);
  552.  
  553.         if (aslc_req & ASLC_SET_PWM_FREQ)
  554.                 aslc_stat |= asle_set_pwm_freq(dev, asle->pfmb);
  555.  
  556.         if (aslc_req & ASLC_SUPPORTED_ROTATION_ANGLES)
  557.                 aslc_stat |= asle_set_supported_rotation_angles(dev,
  558.                                                         asle->srot);
  559.  
  560.         if (aslc_req & ASLC_BUTTON_ARRAY)
  561.                 aslc_stat |= asle_set_button_array(dev, asle->iuer);
  562.  
  563.         if (aslc_req & ASLC_CONVERTIBLE_INDICATOR)
  564.                 aslc_stat |= asle_set_convertible(dev, asle->iuer);
  565.  
  566.         if (aslc_req & ASLC_DOCKING_INDICATOR)
  567.                 aslc_stat |= asle_set_docking(dev, asle->iuer);
  568.  
  569.         if (aslc_req & ASLC_ISCT_STATE_CHANGE)
  570.                 aslc_stat |= asle_isct_state(dev);
  571.  
  572.         asle->aslc = aslc_stat;
  573. }
  574.  
  575. void intel_opregion_asle_intr(struct drm_device *dev)
  576. {
  577.         struct drm_i915_private *dev_priv = dev->dev_private;
  578.  
  579.         if (dev_priv->opregion.asle)
  580.                 schedule_work(&dev_priv->opregion.asle_work);
  581. }
  582.  
  583. #define ACPI_EV_DISPLAY_SWITCH (1<<0)
  584. #define ACPI_EV_LID            (1<<1)
  585. #define ACPI_EV_DOCK           (1<<2)
  586.  
  587. static struct intel_opregion *system_opregion;
  588.  
  589. static int intel_opregion_video_event(struct notifier_block *nb,
  590.                                       unsigned long val, void *data)
  591. {
  592.         /* The only video events relevant to opregion are 0x80. These indicate
  593.            either a docking event, lid switch or display switch request. In
  594.            Linux, these are handled by the dock, button and video drivers.
  595.         */
  596.  
  597.         struct acpi_bus_event *event = data;
  598.         struct opregion_acpi *acpi;
  599.         int ret = NOTIFY_OK;
  600.  
  601.         if (strcmp(event->device_class, ACPI_VIDEO_CLASS) != 0)
  602.                 return NOTIFY_DONE;
  603.  
  604.         if (!system_opregion)
  605.                 return NOTIFY_DONE;
  606.  
  607.         acpi = system_opregion->acpi;
  608.  
  609.         if (event->type == 0x80 && ((acpi->cevt & 1) == 0))
  610.                 ret = NOTIFY_BAD;
  611.  
  612.         acpi->csts = 0;
  613.  
  614.         return ret;
  615. }
  616.  
  617. static struct notifier_block intel_opregion_notifier = {
  618.         .notifier_call = intel_opregion_video_event,
  619. };
  620.  
  621. /*
  622.  * Initialise the DIDL field in opregion. This passes a list of devices to
  623.  * the firmware. Values are defined by section B.4.2 of the ACPI specification
  624.  * (version 3)
  625.  */
  626.  
  627. static u32 get_did(struct intel_opregion *opregion, int i)
  628. {
  629.         u32 did;
  630.  
  631.         if (i < ARRAY_SIZE(opregion->acpi->didl)) {
  632.                 did = opregion->acpi->didl[i];
  633.         } else {
  634.                 i -= ARRAY_SIZE(opregion->acpi->didl);
  635.  
  636.                 if (WARN_ON(i >= ARRAY_SIZE(opregion->acpi->did2)))
  637.                         return 0;
  638.  
  639.                 did = opregion->acpi->did2[i];
  640.         }
  641.  
  642.         return did;
  643. }
  644.  
  645. static void set_did(struct intel_opregion *opregion, int i, u32 val)
  646. {
  647.         if (i < ARRAY_SIZE(opregion->acpi->didl)) {
  648.                 opregion->acpi->didl[i] = val;
  649.         } else {
  650.                 i -= ARRAY_SIZE(opregion->acpi->didl);
  651.  
  652.                 if (WARN_ON(i >= ARRAY_SIZE(opregion->acpi->did2)))
  653.                         return;
  654.  
  655.                 opregion->acpi->did2[i] = val;
  656.         }
  657. }
  658.  
  659. static void intel_didl_outputs(struct drm_device *dev)
  660. {
  661.         struct drm_i915_private *dev_priv = dev->dev_private;
  662.         struct intel_opregion *opregion = &dev_priv->opregion;
  663.         struct drm_connector *connector;
  664.         acpi_handle handle;
  665.         struct acpi_device *acpi_dev, *acpi_cdev, *acpi_video_bus = NULL;
  666.         unsigned long long device_id;
  667.         acpi_status status;
  668.         u32 temp, max_outputs;
  669.         int i = 0;
  670.  
  671.         handle = ACPI_HANDLE(&dev->pdev->dev);
  672.         if (!handle || acpi_bus_get_device(handle, &acpi_dev))
  673.                 return;
  674.  
  675.         if (acpi_is_video_device(handle))
  676.                 acpi_video_bus = acpi_dev;
  677.         else {
  678.                 list_for_each_entry(acpi_cdev, &acpi_dev->children, node) {
  679.                         if (acpi_is_video_device(acpi_cdev->handle)) {
  680.                                 acpi_video_bus = acpi_cdev;
  681.                                 break;
  682.                         }
  683.                 }
  684.         }
  685.  
  686.         if (!acpi_video_bus) {
  687.                 DRM_ERROR("No ACPI video bus found\n");
  688.                 return;
  689.         }
  690.  
  691.         /*
  692.          * In theory, did2, the extended didl, gets added at opregion version
  693.          * 3.0. In practice, however, we're supposed to set it for earlier
  694.          * versions as well, since a BIOS that doesn't understand did2 should
  695.          * not look at it anyway. Use a variable so we can tweak this if a need
  696.          * arises later.
  697.          */
  698.         max_outputs = ARRAY_SIZE(opregion->acpi->didl) +
  699.                 ARRAY_SIZE(opregion->acpi->did2);
  700.  
  701.         list_for_each_entry(acpi_cdev, &acpi_video_bus->children, node) {
  702.                 if (i >= max_outputs) {
  703.                         DRM_DEBUG_KMS("More than %u outputs detected via ACPI\n",
  704.                                       max_outputs);
  705.                         return;
  706.                 }
  707.                 status = acpi_evaluate_integer(acpi_cdev->handle, "_ADR",
  708.                                                NULL, &device_id);
  709.                 if (ACPI_SUCCESS(status)) {
  710.                         if (!device_id)
  711.                                 goto blind_set;
  712.                         set_did(opregion, i++, (u32)(device_id & 0x0f0f));
  713.                 }
  714.         }
  715.  
  716. end:
  717.         DRM_DEBUG_KMS("%d outputs detected\n", i);
  718.  
  719.         /* If fewer than max outputs, the list must be null terminated */
  720.         if (i < max_outputs)
  721.                 set_did(opregion, i, 0);
  722.         return;
  723.  
  724. blind_set:
  725.         i = 0;
  726.         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
  727.                 int output_type = ACPI_OTHER_OUTPUT;
  728.                 if (i >= max_outputs) {
  729.                         DRM_DEBUG_KMS("More than %u outputs in connector list\n",
  730.                                       max_outputs);
  731.                         return;
  732.                 }
  733.                 switch (connector->connector_type) {
  734.                 case DRM_MODE_CONNECTOR_VGA:
  735.                 case DRM_MODE_CONNECTOR_DVIA:
  736.                         output_type = ACPI_VGA_OUTPUT;
  737.                         break;
  738.                 case DRM_MODE_CONNECTOR_Composite:
  739.                 case DRM_MODE_CONNECTOR_SVIDEO:
  740.                 case DRM_MODE_CONNECTOR_Component:
  741.                 case DRM_MODE_CONNECTOR_9PinDIN:
  742.                         output_type = ACPI_TV_OUTPUT;
  743.                         break;
  744.                 case DRM_MODE_CONNECTOR_DVII:
  745.                 case DRM_MODE_CONNECTOR_DVID:
  746.                 case DRM_MODE_CONNECTOR_DisplayPort:
  747.                 case DRM_MODE_CONNECTOR_HDMIA:
  748.                 case DRM_MODE_CONNECTOR_HDMIB:
  749.                         output_type = ACPI_DIGITAL_OUTPUT;
  750.                         break;
  751.                 case DRM_MODE_CONNECTOR_LVDS:
  752.                         output_type = ACPI_LVDS_OUTPUT;
  753.                         break;
  754.                 }
  755.                 temp = get_did(opregion, i);
  756.                 set_did(opregion, i, temp | (1 << 31) | output_type | i);
  757.                 i++;
  758.         }
  759.         goto end;
  760. }
  761.  
  762. static void intel_setup_cadls(struct drm_device *dev)
  763. {
  764.         struct drm_i915_private *dev_priv = dev->dev_private;
  765.         struct intel_opregion *opregion = &dev_priv->opregion;
  766.         int i = 0;
  767.         u32 disp_id;
  768.  
  769.         /* Initialize the CADL field by duplicating the DIDL values.
  770.          * Technically, this is not always correct as display outputs may exist,
  771.          * but not active. This initialization is necessary for some Clevo
  772.          * laptops that check this field before processing the brightness and
  773.          * display switching hotkeys. Just like DIDL, CADL is NULL-terminated if
  774.          * there are less than eight devices. */
  775.         do {
  776.                 disp_id = get_did(opregion, i);
  777.                 opregion->acpi->cadl[i] = disp_id;
  778.         } while (++i < 8 && disp_id != 0);
  779. }
  780.  
  781. void intel_opregion_init(struct drm_device *dev)
  782. {
  783.         struct drm_i915_private *dev_priv = dev->dev_private;
  784.         struct intel_opregion *opregion = &dev_priv->opregion;
  785.  
  786.         if (!opregion->header)
  787.                 return;
  788.  
  789.         if (opregion->acpi) {
  790.                 intel_didl_outputs(dev);
  791.                 intel_setup_cadls(dev);
  792.  
  793.                 /* Notify BIOS we are ready to handle ACPI video ext notifs.
  794.                  * Right now, all the events are handled by the ACPI video module.
  795.                  * We don't actually need to do anything with them. */
  796.                 opregion->acpi->csts = 0;
  797.                 opregion->acpi->drdy = 1;
  798.  
  799.                 system_opregion = opregion;
  800.                 register_acpi_notifier(&intel_opregion_notifier);
  801.         }
  802.  
  803.         if (opregion->asle) {
  804.                 opregion->asle->tche = ASLE_TCHE_BLC_EN;
  805.                 opregion->asle->ardy = ASLE_ARDY_READY;
  806.         }
  807. }
  808.  
  809. void intel_opregion_fini(struct drm_device *dev)
  810. {
  811.         struct drm_i915_private *dev_priv = dev->dev_private;
  812.         struct intel_opregion *opregion = &dev_priv->opregion;
  813.  
  814.         if (!opregion->header)
  815.                 return;
  816.  
  817.         if (opregion->asle)
  818.                 opregion->asle->ardy = ASLE_ARDY_NOT_READY;
  819.  
  820.         cancel_work_sync(&dev_priv->opregion.asle_work);
  821.  
  822.         if (opregion->acpi) {
  823.                 opregion->acpi->drdy = 0;
  824.  
  825.                 system_opregion = NULL;
  826.                 unregister_acpi_notifier(&intel_opregion_notifier);
  827.         }
  828.  
  829.         /* just clear all opregion memory pointers now */
  830.         memunmap(opregion->header);
  831.         opregion->header = NULL;
  832.         opregion->acpi = NULL;
  833.         opregion->swsci = NULL;
  834.         opregion->asle = NULL;
  835.         opregion->vbt = NULL;
  836.         opregion->lid_state = NULL;
  837. }
  838.  
  839. static void swsci_setup(struct drm_device *dev)
  840. {
  841.         struct drm_i915_private *dev_priv = dev->dev_private;
  842.         struct intel_opregion *opregion = &dev_priv->opregion;
  843.         bool requested_callbacks = false;
  844.         u32 tmp;
  845.  
  846.         /* Sub-function code 0 is okay, let's allow them. */
  847.         opregion->swsci_gbda_sub_functions = 1;
  848.         opregion->swsci_sbcb_sub_functions = 1;
  849.  
  850.         /* We use GBDA to ask for supported GBDA calls. */
  851.         if (swsci(dev, SWSCI_GBDA_SUPPORTED_CALLS, 0, &tmp) == 0) {
  852.                 /* make the bits match the sub-function codes */
  853.                 tmp <<= 1;
  854.                 opregion->swsci_gbda_sub_functions |= tmp;
  855.         }
  856.  
  857.         /*
  858.          * We also use GBDA to ask for _requested_ SBCB callbacks. The driver
  859.          * must not call interfaces that are not specifically requested by the
  860.          * bios.
  861.          */
  862.         if (swsci(dev, SWSCI_GBDA_REQUESTED_CALLBACKS, 0, &tmp) == 0) {
  863.                 /* here, the bits already match sub-function codes */
  864.                 opregion->swsci_sbcb_sub_functions |= tmp;
  865.                 requested_callbacks = true;
  866.         }
  867.  
  868.         /*
  869.          * But we use SBCB to ask for _supported_ SBCB calls. This does not mean
  870.          * the callback is _requested_. But we still can't call interfaces that
  871.          * are not requested.
  872.          */
  873.         if (swsci(dev, SWSCI_SBCB_SUPPORTED_CALLBACKS, 0, &tmp) == 0) {
  874.                 /* make the bits match the sub-function codes */
  875.                 u32 low = tmp & 0x7ff;
  876.                 u32 high = tmp & ~0xfff; /* bit 11 is reserved */
  877.                 tmp = (high << 4) | (low << 1) | 1;
  878.  
  879.                 /* best guess what to do with supported wrt requested */
  880.                 if (requested_callbacks) {
  881.                         u32 req = opregion->swsci_sbcb_sub_functions;
  882.                         if ((req & tmp) != req)
  883.                                 DRM_DEBUG_DRIVER("SWSCI BIOS requested (%08x) SBCB callbacks that are not supported (%08x)\n", req, tmp);
  884.                         /* XXX: for now, trust the requested callbacks */
  885.                         /* opregion->swsci_sbcb_sub_functions &= tmp; */
  886.                 } else {
  887.                         opregion->swsci_sbcb_sub_functions |= tmp;
  888.                 }
  889.         }
  890.  
  891.         DRM_DEBUG_DRIVER("SWSCI GBDA callbacks %08x, SBCB callbacks %08x\n",
  892.                          opregion->swsci_gbda_sub_functions,
  893.                          opregion->swsci_sbcb_sub_functions);
  894. }
  895. #else /* CONFIG_ACPI */
  896. static inline void swsci_setup(struct drm_device *dev) {}
  897. #endif  /* CONFIG_ACPI */
  898.  
  899. int intel_opregion_setup(struct drm_device *dev)
  900. {
  901.         struct drm_i915_private *dev_priv = dev->dev_private;
  902.         struct intel_opregion *opregion = &dev_priv->opregion;
  903.         u32 asls, mboxes;
  904.         char buf[sizeof(OPREGION_SIGNATURE)];
  905.         int err = 0;
  906.         void *base;
  907.  
  908.         BUILD_BUG_ON(sizeof(struct opregion_header) != 0x100);
  909.         BUILD_BUG_ON(sizeof(struct opregion_acpi) != 0x100);
  910.         BUILD_BUG_ON(sizeof(struct opregion_swsci) != 0x100);
  911.         BUILD_BUG_ON(sizeof(struct opregion_asle) != 0x100);
  912.  
  913.         pci_read_config_dword(dev->pdev, PCI_ASLS, &asls);
  914.         DRM_DEBUG_DRIVER("graphic opregion physical addr: 0x%x\n", asls);
  915.         if (asls == 0) {
  916.                 DRM_DEBUG_DRIVER("ACPI OpRegion not supported!\n");
  917.                 return -ENOTSUPP;
  918.         }
  919.  
  920. #ifdef CONFIG_ACPI
  921.         INIT_WORK(&opregion->asle_work, asle_work);
  922. #endif
  923.  
  924.         base = memremap(asls, OPREGION_SIZE, MEMREMAP_WB);
  925.         if (!base)
  926.                 return -ENOMEM;
  927.  
  928.         memcpy(buf, base, sizeof(buf));
  929.  
  930.         if (memcmp(buf, OPREGION_SIGNATURE, 16)) {
  931.                 DRM_DEBUG_DRIVER("opregion signature mismatch\n");
  932.                 err = -EINVAL;
  933.                 goto err_out;
  934.         }
  935.         opregion->header = base;
  936.         opregion->vbt = base + OPREGION_VBT_OFFSET;
  937.  
  938.         opregion->lid_state = base + ACPI_CLID;
  939.  
  940.         mboxes = opregion->header->mboxes;
  941.         if (mboxes & MBOX_ACPI) {
  942.                 DRM_DEBUG_DRIVER("Public ACPI methods supported\n");
  943.                 opregion->acpi = base + OPREGION_ACPI_OFFSET;
  944.         }
  945.  
  946.         if (mboxes & MBOX_SWSCI) {
  947.                 DRM_DEBUG_DRIVER("SWSCI supported\n");
  948.                 opregion->swsci = base + OPREGION_SWSCI_OFFSET;
  949.                 swsci_setup(dev);
  950.         }
  951.         if (mboxes & MBOX_ASLE) {
  952.                 DRM_DEBUG_DRIVER("ASLE supported\n");
  953.                 opregion->asle = base + OPREGION_ASLE_OFFSET;
  954.  
  955.                 opregion->asle->ardy = ASLE_ARDY_NOT_READY;
  956.         }
  957.  
  958.         return 0;
  959.  
  960. err_out:
  961.         memunmap(base);
  962.         return err;
  963. }
  964.