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