Patrick Wildt schreef op 2020-01-23 08:26:
Hi,
this is the second attempt of a diff that prepares acpivout(4) to work
with the X395. The previous one broke due to recursive ACPI locking.
So apparently we cannot change the brightness using the acpivout(4)
ACPI
methods. Instead we need to call amdgpu(4) to change the brightness.
But the brightness key events are still reported by acpivout(4). That
means that we need to seperate the keystroke events from the actual
brightness change.
This diff changes the code to always use ws_[gs]et_param instead of
just
calling the ACPI methods. This means that the function pointers can
point to acpivout(4) or amdgpu(4), it shouldn't matter.
Unfortunately there's an issue with acpivout(4) calling itself. The
keystroke event handler runs with the ACPI lock, so if we call our own
function, we try to grab the ACPI lock again and panic. So, in this
diff I check whether we already have it and skip taking it again.
I'm sure this looks ugly, and I'm wondering if it's too ugly. If it is
indeed too ugly, I hope you'll also provide another idea how we can
work
around it.
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.
More testing would be appreciated.
Thanks,
Patrick
diff --git a/sys/dev/acpi/acpivout.c b/sys/dev/acpi/acpivout.c
index 58e8e3d431c..f3de0c582fb 100644
--- a/sys/dev/acpi/acpivout.c
+++ b/sys/dev/acpi/acpivout.c
@@ -66,6 +66,7 @@ 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_get_bcl(struct acpivout_softc *);
@@ -124,6 +125,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 +155,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 +170,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 +228,26 @@ acpivout_get_brightness(struct acpivout_softc *sc)
return (level);
}
+int
+acpivout_select_brightness(struct acpivout_softc *sc, int nlevel)
+{
+ int nindex, level;
+
+ level = acpivout_get_brightness(sc);
+ 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)
{
@@ -290,7 +327,7 @@ int
acpivout_get_param(struct wsdisplay_param *dp)
{
struct acpivout_softc *sc = NULL;
- int i;
+ int i, needlock;
switch (dp->param) {
case WSDISPLAYIO_PARAM_BRIGHTNESS:
@@ -304,10 +341,13 @@ 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->max = sc->sc_bcl[sc->sc_bcl_len - 1];
+ needlock = rw_status(&sc->sc_acpi->sc_lck) != RW_WRITE;
+ if (needlock)
+ rw_enter_write(&sc->sc_acpi->sc_lck);
dp->curval = acpivout_get_brightness(sc);
- rw_exit_write(&sc->sc_acpi->sc_lck);
+ if (needlock)
+ rw_exit_write(&sc->sc_acpi->sc_lck);
if (dp->curval != -1)
return 0;
}
@@ -321,7 +361,7 @@ int
acpivout_set_param(struct wsdisplay_param *dp)
{
struct acpivout_softc *sc = NULL;
- int i, nindex;
+ int i, nindex, needlock;
switch (dp->param) {
case WSDISPLAYIO_PARAM_BRIGHTNESS:
@@ -334,10 +374,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);
+ needlock = rw_status(&sc->sc_acpi->sc_lck) != RW_WRITE;
+ if (needlock)
+ rw_enter_write(&sc->sc_acpi->sc_lck);
+ nindex = acpivout_select_brightness(sc, dp->curval);
+ if (nindex != -1)
+ acpivout_set_brightness(sc, sc->sc_bcl[nindex]);
+ if (needlock)
+ rw_exit_write(&sc->sc_acpi->sc_lck);
return 0;
}
return -1;