13cc28bd9SJustin Hibbits /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 371e3c308SPedro F. Giffuni * 43cc28bd9SJustin Hibbits * Copyright (c) 2012 Justin Hibbits 53cc28bd9SJustin Hibbits * All rights reserved. 63cc28bd9SJustin Hibbits * 73cc28bd9SJustin Hibbits * Redistribution and use in source and binary forms, with or without 83cc28bd9SJustin Hibbits * modification, are permitted provided that the following conditions 93cc28bd9SJustin Hibbits * are met: 103cc28bd9SJustin Hibbits * 1. Redistributions of source code must retain the above copyright 113cc28bd9SJustin Hibbits * notice, this list of conditions and the following disclaimer. 123cc28bd9SJustin Hibbits * 2. Redistributions in binary form must reproduce the above copyright 133cc28bd9SJustin Hibbits * notice, this list of conditions and the following disclaimer in the 143cc28bd9SJustin Hibbits * documentation and/or other materials provided with the distribution. 153cc28bd9SJustin Hibbits * 163cc28bd9SJustin Hibbits * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 173cc28bd9SJustin Hibbits * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 183cc28bd9SJustin Hibbits * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 193cc28bd9SJustin Hibbits * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 203cc28bd9SJustin Hibbits * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 213cc28bd9SJustin Hibbits * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 223cc28bd9SJustin Hibbits * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 233cc28bd9SJustin Hibbits * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 243cc28bd9SJustin Hibbits * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 253cc28bd9SJustin Hibbits * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 263cc28bd9SJustin Hibbits * SUCH DAMAGE. 273cc28bd9SJustin Hibbits */ 283cc28bd9SJustin Hibbits 293cc28bd9SJustin Hibbits #include <sys/param.h> 303cc28bd9SJustin Hibbits #include <sys/bus.h> 313cc28bd9SJustin Hibbits #include <sys/systm.h> 323cc28bd9SJustin Hibbits #include <sys/module.h> 333cc28bd9SJustin Hibbits #include <sys/kernel.h> 343cc28bd9SJustin Hibbits #include <sys/rman.h> 353cc28bd9SJustin Hibbits #include <sys/sysctl.h> 363cc28bd9SJustin Hibbits 373cc28bd9SJustin Hibbits #include <machine/bus.h> 383cc28bd9SJustin Hibbits 393cc28bd9SJustin Hibbits #include <dev/ofw/openfirm.h> 409fdc5d59SJustin Hibbits #include <dev/pci/pcivar.h> 419fdc5d59SJustin Hibbits 429fdc5d59SJustin Hibbits #ifndef PCI_VENDOR_ID_ATI 439fdc5d59SJustin Hibbits #define PCI_VENDOR_ID_ATI 0x1002 449fdc5d59SJustin Hibbits #endif 453cc28bd9SJustin Hibbits 463cc28bd9SJustin Hibbits /* From the xf86-video-ati driver's radeon_reg.h */ 473cc28bd9SJustin Hibbits #define RADEON_LVDS_GEN_CNTL 0x02d0 483cc28bd9SJustin Hibbits #define RADEON_LVDS_ON (1 << 0) 493cc28bd9SJustin Hibbits #define RADEON_LVDS_DISPLAY_DIS (1 << 1) 503cc28bd9SJustin Hibbits #define RADEON_LVDS_PANEL_TYPE (1 << 2) 513cc28bd9SJustin Hibbits #define RADEON_LVDS_PANEL_FORMAT (1 << 3) 523cc28bd9SJustin Hibbits #define RADEON_LVDS_RST_FM (1 << 6) 533cc28bd9SJustin Hibbits #define RADEON_LVDS_EN (1 << 7) 543cc28bd9SJustin Hibbits #define RADEON_LVDS_BL_MOD_LEVEL_SHIFT 8 553cc28bd9SJustin Hibbits #define RADEON_LVDS_BL_MOD_LEVEL_MASK (0xff << 8) 563cc28bd9SJustin Hibbits #define RADEON_LVDS_BL_MOD_EN (1 << 16) 573cc28bd9SJustin Hibbits #define RADEON_LVDS_DIGON (1 << 18) 583cc28bd9SJustin Hibbits #define RADEON_LVDS_BLON (1 << 19) 59c63e7b93SJustin Hibbits #define RADEON_LVDS_PLL_CNTL 0x02d4 60c63e7b93SJustin Hibbits #define RADEON_LVDS_PLL_EN (1 << 16) 61c63e7b93SJustin Hibbits #define RADEON_LVDS_PLL_RESET (1 << 17) 62c63e7b93SJustin Hibbits #define RADEON_PIXCLKS_CNTL 0x002d 63c63e7b93SJustin Hibbits #define RADEON_PIXCLK_LVDS_ALWAYS_ONb (1 << 14) 647b92a9bfSJustin Hibbits #define RADEON_DISP_PWR_MAN 0x0d08 657b92a9bfSJustin Hibbits #define RADEON_AUTO_PWRUP_EN (1 << 26) 667b92a9bfSJustin Hibbits #define RADEON_CLOCK_CNTL_DATA 0x000c 677b92a9bfSJustin Hibbits #define RADEON_CLOCK_CNTL_INDEX 0x0008 687b92a9bfSJustin Hibbits #define RADEON_PLL_WR_EN (1 << 7) 697b92a9bfSJustin Hibbits #define RADEON_CRTC_GEN_CNTL 0x0050 703cc28bd9SJustin Hibbits 713cc28bd9SJustin Hibbits struct atibl_softc { 723cc28bd9SJustin Hibbits struct resource *sc_memr; 73c63e7b93SJustin Hibbits int sc_level; 743cc28bd9SJustin Hibbits }; 753cc28bd9SJustin Hibbits 763cc28bd9SJustin Hibbits static void atibl_identify(driver_t *driver, device_t parent); 773cc28bd9SJustin Hibbits static int atibl_probe(device_t dev); 783cc28bd9SJustin Hibbits static int atibl_attach(device_t dev); 793cc28bd9SJustin Hibbits static int atibl_setlevel(struct atibl_softc *sc, int newlevel); 803cc28bd9SJustin Hibbits static int atibl_getlevel(struct atibl_softc *sc); 81c63e7b93SJustin Hibbits static int atibl_resume(device_t dev); 82c63e7b93SJustin Hibbits static int atibl_suspend(device_t dev); 833cc28bd9SJustin Hibbits static int atibl_sysctl(SYSCTL_HANDLER_ARGS); 843cc28bd9SJustin Hibbits 853cc28bd9SJustin Hibbits static device_method_t atibl_methods[] = { 863cc28bd9SJustin Hibbits /* Device interface */ 873cc28bd9SJustin Hibbits DEVMETHOD(device_identify, atibl_identify), 883cc28bd9SJustin Hibbits DEVMETHOD(device_probe, atibl_probe), 893cc28bd9SJustin Hibbits DEVMETHOD(device_attach, atibl_attach), 90c63e7b93SJustin Hibbits DEVMETHOD(device_suspend, atibl_suspend), 91c63e7b93SJustin Hibbits DEVMETHOD(device_resume, atibl_resume), 923cc28bd9SJustin Hibbits {0, 0}, 933cc28bd9SJustin Hibbits }; 943cc28bd9SJustin Hibbits 953cc28bd9SJustin Hibbits static driver_t atibl_driver = { 963cc28bd9SJustin Hibbits "backlight", 973cc28bd9SJustin Hibbits atibl_methods, 983cc28bd9SJustin Hibbits sizeof(struct atibl_softc) 993cc28bd9SJustin Hibbits }; 1003cc28bd9SJustin Hibbits 101992ae60bSJohn Baldwin DRIVER_MODULE(atibl, vgapci, atibl_driver, 0, 0); 1023cc28bd9SJustin Hibbits 1033cc28bd9SJustin Hibbits static void 1043cc28bd9SJustin Hibbits atibl_identify(driver_t *driver, device_t parent) 1053cc28bd9SJustin Hibbits { 106427467b3SJustin Hibbits if (OF_finddevice("mac-io/backlight") == -1) 107427467b3SJustin Hibbits return; 1083cc28bd9SJustin Hibbits if (device_find_child(parent, "backlight", -1) == NULL) 109*5b56413dSWarner Losh device_add_child(parent, "backlight", DEVICE_UNIT_ANY); 1103cc28bd9SJustin Hibbits } 1113cc28bd9SJustin Hibbits 1123cc28bd9SJustin Hibbits static int 1133cc28bd9SJustin Hibbits atibl_probe(device_t dev) 1143cc28bd9SJustin Hibbits { 1153cc28bd9SJustin Hibbits char control[8]; 1163cc28bd9SJustin Hibbits phandle_t handle; 1173cc28bd9SJustin Hibbits 1183cc28bd9SJustin Hibbits handle = OF_finddevice("mac-io/backlight"); 1193cc28bd9SJustin Hibbits 1201342232fSJustin Hibbits if (handle == -1) 1213cc28bd9SJustin Hibbits return (ENXIO); 1223cc28bd9SJustin Hibbits 1233cc28bd9SJustin Hibbits if (OF_getprop(handle, "backlight-control", &control, sizeof(control)) < 0) 1243cc28bd9SJustin Hibbits return (ENXIO); 1253cc28bd9SJustin Hibbits 1269fdc5d59SJustin Hibbits if (strcmp(control, "ati") != 0 && 1279fdc5d59SJustin Hibbits (strcmp(control, "mnca") != 0 || 1289fdc5d59SJustin Hibbits pci_get_vendor(device_get_parent(dev)) != 0x1002)) 1293cc28bd9SJustin Hibbits return (ENXIO); 1303cc28bd9SJustin Hibbits 1311342232fSJustin Hibbits device_set_desc(dev, "PowerBook backlight for ATI graphics"); 1323cc28bd9SJustin Hibbits 1333cc28bd9SJustin Hibbits return (0); 1343cc28bd9SJustin Hibbits } 1353cc28bd9SJustin Hibbits 1363cc28bd9SJustin Hibbits static int 1373cc28bd9SJustin Hibbits atibl_attach(device_t dev) 1383cc28bd9SJustin Hibbits { 1393cc28bd9SJustin Hibbits struct atibl_softc *sc; 1403cc28bd9SJustin Hibbits struct sysctl_ctx_list *ctx; 1413cc28bd9SJustin Hibbits struct sysctl_oid *tree; 1423cc28bd9SJustin Hibbits int rid; 1433cc28bd9SJustin Hibbits 1443cc28bd9SJustin Hibbits sc = device_get_softc(dev); 1453cc28bd9SJustin Hibbits 1463cc28bd9SJustin Hibbits rid = 0x18; /* BAR[2], for the MMIO register */ 1473cc28bd9SJustin Hibbits sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 1483cc28bd9SJustin Hibbits RF_ACTIVE | RF_SHAREABLE); 1493cc28bd9SJustin Hibbits if (sc->sc_memr == NULL) { 1503cc28bd9SJustin Hibbits device_printf(dev, "Could not alloc mem resource!\n"); 1513cc28bd9SJustin Hibbits return (ENXIO); 1523cc28bd9SJustin Hibbits } 1533cc28bd9SJustin Hibbits 1543cc28bd9SJustin Hibbits ctx = device_get_sysctl_ctx(dev); 1553cc28bd9SJustin Hibbits tree = device_get_sysctl_tree(dev); 1563cc28bd9SJustin Hibbits 1573cc28bd9SJustin Hibbits SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1587029da5cSPawel Biernacki "level", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0, 1593cc28bd9SJustin Hibbits atibl_sysctl, "I", "Backlight level (0-100)"); 1603cc28bd9SJustin Hibbits 1613cc28bd9SJustin Hibbits return (0); 1623cc28bd9SJustin Hibbits } 1633cc28bd9SJustin Hibbits 1647b92a9bfSJustin Hibbits static uint32_t __inline 1657b92a9bfSJustin Hibbits atibl_pll_rreg(struct atibl_softc *sc, uint32_t reg) 1667b92a9bfSJustin Hibbits { 1677b92a9bfSJustin Hibbits uint32_t data, save, tmp; 1687b92a9bfSJustin Hibbits 1695f41b3c1SJustin Hibbits bus_write_1(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX, (reg & 0x3f)); 1707b92a9bfSJustin Hibbits (void)bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_DATA); 1717b92a9bfSJustin Hibbits (void)bus_read_4(sc->sc_memr, RADEON_CRTC_GEN_CNTL); 1727b92a9bfSJustin Hibbits 1737b92a9bfSJustin Hibbits data = bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_DATA); 1747b92a9bfSJustin Hibbits 1755f41b3c1SJustin Hibbits /* Only necessary on R300, but won't hurt others. */ 1767b92a9bfSJustin Hibbits save = bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX); 1777b92a9bfSJustin Hibbits tmp = save & (~0x3f | RADEON_PLL_WR_EN); 1787b92a9bfSJustin Hibbits bus_write_4(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX, tmp); 1797b92a9bfSJustin Hibbits tmp = bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_DATA); 1807b92a9bfSJustin Hibbits bus_write_4(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX, save); 1817b92a9bfSJustin Hibbits 1827b92a9bfSJustin Hibbits return data; 1837b92a9bfSJustin Hibbits } 1847b92a9bfSJustin Hibbits 1857b92a9bfSJustin Hibbits static void __inline 1867b92a9bfSJustin Hibbits atibl_pll_wreg(struct atibl_softc *sc, uint32_t reg, uint32_t val) 1877b92a9bfSJustin Hibbits { 1887b92a9bfSJustin Hibbits uint32_t save, tmp; 1897b92a9bfSJustin Hibbits 1907b92a9bfSJustin Hibbits bus_write_1(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX, 1917b92a9bfSJustin Hibbits ((reg & 0x3f) | RADEON_PLL_WR_EN)); 1927b92a9bfSJustin Hibbits (void)bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_DATA); 1937b92a9bfSJustin Hibbits (void)bus_read_4(sc->sc_memr, RADEON_CRTC_GEN_CNTL); 1947b92a9bfSJustin Hibbits 1957b92a9bfSJustin Hibbits bus_write_4(sc->sc_memr, RADEON_CLOCK_CNTL_DATA, val); 1967b92a9bfSJustin Hibbits DELAY(5000); 1977b92a9bfSJustin Hibbits 1985f41b3c1SJustin Hibbits /* Only necessary on R300, but won't hurt others. */ 1997b92a9bfSJustin Hibbits save = bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX); 2007b92a9bfSJustin Hibbits tmp = save & (~0x3f | RADEON_PLL_WR_EN); 2017b92a9bfSJustin Hibbits bus_write_4(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX, tmp); 2027b92a9bfSJustin Hibbits tmp = bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_DATA); 2037b92a9bfSJustin Hibbits bus_write_4(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX, save); 2047b92a9bfSJustin Hibbits } 2057b92a9bfSJustin Hibbits 2063cc28bd9SJustin Hibbits static int 2073cc28bd9SJustin Hibbits atibl_setlevel(struct atibl_softc *sc, int newlevel) 2083cc28bd9SJustin Hibbits { 2093cc28bd9SJustin Hibbits uint32_t lvds_gen_cntl; 210c63e7b93SJustin Hibbits uint32_t lvds_pll_cntl; 211c63e7b93SJustin Hibbits uint32_t pixclks_cntl; 2127b92a9bfSJustin Hibbits uint32_t disp_pwr_reg; 2133cc28bd9SJustin Hibbits 2143cc28bd9SJustin Hibbits if (newlevel > 100) 2153cc28bd9SJustin Hibbits newlevel = 100; 2163cc28bd9SJustin Hibbits 2173cc28bd9SJustin Hibbits if (newlevel < 0) 2183cc28bd9SJustin Hibbits newlevel = 0; 2193cc28bd9SJustin Hibbits 2203cc28bd9SJustin Hibbits lvds_gen_cntl = bus_read_4(sc->sc_memr, RADEON_LVDS_GEN_CNTL); 221c63e7b93SJustin Hibbits 222c63e7b93SJustin Hibbits if (newlevel > 0) { 223c63e7b93SJustin Hibbits newlevel = (newlevel * 5) / 2 + 5; 2247b92a9bfSJustin Hibbits disp_pwr_reg = bus_read_4(sc->sc_memr, RADEON_DISP_PWR_MAN); 2257b92a9bfSJustin Hibbits disp_pwr_reg |= RADEON_AUTO_PWRUP_EN; 2267b92a9bfSJustin Hibbits bus_write_4(sc->sc_memr, RADEON_DISP_PWR_MAN, disp_pwr_reg); 227c63e7b93SJustin Hibbits lvds_pll_cntl = bus_read_4(sc->sc_memr, RADEON_LVDS_PLL_CNTL); 228c63e7b93SJustin Hibbits lvds_pll_cntl |= RADEON_LVDS_PLL_EN; 229c63e7b93SJustin Hibbits bus_write_4(sc->sc_memr, RADEON_LVDS_PLL_CNTL, lvds_pll_cntl); 230c63e7b93SJustin Hibbits lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET; 231c63e7b93SJustin Hibbits bus_write_4(sc->sc_memr, RADEON_LVDS_PLL_CNTL, lvds_pll_cntl); 2327b92a9bfSJustin Hibbits DELAY(1000); 233c63e7b93SJustin Hibbits 234c63e7b93SJustin Hibbits lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS | 235c63e7b93SJustin Hibbits RADEON_LVDS_BL_MOD_LEVEL_MASK); 236c63e7b93SJustin Hibbits lvds_gen_cntl |= RADEON_LVDS_ON | RADEON_LVDS_EN | 237c63e7b93SJustin Hibbits RADEON_LVDS_DIGON | RADEON_LVDS_BLON; 2383cc28bd9SJustin Hibbits lvds_gen_cntl |= (newlevel << RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 2393cc28bd9SJustin Hibbits RADEON_LVDS_BL_MOD_LEVEL_MASK; 240c63e7b93SJustin Hibbits lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN; 241be9b614dSJustin Hibbits DELAY(200000); 2423cc28bd9SJustin Hibbits bus_write_4(sc->sc_memr, RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); 243c63e7b93SJustin Hibbits } else { 2447b92a9bfSJustin Hibbits pixclks_cntl = atibl_pll_rreg(sc, RADEON_PIXCLKS_CNTL); 2457b92a9bfSJustin Hibbits atibl_pll_wreg(sc, RADEON_PIXCLKS_CNTL, 246c63e7b93SJustin Hibbits pixclks_cntl & ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); 247c63e7b93SJustin Hibbits lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; 248be9b614dSJustin Hibbits lvds_gen_cntl &= ~(RADEON_LVDS_BL_MOD_EN | RADEON_LVDS_BL_MOD_LEVEL_MASK); 249c63e7b93SJustin Hibbits bus_write_4(sc->sc_memr, RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); 250c63e7b93SJustin Hibbits lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_EN); 251be9b614dSJustin Hibbits DELAY(200000); 252c63e7b93SJustin Hibbits bus_write_4(sc->sc_memr, RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); 253c63e7b93SJustin Hibbits 2547b92a9bfSJustin Hibbits atibl_pll_wreg(sc, RADEON_PIXCLKS_CNTL, pixclks_cntl); 255be9b614dSJustin Hibbits DELAY(200000); 256c63e7b93SJustin Hibbits } 2573cc28bd9SJustin Hibbits 2583cc28bd9SJustin Hibbits return (0); 2593cc28bd9SJustin Hibbits } 2603cc28bd9SJustin Hibbits 2613cc28bd9SJustin Hibbits static int 2623cc28bd9SJustin Hibbits atibl_getlevel(struct atibl_softc *sc) 2633cc28bd9SJustin Hibbits { 2643cc28bd9SJustin Hibbits uint32_t lvds_gen_cntl; 2653cc28bd9SJustin Hibbits int level; 2663cc28bd9SJustin Hibbits 2673cc28bd9SJustin Hibbits lvds_gen_cntl = bus_read_4(sc->sc_memr, RADEON_LVDS_GEN_CNTL); 2683cc28bd9SJustin Hibbits 2693cc28bd9SJustin Hibbits level = ((lvds_gen_cntl & RADEON_LVDS_BL_MOD_LEVEL_MASK) >> 2703cc28bd9SJustin Hibbits RADEON_LVDS_BL_MOD_LEVEL_SHIFT); 271c63e7b93SJustin Hibbits if (level != 0) 2723cc28bd9SJustin Hibbits level = ((level - 5) * 2) / 5; 2733cc28bd9SJustin Hibbits 2743cc28bd9SJustin Hibbits return (level); 2753cc28bd9SJustin Hibbits } 2763cc28bd9SJustin Hibbits 2773cc28bd9SJustin Hibbits static int 278c63e7b93SJustin Hibbits atibl_suspend(device_t dev) 279c63e7b93SJustin Hibbits { 280c63e7b93SJustin Hibbits struct atibl_softc *sc; 281c63e7b93SJustin Hibbits 282c63e7b93SJustin Hibbits sc = device_get_softc(dev); 283c63e7b93SJustin Hibbits 284c63e7b93SJustin Hibbits sc->sc_level = atibl_getlevel(sc); 285c63e7b93SJustin Hibbits atibl_setlevel(sc, 0); 286c63e7b93SJustin Hibbits 287c63e7b93SJustin Hibbits return (0); 288c63e7b93SJustin Hibbits } 289c63e7b93SJustin Hibbits 290c63e7b93SJustin Hibbits static int 291c63e7b93SJustin Hibbits atibl_resume(device_t dev) 292c63e7b93SJustin Hibbits { 293c63e7b93SJustin Hibbits struct atibl_softc *sc; 294c63e7b93SJustin Hibbits 295c63e7b93SJustin Hibbits sc = device_get_softc(dev); 296c63e7b93SJustin Hibbits 297c63e7b93SJustin Hibbits atibl_setlevel(sc, sc->sc_level); 298c63e7b93SJustin Hibbits 299c63e7b93SJustin Hibbits return (0); 300c63e7b93SJustin Hibbits } 301c63e7b93SJustin Hibbits 302c63e7b93SJustin Hibbits static int 3033cc28bd9SJustin Hibbits atibl_sysctl(SYSCTL_HANDLER_ARGS) 3043cc28bd9SJustin Hibbits { 3053cc28bd9SJustin Hibbits struct atibl_softc *sc; 3063cc28bd9SJustin Hibbits int newlevel, error; 3073cc28bd9SJustin Hibbits 3083cc28bd9SJustin Hibbits sc = arg1; 3093cc28bd9SJustin Hibbits 3103cc28bd9SJustin Hibbits newlevel = atibl_getlevel(sc); 3113cc28bd9SJustin Hibbits 3123cc28bd9SJustin Hibbits error = sysctl_handle_int(oidp, &newlevel, 0, req); 3133cc28bd9SJustin Hibbits 3143cc28bd9SJustin Hibbits if (error || !req->newptr) 3153cc28bd9SJustin Hibbits return (error); 3163cc28bd9SJustin Hibbits 3173cc28bd9SJustin Hibbits return (atibl_setlevel(sc, newlevel)); 3183cc28bd9SJustin Hibbits } 319