Hello again, Sending toshiba acpi patch as Paul has suggested. Regards, Javier.
On Tue, Jun 14, 2011 at 04:04:19PM +0300, Paul Irofti wrote: > On Tue, Jun 14, 2011 at 11:38:45AM +0200, Javier Vazquez wrote: > > Hello Everybody, > > > > I installed OpenBSD 4.9 current in my old Toshiba M30. Although, > > there was not LCD brightness control, so I started to do something > > about > > it, taking into account the Toshiba acpi support of FreeBSD. > > http://fxr.watson.org/fxr/source/dev/acpi_support/acpi_toshiba.c > > > > Successfully, I can manage the LCD brightness level using wsconsctl(8). > > > > wsconsctl display.brightness=100. ;) works nicely by command > > line as well by setting the brightness level in /etc/wsconsctl.conf > > file. > > > > I attached the required patch files for testing. I hope can be > > useful for other guys using toshiba laptops as I added the > > Libretto and Dynabook models. > > > > Thanks to Paul for coaching me to provide a decent patch :). > > You should have done: > > $ cd /sys/dev/acpi > $ cvs add acpitoshiba.c > $ cd /sys > $ cvs diff -uNp <files> > > So that you can supply one easy patch for people to test. > > Also, the comment about the && instead of || is correct. > > People with Toshiba's should test this and report back if this works for > them or not. > > The 'WARN: not a buffer' AML message is a known issue and jordan@ is > looking into it. ? toshiba_acpi.patch Index: arch/amd64/conf/GENERIC =================================================================== RCS file: /cvs/src/sys/arch/amd64/conf/GENERIC,v retrieving revision 1.319 diff -u -p -r1.319 GENERIC --- arch/amd64/conf/GENERIC 30 May 2011 22:03:47 -0000 1.319 +++ arch/amd64/conf/GENERIC 14 Jun 2011 20:02:40 -0000 @@ -52,6 +52,7 @@ acpimcfg* at acpi? acpiasus* at acpi? acpisony* at acpi? acpithinkpad* at acpi? +acpitoshiba* at acpi? acpivideo* at acpi? acpivout* at acpivideo? acpipwrres* at acpi? Index: arch/i386/conf/GENERIC =================================================================== RCS file: /cvs/src/sys/arch/i386/conf/GENERIC,v retrieving revision 1.716 diff -u -p -r1.716 GENERIC --- arch/i386/conf/GENERIC 30 May 2011 22:03:47 -0000 1.716 +++ arch/i386/conf/GENERIC 14 Jun 2011 20:02:41 -0000 @@ -62,6 +62,7 @@ acpitz* at acpi? acpiasus* at acpi? acpisony* at acpi? acpithinkpad* at acpi? +acpitoshiba* at acpi? acpivideo* at acpi? acpivout* at acpivideo? acpipwrres* at acpi? Index: dev/acpi/acpi.c =================================================================== RCS file: /cvs/src/sys/dev/acpi/acpi.c,v retrieving revision 1.224 diff -u -p -r1.224 acpi.c --- dev/acpi/acpi.c 27 Apr 2011 20:55:42 -0000 1.224 +++ dev/acpi/acpi.c 14 Jun 2011 20:02:44 -0000 @@ -93,6 +93,7 @@ void acpi_pbtn_task(void *, int); #ifndef SMALL_KERNEL int acpi_thinkpad_enabled; +int acpi_toshiba_enabled; int acpi_saved_spl; int acpi_enabled; @@ -781,8 +782,8 @@ acpi_attach(struct device *parent, struc /* check if we're running on a sony */ aml_find_node(&aml_root, "GBRT", acpi_foundsony, sc); - /* attach video only if this is not a stinkpad */ - if (!acpi_thinkpad_enabled) + /* attach video only if this is not a stinkpad or toshiba */ + if (!acpi_thinkpad_enabled || !acpi_toshiba_enabled) aml_find_node(&aml_root, "_DOS", acpi_foundvideo, sc); /* create list of devices we want to query when APM come in */ @@ -2334,6 +2335,13 @@ acpi_foundhid(struct aml_node *node, voi acpi_thinkpad_enabled = 1; } else if (!strcmp(dev, ACPI_DEV_ASUSAIBOOSTER)) aaa.aaa_name = "aibs"; + else if (!strcmp(dev, ACPI_DEV_TOSHIBA_LIBRETTO) || + !strcmp(dev, ACPI_DEV_TOSHIBA_DYNABOOK) || + !strcmp(dev, ACPI_DEV_TOSHIBA_SPA40)) { + aaa.aaa_name = "acpitoshiba"; + acpi_toshiba_enabled = 1; + } + if (aaa.aaa_name) config_found(self, &aaa, acpi_print); Index: dev/acpi/acpireg.h =================================================================== RCS file: /cvs/src/sys/dev/acpi/acpireg.h,v retrieving revision 1.25 diff -u -p -r1.25 acpireg.h --- dev/acpi/acpireg.h 27 Apr 2011 20:55:42 -0000 1.25 +++ dev/acpi/acpireg.h 14 Jun 2011 20:02:44 -0000 @@ -716,5 +716,8 @@ struct acpi_ivrs { #define ACPI_DEV_IBM "IBM0068" /* IBM ThinkPad support */ #define ACPI_DEV_LENOVO "LEN0068" /* Lenovo ThinkPad support */ #define ACPI_DEV_ASUSAIBOOSTER "ATK0110" /* ASUSTeK AI Booster */ +#define ACPI_DEV_TOSHIBA_LIBRETTO "TOS6200" /* Toshiba Libretto support */ +#define ACPI_DEV_TOSHIBA_DYNABOOK "TOS6207" /* Toshiba Dynabook support */ +#define ACPI_DEV_TOSHIBA_SPA40 "TOS6208" /* Toshiba SPA40 support */ #endif /* !_DEV_ACPI_ACPIREG_H_ */ Index: dev/acpi/acpitoshiba.c =================================================================== RCS file: dev/acpi/acpitoshiba.c diff -N dev/acpi/acpitoshiba.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dev/acpi/acpitoshiba.c 14 Jun 2011 20:02:45 -0000 @@ -0,0 +1,529 @@ +/*- + * Copyright (c) 2003 Hiroyuki Aizu <a...@navi.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> + +#include <dev/acpi/acpireg.h> +#include <dev/acpi/acpivar.h> +#include <dev/acpi/acpidev.h> +#include <dev/acpi/amltypes.h> +#include <dev/acpi/dsdt.h> + +#include <machine/apmvar.h> +#include <dev/wscons/wsconsio.h> + +/* + * Toshiba HCI interface definitions + * + * HCI is Toshiba's "Hardware Control Interface" which is supposed to + * be uniform across all their models. Ideally we would just call + * dedicated ACPI methods instead of using this primitive interface. + * However, the ACPI methods seem to be incomplete in some areas (for + * example they allow setting, but not reading, the LCD brightness + * value), so this is still useful. + */ +#define METHOD_HCI "GHCI" +#define METHOD_HCI_ENABLE "ENAB" + +/* Operations */ +#define HCI_SET 0xFF00 +#define HCI_GET 0xFE00 + +/* Functions */ +#define HCI_REG_SYSTEM_EVENT 0x0016 +#define HCI_REG_VIDEO_OUTPUT 0x001C +#define HCI_REG_LCD_BRIGHTNESS 0x002A + +/* Field definitions */ +#define HCI_LCD_BRIGHTNESS_BITS 3 +#define HCI_LCD_BRIGHTNESS_SHIFT (16 - HCI_LCD_BRIGHTNESS_BITS) +#define HCI_LCD_BRIGHTNESS_MAX ((1 << HCI_LCD_BRIGHTNESS_BITS) - 1) +#define HCI_LCD_BRIGHTNESS_MIN 0 +#define HCI_VIDEO_OUTPUT_FLAG 0x0100 +#define HCI_VIDEO_OUTPUT_CYCLE_MIN 0 +#define HCI_VIDEO_OUTPUT_CYCLE_MAX 7 + +/* HCI register definitions */ +#define HCI_WORDS 6 /* Number of register */ +#define HCI_REG_AX 0 /* Operation, then return value */ +#define HCI_REG_BX 1 /* Function */ +#define HCI_REG_CX 2 /* Argument (in or out) */ + +/* Return codes */ +#define HCI_FAILURE -1 +#define HCI_SUCCESS 0 + +/* Toshiba fn_keys events */ +#define FN_KEY_VIDEO_OUTPUT 0x01BF +#define FN_KEY_BRIGHTNESS_DOWN 0x01C0 +#define FN_KEY_BRIGHTNESS_UP 0x01C1 + +struct acpitoshiba_softc { + struct device sc_dev; + struct acpi_softc *sc_acpi; + struct aml_node *sc_devnode; +}; + +int toshiba_enable_events(struct acpitoshiba_softc *); +int toshiba_read_events(struct acpitoshiba_softc *); +int toshiba_match(struct device *, void *, void *); +void toshiba_attach(struct device *, struct device *, void *); +int toshiba_hotkey(struct aml_node *, int, void *); +int toshiba_get_brightness(struct acpitoshiba_softc *, u_int32_t *); +int toshiba_set_brightness(struct acpitoshiba_softc *, u_int32_t *); +int toshiba_get_video_output(struct acpitoshiba_softc *, u_int32_t *); +int toshiba_set_video_output(struct acpitoshiba_softc *, u_int32_t *); +int toshiba_find_brightness(struct acpitoshiba_softc *, int *); +int toshiba_fn_key_brightness_up(struct acpitoshiba_softc *); +int toshiba_fn_key_brightness_down(struct acpitoshiba_softc *); +int toshiba_fn_key_video_output(struct acpitoshiba_softc *); + +/* wconsole hook functions */ +int acpitoshiba_get_param(struct wsdisplay_param *); +int acpitoshiba_set_param(struct wsdisplay_param *); +extern int (*ws_get_param)(struct wsdisplay_param *); +extern int (*ws_set_param)(struct wsdisplay_param *); +int get_param_brightness(struct wsdisplay_param *); +int set_param_brightness(struct wsdisplay_param *); + +struct cfattach acpitoshiba_ca = { + sizeof(struct acpitoshiba_softc), toshiba_match, toshiba_attach +}; + +struct cfdriver acpitoshiba_cd = { + NULL, "acpitoshiba", DV_DULL +}; + +int +get_param_brightness(struct wsdisplay_param *dp) +{ + struct acpitoshiba_softc *sc = NULL; + int i, ret; + + for (i = 0; i < acpitoshiba_cd.cd_ndevs; i++) { + if (acpitoshiba_cd.cd_devs[i] == NULL) + continue; + + sc = (struct acpitoshiba_softc *)acpitoshiba_cd.cd_devs[i]; + } + + if (sc != NULL) { + rw_enter_write(&sc->sc_acpi->sc_lck); + + /* default settings */ + dp->min = HCI_LCD_BRIGHTNESS_MIN; + dp->max = HCI_LCD_BRIGHTNESS_MAX; + + ret = toshiba_get_brightness(sc, &dp->curval); + + rw_exit_write(&sc->sc_acpi->sc_lck); + + if ((dp->curval != -1) && (ret != HCI_FAILURE) ) + return (0); + } + + return (1); +} + +int +acpitoshiba_get_param(struct wsdisplay_param *dp) +{ + int ret; + + switch (dp->param) { + case WSDISPLAYIO_PARAM_BRIGHTNESS: + ret = get_param_brightness(dp); + return (ret); + default: + return (1); + } +} + +int +set_param_brightness(struct wsdisplay_param *dp) +{ + struct acpitoshiba_softc *sc = NULL; + int i, ret; + + for (i = 0; i < acpitoshiba_cd.cd_ndevs; i++) { + if (acpitoshiba_cd.cd_devs[i] == NULL) + continue; + + sc = (struct acpitoshiba_softc *)acpitoshiba_cd.cd_devs[i]; + } + + if (sc != NULL) { + rw_enter_write(&sc->sc_acpi->sc_lck); + ret = toshiba_find_brightness(sc, &dp->curval); + rw_exit_write(&sc->sc_acpi->sc_lck); + + if ((dp->curval != -1) && ( ret != HCI_FAILURE)) + return (0); + + } + + return (1); +} + +int +acpitoshiba_set_param(struct wsdisplay_param *dp) +{ + int ret; + + switch (dp->param) { + case WSDISPLAYIO_PARAM_BRIGHTNESS: + ret = set_param_brightness(dp); + return (ret); + default: + return (1); + } +} + +int +toshiba_find_brightness(struct acpitoshiba_softc *sc, int *new_blevel) +{ + int ret, current_blevel; + + ret = toshiba_get_brightness(sc, ¤t_blevel); + if ( ret != HCI_SUCCESS) + return (1); + + if ( current_blevel != *new_blevel) { + if ( *new_blevel >= HCI_LCD_BRIGHTNESS_MAX) + *new_blevel = current_blevel = HCI_LCD_BRIGHTNESS_MAX; + else if (*new_blevel <= HCI_LCD_BRIGHTNESS_MIN) + *new_blevel = current_blevel = HCI_LCD_BRIGHTNESS_MIN; + else + current_blevel = *new_blevel; + + ret = toshiba_set_brightness(sc, ¤t_blevel); + if ( ret != HCI_SUCCESS) + return (1); + } + + return (0); +} + +int +toshiba_match(struct device *parent, void *match, void *aux) +{ + struct acpi_attach_args *aa = aux; + struct cfdata *cf = match; + + if ( aa->aaa_name == NULL || + strcmp(aa->aaa_name, cf->cf_driver->cd_name) != 0 || + aa->aaa_table != NULL) + return (0); + + return (1); + +} + +int +toshiba_enable_events(struct acpitoshiba_softc *sc) +{ + if (aml_evalname(sc->sc_acpi, sc->sc_devnode, METHOD_HCI_ENABLE, + 0, NULL, NULL)) { + printf("%s: couldn't toggle METHOD_HCI_ENABLE\n", DEVNAME(sc)); + return (HCI_FAILURE); + } + + return (HCI_SUCCESS); +} + +int +toshiba_read_events(struct acpitoshiba_softc *sc) +{ + struct aml_value args[HCI_WORDS]; + struct aml_value res; + int i, val; + + bzero(args, sizeof(args)); + bzero(&res, sizeof(res)); + + for (i = 0; i < HCI_WORDS; ++i) + args[i].type = AML_OBJTYPE_INTEGER; + + args[HCI_REG_AX].v_integer = HCI_GET; + args[HCI_REG_BX].v_integer = HCI_REG_SYSTEM_EVENT; + + if (aml_evalname(sc->sc_acpi, sc->sc_devnode, METHOD_HCI, + i, args, &res)) { + printf("%s: couldn't toggle METHOD_HCI\n", DEVNAME(sc)); + return (HCI_FAILURE); + } + + /* + * We receive a package type so we need to get the event + * value from the HCI_REG_CX. + */ + val = aml_val2int(res.v_package[HCI_REG_CX]); + aml_freevalue(&res); + + return (val); +} + +void +toshiba_attach(struct device *parent, struct device *self, void *aux) +{ + struct acpitoshiba_softc *sc = (struct acpitoshiba_softc *)self; + struct acpi_attach_args *aa = aux; + int ret; + + sc->sc_acpi = (struct acpi_softc *)parent; + sc->sc_devnode = aa->aaa_node; + + printf("\n"); + + /* enable events and hotkeys */ + ret = toshiba_enable_events(sc); + if ( ret != HCI_FAILURE) { + /* Run toshiba_hotkey on button presses */ + aml_register_notify(sc->sc_devnode, aa->aaa_dev, + toshiba_hotkey, sc, ACPIDEV_NOPOLL); + + /* wsconsctl purpose */ + ws_get_param = acpitoshiba_get_param; + ws_set_param = acpitoshiba_set_param; + } + +} + +int +toshiba_fn_key_brightness_up(struct acpitoshiba_softc *sc) +{ + u_int32_t brightness_level; + int ret; + + ret = toshiba_get_brightness(sc, &brightness_level); + if ( ret != HCI_FAILURE) { + + if (brightness_level++ == HCI_LCD_BRIGHTNESS_MAX) + brightness_level = HCI_LCD_BRIGHTNESS_MAX; + else + ret = toshiba_set_brightness(sc, &brightness_level); + } + + return (ret); +} + +int +toshiba_fn_key_brightness_down(struct acpitoshiba_softc *sc) +{ + u_int32_t brightness_level; + int ret; + + ret = toshiba_get_brightness(sc, &brightness_level); + if ( ret != HCI_FAILURE) { + if (brightness_level-- == HCI_LCD_BRIGHTNESS_MIN) + brightness_level = HCI_LCD_BRIGHTNESS_MIN; + else + ret = toshiba_set_brightness(sc, &brightness_level); + } + + return (ret); +} + +int +toshiba_fn_key_video_output(struct acpitoshiba_softc *sc) +{ + u_int32_t video_output; + int ret; + + ret = toshiba_get_video_output(sc, &video_output); + if ( ret != HCI_FAILURE) { + video_output = (video_output + 1) % HCI_VIDEO_OUTPUT_CYCLE_MAX; + + ret = toshiba_set_video_output(sc, &video_output); + } + + return (ret); + +} + +int +toshiba_hotkey(struct aml_node *node, int notify, void *arg) +{ + struct acpitoshiba_softc *sc = arg; + int event, ret; + + event = toshiba_read_events(sc); + if (!event) + return (0); + + switch (event) { + case FN_KEY_BRIGHTNESS_UP: + /* Increase brightness */ + ret = toshiba_fn_key_brightness_up(sc); + break; + case FN_KEY_BRIGHTNESS_DOWN: + /* Decrease brightness */ + ret = toshiba_fn_key_brightness_down(sc); + break; + case FN_KEY_VIDEO_OUTPUT: + /* Cycle through video outputs. */ + ret = toshiba_fn_key_video_output(sc); + break; + default: + break; + } + + if ( ret != HCI_SUCCESS) + return (1); + + return (0); +} + +int +toshiba_set_brightness(struct acpitoshiba_softc *sc, u_int32_t *brightness) +{ + struct aml_value args[HCI_WORDS]; + int i; + + bzero(args, sizeof(args)); + + for (i = 0; i < HCI_WORDS; ++i) + args[i].type = AML_OBJTYPE_INTEGER; + + if ((*brightness < HCI_LCD_BRIGHTNESS_MIN) || + (*brightness > HCI_LCD_BRIGHTNESS_MAX)) + return (HCI_FAILURE); + + *brightness <<= HCI_LCD_BRIGHTNESS_SHIFT; + + args[HCI_REG_AX].v_integer = HCI_SET; + args[HCI_REG_BX].v_integer = HCI_REG_LCD_BRIGHTNESS; + args[HCI_REG_CX].v_integer = *brightness; + + if (aml_evalname(sc->sc_acpi, sc->sc_devnode, METHOD_HCI, + i, args, NULL)) { + printf("%s: set brightness failed\n", DEVNAME(sc)); + return (HCI_FAILURE); + } + + return (HCI_SUCCESS); +} + +int +toshiba_get_brightness(struct acpitoshiba_softc *sc, u_int32_t *brightness) +{ + struct aml_value args[HCI_WORDS]; + struct aml_value res; + int i; + + bzero(args, sizeof(args)); + bzero(&res, sizeof(res)); + + for (i = 0; i < HCI_WORDS; ++i) + args[i].type = AML_OBJTYPE_INTEGER; + + args[HCI_REG_AX].v_integer = HCI_GET; + args[HCI_REG_BX].v_integer = HCI_REG_LCD_BRIGHTNESS; + + if (aml_evalname(sc->sc_acpi, sc->sc_devnode, METHOD_HCI, + i, args, &res)) { + printf("%s: get brightness failed\n", DEVNAME(sc)); + return (HCI_FAILURE); + } + + /* + * We receive a package type so we need to get the event + * value from the HCI_REG_CX. + */ + *brightness = aml_val2int(res.v_package[HCI_REG_CX]); + + *brightness >>= HCI_LCD_BRIGHTNESS_SHIFT; + + aml_freevalue(&res); + + return (HCI_SUCCESS); +} + +int +toshiba_get_video_output(struct acpitoshiba_softc *sc, u_int32_t *video_output) +{ + struct aml_value res, args[HCI_WORDS]; + int i; + + bzero(args, sizeof(args)); + bzero(&res, sizeof(res)); + + for (i = 0; i < HCI_WORDS; ++i) + args[i].type = AML_OBJTYPE_INTEGER; + + args[HCI_REG_AX].v_integer = HCI_GET; + args[HCI_REG_BX].v_integer = HCI_REG_VIDEO_OUTPUT; + + if (aml_evalname(sc->sc_acpi, sc->sc_devnode, METHOD_HCI, + i, args, &res)) { + printf("%s: get video output failed\n", DEVNAME(sc)); + return (HCI_FAILURE); + } + + /* + * We receive a package type so we need to get the event + * value from the HCI_REG_CX. + */ + *video_output = aml_val2int(res.v_package[HCI_REG_CX]); + + *video_output &= 0xff; + + aml_freevalue(&res); + + return (HCI_SUCCESS); +} + +int +toshiba_set_video_output(struct acpitoshiba_softc *sc, u_int32_t *video_output) +{ + struct aml_value args[HCI_WORDS]; + int i; + + bzero(args, sizeof(args)); + + if ((*video_output < HCI_VIDEO_OUTPUT_CYCLE_MIN) || + (*video_output > HCI_VIDEO_OUTPUT_CYCLE_MAX)) + return (HCI_FAILURE); + + *video_output |= HCI_VIDEO_OUTPUT_FLAG; + + for (i = 0; i < HCI_WORDS; ++i) + args[i].type = AML_OBJTYPE_INTEGER; + + args[HCI_REG_AX].v_integer = HCI_SET; + args[HCI_REG_BX].v_integer = HCI_REG_VIDEO_OUTPUT; + args[HCI_REG_CX].v_integer = *video_output; + + if (aml_evalname(sc->sc_acpi, sc->sc_devnode, METHOD_HCI, + i, args, NULL)) { + printf("%s: set video output failed\n", DEVNAME(sc)); + return (HCI_FAILURE); + } + + return (HCI_SUCCESS); +} Index: dev/acpi/files.acpi =================================================================== RCS file: /cvs/src/sys/dev/acpi/files.acpi,v retrieving revision 1.25 diff -u -p -r1.25 files.acpi --- dev/acpi/files.acpi 4 Jan 2011 21:17:49 -0000 1.25 +++ dev/acpi/files.acpi 14 Jun 2011 20:02:45 -0000 @@ -81,6 +81,11 @@ device acpithinkpad attach acpithinkpad at acpi file dev/acpi/acpithinkpad.c acpithinkpad +# Toshiba support +device acpitoshiba +attach acpitoshiba at acpi +file dev/acpi/acpitoshiba.c acpitoshiba + # Sony support device acpisony attach acpisony at acpi