1/* $NetBSD: teliosio.c,v 1.3 2008/05/31 08:08:54 nakayama Exp $ */ 2 3/* 4 * Copyright (c) 2005 Takeshi Nakayama. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28/* 29 * Sharp Telios machine dependent I/O (LCD backlight/Battery unit) driver 30 */ 31 32#include <sys/cdefs.h> 33__KERNEL_RCSID(0, "$NetBSD: teliosio.c,v 1.3 2008/05/31 08:08:54 nakayama Exp $"); 34 35#include "apmdev.h" 36 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/device.h> 40 41#include <machine/bus.h> 42#include <machine/config_hook.h> 43 44#include <hpcmips/tx/tx39var.h> 45#include <hpcmips/tx/txcsbusvar.h> 46 47#if NAPMDEV > 0 48#include <dev/apm/apmbios.h> 49#define __TX39IO_PRIVATE 50#include <hpcmips/tx/tx39ioreg.h> 51#include <hpcmips/tx/tx39timerreg.h> 52#endif 53 54#include <hpcmips/dev/teliosioreg.h> 55 56struct teliosio_softc { 57 tx_chipset_tag_t sc_tc; 58 bus_space_tag_t sc_regt; 59 bus_space_handle_t sc_regh; 60 61 int sc_backlight; 62 int sc_brightness; 63#define MAX_BRIGHTNESS 9 64#define BRIGHTNESSVAL(n) \ 65 ((n) <= 0 ? 0 : ((n) <= MAX_BRIGHTNESS ? (n) : MAX_BRIGHTNESS) * 9 - 1) 66}; 67 68static int teliosio_match(device_t, cfdata_t, void *); 69static void teliosio_attach(device_t, device_t, void *); 70static int teliosio_event(void *, int, long, void *); 71 72/* LCD backlight control */ 73static void teliosio_backlight(struct teliosio_softc *, int); 74static void teliosio_brightness(struct teliosio_softc *, int); 75 76/* Battery unit control */ 77#if NAPMDEV > 0 78static int teliosio_ac_state(struct teliosio_softc *); 79static int teliosio_mbu_state(struct teliosio_softc *); 80static void teliosio_mbu_write(tx_chipset_tag_t, int); 81static int teliosio_mbu_read(tx_chipset_tag_t); 82#endif 83 84CFATTACH_DECL_NEW(teliosio, sizeof(struct teliosio_softc), 85 teliosio_match, teliosio_attach, NULL, NULL); 86 87static int 88teliosio_match(device_t parent, cfdata_t cf, void *aux) 89{ 90 91 return 2; /* attach before plumvideo */ 92} 93 94static void 95teliosio_attach(device_t parent, device_t self, void *aux) 96{ 97 struct cs_attach_args *ca = aux; 98 struct teliosio_softc *sc = device_private(self); 99 100 sc->sc_tc = ca->ca_tc; 101 sc->sc_regt = ca->ca_csreg.cstag; 102 103 if (bus_space_map(sc->sc_regt, TELIOSIO_REGBASE, TELIOSIO_REGSIZE, 104 0, &sc->sc_regh)) { 105 printf(": register map failed\n"); 106 return; 107 } 108 printf("\n"); 109 110 sc->sc_backlight = 1; 111 sc->sc_brightness = MAX_BRIGHTNESS; 112 113 config_hook(CONFIG_HOOK_SET, CONFIG_HOOK_POWER_LCDLIGHT, 114 CONFIG_HOOK_SHARE, teliosio_event, sc); 115 config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_POWER_LCDLIGHT, 116 CONFIG_HOOK_SHARE, teliosio_event, sc); 117 config_hook(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, 118 CONFIG_HOOK_SHARE, teliosio_event, sc); 119 config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_BRIGHTNESS, 120 CONFIG_HOOK_SHARE, teliosio_event, sc); 121 config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_BRIGHTNESS_MAX, 122 CONFIG_HOOK_SHARE, teliosio_event, sc); 123#if NAPMDEV > 0 124 config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_ACADAPTER, 125 CONFIG_HOOK_SHARE, teliosio_event, sc); 126 config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_BATTERYVAL, 127 CONFIG_HOOK_SHARE, teliosio_event, sc); 128#endif 129} 130 131static int 132teliosio_event(void *ctx, int type, long id, void *msg) 133{ 134 struct teliosio_softc *sc = ctx; 135 136 switch (type) { 137 case CONFIG_HOOK_SET: 138 switch (id) { 139 case CONFIG_HOOK_POWER_LCDLIGHT: 140 teliosio_backlight(sc, (int)msg); 141 break; 142 case CONFIG_HOOK_BRIGHTNESS: 143 teliosio_brightness(sc, *(int *)msg + 1); 144 break; 145 default: 146 return 1; 147 } 148 break; 149 case CONFIG_HOOK_GET: 150 switch (id) { 151 case CONFIG_HOOK_POWER_LCDLIGHT: 152 *(int *)msg = sc->sc_backlight; 153 break; 154 case CONFIG_HOOK_BRIGHTNESS: 155 *(int *)msg = sc->sc_brightness - 1; 156 break; 157 case CONFIG_HOOK_BRIGHTNESS_MAX: 158 *(int *)msg = MAX_BRIGHTNESS - 1; 159 break; 160#if NAPMDEV > 0 161 case CONFIG_HOOK_ACADAPTER: 162 *(int *)msg = teliosio_ac_state(sc); 163 break; 164 case CONFIG_HOOK_BATTERYVAL: 165 *(int *)msg = teliosio_mbu_state(sc) / 2; 166 break; 167#endif 168 default: 169 return 1; 170 } 171 break; 172 default: 173 return 1; 174 } 175 176 return 0; 177} 178 179/* 180 * LCD backlight control 181 */ 182static void 183teliosio_backlight(struct teliosio_softc *sc, int on) 184{ 185 int brightness; 186 187 sc->sc_backlight = on; 188 if (on) { 189 teliosio_brightness(sc, sc->sc_brightness); 190 } else { 191 brightness = sc->sc_brightness; 192 teliosio_brightness(sc, 0); 193 sc->sc_brightness = brightness; 194 } 195} 196 197static void 198teliosio_brightness(struct teliosio_softc *sc, int val) 199{ 200 bus_space_tag_t regt = sc->sc_regt; 201 bus_space_handle_t regh = sc->sc_regh; 202 u_int16_t period; 203 204 if (val < 0) 205 val = 0; 206 else if (val > MAX_BRIGHTNESS) 207 val = MAX_BRIGHTNESS; 208 sc->sc_brightness = val; 209 210 period = bus_space_read_2(regt, regh, TELIOSIO_BACKLIGHT_PERIOD); 211 if (val) 212 period |= TELIOSIO_BACKLIGHT_PERIOD_EN; 213 else 214 period &= ~TELIOSIO_BACKLIGHT_PERIOD_EN; 215 bus_space_write_2(regt, regh, TELIOSIO_BACKLIGHT_PERIOD, period); 216 bus_space_write_2(regt, regh, TELIOSIO_BACKLIGHT_RESET, 217 BRIGHTNESSVAL(val)); 218} 219 220/* 221 * Battery unit control 222 */ 223#if NAPMDEV > 0 224static int 225teliosio_ac_state(struct teliosio_softc *sc) 226{ 227 tx_chipset_tag_t tc = sc->sc_tc; 228 txreg_t reg; 229 230 reg = tx_conf_read(tc, TX392X_IODATAINOUT_REG); 231 return (reg & TELIOSIO_AC_STATE) ? APM_AC_OFF : APM_AC_ON; 232} 233 234static int 235teliosio_mbu_state(struct teliosio_softc *sc) 236{ 237 tx_chipset_tag_t tc = sc->sc_tc; 238 int val; 239 240 teliosio_mbu_write(tc, 0x00); 241 delay(7000); 242 val = teliosio_mbu_read(tc); 243 delay(7000); 244 245 return val; 246} 247 248#define WAIT (1000000 / TELIOSIO_BMU_CLOCK_FREQ / 2) 249 250static void 251teliosio_mbu_write(tx_chipset_tag_t tc, int val) 252{ 253 txreg_t reg; 254 int s; 255 int mask; 256 257 for (mask = 0x80; mask != 0; mask >>= 1) { 258 s = splhigh(); 259 reg = tx_conf_read(tc, TX392X_IODATAINOUT_REG); 260 reg |= TELIOSIO_BMU_CLOCK; 261 if (val & mask) 262 reg |= TELIOSIO_BMU_DATAOUT; 263 else 264 reg &= ~TELIOSIO_BMU_DATAOUT; 265 tx_conf_write(tc, TX392X_IODATAINOUT_REG, reg); 266 splx(s); 267 delay(WAIT); 268 269 s = splhigh(); 270 reg = tx_conf_read(tc, TX392X_IODATAINOUT_REG); 271 reg &= ~TELIOSIO_BMU_CLOCK; 272 tx_conf_write(tc, TX392X_IODATAINOUT_REG, reg); 273 splx(s); 274 delay(WAIT); 275 } 276} 277 278static int 279teliosio_mbu_read(tx_chipset_tag_t tc) 280{ 281 txreg_t reg; 282 int s; 283 int mask, val; 284 285 val = 0; 286 for (mask = 0x80; mask != 0; mask >>= 1) { 287 s = splhigh(); 288 reg = tx_conf_read(tc, TX392X_IODATAINOUT_REG); 289 reg |= TELIOSIO_BMU_CLOCK; 290 tx_conf_write(tc, TX392X_IODATAINOUT_REG, reg); 291 splx(s); 292 delay(WAIT); 293 294 s = splhigh(); 295 reg = tx_conf_read(tc, TX392X_IODATAINOUT_REG); 296 if (!(reg & TELIOSIO_BMU_DATAIN)) 297 val |= mask; 298 reg &= ~TELIOSIO_BMU_CLOCK; 299 tx_conf_write(tc, TX392X_IODATAINOUT_REG, reg); 300 splx(s); 301 delay(WAIT); 302 } 303 304 return val; 305} 306#endif /* NAPMDEV */ 307