1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // Socionext UniPhier AIO ALSA common driver. 4 // 5 // Copyright (c) 2016-2018 Socionext Inc. 6 7 #include <linux/bitfield.h> 8 #include <linux/errno.h> 9 #include <linux/kernel.h> 10 #include <linux/module.h> 11 #include <sound/core.h> 12 #include <sound/pcm.h> 13 #include <sound/pcm_params.h> 14 #include <sound/soc.h> 15 16 #include "aio.h" 17 #include "aio-reg.h" 18 19 static u64 rb_cnt(u64 wr, u64 rd, u64 len) 20 { 21 if (rd <= wr) 22 return wr - rd; 23 else 24 return len - (rd - wr); 25 } 26 27 static u64 rb_cnt_to_end(u64 wr, u64 rd, u64 len) 28 { 29 if (rd <= wr) 30 return wr - rd; 31 else 32 return len - rd; 33 } 34 35 static u64 rb_space(u64 wr, u64 rd, u64 len) 36 { 37 if (rd <= wr) 38 return len - (wr - rd) - 8; 39 else 40 return rd - wr - 8; 41 } 42 43 static u64 rb_space_to_end(u64 wr, u64 rd, u64 len) 44 { 45 if (rd > wr) 46 return rd - wr - 8; 47 else if (rd > 0) 48 return len - wr; 49 else 50 return len - wr - 8; 51 } 52 53 u64 aio_rb_cnt(struct uniphier_aio_sub *sub) 54 { 55 return rb_cnt(sub->wr_offs, sub->rd_offs, sub->compr_bytes); 56 } 57 58 u64 aio_rbt_cnt_to_end(struct uniphier_aio_sub *sub) 59 { 60 return rb_cnt_to_end(sub->wr_offs, sub->rd_offs, sub->compr_bytes); 61 } 62 63 u64 aio_rb_space(struct uniphier_aio_sub *sub) 64 { 65 return rb_space(sub->wr_offs, sub->rd_offs, sub->compr_bytes); 66 } 67 68 u64 aio_rb_space_to_end(struct uniphier_aio_sub *sub) 69 { 70 return rb_space_to_end(sub->wr_offs, sub->rd_offs, sub->compr_bytes); 71 } 72 73 /** 74 * aio_iecout_set_enable - setup IEC output via SoC glue 75 * @chip: the AIO chip pointer 76 * @enable: false to stop the output, true to start 77 * 78 * Set enabled or disabled S/PDIF signal output to out of SoC via AOnIEC pins. 79 * This function need to call at driver startup. 80 * 81 * The regmap of SoC glue is specified by 'socionext,syscon' optional property 82 * of DT. This function has no effect if no property. 83 */ 84 void aio_iecout_set_enable(struct uniphier_aio_chip *chip, bool enable) 85 { 86 struct regmap *r = chip->regmap_sg; 87 88 if (!r) 89 return; 90 91 regmap_write(r, SG_AOUTEN, (enable) ? ~0 : 0); 92 } 93 94 /** 95 * aio_chip_set_pll - set frequency to audio PLL 96 * @chip: the AIO chip pointer 97 * @pll_id: PLL 98 * @freq: frequency in Hz, 0 is ignored 99 * 100 * Sets frequency of audio PLL. This function can be called anytime, 101 * but it takes time till PLL is locked. 102 * 103 * Return: Zero if successful, otherwise a negative value on error. 104 */ 105 int aio_chip_set_pll(struct uniphier_aio_chip *chip, int pll_id, 106 unsigned int freq) 107 { 108 struct device *dev = &chip->pdev->dev; 109 struct regmap *r = chip->regmap; 110 int shift; 111 u32 v; 112 113 /* Not change */ 114 if (freq == 0) 115 return 0; 116 117 switch (pll_id) { 118 case AUD_PLL_A1: 119 shift = 0; 120 break; 121 case AUD_PLL_F1: 122 shift = 1; 123 break; 124 case AUD_PLL_A2: 125 shift = 2; 126 break; 127 case AUD_PLL_F2: 128 shift = 3; 129 break; 130 default: 131 dev_err(dev, "PLL(%d) not supported\n", pll_id); 132 return -EINVAL; 133 } 134 135 switch (freq) { 136 case 36864000: 137 v = A2APLLCTR1_APLLX_36MHZ; 138 break; 139 case 33868800: 140 v = A2APLLCTR1_APLLX_33MHZ; 141 break; 142 default: 143 dev_err(dev, "PLL frequency not supported(%d)\n", freq); 144 return -EINVAL; 145 } 146 chip->plls[pll_id].freq = freq; 147 148 regmap_update_bits(r, A2APLLCTR1, A2APLLCTR1_APLLX_MASK << shift, 149 v << shift); 150 151 return 0; 152 } 153 154 /** 155 * aio_chip_init - initialize AIO whole settings 156 * @chip: the AIO chip pointer 157 * 158 * Sets AIO fixed and whole device settings to AIO. 159 * This function need to call once at driver startup. 160 * 161 * The register area that is changed by this function is shared by all 162 * modules of AIO. But there is not race condition since this function 163 * has always set the same initialize values. 164 */ 165 void aio_chip_init(struct uniphier_aio_chip *chip) 166 { 167 struct regmap *r = chip->regmap; 168 169 regmap_update_bits(r, A2APLLCTR0, 170 A2APLLCTR0_APLLXPOW_MASK, 171 A2APLLCTR0_APLLXPOW_PWON); 172 173 regmap_update_bits(r, A2EXMCLKSEL0, 174 A2EXMCLKSEL0_EXMCLK_MASK, 175 A2EXMCLKSEL0_EXMCLK_OUTPUT); 176 177 regmap_update_bits(r, A2AIOINPUTSEL, A2AIOINPUTSEL_RXSEL_MASK, 178 A2AIOINPUTSEL_RXSEL_PCMI1_HDMIRX1 | 179 A2AIOINPUTSEL_RXSEL_PCMI2_SIF | 180 A2AIOINPUTSEL_RXSEL_PCMI3_EVEA | 181 A2AIOINPUTSEL_RXSEL_IECI1_HDMIRX1); 182 183 if (chip->chip_spec->addr_ext) 184 regmap_update_bits(r, CDA2D_TEST, CDA2D_TEST_DDR_MODE_MASK, 185 CDA2D_TEST_DDR_MODE_EXTON0); 186 else 187 regmap_update_bits(r, CDA2D_TEST, CDA2D_TEST_DDR_MODE_MASK, 188 CDA2D_TEST_DDR_MODE_EXTOFF1); 189 } 190 191 /** 192 * aio_init - initialize AIO substream 193 * @sub: the AIO substream pointer 194 * 195 * Sets fixed settings of each AIO substreams. 196 * This function need to call once at substream startup. 197 * 198 * Return: Zero if successful, otherwise a negative value on error. 199 */ 200 int aio_init(struct uniphier_aio_sub *sub) 201 { 202 struct device *dev = &sub->aio->chip->pdev->dev; 203 struct regmap *r = sub->aio->chip->regmap; 204 205 regmap_write(r, A2RBNMAPCTR0(sub->swm->rb.hw), 206 MAPCTR0_EN | sub->swm->rb.map); 207 regmap_write(r, A2CHNMAPCTR0(sub->swm->ch.hw), 208 MAPCTR0_EN | sub->swm->ch.map); 209 210 switch (sub->swm->type) { 211 case PORT_TYPE_I2S: 212 case PORT_TYPE_SPDIF: 213 case PORT_TYPE_EVE: 214 if (sub->swm->dir == PORT_DIR_INPUT) { 215 regmap_write(r, A2IIFNMAPCTR0(sub->swm->iif.hw), 216 MAPCTR0_EN | sub->swm->iif.map); 217 regmap_write(r, A2IPORTNMAPCTR0(sub->swm->iport.hw), 218 MAPCTR0_EN | sub->swm->iport.map); 219 } else { 220 regmap_write(r, A2OIFNMAPCTR0(sub->swm->oif.hw), 221 MAPCTR0_EN | sub->swm->oif.map); 222 regmap_write(r, A2OPORTNMAPCTR0(sub->swm->oport.hw), 223 MAPCTR0_EN | sub->swm->oport.map); 224 } 225 break; 226 case PORT_TYPE_CONV: 227 regmap_write(r, A2OIFNMAPCTR0(sub->swm->oif.hw), 228 MAPCTR0_EN | sub->swm->oif.map); 229 regmap_write(r, A2OPORTNMAPCTR0(sub->swm->oport.hw), 230 MAPCTR0_EN | sub->swm->oport.map); 231 regmap_write(r, A2CHNMAPCTR0(sub->swm->och.hw), 232 MAPCTR0_EN | sub->swm->och.map); 233 regmap_write(r, A2IIFNMAPCTR0(sub->swm->iif.hw), 234 MAPCTR0_EN | sub->swm->iif.map); 235 break; 236 default: 237 dev_err(dev, "Unknown port type %d.\n", sub->swm->type); 238 return -EINVAL; 239 } 240 241 return 0; 242 } 243 244 /** 245 * aio_port_reset - reset AIO port block 246 * @sub: the AIO substream pointer 247 * 248 * Resets the digital signal input/output port block of AIO. 249 */ 250 void aio_port_reset(struct uniphier_aio_sub *sub) 251 { 252 struct regmap *r = sub->aio->chip->regmap; 253 254 if (sub->swm->dir == PORT_DIR_OUTPUT) { 255 regmap_write(r, AOUTRSTCTR0, BIT(sub->swm->oport.map)); 256 regmap_write(r, AOUTRSTCTR1, BIT(sub->swm->oport.map)); 257 } else { 258 regmap_update_bits(r, IPORTMXRSTCTR(sub->swm->iport.map), 259 IPORTMXRSTCTR_RSTPI_MASK, 260 IPORTMXRSTCTR_RSTPI_RESET); 261 regmap_update_bits(r, IPORTMXRSTCTR(sub->swm->iport.map), 262 IPORTMXRSTCTR_RSTPI_MASK, 263 IPORTMXRSTCTR_RSTPI_RELEASE); 264 } 265 } 266 267 /** 268 * aio_port_set_ch - set channels of LPCM 269 * @sub: the AIO substream pointer, PCM substream only 270 * 271 * Set suitable slot selecting to input/output port block of AIO. 272 * 273 * This function may return error if non-PCM substream. 274 * 275 * Return: Zero if successful, otherwise a negative value on error. 276 */ 277 static int aio_port_set_ch(struct uniphier_aio_sub *sub) 278 { 279 struct regmap *r = sub->aio->chip->regmap; 280 static const u32 slotsel_2ch[] = { 281 0, 0, 0, 0, 0, 282 }; 283 static const u32 slotsel_multi[] = { 284 OPORTMXTYSLOTCTR_SLOTSEL_SLOT0, 285 OPORTMXTYSLOTCTR_SLOTSEL_SLOT1, 286 OPORTMXTYSLOTCTR_SLOTSEL_SLOT2, 287 OPORTMXTYSLOTCTR_SLOTSEL_SLOT3, 288 OPORTMXTYSLOTCTR_SLOTSEL_SLOT4, 289 }; 290 u32 mode; 291 const u32 *slotsel; 292 int i; 293 294 switch (params_channels(&sub->params)) { 295 case 8: 296 case 6: 297 mode = OPORTMXTYSLOTCTR_MODE; 298 slotsel = slotsel_multi; 299 break; 300 case 2: 301 mode = 0; 302 slotsel = slotsel_2ch; 303 break; 304 default: 305 return -EINVAL; 306 } 307 308 for (i = 0; i < AUD_MAX_SLOTSEL; i++) { 309 regmap_update_bits(r, OPORTMXTYSLOTCTR(sub->swm->oport.map, i), 310 OPORTMXTYSLOTCTR_MODE, mode); 311 regmap_update_bits(r, OPORTMXTYSLOTCTR(sub->swm->oport.map, i), 312 OPORTMXTYSLOTCTR_SLOTSEL_MASK, slotsel[i]); 313 } 314 315 return 0; 316 } 317 318 /** 319 * aio_port_set_rate - set sampling rate of LPCM 320 * @sub: the AIO substream pointer, PCM substream only 321 * @rate: Sampling rate in Hz. 322 * 323 * Set suitable I2S format settings to input/output port block of AIO. 324 * Parameter is specified by hw_params(). 325 * 326 * This function may return error if non-PCM substream. 327 * 328 * Return: Zero if successful, otherwise a negative value on error. 329 */ 330 static int aio_port_set_rate(struct uniphier_aio_sub *sub, int rate) 331 { 332 struct regmap *r = sub->aio->chip->regmap; 333 struct device *dev = &sub->aio->chip->pdev->dev; 334 u32 v; 335 336 if (sub->swm->dir == PORT_DIR_OUTPUT) { 337 switch (rate) { 338 case 8000: 339 v = OPORTMXCTR1_FSSEL_8; 340 break; 341 case 11025: 342 v = OPORTMXCTR1_FSSEL_11_025; 343 break; 344 case 12000: 345 v = OPORTMXCTR1_FSSEL_12; 346 break; 347 case 16000: 348 v = OPORTMXCTR1_FSSEL_16; 349 break; 350 case 22050: 351 v = OPORTMXCTR1_FSSEL_22_05; 352 break; 353 case 24000: 354 v = OPORTMXCTR1_FSSEL_24; 355 break; 356 case 32000: 357 v = OPORTMXCTR1_FSSEL_32; 358 break; 359 case 44100: 360 v = OPORTMXCTR1_FSSEL_44_1; 361 break; 362 case 48000: 363 v = OPORTMXCTR1_FSSEL_48; 364 break; 365 case 88200: 366 v = OPORTMXCTR1_FSSEL_88_2; 367 break; 368 case 96000: 369 v = OPORTMXCTR1_FSSEL_96; 370 break; 371 case 176400: 372 v = OPORTMXCTR1_FSSEL_176_4; 373 break; 374 case 192000: 375 v = OPORTMXCTR1_FSSEL_192; 376 break; 377 default: 378 dev_err(dev, "Rate not supported(%d)\n", rate); 379 return -EINVAL; 380 } 381 382 regmap_update_bits(r, OPORTMXCTR1(sub->swm->oport.map), 383 OPORTMXCTR1_FSSEL_MASK, v); 384 } else { 385 switch (rate) { 386 case 8000: 387 v = IPORTMXCTR1_FSSEL_8; 388 break; 389 case 11025: 390 v = IPORTMXCTR1_FSSEL_11_025; 391 break; 392 case 12000: 393 v = IPORTMXCTR1_FSSEL_12; 394 break; 395 case 16000: 396 v = IPORTMXCTR1_FSSEL_16; 397 break; 398 case 22050: 399 v = IPORTMXCTR1_FSSEL_22_05; 400 break; 401 case 24000: 402 v = IPORTMXCTR1_FSSEL_24; 403 break; 404 case 32000: 405 v = IPORTMXCTR1_FSSEL_32; 406 break; 407 case 44100: 408 v = IPORTMXCTR1_FSSEL_44_1; 409 break; 410 case 48000: 411 v = IPORTMXCTR1_FSSEL_48; 412 break; 413 case 88200: 414 v = IPORTMXCTR1_FSSEL_88_2; 415 break; 416 case 96000: 417 v = IPORTMXCTR1_FSSEL_96; 418 break; 419 case 176400: 420 v = IPORTMXCTR1_FSSEL_176_4; 421 break; 422 case 192000: 423 v = IPORTMXCTR1_FSSEL_192; 424 break; 425 default: 426 dev_err(dev, "Rate not supported(%d)\n", rate); 427 return -EINVAL; 428 } 429 430 regmap_update_bits(r, IPORTMXCTR1(sub->swm->iport.map), 431 IPORTMXCTR1_FSSEL_MASK, v); 432 } 433 434 return 0; 435 } 436 437 /** 438 * aio_port_set_fmt - set format of I2S data 439 * @sub: the AIO substream pointer, PCM substream only 440 * This parameter has no effect if substream is I2S or PCM. 441 * 442 * Set suitable I2S format settings to input/output port block of AIO. 443 * Parameter is specified by set_fmt(). 444 * 445 * This function may return error if non-PCM substream. 446 * 447 * Return: Zero if successful, otherwise a negative value on error. 448 */ 449 static int aio_port_set_fmt(struct uniphier_aio_sub *sub) 450 { 451 struct regmap *r = sub->aio->chip->regmap; 452 struct device *dev = &sub->aio->chip->pdev->dev; 453 u32 v; 454 455 if (sub->swm->dir == PORT_DIR_OUTPUT) { 456 switch (sub->aio->fmt) { 457 case SND_SOC_DAIFMT_LEFT_J: 458 v = OPORTMXCTR1_I2SLRSEL_LEFT; 459 break; 460 case SND_SOC_DAIFMT_RIGHT_J: 461 v = OPORTMXCTR1_I2SLRSEL_RIGHT; 462 break; 463 case SND_SOC_DAIFMT_I2S: 464 v = OPORTMXCTR1_I2SLRSEL_I2S; 465 break; 466 default: 467 dev_err(dev, "Format is not supported(%d)\n", 468 sub->aio->fmt); 469 return -EINVAL; 470 } 471 472 v |= OPORTMXCTR1_OUTBITSEL_24; 473 regmap_update_bits(r, OPORTMXCTR1(sub->swm->oport.map), 474 OPORTMXCTR1_I2SLRSEL_MASK | 475 OPORTMXCTR1_OUTBITSEL_MASK, v); 476 } else { 477 switch (sub->aio->fmt) { 478 case SND_SOC_DAIFMT_LEFT_J: 479 v = IPORTMXCTR1_LRSEL_LEFT; 480 break; 481 case SND_SOC_DAIFMT_RIGHT_J: 482 v = IPORTMXCTR1_LRSEL_RIGHT; 483 break; 484 case SND_SOC_DAIFMT_I2S: 485 v = IPORTMXCTR1_LRSEL_I2S; 486 break; 487 default: 488 dev_err(dev, "Format is not supported(%d)\n", 489 sub->aio->fmt); 490 return -EINVAL; 491 } 492 493 v |= IPORTMXCTR1_OUTBITSEL_24 | 494 IPORTMXCTR1_CHSEL_ALL; 495 regmap_update_bits(r, IPORTMXCTR1(sub->swm->iport.map), 496 IPORTMXCTR1_LRSEL_MASK | 497 IPORTMXCTR1_OUTBITSEL_MASK | 498 IPORTMXCTR1_CHSEL_MASK, v); 499 } 500 501 return 0; 502 } 503 504 /** 505 * aio_port_set_clk - set clock and divider of AIO port block 506 * @sub: the AIO substream pointer 507 * 508 * Set suitable PLL clock divider and relational settings to 509 * input/output port block of AIO. Parameters are specified by 510 * set_sysclk() and set_pll(). 511 * 512 * Return: Zero if successful, otherwise a negative value on error. 513 */ 514 static int aio_port_set_clk(struct uniphier_aio_sub *sub) 515 { 516 struct uniphier_aio_chip *chip = sub->aio->chip; 517 struct device *dev = &sub->aio->chip->pdev->dev; 518 struct regmap *r = sub->aio->chip->regmap; 519 static const u32 v_pll[] = { 520 OPORTMXCTR2_ACLKSEL_A1, OPORTMXCTR2_ACLKSEL_F1, 521 OPORTMXCTR2_ACLKSEL_A2, OPORTMXCTR2_ACLKSEL_F2, 522 OPORTMXCTR2_ACLKSEL_A2PLL, 523 OPORTMXCTR2_ACLKSEL_RX1, 524 }; 525 static const u32 v_div[] = { 526 OPORTMXCTR2_DACCKSEL_1_2, OPORTMXCTR2_DACCKSEL_1_3, 527 OPORTMXCTR2_DACCKSEL_1_1, OPORTMXCTR2_DACCKSEL_2_3, 528 }; 529 u32 v; 530 531 if (sub->swm->dir == PORT_DIR_OUTPUT) { 532 if (sub->swm->type == PORT_TYPE_I2S) { 533 if (sub->aio->pll_out >= ARRAY_SIZE(v_pll)) { 534 dev_err(dev, "PLL(%d) is invalid\n", 535 sub->aio->pll_out); 536 return -EINVAL; 537 } 538 if (sub->aio->plldiv >= ARRAY_SIZE(v_div)) { 539 dev_err(dev, "PLL divider(%d) is invalid\n", 540 sub->aio->plldiv); 541 return -EINVAL; 542 } 543 544 v = v_pll[sub->aio->pll_out] | 545 OPORTMXCTR2_MSSEL_MASTER | 546 v_div[sub->aio->plldiv]; 547 548 switch (chip->plls[sub->aio->pll_out].freq) { 549 case 0: 550 case 36864000: 551 case 33868800: 552 v |= OPORTMXCTR2_EXTLSIFSSEL_36; 553 break; 554 default: 555 v |= OPORTMXCTR2_EXTLSIFSSEL_24; 556 break; 557 } 558 } else if (sub->swm->type == PORT_TYPE_EVE) { 559 v = OPORTMXCTR2_ACLKSEL_A2PLL | 560 OPORTMXCTR2_MSSEL_MASTER | 561 OPORTMXCTR2_EXTLSIFSSEL_36 | 562 OPORTMXCTR2_DACCKSEL_1_2; 563 } else if (sub->swm->type == PORT_TYPE_SPDIF) { 564 if (sub->aio->pll_out >= ARRAY_SIZE(v_pll)) { 565 dev_err(dev, "PLL(%d) is invalid\n", 566 sub->aio->pll_out); 567 return -EINVAL; 568 } 569 v = v_pll[sub->aio->pll_out] | 570 OPORTMXCTR2_MSSEL_MASTER | 571 OPORTMXCTR2_DACCKSEL_1_2; 572 573 switch (chip->plls[sub->aio->pll_out].freq) { 574 case 0: 575 case 36864000: 576 case 33868800: 577 v |= OPORTMXCTR2_EXTLSIFSSEL_36; 578 break; 579 default: 580 v |= OPORTMXCTR2_EXTLSIFSSEL_24; 581 break; 582 } 583 } else { 584 v = OPORTMXCTR2_ACLKSEL_A1 | 585 OPORTMXCTR2_MSSEL_MASTER | 586 OPORTMXCTR2_EXTLSIFSSEL_36 | 587 OPORTMXCTR2_DACCKSEL_1_2; 588 } 589 regmap_write(r, OPORTMXCTR2(sub->swm->oport.map), v); 590 } else { 591 v = IPORTMXCTR2_ACLKSEL_A1 | 592 IPORTMXCTR2_MSSEL_SLAVE | 593 IPORTMXCTR2_EXTLSIFSSEL_36 | 594 IPORTMXCTR2_DACCKSEL_1_2; 595 regmap_write(r, IPORTMXCTR2(sub->swm->iport.map), v); 596 } 597 598 return 0; 599 } 600 601 /** 602 * aio_port_set_param - set parameters of AIO port block 603 * @sub: the AIO substream pointer 604 * @pass_through: Zero if sound data is LPCM, otherwise if data is not LPCM. 605 * This parameter has no effect if substream is I2S or PCM. 606 * @params: hardware parameters of ALSA 607 * 608 * Set suitable setting to input/output port block of AIO to process the 609 * specified in params. 610 * 611 * Return: Zero if successful, otherwise a negative value on error. 612 */ 613 int aio_port_set_param(struct uniphier_aio_sub *sub, int pass_through, 614 const struct snd_pcm_hw_params *params) 615 { 616 struct regmap *r = sub->aio->chip->regmap; 617 unsigned int rate; 618 u32 v; 619 int ret; 620 621 if (!pass_through) { 622 if (sub->swm->type == PORT_TYPE_EVE || 623 sub->swm->type == PORT_TYPE_CONV) { 624 rate = 48000; 625 } else { 626 rate = params_rate(params); 627 } 628 629 ret = aio_port_set_ch(sub); 630 if (ret) 631 return ret; 632 633 ret = aio_port_set_rate(sub, rate); 634 if (ret) 635 return ret; 636 637 ret = aio_port_set_fmt(sub); 638 if (ret) 639 return ret; 640 } 641 642 ret = aio_port_set_clk(sub); 643 if (ret) 644 return ret; 645 646 if (sub->swm->dir == PORT_DIR_OUTPUT) { 647 if (pass_through) 648 v = OPORTMXCTR3_SRCSEL_STREAM | 649 OPORTMXCTR3_VALID_STREAM; 650 else 651 v = OPORTMXCTR3_SRCSEL_PCM | 652 OPORTMXCTR3_VALID_PCM; 653 654 v |= OPORTMXCTR3_IECTHUR_IECOUT | 655 OPORTMXCTR3_PMSEL_PAUSE | 656 OPORTMXCTR3_PMSW_MUTE_OFF; 657 regmap_write(r, OPORTMXCTR3(sub->swm->oport.map), v); 658 } else { 659 regmap_write(r, IPORTMXACLKSEL0EX(sub->swm->iport.map), 660 IPORTMXACLKSEL0EX_ACLKSEL0EX_INTERNAL); 661 regmap_write(r, IPORTMXEXNOE(sub->swm->iport.map), 662 IPORTMXEXNOE_PCMINOE_INPUT); 663 } 664 665 return 0; 666 } 667 668 /** 669 * aio_port_set_enable - start or stop of AIO port block 670 * @sub: the AIO substream pointer 671 * @enable: zero to stop the block, otherwise to start 672 * 673 * Start or stop the signal input/output port block of AIO. 674 */ 675 void aio_port_set_enable(struct uniphier_aio_sub *sub, int enable) 676 { 677 struct regmap *r = sub->aio->chip->regmap; 678 679 if (sub->swm->dir == PORT_DIR_OUTPUT) { 680 regmap_write(r, OPORTMXPATH(sub->swm->oport.map), 681 sub->swm->oif.map); 682 683 regmap_update_bits(r, OPORTMXMASK(sub->swm->oport.map), 684 OPORTMXMASK_IUDXMSK_MASK | 685 OPORTMXMASK_IUXCKMSK_MASK | 686 OPORTMXMASK_DXMSK_MASK | 687 OPORTMXMASK_XCKMSK_MASK, 688 OPORTMXMASK_IUDXMSK_OFF | 689 OPORTMXMASK_IUXCKMSK_OFF | 690 OPORTMXMASK_DXMSK_OFF | 691 OPORTMXMASK_XCKMSK_OFF); 692 693 if (enable) 694 regmap_write(r, AOUTENCTR0, BIT(sub->swm->oport.map)); 695 else 696 regmap_write(r, AOUTENCTR1, BIT(sub->swm->oport.map)); 697 } else { 698 regmap_update_bits(r, IPORTMXMASK(sub->swm->iport.map), 699 IPORTMXMASK_IUXCKMSK_MASK | 700 IPORTMXMASK_XCKMSK_MASK, 701 IPORTMXMASK_IUXCKMSK_OFF | 702 IPORTMXMASK_XCKMSK_OFF); 703 704 if (enable) 705 regmap_update_bits(r, 706 IPORTMXCTR2(sub->swm->iport.map), 707 IPORTMXCTR2_REQEN_MASK, 708 IPORTMXCTR2_REQEN_ENABLE); 709 else 710 regmap_update_bits(r, 711 IPORTMXCTR2(sub->swm->iport.map), 712 IPORTMXCTR2_REQEN_MASK, 713 IPORTMXCTR2_REQEN_DISABLE); 714 } 715 } 716 717 /** 718 * aio_port_get_volume - get volume of AIO port block 719 * @sub: the AIO substream pointer 720 * 721 * Return: current volume, range is 0x0000 - 0xffff 722 */ 723 int aio_port_get_volume(struct uniphier_aio_sub *sub) 724 { 725 struct regmap *r = sub->aio->chip->regmap; 726 u32 v; 727 728 regmap_read(r, OPORTMXTYVOLGAINSTATUS(sub->swm->oport.map, 0), &v); 729 730 return FIELD_GET(OPORTMXTYVOLGAINSTATUS_CUR_MASK, v); 731 } 732 733 /** 734 * aio_port_set_volume - set volume of AIO port block 735 * @sub: the AIO substream pointer 736 * @vol: target volume, range is 0x0000 - 0xffff. 737 * 738 * Change digital volume and perfome fade-out/fade-in effect for specified 739 * output slot of port. Gained PCM value can calculate as the following: 740 * Gained = Original * vol / 0x4000 741 */ 742 void aio_port_set_volume(struct uniphier_aio_sub *sub, int vol) 743 { 744 struct regmap *r = sub->aio->chip->regmap; 745 int oport_map = sub->swm->oport.map; 746 int cur, diff, slope = 0, fs; 747 748 if (sub->swm->dir == PORT_DIR_INPUT) 749 return; 750 751 cur = aio_port_get_volume(sub); 752 diff = abs(vol - cur); 753 fs = params_rate(&sub->params); 754 if (fs) 755 slope = diff / AUD_VOL_FADE_TIME * 1000 / fs; 756 slope = max(1, slope); 757 758 regmap_update_bits(r, OPORTMXTYVOLPARA1(oport_map, 0), 759 OPORTMXTYVOLPARA1_SLOPEU_MASK, slope << 16); 760 regmap_update_bits(r, OPORTMXTYVOLPARA2(oport_map, 0), 761 OPORTMXTYVOLPARA2_TARGET_MASK, vol); 762 763 if (cur < vol) 764 regmap_update_bits(r, OPORTMXTYVOLPARA2(oport_map, 0), 765 OPORTMXTYVOLPARA2_FADE_MASK, 766 OPORTMXTYVOLPARA2_FADE_FADEIN); 767 else 768 regmap_update_bits(r, OPORTMXTYVOLPARA2(oport_map, 0), 769 OPORTMXTYVOLPARA2_FADE_MASK, 770 OPORTMXTYVOLPARA2_FADE_FADEOUT); 771 772 regmap_write(r, AOUTFADECTR0, BIT(oport_map)); 773 } 774 775 /** 776 * aio_if_set_param - set parameters of AIO DMA I/F block 777 * @sub: the AIO substream pointer 778 * @pass_through: Zero if sound data is LPCM, otherwise if data is not LPCM. 779 * This parameter has no effect if substream is I2S or PCM. 780 * 781 * Set suitable setting to DMA interface block of AIO to process the 782 * specified in settings. 783 * 784 * Return: Zero if successful, otherwise a negative value on error. 785 */ 786 int aio_if_set_param(struct uniphier_aio_sub *sub, int pass_through) 787 { 788 struct regmap *r = sub->aio->chip->regmap; 789 u32 memfmt, v; 790 791 if (sub->swm->dir == PORT_DIR_OUTPUT) { 792 if (pass_through) { 793 v = PBOUTMXCTR0_ENDIAN_0123 | 794 PBOUTMXCTR0_MEMFMT_STREAM; 795 } else { 796 switch (params_channels(&sub->params)) { 797 case 2: 798 memfmt = PBOUTMXCTR0_MEMFMT_2CH; 799 break; 800 case 6: 801 memfmt = PBOUTMXCTR0_MEMFMT_6CH; 802 break; 803 case 8: 804 memfmt = PBOUTMXCTR0_MEMFMT_8CH; 805 break; 806 default: 807 return -EINVAL; 808 } 809 v = PBOUTMXCTR0_ENDIAN_3210 | memfmt; 810 } 811 812 regmap_write(r, PBOUTMXCTR0(sub->swm->oif.map), v); 813 regmap_write(r, PBOUTMXCTR1(sub->swm->oif.map), 0); 814 } else { 815 regmap_write(r, PBINMXCTR(sub->swm->iif.map), 816 PBINMXCTR_NCONNECT_CONNECT | 817 PBINMXCTR_INOUTSEL_IN | 818 (sub->swm->iport.map << PBINMXCTR_PBINSEL_SHIFT) | 819 PBINMXCTR_ENDIAN_3210 | 820 PBINMXCTR_MEMFMT_D0); 821 } 822 823 return 0; 824 } 825 826 /** 827 * aio_oport_set_stream_type - set parameters of AIO playback port block 828 * @sub: the AIO substream pointer 829 * @pc: Pc type of IEC61937 830 * 831 * Set special setting to output port block of AIO to output the stream 832 * via S/PDIF. 833 * 834 * Return: Zero if successful, otherwise a negative value on error. 835 */ 836 int aio_oport_set_stream_type(struct uniphier_aio_sub *sub, 837 enum IEC61937_PC pc) 838 { 839 struct regmap *r = sub->aio->chip->regmap; 840 u32 repet = 0, pause = OPORTMXPAUDAT_PAUSEPC_CMN; 841 842 switch (pc) { 843 case IEC61937_PC_AC3: 844 repet = OPORTMXREPET_STRLENGTH_AC3 | 845 OPORTMXREPET_PMLENGTH_AC3; 846 pause |= OPORTMXPAUDAT_PAUSEPD_AC3; 847 break; 848 case IEC61937_PC_MPA: 849 repet = OPORTMXREPET_STRLENGTH_MPA | 850 OPORTMXREPET_PMLENGTH_MPA; 851 pause |= OPORTMXPAUDAT_PAUSEPD_MPA; 852 break; 853 case IEC61937_PC_MP3: 854 repet = OPORTMXREPET_STRLENGTH_MP3 | 855 OPORTMXREPET_PMLENGTH_MP3; 856 pause |= OPORTMXPAUDAT_PAUSEPD_MP3; 857 break; 858 case IEC61937_PC_DTS1: 859 repet = OPORTMXREPET_STRLENGTH_DTS1 | 860 OPORTMXREPET_PMLENGTH_DTS1; 861 pause |= OPORTMXPAUDAT_PAUSEPD_DTS1; 862 break; 863 case IEC61937_PC_DTS2: 864 repet = OPORTMXREPET_STRLENGTH_DTS2 | 865 OPORTMXREPET_PMLENGTH_DTS2; 866 pause |= OPORTMXPAUDAT_PAUSEPD_DTS2; 867 break; 868 case IEC61937_PC_DTS3: 869 repet = OPORTMXREPET_STRLENGTH_DTS3 | 870 OPORTMXREPET_PMLENGTH_DTS3; 871 pause |= OPORTMXPAUDAT_PAUSEPD_DTS3; 872 break; 873 case IEC61937_PC_AAC: 874 repet = OPORTMXREPET_STRLENGTH_AAC | 875 OPORTMXREPET_PMLENGTH_AAC; 876 pause |= OPORTMXPAUDAT_PAUSEPD_AAC; 877 break; 878 case IEC61937_PC_PAUSE: 879 /* Do nothing */ 880 break; 881 } 882 883 regmap_write(r, OPORTMXREPET(sub->swm->oport.map), repet); 884 regmap_write(r, OPORTMXPAUDAT(sub->swm->oport.map), pause); 885 886 return 0; 887 } 888 889 /** 890 * aio_src_reset - reset AIO SRC block 891 * @sub: the AIO substream pointer 892 * 893 * Resets the digital signal input/output port with sampling rate converter 894 * block of AIO. 895 * This function has no effect if substream is not supported rate converter. 896 */ 897 void aio_src_reset(struct uniphier_aio_sub *sub) 898 { 899 struct regmap *r = sub->aio->chip->regmap; 900 901 if (sub->swm->dir != PORT_DIR_OUTPUT) 902 return; 903 904 regmap_write(r, AOUTSRCRSTCTR0, BIT(sub->swm->oport.map)); 905 regmap_write(r, AOUTSRCRSTCTR1, BIT(sub->swm->oport.map)); 906 } 907 908 /** 909 * aio_src_set_param - set parameters of AIO SRC block 910 * @sub: the AIO substream pointer 911 * @params: hardware parameters of ALSA 912 * 913 * Set suitable setting to input/output port with sampling rate converter 914 * block of AIO to process the specified in params. 915 * This function has no effect if substream is not supported rate converter. 916 * 917 * Return: Zero if successful, otherwise a negative value on error. 918 */ 919 int aio_src_set_param(struct uniphier_aio_sub *sub, 920 const struct snd_pcm_hw_params *params) 921 { 922 struct regmap *r = sub->aio->chip->regmap; 923 u32 v; 924 925 if (sub->swm->dir != PORT_DIR_OUTPUT) 926 return 0; 927 928 regmap_write(r, OPORTMXSRC1CTR(sub->swm->oport.map), 929 OPORTMXSRC1CTR_THMODE_SRC | 930 OPORTMXSRC1CTR_SRCPATH_CALC | 931 OPORTMXSRC1CTR_SYNC_ASYNC | 932 OPORTMXSRC1CTR_FSIIPSEL_INNER | 933 OPORTMXSRC1CTR_FSISEL_ACLK); 934 935 switch (params_rate(params)) { 936 default: 937 case 48000: 938 v = OPORTMXRATE_I_ACLKSEL_APLLA1 | 939 OPORTMXRATE_I_MCKSEL_36 | 940 OPORTMXRATE_I_FSSEL_48; 941 break; 942 case 44100: 943 v = OPORTMXRATE_I_ACLKSEL_APLLA2 | 944 OPORTMXRATE_I_MCKSEL_33 | 945 OPORTMXRATE_I_FSSEL_44_1; 946 break; 947 case 32000: 948 v = OPORTMXRATE_I_ACLKSEL_APLLA1 | 949 OPORTMXRATE_I_MCKSEL_36 | 950 OPORTMXRATE_I_FSSEL_32; 951 break; 952 } 953 954 regmap_write(r, OPORTMXRATE_I(sub->swm->oport.map), 955 v | OPORTMXRATE_I_ACLKSRC_APLL | 956 OPORTMXRATE_I_LRCKSTP_STOP); 957 regmap_update_bits(r, OPORTMXRATE_I(sub->swm->oport.map), 958 OPORTMXRATE_I_LRCKSTP_MASK, 959 OPORTMXRATE_I_LRCKSTP_START); 960 961 return 0; 962 } 963 964 int aio_srcif_set_param(struct uniphier_aio_sub *sub) 965 { 966 struct regmap *r = sub->aio->chip->regmap; 967 968 regmap_write(r, PBINMXCTR(sub->swm->iif.map), 969 PBINMXCTR_NCONNECT_CONNECT | 970 PBINMXCTR_INOUTSEL_OUT | 971 (sub->swm->oport.map << PBINMXCTR_PBINSEL_SHIFT) | 972 PBINMXCTR_ENDIAN_3210 | 973 PBINMXCTR_MEMFMT_D0); 974 975 return 0; 976 } 977 978 int aio_srcch_set_param(struct uniphier_aio_sub *sub) 979 { 980 struct regmap *r = sub->aio->chip->regmap; 981 982 regmap_write(r, CDA2D_CHMXCTRL1(sub->swm->och.map), 983 CDA2D_CHMXCTRL1_INDSIZE_INFINITE); 984 985 regmap_write(r, CDA2D_CHMXSRCAMODE(sub->swm->och.map), 986 CDA2D_CHMXAMODE_ENDIAN_3210 | 987 CDA2D_CHMXAMODE_AUPDT_FIX | 988 CDA2D_CHMXAMODE_TYPE_NORMAL); 989 990 regmap_write(r, CDA2D_CHMXDSTAMODE(sub->swm->och.map), 991 CDA2D_CHMXAMODE_ENDIAN_3210 | 992 CDA2D_CHMXAMODE_AUPDT_INC | 993 CDA2D_CHMXAMODE_TYPE_RING | 994 (sub->swm->och.map << CDA2D_CHMXAMODE_RSSEL_SHIFT)); 995 996 return 0; 997 } 998 999 void aio_srcch_set_enable(struct uniphier_aio_sub *sub, int enable) 1000 { 1001 struct regmap *r = sub->aio->chip->regmap; 1002 u32 v; 1003 1004 if (enable) 1005 v = CDA2D_STRT0_STOP_START; 1006 else 1007 v = CDA2D_STRT0_STOP_STOP; 1008 1009 regmap_write(r, CDA2D_STRT0, 1010 v | BIT(sub->swm->och.map)); 1011 } 1012 1013 int aiodma_ch_set_param(struct uniphier_aio_sub *sub) 1014 { 1015 struct regmap *r = sub->aio->chip->regmap; 1016 u32 v; 1017 1018 regmap_write(r, CDA2D_CHMXCTRL1(sub->swm->ch.map), 1019 CDA2D_CHMXCTRL1_INDSIZE_INFINITE); 1020 1021 v = CDA2D_CHMXAMODE_ENDIAN_3210 | 1022 CDA2D_CHMXAMODE_AUPDT_INC | 1023 CDA2D_CHMXAMODE_TYPE_NORMAL | 1024 (sub->swm->rb.map << CDA2D_CHMXAMODE_RSSEL_SHIFT); 1025 if (sub->swm->dir == PORT_DIR_OUTPUT) 1026 regmap_write(r, CDA2D_CHMXSRCAMODE(sub->swm->ch.map), v); 1027 else 1028 regmap_write(r, CDA2D_CHMXDSTAMODE(sub->swm->ch.map), v); 1029 1030 return 0; 1031 } 1032 1033 void aiodma_ch_set_enable(struct uniphier_aio_sub *sub, int enable) 1034 { 1035 struct regmap *r = sub->aio->chip->regmap; 1036 1037 if (enable) { 1038 regmap_write(r, CDA2D_STRT0, 1039 CDA2D_STRT0_STOP_START | BIT(sub->swm->ch.map)); 1040 1041 regmap_update_bits(r, INTRBIM(0), 1042 BIT(sub->swm->rb.map), 1043 BIT(sub->swm->rb.map)); 1044 } else { 1045 regmap_write(r, CDA2D_STRT0, 1046 CDA2D_STRT0_STOP_STOP | BIT(sub->swm->ch.map)); 1047 1048 regmap_update_bits(r, INTRBIM(0), 1049 BIT(sub->swm->rb.map), 1050 0); 1051 } 1052 } 1053 1054 static u64 aiodma_rb_get_rp(struct uniphier_aio_sub *sub) 1055 { 1056 struct regmap *r = sub->aio->chip->regmap; 1057 u32 pos_u, pos_l; 1058 int i; 1059 1060 regmap_write(r, CDA2D_RDPTRLOAD, 1061 CDA2D_RDPTRLOAD_LSFLAG_STORE | BIT(sub->swm->rb.map)); 1062 /* Wait for setup */ 1063 for (i = 0; i < 6; i++) 1064 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &pos_l); 1065 1066 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &pos_l); 1067 regmap_read(r, CDA2D_RBMXRDPTRU(sub->swm->rb.map), &pos_u); 1068 pos_u = FIELD_GET(CDA2D_RBMXPTRU_PTRU_MASK, pos_u); 1069 1070 return ((u64)pos_u << 32) | pos_l; 1071 } 1072 1073 static void aiodma_rb_set_rp(struct uniphier_aio_sub *sub, u64 pos) 1074 { 1075 struct regmap *r = sub->aio->chip->regmap; 1076 u32 tmp; 1077 int i; 1078 1079 regmap_write(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), (u32)pos); 1080 regmap_write(r, CDA2D_RBMXRDPTRU(sub->swm->rb.map), (u32)(pos >> 32)); 1081 regmap_write(r, CDA2D_RDPTRLOAD, BIT(sub->swm->rb.map)); 1082 /* Wait for setup */ 1083 for (i = 0; i < 6; i++) 1084 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &tmp); 1085 } 1086 1087 static u64 aiodma_rb_get_wp(struct uniphier_aio_sub *sub) 1088 { 1089 struct regmap *r = sub->aio->chip->regmap; 1090 u32 pos_u, pos_l; 1091 int i; 1092 1093 regmap_write(r, CDA2D_WRPTRLOAD, 1094 CDA2D_WRPTRLOAD_LSFLAG_STORE | BIT(sub->swm->rb.map)); 1095 /* Wait for setup */ 1096 for (i = 0; i < 6; i++) 1097 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &pos_l); 1098 1099 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &pos_l); 1100 regmap_read(r, CDA2D_RBMXWRPTRU(sub->swm->rb.map), &pos_u); 1101 pos_u = FIELD_GET(CDA2D_RBMXPTRU_PTRU_MASK, pos_u); 1102 1103 return ((u64)pos_u << 32) | pos_l; 1104 } 1105 1106 static void aiodma_rb_set_wp(struct uniphier_aio_sub *sub, u64 pos) 1107 { 1108 struct regmap *r = sub->aio->chip->regmap; 1109 u32 tmp; 1110 int i; 1111 1112 regmap_write(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), 1113 lower_32_bits(pos)); 1114 regmap_write(r, CDA2D_RBMXWRPTRU(sub->swm->rb.map), 1115 upper_32_bits(pos)); 1116 regmap_write(r, CDA2D_WRPTRLOAD, BIT(sub->swm->rb.map)); 1117 /* Wait for setup */ 1118 for (i = 0; i < 6; i++) 1119 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &tmp); 1120 } 1121 1122 int aiodma_rb_set_threshold(struct uniphier_aio_sub *sub, u64 size, u32 th) 1123 { 1124 struct regmap *r = sub->aio->chip->regmap; 1125 1126 if (size <= th) 1127 return -EINVAL; 1128 1129 regmap_write(r, CDA2D_RBMXBTH(sub->swm->rb.map), th); 1130 regmap_write(r, CDA2D_RBMXRTH(sub->swm->rb.map), th); 1131 1132 return 0; 1133 } 1134 1135 int aiodma_rb_set_buffer(struct uniphier_aio_sub *sub, u64 start, u64 end, 1136 int period) 1137 { 1138 struct regmap *r = sub->aio->chip->regmap; 1139 u64 size = end - start; 1140 int ret; 1141 1142 if (end < start || period < 0) 1143 return -EINVAL; 1144 1145 regmap_write(r, CDA2D_RBMXCNFG(sub->swm->rb.map), 0); 1146 regmap_write(r, CDA2D_RBMXBGNADRS(sub->swm->rb.map), 1147 lower_32_bits(start)); 1148 regmap_write(r, CDA2D_RBMXBGNADRSU(sub->swm->rb.map), 1149 upper_32_bits(start)); 1150 regmap_write(r, CDA2D_RBMXENDADRS(sub->swm->rb.map), 1151 lower_32_bits(end)); 1152 regmap_write(r, CDA2D_RBMXENDADRSU(sub->swm->rb.map), 1153 upper_32_bits(end)); 1154 1155 regmap_write(r, CDA2D_RBADRSLOAD, BIT(sub->swm->rb.map)); 1156 1157 ret = aiodma_rb_set_threshold(sub, size, 2 * period); 1158 if (ret) 1159 return ret; 1160 1161 if (sub->swm->dir == PORT_DIR_OUTPUT) { 1162 aiodma_rb_set_rp(sub, start); 1163 aiodma_rb_set_wp(sub, end - period); 1164 1165 regmap_update_bits(r, CDA2D_RBMXIE(sub->swm->rb.map), 1166 CDA2D_RBMXIX_SPACE, 1167 CDA2D_RBMXIX_SPACE); 1168 } else { 1169 aiodma_rb_set_rp(sub, end - period); 1170 aiodma_rb_set_wp(sub, start); 1171 1172 regmap_update_bits(r, CDA2D_RBMXIE(sub->swm->rb.map), 1173 CDA2D_RBMXIX_REMAIN, 1174 CDA2D_RBMXIX_REMAIN); 1175 } 1176 1177 sub->threshold = 2 * period; 1178 sub->rd_offs = 0; 1179 sub->wr_offs = 0; 1180 sub->rd_org = 0; 1181 sub->wr_org = 0; 1182 sub->rd_total = 0; 1183 sub->wr_total = 0; 1184 1185 return 0; 1186 } 1187 1188 void aiodma_rb_sync(struct uniphier_aio_sub *sub, u64 start, u64 size, 1189 int period) 1190 { 1191 if (sub->swm->dir == PORT_DIR_OUTPUT) { 1192 sub->rd_offs = aiodma_rb_get_rp(sub) - start; 1193 1194 if (sub->use_mmap) { 1195 sub->threshold = 2 * period; 1196 aiodma_rb_set_threshold(sub, size, 2 * period); 1197 1198 sub->wr_offs = sub->rd_offs - period; 1199 if (sub->rd_offs < period) 1200 sub->wr_offs += size; 1201 } 1202 aiodma_rb_set_wp(sub, sub->wr_offs + start); 1203 } else { 1204 sub->wr_offs = aiodma_rb_get_wp(sub) - start; 1205 1206 if (sub->use_mmap) { 1207 sub->threshold = 2 * period; 1208 aiodma_rb_set_threshold(sub, size, 2 * period); 1209 1210 sub->rd_offs = sub->wr_offs - period; 1211 if (sub->wr_offs < period) 1212 sub->rd_offs += size; 1213 } 1214 aiodma_rb_set_rp(sub, sub->rd_offs + start); 1215 } 1216 1217 sub->rd_total += sub->rd_offs - sub->rd_org; 1218 if (sub->rd_offs < sub->rd_org) 1219 sub->rd_total += size; 1220 sub->wr_total += sub->wr_offs - sub->wr_org; 1221 if (sub->wr_offs < sub->wr_org) 1222 sub->wr_total += size; 1223 1224 sub->rd_org = sub->rd_offs; 1225 sub->wr_org = sub->wr_offs; 1226 } 1227 1228 bool aiodma_rb_is_irq(struct uniphier_aio_sub *sub) 1229 { 1230 struct regmap *r = sub->aio->chip->regmap; 1231 u32 ir; 1232 1233 regmap_read(r, CDA2D_RBMXIR(sub->swm->rb.map), &ir); 1234 1235 if (sub->swm->dir == PORT_DIR_OUTPUT) 1236 return !!(ir & CDA2D_RBMXIX_SPACE); 1237 else 1238 return !!(ir & CDA2D_RBMXIX_REMAIN); 1239 } 1240 1241 void aiodma_rb_clear_irq(struct uniphier_aio_sub *sub) 1242 { 1243 struct regmap *r = sub->aio->chip->regmap; 1244 1245 if (sub->swm->dir == PORT_DIR_OUTPUT) 1246 regmap_write(r, CDA2D_RBMXIR(sub->swm->rb.map), 1247 CDA2D_RBMXIX_SPACE); 1248 else 1249 regmap_write(r, CDA2D_RBMXIR(sub->swm->rb.map), 1250 CDA2D_RBMXIX_REMAIN); 1251 } 1252
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.