The diff below provides a minimal implementation of some of the Linux
ACPI iterfaces.  Enough to allow us to compile the ACPI code for
radeon(4) and amdgpu(4).  With this diff the brightness keys on my HP
laptop with:

cpu0: AMD A4-4355M APU with Radeon(tm) HD Graphics, 1897.56 MHz, 15-10-01
...
radeondrm0 at pci0 dev 1 function 0 "ATI Radeon HD 7400G" rev 0x00

now work.  I'd like to see some more tests, especially on laptops with
amdgpu(4).  Diff has some debug printing enabled.  Feel free to share
the dmesg output with me.


Index: dev/pci/drm/drm_drv.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/drm_drv.c,v
retrieving revision 1.164
diff -u -p -r1.164 drm_drv.c
--- dev/pci/drm/drm_drv.c       30 Jul 2019 05:50:20 -0000      1.164
+++ dev/pci/drm/drm_drv.c       16 Aug 2019 20:05:55 -0000
@@ -55,6 +55,14 @@
 #include <uvm/uvm.h>
 #include <uvm/uvm_device.h>
 
+#include <machine/bus.h>
+
+#ifdef __HAVE_ACPI
+#include <dev/acpi/acpidev.h>
+#include <dev/acpi/acpivar.h>
+#include <dev/acpi/dsdt.h>
+#endif
+
 #include <drm/drmP.h>
 #include <drm/drm_gem.h>
 #include <uapi/drm/drm.h>
@@ -76,7 +84,7 @@ struct drm_softc {
 #ifdef DRMDEBUG
 unsigned int drm_debug = DRM_UT_DRIVER | DRM_UT_KMS;
 #else
-unsigned int drm_debug = 0;
+unsigned int drm_debug = DRM_UT_DRIVER;
 #endif
 
 int     drm_firstopen(struct drm_device *);
@@ -256,6 +264,12 @@ drm_attach(struct device *parent, struct
        dev->bridgetag = da->bridgetag;
        dev->pdev->tag = da->tag;
        dev->pdev->pci = (struct pci_softc *)parent->dv_parent;
+
+#ifdef CONFIG_ACPI
+       dev->pdev->dev.node = acpi_find_pci(da->pc, da->tag);
+       aml_register_notify(dev->pdev->dev.node, NULL,
+           drm_linux_acpi_notify, NULL, ACPIDEV_NOPOLL);
+#endif
 
        rw_init(&dev->struct_mutex, "drmdevlk");
        mtx_init(&dev->event_lock, IPL_TTY);
Index: dev/pci/drm/drm_linux.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/drm_linux.c,v
retrieving revision 1.47
diff -u -p -r1.47 drm_linux.c
--- dev/pci/drm/drm_linux.c     5 Aug 2019 08:35:59 -0000       1.47
+++ dev/pci/drm/drm_linux.c     16 Aug 2019 20:05:55 -0000
@@ -987,6 +987,8 @@ vga_put(struct pci_dev *pdev, int rsrc)
 
 #include <dev/acpi/acpireg.h>
 #include <dev/acpi/acpivar.h>
+#include <dev/acpi/amltypes.h>
+#include <dev/acpi/dsdt.h>
 
 acpi_status
 acpi_get_table(const char *sig, int instance,
@@ -1008,6 +1010,131 @@ acpi_get_table(const char *sig, int inst
        }
 
        return AE_NOT_FOUND;
+}
+
+acpi_status
+acpi_get_handle(acpi_handle node, const char *name, acpi_handle *rnode)
+{
+       node = aml_searchname(node, name);
+       if (node == NULL)
+               return AE_NOT_FOUND;
+
+       *rnode = node;
+       return 0;
+}
+
+acpi_status
+acpi_get_name(acpi_handle node, int type,  struct acpi_buffer *buffer)
+{
+       KASSERT(buffer->length != ACPI_ALLOCATE_BUFFER);
+       KASSERT(type == ACPI_FULL_PATHNAME);
+       strlcpy(buffer->pointer, aml_nodename(node), buffer->length);
+       return 0;
+}
+
+acpi_status
+acpi_evaluate_object(acpi_handle node, const char *name,
+    struct acpi_object_list *params, struct acpi_buffer *result)
+{
+       struct aml_value args[4], res;
+       union acpi_object *obj;
+       uint8_t *data;
+       int i;
+
+       KASSERT(params->count <= nitems(args));
+
+       for (i = 0; i < params->count; i++) {
+               args[i].type = params->pointer[i].type;
+               switch (args[i].type) {
+               case AML_OBJTYPE_INTEGER:
+                       args[i].v_integer = params->pointer[i].integer.value;
+                       break;
+               case AML_OBJTYPE_BUFFER:
+                       args[i].length = params->pointer[i].buffer.length;
+                       args[i].v_buffer = params->pointer[i].buffer.pointer;
+                       break;
+               default:
+                       printf("%s: arg type 0x%02x", __func__, args[i].type);
+                       return AE_BAD_PARAMETER;
+               }
+       }
+
+       if (name) {
+               node = aml_searchname(node, name);
+               if (node == NULL)
+                       return AE_NOT_FOUND;
+       }
+       if (aml_evalnode(acpi_softc, node, params->count, args, &res)) {
+               aml_freevalue(&res);
+               return AE_ERROR;
+       }
+
+       KASSERT(result->length == ACPI_ALLOCATE_BUFFER);
+
+       result->length = sizeof(union acpi_object);
+       switch (res.type) {
+       case AML_OBJTYPE_BUFFER:
+               result->length += res.length;
+               result->pointer = malloc(result->length, M_DRM, M_WAITOK);
+               obj = (union acpi_object *)result->pointer;
+               data = (uint8_t *)(obj + 1);
+               obj->type = res.type;
+               obj->buffer.length = res.length;
+               obj->buffer.pointer = data;
+               memcpy(data, res.v_buffer, res.length);
+               break;
+       default:
+               printf("%s: return type 0x%02x", __func__, res.type);
+               aml_freevalue(&res);
+               return AE_ERROR;
+       }
+
+       aml_freevalue(&res);
+       return 0;
+}
+
+SLIST_HEAD(, notifier_block) drm_linux_acpi_notify_list =
+       SLIST_HEAD_INITIALIZER(drm_linux_acpi_notify_list);
+
+int
+drm_linux_acpi_notify(struct aml_node *node, int notify, void *arg)
+{
+       struct acpi_bus_event event;
+       struct notifier_block *nb;
+
+       event.device_class = ACPI_VIDEO_CLASS;
+       event.type = notify;
+
+       SLIST_FOREACH(nb, &drm_linux_acpi_notify_list, link)
+               nb->notifier_call(nb, 0, &event);
+       return 0;
+}
+
+int
+register_acpi_notifier(struct notifier_block *nb)
+{
+       SLIST_INSERT_HEAD(&drm_linux_acpi_notify_list, nb, link);
+       return 0;
+}
+
+int
+unregister_acpi_notifier(struct notifier_block *nb)
+{
+       SLIST_REMOVE(&drm_linux_acpi_notify_list, nb, notifier_block, link);
+       return 0;
+}
+
+const char *
+acpi_format_exception(acpi_status status)
+{
+       switch (status) {
+       case AE_NOT_FOUND:
+               return "not found";
+       case AE_BAD_PARAMETER:
+               return "bad parameter";
+       default:
+               return "unknown";
+       }
 }
 
 #endif
Index: dev/pci/drm/files.drm
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/files.drm,v
retrieving revision 1.45
diff -u -p -r1.45 files.drm
--- dev/pci/drm/files.drm       21 May 2019 22:40:06 -0000      1.45
+++ dev/pci/drm/files.drm       16 Aug 2019 20:05:55 -0000
@@ -235,7 +235,7 @@ file        dev/pci/drm/radeon/r600_cs.c                    
rade
 file   dev/pci/drm/radeon/r600_dma.c                   radeondrm
 file   dev/pci/drm/radeon/r600_dpm.c                   radeondrm
 file   dev/pci/drm/radeon/r600_hdmi.c                  radeondrm
-#file  dev/pci/drm/radeon/radeon_acpi.c                radeondrm
+file   dev/pci/drm/radeon/radeon_acpi.c                radeondrm
 file   dev/pci/drm/radeon/radeon_agp.c                 radeondrm
 file   dev/pci/drm/radeon/radeon_asic.c                radeondrm
 file   dev/pci/drm/radeon/radeon_atombios.c            radeondrm
@@ -518,7 +518,7 @@ file        dev/pci/drm/amd/amdgpu/amdgpu_vce_v
 
 device amdgpu: drmbase, ttm, wsemuldisplaydev, rasops8, rasops32, i2cbus, 
i2c_bitbang, drm_sched, chash, powerplay, amddal
 attach amdgpu at pci
-#file  dev/pci/drm/amd/amdgpu/amdgpu_acpi.c            amdgpu
+file   dev/pci/drm/amd/amdgpu/amdgpu_acpi.c            amdgpu
 file   dev/pci/drm/amd/amdgpu/amdgpu_afmt.c            amdgpu
 file   dev/pci/drm/amd/amdgpu/amdgpu_amdkfd.c          amdgpu
 file   dev/pci/drm/amd/amdgpu/amdgpu_atombios.c        amdgpu
Index: dev/pci/drm/amd/amdgpu/amdgpu_acpi.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/amd/amdgpu/amdgpu_acpi.c,v
retrieving revision 1.2
diff -u -p -r1.2 amdgpu_acpi.c
--- dev/pci/drm/amd/amdgpu/amdgpu_acpi.c        11 Jun 2019 11:47:24 -0000      
1.2
+++ dev/pci/drm/amd/amdgpu/amdgpu_acpi.c        16 Aug 2019 20:05:55 -0000
@@ -1,3 +1,4 @@
+#define DRMDEBUG
 /*
  * Copyright 2012 Advanced Micro Devices, Inc.
  *
Index: dev/pci/drm/amd/amdgpu/amdgpu_bios.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/amd/amdgpu/amdgpu_bios.c,v
retrieving revision 1.1
diff -u -p -r1.1 amdgpu_bios.c
--- dev/pci/drm/amd/amdgpu/amdgpu_bios.c        21 May 2019 22:40:06 -0000      
1.1
+++ dev/pci/drm/amd/amdgpu/amdgpu_bios.c        16 Aug 2019 20:05:55 -0000
@@ -37,10 +37,6 @@
 #include <dev/isa/isavar.h>
 #endif
 
-#ifdef __HAVE_ACPI
-#include "acpi.h"
-#endif
-
 /*
  * BIOS.
  */
@@ -476,10 +472,6 @@ static bool amdgpu_read_disabled_bios(st
        else
                return amdgpu_asic_read_disabled_bios(adev);
 }
-
-#if NACPI > 0
-#define CONFIG_ACPI
-#endif
 
 #ifdef CONFIG_ACPI
 static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
Index: dev/pci/drm/i915/i915_drv.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/i915/i915_drv.h,v
retrieving revision 1.82
diff -u -p -r1.82 i915_drv.h
--- dev/pci/drm/i915/i915_drv.h 4 May 2019 11:34:47 -0000       1.82
+++ dev/pci/drm/i915/i915_drv.h 16 Aug 2019 20:05:56 -0000
@@ -55,11 +55,6 @@
 #include <drm/drm_gem.h>
 #include <drm/drm_cache.h>
 
-#include "acpi.h"
-#if NACPI > 0
-#define CONFIG_ACPI
-#endif
-
 #include "drm.h"
 #include "vga.h"
 
Index: dev/pci/drm/include/drm/drmP.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/include/drm/drmP.h,v
retrieving revision 1.4
diff -u -p -r1.4 drmP.h
--- dev/pci/drm/include/drm/drmP.h      14 Aug 2019 05:32:56 -0000      1.4
+++ dev/pci/drm/include/drm/drmP.h      16 Aug 2019 20:05:56 -0000
@@ -242,6 +242,7 @@ struct drm_attach_args {
 #define DRMDEVCF_PRIMARY_UNK   -1
 
 void   drm_linux_init(void);
+int    drm_linux_acpi_notify(struct aml_node *, int, void *);
 
 /* Device setup support (drm_drv.c) */
 int    drm_pciprobe(struct pci_attach_args *, const struct drm_pcidev * );
Index: dev/pci/drm/include/linux/acpi.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/include/linux/acpi.h,v
retrieving revision 1.1
diff -u -p -r1.1 acpi.h
--- dev/pci/drm/include/linux/acpi.h    14 Apr 2019 10:14:53 -0000      1.1
+++ dev/pci/drm/include/linux/acpi.h    16 Aug 2019 20:05:56 -0000
@@ -13,13 +13,71 @@
 
 typedef size_t acpi_size;
 typedef int acpi_status;
+typedef struct aml_node *acpi_handle;
+
+struct acpi_bus_event {
+       const char *device_class;
+       int type;
+};
+
+struct acpi_buffer {
+       size_t length;
+       void *pointer;
+};
+
+#define ACPI_ALLOCATE_BUFFER   (size_t)-1
+
+union acpi_object {
+       int type;
+       struct {
+               int type;
+               uint64_t value;
+       } integer;
+       struct {
+               int type;
+               size_t length;
+               void *pointer;
+       } buffer;
+};
+
+#define ACPI_TYPE_INTEGER      1
+#define ACPI_TYPE_BUFFER       3
+
+struct acpi_object_list {
+       int count;
+       union acpi_object *pointer;
+};
 
 struct acpi_table_header;
 
 #define ACPI_SUCCESS(x) ((x) == 0)
+#define ACPI_FAILURE(x) ((x) != 0)
 
-#define AE_NOT_FOUND   0x0005
+#define AE_ERROR               1
+#define AE_NOT_FOUND           2
+#define AE_BAD_PARAMETER       3
 
 acpi_status acpi_get_table(const char *, int, struct acpi_table_header **);
+
+acpi_status acpi_evaluate_object(acpi_handle, const char *,
+       struct acpi_object_list *, struct acpi_buffer *);
+
+acpi_status acpi_get_handle(acpi_handle, const char *, acpi_handle *);
+acpi_status acpi_get_name(acpi_handle, int, struct acpi_buffer *);
+
+#define ACPI_FULL_PATHNAME 1
+
+#define ACPI_VIDEO_CLASS   "video"
+
+#define ACPI_VIDEO_NOTIFY_PROBE                0x81
+
+#define ACPI_HANDLE(x) ((x)->node)
+
+const char *acpi_format_exception(acpi_status);
+
+struct notifier_block;
+
+int register_acpi_notifier(struct notifier_block *);
+int unregister_acpi_notifier(struct notifier_block *);
 
 #endif
Index: dev/pci/drm/include/linux/backlight.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/include/linux/backlight.h,v
retrieving revision 1.1
diff -u -p -r1.1 backlight.h
--- dev/pci/drm/include/linux/backlight.h       14 Apr 2019 10:14:53 -0000      
1.1
+++ dev/pci/drm/include/linux/backlight.h       16 Aug 2019 20:05:56 -0000
@@ -31,6 +31,8 @@ struct backlight_device {
 #define BACKLIGHT_RAW          0
 #define BACKLIGHT_FIRMWARE     1
 
+#define BACKLIGHT_UPDATE_HOTKEY        0
+
 struct backlight_device *backlight_device_register(const char *, void *,
      void *, const struct backlight_ops *, struct backlight_properties *);
 void backlight_device_unregister(struct backlight_device *);
@@ -39,6 +41,12 @@ static inline void
 backlight_update_status(struct backlight_device *bd)
 {
        bd->ops->update_status(bd);
+}
+
+static inline void
+backlight_force_update(struct backlight_device *bd, int reason)
+{
+       bd->props.brightness = bd->ops->get_brightness(bd);
 }
 
 void backlight_schedule_update_status(struct backlight_device *);
Index: dev/pci/drm/include/linux/kconfig.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/include/linux/kconfig.h,v
retrieving revision 1.4
diff -u -p -r1.4 kconfig.h
--- dev/pci/drm/include/linux/kconfig.h 14 Aug 2019 05:32:56 -0000      1.4
+++ dev/pci/drm/include/linux/kconfig.h 16 Aug 2019 20:05:56 -0000
@@ -3,8 +3,7 @@
 #ifndef _LINUX_KCONFIG_H
 #define _LINUX_KCONFIG_H
 
-#include "agp.h"
-
+#include <sys/param.h>
 #include <sys/endian.h>
 
 #define IS_ENABLED(x) x - 0
@@ -34,6 +33,14 @@
 #define __LITTLE_ENDIAN
 #endif
 
+#ifdef __HAVE_ACPI
+#include <acpi.h>
+#if NACPI > 0
+#define CONFIG_ACPI                            1
+#endif
+#endif
+
+#include <agp.h>
 #if NAGP > 0
 #define CONFIG_AGP                             1
 #endif
Index: dev/pci/drm/include/linux/notifier.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/include/linux/notifier.h,v
retrieving revision 1.1
diff -u -p -r1.1 notifier.h
--- dev/pci/drm/include/linux/notifier.h        14 Apr 2019 10:14:53 -0000      
1.1
+++ dev/pci/drm/include/linux/notifier.h        16 Aug 2019 20:05:56 -0000
@@ -4,7 +4,8 @@
 #define _LINUX_NOTIFIER_H
 
 struct notifier_block {
-       void *notifier_call;
+       int (*notifier_call)(struct notifier_block *, unsigned long, void *);
+       SLIST_ENTRY(notifier_block) link;
 };
 
 #define ATOMIC_INIT_NOTIFIER_HEAD(x)
Index: dev/pci/drm/include/linux/pci.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/include/linux/pci.h,v
retrieving revision 1.2
diff -u -p -r1.2 pci.h
--- dev/pci/drm/include/linux/pci.h     15 Jul 2019 03:35:23 -0000      1.2
+++ dev/pci/drm/include/linux/pci.h     16 Aug 2019 20:05:56 -0000
@@ -39,6 +39,10 @@ struct pci_bus {
        struct pci_dev  *self;
 };
 
+struct pci_acpi {
+       struct aml_node *node;
+};
+
 struct pci_dev {
        struct pci_bus  _bus;
        struct pci_bus  *bus;
@@ -57,6 +61,8 @@ struct pci_dev {
        int             irq;
        int             msi_enabled;
        uint8_t         no_64bit_msi;
+
+       struct pci_acpi dev;
 };
 #define PCI_ANY_ID (uint16_t) (~0U)
 
@@ -296,6 +302,17 @@ pci_dma_mapping_error(struct pci_dev *pd
 
 #define pci_set_dma_mask(x, y)                 0
 #define pci_set_consistent_dma_mask(x, y)      0
+
+static inline struct pci_dev *
+pci_get_class(pcireg_t class, struct pci_dev *pdev)
+{
+       return NULL;
+}
+
+#define PCI_CLASS_DISPLAY_VGA \
+    (PCI_CLASS_DISPLAY | PCI_SUBCLASS_DISPLAY_VGA)
+#define PCI_CLASS_DISPLAY_OTHER \
+    (PCI_CLASS_DISPLAY | PCI_SUBCLASS_DISPLAY_MISC)
 
 #endif /* defined(__amd64__) || defined(__i386__) */
 
Index: dev/pci/drm/radeon/radeon_acpi.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/radeon/radeon_acpi.c,v
retrieving revision 1.6
diff -u -p -r1.6 radeon_acpi.c
--- dev/pci/drm/radeon/radeon_acpi.c    14 Apr 2019 10:14:54 -0000      1.6
+++ dev/pci/drm/radeon/radeon_acpi.c    16 Aug 2019 20:05:56 -0000
@@ -1,3 +1,4 @@
+#define DRMDEBUG
 /*
  * Copyright 2012 Advanced Micro Devices, Inc.
  *
Index: dev/pci/drm/radeon/radeon_bios.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/radeon/radeon_bios.c,v
retrieving revision 1.15
diff -u -p -r1.15 radeon_bios.c
--- dev/pci/drm/radeon/radeon_bios.c    14 Apr 2019 10:14:54 -0000      1.15
+++ dev/pci/drm/radeon/radeon_bios.c    16 Aug 2019 20:05:56 -0000
@@ -42,10 +42,6 @@
 #include <machine/autoconf.h>
 #endif
 
-#ifdef __HAVE_ACPI
-#include "acpi.h"
-#endif
-
 /*
  * BIOS.
  */
@@ -737,10 +733,6 @@ static bool radeon_read_disabled_bios(st
        else
                return legacy_read_disabled_bios(rdev);
 }
-
-#if NACPI > 0
-#define CONFIG_ACPI
-#endif
 
 #ifdef CONFIG_ACPI
 static bool radeon_acpi_vfct_bios(struct radeon_device *rdev)

Reply via email to