Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/macppc/dev make this work properly:
details: https://anonhg.NetBSD.org/src/rev/d5caba198f01
branches: trunk
changeset: 1009449:d5caba198f01
user: macallan <macallan%NetBSD.org@localhost>
date: Thu Apr 23 12:56:40 2020 +0000
description:
make this work properly:
- get rid of cargo-culted register assignments, I found the right ones by
experiment, now both light sensors report sane values
- keyboard brightness seems to max out at 16, act like it
- do what MacOS does and fade keyboard brightness instead of just switching
- add sysctls to configure keyboard brightness and environmental light
thresholds
- don't poll the chip more often than once a second
diffstat:
sys/arch/macppc/dev/lmu.c | 156 ++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 137 insertions(+), 19 deletions(-)
diffs (263 lines):
diff -r 3dc30a726d6b -r d5caba198f01 sys/arch/macppc/dev/lmu.c
--- a/sys/arch/macppc/dev/lmu.c Thu Apr 23 11:41:28 2020 +0000
+++ b/sys/arch/macppc/dev/lmu.c Thu Apr 23 12:56:40 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lmu.c,v 1.3 2020/04/23 09:47:31 macallan Exp $ */
+/* $NetBSD: lmu.c,v 1.4 2020/04/23 12:56:40 macallan Exp $ */
/*-
* Copyright (c) 2020 Michael Lorenz
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lmu.c,v 1.3 2020/04/23 09:47:31 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lmu.c,v 1.4 2020/04/23 12:56:40 macallan Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -40,11 +40,18 @@
#include <sys/bus.h>
#include <sys/time.h>
#include <sys/callout.h>
+#include <sys/sysctl.h>
#include <dev/i2c/i2cvar.h>
#include <dev/sysmon/sysmonvar.h>
+#ifdef LMU_DEBUG
+#define DPRINTF printf
+#else
+#define DPRINTF if (0) printf
+#endif
+
struct lmu_softc {
device_t sc_dev;
i2c_tag_t sc_i2c;
@@ -54,7 +61,9 @@
struct sysmon_envsys *sc_sme;
envsys_data_t sc_sensors[2];
callout_t sc_adjust;
- int sc_thresh, sc_hyst, sc_level;
+ int sc_thresh, sc_hyst, sc_level, sc_target, sc_current;
+ int sc_lux[2];
+ time_t sc_last;
int sc_lid_state, sc_video_state;
};
@@ -65,6 +74,8 @@
static void lmu_set_brightness(struct lmu_softc *, int);
static int lmu_get_brightness(struct lmu_softc *, int);
static void lmu_adjust(void *);
+static int lmu_sysctl(SYSCTLFN_ARGS);
+static int lmu_sysctl_thresh(SYSCTLFN_ARGS);
CFATTACH_DECL_NEW(lmu, sizeof(struct lmu_softc),
lmu_match, lmu_attach, NULL, NULL);
@@ -75,6 +86,11 @@
{ NULL, 0 }
};
+/* time between polling the light sensors */
+#define LMU_POLL (hz * 2)
+/* time between updates to keyboard brightness */
+#define LMU_FADE (hz / 16)
+
static void
lmu_lid_open(device_t dev)
{
@@ -125,11 +141,13 @@
struct lmu_softc *sc = device_private(self);
struct i2c_attach_args *ia = aux;
envsys_data_t *s;
+ const struct sysctlnode *me;
sc->sc_dev = self;
sc->sc_i2c = ia->ia_tag;
sc->sc_addr = ia->ia_addr;
sc->sc_node = ia->ia_cookie;
+ sc->sc_last = 0;
aprint_naive("\n");
aprint_normal(": ambient light sensor\n");
@@ -161,7 +179,7 @@
s->state = ENVSYS_SINVALID;
s->units = ENVSYS_LUX;
strcpy(s->desc, "left");
- s->private = 2;
+ s->private = 1;
sysmon_envsys_sensor_attach(sc->sc_sme, s);
sysmon_envsys_register(sc->sc_sme);
@@ -169,7 +187,30 @@
/* TODO: make this adjustable via sysctl */
sc->sc_thresh = 300;
sc->sc_hyst = 30;
- sc->sc_level = 100;
+ sc->sc_level = 16;
+ sc->sc_target = 0;
+ sc->sc_current = 0;
+
+ sysctl_createv(NULL, 0, NULL, &me,
+ CTLFLAG_READWRITE,
+ CTLTYPE_NODE, "lmu",
+ SYSCTL_DESCR("LMU driver"),
+ NULL, 0, NULL, 0,
+ CTL_HW, CTL_CREATE, CTL_EOL);
+
+ sysctl_createv(NULL, 0, NULL, NULL,
+ CTLFLAG_READWRITE,
+ CTLTYPE_INT, "level",
+ SYSCTL_DESCR("keyboard brightness"),
+ lmu_sysctl, 0, (void *)sc, 0,
+ CTL_HW, me->sysctl_num, CTL_CREATE, CTL_EOL);
+
+ sysctl_createv(NULL, 0, NULL, NULL,
+ CTLFLAG_READWRITE,
+ CTLTYPE_INT, "threshold",
+ SYSCTL_DESCR("environmental light threshold"),
+ lmu_sysctl_thresh, 1, (void *)sc, 0,
+ CTL_HW, me->sysctl_num, CTL_CREATE, CTL_EOL);
callout_init(&sc->sc_adjust, 0);
callout_setfunc(&sc->sc_adjust, lmu_adjust, sc);
@@ -193,28 +234,38 @@
static int
lmu_get_brightness(struct lmu_softc *sc, int reg)
{
- int error;
- uint16_t buf;
- uint8_t cmd = reg;
+ int error, i;
+ uint16_t buf[2];
+ uint8_t cmd = 0;
+
+ if (reg > 1) return -1;
+ if (time_second == sc->sc_last)
+ return sc->sc_lux[reg];
iic_acquire_bus(sc->sc_i2c, 0);
error = iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP,
- sc->sc_addr, &cmd, 1, &buf, 2, 0);
+ sc->sc_addr, &cmd, 1, buf, 4, 0);
iic_release_bus(sc->sc_i2c, 0);
if (error) return -1;
- return be16toh(buf);
+ sc->sc_last = time_second;
+
+ for (i = 0; i < 2; i++)
+ sc->sc_lux[i] = be16toh(buf[i]);
+
+ DPRINTF("<%d %04x %04x>", reg, buf[0], buf[1]);
+
+ return (sc->sc_lux[reg]);
}
static void
lmu_set_brightness(struct lmu_softc *sc, int b)
{
- int bb;
uint8_t cmd[3];
cmd[0] = 1;
- bb = b * 255;
- cmd[1] = (bb & 0xff00) >> 8;
- cmd[2] = bb & 0xff;
+
+ cmd[1] = (b & 0xff);
+ cmd[2] = (b & 0xff) >> 8;
iic_acquire_bus(sc->sc_i2c, 0);
iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP,
@@ -226,18 +277,85 @@
lmu_adjust(void *cookie)
{
struct lmu_softc *sc = cookie;
- int left, right, b;
+ int left, right, b, offset;
- left = lmu_get_brightness(sc, 2);
+ left = lmu_get_brightness(sc, 1);
right = lmu_get_brightness(sc, 0);
b = left > right ? left : right;
if ((b > (sc->sc_thresh + sc->sc_hyst)) ||
!(sc->sc_lid_state && sc->sc_video_state)) {
- lmu_set_brightness(sc, 0);
+ sc->sc_target = 0;
} else if (b < sc->sc_thresh) {
- lmu_set_brightness(sc, sc->sc_level);
+ sc->sc_target = sc->sc_level;
}
- callout_schedule(&sc->sc_adjust, hz * 2);
+ if (sc->sc_target == sc->sc_current) {
+ /* no update needed, check again later */
+ callout_schedule(&sc->sc_adjust, LMU_POLL);
+ return;
+ }
+
+
+ offset = ((sc->sc_target - sc->sc_current) > 0) ? 2 : -2;
+ sc->sc_current += offset;
+ if (sc->sc_current > sc->sc_level) sc->sc_current = sc->sc_level;
+ if (sc->sc_current < 0) sc->sc_current = 0;
+
+ DPRINTF("[%d]", sc->sc_current);
+
+ lmu_set_brightness(sc, sc->sc_current);
+
+ if (sc->sc_target == sc->sc_current) {
+ /* no update needed, check again later */
+ callout_schedule(&sc->sc_adjust, LMU_POLL);
+ return;
+ }
+
+ /* more updates upcoming */
+ callout_schedule(&sc->sc_adjust, LMU_FADE);
}
+
+static int
+lmu_sysctl(SYSCTLFN_ARGS)
+{
+ struct sysctlnode node = *rnode;
+ struct lmu_softc *sc = node.sysctl_data;
+ int target;
+
+ target = sc->sc_level;
+ node.sysctl_data = ⌖
+ if (sysctl_lookup(SYSCTLFN_CALL(&node)) == 0) {
+ int new_reg;
+
+ new_reg = *(int *)node.sysctl_data;
+ if (new_reg != sc->sc_target) {
+ sc->sc_level = target;
+ sc->sc_target = target;
+
+ }
+ return 0;
+ }
+ return EINVAL;
+}
+
+static int
+lmu_sysctl_thresh(SYSCTLFN_ARGS)
+{
+ struct sysctlnode node = *rnode;
+ struct lmu_softc *sc = node.sysctl_data;
+ int thresh;
+
+ thresh = sc->sc_thresh;
+ node.sysctl_data = &thresh;
+ if (sysctl_lookup(SYSCTLFN_CALL(&node)) == 0) {
+ int new_reg;
+
+ new_reg = *(int *)node.sysctl_data;
+ if (new_reg != sc->sc_thresh && new_reg > 0) {
+ sc->sc_thresh = new_reg;
+ }
+ return 0;
+ }
+ return EINVAL;
+}
Home |
Main Index |
Thread Index |
Old Index