]> xenbits.xen.org Git - xenclient/linux-2.6.27-pq.git/commitdiff
Guest operating system driven brightness control support. master
authorKamala Narasimhan <kamala.narasimhan@citrix.com>
Fri, 8 Jan 2010 21:37:50 +0000 (16:37 -0500)
committerKamala Narasimhan <kamala.narasimhan@citrix.com>
Fri, 8 Jan 2010 21:37:50 +0000 (16:37 -0500)
Xen acpi video driver implementation to interface between qemu and linux
acpi video driver.

master/guest-os-controlled-brightness-support [new file with mode: 0644]
master/series

diff --git a/master/guest-os-controlled-brightness-support b/master/guest-os-controlled-brightness-support
new file mode 100644 (file)
index 0000000..bf12d2f
--- /dev/null
@@ -0,0 +1,415 @@
+diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
+index 8f2c530..a2c87d8 100644
+--- a/drivers/acpi/video.c
++++ b/drivers/acpi/video.c
+@@ -283,6 +283,8 @@ static char device_decode[][30] = {
+       "UNKNOWN",
+ };
++static struct acpi_video_device_brightness lcd_device_brightness;
++
+ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data);
+ static void acpi_video_device_rebind(struct acpi_video_bus *video);
+ static void acpi_video_device_bind(struct acpi_video_bus *video,
+@@ -693,6 +695,14 @@ acpi_video_init_brightness(struct acpi_video_device *device)
+               count++;
+       }
++        if ( count >=2 && lcd_device_brightness.levels == NULL ) {
++            lcd_device_brightness.levels = kmalloc(count * sizeof(int), GFP_KERNEL);
++            if ( lcd_device_brightness.levels ) {
++                memcpy(lcd_device_brightness.levels, br->levels, count * sizeof(int));
++                lcd_device_brightness.count = count;
++            }
++        }
++
+       /* don't sort the first two brightness levels */
+       sort(&br->levels[2], count - 2, sizeof(br->levels[2]),
+               acpi_video_cmp_level, NULL);
+@@ -2136,10 +2146,30 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type)
+       return 0;
+ }
++unsigned int acpi_video_get_num_brightness_levels(void)
++{
++        return lcd_device_brightness.count;
++}
++EXPORT_SYMBOL(acpi_video_get_num_brightness_levels);
++
++acpi_status acpi_video_get_brigtness_levels(unsigned int *levels, unsigned int size)
++{
++        if ( lcd_device_brightness.levels == NULL)
++            return AE_ERROR;
++
++        if ( (levels == NULL) || (size < lcd_device_brightness.count * sizeof(int)) )
++            return AE_NO_MEMORY;
++
++        memcpy(levels, lcd_device_brightness.levels, lcd_device_brightness.count * sizeof(int));
++        return AE_OK;
++}
++EXPORT_SYMBOL(acpi_video_get_brigtness_levels);
++
+ static int __init acpi_video_init(void)
+ {
+       int result = 0;
++        memset(&lcd_device_brightness, 0, sizeof(lcd_device_brightness));
+       /*
+          acpi_dbg_level = 0xFFFFFFFF;
+@@ -2167,6 +2197,11 @@ static void __exit acpi_video_exit(void)
+       remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
++        if ( lcd_device_brightness.levels != NULL ) {
++            kfree(lcd_device_brightness.levels);
++            lcd_device_brightness.count = 0;
++        }
++
+       return;
+ }
+diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
+index bc14812..86f1a2b 100644
+--- a/drivers/xen/Kconfig
++++ b/drivers/xen/Kconfig
+@@ -325,6 +325,17 @@ config XEN_ACPI_WMI_WRAPPER
+           Facilitates OEM specific hotkey implementation within
+           guest space.
++config XEN_ACPI_VIDEO
++        tristate "Xen Video"
++        depends on X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL && XEN
++        depends on INPUT
++        depends on ACPI_VIDEO
++        help
++          Minimal Xen ACPI video driver implementation to query for a list of
++          brightness control levels from the firmware and communicate it to the
++          virtual firmware and to set and get current brightness level from the
++          firmware based on request from the virtual firmware.
++
+ source "drivers/xen/v2v/Kconfig"
+           
+ choice
+diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
+index 465d341..6a7fc84 100644
+--- a/drivers/xen/Makefile
++++ b/drivers/xen/Makefile
+@@ -31,5 +31,6 @@ obj-$(CONFIG_XEN_NETDEV_ACCEL_SFC_UTIL)              += sfc_netutil/
+ obj-$(CONFIG_XEN_NETDEV_ACCEL_SFC_FRONTEND)   += sfc_netfront/
+ obj-$(CONFIG_XEN_NETDEV_ACCEL_SFC_BACKEND)    += sfc_netback/
+ obj-$(CONFIG_XEN_ACPI_WMI_WRAPPER)              += acpi-wmi/
++obj-$(CONFIG_XEN_ACPI_VIDEO)                    += acpi-video/
+ obj-$(CONFIG_XEN_NETCHANNEL2)          += netchannel2/
+ obj-$(CONFIG_XEN_V2V)          += v2v/
+diff --git a/drivers/xen/acpi-video/Makefile b/drivers/xen/acpi-video/Makefile
+new file mode 100644
+index 0000000..e54a29d
+--- /dev/null
++++ b/drivers/xen/acpi-video/Makefile
+@@ -0,0 +1,3 @@
++
++obj-y := acpi-video.o
++
+diff --git a/drivers/xen/acpi-video/acpi-video.c b/drivers/xen/acpi-video/acpi-video.c
+new file mode 100644
+index 0000000..b9a1e3d
+--- /dev/null
++++ b/drivers/xen/acpi-video/acpi-video.c
+@@ -0,0 +1,213 @@
++/******************************************************************************
++ * drivers/xen/acpi-video/acpi-video.c
++ *
++ * Copyright (c) 2009 Kamala Narasimhan
++ * Copyright (c) 2009 Citrix Systems, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (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
++ * AUTHORS OR COPYRIGHT HOLDERS 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.
++ */
++
++/* This module receives ioctl request from qemu xen-acpi-video implementation,
++ * talks to linux-acpi-video driver to get relevant firmware information
++ * and returns that to qemu which in turn responds back to the virtual firmware
++ * with the same information.  Currently, we get request for brightness levels alone
++ * but this could be easily extended in future to support more output/video device
++ * level information.
++ */
++
++#include <linux/module.h>
++#include <linux/miscdevice.h>
++#include <linux/acpi.h>
++#include <asm/uaccess.h>
++#include <xen/public/acpi-video.h>
++
++/* #define XEN_VIDEO_DEBUG */
++
++static bool xen_video_misc_dev_registered = false;
++static int xen_video_ioctl(struct inode *inode, struct file *filp,
++                         unsigned int cmd, unsigned long arg);
++
++static struct file_operations xen_video_fops = {
++    .owner = THIS_MODULE,
++    .ioctl = xen_video_ioctl,
++};
++
++static struct miscdevice xen_video_misc = {
++        .minor    = MISC_DYNAMIC_MINOR,
++        .name     = XEN_VIDEO_DEVICE_NAME,
++        .fops     = &xen_video_fops,
++};
++
++/*
++ * xen_video_num_brightness_levels
++ */
++int xen_video_num_brightness_levels(xen_video_data_t *video_data)
++{
++    unsigned int num_levels;
++
++    if ( video_data->buffer_size < sizeof(unsigned int) )
++    {
++        printk("Xen Video: Not enough memory!\n");
++        return XEN_VIDEO_NOT_ENOUGH_MEMORY;
++    }
++    
++    num_levels = acpi_video_get_num_brightness_levels();
++    if ( num_levels == 0 )
++    {
++        printk("XEN Video: Unable to get brightness levels\n");
++        return XEN_VIDEO_EFAULT;
++    }
++
++    if ( copy_to_user((char __user *) video_data->out_buf, &num_levels, sizeof(unsigned int)) )
++    {
++        printk("XEN Video: Invalid user buffer\n");
++        return XEN_VIDEO_NOT_ENOUGH_MEMORY;
++    }
++
++#ifdef XEN_VIDEO_DEBUG
++    printk("XEN Video: Returning number of brightness levels - %d\n", num_levels);
++#endif
++    return XEN_VIDEO_SUCCESS;
++}
++
++/*
++ * xen_video_brightness_levels
++ */
++int xen_video_brightness_levels(xen_video_data_t *video_data)
++{
++    int ret;
++    unsigned int *levels, num_levels;
++
++    if (  video_data->out_buf == NULL )
++    {
++        printk("XEN Video: Output buffer is null!\n");
++        return XEN_VIDEO_NOT_ENOUGH_MEMORY;
++    }
++
++    num_levels = acpi_video_get_num_brightness_levels();
++    if ( num_levels == 0 )
++        return XEN_VIDEO_EFAULT;
++
++    if ( video_data->buffer_size < num_levels * sizeof(unsigned int) )
++    {
++        printk("Xen Video: Not enough memory!\n");
++        return XEN_VIDEO_NOT_ENOUGH_MEMORY;
++    }
++
++    levels = kmalloc(video_data->buffer_size, GFP_KERNEL);
++    if ( levels == NULL )
++    {
++        printk("XEN Video: Allocation failure!\n");
++        return XEN_VIDEO_NOT_ENOUGH_MEMORY;
++    }
++ 
++    ret = acpi_video_get_brigtness_levels(levels, video_data->buffer_size);
++    if ( ret != XEN_VIDEO_SUCCESS )
++    {
++        kfree(levels);
++        return ret;
++    }
++
++    if ( copy_to_user((char __user *) video_data->out_buf, levels, video_data->buffer_size) )
++    {
++        printk("XEN Video: Invalid user buffer\n");
++        kfree(levels);
++        return XEN_VIDEO_NOT_ENOUGH_MEMORY;
++    }
++
++    kfree(levels);
++#ifdef XEN_VIDEO_DEBUG
++    printk("XEN Video: xen_video_brightness_levels succeeded!\n");
++#endif
++    return XEN_VIDEO_SUCCESS;
++}
++
++/*
++ * xen_video_ioctl
++ */
++static int xen_video_ioctl(struct inode *inode, struct file *filp,
++                         unsigned int cmd, unsigned long arg)
++{
++    xen_video_data_t video_data;
++
++#ifdef XEN_VIDEO_DEBUG
++    printk("XEN VIDEO:  In xen_video_ioctl - %d\n", cmd);
++#endif
++
++    memset(&video_data, 0, sizeof(video_data));
++    if ( copy_from_user(&video_data, (char __user *)arg, sizeof(xen_video_data_t)) )
++    {
++        printk("XEN Video: Invalid object invocation parameter\n");
++        return XEN_VIDEO_EFAULT;
++    }
++
++    switch ( cmd )
++    {
++        case XEN_VIDEO_IOCTL_NUM_BRIGHTNESS_LEVELS:
++            return xen_video_num_brightness_levels(&video_data);
++        case XEN_VIDEO_IOCTL_BRIGHTNESS_LEVELS:
++            return xen_video_brightness_levels(&video_data);
++    }
++
++    return XEN_VIDEO_ENOIOCTLCMD;
++}
++
++/*
++ * xen_video_init
++ */
++static int __init xen_video_init(void)
++{
++    int ret;
++
++    ret = misc_register(&xen_video_misc);
++    if ( ret < 0 )
++        printk("XEN Video: misc_register failed with error - %d\n", ret);
++    else
++        xen_video_misc_dev_registered = true;
++
++#ifdef XEN_VIDEO_DEBUG
++    printk("XEN Video: xen-acpi-video misc_register succeeded!\n");
++#endif
++    return ret;
++}
++
++/*
++ * xen_video_exit
++ */
++static void xen_video_exit(void)
++{
++    int ret;
++
++    if ( xen_video_misc_dev_registered == false )
++        return;
++
++    if ( (ret = misc_deregister(&xen_video_misc)) < 0 )
++        printk("XEN VIDEO: misc_deregister failed with error - %d\n", ret);
++}
++
++module_init(xen_video_init);
++module_exit(xen_video_exit);
++MODULE_LICENSE("Dual BSD/GPL");
++
+diff --git a/include/linux/acpi.h b/include/linux/acpi.h
+index cd5c2be..fcf11a7 100644
+--- a/include/linux/acpi.h
++++ b/include/linux/acpi.h
+@@ -202,6 +202,13 @@ extern bool wmi_has_guid(const char *guid);
+ #endif        /* CONFIG_ACPI_WMI */
++#if defined(CONFIG_ACPI_VIDEO)
++
++extern unsigned int acpi_video_get_num_brightness_levels(void);
++extern acpi_status acpi_video_get_brigtness_levels(unsigned int *levels, unsigned int size);
++
++#endif /* CONFIG_ACPI_VIDEO */
++
+ #define ACPI_VIDEO_OUTPUT_SWITCHING                   0x0001
+ #define ACPI_VIDEO_DEVICE_POSTING                     0x0002
+ #define ACPI_VIDEO_ROM_AVAILABLE                      0x0004
+diff --git a/include/xen/public/acpi-video.h b/include/xen/public/acpi-video.h
+new file mode 100644
+index 0000000..3763241
+--- /dev/null
++++ b/include/xen/public/acpi-video.h
+@@ -0,0 +1,59 @@
++/******************************************************************************
++ * acpi-video.h
++ *
++ * Interface to /proc/misc/xen-acpi-video
++ *
++ * Copyright (c) 2009 Kamala Narasimhan
++ * Copyright (c) 2009 Citrix Systems, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (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
++ * AUTHORS OR COPYRIGHT HOLDERS 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.
++ */
++
++
++#ifndef _XEN_ACPI_VIDEO
++#define _XEN_ACPI_VIDEO
++
++/*
++ * Userspace Interface
++ */
++
++#define XEN_VIDEO_DEVICE_NAME                  "xen-acpi-video"
++#define XEN_VIDEO_GUID_SIZE                    16
++
++#define XEN_VIDEO_SUCCESS                      0
++#define XEN_VIDEO_EFAULT                      -14
++#define XEN_VIDEO_NOT_ENOUGH_MEMORY           -12
++#define XEN_VIDEO_ENOIOCTLCMD                 -515
++
++#define XEN_VIDEO_IOCTL_NUM_BRIGHTNESS_LEVELS  100
++#define XEN_VIDEO_IOCTL_BRIGHTNESS_LEVELS      101
++
++typedef struct xen_video_data {
++            uint  buffer_size;
++            uint  *out_buf;
++} xen_video_data_t;
++
++#endif /* _XEN_ACPI_VIDEO */
++
index 5a5c7815312bcf547e4db94c48fd021eb18f276c..8d68cc40c65bc2ba5e583b93ab3f815e925cbed9 100644 (file)
@@ -360,3 +360,4 @@ v2v-dev
 v2v-fix-disconnect
 v2v-dev-ringsizes
 netback-tcpchecksum-fix
+guest-os-controlled-brightness-support