diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2011-11-07 13:36:08 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2011-12-21 19:01:42 +1000 |
commit | 3952315b9d20fb04d43d184f9c1475327811c5aa (patch) | |
tree | fabff1baedd0a2a3daf2e8953d27cdef666ced37 /drivers | |
parent | 93d9206d08dd18e3aaeed90a3e076b8c323fdd72 (diff) |
drm/nouveau/mxm: implement _DSM shadow method
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_mxm.c | 61 |
1 files changed, 60 insertions, 1 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_mxm.c b/drivers/gpu/drm/nouveau/nouveau_mxm.c index f6f73568c4f..840c88fc4f0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mxm.c +++ b/drivers/gpu/drm/nouveau/nouveau_mxm.c @@ -476,11 +476,68 @@ mxm_shadow_rom(struct drm_device *dev, u8 version) return false; } +#if defined(CONFIG_ACPI) static bool mxm_shadow_dsm(struct drm_device *dev, u8 version) { - return false; + struct drm_nouveau_private *dev_priv = dev->dev_private; + static char muid[] = { + 0x00, 0xA4, 0x04, 0x40, 0x7D, 0x91, 0xF2, 0x4C, + 0xB8, 0x9C, 0x79, 0xB6, 0x2F, 0xD5, 0x56, 0x65 + }; + u32 mxms_args[] = { 0x00000000 }; + union acpi_object args[4] = { + /* _DSM MUID */ + { .buffer.type = 3, + .buffer.length = sizeof(muid), + .buffer.pointer = muid, + }, + /* spec says this can be zero to mean "highest revision", but + * of course there's at least one bios out there which fails + * unless you pass in exactly the version it supports.. + */ + { .integer.type = ACPI_TYPE_INTEGER, + .integer.value = (version & 0xf0) << 4 | (version & 0x0f), + }, + /* MXMS function */ + { .integer.type = ACPI_TYPE_INTEGER, + .integer.value = 0x00000010, + }, + /* Pointer to MXMS arguments */ + { .buffer.type = ACPI_TYPE_BUFFER, + .buffer.length = sizeof(mxms_args), + .buffer.pointer = (char *)mxms_args, + }, + }; + struct acpi_object_list list = { ARRAY_SIZE(args), args }; + struct acpi_buffer retn = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *obj; + acpi_handle handle; + int ret; + + handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev); + if (!handle) + return false; + + ret = acpi_evaluate_object(handle, "_DSM", &list, &retn); + if (ret) { + MXM_DBG(dev, "DSM MXMS failed: %d\n", ret); + return false; + } + + obj = retn.pointer; + if (obj->type == ACPI_TYPE_BUFFER) { + dev_priv->mxms = kmemdup(obj->buffer.pointer, + obj->buffer.length, GFP_KERNEL); + } else + if (obj->type == ACPI_TYPE_INTEGER) { + MXM_DBG(dev, "DSM MXMS returned 0x%llx\n", obj->integer.value); + } + + kfree(obj); + return dev_priv->mxms != NULL; } +#endif #if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE) @@ -521,7 +578,9 @@ struct mxm_shadow_h { bool (*exec)(struct drm_device *, u8 version); } _mxm_shadow[] = { { "ROM", mxm_shadow_rom }, +#if defined(CONFIG_ACPI) { "DSM", mxm_shadow_dsm }, +#endif #if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE) { "WMI", mxm_shadow_wmi }, #endif |