# $Id: openbsd-acpithinkpad_brightness_fix.diff,v 1.1 2008/12/16 22:19:58 jcs Exp $ # # make acpithinkpad(4) handle brightness adjustments properly on the # x61s and t61. on those two models, it still uses the brightness # adjustment callback to adjust inside the driver. this fixes the # double adjustment problem on newer models while still working on # these two quirky models. # # jcs@openbsd.org # Index: acpithinkpad.c =================================================================== RCS file: /cvs/src/sys/dev/acpi/acpithinkpad.c,v retrieving revision 1.13 diff -u -p -r1.13 acpithinkpad.c --- acpithinkpad.c 6 Nov 2008 23:41:28 -0000 1.13 +++ acpithinkpad.c 16 Dec 2008 22:18:07 -0000 @@ -32,6 +32,9 @@ #define THINKPAD_CMOS_BRIGHTNESS_UP 0x04 #define THINKPAD_CMOS_BRIGHTNESS_DOWN 0x05 +#define THINKPAD_EC_BRIGHTNESS_OFFSET 0x31 +#define THINKPAD_EC_BRIGHTNESS_LEVEL_MASK 0x1f + #define THINKPAD_BLUETOOTH_PRESENT 0x01 #define THINKPAD_BLUETOOTH_ENABLED 0x02 @@ -82,6 +85,17 @@ struct acpithinkpad_softc { struct aml_node *sc_devnode; }; +/* from bios.c */ +extern char *hw_ver; + +/* models (according to smbios info version) that need a brightness helper */ +const char *acpithinkpad_models_to_help[] = { + "ThinkPad X61s", + "ThinkPad T61", +}; + +int thinkpad_need_helper = 0; + int thinkpad_match(struct device *, void *, void *); void thinkpad_attach(struct device *, struct device *, void *); int thinkpad_hotkey(struct aml_node *, int, void *); @@ -92,8 +106,9 @@ int thinkpad_cmos(struct acpithinkpad_so int thinkpad_volume_down(struct acpithinkpad_softc *); int thinkpad_volume_up(struct acpithinkpad_softc *); int thinkpad_volume_mute(struct acpithinkpad_softc *); -int thinkpad_brightness_up(struct acpithinkpad_softc *); +int thinkpad_brightness_get(struct acpithinkpad_softc *); int thinkpad_brightness_down(struct acpithinkpad_softc *); +int thinkpad_brightness_up(struct acpithinkpad_softc *); struct cfattach acpithinkpad_ca = { sizeof(struct acpithinkpad_softc), thinkpad_match, thinkpad_attach @@ -132,11 +147,22 @@ thinkpad_attach(struct device *parent, s { struct acpithinkpad_softc *sc = (struct acpithinkpad_softc *)self; struct acpi_attach_args *aa = aux; + int i; sc->sc_acpi = (struct acpi_softc *)parent; sc->sc_devnode = aa->aaa_node; - printf("\n"); + for (i = 0; i < nitems(acpithinkpad_models_to_help); i++) + if (strcmp(hw_ver, acpithinkpad_models_to_help[i]) == 0) { + printf(": activating brightness helper"); + thinkpad_need_helper = 1; + break; + } + + /* for models that don't need a brightness helper, adjust brightness on + * our own */ + if (!thinkpad_need_helper) + thinkpad_brightness_get(sc); /* set event mask to receive everything */ thinkpad_enable_events(sc); @@ -144,6 +170,8 @@ thinkpad_attach(struct device *parent, s /* run thinkpad_hotkey on button presses */ aml_register_notify(sc->sc_devnode, aa->aaa_dev, thinkpad_hotkey, sc, ACPIDEV_NOPOLL); + + printf("\n"); } int @@ -203,6 +231,7 @@ thinkpad_hotkey(struct aml_node *node, i if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "MHKP", 0, NULL, &res)) goto done; + val = aml_val2int(&res); aml_freevalue(&res); if (val == 0) @@ -215,25 +244,27 @@ thinkpad_hotkey(struct aml_node *node, i switch (type) { case 1: switch (event) { - case THINKPAD_BUTTON_BRIGHTNESS_UP: - thinkpad_brightness_up(sc); - handled = 1; - break; - case THINKPAD_BUTTON_BRIGHTNESS_DOWN: - thinkpad_brightness_down(sc); - handled = 1; - break; case THINKPAD_BUTTON_WIRELESS: thinkpad_toggle_bluetooth(sc); handled = 1; break; case THINKPAD_BUTTON_SUSPEND: handled = 1; - /* + /* acpi_enter_sleep_state(sc->sc_acpi, ACPI_STATE_S3); */ break; + case THINKPAD_BUTTON_BRIGHTNESS_UP: + if (thinkpad_need_helper) + thinkpad_brightness_up(sc); + handled = 1; + break; + case THINKPAD_BUTTON_BRIGHTNESS_DOWN: + if (thinkpad_need_helper) + thinkpad_brightness_down(sc); + handled = 1; + break; case THINKPAD_BUTTON_HIBERNATE: case THINKPAD_BUTTON_FN_F1: case THINKPAD_BUTTON_LOCK_SCREEN: @@ -318,8 +349,10 @@ thinkpad_toggle_bluetooth(struct acpithi bluetooth = aml_val2int(&res); aml_freevalue(&res); - if (!(bluetooth & THINKPAD_BLUETOOTH_PRESENT)) + if (!(bluetooth & THINKPAD_BLUETOOTH_PRESENT)) { + printf("no bluetooth present\n"); goto fail; + } bzero(&arg, sizeof(arg)); arg.type = AML_OBJTYPE_INTEGER; @@ -338,7 +371,7 @@ int thinkpad_toggle_wan(struct acpithinkpad_softc *sc) { struct aml_value res, arg; - int wan, rv = 1;; + int wan, rv = 1; if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "GWAN", 0, NULL, &res)) goto fail; @@ -395,6 +428,18 @@ int thinkpad_volume_mute(struct acpithinkpad_softc *sc) { return (thinkpad_cmos(sc, THINKPAD_CMOS_VOLUME_MUTE)); +} + +int +thinkpad_brightness_get(struct acpithinkpad_softc *sc) +{ + uint8_t val; + int level; + + acpiec_read(sc->sc_acpi->sc_ec, THINKPAD_EC_BRIGHTNESS_OFFSET, 1, &val); + level = val & THINKPAD_EC_BRIGHTNESS_LEVEL_MASK; + + return level; } int