]> xenbits.xen.org Git - xenclient/ioemu-pq.git/commitdiff
Guest operating system driven brightness control support.
authorKamala Narasimhan <kamala.narasimhan@citrix.com>
Fri, 8 Jan 2010 20:12:22 +0000 (15:12 -0500)
committerKamala Narasimhan <kamala.narasimhan@citrix.com>
Fri, 8 Jan 2010 20:12:22 +0000 (15:12 -0500)
Respond to requests from virtual acpi layer output device to get supported brightness levels from
actual firmware.  This can be extended to support more output device requests in future.

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..ef76a78
--- /dev/null
@@ -0,0 +1,406 @@
+diff --git a/hw/acpi-video.h b/hw/acpi-video.h
+new file mode 100644
+index 0000000..3763241
+--- /dev/null
++++ b/hw/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 */
++
+diff --git a/hw/piix4acpi.c b/hw/piix4acpi.c
+index 3e48413..87fb2b3 100644
+--- a/hw/piix4acpi.c
++++ b/hw/piix4acpi.c
+@@ -30,6 +30,7 @@
+ #include "qemu-xen.h"
+ #include "battery_mgmt.h"
+ #include "xen_acpi_wmi.h"
++#include "xen_acpi_video.h"
+ #include "thermal_mgmt.h"
+ #include "switcher.h"
+@@ -213,6 +214,7 @@ static void acpi_map(PCIDevice *pci_dev, int region_num,
+     battery_mgmt_init(pci_dev);
+     xen_acpi_wmi_init(pci_dev);
++    xen_acpi_video_init(pci_dev);
+     thermal_mgmt_init(pci_dev);
+ }
+diff --git a/hw/xen_acpi_video.c b/hw/xen_acpi_video.c
+new file mode 100644
+index 0000000..ccef147
+--- /dev/null
++++ b/hw/xen_acpi_video.c
+@@ -0,0 +1,247 @@
++/*
++ * xen_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 as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++/* When well known output device object methods in virtual ACPI space are called,
++ * the guest delegate those requests to qemu and the below implementation in qemu
++ * talks to the actual firmware through dom0 kernel xen/acpi driver implementation 
++ * to cater to those guest level acpi requests.
++ */
++
++#include "hw.h"
++#include "pc.h"
++#include "qemu-xen.h"
++#include "isa.h"
++#include "xen_acpi_video.h"
++#include <sys/ioctl.h>
++
++#ifndef CONFIG_NO_XEN_ACPI_VIDEO
++
++static int xen_video_device = -ENODEV;
++extern FILE *logfile;
++
++static enum XEN_ACPI_VIDEO_COMMAND video_cmd_type = XEN_ACPI_VIDEO_CMD_NONE;
++static unsigned int num_brightness_levels = 0;
++static unsigned int *brightness_levels = NULL;
++static unsigned int current_index = 0; 
++
++/* #define XEN_ACPI_VIDEO_DEBUG */
++
++/*
++ * xen_acpi_video_get_num_brightness_levels
++ */
++unsigned int xen_acpi_video_get_num_brightness_levels(void)
++{
++    /* Our virtual acpi layer can only accomodate a package of 11 elements
++     * at this point which appear to be enough with the firmwares we have
++     * checked so far.  If that should change it is easy enough to 
++     * accomodate more and if such change become common place, we can then
++     * make asl package creation dynamic too.
++     */
++
++    if ( num_brightness_levels > 11 )
++    {
++        fprintf(logfile, "Truncating brightness levels to 11\n");
++        return 11;
++     }
++
++#ifdef XEN_ACPI_VIDEO_DEBUG
++    fprintf(logfile, "XEN VIDEO: Number of brightness levels - %d\n", num_brightness_levels);
++#endif
++
++    return num_brightness_levels;
++}
++
++/*
++ * xen_acpi_video_get_next_brightness_level
++ */
++unsigned int xen_acpi_video_get_next_brightness_level(void)
++{
++    if ( brightness_levels == NULL )
++    {
++        fprintf(logfile, "XEN VIDEO: Brightness levels array empty!\n");
++        return 0;
++    }
++
++    if ( current_index >= num_brightness_levels )
++    {
++        fprintf(logfile, "XEN VIDEO: Index overflow!\n");
++        return 0;
++    }
++
++#ifdef XEN_ACPI_VIDEO_DEBUG
++    fprintf(logfile, "XEN VIDEO: Level - %d\n", brightness_levels[current_index]);
++#endif
++
++    return brightness_levels[current_index++];
++}
++
++/*
++ * xen_acpi_video_port_readb
++ */
++static uint32_t xen_acpi_video_port_readb(void *opaque, uint32_t addr)
++{
++#ifdef XEN_ACPI_VIDEO_DEBUG
++    fprintf(logfile, "XEN VIDEO: In video port read\n");
++#endif
++
++    switch ( video_cmd_type )
++    {
++        case XEN_ACPI_VIDEO_GET_NUM_LEVELS:
++            return xen_acpi_video_get_num_brightness_levels();
++        case XEN_ACPI_VIDEO_GET_LEVLES:
++            return xen_acpi_video_get_next_brightness_level();
++        case XEN_ACPI_VIDEO_CMD_NONE:
++        default:
++            fprintf(logfile, "XEN VIDEO: Unknown request - %d\n",
++                video_cmd_type);
++            break;
++    }
++
++    return 0;
++}
++
++/*
++ * xen_acpi_video_port_writeb
++ */
++static void xen_acpi_video_port_writeb(void *opaque, uint32_t addr, uint32_t val)
++{
++    video_cmd_type = val;
++    if ( val == XEN_ACPI_VIDEO_CMD_NONE )
++        current_index = 0;
++
++#ifdef XEN_ACPI_VIDEO_DEBUG
++    fprintf(logfile, "XEN VIDEO: In video port write, command - %d\n", video_cmd_type);
++#endif
++}
++
++/*
++ * xen_acpi_video_initialize_brightness_info
++ */
++void xen_acpi_video_initialize_brightness_info(void)
++{
++    int ret;
++    xen_video_data_t video_data;
++
++#ifdef XEN_ACPI_VIDEO_DEBUG
++    unsigned int count;
++#endif
++
++    video_data.buffer_size = sizeof(uint);
++    video_data.out_buf = malloc(video_data.buffer_size);
++    if (video_data.out_buf == NULL )
++    {
++        fprintf(logfile, "XEN VIDEO: Allocation failure!\n");
++        return;
++    }
++
++    ret = ioctl(xen_video_device, XEN_ACPI_VIDEO_GET_NUM_LEVELS, &video_data);
++    if ( ret != XEN_VIDEO_SUCCESS || video_data.out_buf == NULL )
++    {
++        fprintf(logfile, "XEN VIDEO:  Unable to get number of brightness levels - %d\n",
++            ret);
++        free(video_data.out_buf);
++        video_data.out_buf = NULL;
++        return;
++    }
++
++    num_brightness_levels = *video_data.out_buf;
++    free(video_data.out_buf);
++
++    video_data.buffer_size = num_brightness_levels * sizeof(uint);
++    video_data.out_buf = malloc(video_data.buffer_size);
++    if ( video_data.out_buf == NULL )
++    {
++        num_brightness_levels = 0;
++        fprintf(logfile, "XEN VIDEO: Allocation failure!\n");
++        return;
++    }
++
++    memset(video_data.out_buf, 0, video_data.buffer_size);
++    ret = ioctl(xen_video_device, XEN_ACPI_VIDEO_GET_LEVLES, &video_data);
++    if (ret != XEN_VIDEO_SUCCESS )
++    {
++        num_brightness_levels = 0;
++        free(video_data.out_buf);
++        video_data.out_buf = NULL;
++        fprintf(logfile, "XEN VIDEO: Unable to get brigtness levels - %d\n");
++        return;
++    }
++
++    brightness_levels = video_data.out_buf;
++
++#ifdef XEN_ACPI_VIDEO_DEBUG
++    fprintf(logfile, "XEN VIDEO: Initialize brightness info succeeded!\n");
++    fprintf(logfile, "XEN VIDEO: Number of brightness levels - %d\n", num_brightness_levels);
++    fprintf(logfile, "XEN VIDEO: Brightness levels -");
++    for (count = 0; count < num_brightness_levels; count++)
++        fprintf(logfile, "  %d", brightness_levels[count]);
++    fprintf(logfile, "\n");
++#endif
++}
++
++/*
++ * xen_acpi_video_init
++ */
++void xen_acpi_video_init(PCIDevice *device)
++{
++    char dev_name[64];
++
++    sprintf(dev_name, "/dev/%s", XEN_VIDEO_DEVICE_NAME);
++    xen_video_device = open(dev_name, 0);
++    if ( xen_video_device < 0 )
++    {
++        fprintf(logfile, "XEN VIDEO: Unable to open device - %s\n", XEN_VIDEO_DEVICE_NAME);
++        return;
++    }
++
++    register_ioport_read(XEN_ACPI_VIDEO_PORTB, 1, 1, xen_acpi_video_port_readb, device);
++    register_ioport_write(XEN_ACPI_VIDEO_PORTB, 1, 1, xen_acpi_video_port_writeb, device);
++
++    xen_acpi_video_initialize_brightness_info();
++
++#ifdef XEN_ACPI_VIDEO_DEBUG
++    fprintf(logfile, "XEN VIDEO: Xen acpi video registration succeeded!!!\n");
++#endif
++}
++
++/*
++ * xen_acpi_video_cleanup(void)
++ */
++void xen_acpi_video_cleanup(void)
++{
++    if ( xen_video_device > 0 )
++        close(xen_video_device);
++
++    num_brightness_levels = 0;
++    if ( brightness_levels != NULL )
++    {
++        free(brightness_levels);
++        brightness_levels = NULL;
++    }
++}
++
++#else
++
++void xen_acpi_video_init(PCIDevice *device) { }
++void xen_acpi_video_cleanup(void) { }
++
++#endif /* CONFIG_NO_XEN_ACPI_VIDEO */
++
+diff --git a/hw/xen_acpi_video.h b/hw/xen_acpi_video.h
+new file mode 100644
+index 0000000..fd77443
+--- /dev/null
++++ b/hw/xen_acpi_video.h
+@@ -0,0 +1,50 @@
++/*
++ * xen_acpi_video.h
++ *
++ * 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 as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#ifndef _XEN_ACPI_VIDEO_H
++#define _XEN_ACPI_VIDEO_H
++
++#ifdef CONFIG_STUBDOM
++#define CONFIG_NO_XEN_ACPI_VIDEO
++#endif
++
++#include "acpi-video.h"
++
++#define XEN_ACPI_VIDEO_PORTB 0x94
++
++/* Values written to VIDEO command port */
++enum XEN_ACPI_VIDEO_COMMAND 
++{ 
++    XEN_ACPI_VIDEO_GET_NUM_LEVELS = 100,
++    XEN_ACPI_VIDEO_GET_LEVLES,
++    XEN_ACPI_VIDEO_CMD_NONE,
++};
++
++void xen_acpi_video_init(PCIDevice *device);
++void xen_acpi_video_cleanup(void);
++
++#ifndef CONFIG_NO_XEN_ACPI_VIDEO
++    void xen_acpi_video_initialize_brightness_info(void);
++    unsigned int xen_acpi_video_get_num_brightness_levels(void);
++    unsigned int xen_acpi_video_get_next_brightness_level(void);
++#endif
++
++#endif /* _XEN_ACPI_VIDEO_H */
+diff --git a/xen-hooks.mak b/xen-hooks.mak
+index 88aff50..546d37f 100644
+--- a/xen-hooks.mak
++++ b/xen-hooks.mak
+@@ -36,6 +36,7 @@ OBJS += pci_emulation.o
+ OBJS += helper2.o
+ OBJS += battery_mgmt.o
+ OBJS += xen_acpi_wmi.o
++OBJS += xen_acpi_video.o
+ OBJS += thermal_mgmt.o
+ OBJS += switcher.o
+ OBJS += intel.o
index 9abe27c21011cebb295689cf5e38336ee98653e0..b08db3331de0381660cbcab2489c5bfb6500d7cf 100644 (file)
@@ -33,3 +33,4 @@ hide-msi-capability-for-igfx
 vga-edid
 tidy-muticies-in-ata-pt
 alsa-fix-resume
+guest-os-controlled-brightness-support