--- /dev/null
+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 */
++