1/* $OpenBSD: rkiis.c,v 1.4 2022/10/28 15:09:45 kn Exp $ */ 2/* $NetBSD: rk_i2s.c,v 1.3 2020/02/29 05:51:10 isaki Exp $ */ 3/*- 4 * Copyright (c) 2019 Jared McNeill <jmcneill@invisible.ca> 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. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <sys/param.h> 30#include <sys/systm.h> 31#include <sys/device.h> 32#include <sys/malloc.h> 33#include <sys/fcntl.h> 34 35#include <machine/intr.h> 36#include <machine/bus.h> 37#include <machine/fdt.h> 38 39#include <dev/ofw/openfirm.h> 40#include <dev/ofw/ofw_clock.h> 41#include <dev/ofw/ofw_misc.h> 42#include <dev/ofw/ofw_pinctrl.h> 43#include <dev/ofw/fdt.h> 44 45#include <sys/audioio.h> 46#include <dev/audio_if.h> 47#include <dev/midi_if.h> 48 49#define RK_I2S_FIFO_DEPTH 32 50#define RK_I2S_SAMPLE_RATE 48000 51 52#define I2S_TXCR 0x00 53#define TXCR_RCNT_MASK (0x3f << 17) 54#define TXCR_RCNT_SHIFT 17 55#define TXCR_TCSR_MASK (0x3 << 15) 56#define TXCR_TCSR_SHIFT 15 57#define TXCR_HWT (1 << 14) 58#define TXCR_SJM (1 << 12) 59#define TXCR_FBM (1 << 11) 60#define TXCR_IBM_MASK (0x3 << 9) 61#define TXCR_IBM_SHIFT 9 62#define TXCR_PBM_MASK (0x3 << 7) 63#define TXCR_PBM_SHIFT 7 64#define TXCR_TFS (1 << 5) 65#define TXCR_VDW_MASK (0x1f << 0) 66#define TXCR_VDW_SHIFT 0 67#define I2S_RXCR 0x04 68#define RXCR_RCSR_MASK (0x3 << 15) 69#define RXCR_RCSR_SHIFT 15 70#define RXCR_HWT (1 << 14) 71#define RXCR_SJM (1 << 12) 72#define RXCR_FBM (1 << 11) 73#define RXCR_IBM_MASK (0x3 << 9) 74#define RXCR_IBM_SHIFT 9 75#define RXCR_PBM_MASK (0x3 << 7) 76#define RXCR_PBM_SHIFT 7 77#define RXCR_TFS (1 << 5) 78#define RXCR_VDW_MASK (0x1f << 0) 79#define RXCR_VDW_SHIFT 0 80#define I2S_CKR 0x08 81#define CKR_TRCM_MASK (0x3 << 28) 82#define CKR_TRCM_SHIFT 28 83#define CKR_MSS (1 << 27) 84#define CKR_CKP (1 << 26) 85#define CKR_RLP (1 << 25) 86#define CKR_TLP (1 << 24) 87#define CKR_MDIV_MASK (0xff << 16) 88#define CKR_MDIV_SHIFT 16 89#define CKR_RSD_MASK (0xff << 8) 90#define CKR_RSD_SHIFT 8 91#define CKR_TSD_MASK (0xff << 0) 92#define CKR_TSD_SHIFT 0 93#define I2S_TXFIFOLR 0x0c 94#define TXFIFOLR_TFL_MASK(n) (0x3f << ((n) * 6)) 95#define TXFIFOLR_TFL_SHIFT(n) ((n) * 6) 96#define I2S_DMACR 0x10 97#define DMACR_RDE (1 << 24) 98#define DMACR_RDL_MASK (0x1f << 16) 99#define DMACR_RDL_SHIFT 16 100#define DMACR_TDE (1 << 8) 101#define DMACR_TDL_MASK (0x1f << 0) 102#define DMACR_TDL_SHIFT 0 103#define I2S_INTCR 0x14 104#define INTCR_RFT_MASK (0x1f << 20) 105#define INTCR_RFT_SHIFT 20 106#define INTCR_RXOIC (1 << 18) 107#define INTCR_RXOIE (1 << 17) 108#define INTCR_RXFIE (1 << 16) 109#define INTCR_TFT_MASK (0x1f << 4) 110#define INTCR_TFT_SHIFT 4 111#define INTCR_TXUIC (1 << 2) 112#define INTCR_TXUIE (1 << 1) 113#define INTCR_TXEIE (1 << 0) 114#define I2S_INTSR 0x18 115#define INTSR_RXOI (1 << 17) 116#define INTSR_RXFI (1 << 16) 117#define INTSR_TXUI (1 << 1) 118#define INTSR_TXEI (1 << 0) 119#define I2S_XFER 0x1c 120#define XFER_RXS (1 << 1) 121#define XFER_TXS (1 << 0) 122#define I2S_CLR 0x20 123#define CLR_RXC (1 << 1) 124#define CLR_TXC (1 << 0) 125#define I2S_TXDR 0x24 126#define I2S_RXDR 0x28 127#define I2S_RXFIFOLR 0x2c 128#define RXFIFOLR_RFL_MASK(n) (0x3f << ((n) * 6)) 129#define RXFIFOLR_RFL_SHIFT(n) ((n) * 6) 130 131#define HREAD4(sc, reg) \ 132 (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) 133#define HWRITE4(sc, reg, val) \ 134 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) 135#define HSET4(sc, reg, bits) \ 136 HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits)) 137#define HCLR4(sc, reg, bits) \ 138 HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits)) 139 140int rkiis_match(struct device *, void *, void *); 141void rkiis_attach(struct device *, struct device *, void *); 142 143int rkiis_intr(void *); 144int rkiis_set_format(void *, uint32_t, uint32_t, uint32_t); 145int rkiis_set_sysclk(void *, uint32_t); 146 147int rkiis_open(void *, int); 148int rkiis_set_params(void *, int, int, 149 struct audio_params *, struct audio_params *); 150void *rkiis_allocm(void *, int, size_t, int, int); 151void rkiis_freem(void *, void *, int); 152int rkiis_trigger_output(void *, void *, void *, int, 153 void (*)(void *), void *, struct audio_params *); 154int rkiis_trigger_input(void *, void *, void *, int, 155 void (*)(void *), void *, struct audio_params *); 156int rkiis_halt_output(void *); 157int rkiis_halt_input(void *); 158 159struct rkiis_config { 160 bus_size_t oe_reg; 161 uint32_t oe_mask; 162 uint32_t oe_shift; 163 uint32_t oe_val; 164}; 165 166struct rkiis_config rk3399_i2s_config = { 167 .oe_reg = 0xe220, 168 .oe_mask = 0x7, 169 .oe_shift = 11, 170 .oe_val = 0x7, 171}; 172 173struct rkiis_chan { 174 uint32_t *ch_start; 175 uint32_t *ch_end; 176 uint32_t *ch_cur; 177 178 int ch_blksize; 179 int ch_resid; 180 181 void (*ch_intr)(void *); 182 void *ch_intrarg; 183}; 184 185struct rkiis_softc { 186 struct device sc_dev; 187 bus_space_tag_t sc_iot; 188 bus_space_handle_t sc_ioh; 189 void *sc_ih; 190 191 int sc_node; 192 struct rkiis_config *sc_conf; 193 194 struct rkiis_chan sc_pchan; 195 struct rkiis_chan sc_rchan; 196 197 uint32_t sc_active; 198 199 struct dai_device sc_dai; 200}; 201 202const struct audio_hw_if rkiis_hw_if = { 203 .open = rkiis_open, 204 .set_params = rkiis_set_params, 205 .allocm = rkiis_allocm, 206 .freem = rkiis_freem, 207 .trigger_output = rkiis_trigger_output, 208 .trigger_input = rkiis_trigger_input, 209 .halt_output = rkiis_halt_output, 210 .halt_input = rkiis_halt_input, 211}; 212 213const struct cfattach rkiis_ca = { 214 sizeof (struct rkiis_softc), rkiis_match, rkiis_attach 215}; 216 217struct cfdriver rkiis_cd = { 218 NULL, "rkiis", DV_DULL 219}; 220 221int 222rkiis_match(struct device *parent, void *match, void *aux) 223{ 224 struct fdt_attach_args *faa = aux; 225 226 return OF_is_compatible(faa->fa_node, "rockchip,rk3399-i2s"); 227} 228 229void 230rkiis_attach(struct device *parent, struct device *self, void *aux) 231{ 232 struct rkiis_softc *sc = (struct rkiis_softc *)self; 233 struct fdt_attach_args *faa = aux; 234 struct regmap *rm; 235 uint32_t grf, val; 236 237 if (faa->fa_nreg < 1) { 238 printf(": no registers\n"); 239 return; 240 } 241 242 sc->sc_iot = faa->fa_iot; 243 sc->sc_node = faa->fa_node; 244 sc->sc_conf = &rk3399_i2s_config; 245 246 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, 247 faa->fa_reg[0].size, 0, &sc->sc_ioh)) { 248 printf(": can't map registers\n"); 249 return; 250 } 251 252 pinctrl_byname(sc->sc_node, "default"); 253 clock_enable_all(sc->sc_node); 254 255 grf = OF_getpropint(sc->sc_node, "rockchip,grf", 0); 256 rm = regmap_byphandle(grf); 257 if (rm && sc->sc_conf->oe_mask) { 258 val = sc->sc_conf->oe_val << sc->sc_conf->oe_shift; 259 val |= (sc->sc_conf->oe_mask << sc->sc_conf->oe_shift) << 16; 260 regmap_write_4(rm, sc->sc_conf->oe_reg, val); 261 } 262 263 sc->sc_ih = fdt_intr_establish(faa->fa_node, IPL_AUDIO | IPL_MPSAFE, 264 rkiis_intr, sc, sc->sc_dev.dv_xname); 265 if (sc->sc_ih == NULL) { 266 printf(": can't establish interrupt\n"); 267 goto unmap; 268 } 269 270 printf("\n"); 271 272 sc->sc_dai.dd_node = faa->fa_node; 273 sc->sc_dai.dd_cookie = sc; 274 sc->sc_dai.dd_hw_if = &rkiis_hw_if; 275 sc->sc_dai.dd_set_format = rkiis_set_format; 276 sc->sc_dai.dd_set_sysclk = rkiis_set_sysclk; 277 dai_register(&sc->sc_dai); 278 return; 279 280unmap: 281 bus_space_unmap(sc->sc_iot, sc->sc_ioh, faa->fa_reg[0].size); 282} 283 284int 285rkiis_intr(void *cookie) 286{ 287 struct rkiis_softc *sc = cookie; 288 struct rkiis_chan *pch = &sc->sc_pchan; 289#if notyet 290 struct rkiis_chan *rch = &sc->sc_rchan; 291#endif 292 uint32_t sr, val; 293 int fifolr; 294 295 mtx_enter(&audio_lock); 296 297 sr = HREAD4(sc, I2S_INTSR); 298 299 if ((sr & INTSR_RXFI) != 0) { 300#if notyet 301 val = HREAD4(sc, I2S_RXFIFOLR); 302 fifolr = val & RXFIFOLR_RFL_MASK(0); 303 fifolr >>= RXFIFOLR_RFL_SHIFT(0); 304 while (fifolr > 0) { 305 *rch->ch_data = HREAD4(sc, I2S_RXDR); 306 rch->ch_data++; 307 rch->ch_resid -= 4; 308 if (rch->ch_resid == 0) 309 rch->ch_intr(rch->ch_intrarg); 310 --fifolr; 311 } 312#endif 313 } 314 315 if ((sr & INTSR_TXEI) != 0) { 316 val = HREAD4(sc, I2S_TXFIFOLR); 317 fifolr = val & TXFIFOLR_TFL_MASK(0); 318 fifolr >>= TXFIFOLR_TFL_SHIFT(0); 319 fifolr = min(fifolr, RK_I2S_FIFO_DEPTH); 320 while (fifolr < RK_I2S_FIFO_DEPTH - 1) { 321 HWRITE4(sc, I2S_TXDR, *pch->ch_cur); 322 pch->ch_cur++; 323 if (pch->ch_cur == pch->ch_end) 324 pch->ch_cur = pch->ch_start; 325 pch->ch_resid -= 4; 326 if (pch->ch_resid == 0) { 327 pch->ch_intr(pch->ch_intrarg); 328 pch->ch_resid = pch->ch_blksize; 329 } 330 ++fifolr; 331 } 332 } 333 334 mtx_leave(&audio_lock); 335 336 return 1; 337} 338 339int 340rkiis_set_format(void *cookie, uint32_t fmt, uint32_t pol, 341 uint32_t clk) 342{ 343 struct rkiis_softc *sc = cookie; 344 uint32_t txcr, rxcr, ckr; 345 346 txcr = HREAD4(sc, I2S_TXCR); 347 rxcr = HREAD4(sc, I2S_RXCR); 348 ckr = HREAD4(sc, I2S_CKR); 349 350 txcr &= ~(TXCR_IBM_MASK|TXCR_PBM_MASK|TXCR_TFS); 351 rxcr &= ~(RXCR_IBM_MASK|RXCR_PBM_MASK|RXCR_TFS); 352 switch (fmt) { 353 case DAI_FORMAT_I2S: 354 txcr |= 0 << TXCR_IBM_SHIFT; 355 rxcr |= 0 << RXCR_IBM_SHIFT; 356 break; 357 case DAI_FORMAT_LJ: 358 txcr |= 1 << TXCR_IBM_SHIFT; 359 rxcr |= 1 << RXCR_IBM_SHIFT; 360 break; 361 case DAI_FORMAT_RJ: 362 txcr |= 2 << TXCR_IBM_SHIFT; 363 rxcr |= 2 << RXCR_IBM_SHIFT; 364 break; 365 case DAI_FORMAT_DSPA: 366 txcr |= 0 << TXCR_PBM_SHIFT; 367 txcr |= TXCR_TFS; 368 rxcr |= 0 << RXCR_PBM_SHIFT; 369 txcr |= RXCR_TFS; 370 break; 371 case DAI_FORMAT_DSPB: 372 txcr |= 1 << TXCR_PBM_SHIFT; 373 txcr |= TXCR_TFS; 374 rxcr |= 1 << RXCR_PBM_SHIFT; 375 txcr |= RXCR_TFS; 376 break; 377 default: 378 return EINVAL; 379 } 380 381 HWRITE4(sc, I2S_TXCR, txcr); 382 HWRITE4(sc, I2S_RXCR, rxcr); 383 384 switch (pol) { 385 case DAI_POLARITY_IB|DAI_POLARITY_NF: 386 ckr |= CKR_CKP; 387 break; 388 case DAI_POLARITY_NB|DAI_POLARITY_NF: 389 ckr &= ~CKR_CKP; 390 break; 391 default: 392 return EINVAL; 393 } 394 395 switch (clk) { 396 case DAI_CLOCK_CBM|DAI_CLOCK_CFM: 397 ckr |= CKR_MSS; /* sclk input */ 398 break; 399 case DAI_CLOCK_CBS|DAI_CLOCK_CFS: 400 ckr &= ~CKR_MSS; /* sclk output */ 401 break; 402 default: 403 return EINVAL; 404 } 405 406 HWRITE4(sc, I2S_CKR, ckr); 407 408 return 0; 409} 410 411int 412rkiis_set_sysclk(void *cookie, uint32_t rate) 413{ 414 struct rkiis_softc *sc = cookie; 415 int error; 416 417 error = clock_set_frequency(sc->sc_node, "i2s_clk", rate); 418 if (error != 0) { 419 printf("%s: can't set sysclk to %u Hz\n", 420 sc->sc_dev.dv_xname, rate); 421 return error; 422 } 423 424 return 0; 425} 426 427int 428rkiis_open(void *cookie, int flags) 429{ 430 if ((flags & (FWRITE | FREAD)) == (FWRITE | FREAD)) 431 return ENXIO; 432 433 return 0; 434} 435 436int 437rkiis_set_params(void *cookie, int setmode, int usemode, 438 struct audio_params *play, struct audio_params *rec) 439{ 440 struct rkiis_softc *sc = cookie; 441 uint32_t mclk_rate, bclk_rate; 442 uint32_t bclk_div, lrck_div; 443 uint32_t ckr, txcr, rxcr; 444 int i; 445 446 ckr = HREAD4(sc, I2S_CKR); 447 if ((ckr & CKR_MSS) == 0) { 448 mclk_rate = clock_get_frequency(sc->sc_node, "i2s_clk"); 449 bclk_rate = 2 * 32 * RK_I2S_SAMPLE_RATE; 450 bclk_div = mclk_rate / bclk_rate; 451 lrck_div = bclk_rate / RK_I2S_SAMPLE_RATE; 452 453 ckr &= ~CKR_MDIV_MASK; 454 ckr |= (bclk_div - 1) << CKR_MDIV_SHIFT; 455 ckr &= ~CKR_TSD_MASK; 456 ckr |= (lrck_div - 1) << CKR_TSD_SHIFT; 457 ckr &= ~CKR_RSD_MASK; 458 ckr |= (lrck_div - 1) << CKR_RSD_SHIFT; 459 } 460 461 ckr &= ~CKR_TRCM_MASK; 462 HWRITE4(sc, I2S_CKR, ckr); 463 464 for (i = 0; i < 2; i++) { 465 struct audio_params *p; 466 int mode; 467 468 switch (i) { 469 case 0: 470 mode = AUMODE_PLAY; 471 p = play; 472 break; 473 case 1: 474 mode = AUMODE_RECORD; 475 p = rec; 476 break; 477 default: 478 return EINVAL; 479 } 480 481 if (!(setmode & mode)) 482 continue; 483 484 if (p->channels & 1) 485 return EINVAL; 486 487 if (setmode & AUMODE_PLAY) { 488 txcr = HREAD4(sc, I2S_TXCR); 489 txcr &= ~TXCR_VDW_MASK; 490 txcr |= (16 - 1) << TXCR_VDW_SHIFT; 491 txcr &= ~TXCR_TCSR_MASK; 492 txcr |= (p->channels / 2 - 1) << TXCR_TCSR_SHIFT; 493 HWRITE4(sc, I2S_TXCR, txcr); 494 } else { 495 rxcr = HREAD4(sc, I2S_RXCR); 496 rxcr &= ~RXCR_VDW_MASK; 497 rxcr |= (16 - 1) << RXCR_VDW_SHIFT; 498 rxcr &= ~RXCR_RCSR_MASK; 499 rxcr |= (p->channels / 2 - 1) << RXCR_RCSR_SHIFT; 500 HWRITE4(sc, I2S_RXCR, rxcr); 501 } 502 503 p->encoding = AUDIO_ENCODING_SLINEAR_LE; 504 p->precision = 16; 505 p->bps = AUDIO_BPS(p->precision); 506 p->msb = 1; 507 p->sample_rate = RK_I2S_SAMPLE_RATE; 508 } 509 510 return 0; 511} 512 513void * 514rkiis_allocm(void *cookie, int direction, size_t size, int type, 515 int flags) 516{ 517 return malloc(size, M_DEVBUF, M_WAITOK | M_ZERO); 518} 519 520void 521rkiis_freem(void *cookie, void *addr, int size) 522{ 523 free(addr, M_DEVBUF, size); 524} 525 526int 527rkiis_trigger_output(void *cookie, void *start, void *end, int blksize, 528 void (*intr)(void *), void *intrarg, struct audio_params *params) 529{ 530 struct rkiis_softc *sc = cookie; 531 struct rkiis_chan *ch = &sc->sc_pchan; 532 uint32_t val; 533 534 if (sc->sc_active == 0) { 535 val = HREAD4(sc, I2S_XFER); 536 val |= (XFER_TXS | XFER_RXS); 537 HWRITE4(sc, I2S_XFER, val); 538 } 539 540 sc->sc_active |= XFER_TXS; 541 542 val = HREAD4(sc, I2S_INTCR); 543 val |= INTCR_TXEIE; 544 val &= ~INTCR_TFT_MASK; 545 val |= (RK_I2S_FIFO_DEPTH / 2) << INTCR_TFT_SHIFT; 546 HWRITE4(sc, I2S_INTCR, val); 547 548 ch->ch_intr = intr; 549 ch->ch_intrarg = intrarg; 550 ch->ch_start = ch->ch_cur = start; 551 ch->ch_end = end; 552 ch->ch_blksize = blksize; 553 ch->ch_resid = blksize; 554 555 return 0; 556} 557 558int 559rkiis_trigger_input(void *cookie, void *start, void *end, int blksize, 560 void (*intr)(void *), void *intrarg, struct audio_params *params) 561{ 562 return EIO; 563} 564 565int 566rkiis_halt_output(void *cookie) 567{ 568 struct rkiis_softc *sc = cookie; 569 struct rkiis_chan *ch = &sc->sc_pchan; 570 uint32_t val; 571 572 sc->sc_active &= ~XFER_TXS; 573 if (sc->sc_active == 0) { 574 val = HREAD4(sc, I2S_XFER); 575 val &= ~(XFER_TXS|XFER_RXS); 576 HWRITE4(sc, I2S_XFER, val); 577 } 578 579 val = HREAD4(sc, I2S_INTCR); 580 val &= ~INTCR_TXEIE; 581 HWRITE4(sc, I2S_INTCR, val); 582 583 val = HREAD4(sc, I2S_CLR); 584 val |= CLR_TXC; 585 HWRITE4(sc, I2S_CLR, val); 586 587 while ((HREAD4(sc, I2S_CLR) & CLR_TXC) != 0) 588 delay(1); 589 590 ch->ch_intr = NULL; 591 ch->ch_intrarg = NULL; 592 593 return 0; 594} 595 596int 597rkiis_halt_input(void *cookie) 598{ 599 struct rkiis_softc *sc = cookie; 600 struct rkiis_chan *ch = &sc->sc_rchan; 601 uint32_t val; 602 603 sc->sc_active &= ~XFER_RXS; 604 if (sc->sc_active == 0) { 605 val = HREAD4(sc, I2S_XFER); 606 val &= ~(XFER_TXS|XFER_RXS); 607 HWRITE4(sc, I2S_XFER, val); 608 } 609 610 val = HREAD4(sc, I2S_INTCR); 611 val &= ~INTCR_RXFIE; 612 HWRITE4(sc, I2S_INTCR, val); 613 614 ch->ch_intr = NULL; 615 ch->ch_intrarg = NULL; 616 617 return 0; 618} 619