drm/radeon: Add support for the ATIF ACPI method to the radeon driver
authorAlberto Milone <alberto.milone@canonical.com>
Tue, 6 Jul 2010 15:40:24 +0000 (11:40 -0400)
committerDave Airlie <airlied@redhat.com>
Sun, 1 Aug 2010 23:59:59 +0000 (09:59 +1000)
By calling the ATIF method in the radeon driver we can make sure
that hotkeys such as the video switch key emit ACPI events when
pressed.

agd5f: fix warning

Signed-off-by: Alberto Milone <alberto.milone@canonical.com>
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/radeon/Makefile
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_acpi.c [new file with mode: 0644]
drivers/gpu/drm/radeon/radeon_kms.c

index 84b1f2729d430deaddcf6e4241a1886339c0123b..aebe00875041448351bb129b7a131baab66f4e9e 100644 (file)
@@ -69,5 +69,6 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
 
 radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
 radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
+radeon-$(CONFIG_ACPI) += radeon_acpi.o
 
 obj-$(CONFIG_DRM_RADEON)+= radeon.o
index ab61aaa887bb449c486b59abccb89772b021f35a..a5c1a3e9dd3976ad9569d4de7a78a9e8a3db82f2 100644 (file)
@@ -1414,6 +1414,13 @@ extern void r700_cp_fini(struct radeon_device *rdev);
 extern void evergreen_disable_interrupt_state(struct radeon_device *rdev);
 extern int evergreen_irq_set(struct radeon_device *rdev);
 
+/* radeon_acpi.c */ 
+#if defined(CONFIG_ACPI) 
+extern int radeon_acpi_init(struct radeon_device *rdev); 
+#else 
+static inline int radeon_acpi_init(struct radeon_device *rdev) { return 0; } 
+#endif 
+
 /* evergreen */
 struct evergreen_mc_save {
        u32 vga_control[6];
diff --git a/drivers/gpu/drm/radeon/radeon_acpi.c b/drivers/gpu/drm/radeon/radeon_acpi.c
new file mode 100644 (file)
index 0000000..e366434
--- /dev/null
@@ -0,0 +1,67 @@
+#include <linux/pci.h>
+#include <linux/acpi.h>
+#include <linux/slab.h>
+#include <acpi/acpi_drivers.h>
+#include <acpi/acpi_bus.h>
+
+#include "drmP.h"
+#include "drm.h"
+#include "drm_sarea.h"
+#include "drm_crtc_helper.h"
+#include "radeon.h"
+
+#include <linux/vga_switcheroo.h>
+
+/* Call the ATIF method
+ *
+ * Note: currently we discard the output
+ */
+static int radeon_atif_call(acpi_handle handle)
+{
+       acpi_status status;
+       union acpi_object atif_arg_elements[2];
+       struct acpi_object_list atif_arg;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
+
+       atif_arg.count = 2;
+       atif_arg.pointer = &atif_arg_elements[0];
+
+       atif_arg_elements[0].type = ACPI_TYPE_INTEGER;
+       atif_arg_elements[0].integer.value = 0;
+       atif_arg_elements[1].type = ACPI_TYPE_INTEGER;
+       atif_arg_elements[1].integer.value = 0;
+
+       status = acpi_evaluate_object(handle, "ATIF", &atif_arg, &buffer);
+
+       /* Fail only if calling the method fails and ATIF is supported */
+       if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+               printk(KERN_INFO "failed to evaluate ATIF got %s\n", acpi_format_exception(status));
+               kfree(buffer.pointer);
+               return 1;
+       }
+
+       kfree(buffer.pointer);
+       return 0;
+}
+
+/* Call all ACPI methods here */
+int radeon_acpi_init(struct radeon_device *rdev)
+{
+       acpi_handle handle;
+       int ret;
+
+       /* No need to proceed if we're sure that ATIF is not supported */
+       if (!ASIC_IS_AVIVO(rdev) || !rdev->bios)
+               return 0;
+
+       /* Get the device handle */
+       handle = DEVICE_ACPI_HANDLE(&rdev->pdev->dev);
+
+       /* Call the ATIF method */
+       ret = radeon_atif_call(handle);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
index 6a70c0dc7f92dbb74cdf2e24ac986b14555ef177..70fda6361cd0a7b19f41c8394280e11d08e1dd38 100644 (file)
@@ -49,7 +49,7 @@ int radeon_driver_unload_kms(struct drm_device *dev)
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
 {
        struct radeon_device *rdev;
-       int r;
+       int r, acpi_status;
 
        rdev = kzalloc(sizeof(struct radeon_device), GFP_KERNEL);
        if (rdev == NULL) {
@@ -77,6 +77,12 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
                dev_err(&dev->pdev->dev, "Fatal error during GPU init\n");
                goto out;
        }
+
+       /* Call ACPI methods */
+       acpi_status = radeon_acpi_init(rdev);
+       if (acpi_status)
+               dev_err(&dev->pdev->dev, "Error during ACPI methods call\n");
+
        /* Again modeset_init should fail only on fatal error
         * otherwise it should provide enough functionalities
         * for shadowfb to run