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