summaryrefslogtreecommitdiff
path: root/sys/dev/wscons/wsdisplay.c
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2020-04-19 15:05:16 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2020-04-19 15:05:16 +0000
commit665e49b26083d06d142bf33b45c1aded7d6bb815 (patch)
tree85d5381f94d35fdb4dfd6a145ddf207ccd92f5bf /sys/dev/wscons/wsdisplay.c
parent4d85d754528985a769e7754fc22f6a0c3c7f3608 (diff)
Move logic to change brightness level in reasonable steps from acpivout(4)
into wsdisplay(4). This code is now exposed through wsdisplay_brightness_{step,zero,cycle} functions that can be called by any driver that handles brightnes "hotkeys". These functions take a wsdisplay(4) device pointer as their first argument, which should be provided if a clear association between events and a particular display exist. This is used in wskbd(4). Otherwise NULL can be passed and the code will direct the request at the first wsdisplay(4) that implements brightness adjustment. Tested by many. Fixes brightness keys on x395 and other thinkpads with AMD graphics. ok patrick@
Diffstat (limited to 'sys/dev/wscons/wsdisplay.c')
-rw-r--r--sys/dev/wscons/wsdisplay.c114
1 files changed, 113 insertions, 1 deletions
diff --git a/sys/dev/wscons/wsdisplay.c b/sys/dev/wscons/wsdisplay.c
index 7bf8c016238..e0f16514133 100644
--- a/sys/dev/wscons/wsdisplay.c
+++ b/sys/dev/wscons/wsdisplay.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wsdisplay.c,v 1.136 2020/03/22 07:59:59 anton Exp $ */
+/* $OpenBSD: wsdisplay.c,v 1.137 2020/04/19 15:05:14 kettenis Exp $ */
/* $NetBSD: wsdisplay.c,v 1.82 2005/02/27 00:27:52 perry Exp $ */
/*
@@ -2368,6 +2368,118 @@ wsdisplay_burner(void *v)
}
#endif
+int
+wsdisplay_get_param(struct wsdisplay_softc *sc, struct wsdisplay_param *dp)
+{
+ int error = ENXIO;
+ int i;
+
+ if (sc != NULL)
+ return wsdisplay_param(&sc->sc_dv, WSDISPLAYIO_GETPARAM, dp);
+
+ for (i = 0; i < wsdisplay_cd.cd_ndevs; i++) {
+ sc = wsdisplay_cd.cd_devs[i];
+ if (sc == NULL)
+ continue;
+ error = wsdisplay_param(&sc->sc_dv, WSDISPLAYIO_GETPARAM, dp);
+ if (error == 0)
+ break;
+ }
+
+ if (error && ws_get_param)
+ error = ws_get_param(dp);
+
+ return error;
+}
+
+int
+wsdisplay_set_param(struct wsdisplay_softc *sc, struct wsdisplay_param *dp)
+{
+ int error = ENXIO;
+ int i;
+
+ if (sc != NULL)
+ return wsdisplay_param(&sc->sc_dv, WSDISPLAYIO_SETPARAM, dp);
+
+ for (i = 0; i < wsdisplay_cd.cd_ndevs; i++) {
+ sc = wsdisplay_cd.cd_devs[i];
+ if (sc == NULL)
+ continue;
+ error = wsdisplay_param(&sc->sc_dv, WSDISPLAYIO_SETPARAM, dp);
+ if (error == 0)
+ break;
+ }
+
+ if (error && ws_set_param)
+ error = ws_set_param(dp);
+
+ return error;
+}
+
+void
+wsdisplay_brightness_step(struct device *dev, int dir)
+{
+ struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
+ struct wsdisplay_param dp;
+ int delta, new;
+
+ dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS;
+ if (wsdisplay_get_param(sc, &dp))
+ return;
+
+ /* Use a step size of approximately 5%. */
+ delta = max(1, ((dp.max - dp.min) * 5) / 100);
+ new = dp.curval;
+
+ if (dir > 0) {
+ if (delta > dp.max - dp.curval)
+ new = dp.max;
+ else
+ new += delta;
+ } else if (dir < 0) {
+ if (delta > dp.curval - dp.min)
+ new = dp.min;
+ else
+ new -= delta;
+ }
+
+ if (dp.curval == new)
+ return;
+
+ dp.curval = new;
+ wsdisplay_set_param(sc, &dp);
+}
+
+void
+wsdisplay_brightness_zero(struct device *dev)
+{
+ struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
+ struct wsdisplay_param dp;
+
+ dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS;
+ if (wsdisplay_get_param(sc, &dp))
+ return;
+
+ dp.curval = dp.min;
+ wsdisplay_set_param(sc, &dp);
+}
+
+void
+wsdisplay_brightness_cycle(struct device *dev)
+{
+ struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
+ struct wsdisplay_param dp;
+
+ dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS;
+ if (wsdisplay_get_param(sc, &dp))
+ return;
+
+ if (dp.curval == dp.max)
+ wsdisplay_brightness_zero(dev);
+ else
+ wsdisplay_brightness_step(dev, 1);
+}
+
#ifdef HAVE_WSMOUSED_SUPPORT
/*
* wsmoused(8) support functions