1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#include <linux/acpi.h>
29#include <linux/dmi.h>
30#include <acpi/video.h>
31
32#include <drm/drmP.h>
33#include <drm/i915_drm.h>
34#include "i915_drv.h"
35#include "intel_drv.h"
36
37#define OPREGION_HEADER_OFFSET 0
38#define OPREGION_ACPI_OFFSET 0x100
39#define ACPI_CLID 0x01ac
40#define ACPI_CDCK 0x01b0
41#define OPREGION_SWSCI_OFFSET 0x200
42#define OPREGION_ASLE_OFFSET 0x300
43#define OPREGION_VBT_OFFSET 0x400
44#define OPREGION_ASLE_EXT_OFFSET 0x1C00
45
46#define OPREGION_SIGNATURE "IntelGraphicsMem"
47#define MBOX_ACPI (1<<0)
48#define MBOX_SWSCI (1<<1)
49#define MBOX_ASLE (1<<2)
50#define MBOX_ASLE_EXT (1<<4)
51
52struct opregion_header {
53 u8 signature[16];
54 u32 size;
55 u32 opregion_ver;
56 u8 bios_ver[32];
57 u8 vbios_ver[16];
58 u8 driver_ver[16];
59 u32 mboxes;
60 u32 driver_model;
61 u32 pcon;
62 u8 dver[32];
63 u8 rsvd[124];
64} __packed;
65
66
67struct opregion_acpi {
68 u32 drdy;
69 u32 csts;
70 u32 cevt;
71 u8 rsvd1[20];
72 u32 didl[8];
73 u32 cpdl[8];
74 u32 cadl[8];
75 u32 nadl[8];
76 u32 aslp;
77 u32 tidx;
78 u32 chpd;
79 u32 clid;
80 u32 cdck;
81 u32 sxsw;
82 u32 evts;
83 u32 cnot;
84 u32 nrdy;
85 u32 did2[7];
86 u32 cpd2[7];
87 u8 rsvd2[4];
88} __packed;
89
90
91struct opregion_swsci {
92 u32 scic;
93 u32 parm;
94 u32 dslp;
95 u8 rsvd[244];
96} __packed;
97
98
99struct opregion_asle {
100 u32 ardy;
101 u32 aslc;
102 u32 tche;
103 u32 alsi;
104 u32 bclp;
105 u32 pfit;
106 u32 cblv;
107 u16 bclm[20];
108 u32 cpfm;
109 u32 epfm;
110 u8 plut[74];
111 u32 pfmb;
112 u32 cddv;
113 u32 pcft;
114 u32 srot;
115 u32 iuer;
116 u64 fdss;
117 u32 fdsp;
118 u32 stat;
119 u64 rvda;
120 u32 rvds;
121 u8 rsvd[58];
122} __packed;
123
124
125struct opregion_asle_ext {
126 u32 phed;
127 u8 bddc[256];
128 u8 rsvd[764];
129} __packed;
130
131
132#define ASLE_ARDY_READY (1 << 0)
133#define ASLE_ARDY_NOT_READY (0 << 0)
134
135
136#define ASLC_SET_ALS_ILLUM (1 << 0)
137#define ASLC_SET_BACKLIGHT (1 << 1)
138#define ASLC_SET_PFIT (1 << 2)
139#define ASLC_SET_PWM_FREQ (1 << 3)
140#define ASLC_SUPPORTED_ROTATION_ANGLES (1 << 4)
141#define ASLC_BUTTON_ARRAY (1 << 5)
142#define ASLC_CONVERTIBLE_INDICATOR (1 << 6)
143#define ASLC_DOCKING_INDICATOR (1 << 7)
144#define ASLC_ISCT_STATE_CHANGE (1 << 8)
145#define ASLC_REQ_MSK 0x1ff
146
147#define ASLC_ALS_ILLUM_FAILED (1 << 10)
148#define ASLC_BACKLIGHT_FAILED (1 << 12)
149#define ASLC_PFIT_FAILED (1 << 14)
150#define ASLC_PWM_FREQ_FAILED (1 << 16)
151#define ASLC_ROTATION_ANGLES_FAILED (1 << 18)
152#define ASLC_BUTTON_ARRAY_FAILED (1 << 20)
153#define ASLC_CONVERTIBLE_FAILED (1 << 22)
154#define ASLC_DOCKING_FAILED (1 << 24)
155#define ASLC_ISCT_STATE_FAILED (1 << 26)
156
157
158#define ASLE_TCHE_ALS_EN (1 << 0)
159#define ASLE_TCHE_BLC_EN (1 << 1)
160#define ASLE_TCHE_PFIT_EN (1 << 2)
161#define ASLE_TCHE_PFMB_EN (1 << 3)
162
163
164#define ASLE_BCLP_VALID (1<<31)
165#define ASLE_BCLP_MSK (~(1<<31))
166
167
168#define ASLE_PFIT_VALID (1<<31)
169#define ASLE_PFIT_CENTER (1<<0)
170#define ASLE_PFIT_STRETCH_TEXT (1<<1)
171#define ASLE_PFIT_STRETCH_GFX (1<<2)
172
173
174#define ASLE_PFMB_BRIGHTNESS_MASK (0xff)
175#define ASLE_PFMB_BRIGHTNESS_VALID (1<<8)
176#define ASLE_PFMB_PWM_MASK (0x7ffffe00)
177#define ASLE_PFMB_PWM_VALID (1<<31)
178
179#define ASLE_CBLV_VALID (1<<31)
180
181
182#define ASLE_IUER_DOCKING (1 << 7)
183#define ASLE_IUER_CONVERTIBLE (1 << 6)
184#define ASLE_IUER_ROTATION_LOCK_BTN (1 << 4)
185#define ASLE_IUER_VOLUME_DOWN_BTN (1 << 3)
186#define ASLE_IUER_VOLUME_UP_BTN (1 << 2)
187#define ASLE_IUER_WINDOWS_BTN (1 << 1)
188#define ASLE_IUER_POWER_BTN (1 << 0)
189
190
191#define SWSCI_SCIC_INDICATOR (1 << 0)
192#define SWSCI_SCIC_MAIN_FUNCTION_SHIFT 1
193#define SWSCI_SCIC_MAIN_FUNCTION_MASK (0xf << 1)
194#define SWSCI_SCIC_SUB_FUNCTION_SHIFT 8
195#define SWSCI_SCIC_SUB_FUNCTION_MASK (0xff << 8)
196#define SWSCI_SCIC_EXIT_PARAMETER_SHIFT 8
197#define SWSCI_SCIC_EXIT_PARAMETER_MASK (0xff << 8)
198#define SWSCI_SCIC_EXIT_STATUS_SHIFT 5
199#define SWSCI_SCIC_EXIT_STATUS_MASK (7 << 5)
200#define SWSCI_SCIC_EXIT_STATUS_SUCCESS 1
201
202#define SWSCI_FUNCTION_CODE(main, sub) \
203 ((main) << SWSCI_SCIC_MAIN_FUNCTION_SHIFT | \
204 (sub) << SWSCI_SCIC_SUB_FUNCTION_SHIFT)
205
206
207#define SWSCI_GBDA 4
208#define SWSCI_GBDA_SUPPORTED_CALLS SWSCI_FUNCTION_CODE(SWSCI_GBDA, 0)
209#define SWSCI_GBDA_REQUESTED_CALLBACKS SWSCI_FUNCTION_CODE(SWSCI_GBDA, 1)
210#define SWSCI_GBDA_BOOT_DISPLAY_PREF SWSCI_FUNCTION_CODE(SWSCI_GBDA, 4)
211#define SWSCI_GBDA_PANEL_DETAILS SWSCI_FUNCTION_CODE(SWSCI_GBDA, 5)
212#define SWSCI_GBDA_TV_STANDARD SWSCI_FUNCTION_CODE(SWSCI_GBDA, 6)
213#define SWSCI_GBDA_INTERNAL_GRAPHICS SWSCI_FUNCTION_CODE(SWSCI_GBDA, 7)
214#define SWSCI_GBDA_SPREAD_SPECTRUM SWSCI_FUNCTION_CODE(SWSCI_GBDA, 10)
215
216
217#define SWSCI_SBCB 6
218#define SWSCI_SBCB_SUPPORTED_CALLBACKS SWSCI_FUNCTION_CODE(SWSCI_SBCB, 0)
219#define SWSCI_SBCB_INIT_COMPLETION SWSCI_FUNCTION_CODE(SWSCI_SBCB, 1)
220#define SWSCI_SBCB_PRE_HIRES_SET_MODE SWSCI_FUNCTION_CODE(SWSCI_SBCB, 3)
221#define SWSCI_SBCB_POST_HIRES_SET_MODE SWSCI_FUNCTION_CODE(SWSCI_SBCB, 4)
222#define SWSCI_SBCB_DISPLAY_SWITCH SWSCI_FUNCTION_CODE(SWSCI_SBCB, 5)
223#define SWSCI_SBCB_SET_TV_FORMAT SWSCI_FUNCTION_CODE(SWSCI_SBCB, 6)
224#define SWSCI_SBCB_ADAPTER_POWER_STATE SWSCI_FUNCTION_CODE(SWSCI_SBCB, 7)
225#define SWSCI_SBCB_DISPLAY_POWER_STATE SWSCI_FUNCTION_CODE(SWSCI_SBCB, 8)
226#define SWSCI_SBCB_SET_BOOT_DISPLAY SWSCI_FUNCTION_CODE(SWSCI_SBCB, 9)
227#define SWSCI_SBCB_SET_PANEL_DETAILS SWSCI_FUNCTION_CODE(SWSCI_SBCB, 10)
228#define SWSCI_SBCB_SET_INTERNAL_GFX SWSCI_FUNCTION_CODE(SWSCI_SBCB, 11)
229#define SWSCI_SBCB_POST_HIRES_TO_DOS_FS SWSCI_FUNCTION_CODE(SWSCI_SBCB, 16)
230#define SWSCI_SBCB_SUSPEND_RESUME SWSCI_FUNCTION_CODE(SWSCI_SBCB, 17)
231#define SWSCI_SBCB_SET_SPREAD_SPECTRUM SWSCI_FUNCTION_CODE(SWSCI_SBCB, 18)
232#define SWSCI_SBCB_POST_VBE_PM SWSCI_FUNCTION_CODE(SWSCI_SBCB, 19)
233#define SWSCI_SBCB_ENABLE_DISABLE_AUDIO SWSCI_FUNCTION_CODE(SWSCI_SBCB, 21)
234
235
236
237
238
239#define ACPI_DISPLAY_INDEX_SHIFT 0
240#define ACPI_DISPLAY_INDEX_MASK (0xf << 0)
241#define ACPI_DISPLAY_PORT_ATTACHMENT_SHIFT 4
242#define ACPI_DISPLAY_PORT_ATTACHMENT_MASK (0xf << 4)
243#define ACPI_DISPLAY_TYPE_SHIFT 8
244#define ACPI_DISPLAY_TYPE_MASK (0xf << 8)
245#define ACPI_DISPLAY_TYPE_OTHER (0 << 8)
246#define ACPI_DISPLAY_TYPE_VGA (1 << 8)
247#define ACPI_DISPLAY_TYPE_TV (2 << 8)
248#define ACPI_DISPLAY_TYPE_EXTERNAL_DIGITAL (3 << 8)
249#define ACPI_DISPLAY_TYPE_INTERNAL_DIGITAL (4 << 8)
250#define ACPI_VENDOR_SPECIFIC_SHIFT 12
251#define ACPI_VENDOR_SPECIFIC_MASK (0xf << 12)
252#define ACPI_BIOS_CAN_DETECT (1 << 16)
253#define ACPI_DEPENDS_ON_VGA (1 << 17)
254#define ACPI_PIPE_ID_SHIFT 18
255#define ACPI_PIPE_ID_MASK (7 << 18)
256#define ACPI_DEVICE_ID_SCHEME (1 << 31)
257
258#define MAX_DSLP 1500
259
260static int swsci(struct drm_i915_private *dev_priv,
261 u32 function, u32 parm, u32 *parm_out)
262{
263 struct opregion_swsci *swsci = dev_priv->opregion.swsci;
264 struct pci_dev *pdev = dev_priv->drm.pdev;
265 u32 main_function, sub_function, scic;
266 u16 swsci_val;
267 u32 dslp;
268
269 if (!swsci)
270 return -ENODEV;
271
272 main_function = (function & SWSCI_SCIC_MAIN_FUNCTION_MASK) >>
273 SWSCI_SCIC_MAIN_FUNCTION_SHIFT;
274 sub_function = (function & SWSCI_SCIC_SUB_FUNCTION_MASK) >>
275 SWSCI_SCIC_SUB_FUNCTION_SHIFT;
276
277
278 if (main_function == SWSCI_SBCB) {
279 if ((dev_priv->opregion.swsci_sbcb_sub_functions &
280 (1 << sub_function)) == 0)
281 return -EINVAL;
282 } else if (main_function == SWSCI_GBDA) {
283 if ((dev_priv->opregion.swsci_gbda_sub_functions &
284 (1 << sub_function)) == 0)
285 return -EINVAL;
286 }
287
288
289 dslp = swsci->dslp;
290 if (!dslp) {
291
292
293 dslp = 50;
294 } else if (dslp > MAX_DSLP) {
295
296 DRM_INFO_ONCE("ACPI BIOS requests an excessive sleep of %u ms, "
297 "using %u ms instead\n", dslp, MAX_DSLP);
298 dslp = MAX_DSLP;
299 }
300
301
302 scic = swsci->scic;
303 if (scic & SWSCI_SCIC_INDICATOR) {
304 DRM_DEBUG_DRIVER("SWSCI request already in progress\n");
305 return -EBUSY;
306 }
307
308 scic = function | SWSCI_SCIC_INDICATOR;
309
310 swsci->parm = parm;
311 swsci->scic = scic;
312
313
314 pci_read_config_word(pdev, SWSCI, &swsci_val);
315 if (!(swsci_val & SWSCI_SCISEL) || (swsci_val & SWSCI_GSSCIE)) {
316 swsci_val |= SWSCI_SCISEL;
317 swsci_val &= ~SWSCI_GSSCIE;
318 pci_write_config_word(pdev, SWSCI, swsci_val);
319 }
320
321
322 swsci_val |= SWSCI_GSSCIE;
323 pci_write_config_word(pdev, SWSCI, swsci_val);
324
325
326#define C (((scic = swsci->scic) & SWSCI_SCIC_INDICATOR) == 0)
327 if (wait_for(C, dslp)) {
328 DRM_DEBUG_DRIVER("SWSCI request timed out\n");
329 return -ETIMEDOUT;
330 }
331
332 scic = (scic & SWSCI_SCIC_EXIT_STATUS_MASK) >>
333 SWSCI_SCIC_EXIT_STATUS_SHIFT;
334
335
336 if (scic != SWSCI_SCIC_EXIT_STATUS_SUCCESS) {
337 DRM_DEBUG_DRIVER("SWSCI request error %u\n", scic);
338 return -EIO;
339 }
340
341 if (parm_out)
342 *parm_out = swsci->parm;
343
344 return 0;
345
346#undef C
347}
348
349#define DISPLAY_TYPE_CRT 0
350#define DISPLAY_TYPE_TV 1
351#define DISPLAY_TYPE_EXTERNAL_FLAT_PANEL 2
352#define DISPLAY_TYPE_INTERNAL_FLAT_PANEL 3
353
354int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
355 bool enable)
356{
357 struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
358 u32 parm = 0;
359 u32 type = 0;
360 u32 port;
361
362
363 if (!HAS_DDI(dev_priv))
364 return 0;
365
366 if (intel_encoder->type == INTEL_OUTPUT_DSI)
367 port = 0;
368 else
369 port = intel_ddi_get_encoder_port(intel_encoder);
370
371 if (port == PORT_E) {
372 port = 0;
373 } else {
374 parm |= 1 << port;
375 port++;
376 }
377
378 if (!enable)
379 parm |= 4 << 8;
380
381 switch (intel_encoder->type) {
382 case INTEL_OUTPUT_ANALOG:
383 type = DISPLAY_TYPE_CRT;
384 break;
385 case INTEL_OUTPUT_UNKNOWN:
386 case INTEL_OUTPUT_DP:
387 case INTEL_OUTPUT_HDMI:
388 case INTEL_OUTPUT_DP_MST:
389 type = DISPLAY_TYPE_EXTERNAL_FLAT_PANEL;
390 break;
391 case INTEL_OUTPUT_EDP:
392 case INTEL_OUTPUT_DSI:
393 type = DISPLAY_TYPE_INTERNAL_FLAT_PANEL;
394 break;
395 default:
396 WARN_ONCE(1, "unsupported intel_encoder type %d\n",
397 intel_encoder->type);
398 return -EINVAL;
399 }
400
401 parm |= type << (16 + port * 3);
402
403 return swsci(dev_priv, SWSCI_SBCB_DISPLAY_POWER_STATE, parm, NULL);
404}
405
406static const struct {
407 pci_power_t pci_power_state;
408 u32 parm;
409} power_state_map[] = {
410 { PCI_D0, 0x00 },
411 { PCI_D1, 0x01 },
412 { PCI_D2, 0x02 },
413 { PCI_D3hot, 0x04 },
414 { PCI_D3cold, 0x04 },
415};
416
417int intel_opregion_notify_adapter(struct drm_i915_private *dev_priv,
418 pci_power_t state)
419{
420 int i;
421
422 if (!HAS_DDI(dev_priv))
423 return 0;
424
425 for (i = 0; i < ARRAY_SIZE(power_state_map); i++) {
426 if (state == power_state_map[i].pci_power_state)
427 return swsci(dev_priv, SWSCI_SBCB_ADAPTER_POWER_STATE,
428 power_state_map[i].parm, NULL);
429 }
430
431 return -EINVAL;
432}
433
434static u32 asle_set_backlight(struct drm_i915_private *dev_priv, u32 bclp)
435{
436 struct intel_connector *connector;
437 struct drm_connector_list_iter conn_iter;
438 struct opregion_asle *asle = dev_priv->opregion.asle;
439 struct drm_device *dev = &dev_priv->drm;
440
441 DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp);
442
443 if (acpi_video_get_backlight_type() == acpi_backlight_native) {
444 DRM_DEBUG_KMS("opregion backlight request ignored\n");
445 return 0;
446 }
447
448 if (!(bclp & ASLE_BCLP_VALID))
449 return ASLC_BACKLIGHT_FAILED;
450
451 bclp &= ASLE_BCLP_MSK;
452 if (bclp > 255)
453 return ASLC_BACKLIGHT_FAILED;
454
455 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
456
457
458
459
460
461 DRM_DEBUG_KMS("updating opregion backlight %d/255\n", bclp);
462 drm_connector_list_iter_begin(dev, &conn_iter);
463 for_each_intel_connector_iter(connector, &conn_iter)
464 intel_panel_set_backlight_acpi(connector, bclp, 255);
465 drm_connector_list_iter_end(&conn_iter);
466 asle->cblv = DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID;
467
468 drm_modeset_unlock(&dev->mode_config.connection_mutex);
469
470
471 return 0;
472}
473
474static u32 asle_set_als_illum(struct drm_i915_private *dev_priv, u32 alsi)
475{
476
477
478 DRM_DEBUG_DRIVER("Illum is not supported\n");
479 return ASLC_ALS_ILLUM_FAILED;
480}
481
482static u32 asle_set_pwm_freq(struct drm_i915_private *dev_priv, u32 pfmb)
483{
484 DRM_DEBUG_DRIVER("PWM freq is not supported\n");
485 return ASLC_PWM_FREQ_FAILED;
486}
487
488static u32 asle_set_pfit(struct drm_i915_private *dev_priv, u32 pfit)
489{
490
491
492 DRM_DEBUG_DRIVER("Pfit is not supported\n");
493 return ASLC_PFIT_FAILED;
494}
495
496static u32 asle_set_supported_rotation_angles(struct drm_i915_private *dev_priv, u32 srot)
497{
498 DRM_DEBUG_DRIVER("SROT is not supported\n");
499 return ASLC_ROTATION_ANGLES_FAILED;
500}
501
502static u32 asle_set_button_array(struct drm_i915_private *dev_priv, u32 iuer)
503{
504 if (!iuer)
505 DRM_DEBUG_DRIVER("Button array event is not supported (nothing)\n");
506 if (iuer & ASLE_IUER_ROTATION_LOCK_BTN)
507 DRM_DEBUG_DRIVER("Button array event is not supported (rotation lock)\n");
508 if (iuer & ASLE_IUER_VOLUME_DOWN_BTN)
509 DRM_DEBUG_DRIVER("Button array event is not supported (volume down)\n");
510 if (iuer & ASLE_IUER_VOLUME_UP_BTN)
511 DRM_DEBUG_DRIVER("Button array event is not supported (volume up)\n");
512 if (iuer & ASLE_IUER_WINDOWS_BTN)
513 DRM_DEBUG_DRIVER("Button array event is not supported (windows)\n");
514 if (iuer & ASLE_IUER_POWER_BTN)
515 DRM_DEBUG_DRIVER("Button array event is not supported (power)\n");
516
517 return ASLC_BUTTON_ARRAY_FAILED;
518}
519
520static u32 asle_set_convertible(struct drm_i915_private *dev_priv, u32 iuer)
521{
522 if (iuer & ASLE_IUER_CONVERTIBLE)
523 DRM_DEBUG_DRIVER("Convertible is not supported (clamshell)\n");
524 else
525 DRM_DEBUG_DRIVER("Convertible is not supported (slate)\n");
526
527 return ASLC_CONVERTIBLE_FAILED;
528}
529
530static u32 asle_set_docking(struct drm_i915_private *dev_priv, u32 iuer)
531{
532 if (iuer & ASLE_IUER_DOCKING)
533 DRM_DEBUG_DRIVER("Docking is not supported (docked)\n");
534 else
535 DRM_DEBUG_DRIVER("Docking is not supported (undocked)\n");
536
537 return ASLC_DOCKING_FAILED;
538}
539
540static u32 asle_isct_state(struct drm_i915_private *dev_priv)
541{
542 DRM_DEBUG_DRIVER("ISCT is not supported\n");
543 return ASLC_ISCT_STATE_FAILED;
544}
545
546static void asle_work(struct work_struct *work)
547{
548 struct intel_opregion *opregion =
549 container_of(work, struct intel_opregion, asle_work);
550 struct drm_i915_private *dev_priv =
551 container_of(opregion, struct drm_i915_private, opregion);
552 struct opregion_asle *asle = dev_priv->opregion.asle;
553 u32 aslc_stat = 0;
554 u32 aslc_req;
555
556 if (!asle)
557 return;
558
559 aslc_req = asle->aslc;
560
561 if (!(aslc_req & ASLC_REQ_MSK)) {
562 DRM_DEBUG_DRIVER("No request on ASLC interrupt 0x%08x\n",
563 aslc_req);
564 return;
565 }
566
567 if (aslc_req & ASLC_SET_ALS_ILLUM)
568 aslc_stat |= asle_set_als_illum(dev_priv, asle->alsi);
569
570 if (aslc_req & ASLC_SET_BACKLIGHT)
571 aslc_stat |= asle_set_backlight(dev_priv, asle->bclp);
572
573 if (aslc_req & ASLC_SET_PFIT)
574 aslc_stat |= asle_set_pfit(dev_priv, asle->pfit);
575
576 if (aslc_req & ASLC_SET_PWM_FREQ)
577 aslc_stat |= asle_set_pwm_freq(dev_priv, asle->pfmb);
578
579 if (aslc_req & ASLC_SUPPORTED_ROTATION_ANGLES)
580 aslc_stat |= asle_set_supported_rotation_angles(dev_priv,
581 asle->srot);
582
583 if (aslc_req & ASLC_BUTTON_ARRAY)
584 aslc_stat |= asle_set_button_array(dev_priv, asle->iuer);
585
586 if (aslc_req & ASLC_CONVERTIBLE_INDICATOR)
587 aslc_stat |= asle_set_convertible(dev_priv, asle->iuer);
588
589 if (aslc_req & ASLC_DOCKING_INDICATOR)
590 aslc_stat |= asle_set_docking(dev_priv, asle->iuer);
591
592 if (aslc_req & ASLC_ISCT_STATE_CHANGE)
593 aslc_stat |= asle_isct_state(dev_priv);
594
595 asle->aslc = aslc_stat;
596}
597
598void intel_opregion_asle_intr(struct drm_i915_private *dev_priv)
599{
600 if (dev_priv->opregion.asle)
601 schedule_work(&dev_priv->opregion.asle_work);
602}
603
604#define ACPI_EV_DISPLAY_SWITCH (1<<0)
605#define ACPI_EV_LID (1<<1)
606#define ACPI_EV_DOCK (1<<2)
607
608static struct intel_opregion *system_opregion;
609
610static int intel_opregion_video_event(struct notifier_block *nb,
611 unsigned long val, void *data)
612{
613
614
615
616
617
618 struct acpi_bus_event *event = data;
619 struct opregion_acpi *acpi;
620 int ret = NOTIFY_OK;
621
622 if (strcmp(event->device_class, ACPI_VIDEO_CLASS) != 0)
623 return NOTIFY_DONE;
624
625 if (!system_opregion)
626 return NOTIFY_DONE;
627
628 acpi = system_opregion->acpi;
629
630 if (event->type == 0x80 && ((acpi->cevt & 1) == 0))
631 ret = NOTIFY_BAD;
632
633 acpi->csts = 0;
634
635 return ret;
636}
637
638static struct notifier_block intel_opregion_notifier = {
639 .notifier_call = intel_opregion_video_event,
640};
641
642
643
644
645
646
647
648static void set_did(struct intel_opregion *opregion, int i, u32 val)
649{
650 if (i < ARRAY_SIZE(opregion->acpi->didl)) {
651 opregion->acpi->didl[i] = val;
652 } else {
653 i -= ARRAY_SIZE(opregion->acpi->didl);
654
655 if (WARN_ON(i >= ARRAY_SIZE(opregion->acpi->did2)))
656 return;
657
658 opregion->acpi->did2[i] = val;
659 }
660}
661
662static u32 acpi_display_type(struct intel_connector *connector)
663{
664 u32 display_type;
665
666 switch (connector->base.connector_type) {
667 case DRM_MODE_CONNECTOR_VGA:
668 case DRM_MODE_CONNECTOR_DVIA:
669 display_type = ACPI_DISPLAY_TYPE_VGA;
670 break;
671 case DRM_MODE_CONNECTOR_Composite:
672 case DRM_MODE_CONNECTOR_SVIDEO:
673 case DRM_MODE_CONNECTOR_Component:
674 case DRM_MODE_CONNECTOR_9PinDIN:
675 case DRM_MODE_CONNECTOR_TV:
676 display_type = ACPI_DISPLAY_TYPE_TV;
677 break;
678 case DRM_MODE_CONNECTOR_DVII:
679 case DRM_MODE_CONNECTOR_DVID:
680 case DRM_MODE_CONNECTOR_DisplayPort:
681 case DRM_MODE_CONNECTOR_HDMIA:
682 case DRM_MODE_CONNECTOR_HDMIB:
683 display_type = ACPI_DISPLAY_TYPE_EXTERNAL_DIGITAL;
684 break;
685 case DRM_MODE_CONNECTOR_LVDS:
686 case DRM_MODE_CONNECTOR_eDP:
687 case DRM_MODE_CONNECTOR_DSI:
688 display_type = ACPI_DISPLAY_TYPE_INTERNAL_DIGITAL;
689 break;
690 case DRM_MODE_CONNECTOR_Unknown:
691 case DRM_MODE_CONNECTOR_VIRTUAL:
692 display_type = ACPI_DISPLAY_TYPE_OTHER;
693 break;
694 default:
695 MISSING_CASE(connector->base.connector_type);
696 display_type = ACPI_DISPLAY_TYPE_OTHER;
697 break;
698 }
699
700 return display_type;
701}
702
703static void intel_didl_outputs(struct drm_i915_private *dev_priv)
704{
705 struct intel_opregion *opregion = &dev_priv->opregion;
706 struct intel_connector *connector;
707 struct drm_connector_list_iter conn_iter;
708 int i = 0, max_outputs;
709 int display_index[16] = {};
710
711
712
713
714
715
716
717
718 max_outputs = ARRAY_SIZE(opregion->acpi->didl) +
719 ARRAY_SIZE(opregion->acpi->did2);
720
721 drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
722 for_each_intel_connector_iter(connector, &conn_iter) {
723 u32 device_id, type;
724
725 device_id = acpi_display_type(connector);
726
727
728 type = (device_id & ACPI_DISPLAY_TYPE_MASK)
729 >> ACPI_DISPLAY_TYPE_SHIFT;
730 device_id |= display_index[type]++ << ACPI_DISPLAY_INDEX_SHIFT;
731
732 connector->acpi_device_id = device_id;
733 if (i < max_outputs)
734 set_did(opregion, i, device_id);
735 i++;
736 }
737 drm_connector_list_iter_end(&conn_iter);
738
739 DRM_DEBUG_KMS("%d outputs detected\n", i);
740
741 if (i > max_outputs)
742 DRM_ERROR("More than %d outputs in connector list\n",
743 max_outputs);
744
745
746 if (i < max_outputs)
747 set_did(opregion, i, 0);
748}
749
750static void intel_setup_cadls(struct drm_i915_private *dev_priv)
751{
752 struct intel_opregion *opregion = &dev_priv->opregion;
753 struct intel_connector *connector;
754 struct drm_connector_list_iter conn_iter;
755 int i = 0;
756
757
758
759
760
761
762
763
764
765
766
767 drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
768 for_each_intel_connector_iter(connector, &conn_iter) {
769 if (i >= ARRAY_SIZE(opregion->acpi->cadl))
770 break;
771 opregion->acpi->cadl[i++] = connector->acpi_device_id;
772 }
773 drm_connector_list_iter_end(&conn_iter);
774
775
776 if (i < ARRAY_SIZE(opregion->acpi->cadl))
777 opregion->acpi->cadl[i] = 0;
778}
779
780void intel_opregion_register(struct drm_i915_private *dev_priv)
781{
782 struct intel_opregion *opregion = &dev_priv->opregion;
783
784 if (!opregion->header)
785 return;
786
787 if (opregion->acpi) {
788 intel_didl_outputs(dev_priv);
789 intel_setup_cadls(dev_priv);
790
791
792
793
794 opregion->acpi->csts = 0;
795 opregion->acpi->drdy = 1;
796
797 system_opregion = opregion;
798 register_acpi_notifier(&intel_opregion_notifier);
799 }
800
801 if (opregion->asle) {
802 opregion->asle->tche = ASLE_TCHE_BLC_EN;
803 opregion->asle->ardy = ASLE_ARDY_READY;
804 }
805}
806
807void intel_opregion_unregister(struct drm_i915_private *dev_priv)
808{
809 struct intel_opregion *opregion = &dev_priv->opregion;
810
811 if (!opregion->header)
812 return;
813
814 if (opregion->asle)
815 opregion->asle->ardy = ASLE_ARDY_NOT_READY;
816
817 cancel_work_sync(&dev_priv->opregion.asle_work);
818
819 if (opregion->acpi) {
820 opregion->acpi->drdy = 0;
821
822 system_opregion = NULL;
823 unregister_acpi_notifier(&intel_opregion_notifier);
824 }
825
826
827 memunmap(opregion->header);
828 if (opregion->rvda) {
829 memunmap(opregion->rvda);
830 opregion->rvda = NULL;
831 }
832 opregion->header = NULL;
833 opregion->acpi = NULL;
834 opregion->swsci = NULL;
835 opregion->asle = NULL;
836 opregion->vbt = NULL;
837 opregion->lid_state = NULL;
838}
839
840static void swsci_setup(struct drm_i915_private *dev_priv)
841{
842 struct intel_opregion *opregion = &dev_priv->opregion;
843 bool requested_callbacks = false;
844 u32 tmp;
845
846
847 opregion->swsci_gbda_sub_functions = 1;
848 opregion->swsci_sbcb_sub_functions = 1;
849
850
851 if (swsci(dev_priv, SWSCI_GBDA_SUPPORTED_CALLS, 0, &tmp) == 0) {
852
853 tmp <<= 1;
854 opregion->swsci_gbda_sub_functions |= tmp;
855 }
856
857
858
859
860
861
862 if (swsci(dev_priv, SWSCI_GBDA_REQUESTED_CALLBACKS, 0, &tmp) == 0) {
863
864 opregion->swsci_sbcb_sub_functions |= tmp;
865 requested_callbacks = true;
866 }
867
868
869
870
871
872
873 if (swsci(dev_priv, SWSCI_SBCB_SUPPORTED_CALLBACKS, 0, &tmp) == 0) {
874
875 u32 low = tmp & 0x7ff;
876 u32 high = tmp & ~0xfff;
877 tmp = (high << 4) | (low << 1) | 1;
878
879
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
885
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
896static int intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
897{
898 DRM_DEBUG_KMS("Falling back to manually reading VBT from "
899 "VBIOS ROM for %s\n", id->ident);
900 return 1;
901}
902
903static const struct dmi_system_id intel_no_opregion_vbt[] = {
904 {
905 .callback = intel_no_opregion_vbt_callback,
906 .ident = "ThinkCentre A57",
907 .matches = {
908 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
909 DMI_MATCH(DMI_PRODUCT_NAME, "97027RG"),
910 },
911 },
912 { }
913};
914
915int intel_opregion_setup(struct drm_i915_private *dev_priv)
916{
917 struct intel_opregion *opregion = &dev_priv->opregion;
918 struct pci_dev *pdev = dev_priv->drm.pdev;
919 u32 asls, mboxes;
920 char buf[sizeof(OPREGION_SIGNATURE)];
921 int err = 0;
922 void *base;
923 const void *vbt;
924 u32 vbt_size;
925
926 BUILD_BUG_ON(sizeof(struct opregion_header) != 0x100);
927 BUILD_BUG_ON(sizeof(struct opregion_acpi) != 0x100);
928 BUILD_BUG_ON(sizeof(struct opregion_swsci) != 0x100);
929 BUILD_BUG_ON(sizeof(struct opregion_asle) != 0x100);
930 BUILD_BUG_ON(sizeof(struct opregion_asle_ext) != 0x400);
931
932 pci_read_config_dword(pdev, ASLS, &asls);
933 DRM_DEBUG_DRIVER("graphic opregion physical addr: 0x%x\n", asls);
934 if (asls == 0) {
935 DRM_DEBUG_DRIVER("ACPI OpRegion not supported!\n");
936 return -ENOTSUPP;
937 }
938
939 INIT_WORK(&opregion->asle_work, asle_work);
940
941 base = memremap(asls, OPREGION_SIZE, MEMREMAP_WB);
942 if (!base)
943 return -ENOMEM;
944
945 memcpy(buf, base, sizeof(buf));
946
947 if (memcmp(buf, OPREGION_SIGNATURE, 16)) {
948 DRM_DEBUG_DRIVER("opregion signature mismatch\n");
949 err = -EINVAL;
950 goto err_out;
951 }
952 opregion->header = base;
953 opregion->lid_state = base + ACPI_CLID;
954
955 mboxes = opregion->header->mboxes;
956 if (mboxes & MBOX_ACPI) {
957 DRM_DEBUG_DRIVER("Public ACPI methods supported\n");
958 opregion->acpi = base + OPREGION_ACPI_OFFSET;
959 }
960
961 if (mboxes & MBOX_SWSCI) {
962 DRM_DEBUG_DRIVER("SWSCI supported\n");
963 opregion->swsci = base + OPREGION_SWSCI_OFFSET;
964 swsci_setup(dev_priv);
965 }
966
967 if (mboxes & MBOX_ASLE) {
968 DRM_DEBUG_DRIVER("ASLE supported\n");
969 opregion->asle = base + OPREGION_ASLE_OFFSET;
970
971 opregion->asle->ardy = ASLE_ARDY_NOT_READY;
972 }
973
974 if (mboxes & MBOX_ASLE_EXT)
975 DRM_DEBUG_DRIVER("ASLE extension supported\n");
976
977 if (dmi_check_system(intel_no_opregion_vbt))
978 goto out;
979
980 if (opregion->header->opregion_ver >= 2 && opregion->asle &&
981 opregion->asle->rvda && opregion->asle->rvds) {
982 opregion->rvda = memremap(opregion->asle->rvda,
983 opregion->asle->rvds,
984 MEMREMAP_WB);
985 vbt = opregion->rvda;
986 vbt_size = opregion->asle->rvds;
987 if (intel_bios_is_valid_vbt(vbt, vbt_size)) {
988 DRM_DEBUG_KMS("Found valid VBT in ACPI OpRegion (RVDA)\n");
989 opregion->vbt = vbt;
990 opregion->vbt_size = vbt_size;
991 goto out;
992 } else {
993 DRM_DEBUG_KMS("Invalid VBT in ACPI OpRegion (RVDA)\n");
994 }
995 }
996
997 vbt = base + OPREGION_VBT_OFFSET;
998
999
1000
1001
1002
1003
1004
1005 vbt_size = (mboxes & MBOX_ASLE_EXT) ?
1006 OPREGION_ASLE_EXT_OFFSET : OPREGION_SIZE;
1007 vbt_size -= OPREGION_VBT_OFFSET;
1008 if (intel_bios_is_valid_vbt(vbt, vbt_size)) {
1009 DRM_DEBUG_KMS("Found valid VBT in ACPI OpRegion (Mailbox #4)\n");
1010 opregion->vbt = vbt;
1011 opregion->vbt_size = vbt_size;
1012 } else {
1013 DRM_DEBUG_KMS("Invalid VBT in ACPI OpRegion (Mailbox #4)\n");
1014 }
1015
1016out:
1017 return 0;
1018
1019err_out:
1020 memunmap(base);
1021 return err;
1022}
1023
1024static int intel_use_opregion_panel_type_callback(const struct dmi_system_id *id)
1025{
1026 DRM_INFO("Using panel type from OpRegion on %s\n", id->ident);
1027 return 1;
1028}
1029
1030static const struct dmi_system_id intel_use_opregion_panel_type[] = {
1031 {
1032 .callback = intel_use_opregion_panel_type_callback,
1033 .ident = "Conrac GmbH IX45GM2",
1034 .matches = {DMI_MATCH(DMI_SYS_VENDOR, "Conrac GmbH"),
1035 DMI_MATCH(DMI_PRODUCT_NAME, "IX45GM2"),
1036 },
1037 },
1038 { }
1039};
1040
1041int
1042intel_opregion_get_panel_type(struct drm_i915_private *dev_priv)
1043{
1044 u32 panel_details;
1045 int ret;
1046
1047 ret = swsci(dev_priv, SWSCI_GBDA_PANEL_DETAILS, 0x0, &panel_details);
1048 if (ret) {
1049 DRM_DEBUG_KMS("Failed to get panel details from OpRegion (%d)\n",
1050 ret);
1051 return ret;
1052 }
1053
1054 ret = (panel_details >> 8) & 0xff;
1055 if (ret > 0x10) {
1056 DRM_DEBUG_KMS("Invalid OpRegion panel type 0x%x\n", ret);
1057 return -EINVAL;
1058 }
1059
1060
1061 if (ret == 0x0) {
1062 DRM_DEBUG_KMS("No panel type in OpRegion\n");
1063 return -ENODEV;
1064 }
1065
1066
1067
1068
1069
1070
1071 if (!dmi_check_system(intel_use_opregion_panel_type)) {
1072 DRM_DEBUG_KMS("Ignoring OpRegion panel type (%d)\n", ret - 1);
1073 return -ENODEV;
1074 }
1075
1076 return ret - 1;
1077}
1078