diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index b530d49ca92a44663d8322953cc564ebd31336db..e5c9886cea51775c3ba7cc49166bd0d1151daba2 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -213,6 +213,7 @@ nouveau-y += core/engine/copy/nvc0.o nouveau-y += core/engine/copy/nve0.o nouveau-y += core/engine/crypt/nv84.o nouveau-y += core/engine/crypt/nv98.o +nouveau-y += core/engine/device/acpi.o nouveau-y += core/engine/device/base.o nouveau-y += core/engine/device/ctrl.o nouveau-y += core/engine/device/nv04.o diff --git a/drivers/gpu/drm/nouveau/core/engine/device/acpi.c b/drivers/gpu/drm/nouveau/core/engine/device/acpi.c new file mode 100644 index 0000000000000000000000000000000000000000..79a2e4d4731c6736ec0528500f9904413b84db50 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/device/acpi.c @@ -0,0 +1,59 @@ +/* + * Copyright 2014 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "acpi.h" + +#ifdef CONFIG_ACPI +static int +nvkm_acpi_ntfy(struct notifier_block *nb, unsigned long val, void *data) +{ + struct nouveau_device *device = + container_of(nb, typeof(*device), acpi.nb); + struct acpi_bus_event *info = data; + + if (!strcmp(info->device_class, "ac_adapter")) + nouveau_event_trigger(device->ntfy, 1, NVKM_DEVICE_NTFY_POWER); + + return NOTIFY_DONE; +} +#endif + +int +nvkm_acpi_fini(struct nouveau_device *device, bool suspend) +{ +#ifdef CONFIG_ACPI + unregister_acpi_notifier(&device->acpi.nb); +#endif + return 0; +} + +int +nvkm_acpi_init(struct nouveau_device *device) +{ +#ifdef CONFIG_ACPI + device->acpi.nb.notifier_call = nvkm_acpi_ntfy; + register_acpi_notifier(&device->acpi.nb); +#endif + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/device/acpi.h b/drivers/gpu/drm/nouveau/core/engine/device/acpi.h new file mode 100644 index 0000000000000000000000000000000000000000..cc49f4f568cd091861a44a7ec2d583ba197882d4 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/device/acpi.h @@ -0,0 +1,9 @@ +#ifndef __NVKM_DEVICE_ACPI_H__ +#define __NVKM_DEVICE_ACPI_H__ + +#include + +int nvkm_acpi_init(struct nouveau_device *); +int nvkm_acpi_fini(struct nouveau_device *, bool); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/device/base.c b/drivers/gpu/drm/nouveau/core/engine/device/base.c index 18c8c7245b73b2b1e12ec3fe921266621763f8ee..466dda2f7a3a67a7621a711377abe7ebf21f426f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/base.c @@ -30,6 +30,7 @@ #include #include "priv.h" +#include "acpi.h" static DEFINE_MUTEX(nv_devices_mutex); static LIST_HEAD(nv_devices); @@ -386,7 +387,7 @@ nouveau_device_fini(struct nouveau_object *object, bool suspend) } } - ret = 0; + ret = nvkm_acpi_fini(device, suspend); fail: for (; ret && i < NVDEV_SUBDEV_NR; i++) { if ((subdev = device->subdev[i])) { @@ -407,7 +408,11 @@ nouveau_device_init(struct nouveau_object *object) { struct nouveau_device *device = (void *)object; struct nouveau_object *subdev; - int ret, i; + int ret, i = 0; + + ret = nvkm_acpi_init(device); + if (ret) + goto fail; for (i = 0; i < NVDEV_SUBDEV_NR; i++) { if ((subdev = device->subdev[i])) { @@ -430,6 +435,8 @@ nouveau_device_init(struct nouveau_object *object) } } + if (ret) + nvkm_acpi_fini(device, false); return ret; } @@ -438,6 +445,8 @@ nouveau_device_dtor(struct nouveau_object *object) { struct nouveau_device *device = (void *)object; + nouveau_event_destroy(&device->ntfy); + mutex_lock(&nv_devices_mutex); list_del(&device->head); mutex_unlock(&nv_devices_mutex); @@ -560,6 +569,8 @@ nouveau_device_create_(void *dev, enum nv_bus_type type, u64 name, nv_subdev(device)->debug = nouveau_dbgopt(device->dbgopt, "DEVICE"); nv_engine(device)->sclass = nouveau_device_sclass; list_add(&device->head, &nv_devices); + + ret = nouveau_event_create(1, NVKM_DEVICE_NTFY, &device->ntfy); done: mutex_unlock(&nv_devices_mutex); return ret; diff --git a/drivers/gpu/drm/nouveau/core/include/core/device.h b/drivers/gpu/drm/nouveau/core/include/core/device.h index a8a9a9cf16cb2e8e62c6f96e68e9d8ee95aeb73b..9ce2ee9aa32e840d0058a85e0df80113a05ede5d 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/device.h +++ b/drivers/gpu/drm/nouveau/core/include/core/device.h @@ -4,6 +4,7 @@ #include #include #include +#include enum nv_subdev_type { NVDEV_ENGINE_DEVICE, @@ -61,6 +62,11 @@ enum nv_subdev_type { NVDEV_SUBDEV_NR, }; +enum nvkm_device_ntfy { + NVKM_DEVICE_NTFY_POWER = 0, + NVKM_DEVICE_NTFY +}; + struct nouveau_device { struct nouveau_engine base; struct list_head head; @@ -69,6 +75,8 @@ struct nouveau_device { struct platform_device *platformdev; u64 handle; + struct nouveau_event *ntfy; + const char *cfgopt; const char *dbgopt; const char *name; @@ -93,6 +101,10 @@ struct nouveau_device { struct nouveau_oclass *oclass[NVDEV_SUBDEV_NR]; struct nouveau_object *subdev[NVDEV_SUBDEV_NR]; + + struct { + struct notifier_block nb; + } acpi; }; static inline struct nouveau_device *