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