hello,
in the past I wrote a very humble brightness driver (via acpi) for my
vaio laptop.
http://marc.info/?l=openbsd-misc&m=117862756504674&w=2
w/ these suggestion during this summer w/ a bit of spare time I've also
added brightness support for the asus and fujitsu laptops (ported from
freebsd w/ some minor modifications)
now while the vaio driver has been tested on several recent vaio laptops
models, the asus patch has been tested w/ only one model (A2H) so it may
fail w/ other models. the fujitsu has not been tested at all.
so if somebody is interested in trying it here it is the whole patch.
vaio usage:
sysctl -w hw.brightness=0..8
asus usage:
sysctl -w hw.brightness=0..15
fujitsu usage
sysctl -w hw.brightness=0..7
btw just remember to rebuild sysctl because sysctl.h header has been
modified. if you do not do this you'll not see the brightness variable
diff -ur sys.orig/arch/i386/conf/GENERIC sys/arch/i386/conf/GENERIC
--- sys.orig/arch/i386/conf/GENERIC Mon Sep 3 09:10:33 2007
+++ sys/arch/i386/conf/GENERIC Mon Sep 3 09:37:27 2007
@@ -58,19 +58,19 @@
pci* at mainbus0
#option ACPIVERBOSE
-#option ACPI_ENABLE
+option ACPI_ENABLE
-acpi0 at mainbus? disable
-#acpitimer* at acpi?
-#acpihpet* at acpi?
-#acpiac* at acpi?
-#acpibat* at acpi?
-#acpibtn* at acpi?
-#acpicpu* at acpi?
-#acpidock* at acpi?
-acpiec* at acpi? disable
+acpi0 at mainbus?
+acpitimer* at acpi?
+acpihpet* at acpi?
+acpiac* at acpi?
+acpibat* at acpi?
+acpibtn* at acpi?
+acpicpu* at acpi?
+acpidock* at acpi?
+acpiec* at acpi?
acpiprt* at acpi?
-#acpitz* at acpi?
+acpitz* at acpi?
option PCIVERBOSE
option EISAVERBOSE
diff -ur sys.orig/dev/acpi/acpi.c sys/dev/acpi/acpi.c
--- sys.orig/dev/acpi/acpi.c Tue Apr 17 18:07:45 2007
+++ sys/dev/acpi/acpi.c Mon Sep 3 09:37:27 2007
@@ -1691,7 +1691,10 @@
aaa.aaa_name = "acpibat";
else if (!strcmp(dev, ACPI_DEV_LD) ||
!strcmp(dev, ACPI_DEV_PBD) ||
- !strcmp(dev, ACPI_DEV_SBD))
+ !strcmp(dev, ACPI_DEV_SBD) ||
+ !strcmp(dev, ACPI_DEV_SNC) ||
+ !strcmp(dev, ACPI_DEV_ATK) ||
+ !strcmp(dev, ACPI_DEV_FUJ))
aaa.aaa_name = "acpibtn";
if (aaa.aaa_name)
diff -ur sys.orig/dev/acpi/acpibtn.c sys/dev/acpi/acpibtn.c
--- sys.orig/dev/acpi/acpibtn.c Wed Dec 27 00:58:08 2006
+++ sys/dev/acpi/acpibtn.c Mon Sep 3 09:37:27 2007
@@ -20,6 +20,7 @@
#include <sys/signalvar.h>
#include <sys/systm.h>
#include <sys/device.h>
+#include <sys/sysctl.h>
#include <sys/malloc.h>
#include <machine/bus.h>
@@ -32,36 +33,168 @@
#include <sys/sensors.h>
+void sony_brightness(int*);
+void asus_brightness(int*);
+void fujitsu_brightness(int*);
+
int acpibtn_match(struct device *, void *, void *);
void acpibtn_attach(struct device *, struct device *, void *);
int acpibtn_notify(struct aml_node *, int, void *);
+int acpibtn_getsta(struct acpibtn_softc *);
-struct acpibtn_softc {
- struct device sc_dev;
+struct acpibtn_softc sc_brt;
- bus_space_tag_t sc_iot;
- bus_space_handle_t sc_ioh;
+struct cfattach acpibtn_ca = {
+ sizeof(struct acpibtn_softc), acpibtn_match, acpibtn_attach
+};
- struct acpi_softc *sc_acpi;
- struct aml_node *sc_devnode;
+struct cfdriver acpibtn_cd = {
+ NULL, "acpibtn", DV_DULL
+};
- int sc_btn_type;
-#define ACPIBTN_UNKNOWN -1
-#define ACPIBTN_LID 0
-#define ACPIBTN_POWER 1
-#define ACPIBTN_SLEEP 2
+struct acpi_vaio_model {
+ char *name;
+ char *brt_get;
+ char *brt_set;
};
-int acpibtn_getsta(struct acpibtn_softc *);
+static struct acpi_vaio_model vaio_models = {
+ .name = "xxx",
+ .brt_get = "GBRT",
+ .brt_set = "SBRT",
+};
-struct cfattach acpibtn_ca = {
- sizeof(struct acpibtn_softc), acpibtn_match, acpibtn_attach
+static struct acpi_vaio_model fujitsu_models = {
+ .name = "xxx",
+ .brt_get = "GBLL",
+ .brt_set = "SBLL",
};
-struct cfdriver acpibtn_cd = {
- NULL, "acpibtn", DV_DULL
+/* asus support (part of it) is havily based on the asus_acpi.c
+ written by Philip Paeps <[EMAIL PROTECTED]> */
+struct acpi_asus_model {
+ char *name;
+ char *brt_get;
+ char *brt_set;
+ char *brt_up;
+ char *brt_down;
};
+static struct acpi_asus_model *p = NULL;
+
+static struct acpi_asus_model asus_models[] = {
+ {
+ .name = "xxN",
+ .brt_get = "GPLV",
+ .brt_set = "SPLV",
+ },
+ {
+ .name = "A2x",
+ .brt_get = "GPLV",
+ .brt_set = "SPLV",
+ },
+ {
+ .name = "A3N",
+ .brt_get = "SDSP",
+ .brt_set = "SPLV",
+ },
+ {
+ .name = "A4D",
+ .brt_get = "GPLV",
+ .brt_set = "SPLV",
+ },
+ {
+ .name = "A6V",
+ .brt_get = "GPLV",
+ .brt_set = "SPLV",
+ },
+ {
+ .name = "L3C",
+ .brt_get = "GPLV",
+ .brt_set = "SPLV",
+ },
+ {
+ .name = "L3D",
+ .brt_get = "GPLV",
+ .brt_set = "SPLV",
+ },
+ {
+ .name = "L3H",
+ .brt_get = "GPLV",
+ .brt_set = "SPLV",
+ },
+ {
+ .name = "L4R",
+ .brt_get = "GPLV",
+ .brt_set = "SPLV",
+ },
+ {
+ .name = "L5x",
+ .brt_get = "GPLV",
+ .brt_set = "SPLV",
+ },
+ {
+ .name = "M2E",
+ .brt_get = "GPLV",
+ .brt_set = "SPLV",
+ },
+ {
+ .name = "M6N",
+ .brt_get = "GPLV",
+ .brt_set = "SPLV",
+ },
+ {
+ .name = "M6R",
+ .brt_get = "GPLV",
+ .brt_set = "SPLV",
+ },
+ {
+ .name = "S1x",
+ .brt_get = "GPLV",
+ .brt_set = "SPLV"
+ },
+ {
+ .name = "V6V",
+ .brt_get = "GPLV",
+ .brt_set = "SPLV",
+ },
+ {
+ .name = "Wxx",
+ .brt_get = "GPLV",
+ .brt_set = "SPLV",
+ },
+#if 1 /* increase/decrease methods models */
+ {
+ .name = "D1x",
+ .brt_up = "\\Q0C",
+ .brt_down = "\\Q0B",
+ },
+ {
+ .name = "L2D",
+ .brt_up = "\\Q0E",
+ .brt_down = "\\Q0F",
+ },
+ {
+ .name = "A1x",
+ .brt_up = "\\_SB.PCI0.ISA.EC0._Q0E",
+ .brt_down = "\\_SB.PCI0.ISA.EC0._Q0F"
+ },
+ {
+ .name = "M1A",
+ .brt_up = "\\_SB.PCI0.PX40.EC0.Q0E",
+ .brt_down = "\\_SB.PCI0.PX40.EC0.Q0F",
+ },
+ {
+ .name = "S2x",
+ .brt_up = "\\_SB.PCI0.ISA.EC0._Q0B",
+ .brt_down = "\\_SB.PCI0.ISA.EC0._Q0A"
+ },
+#endif
+ {
+ .name = NULL
+ }
+};
+
int
acpibtn_match(struct device *parent, void *match, void *aux)
{
@@ -80,12 +213,180 @@
void
acpibtn_attach(struct device *parent, struct device *self, void *aux)
{
- struct acpibtn_softc *sc = (struct acpibtn_softc *)self;
struct acpi_attach_args *aa = aux;
-
+ struct aml_value res, res1;
+ struct acpibtn_softc *sc = (struct acpibtn_softc *)self;
+
sc->sc_acpi = (struct acpi_softc *)parent;
sc->sc_devnode = aa->aaa_node->child;
+
+ /* asus notebook driver (not a real button) */
+ if (!strcmp(aa->aaa_dev, ACPI_DEV_ATK)) {
+
+ sc_brt.sc_acpi = sc->sc_acpi;
+ sc_brt.sc_devnode = sc->sc_devnode;
+ printf(": %s ", sc_brt.sc_devnode->parent->name);
+
+ memset(&res, 0, sizeof(res));
+ res.type = AML_OBJTYPE_INTEGER;
+ res.v_integer = 0;
+
+ if (aml_evalname(sc_brt.sc_acpi, sc_brt.sc_devnode, "INIT", 1, &res,
&res1)) {
+ printf("error INIT evaluation\n");
+ goto err1;
+ }
+#if 0
+ switch (res1.type) {
+ case AML_OBJTYPE_STRING:
+ printf("INIT object type: string\n");
+ break;
+ case AML_OBJTYPE_BUFFER:
+ printf("INIT object type: buffer\n");
+ break;
+ default:
+ printf("INIT object type: unknown %x\n",
res1.type);
+ }
+#endif
+ if (aml_evalname(sc_brt.sc_acpi, sc_brt.sc_devnode, "BSTS", 0, NULL,
NULL))
+ dnprintf("error BSTS evaluation\n");
+
+ if (res1.type == AML_OBJTYPE_STRING && res1.v_string != NULL) {
+
+ for (p = asus_models; p->name != NULL; p++) {
+ if (strncmp(res1.v_string, p->name, 3)
== 0)
+ break;
+ else if (strncmp(p->name, "xxN", 3) == 0
&&
+ (strncmp(res1.v_string,
"M2N", 3) == 0 ||
+ strncmp(res1.v_string,
"M3N", 3) == 0 ||
+ strncmp(res1.v_string,
"M5N", 3) == 0 ||
+ strncmp(res1.v_string,
"S1N", 3) == 0 ||
+ strncmp(res1.v_string,
"S5N", 3) == 0 ||
+ strncmp(res1.v_string,
"W1N", 3) == 0))
+ break;
+ else if (strncmp(p->name, "A1x", 3) == 0
&&
+ strncmp(res1.v_string,
"A1", 2) == 0)
+ break;
+ else if (strncmp(p->name, "A2x", 3) == 0
&&
+ strncmp(res1.v_string,
"A2", 2) == 0)
+ break;
+ else if (strncmp(p->name, "D1x", 3) == 0
&&
+ strncmp(res1.v_string,
"D1", 2) == 0)
+ break;
+ else if (strncmp(p->name, "L3H", 3) == 0
&&
+ strncmp(res1.v_string,
"L2E", 3) == 0)
+ break;
+ else if (strncmp(p->name, "L3C", 3) == 0
&&
+ strncmp(res1.v_string,
"L2B", 3) == 0)
+ break;
+ else if (strncmp(p->name, "L5x", 3) == 0
&&
+ strncmp(res1.v_string,
"L5", 2) == 0)
+ break;
+ else if (strncmp(p->name, "M6R", 3) == 0
&&
+ strncmp(res1.v_string,
"A3G", 3) == 0)
+ break;
+ else if (strncmp(p->name, "M2E", 3) == 0
&&
+ (strncmp(res1.v_string,
"M2", 2) == 0 ||
+ strncmp(res1.v_string,
"L4E", 3) == 0))
+ break;
+ else if (strncmp(p->name, "S1x", 3) == 0
&&
+ (strncmp(res1.v_string,
"L8", 2) == 0 ||
+ strncmp(res1.v_string,
"S2", 2) == 0))
+ break;
+ else if (strncmp(p->name, "Wxx", 3) == 0
&&
+ (strncmp(res1.v_string,
"W5A", 3) == 0 ||
+ strncmp(res1.v_string,
"W6", 2) == 0))
+ break;
+ }
+
+ if (p == NULL)
+ printf("ASUS model not matched %s\n",
res1.v_string);
+ else {
+ printf("ASUS model %s\n",
res1.v_string);
+
+ aml_freevalue(&res);
+
+ if (p->brt_get != NULL) {
+ if (aml_evalname(sc_brt.sc_acpi, sc_brt.sc_devnode, p->brt_get,
0, NULL, &res)) {
+ dnprintf(10, "%s:
error reading brightness", DEVNAME(sc));
+ goto err1;
+ }
+ }
+ else if (p->brt_up != NULL &&
p->brt_down != NULL) {
+ if (aml_evalname(sc_brt.sc_acpi, sc_brt.sc_devnode, p->brt_up, 0,
NULL, NULL)) {
+ dnprintf(10, "%s:
error reading brightness up", DEVNAME(sc));
+ goto err1;
+ }
+ if (aml_evalname(sc_brt.sc_acpi, sc_brt.sc_devnode, p->brt_down,
0, NULL, NULL)) {
+ dnprintf(10, "%s:
error reading brightness down", DEVNAME(sc));
+ goto err1;
+ }
+ }
+
+ if (!brt_set) {
+ sc_brt.brtlevel = 0;
+ sc_brt.brtlevel_prev = 0;
+
+ if (p->brt_get != NULL)
+ sc_brt.brtlevel =
aml_val2int(&res);
+ brt_set = asus_brightness;
+ }
+ }
+ }
+
+err1:
+ aml_freevalue(&res);
+ aml_freevalue(&res1);
+ return;
+ }
+
+ /* sony notebook controller (not a real button) */
+ if (!strcmp(aa->aaa_dev, ACPI_DEV_SNC)) {
+
+ sc_brt.sc_acpi = sc->sc_acpi;
+ sc_brt.sc_devnode = sc->sc_devnode;
+
+ if (aml_evalname(sc_brt.sc_acpi, sc_brt.sc_devnode,
vaio_models.brt_get, 0, NULL, &res)) {
+ dnprintf(10, "%s: error reading brightness",
DEVNAME(sc));
+ goto err;
+ }
+
+ printf(": %s VAIO\n", sc_brt.sc_devnode->parent->name);
+
+ if (!brt_set) {
+ sc_brt.brtlevel = aml_val2int(&res);
+ brt_set = sony_brightness;
+ }
+
+err:
+ aml_freevalue(&res);
+ return;
+ }
+
+ /* fujitsu notebook controller (not a real button) */
+ if (!strcmp(aa->aaa_dev, ACPI_DEV_FUJ)) {
+
+ sc_brt.sc_acpi = sc->sc_acpi;
+ sc_brt.sc_devnode = sc->sc_devnode;
+
+ if (aml_evalname(sc_brt.sc_acpi, sc_brt.sc_devnode,
fujitsu_models.brt_get, 0, NULL, &res)) {
+ dnprintf(10, "%s: error reading brightness",
DEVNAME(sc));
+ goto err2;
+ }
+
+ printf(": %s FUJITSU\n", sc_brt.sc_devnode->parent->name);
+
+ if (!brt_set) {
+ sc_brt.brtlevel = aml_val2int(&res);
+ sc_brt.brtlevel &= 0x0fffffff;
+ brt_set = fujitsu_brightness;
+ }
+
+err2:
+ aml_freevalue(&res);
+ return;
+ }
+
if (!strcmp(aa->aaa_dev, ACPI_DEV_LD))
sc->sc_btn_type = ACPIBTN_LID;
else if (!strcmp(aa->aaa_dev, ACPI_DEV_PBD))
@@ -140,4 +441,95 @@
}
return (0);
+}
+
+void
+fujitsu_brightness(int *val)
+{
+ #define FUJITSU_MAX_BRT_VAL 8
+ #define FUJITSU_MIN_BRT_VAL 0
+
+ struct aml_value res;
+
+ if (*val > FUJITSU_MAX_BRT_VAL)
+ *val = FUJITSU_MAX_BRT_VAL - 1;
+ if (*val < FUJITSU_MIN_BRT_VAL)
+ *val = FUJITSU_MIN_BRT_VAL;
+
+ memset(&res, 0, sizeof(res));
+ res.type = AML_OBJTYPE_INTEGER;
+ res.v_integer = *val;
+
+ if (aml_evalname(sc_brt.sc_acpi, sc_brt.sc_devnode,
fujitsu_models.brt_set, 1, &res, NULL))
+ printf("error setting brightness to %d\n", *val);
+
+ aml_freevalue(&res);
+}
+
+void
+sony_brightness(int *val)
+{
+ #define VAIO_MAX_BRT_VAL 8
+ #define VAIO_MIN_BRT_VAL 0
+
+ struct aml_value res;
+
+ if (*val > VAIO_MAX_BRT_VAL)
+ *val = VAIO_MAX_BRT_VAL;
+ if (*val < VAIO_MIN_BRT_VAL)
+ *val = VAIO_MIN_BRT_VAL;
+
+ memset(&res, 0, sizeof(res));
+ res.type = AML_OBJTYPE_INTEGER;
+ res.v_integer = *val;
+
+ if (aml_evalname(sc_brt.sc_acpi, sc_brt.sc_devnode,
vaio_models.brt_set, 1, &res, NULL))
+ printf("error setting brightness to %d\n", *val);
+
+ aml_freevalue(&res);
+}
+
+void
+asus_brightness(int *val)
+{
+ #define ASUS_MAX_BRT_VAL 15
+ #define ASUS_MIN_BRT_VAL 0
+
+ struct aml_value res;
+ int tmp;
+
+ if (*val > ASUS_MAX_BRT_VAL)
+ *val = ASUS_MAX_BRT_VAL;
+ if (*val < ASUS_MIN_BRT_VAL)
+ *val = ASUS_MIN_BRT_VAL;
+
+ memset(&res, 0, sizeof(res));
+ res.type = AML_OBJTYPE_INTEGER;
+ res.v_integer = *val;
+
+ if (p->brt_set != NULL) {
+ if (aml_evalname(sc_brt.sc_acpi, sc_brt.sc_devnode, p->brt_set, 1,
&res, NULL))
+ printf("error setting brightness to %d\n", *val);
+ } /* incremental changes */
+ else if (p->brt_up != NULL && p->brt_down != NULL) {
+ tmp = *val - sc_brt.brtlevel_prev;
+ while (tmp != 0) {
+ if (tmp > 0) {
+ if (aml_evalname(sc_brt.sc_acpi, sc_brt.sc_devnode, p->brt_up, 0,
NULL, NULL)) {
+ printf("error setting brightness\n");
+ break;
+ }
+ }
+ else if (aml_evalname(sc_brt.sc_acpi, sc_brt.sc_devnode,
p->brt_down, 0, NULL, NULL)) {
+ printf("error setting brightness\n");
+ break;
+ }
+ (tmp > 0) ? tmp-- : tmp++;
+ }
+
+ if (!tmp)
+ sc_brt.brtlevel_prev = *val;
+ }
+
+ aml_freevalue(&res);
}
diff -ur sys.orig/dev/acpi/acpidev.h sys/dev/acpi/acpidev.h
--- sys.orig/dev/acpi/acpidev.h Thu May 31 19:49:16 2007
+++ sys/dev/acpi/acpidev.h Mon Sep 3 09:37:27 2007
@@ -314,5 +314,22 @@
#define ACPIDOCK_EVENT_INSERT 0
#define ACPIDOCK_EVENT_EJECT 3
+struct acpibtn_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+
+ struct acpi_softc *sc_acpi;
+ struct aml_node *sc_devnode;
+
+ int sc_btn_type;
+ #define ACPIBTN_UNKNOWN -1
+ #define ACPIBTN_LID 0
+ #define ACPIBTN_POWER 1
+ #define ACPIBTN_SLEEP 2
+
+ int brtlevel;
+ int brtlevel_prev;
+};
#endif /* __DEV_ACPI_ACPIDEV_H__ */
diff -ur sys.orig/dev/acpi/acpireg.h sys/dev/acpi/acpireg.h
--- sys.orig/dev/acpi/acpireg.h Tue Dec 12 19:07:25 2006
+++ sys/dev/acpi/acpireg.h Mon Sep 3 09:37:27 2007
@@ -484,5 +484,8 @@
#define ACPI_DEV_IOSA "ACPI000B" /* IO SAPIC Device */
#define ACPI_DEV_THZ "THERMALZONE" /* Thermal Zone */
#define ACPI_DEV_FFB "FIXEDBUTTON" /* Fixed Feature Button */
+#define ACPI_DEV_SNC "SNY5001" /* Sony notebook controller */
+#define ACPI_DEV_ATK "ATK0100" /* Asus notebook driver */
+#define ACPI_DEV_FUJ "FUJ02B1" /* Fujitsu notebook driver */
#endif /* !_DEV_ACPI_ACPIREG_H_ */
diff -ur sys.orig/kern/kern_sysctl.c sys/kern/kern_sysctl.c
--- sys.orig/kern/kern_sysctl.c Mon Sep 3 09:10:49 2007
+++ sys/kern/kern_sysctl.c Mon Sep 3 09:37:27 2007
@@ -85,6 +85,13 @@
#include <sys/shm.h>
#endif
+#include <machine/bus.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>
+
#define PTRTOINT64(_x) ((u_int64_t)(u_long)(_x))
extern struct forkstat forkstat;
@@ -96,6 +103,8 @@
extern void nmbclust_update(void);
+extern struct acpibtn_softc sc_brt;
+
int sysctl_diskinit(int, struct proc *);
int sysctl_proc_args(int *, u_int, void *, size_t *, struct proc *);
int sysctl_intrcnt(int *, u_int, void *, size_t *);
@@ -107,6 +116,8 @@
void (*cpu_setperf)(int);
int perflevel = 100;
+void (*brt_set)(int*);
+
/*
* Lock to avoid too many processes vslocking a large amount of memory
* at the same time.
@@ -602,6 +613,15 @@
if (err)
return err;
return (sysctl_rdint(oldp, oldlenp, newp, cpuspeed));
+ case HW_SETBRT:
+ if (!brt_set)
+ return (EOPNOTSUPP);
+ err = sysctl_int(oldp, oldlenp, newp, newlen, &sc_brt.brtlevel);
+ if (err)
+ return err;
+ if (newp)
+ brt_set(&sc_brt.brtlevel);
+ return (0);
case HW_SETPERF:
if (!cpu_setperf)
return (EOPNOTSUPP);
diff -ur sys.orig/sys/sysctl.h sys/sys/sysctl.h
--- sys.orig/sys/sysctl.h Fri Apr 13 00:14:15 2007
+++ sys/sys/sysctl.h Mon Sep 3 09:37:27 2007
@@ -552,7 +552,8 @@
#define HW_VERSION 16 /* string: hardware version */
#define HW_SERIALNO 17 /* string: hardware serial
number */
#define HW_UUID 18 /* string: universal unique id
*/
-#define HW_MAXID 19 /* number of valid hw ids */
+#define HW_SETBRT 19 /* set LCD brightness */
+#define HW_MAXID 20 /* number of valid hw ids */
#define CTL_HW_NAMES { \
{ 0, 0 }, \
@@ -574,6 +575,7 @@
{ "version", CTLTYPE_STRING }, \
{ "serialno", CTLTYPE_STRING }, \
{ "uuid", CTLTYPE_STRING }, \
+ { "brightness", CTLTYPE_INT }, \
}
/*
@@ -724,6 +726,7 @@
extern int (*cpu_cpuspeed)(int *);
extern void (*cpu_setperf)(int);
+extern void (*brt_set)(int*);
int bpf_sysctl(int *, u_int, void *, size_t *, void *, size_t);