Re: acpivout: try to consistently adjust brightness by 5%
On Mon, Jan 13, 2020 at 12:20:10PM +0100, Patrick Wildt wrote: > The problem is that the last two values are 67 and 100. If you go > 5% down, it's 95. The nearest will still be 100. The code then > realizes that it's the same level as before, and does nlevel--. > But nlevel-- is 99, and not 67, because nlevel is the value and > not the index of the bcl array. So in essence the change needed > is to decrease the index, not the value, and then look up the value. Disucssing this over dinner again, patrick and I independently came up with the very same diff below. It makes acpivout_find_brightness() return an index instead a level for the selected brightness. Just works on my X230; I can go through every level with the function keys and verify with xbacklight(1) that I am indeed not skipping any of the 16 levels in either direction. OK? Index: acpivout.c === RCS file: /cvs/src/sys/dev/acpi/acpivout.c,v retrieving revision 1.16 diff -u -p -r1.16 acpivout.c --- acpivout.c 14 Dec 2019 10:57:48 - 1.16 +++ acpivout.c 14 Jan 2020 18:50:23 - @@ -165,7 +165,7 @@ acpivout_brightness_cycle(struct acpivou void acpivout_brightness_step(struct acpivout_softc *sc, int dir) { - int level, nlevel; + int level, nindex; if (sc->sc_bcl_len == 0) return; @@ -173,17 +173,17 @@ acpivout_brightness_step(struct acpivout if (level == -1) return; - nlevel = acpivout_find_brightness(sc, level + (dir * BRIGHTNESS_STEP)); - if (nlevel == level) { - if (dir == 1 && (nlevel + 1 < sc->sc_bcl_len)) - nlevel++; - else if (dir == -1 && (nlevel - 1 >= 0)) - nlevel--; + 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--; } - if (nlevel == level) + if (sc->sc_bcl[nindex] == level) return; - acpivout_set_brightness(sc, nlevel); + acpivout_set_brightness(sc, sc->sc_bcl[nindex]); } void @@ -219,14 +219,14 @@ acpivout_find_brightness(struct acpivout for (i = 0; i < sc->sc_bcl_len - 1; i++) { mid = sc->sc_bcl[i] + (sc->sc_bcl[i + 1] - sc->sc_bcl[i]) / 2; if (sc->sc_bcl[i] <= level && level <= mid) - return sc->sc_bcl[i]; + return i; if (mid < level && level <= sc->sc_bcl[i + 1]) - return sc->sc_bcl[i + 1]; + return i + 1; } if (level < sc->sc_bcl[0]) - return sc->sc_bcl[0]; + return 0; else - return sc->sc_bcl[i]; + return i; } void @@ -321,7 +321,7 @@ int acpivout_set_param(struct wsdisplay_param *dp) { struct acpivout_softc *sc = NULL; - int i, exact; + int i, nindex; switch (dp->param) { case WSDISPLAYIO_PARAM_BRIGHTNESS: @@ -335,8 +335,8 @@ acpivout_set_param(struct wsdisplay_para } if (sc != NULL && sc->sc_bcl_len != 0) { rw_enter_write(&sc->sc_acpi->sc_lck); - exact = acpivout_find_brightness(sc, dp->curval); - acpivout_set_brightness(sc, exact); + 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; }
Re: acpivout: try to consistently adjust brightness by 5%
On Mon, Jan 13, 2020 at 12:20:10PM +0100, Patrick Wildt wrote: > The problem is that the last two values are 67 and 100. If you go > 5% down, it's 95. The nearest will still be 100. The code then > realizes that it's the same level as before, and does nlevel--. > But nlevel-- is 99, and not 67, because nlevel is the value and > not the index of the bcl array. So in essence the change needed > is to decrease the index, not the value, and then look up the value. That's what happens, but the problem isn't that my machine is lacking levels between 67 and 100. Rather, acpivout_find_brightness() seems to linear scale in levels (which presumably is the case on newer machines), but my machine's levels scale exponentially. Diff below comments on this and hilights the two relevant checks: Given an initial brightness of 100% (the last level), pressing the function key to decrease the level eventually calls acpivout_find_brightness() with `level = 100 + (-1 * 5) = 95', it then iterates over the levels starting with the smallest. Reaching the second last level (67 on my machine), the loop's body does mid = 67 + (100 - 67) / 2 = 83; if (67 <= 95 && 95 <= 83) return 67; if (83 <= 95 and 95 <= 100) return 100; So for requesting level below 100 it always returns 100 itself because the next level has a value of 67 which is way out of the 5% threshold this algorithm assumes. I suppose a better heuristic is required to make both linearly and exponentially scaling machines happy, but this is currently too finicky for me so I just reverted 1.14 in my tree. Index: acpivout.c === RCS file: /cvs/src/sys/dev/acpi/acpivout.c,v retrieving revision 1.16 diff -u -p -r1.16 acpivout.c --- acpivout.c 14 Dec 2019 10:57:48 - 1.16 +++ acpivout.c 14 Jan 2020 14:19:08 - @@ -218,6 +218,11 @@ acpivout_find_brightness(struct acpivout for (i = 0; i < sc->sc_bcl_len - 1; i++) { mid = sc->sc_bcl[i] + (sc->sc_bcl[i + 1] - sc->sc_bcl[i]) / 2; + /* +* XXX these checks assume levels to be on a linear scale, +* but some hardware provides exponentially scaled brightness +* levels (ThinkPad X230, T420). +*/ if (sc->sc_bcl[i] <= level && level <= mid) return sc->sc_bcl[i]; if (mid < level && level <= sc->sc_bcl[i + 1])
Re: acpivout: try to consistently adjust brightness by 5%
On Mon, Jan 13, 2020 at 11:58:11AM +0100, Klemens Nanni wrote: > On Sun, Oct 13, 2019 at 09:28:26PM -0500, joshua stein wrote: > > When responding to hardware keys to increment or decrement screen > > brightness, don't just adjust by 1 BCL level as there may be 100 > > levels. Find the next brightness level that is at least 5% up or > > down, and use that. > revision 1.14 > date: 2019/10/21 16:32:51; author: jcs; state: Exp; lines: +20 -33; > When incrementing or decrementing screen brightness, don't just > adjust by 1 BCL level as there may be 100 levels. Find the next > brightness level that is at least 5% up or down and use that. > > ok kettenis > > This diff broke backlight adjustment on my X230: With 100% screen > brightness, pressing the function keys to *de*crease it won't do > anything. Booting a kernel with ACPIVIDEO_DEBUG suggests that > acpivout_find_brightness() is unable to find the next level below 100% > that is at least 5% less than the full brightness, hence it returns > something above 95% such that acpivout_brightness_step() gets stuck and > will set brightness to 100% again. > > `xbacklight -50' will properly decrease brightness to 50%, then the > function keys also work and I can decrease to 44% as the immediate lower > level, however increasing it again never works and is stuck at 44%. > > In general, setting a lower brightness level with xbacklight(1) makes > the function keys work but only ever in the range of [0, n) -- I can > never reach a higher level than set with xbacklight. > > `xbacklight +100' works and reverting avpivout.c revision 1.14 makes > everything work again for me. > > tobhe has the exact same issues on his T420. > > Below is diff to show my X230 brightness levels, dmesg as well. The problem is that the last two values are 67 and 100. If you go 5% down, it's 95. The nearest will still be 100. The code then realizes that it's the same level as before, and does nlevel--. But nlevel-- is 99, and not 67, because nlevel is the value and not the index of the bcl array. So in essence the change needed is to decrease the index, not the value, and then look up the value. Patrick
Re: acpivout: try to consistently adjust brightness by 5%
On Sun, Oct 13, 2019 at 09:28:26PM -0500, joshua stein wrote: > When responding to hardware keys to increment or decrement screen > brightness, don't just adjust by 1 BCL level as there may be 100 > levels. Find the next brightness level that is at least 5% up or > down, and use that. revision 1.14 date: 2019/10/21 16:32:51; author: jcs; state: Exp; lines: +20 -33; When incrementing or decrementing screen brightness, don't just adjust by 1 BCL level as there may be 100 levels. Find the next brightness level that is at least 5% up or down and use that. ok kettenis This diff broke backlight adjustment on my X230: With 100% screen brightness, pressing the function keys to *de*crease it won't do anything. Booting a kernel with ACPIVIDEO_DEBUG suggests that acpivout_find_brightness() is unable to find the next level below 100% that is at least 5% less than the full brightness, hence it returns something above 95% such that acpivout_brightness_step() gets stuck and will set brightness to 100% again. `xbacklight -50' will properly decrease brightness to 50%, then the function keys also work and I can decrease to 44% as the immediate lower level, however increasing it again never works and is stuck at 44%. In general, setting a lower brightness level with xbacklight(1) makes the function keys work but only ever in the range of [0, n) -- I can never reach a higher level than set with xbacklight. `xbacklight +100' works and reverting avpivout.c revision 1.14 makes everything work again for me. tobhe has the exact same issues on his T420. Below is diff to show my X230 brightness levels, dmesg as well. Index: dev/acpi/acpivout.c === RCS file: /cvs/src/sys/dev/acpi/acpivout.c,v retrieving revision 1.16 diff -u -p -r1.16 acpivout.c --- dev/acpi/acpivout.c 14 Dec 2019 10:57:48 - 1.16 +++ dev/acpi/acpivout.c 13 Jan 2020 10:47:13 - @@ -34,6 +34,7 @@ int acpivout_match(struct device *, void void acpivout_attach(struct device *, struct device *, void *); intacpivout_notify(struct aml_node *, int, void *); +#define ACPIVIDEO_DEBUG #ifdef ACPIVIDEO_DEBUG #define DPRINTF(x) printf x #else @@ -215,6 +216,9 @@ int acpivout_find_brightness(struct acpivout_softc *sc, int level) { int i, mid; + + for (i = 0; i < sc->sc_bcl_len; i++) + printf("%s: sc->sc_bcl[%d]: %d\n", __func__, i, sc->sc_bcl[i]); for (i = 0; i < sc->sc_bcl_len - 1; i++) { mid = sc->sc_bcl[i] + (sc->sc_bcl[i + 1] - sc->sc_bcl[i]) / 2; OpenBSD 6.6-current (GENERIC.MP) #3: Mon Jan 13 11:47:31 CET 2020 k...@eru.my.domain:/sys/arch/amd64/compile/GENERIC.MP real mem = 17118126080 (16325MB) avail mem = 16586883072 (15818MB) mpath0 at root scsibus0 at mpath0: 256 targets mainbus0 at root bios0 at mainbus0: SMBIOS rev. 2.8 @ 0xbff31020 (17 entries) bios0: vendor coreboot version "CBET4000 x230-seabios" date 01/07/2020 bios0: LENOVO 2325A95 acpi0 at bios0: ACPI 4.0 acpi0: sleep states S0 S3 S4 S5 acpi0: tables DSDT FACP SSDT MCFG TCPA APIC DMAR HPET acpi0: wakeup devices HDEF(S4) EHC1(S4) EHC2(S4) XHC_(S4) SLPB(S3) LID_(S3) acpitimer0 at acpi0: 3579545 Hz, 24 bits acpimcfg0 at acpi0 acpimcfg0: addr 0xf000, bus 0-63 acpimadt0 at acpi0 addr 0xfee0: PC-AT compat cpu0 at mainbus0: apid 0 (boot processor) cpu0: Intel(R) Core(TM) i5-3320M CPU @ 2.60GHz, 2594.47 MHz, 06-3a-09 cpu0: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,SMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,RDTSCP,LONG,LAHF,PERF,ITSC,FSGSBASE,SMEP,ERMS,MD_CLEAR,IBRS,IBPB,STIBP,L1DF,SSBD,SENSOR,ARAT,XSAVEOPT,MELTDOWN cpu0: 256KB 64b/line 8-way L2 cache cpu0: smt 0, core 0, package 0 mtrr: Pentium Pro MTRR support, 10 var ranges, 88 fixed ranges cpu0: apic clock running at 99MHz cpu0: mwait min=64, max=64, C-substates=0.2.1.1.2, IBE cpu1 at mainbus0: apid 1 (application processor) cpu1: Intel(R) Core(TM) i5-3320M CPU @ 2.60GHz, 2594.11 MHz, 06-3a-09 cpu1: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,SMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,RDTSCP,LONG,LAHF,PERF,ITSC,FSGSBASE,SMEP,ERMS,MD_CLEAR,IBRS,IBPB,STIBP,L1DF,SSBD,SENSOR,ARAT,XSAVEOPT,MELTDOWN cpu1: 256KB 64b/line 8-way L2 cache cpu1: smt 1, core 0, package 0 cpu2 at mainbus0: apid 2 (application processor) cpu2: Intel(R) Core(TM) i5-3320M CPU @ 2.60GHz, 2594.12 MHz, 06-3a-09 cpu2: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,SMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,POPCN
Re: acpivout: try to consistently adjust brightness by 5%
> Date: Sun, 13 Oct 2019 21:28:26 -0500 > From: joshua stein > > When responding to hardware keys to increment or decrement screen > brightness, don't just adjust by 1 BCL level as there may be 100 > levels. Find the next brightness level that is at least 5% up or > down, and use that. I suspect we want the same behaviour in wskbd(4) as well if the hardware supports a lot of steps. But this is a step forward in itself. ok kettenis@ > Index: dev/acpi/acpivout.c > === > RCS file: /cvs/src/sys/dev/acpi/acpivout.c,v > retrieving revision 1.13 > diff -u -p -u -p -r1.13 acpivout.c > --- dev/acpi/acpivout.c 13 Oct 2019 10:56:31 - 1.13 > +++ dev/acpi/acpivout.c 14 Oct 2019 02:26:12 - > @@ -47,6 +47,8 @@ int acpivout_notify(struct aml_node *, i > #define NOTIFY_BRIGHTNESS_ZERO 0x88 > #define NOTIFY_DISPLAY_OFF 0x89 > > +#define BRIGHTNESS_STEP 5 > + > struct acpivout_softc { > struct device sc_dev; > > @@ -61,8 +63,7 @@ struct acpivout_softc { > }; > > void acpivout_brightness_cycle(struct acpivout_softc *); > -void acpivout_brightness_up(struct acpivout_softc *); > -void acpivout_brightness_down(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_find_brightness(struct acpivout_softc *, int); > @@ -128,10 +129,10 @@ acpivout_notify(struct aml_node *node, i > acpivout_brightness_cycle(sc); > break; > case NOTIFY_BRIGHTNESS_UP: > - acpivout_brightness_up(sc); > + acpivout_brightness_step(sc, 1); > break; > case NOTIFY_BRIGHTNESS_DOWN: > - acpivout_brightness_down(sc); > + acpivout_brightness_step(sc, -1); > break; > case NOTIFY_BRIGHTNESS_ZERO: > acpivout_brightness_zero(sc); > @@ -158,45 +159,31 @@ acpivout_brightness_cycle(struct acpivou > if (cur_level == sc->sc_bcl[sc->sc_bcl_len - 1]) > acpivout_brightness_zero(sc); > else > - acpivout_brightness_up(sc); > -} > - > -void > -acpivout_brightness_up(struct acpivout_softc *sc) > -{ > - int i, cur_level; > - > - if (sc->sc_bcl_len == 0) > - return; > - cur_level = acpivout_get_brightness(sc); > - if (cur_level == -1) > - return; > - > - /* check for max brightness level */ > - if (cur_level == sc->sc_bcl[sc->sc_bcl_len - 1]) > - return; > - > - for (i = 0; i < sc->sc_bcl_len && cur_level != sc->sc_bcl[i]; i++); > - acpivout_set_brightness(sc, sc->sc_bcl[i + 1]); > + acpivout_brightness_step(sc, 1); > } > > void > -acpivout_brightness_down(struct acpivout_softc *sc) > +acpivout_brightness_step(struct acpivout_softc *sc, int dir) > { > - int i, cur_level; > + int level, nlevel; > > if (sc->sc_bcl_len == 0) > return; > - cur_level = acpivout_get_brightness(sc); > - if (cur_level == -1) > + level = acpivout_get_brightness(sc); > + if (level == -1) > return; > > - /* check for min brightness level */ > - if (cur_level == sc->sc_bcl[0]) > + nlevel = acpivout_find_brightness(sc, level + (dir * BRIGHTNESS_STEP)); > + if (nlevel == level) { > + if (dir == 1 && (nlevel + 1 < sc->sc_bcl_len)) > + nlevel++; > + else if (dir == -1 && (nlevel - 1 >= 0)) > + nlevel--; > + } > + if (nlevel == level) > return; > > - for (i = 0; i < sc->sc_bcl_len && cur_level != sc->sc_bcl[i]; i++); > - acpivout_set_brightness(sc, sc->sc_bcl[i - 1]); > + acpivout_set_brightness(sc, nlevel); > } > > void > >
Re: acpivout: try to consistently adjust brightness by 5%
Patch works well on a T470s. Stepping is better in the larger increments. No ill effects from the patch here. Thanks, Tracey On Sun, Oct 13, 2019 at 09:28:26PM -0500, joshua stein wrote: > When responding to hardware keys to increment or decrement screen > brightness, don't just adjust by 1 BCL level as there may be 100 > levels. Find the next brightness level that is at least 5% up or > down, and use that. > > > Index: dev/acpi/acpivout.c > === > RCS file: /cvs/src/sys/dev/acpi/acpivout.c,v > retrieving revision 1.13 > diff -u -p -u -p -r1.13 acpivout.c > --- dev/acpi/acpivout.c 13 Oct 2019 10:56:31 - 1.13 > +++ dev/acpi/acpivout.c 14 Oct 2019 02:26:12 - > @@ -47,6 +47,8 @@ int acpivout_notify(struct aml_node *, i > #define NOTIFY_BRIGHTNESS_ZERO 0x88 > #define NOTIFY_DISPLAY_OFF 0x89 > > +#define BRIGHTNESS_STEP 5 > + > struct acpivout_softc { > struct device sc_dev; > > @@ -61,8 +63,7 @@ struct acpivout_softc { > }; > > void acpivout_brightness_cycle(struct acpivout_softc *); > -void acpivout_brightness_up(struct acpivout_softc *); > -void acpivout_brightness_down(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_find_brightness(struct acpivout_softc *, int); > @@ -128,10 +129,10 @@ acpivout_notify(struct aml_node *node, i > acpivout_brightness_cycle(sc); > break; > case NOTIFY_BRIGHTNESS_UP: > - acpivout_brightness_up(sc); > + acpivout_brightness_step(sc, 1); > break; > case NOTIFY_BRIGHTNESS_DOWN: > - acpivout_brightness_down(sc); > + acpivout_brightness_step(sc, -1); > break; > case NOTIFY_BRIGHTNESS_ZERO: > acpivout_brightness_zero(sc); > @@ -158,45 +159,31 @@ acpivout_brightness_cycle(struct acpivou > if (cur_level == sc->sc_bcl[sc->sc_bcl_len - 1]) > acpivout_brightness_zero(sc); > else > - acpivout_brightness_up(sc); > -} > - > -void > -acpivout_brightness_up(struct acpivout_softc *sc) > -{ > - int i, cur_level; > - > - if (sc->sc_bcl_len == 0) > - return; > - cur_level = acpivout_get_brightness(sc); > - if (cur_level == -1) > - return; > - > - /* check for max brightness level */ > - if (cur_level == sc->sc_bcl[sc->sc_bcl_len - 1]) > - return; > - > - for (i = 0; i < sc->sc_bcl_len && cur_level != sc->sc_bcl[i]; i++); > - acpivout_set_brightness(sc, sc->sc_bcl[i + 1]); > + acpivout_brightness_step(sc, 1); > } > > void > -acpivout_brightness_down(struct acpivout_softc *sc) > +acpivout_brightness_step(struct acpivout_softc *sc, int dir) > { > - int i, cur_level; > + int level, nlevel; > > if (sc->sc_bcl_len == 0) > return; > - cur_level = acpivout_get_brightness(sc); > - if (cur_level == -1) > + level = acpivout_get_brightness(sc); > + if (level == -1) > return; > > - /* check for min brightness level */ > - if (cur_level == sc->sc_bcl[0]) > + nlevel = acpivout_find_brightness(sc, level + (dir * BRIGHTNESS_STEP)); > + if (nlevel == level) { > + if (dir == 1 && (nlevel + 1 < sc->sc_bcl_len)) > + nlevel++; > + else if (dir == -1 && (nlevel - 1 >= 0)) > + nlevel--; > + } > + if (nlevel == level) > return; > > - for (i = 0; i < sc->sc_bcl_len && cur_level != sc->sc_bcl[i]; i++); > - acpivout_set_brightness(sc, sc->sc_bcl[i - 1]); > + acpivout_set_brightness(sc, nlevel); > } > > void -- Tracey Emery
acpivout: try to consistently adjust brightness by 5%
When responding to hardware keys to increment or decrement screen brightness, don't just adjust by 1 BCL level as there may be 100 levels. Find the next brightness level that is at least 5% up or down, and use that. Index: dev/acpi/acpivout.c === RCS file: /cvs/src/sys/dev/acpi/acpivout.c,v retrieving revision 1.13 diff -u -p -u -p -r1.13 acpivout.c --- dev/acpi/acpivout.c 13 Oct 2019 10:56:31 - 1.13 +++ dev/acpi/acpivout.c 14 Oct 2019 02:26:12 - @@ -47,6 +47,8 @@ int acpivout_notify(struct aml_node *, i #define NOTIFY_BRIGHTNESS_ZERO 0x88 #define NOTIFY_DISPLAY_OFF 0x89 +#define BRIGHTNESS_STEP5 + struct acpivout_softc { struct device sc_dev; @@ -61,8 +63,7 @@ struct acpivout_softc { }; void acpivout_brightness_cycle(struct acpivout_softc *); -void acpivout_brightness_up(struct acpivout_softc *); -void acpivout_brightness_down(struct acpivout_softc *); +void acpivout_brightness_step(struct acpivout_softc *, int); void acpivout_brightness_zero(struct acpivout_softc *); intacpivout_get_brightness(struct acpivout_softc *); intacpivout_find_brightness(struct acpivout_softc *, int); @@ -128,10 +129,10 @@ acpivout_notify(struct aml_node *node, i acpivout_brightness_cycle(sc); break; case NOTIFY_BRIGHTNESS_UP: - acpivout_brightness_up(sc); + acpivout_brightness_step(sc, 1); break; case NOTIFY_BRIGHTNESS_DOWN: - acpivout_brightness_down(sc); + acpivout_brightness_step(sc, -1); break; case NOTIFY_BRIGHTNESS_ZERO: acpivout_brightness_zero(sc); @@ -158,45 +159,31 @@ acpivout_brightness_cycle(struct acpivou if (cur_level == sc->sc_bcl[sc->sc_bcl_len - 1]) acpivout_brightness_zero(sc); else - acpivout_brightness_up(sc); -} - -void -acpivout_brightness_up(struct acpivout_softc *sc) -{ - int i, cur_level; - - if (sc->sc_bcl_len == 0) - return; - cur_level = acpivout_get_brightness(sc); - if (cur_level == -1) - return; - - /* check for max brightness level */ - if (cur_level == sc->sc_bcl[sc->sc_bcl_len - 1]) - return; - - for (i = 0; i < sc->sc_bcl_len && cur_level != sc->sc_bcl[i]; i++); - acpivout_set_brightness(sc, sc->sc_bcl[i + 1]); + acpivout_brightness_step(sc, 1); } void -acpivout_brightness_down(struct acpivout_softc *sc) +acpivout_brightness_step(struct acpivout_softc *sc, int dir) { - int i, cur_level; + int level, nlevel; if (sc->sc_bcl_len == 0) return; - cur_level = acpivout_get_brightness(sc); - if (cur_level == -1) + level = acpivout_get_brightness(sc); + if (level == -1) return; - /* check for min brightness level */ - if (cur_level == sc->sc_bcl[0]) + nlevel = acpivout_find_brightness(sc, level + (dir * BRIGHTNESS_STEP)); + if (nlevel == level) { + if (dir == 1 && (nlevel + 1 < sc->sc_bcl_len)) + nlevel++; + else if (dir == -1 && (nlevel - 1 >= 0)) + nlevel--; + } + if (nlevel == level) return; - for (i = 0; i < sc->sc_bcl_len && cur_level != sc->sc_bcl[i]; i++); - acpivout_set_brightness(sc, sc->sc_bcl[i - 1]); + acpivout_set_brightness(sc, nlevel); } void