Home | History | Annotate | Line # | Download | only in tx
tx39sib.c revision 1.4
      1 /*	$NetBSD: tx39sib.c,v 1.4 2000/03/03 19:54:36 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	tx39sibdebug = 0;
     51 #define	DPRINTF(arg) if (tx39sibdebug) 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_3912 = {
     98 	0,			/* SIBSCLK = 9.216MHz */
     99 #if 0 /* setting sample */
    100 	40,			/* audio: 7.2kHz */
    101 	26,			/* audio: CD-Audio(/4) 11.077kHz*/
    102 	6,			/* audio: 48kHz */
    103 #endif
    104 	13,			/* audio: CD-Audio(/2 = 22.050) 22.154kHz*/
    105 	40,			/* telecom: 7.2kHz */
    106 	TX39_SIBCTRL_SND16,	/* Audio 16bit mono */
    107 	TX39_SIBCTRL_TEL16	/* Telecom 16bit mono */
    108 };
    109 
    110 struct tx39sib_param tx39sib_param_default_3922 = {
    111 	0,			/* SIBSCLK = 9.216MHz */
    112 	13,			/* audio: CD-Audio(/4) 11.077kHz */
    113 	40,			/* telecom: 7.2kHz */
    114 	TX39_SIBCTRL_SND16,	/* Audio 16bit mono */
    115 	TX39_SIBCTRL_TEL16	/* Telecom 16bit mono */
    116 };
    117 
    118 struct tx39sib_softc {
    119 	struct	device sc_dev;
    120 	tx_chipset_tag_t sc_tc;
    121 
    122 	struct tx39sib_param sc_param;
    123 	int sc_attached;
    124 };
    125 
    126 __inline int	__txsibsf0_ready __P((tx_chipset_tag_t));
    127 #ifdef TX39SIBDEBUG
    128 void	tx39sib_dump __P((struct tx39sib_softc*));
    129 #endif
    130 
    131 struct cfattach tx39sib_ca = {
    132 	sizeof(struct tx39sib_softc), tx39sib_match, tx39sib_attach
    133 };
    134 
    135 int
    136 tx39sib_match(parent, cf, aux)
    137 	struct device *parent;
    138 	struct cfdata *cf;
    139 	void *aux;
    140 {
    141 	return 1;
    142 }
    143 
    144 void
    145 tx39sib_attach(parent, self, aux)
    146 	struct device *parent;
    147 	struct device *self;
    148 	void *aux;
    149 {
    150 	struct txsim_attach_args *ta = aux;
    151 	struct tx39sib_softc *sc = (void*)self;
    152 	tx_chipset_tag_t tc;
    153 
    154 	sc->sc_tc = tc = ta->ta_tc;
    155 
    156 	/* set default param */
    157 #ifdef TX391X
    158 	sc->sc_param = tx39sib_param_default_3912;
    159 #endif /* TX391X */
    160 #ifdef TX392X
    161 	sc->sc_param = tx39sib_param_default_3922;
    162 #endif /* TX392X */
    163 
    164 #define MHZ(a) ((a) / 1000000), (((a) % 1000000) / 1000)
    165 	printf(": %d.%03d MHz", MHZ(tx39sib_clock(self)));
    166 
    167 	printf("\n");
    168 #ifdef TX39SIBDEBUG
    169 	if (tx39sibdebug)
    170 		tx39sib_dump(sc);
    171 #endif
    172 	/* enable subframe0 */
    173 	tx39sib_enable1(self);
    174 	/* enable SIB */
    175 	tx39sib_enable2(self);
    176 
    177 #ifdef TX39SIBDEBUG
    178 	if (tx39sibdebug)
    179 		tx39sib_dump(sc);
    180 #endif
    181 
    182 	config_search(tx39sib_search, self, tx39sib_print);
    183 }
    184 
    185 void
    186 tx39sib_enable1(dev)
    187 	struct device *dev;
    188 {
    189 	struct tx39sib_softc *sc = (void*)dev;
    190 	struct tx39sib_param *param = &sc->sc_param;
    191 	tx_chipset_tag_t tc = sc->sc_tc;
    192 
    193 	txreg_t reg;
    194 
    195 	/* disable SIB */
    196 	tx39sib_disable(dev);
    197 
    198 	/* setup */
    199 	reg = 0;
    200 	/*  SIB clock rate */
    201 	reg = TX39_SIBCTRL_SCLKDIV_SET(reg, param->sp_clock);
    202 	/*  sampling rate (sound) */
    203 	reg = TX39_SIBCTRL_SNDFSDIV_SET(reg, param->sp_snd_rate - 1);
    204 	/*  sampling rate (telecom) */
    205 	reg = TX39_SIBCTRL_TELFSDIV_SET(reg, param->sp_tel_rate - 1);
    206 	/*  data format (8/16bit) */
    207 	reg |= param->sp_sf0sndmode;
    208 	reg |= param->sp_sf0telmode;
    209 	tx_conf_write(tc, TX39_SIBCTRL_REG, reg);
    210 
    211 	/* DMA */
    212 	reg = tx_conf_read(tc, TX39_SIBDMACTRL_REG);
    213 	reg &= ~(TX39_SIBDMACTRL_ENDMARXSND |
    214 		 TX39_SIBDMACTRL_ENDMATXSND |
    215 		 TX39_SIBDMACTRL_ENDMARXTEL |
    216 		 TX39_SIBDMACTRL_ENDMATXTEL);
    217 	tx_conf_write(tc, TX39_SIBDMACTRL_REG, reg);
    218 
    219 	/*
    220 	 * Enable subframe0 (BETTY)
    221 	 */
    222 	reg = tx_conf_read(tc, TX39_SIBCTRL_REG);
    223 	reg |= TX39_SIBCTRL_ENSF0;
    224 	tx_conf_write(tc, TX39_SIBCTRL_REG, reg);
    225 }
    226 
    227 void
    228 tx39sib_enable2(dev)
    229 	struct device *dev;
    230 {
    231 	struct tx39sib_softc *sc = (void*)dev;
    232 	tx_chipset_tag_t tc = sc->sc_tc;
    233 	txreg_t reg;
    234 
    235 	reg = tx_conf_read(tc, TX39_SIBCTRL_REG);
    236 	reg |= TX39_SIBCTRL_ENSIB;
    237 	tx_conf_write(tc, TX39_SIBCTRL_REG, reg);
    238 }
    239 
    240 void
    241 tx39sib_disable(dev)
    242 	struct device *dev;
    243 {
    244 	struct tx39sib_softc *sc = (void*)dev;
    245 	tx_chipset_tag_t tc = sc->sc_tc;
    246 	txreg_t reg;
    247 	/* disable codec side */
    248 	/* notyet */
    249 
    250 	/* disable TX39 side */
    251 	reg = tx_conf_read(tc, TX39_SIBCTRL_REG);
    252 	reg &= ~(TX39_SIBCTRL_ENTEL | TX39_SIBCTRL_ENSND);
    253 	tx_conf_write(tc, TX39_SIBCTRL_REG, reg);
    254 
    255 	/*
    256 	 * Disable subframe0/1 (BETTY/external codec)
    257 	 */
    258 	reg = tx_conf_read(tc, TX39_SIBCTRL_REG);
    259 	reg &= ~TX39_SIBCTRL_ENSF0;
    260 	reg &= ~(TX39_SIBCTRL_ENSF1 | TX39_SIBCTRL_SELTELSF1 |
    261 		 TX39_SIBCTRL_SELSNDSF1);
    262 	tx_conf_write(tc, TX39_SIBCTRL_REG, reg);
    263 
    264 	/* disable TX39SIB module */
    265 	reg &= ~TX39_SIBCTRL_ENSIB;
    266 	tx_conf_write(tc, TX39_SIBCTRL_REG, reg);
    267 }
    268 
    269 int
    270 tx39sib_clock(dev)
    271 	struct device *dev;
    272 {
    273 	struct tx39sib_softc *sc = (void*)dev;
    274 
    275 	return TX39_CLK2X / sibsclk_divide_table[sc->sc_param.sp_clock];
    276 }
    277 
    278 int
    279 tx39sib_search(parent, cf, aux)
    280 	struct device *parent;
    281 	struct cfdata *cf;
    282 	void *aux;
    283 {
    284 	struct tx39sib_softc *sc = (void*)parent;
    285 	struct txsib_attach_args sa;
    286 
    287 	sa.sa_tc	= sc->sc_tc;
    288 	sa.sa_slot	= cf->cf_loc[TXSIBIFCF_SLOT];
    289 	sa.sa_snd_rate	= sc->sc_param.sp_snd_rate;
    290 	sa.sa_tel_rate	= sc->sc_param.sp_tel_rate;
    291 
    292 	if (sa.sa_slot == TXSIBIFCF_SLOT_DEFAULT) {
    293 		printf("tx39sib_search: wildcarded slot, skipping\n");
    294 		return 0;
    295 	}
    296 
    297 	if (!(sc->sc_attached & (1 << sa.sa_slot)) &&/* not attached slot */
    298 	    (*cf->cf_attach->ca_match)(parent, cf, &sa)) {
    299 		config_attach(parent, cf, &sa, tx39sib_print);
    300 		sc->sc_attached |= (1 << sa.sa_slot);
    301 	}
    302 
    303 	return 0;
    304 }
    305 
    306 int
    307 tx39sib_print(aux, pnp)
    308 	void *aux;
    309 	const char *pnp;
    310 {
    311 	struct txsib_attach_args *sa = aux;
    312 
    313 	printf(" slot %d", sa->sa_slot);
    314 
    315 	return QUIET;
    316 }
    317 
    318 /*
    319  * sync access method. don't use runtime.
    320  */
    321 
    322 __inline int
    323 __txsibsf0_ready(tc)
    324 	tx_chipset_tag_t tc;
    325 {
    326 	int i;
    327 
    328 	tx_conf_write(tc, TX39_INTRSTATUS1_REG, TX39_INTRSTATUS1_SIBSF0INT);
    329 	for (i = 0; (!(tx_conf_read(tc, TX39_INTRSTATUS1_REG) &
    330 		       TX39_INTRSTATUS1_SIBSF0INT)) && i < 200; i++)
    331 		;
    332 	if (i >= 200) {
    333 		printf("sf0 busy\n");
    334 		return 0;
    335 	} else 	if (i > 100) {
    336 		printf("sf0 busy loop:%d\n", i);
    337 		return 0;
    338 	}
    339 
    340 	return 1;
    341 }
    342 
    343 void
    344 txsibsf0_reg_write(tc, addr, val)
    345 	tx_chipset_tag_t tc;
    346 	int addr;
    347 	u_int16_t val;
    348 {
    349 	txreg_t reg;
    350 
    351 	reg = txsibsf0_read(tc, addr);
    352 	reg |= TX39_SIBSF0_WRITE;
    353 	TX39_SIBSF0_REGDATA_CLR(reg);
    354 	reg = TX39_SIBSF0_REGDATA_SET(reg, val);
    355 
    356 	__txsibsf0_ready(tc);
    357 	tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg);
    358 }
    359 
    360 u_int16_t
    361 txsibsf0_reg_read(tc, addr)
    362 	tx_chipset_tag_t tc;
    363 	int addr;
    364 {
    365 	return TX39_SIBSF0_REGDATA(txsibsf0_read(tc, addr));
    366 }
    367 
    368 u_int32_t
    369 txsibsf0_read(tc, addr)
    370 	tx_chipset_tag_t tc;
    371 	int addr;
    372 {
    373 	txreg_t reg;
    374 	int retry = 3;
    375 
    376 	do {
    377 		reg = TX39_SIBSF0_REGADDR_SET(0, addr);
    378 		__txsibsf0_ready(tc);
    379 		tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg);
    380 
    381 		__txsibsf0_ready(tc);
    382 		reg = tx_conf_read(tc, TX39_SIBSF0STAT_REG);
    383 
    384 	} while ((TX39_SIBSF0_REGADDR(reg) != addr) && --retry > 0);
    385 
    386 	if (retry <= 0)
    387 		printf("txsibsf0_read: command failed\n");
    388 
    389 	return reg;
    390 }
    391 
    392 #ifdef TX39SIBDEBUG
    393 #define ISSETPRINT_CTRL(r, m) \
    394 	__is_set_print(r, TX39_SIBCTRL_##m, #m)
    395 #define ISSETPRINT_DMACTRL(r, m) \
    396 	__is_set_print(r, TX39_SIBDMACTRL_##m, #m)
    397 
    398 void
    399 tx39sib_dump(sc)
    400 	struct tx39sib_softc *sc;
    401 {
    402 	tx_chipset_tag_t tc = sc->sc_tc;
    403 	txreg_t reg;
    404 
    405 	reg = tx_conf_read(tc, TX39_SIBCTRL_REG);
    406 	ISSETPRINT_CTRL(reg, SIBIRQ);
    407 	ISSETPRINT_CTRL(reg, ENCNTTEST);
    408 	ISSETPRINT_CTRL(reg, ENDMATEST);
    409 	ISSETPRINT_CTRL(reg, SNDMONO);
    410 	ISSETPRINT_CTRL(reg, RMONOSNDIN);
    411 	ISSETPRINT_CTRL(reg, TEL16);
    412 	ISSETPRINT_CTRL(reg, SND16);
    413 	ISSETPRINT_CTRL(reg, SELTELSF1);
    414 	ISSETPRINT_CTRL(reg, SELSNDSF1);
    415 	ISSETPRINT_CTRL(reg, ENTEL);
    416 	ISSETPRINT_CTRL(reg, ENSND);
    417 	ISSETPRINT_CTRL(reg, SIBLOOP);
    418 	ISSETPRINT_CTRL(reg, ENSF1);
    419 	ISSETPRINT_CTRL(reg, ENSF0);
    420 	ISSETPRINT_CTRL(reg, ENSIB);
    421 	printf("\n");
    422 	printf("SCLKDIV %d\n", TX39_SIBCTRL_SCLKDIV(reg));
    423 	printf("TELFSDIV %d\n", TX39_SIBCTRL_TELFSDIV(reg));
    424 	printf("SNDFSDIV %d\n", TX39_SIBCTRL_SNDFSDIV(reg));
    425 
    426 	reg = tx_conf_read(tc, TX39_SIBDMACTRL_REG);
    427 	ISSETPRINT_DMACTRL(reg, SNDBUFF1TIME);
    428 	ISSETPRINT_DMACTRL(reg, SNDDMALOOP);
    429 	ISSETPRINT_DMACTRL(reg, ENDMARXSND);
    430 	ISSETPRINT_DMACTRL(reg, ENDMATXSND);
    431 	ISSETPRINT_DMACTRL(reg, TELBUFF1TIME);
    432 	ISSETPRINT_DMACTRL(reg, TELDMALOOP);
    433 	ISSETPRINT_DMACTRL(reg, ENDMARXTEL);
    434 	ISSETPRINT_DMACTRL(reg, ENDMATXTEL);
    435 	printf("\n");
    436 	printf("SNDDMAPTR %d\n", TX39_SIBDMACTRL_TELDMAPTR(reg));
    437 	printf("TELDMAPTR %d\n", TX39_SIBDMACTRL_SNDDMAPTR(reg));
    438 
    439 }
    440 #endif /* TX39SIBDEBUG */
    441