Home | History | Annotate | Line # | Download | only in tx
tx39sib.c revision 1.2
      1 /*	$NetBSD: tx39sib.c,v 1.2 2000/01/12 14:56:19 uch Exp $ */
      2 
      3 /*
      4  * Copyright (c) 2000, by UCHIYAMA Yasushi
      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. The name of the developer may NOT be used to endorse or promote products
     13  *    derived from this software without specific prior written permission.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25  * SUCH DAMAGE.
     26  *
     27  */
     28 
     29 /*
     30  * TX39 SIB (Serial Interface Bus) module.
     31  */
     32 #undef TX39SIBDEBUG
     33 #include "opt_tx39_debug.h"
     34 
     35 #include <sys/param.h>
     36 #include <sys/systm.h>
     37 #include <sys/device.h>
     38 
     39 #include <machine/bus.h>
     40 #include <machine/intr.h>
     41 
     42 #include <hpcmips/tx/tx39var.h>
     43 #include <hpcmips/tx/tx39icureg.h>
     44 #include <hpcmips/tx/tx39sibvar.h>
     45 #include <hpcmips/tx/tx39sibreg.h>
     46 
     47 #include "locators.h"
     48 
     49 #ifdef TX39SIBDEBUG
     50 int	tx39sib_debug = 0;
     51 #define	DPRINTF(arg) if (vrpiu_debug) printf arg;
     52 #else
     53 #define	DPRINTF(arg)
     54 #endif
     55 
     56 int	tx39sib_match	__P((struct device*, struct cfdata*, void*));
     57 void	tx39sib_attach	__P((struct device*, struct device*, void*));
     58 int	tx39sib_print	__P((void*, const char*));
     59 int	tx39sib_search	__P((struct device*, struct cfdata*, void*));
     60 
     61 #define TX39_CLK2X	18432000
     62 const int sibsclk_divide_table[8] = {
     63 	2, 3, 4, 5, 6, 8, 10, 12
     64 };
     65 
     66 struct tx39sib_param {
     67 	/* SIB clock rate */
     68 	int sp_clock;
     69 /*
     70  *	SIBMCLK = 18.432MHz = (CLK2X /4)
     71  *	SIBSCLK = SIBMCLK / sp_clock
     72  *	sp_clock	start	end	divide module
     73  *	0		7	8	2
     74  *	1		6	8	3
     75  *	2		6	9	4
     76  *	3		5	9	5
     77  *	4		5	10	6
     78  *	5		4	11	8
     79  *	6		3	12	10
     80  *	7		2	13	12
     81  */
     82 	/* sampling rate */
     83 	int sp_snd_rate; /* SNDFSDIV + 1 */
     84 	int sp_tel_rate; /* TELFSDIV + 1 */
     85 /*
     86  *	Fs = (SIBSCLK * 2) / ((FSDIV + 1) * 64
     87  *	FSDIV + 1	sampling rate
     88  *	15		19.2k		(1.6% error vs. CD-XA)
     89  *	13		22.154k		(0.47% error vs. CD-Audio)
     90  *	22		7.85k		(1.8% error vs. 8k)
     91  */
     92 	/* data format 16/8bit */
     93 	int sp_sf0sndmode;
     94 	int sp_sf0telmode;
     95 };
     96 
     97 struct tx39sib_param tx39sib_param_default = {
     98 	0,			/* SIBSCLK = 9.216MHz */
     99 	13,			/* audio: CD-Audio */
    100 	40,			/* telecom: 7.2kHz */
    101 	TX39_SIBCTRL_SND16,	/* Audio 16bit mono */
    102 	TX39_SIBCTRL_TEL16	/* Telecom 16bit mono */
    103 };
    104 
    105 struct tx39sib_softc {
    106 	struct	device sc_dev;
    107 	tx_chipset_tag_t sc_tc;
    108 
    109 	struct tx39sib_param sc_param;
    110 	int sc_attached;
    111 };
    112 
    113 __inline int	__txsibsf0_ready __P((tx_chipset_tag_t));
    114 void	tx39sib_dump __P((struct tx39sib_softc*));
    115 
    116 struct cfattach tx39sib_ca = {
    117 	sizeof(struct tx39sib_softc), tx39sib_match, tx39sib_attach
    118 };
    119 
    120 int
    121 tx39sib_match(parent, cf, aux)
    122 	struct device *parent;
    123 	struct cfdata *cf;
    124 	void *aux;
    125 {
    126 	return 1;
    127 }
    128 
    129 void
    130 tx39sib_attach(parent, self, aux)
    131 	struct device *parent;
    132 	struct device *self;
    133 	void *aux;
    134 {
    135 	struct txsim_attach_args *ta = aux;
    136 	struct tx39sib_softc *sc = (void*)self;
    137 	tx_chipset_tag_t tc;
    138 
    139 	sc->sc_tc = tc = ta->ta_tc;
    140 
    141 	/* set default param */
    142 	sc->sc_param = tx39sib_param_default;
    143 #define MHZ(a) ((a) / 1000000), (((a) % 1000000) / 1000)
    144 	printf(": %d.%03d MHz", MHZ(tx39sib_clock(self)));
    145 
    146 	printf("\n");
    147 #ifdef TX39SIBDEBUG
    148 	tx39sib_dump(sc);
    149 #endif
    150 	/* enable subframe0 */
    151 	tx39sib_enable1(self);
    152 	/* enable SIB */
    153 	tx39sib_enable2(self);
    154 
    155 #ifdef TX39SIBDEBUG
    156 	tx39sib_dump(sc);
    157 #endif
    158 
    159 	config_search(tx39sib_search, self, tx39sib_print);
    160 }
    161 
    162 void
    163 tx39sib_enable1(dev)
    164 	struct device *dev;
    165 {
    166 	struct tx39sib_softc *sc = (void*)dev;
    167 	struct tx39sib_param *param = &sc->sc_param;
    168 	tx_chipset_tag_t tc = sc->sc_tc;
    169 
    170 	txreg_t reg;
    171 
    172 	/* disable SIB */
    173 	tx39sib_disable(dev);
    174 
    175 	/* setup */
    176 	reg = 0;
    177 	/*  SIB clock rate */
    178 	reg = TX39_SIBCTRL_SCLKDIV_SET(reg, param->sp_clock);
    179 	/*  sampling rate (sound) */
    180 	reg = TX39_SIBCTRL_SNDFSDIV_SET(reg, param->sp_snd_rate - 1);
    181 	/*  sampling rate (telecom) */
    182 	reg = TX39_SIBCTRL_TELFSDIV_SET(reg, param->sp_tel_rate - 1);
    183 	/*  data format (8/16bit) */
    184 	reg |= param->sp_sf0sndmode;
    185 	reg |= param->sp_sf0telmode;
    186 	tx_conf_write(tc, TX39_SIBCTRL_REG, reg);
    187 
    188 	/* DMA */
    189 	reg = tx_conf_read(tc, TX39_SIBDMACTRL_REG);
    190 	reg &= ~(TX39_SIBDMACTRL_ENDMARXSND |
    191 		 TX39_SIBDMACTRL_ENDMATXSND |
    192 		 TX39_SIBDMACTRL_ENDMARXTEL |
    193 		 TX39_SIBDMACTRL_ENDMATXTEL);
    194 	tx_conf_write(tc, TX39_SIBDMACTRL_REG, reg);
    195 
    196 	/*
    197 	 * Enable subframe0 (BETTY)
    198 	 */
    199 	reg = tx_conf_read(tc, TX39_SIBCTRL_REG);
    200 	reg |= TX39_SIBCTRL_ENSF0;
    201 	tx_conf_write(tc, TX39_SIBCTRL_REG, reg);
    202 }
    203 
    204 void
    205 tx39sib_enable2(dev)
    206 	struct device *dev;
    207 {
    208 	struct tx39sib_softc *sc = (void*)dev;
    209 	tx_chipset_tag_t tc = sc->sc_tc;
    210 	txreg_t reg;
    211 
    212 	reg = tx_conf_read(tc, TX39_SIBCTRL_REG);
    213 	reg |= TX39_SIBCTRL_ENSIB;
    214 	tx_conf_write(tc, TX39_SIBCTRL_REG, reg);
    215 }
    216 
    217 void
    218 tx39sib_disable(dev)
    219 	struct device *dev;
    220 {
    221 	struct tx39sib_softc *sc = (void*)dev;
    222 	tx_chipset_tag_t tc = sc->sc_tc;
    223 	txreg_t reg;
    224 	/* disable codec side */
    225 	/* notyet */
    226 
    227 	/* disable TX39 side */
    228 	reg = tx_conf_read(tc, TX39_SIBCTRL_REG);
    229 	reg &= ~(TX39_SIBCTRL_ENTEL | TX39_SIBCTRL_ENSND);
    230 	tx_conf_write(tc, TX39_SIBCTRL_REG, reg);
    231 
    232 	/*
    233 	 * Disable subframe0/1 (BETTY/external codec)
    234 	 */
    235 	reg = tx_conf_read(tc, TX39_SIBCTRL_REG);
    236 	reg &= ~TX39_SIBCTRL_ENSF0;
    237 	reg &= ~(TX39_SIBCTRL_ENSF1 | TX39_SIBCTRL_SELTELSF1 |
    238 		 TX39_SIBCTRL_SELSNDSF1);
    239 	tx_conf_write(tc, TX39_SIBCTRL_REG, reg);
    240 
    241 	/* disable TX39SIB module */
    242 	reg &= ~TX39_SIBCTRL_ENSIB;
    243 	tx_conf_write(tc, TX39_SIBCTRL_REG, reg);
    244 }
    245 
    246 int
    247 tx39sib_clock(dev)
    248 	struct device *dev;
    249 {
    250 	struct tx39sib_softc *sc = (void*)dev;
    251 
    252 	return TX39_CLK2X / sibsclk_divide_table[sc->sc_param.sp_clock];
    253 }
    254 
    255 int
    256 tx39sib_search(parent, cf, aux)
    257 	struct device *parent;
    258 	struct cfdata *cf;
    259 	void *aux;
    260 {
    261 	struct tx39sib_softc *sc = (void*)parent;
    262 	struct txsib_attach_args sa;
    263 
    264 	sa.sa_tc	= sc->sc_tc;
    265 	sa.sa_slot	= cf->cf_loc[TXSIBIFCF_SLOT];
    266 	sa.sa_snd_rate	= sc->sc_param.sp_snd_rate;
    267 	sa.sa_tel_rate	= sc->sc_param.sp_tel_rate;
    268 
    269 	if (sa.sa_slot == TXSIBIFCF_SLOT_DEFAULT) {
    270 		printf("tx39sib_search: wildcarded slot, skipping\n");
    271 		return 0;
    272 	}
    273 
    274 	if (!(sc->sc_attached & (1 << sa.sa_slot)) &&/* not attached slot */
    275 	    (*cf->cf_attach->ca_match)(parent, cf, &sa)) {
    276 		config_attach(parent, cf, &sa, tx39sib_print);
    277 		sc->sc_attached |= (1 << sa.sa_slot);
    278 	}
    279 
    280 	return 0;
    281 }
    282 
    283 int
    284 tx39sib_print(aux, pnp)
    285 	void *aux;
    286 	const char *pnp;
    287 {
    288 	struct txsib_attach_args *sa = aux;
    289 
    290 	printf(" slot %d", sa->sa_slot);
    291 
    292 	return QUIET;
    293 }
    294 
    295 /*
    296  * sync access method. don't use runtime.
    297  */
    298 
    299 __inline int
    300 __txsibsf0_ready(tc)
    301 	tx_chipset_tag_t tc;
    302 {
    303 	int i;
    304 
    305 	tx_conf_write(tc, TX39_INTRSTATUS1_REG, TX39_INTRSTATUS1_SIBSF0INT);
    306 	for (i = 0; (!(tx_conf_read(tc, TX39_INTRSTATUS1_REG) &
    307 		       TX39_INTRSTATUS1_SIBSF0INT)) && i < 100; i++)
    308 		;
    309 	if (i == 100) {
    310 		printf("sf0 busy\n");
    311 		return 0;
    312 	} else 	if (i > 50) {
    313 		printf("sf0 busy loop:%d\n", i);
    314 		return 0;
    315 	}
    316 
    317 	return 1;
    318 }
    319 
    320 void
    321 txsibsf0_reg_write(tc, addr, val)
    322 	tx_chipset_tag_t tc;
    323 	int addr;
    324 	u_int16_t val;
    325 {
    326 	txreg_t reg;
    327 
    328 	reg = txsibsf0_read(tc, addr);
    329 	reg |= TX39_SIBSF0_WRITE;
    330 	TX39_SIBSF0_REGDATA_CLR(reg);
    331 	reg = TX39_SIBSF0_REGDATA_SET(reg, val);
    332 
    333 	__txsibsf0_ready(tc);
    334 	tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg);
    335 }
    336 
    337 u_int16_t
    338 txsibsf0_reg_read(tc, addr)
    339 	tx_chipset_tag_t tc;
    340 	int addr;
    341 {
    342 	return TX39_SIBSF0_REGDATA(txsibsf0_read(tc, addr));
    343 }
    344 
    345 u_int32_t
    346 txsibsf0_read(tc, addr)
    347 	tx_chipset_tag_t tc;
    348 	int addr;
    349 {
    350 	txreg_t reg;
    351 	int retry = 3;
    352 
    353 	do {
    354 		reg = TX39_SIBSF0_REGADDR_SET(0, addr);
    355 		__txsibsf0_ready(tc);
    356 		tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg);
    357 
    358 		__txsibsf0_ready(tc);
    359 		reg = tx_conf_read(tc, TX39_SIBSF0STAT_REG);
    360 
    361 	} while ((TX39_SIBSF0_REGADDR(reg) != addr) && --retry > 0);
    362 
    363 	if (retry <= 0)
    364 		printf("txsibsf0_read: command failed\n");
    365 
    366 	return reg;
    367 }
    368 
    369 /*
    370  * debug functions.
    371  */
    372 
    373 #define ISSETPRINT_CTRL(r, m) \
    374 	__is_set_print(r, TX39_SIBCTRL_##m, #m)
    375 #define ISSETPRINT_DMACTRL(r, m) \
    376 	__is_set_print(r, TX39_SIBDMACTRL_##m, #m)
    377 
    378 void
    379 tx39sib_dump(sc)
    380 	struct tx39sib_softc *sc;
    381 {
    382 	tx_chipset_tag_t tc = sc->sc_tc;
    383 	txreg_t reg;
    384 
    385 	reg = tx_conf_read(tc, TX39_SIBCTRL_REG);
    386 	ISSETPRINT_CTRL(reg, SIBIRQ);
    387 	ISSETPRINT_CTRL(reg, ENCNTTEST);
    388 	ISSETPRINT_CTRL(reg, ENDMATEST);
    389 	ISSETPRINT_CTRL(reg, SNDMONO);
    390 	ISSETPRINT_CTRL(reg, RMONOSNDIN);
    391 	ISSETPRINT_CTRL(reg, TEL16);
    392 	ISSETPRINT_CTRL(reg, SND16);
    393 	ISSETPRINT_CTRL(reg, SELTELSF1);
    394 	ISSETPRINT_CTRL(reg, SELSNDSF1);
    395 	ISSETPRINT_CTRL(reg, ENTEL);
    396 	ISSETPRINT_CTRL(reg, ENSND);
    397 	ISSETPRINT_CTRL(reg, SIBLOOP);
    398 	ISSETPRINT_CTRL(reg, ENSF1);
    399 	ISSETPRINT_CTRL(reg, ENSF0);
    400 	ISSETPRINT_CTRL(reg, ENSIB);
    401 	printf("\n");
    402 	printf("SCLKDIV %d\n", TX39_SIBCTRL_SCLKDIV(reg));
    403 	printf("TELFSDIV %d\n", TX39_SIBCTRL_TELFSDIV(reg));
    404 	printf("SNDFSDIV %d\n", TX39_SIBCTRL_SNDFSDIV(reg));
    405 
    406 	reg = tx_conf_read(tc, TX39_SIBDMACTRL_REG);
    407 	ISSETPRINT_DMACTRL(reg, SNDBUFF1TIME);
    408 	ISSETPRINT_DMACTRL(reg, SNDDMALOOP);
    409 	ISSETPRINT_DMACTRL(reg, ENDMARXSND);
    410 	ISSETPRINT_DMACTRL(reg, ENDMATXSND);
    411 	ISSETPRINT_DMACTRL(reg, TELBUFF1TIME);
    412 	ISSETPRINT_DMACTRL(reg, TELDMALOOP);
    413 	ISSETPRINT_DMACTRL(reg, ENDMARXTEL);
    414 	ISSETPRINT_DMACTRL(reg, ENDMATXTEL);
    415 	printf("\n");
    416 	printf("SNDDMAPTR %d\n", TX39_SIBDMACTRL_TELDMAPTR(reg));
    417 	printf("TELDMAPTR %d\n", TX39_SIBDMACTRL_SNDDMAPTR(reg));
    418 
    419 }
    420