Add support for PWM backlights.
This commit is contained in:
parent
2a22daa1c9
commit
39f9e242ac
116
sys/dev/fdt/fdt_pwm.c
Normal file
116
sys/dev/fdt/fdt_pwm.c
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
/* $NetBSD: fdt_pwm.c,v 1.1 2018/05/06 10:33:21 jmcneill Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__KERNEL_RCSID(0, "$NetBSD: fdt_pwm.c,v 1.1 2018/05/06 10:33:21 jmcneill Exp $");
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
#include <sys/kmem.h>
|
||||||
|
|
||||||
|
#include <libfdt.h>
|
||||||
|
#include <dev/fdt/fdtvar.h>
|
||||||
|
|
||||||
|
struct fdtbus_pwm_controller {
|
||||||
|
device_t pc_dev;
|
||||||
|
int pc_phandle;
|
||||||
|
const struct fdtbus_pwm_controller_func *pc_funcs;
|
||||||
|
|
||||||
|
struct fdtbus_pwm_controller *pc_next;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct fdtbus_pwm_controller *fdtbus_pc = NULL;
|
||||||
|
|
||||||
|
int
|
||||||
|
fdtbus_register_pwm_controller(device_t dev, int phandle,
|
||||||
|
const struct fdtbus_pwm_controller_func *funcs)
|
||||||
|
{
|
||||||
|
struct fdtbus_pwm_controller *pc;
|
||||||
|
|
||||||
|
pc = kmem_alloc(sizeof(*pc), KM_SLEEP);
|
||||||
|
pc->pc_dev = dev;
|
||||||
|
pc->pc_phandle = phandle;
|
||||||
|
pc->pc_funcs = funcs;
|
||||||
|
|
||||||
|
pc->pc_next = fdtbus_pc;
|
||||||
|
fdtbus_pc = pc;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct fdtbus_pwm_controller *
|
||||||
|
fdtbus_get_pwm_controller(int phandle)
|
||||||
|
{
|
||||||
|
struct fdtbus_pwm_controller *pc;
|
||||||
|
|
||||||
|
for (pc = fdtbus_pc; pc; pc = pc->pc_next) {
|
||||||
|
if (pc->pc_phandle == phandle) {
|
||||||
|
return pc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pwm_tag_t
|
||||||
|
fdtbus_pwm_acquire(int phandle, const char *prop)
|
||||||
|
{
|
||||||
|
return fdtbus_pwm_acquire_index(phandle, prop, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pwm_tag_t
|
||||||
|
fdtbus_pwm_acquire_index(int phandle, const char *prop, int index)
|
||||||
|
{
|
||||||
|
struct fdtbus_pwm_controller *pc;
|
||||||
|
const uint32_t *pwms, *p;
|
||||||
|
u_int n, pwm_cells;
|
||||||
|
int len, resid;
|
||||||
|
|
||||||
|
pwms = fdtbus_get_prop(phandle, prop, &len);
|
||||||
|
if (pwms == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
p = pwms;
|
||||||
|
for (n = 0, resid = len; resid > 0; n++) {
|
||||||
|
const int pc_phandle =
|
||||||
|
fdtbus_get_phandle_from_native(be32toh(p[0]));
|
||||||
|
if (of_getprop_uint32(pc_phandle, "#pwm-cells", &pwm_cells))
|
||||||
|
break;
|
||||||
|
if (n == index) {
|
||||||
|
pc = fdtbus_get_pwm_controller(pc_phandle);
|
||||||
|
if (pc == NULL)
|
||||||
|
return NULL;
|
||||||
|
return pc->pc_funcs->get_tag(pc->pc_dev,
|
||||||
|
&p[0], (pwm_cells + 1) * 4);
|
||||||
|
}
|
||||||
|
resid -= (pwm_cells + 1) * 4;
|
||||||
|
p += pwm_cells + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: fdtvar.h,v 1.29 2018/04/07 18:05:08 bouyer Exp $ */
|
/* $NetBSD: fdtvar.h,v 1.30 2018/05/06 10:33:21 jmcneill Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca>
|
* Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca>
|
||||||
@ -34,6 +34,7 @@
|
|||||||
#include <sys/termios.h>
|
#include <sys/termios.h>
|
||||||
|
|
||||||
#include <dev/i2c/i2cvar.h>
|
#include <dev/i2c/i2cvar.h>
|
||||||
|
#include <dev/pwm/pwmvar.h>
|
||||||
#include <dev/clk/clk.h>
|
#include <dev/clk/clk.h>
|
||||||
|
|
||||||
#include <dev/clock_subr.h>
|
#include <dev/clock_subr.h>
|
||||||
@ -185,6 +186,10 @@ struct fdtbus_phy_controller_func {
|
|||||||
int (*enable)(device_t, void *, bool);
|
int (*enable)(device_t, void *, bool);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct fdtbus_pwm_controller_func {
|
||||||
|
pwm_tag_t (*get_tag)(device_t, const void *, size_t);
|
||||||
|
};
|
||||||
|
|
||||||
struct fdtbus_mmc_pwrseq;
|
struct fdtbus_mmc_pwrseq;
|
||||||
|
|
||||||
struct fdtbus_mmc_pwrseq_func {
|
struct fdtbus_mmc_pwrseq_func {
|
||||||
@ -234,6 +239,8 @@ int fdtbus_register_power_controller(device_t, int,
|
|||||||
const struct fdtbus_power_controller_func *);
|
const struct fdtbus_power_controller_func *);
|
||||||
int fdtbus_register_phy_controller(device_t, int,
|
int fdtbus_register_phy_controller(device_t, int,
|
||||||
const struct fdtbus_phy_controller_func *);
|
const struct fdtbus_phy_controller_func *);
|
||||||
|
int fdtbus_register_pwm_controller(device_t, int,
|
||||||
|
const struct fdtbus_pwm_controller_func *);
|
||||||
int fdtbus_register_mmc_pwrseq(device_t, int,
|
int fdtbus_register_mmc_pwrseq(device_t, int,
|
||||||
const struct fdtbus_mmc_pwrseq_func *);
|
const struct fdtbus_mmc_pwrseq_func *);
|
||||||
|
|
||||||
@ -257,6 +264,8 @@ int fdtbus_gpio_read(struct fdtbus_gpio_pin *);
|
|||||||
void fdtbus_gpio_write(struct fdtbus_gpio_pin *, int);
|
void fdtbus_gpio_write(struct fdtbus_gpio_pin *, int);
|
||||||
int fdtbus_gpio_read_raw(struct fdtbus_gpio_pin *);
|
int fdtbus_gpio_read_raw(struct fdtbus_gpio_pin *);
|
||||||
void fdtbus_gpio_write_raw(struct fdtbus_gpio_pin *, int);
|
void fdtbus_gpio_write_raw(struct fdtbus_gpio_pin *, int);
|
||||||
|
pwm_tag_t fdtbus_pwm_acquire(int, const char *);
|
||||||
|
pwm_tag_t fdtbus_pwm_acquire_index(int, const char *, int);
|
||||||
void fdtbus_pinctrl_configure(void);
|
void fdtbus_pinctrl_configure(void);
|
||||||
int fdtbus_pinctrl_set_config_index(int, u_int);
|
int fdtbus_pinctrl_set_config_index(int, u_int);
|
||||||
int fdtbus_pinctrl_set_config(int, const char *);
|
int fdtbus_pinctrl_set_config(int, const char *);
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
# $NetBSD: files.fdt,v 1.24 2018/05/01 23:59:15 jmcneill Exp $
|
# $NetBSD: files.fdt,v 1.25 2018/05/06 10:33:21 jmcneill Exp $
|
||||||
|
|
||||||
include "external/bsd/libfdt/conf/files.libfdt"
|
include "external/bsd/libfdt/conf/files.libfdt"
|
||||||
|
|
||||||
defflag opt_fdt.h FDT: libfdt, ofw_subr
|
defflag opt_fdt.h FDT: libfdt, ofw_subr
|
||||||
|
|
||||||
define fdtbus { } : clk
|
define fdtbus { } : clk, pwm
|
||||||
|
|
||||||
device fdt { [pass = 10] } : fdtbus
|
device fdt { [pass = 10] } : fdtbus
|
||||||
attach fdt at fdtbus
|
attach fdt at fdtbus
|
||||||
@ -54,6 +54,7 @@ file dev/fdt/fdt_intr.c fdtbus
|
|||||||
file dev/fdt/fdt_mmc_pwrseq.c fdtbus
|
file dev/fdt/fdt_mmc_pwrseq.c fdtbus
|
||||||
file dev/fdt/fdt_phy.c fdtbus
|
file dev/fdt/fdt_phy.c fdtbus
|
||||||
file dev/fdt/fdt_power.c fdtbus
|
file dev/fdt/fdt_power.c fdtbus
|
||||||
|
file dev/fdt/fdt_pwm.c fdtbus
|
||||||
file dev/fdt/fdt_regulator.c fdtbus
|
file dev/fdt/fdt_regulator.c fdtbus
|
||||||
file dev/fdt/fdt_reset.c fdtbus
|
file dev/fdt/fdt_reset.c fdtbus
|
||||||
file dev/fdt/fdt_rtc.c fdtbus
|
file dev/fdt/fdt_rtc.c fdtbus
|
||||||
@ -67,6 +68,10 @@ device mmcpwrseq
|
|||||||
attach mmcpwrseq at fdt
|
attach mmcpwrseq at fdt
|
||||||
file dev/fdt/mmc_pwrseq_simple.c mmcpwrseq
|
file dev/fdt/mmc_pwrseq_simple.c mmcpwrseq
|
||||||
|
|
||||||
|
device pwmbacklight
|
||||||
|
attach pwmbacklight at fdt
|
||||||
|
file dev/fdt/pwm_backlight.c pwmbacklight
|
||||||
|
|
||||||
define fdt_display_timing
|
define fdt_display_timing
|
||||||
file dev/fdt/display_timing.c fdt_display_timing
|
file dev/fdt/display_timing.c fdt_display_timing
|
||||||
|
|
||||||
|
293
sys/dev/fdt/pwm_backlight.c
Normal file
293
sys/dev/fdt/pwm_backlight.c
Normal file
@ -0,0 +1,293 @@
|
|||||||
|
/* $NetBSD: pwm_backlight.c,v 1.1 2018/05/06 10:33:21 jmcneill Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__KERNEL_RCSID(0, "$NetBSD: pwm_backlight.c,v 1.1 2018/05/06 10:33:21 jmcneill Exp $");
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
#include <sys/device.h>
|
||||||
|
#include <sys/systm.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <sys/kmem.h>
|
||||||
|
#include <sys/gpio.h>
|
||||||
|
|
||||||
|
#include <dev/pwm/pwmvar.h>
|
||||||
|
|
||||||
|
#include <dev/fdt/fdtvar.h>
|
||||||
|
|
||||||
|
struct pwm_backlight_softc {
|
||||||
|
device_t sc_dev;
|
||||||
|
pwm_tag_t sc_pwm;
|
||||||
|
struct fdtbus_gpio_pin *sc_pin;
|
||||||
|
|
||||||
|
u_int *sc_levels;
|
||||||
|
u_int sc_nlevels;
|
||||||
|
|
||||||
|
char *sc_levelstr;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int pwm_backlight_match(device_t, cfdata_t, void *);
|
||||||
|
static void pwm_backlight_attach(device_t, device_t, void *);
|
||||||
|
|
||||||
|
static void pwm_backlight_sysctl_init(struct pwm_backlight_softc *);
|
||||||
|
static void pwm_backlight_pmf_init(struct pwm_backlight_softc *);
|
||||||
|
static void pwm_backlight_set(struct pwm_backlight_softc *, u_int);
|
||||||
|
static u_int pwm_backlight_get(struct pwm_backlight_softc *);
|
||||||
|
|
||||||
|
static const char *compatible[] = {
|
||||||
|
"pwm-backlight",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
CFATTACH_DECL_NEW(pwmbacklight, sizeof(struct pwm_backlight_softc),
|
||||||
|
pwm_backlight_match, pwm_backlight_attach, NULL, NULL);
|
||||||
|
|
||||||
|
static int
|
||||||
|
pwm_backlight_match(device_t parent, cfdata_t cf, void *aux)
|
||||||
|
{
|
||||||
|
struct fdt_attach_args * const faa = aux;
|
||||||
|
|
||||||
|
return of_match_compatible(faa->faa_phandle, compatible);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pwm_backlight_attach(device_t parent, device_t self, void *aux)
|
||||||
|
{
|
||||||
|
struct pwm_backlight_softc * const sc = device_private(self);
|
||||||
|
struct fdt_attach_args * const faa = aux;
|
||||||
|
const int phandle = faa->faa_phandle;
|
||||||
|
const u_int *levels;
|
||||||
|
u_int default_level;
|
||||||
|
u_int n;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
sc->sc_dev = self;
|
||||||
|
sc->sc_pwm = fdtbus_pwm_acquire(phandle, "pwms");
|
||||||
|
if (sc->sc_pwm == NULL) {
|
||||||
|
aprint_error(": couldn't acquire pwm\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (of_hasprop(phandle, "enable-gpios")) {
|
||||||
|
sc->sc_pin = fdtbus_gpio_acquire(phandle, "enable-gpios",
|
||||||
|
GPIO_PIN_OUTPUT);
|
||||||
|
if (!sc->sc_pin) {
|
||||||
|
aprint_error(": couldn't acquire enable gpio\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
levels = fdtbus_get_prop(phandle, "brightness-levels", &len);
|
||||||
|
if (len < 4) {
|
||||||
|
aprint_error(": couldn't get 'brightness-levels' property\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sc->sc_levels = kmem_alloc(len, KM_SLEEP);
|
||||||
|
sc->sc_nlevels = len / 4;
|
||||||
|
for (n = 0; n < sc->sc_nlevels; n++)
|
||||||
|
sc->sc_levels[n] = be32toh(levels[n]);
|
||||||
|
|
||||||
|
aprint_naive("\n");
|
||||||
|
aprint_normal(": PWM Backlight");
|
||||||
|
aprint_verbose(" <");
|
||||||
|
for (n = 0; n < sc->sc_nlevels; n++) {
|
||||||
|
aprint_verbose("%s%u", n ? " " : "", sc->sc_levels[n]);
|
||||||
|
}
|
||||||
|
aprint_verbose(">");
|
||||||
|
aprint_normal("\n");
|
||||||
|
|
||||||
|
if (of_getprop_uint32(phandle, "default-brightness-level", &default_level) == 0) {
|
||||||
|
/* set the default level now */
|
||||||
|
pwm_backlight_set(sc, default_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
pwm_backlight_sysctl_init(sc);
|
||||||
|
pwm_backlight_pmf_init(sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pwm_backlight_set(struct pwm_backlight_softc *sc, u_int index)
|
||||||
|
{
|
||||||
|
struct pwm_config conf;
|
||||||
|
|
||||||
|
if (index >= sc->sc_nlevels)
|
||||||
|
return;
|
||||||
|
|
||||||
|
aprint_debug_dev(sc->sc_dev, "set duty cycle to %u%%\n", sc->sc_levels[index]);
|
||||||
|
|
||||||
|
pwm_disable(sc->sc_pwm);
|
||||||
|
pwm_get_config(sc->sc_pwm, &conf);
|
||||||
|
conf.duty_cycle = (conf.period * sc->sc_levels[index]) / sc->sc_levels[sc->sc_nlevels - 1];
|
||||||
|
pwm_set_config(sc->sc_pwm, &conf);
|
||||||
|
pwm_enable(sc->sc_pwm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u_int
|
||||||
|
pwm_backlight_get(struct pwm_backlight_softc *sc)
|
||||||
|
{
|
||||||
|
struct pwm_config conf;
|
||||||
|
u_int raw_val, n;
|
||||||
|
|
||||||
|
pwm_get_config(sc->sc_pwm, &conf);
|
||||||
|
|
||||||
|
raw_val = (conf.duty_cycle * sc->sc_levels[sc->sc_nlevels - 1]) / conf.period;
|
||||||
|
|
||||||
|
/* Return the closest setting to the raw value */
|
||||||
|
for (n = 0; n < sc->sc_nlevels; n++) {
|
||||||
|
if (raw_val <= sc->sc_levels[n])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pwm_backlight_sysctl_helper(SYSCTLFN_ARGS)
|
||||||
|
{
|
||||||
|
struct pwm_backlight_softc * const sc = rnode->sysctl_data;
|
||||||
|
struct sysctlnode node;
|
||||||
|
int error;
|
||||||
|
u_int level, n;
|
||||||
|
|
||||||
|
node = *rnode;
|
||||||
|
node.sysctl_data = &level;
|
||||||
|
|
||||||
|
n = pwm_backlight_get(sc);
|
||||||
|
level = sc->sc_levels[n];
|
||||||
|
|
||||||
|
error = sysctl_lookup(SYSCTLFN_CALL(&node));
|
||||||
|
if (error || newp == NULL)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
for (n = 0; n < sc->sc_nlevels; n++) {
|
||||||
|
if (sc->sc_levels[n] == level) {
|
||||||
|
pwm_backlight_set(sc, n);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pwm_backlight_sysctl_init(struct pwm_backlight_softc *sc)
|
||||||
|
{
|
||||||
|
const struct sysctlnode *node, *pwmnode;
|
||||||
|
struct sysctllog *log = NULL;
|
||||||
|
int error;
|
||||||
|
u_int n;
|
||||||
|
|
||||||
|
sc->sc_levelstr = kmem_zalloc(strlen("XXXXX ") * sc->sc_nlevels, KM_SLEEP);
|
||||||
|
for (n = 0; n < sc->sc_nlevels; n++) {
|
||||||
|
char buf[7];
|
||||||
|
snprintf(buf, sizeof(buf), n ? " %u" : "%u", sc->sc_levels[n]);
|
||||||
|
strcat(sc->sc_levelstr, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
error = sysctl_createv(&log, 0, NULL, &node,
|
||||||
|
CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL,
|
||||||
|
NULL, 0, NULL, 0, CTL_HW, CTL_EOL);
|
||||||
|
if (error)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
error = sysctl_createv(&log, 0, &node, &pwmnode,
|
||||||
|
0, CTLTYPE_NODE, device_xname(sc->sc_dev), NULL,
|
||||||
|
NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
|
||||||
|
if (error)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
error = sysctl_createv(&log, 0, &pwmnode, NULL,
|
||||||
|
0, CTLTYPE_STRING, "levels", NULL,
|
||||||
|
NULL, 0, sc->sc_levelstr, NULL,
|
||||||
|
CTL_CREATE, CTL_EOL);
|
||||||
|
if (error)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
error = sysctl_createv(&log, 0, &pwmnode, NULL,
|
||||||
|
CTLFLAG_READWRITE, CTLTYPE_INT, "level", NULL,
|
||||||
|
pwm_backlight_sysctl_helper, 0, (void *)sc, 0,
|
||||||
|
CTL_CREATE, CTL_EOL);
|
||||||
|
if (error)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
aprint_error_dev(sc->sc_dev, "couldn't create sysctl nodes: %d\n", error);
|
||||||
|
sysctl_teardown(&log);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pwm_backlight_display_on(device_t dev)
|
||||||
|
{
|
||||||
|
struct pwm_backlight_softc * const sc = device_private(dev);
|
||||||
|
|
||||||
|
pwm_enable(sc->sc_pwm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pwm_backlight_display_off(device_t dev)
|
||||||
|
{
|
||||||
|
struct pwm_backlight_softc * const sc = device_private(dev);
|
||||||
|
|
||||||
|
pwm_disable(sc->sc_pwm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pwm_backlight_display_brightness_up(device_t dev)
|
||||||
|
{
|
||||||
|
struct pwm_backlight_softc * const sc = device_private(dev);
|
||||||
|
u_int n;
|
||||||
|
|
||||||
|
n = pwm_backlight_get(sc);
|
||||||
|
if (n < sc->sc_nlevels - 1)
|
||||||
|
pwm_backlight_set(sc, n + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pwm_backlight_display_brightness_down(device_t dev)
|
||||||
|
{
|
||||||
|
struct pwm_backlight_softc * const sc = device_private(dev);
|
||||||
|
u_int n;
|
||||||
|
|
||||||
|
n = pwm_backlight_get(sc);
|
||||||
|
if (n > 0)
|
||||||
|
pwm_backlight_set(sc, n - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pwm_backlight_pmf_init(struct pwm_backlight_softc *sc)
|
||||||
|
{
|
||||||
|
pmf_event_register(sc->sc_dev, PMFE_DISPLAY_ON,
|
||||||
|
pwm_backlight_display_on, true);
|
||||||
|
pmf_event_register(sc->sc_dev, PMFE_DISPLAY_OFF,
|
||||||
|
pwm_backlight_display_off, true);
|
||||||
|
pmf_event_register(sc->sc_dev, PMFE_DISPLAY_BRIGHTNESS_UP,
|
||||||
|
pwm_backlight_display_brightness_up, true);
|
||||||
|
pmf_event_register(sc->sc_dev, PMFE_DISPLAY_BRIGHTNESS_DOWN,
|
||||||
|
pwm_backlight_display_brightness_down, true);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user