diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2011-11-06 21:54:20 -0500 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2011-12-21 04:01:42 -0500 |
commit | 93d9206d08dd18e3aaeed90a3e076b8c323fdd72 (patch) | |
tree | 37ad68e542eefa4bf9a0487ca936db8f51f09521 /drivers/gpu/drm/nouveau | |
parent | b4c26818aeb4159dd537eff6453ae5ebf7a69723 (diff) |
drm/nouveau/mxm: implement wmi shadow method
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_mxm.c | 51 |
1 files changed, 45 insertions, 6 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_mxm.c b/drivers/gpu/drm/nouveau/nouveau_mxm.c index ae9a5ac750fd..f6f73568c4f0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mxm.c +++ b/drivers/gpu/drm/nouveau/nouveau_mxm.c | |||
@@ -22,6 +22,8 @@ | |||
22 | * Authors: Ben Skeggs | 22 | * Authors: Ben Skeggs |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <linux/acpi.h> | ||
26 | |||
25 | #include "drmP.h" | 27 | #include "drmP.h" |
26 | #include "nouveau_drv.h" | 28 | #include "nouveau_drv.h" |
27 | 29 | ||
@@ -469,34 +471,71 @@ mxm_dcb_sanitise(struct drm_device *dev) | |||
469 | } | 471 | } |
470 | 472 | ||
471 | static bool | 473 | static bool |
472 | mxm_shadow_rom(struct drm_device *dev) | 474 | mxm_shadow_rom(struct drm_device *dev, u8 version) |
473 | { | 475 | { |
474 | return false; | 476 | return false; |
475 | } | 477 | } |
476 | 478 | ||
477 | static bool | 479 | static bool |
478 | mxm_shadow_dsm(struct drm_device *dev) | 480 | mxm_shadow_dsm(struct drm_device *dev, u8 version) |
479 | { | 481 | { |
480 | return false; | 482 | return false; |
481 | } | 483 | } |
482 | 484 | ||
485 | #if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE) | ||
486 | |||
487 | #define WMI_WMMX_GUID "F6CB5C3C-9CAE-4EBD-B577-931EA32A2CC0" | ||
488 | |||
489 | static bool | ||
490 | mxm_shadow_wmi(struct drm_device *dev, u8 version) | ||
491 | { | ||
492 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
493 | u32 mxms_args[] = { 0x534D584D /* MXMS */, version, 0 }; | ||
494 | struct acpi_buffer args = { sizeof(mxms_args), mxms_args }; | ||
495 | struct acpi_buffer retn = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
496 | union acpi_object *obj; | ||
497 | acpi_status status; | ||
498 | |||
499 | if (!wmi_has_guid(WMI_WMMX_GUID)) | ||
500 | return false; | ||
501 | |||
502 | status = wmi_evaluate_method(WMI_WMMX_GUID, 0, 0, &args, &retn); | ||
503 | if (ACPI_FAILURE(status)) { | ||
504 | MXM_DBG(dev, "WMMX MXMS returned %d\n", status); | ||
505 | return false; | ||
506 | } | ||
507 | |||
508 | obj = retn.pointer; | ||
509 | if (obj->type == ACPI_TYPE_BUFFER) { | ||
510 | dev_priv->mxms = kmemdup(obj->buffer.pointer, | ||
511 | obj->buffer.length, GFP_KERNEL); | ||
512 | } | ||
513 | |||
514 | kfree(obj); | ||
515 | return dev_priv->mxms != NULL; | ||
516 | } | ||
517 | #endif | ||
518 | |||
483 | struct mxm_shadow_h { | 519 | struct mxm_shadow_h { |
484 | const char *name; | 520 | const char *name; |
485 | bool (*exec)(struct drm_device *); | 521 | bool (*exec)(struct drm_device *, u8 version); |
486 | } _mxm_shadow[] = { | 522 | } _mxm_shadow[] = { |
487 | { "ROM", mxm_shadow_rom }, | 523 | { "ROM", mxm_shadow_rom }, |
488 | { "DSM", mxm_shadow_dsm }, | 524 | { "DSM", mxm_shadow_dsm }, |
525 | #if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE) | ||
526 | { "WMI", mxm_shadow_wmi }, | ||
527 | #endif | ||
489 | {} | 528 | {} |
490 | }; | 529 | }; |
491 | 530 | ||
492 | static int | 531 | static int |
493 | mxm_shadow(struct drm_device *dev) | 532 | mxm_shadow(struct drm_device *dev, u8 version) |
494 | { | 533 | { |
495 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 534 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
496 | struct mxm_shadow_h *shadow = _mxm_shadow; | 535 | struct mxm_shadow_h *shadow = _mxm_shadow; |
497 | do { | 536 | do { |
498 | MXM_DBG(dev, "checking %s\n", shadow->name); | 537 | MXM_DBG(dev, "checking %s\n", shadow->name); |
499 | if (shadow->exec(dev)) { | 538 | if (shadow->exec(dev, version)) { |
500 | if (mxms_valid(dev)) | 539 | if (mxms_valid(dev)) |
501 | return 0; | 540 | return 0; |
502 | kfree(dev_priv->mxms); | 541 | kfree(dev_priv->mxms); |
@@ -517,7 +556,7 @@ nouveau_mxm_init(struct drm_device *dev) | |||
517 | 556 | ||
518 | MXM_MSG(dev, "BIOS version %d.%d\n", mxm[0] >> 4, mxm[0] & 0x0f); | 557 | MXM_MSG(dev, "BIOS version %d.%d\n", mxm[0] >> 4, mxm[0] & 0x0f); |
519 | 558 | ||
520 | if (mxm_shadow(dev)) { | 559 | if (mxm_shadow(dev, mxm[0])) { |
521 | MXM_MSG(dev, "failed to locate valid SIS\n"); | 560 | MXM_MSG(dev, "failed to locate valid SIS\n"); |
522 | return -EINVAL; | 561 | return -EINVAL; |
523 | } | 562 | } |