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