On Thu, Jan 23, 2020 at 11:25:51PM +0100, Mark Kettenis wrote:
> Since acpi_set_brightness() can be called from anywhere, it should really
> use the acpi task queue to do its thing instead of calling AML directly.

I didn't know there's an acpi task queue, so that's awesome!  I just saw
that acpithinkpad(4) also uses that.  Changing this diff to do it that
way was also quite easy, so this should read much better.  Feel free to
give it a go.

ok?

Patrick

diff --git a/sys/dev/acpi/acpivout.c b/sys/dev/acpi/acpivout.c
index 58e8e3d431c..89922f4723b 100644
--- a/sys/dev/acpi/acpivout.c
+++ b/sys/dev/acpi/acpivout.c
@@ -60,14 +60,17 @@ struct acpivout_softc {
 
        int     *sc_bcl;
        size_t  sc_bcl_len;
+
+       int     sc_brightness;
 };
 
 void   acpivout_brightness_cycle(struct acpivout_softc *);
 void   acpivout_brightness_step(struct acpivout_softc *, int);
 void   acpivout_brightness_zero(struct acpivout_softc *);
 int    acpivout_get_brightness(struct acpivout_softc *);
+int    acpivout_select_brightness(struct acpivout_softc *, int);
 int    acpivout_find_brightness(struct acpivout_softc *, int);
-void   acpivout_set_brightness(struct acpivout_softc *, int);
+void   acpivout_set_brightness(void *, int);
 void   acpivout_get_bcl(struct acpivout_softc *);
 
 /* wconsole hook functions */
@@ -117,6 +120,8 @@ acpivout_attach(struct device *parent, struct device *self, 
void *aux)
        ws_set_param = acpivout_set_param;
 
        acpivout_get_bcl(sc);
+
+       sc->sc_brightness = acpivout_get_brightness(sc);
 }
 
 int
@@ -124,6 +129,9 @@ acpivout_notify(struct aml_node *node, int notify, void 
*arg)
 {
        struct acpivout_softc *sc = arg;
 
+       if (ws_get_param == NULL || ws_set_param == NULL)
+               return (0);
+
        switch (notify) {
        case NOTIFY_BRIGHTNESS_CYCLE:
                acpivout_brightness_cycle(sc);
@@ -151,12 +159,13 @@ acpivout_notify(struct aml_node *node, int notify, void 
*arg)
 void
 acpivout_brightness_cycle(struct acpivout_softc *sc)
 {
-       int     cur_level;
+       struct wsdisplay_param dp;
 
-       if (sc->sc_bcl_len == 0)
+       dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS;
+       if (ws_get_param(&dp))
                return;
-       cur_level = acpivout_get_brightness(sc);
-       if (cur_level == sc->sc_bcl[sc->sc_bcl_len - 1])
+
+       if (dp.curval == dp.max)
                acpivout_brightness_zero(sc);
        else
                acpivout_brightness_step(sc, 1);
@@ -165,33 +174,45 @@ acpivout_brightness_cycle(struct acpivout_softc *sc)
 void
 acpivout_brightness_step(struct acpivout_softc *sc, int dir)
 {
-       int level, nindex;
+       struct wsdisplay_param dp;
+       int delta, new;
 
-       if (sc->sc_bcl_len == 0)
-               return;
-       level = acpivout_get_brightness(sc);
-       if (level == -1)
+       dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS;
+       if (ws_get_param(&dp))
                return;
 
-       nindex = acpivout_find_brightness(sc, level + (dir * BRIGHTNESS_STEP));
-       if (sc->sc_bcl[nindex] == level) {
-               if (dir == 1 && (nindex + 1 < sc->sc_bcl_len))
-                       nindex++;
-               else if (dir == -1 && (nindex - 1 >= 0))
-                       nindex--;
+       new = dp.curval;
+       delta = ((dp.max - dp.min) * BRIGHTNESS_STEP) / 100;
+       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 (sc->sc_bcl[nindex] == level)
+
+       if (dp.curval == new)
                return;
 
-       acpivout_set_brightness(sc, sc->sc_bcl[nindex]);
+       dp.curval = new;
+       ws_set_param(&dp);
 }
 
 void
 acpivout_brightness_zero(struct acpivout_softc *sc)
 {
-       if (sc->sc_bcl_len == 0)
+       struct wsdisplay_param dp;
+
+       dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS;
+       if (ws_get_param(&dp))
                return;
-       acpivout_set_brightness(sc, sc->sc_bcl[0]);
+
+       dp.curval = dp.min;
+       ws_set_param(&dp);
 }
 
 int
@@ -211,6 +232,26 @@ acpivout_get_brightness(struct acpivout_softc *sc)
        return (level);
 }
 
+int
+acpivout_select_brightness(struct acpivout_softc *sc, int nlevel)
+{
+       int nindex, level;
+
+       level = sc->sc_brightness;
+       if (level == -1)
+               return level;
+
+       nindex = acpivout_find_brightness(sc, nlevel);
+       if (sc->sc_bcl[nindex] == level) {
+               if (nlevel > level && (nindex + 1 < sc->sc_bcl_len))
+                       nindex++;
+               else if (nlevel < level && (nindex - 1 >= 0))
+                       nindex--;
+       }
+
+       return nindex;
+}
+
 int
 acpivout_find_brightness(struct acpivout_softc *sc, int level)
 {
@@ -230,15 +271,16 @@ acpivout_find_brightness(struct acpivout_softc *sc, int 
level)
 }
 
 void
-acpivout_set_brightness(struct acpivout_softc *sc, int level)
+acpivout_set_brightness(void *arg0, int arg1)
 {
+       struct acpivout_softc *sc = arg0;
        struct aml_value args, res;
 
        memset(&args, 0, sizeof(args));
-       args.v_integer = level;
+       args.v_integer = sc->sc_brightness;
        args.type = AML_OBJTYPE_INTEGER;
 
-       DPRINTF(("%s: BCM = %d\n", DEVNAME(sc), level));
+       DPRINTF(("%s: BCM = %d\n", DEVNAME(sc), sc->sc_brightness));
        aml_evalname(sc->sc_acpi, sc->sc_devnode, "_BCM", 1, &args, &res);
 
        aml_freevalue(&res);
@@ -304,12 +346,9 @@ acpivout_get_param(struct wsdisplay_param *dp)
                }
                if (sc != NULL && sc->sc_bcl_len != 0) {
                        dp->min = 0;
-                       dp->max =  sc->sc_bcl[sc->sc_bcl_len - 1];
-                       rw_enter_write(&sc->sc_acpi->sc_lck);
-                       dp->curval = acpivout_get_brightness(sc);
-                       rw_exit_write(&sc->sc_acpi->sc_lck);
-                       if (dp->curval != -1)
-                               return 0;
+                       dp->max = sc->sc_bcl[sc->sc_bcl_len - 1];
+                       dp->curval = sc->sc_brightness;
+                       return 0;
                }
                return -1;
        default:
@@ -334,11 +373,14 @@ acpivout_set_param(struct wsdisplay_param *dp)
                                break;
                }
                if (sc != NULL && sc->sc_bcl_len != 0) {
-                       rw_enter_write(&sc->sc_acpi->sc_lck);
-                       nindex = acpivout_find_brightness(sc, dp->curval);
-                       acpivout_set_brightness(sc, sc->sc_bcl[nindex]);
-                       rw_exit_write(&sc->sc_acpi->sc_lck);
-                       return 0;
+                       nindex = acpivout_select_brightness(sc, dp->curval);
+                       if (nindex != -1) {
+                               sc->sc_brightness = sc->sc_bcl[nindex];
+                               acpi_addtask(sc->sc_acpi,
+                                   acpivout_set_brightness, sc, 0);
+                               acpi_wakeup(sc->sc_acpi);
+                               return 0;
+                       }
                }
                return -1;
        default:

Reply via email to