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