aio-core.c (31817B)
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 19static 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 27static 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 35static 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 43static 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 53u64 aio_rb_cnt(struct uniphier_aio_sub *sub) 54{ 55 return rb_cnt(sub->wr_offs, sub->rd_offs, sub->compr_bytes); 56} 57 58u64 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 63u64 aio_rb_space(struct uniphier_aio_sub *sub) 64{ 65 return rb_space(sub->wr_offs, sub->rd_offs, sub->compr_bytes); 66} 67 68u64 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 */ 84void 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 */ 105int 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 */ 165void 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 */ 200int 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 */ 250void 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 */ 277static int aio_port_set_ch(struct uniphier_aio_sub *sub) 278{ 279 struct regmap *r = sub->aio->chip->regmap; 280 u32 slotsel_2ch[] = { 281 0, 0, 0, 0, 0, 282 }; 283 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, *slotsel; 291 int i; 292 293 switch (params_channels(&sub->params)) { 294 case 8: 295 case 6: 296 mode = OPORTMXTYSLOTCTR_MODE; 297 slotsel = slotsel_multi; 298 break; 299 case 2: 300 mode = 0; 301 slotsel = slotsel_2ch; 302 break; 303 default: 304 return -EINVAL; 305 } 306 307 for (i = 0; i < AUD_MAX_SLOTSEL; i++) { 308 regmap_update_bits(r, OPORTMXTYSLOTCTR(sub->swm->oport.map, i), 309 OPORTMXTYSLOTCTR_MODE, mode); 310 regmap_update_bits(r, OPORTMXTYSLOTCTR(sub->swm->oport.map, i), 311 OPORTMXTYSLOTCTR_SLOTSEL_MASK, slotsel[i]); 312 } 313 314 return 0; 315} 316 317/** 318 * aio_port_set_rate - set sampling rate of LPCM 319 * @sub: the AIO substream pointer, PCM substream only 320 * @rate: Sampling rate in Hz. 321 * 322 * Set suitable I2S format settings to input/output port block of AIO. 323 * Parameter is specified by hw_params(). 324 * 325 * This function may return error if non-PCM substream. 326 * 327 * Return: Zero if successful, otherwise a negative value on error. 328 */ 329static int aio_port_set_rate(struct uniphier_aio_sub *sub, int rate) 330{ 331 struct regmap *r = sub->aio->chip->regmap; 332 struct device *dev = &sub->aio->chip->pdev->dev; 333 u32 v; 334 335 if (sub->swm->dir == PORT_DIR_OUTPUT) { 336 switch (rate) { 337 case 8000: 338 v = OPORTMXCTR1_FSSEL_8; 339 break; 340 case 11025: 341 v = OPORTMXCTR1_FSSEL_11_025; 342 break; 343 case 12000: 344 v = OPORTMXCTR1_FSSEL_12; 345 break; 346 case 16000: 347 v = OPORTMXCTR1_FSSEL_16; 348 break; 349 case 22050: 350 v = OPORTMXCTR1_FSSEL_22_05; 351 break; 352 case 24000: 353 v = OPORTMXCTR1_FSSEL_24; 354 break; 355 case 32000: 356 v = OPORTMXCTR1_FSSEL_32; 357 break; 358 case 44100: 359 v = OPORTMXCTR1_FSSEL_44_1; 360 break; 361 case 48000: 362 v = OPORTMXCTR1_FSSEL_48; 363 break; 364 case 88200: 365 v = OPORTMXCTR1_FSSEL_88_2; 366 break; 367 case 96000: 368 v = OPORTMXCTR1_FSSEL_96; 369 break; 370 case 176400: 371 v = OPORTMXCTR1_FSSEL_176_4; 372 break; 373 case 192000: 374 v = OPORTMXCTR1_FSSEL_192; 375 break; 376 default: 377 dev_err(dev, "Rate not supported(%d)\n", rate); 378 return -EINVAL; 379 } 380 381 regmap_update_bits(r, OPORTMXCTR1(sub->swm->oport.map), 382 OPORTMXCTR1_FSSEL_MASK, v); 383 } else { 384 switch (rate) { 385 case 8000: 386 v = IPORTMXCTR1_FSSEL_8; 387 break; 388 case 11025: 389 v = IPORTMXCTR1_FSSEL_11_025; 390 break; 391 case 12000: 392 v = IPORTMXCTR1_FSSEL_12; 393 break; 394 case 16000: 395 v = IPORTMXCTR1_FSSEL_16; 396 break; 397 case 22050: 398 v = IPORTMXCTR1_FSSEL_22_05; 399 break; 400 case 24000: 401 v = IPORTMXCTR1_FSSEL_24; 402 break; 403 case 32000: 404 v = IPORTMXCTR1_FSSEL_32; 405 break; 406 case 44100: 407 v = IPORTMXCTR1_FSSEL_44_1; 408 break; 409 case 48000: 410 v = IPORTMXCTR1_FSSEL_48; 411 break; 412 case 88200: 413 v = IPORTMXCTR1_FSSEL_88_2; 414 break; 415 case 96000: 416 v = IPORTMXCTR1_FSSEL_96; 417 break; 418 case 176400: 419 v = IPORTMXCTR1_FSSEL_176_4; 420 break; 421 case 192000: 422 v = IPORTMXCTR1_FSSEL_192; 423 break; 424 default: 425 dev_err(dev, "Rate not supported(%d)\n", rate); 426 return -EINVAL; 427 } 428 429 regmap_update_bits(r, IPORTMXCTR1(sub->swm->iport.map), 430 IPORTMXCTR1_FSSEL_MASK, v); 431 } 432 433 return 0; 434} 435 436/** 437 * aio_port_set_fmt - set format of I2S data 438 * @sub: the AIO substream pointer, PCM substream only 439 * This parameter has no effect if substream is I2S or PCM. 440 * 441 * Set suitable I2S format settings to input/output port block of AIO. 442 * Parameter is specified by set_fmt(). 443 * 444 * This function may return error if non-PCM substream. 445 * 446 * Return: Zero if successful, otherwise a negative value on error. 447 */ 448static int aio_port_set_fmt(struct uniphier_aio_sub *sub) 449{ 450 struct regmap *r = sub->aio->chip->regmap; 451 struct device *dev = &sub->aio->chip->pdev->dev; 452 u32 v; 453 454 if (sub->swm->dir == PORT_DIR_OUTPUT) { 455 switch (sub->aio->fmt) { 456 case SND_SOC_DAIFMT_LEFT_J: 457 v = OPORTMXCTR1_I2SLRSEL_LEFT; 458 break; 459 case SND_SOC_DAIFMT_RIGHT_J: 460 v = OPORTMXCTR1_I2SLRSEL_RIGHT; 461 break; 462 case SND_SOC_DAIFMT_I2S: 463 v = OPORTMXCTR1_I2SLRSEL_I2S; 464 break; 465 default: 466 dev_err(dev, "Format is not supported(%d)\n", 467 sub->aio->fmt); 468 return -EINVAL; 469 } 470 471 v |= OPORTMXCTR1_OUTBITSEL_24; 472 regmap_update_bits(r, OPORTMXCTR1(sub->swm->oport.map), 473 OPORTMXCTR1_I2SLRSEL_MASK | 474 OPORTMXCTR1_OUTBITSEL_MASK, v); 475 } else { 476 switch (sub->aio->fmt) { 477 case SND_SOC_DAIFMT_LEFT_J: 478 v = IPORTMXCTR1_LRSEL_LEFT; 479 break; 480 case SND_SOC_DAIFMT_RIGHT_J: 481 v = IPORTMXCTR1_LRSEL_RIGHT; 482 break; 483 case SND_SOC_DAIFMT_I2S: 484 v = IPORTMXCTR1_LRSEL_I2S; 485 break; 486 default: 487 dev_err(dev, "Format is not supported(%d)\n", 488 sub->aio->fmt); 489 return -EINVAL; 490 } 491 492 v |= IPORTMXCTR1_OUTBITSEL_24 | 493 IPORTMXCTR1_CHSEL_ALL; 494 regmap_update_bits(r, IPORTMXCTR1(sub->swm->iport.map), 495 IPORTMXCTR1_LRSEL_MASK | 496 IPORTMXCTR1_OUTBITSEL_MASK | 497 IPORTMXCTR1_CHSEL_MASK, v); 498 } 499 500 return 0; 501} 502 503/** 504 * aio_port_set_clk - set clock and divider of AIO port block 505 * @sub: the AIO substream pointer 506 * 507 * Set suitable PLL clock divider and relational settings to 508 * input/output port block of AIO. Parameters are specified by 509 * set_sysclk() and set_pll(). 510 * 511 * Return: Zero if successful, otherwise a negative value on error. 512 */ 513static int aio_port_set_clk(struct uniphier_aio_sub *sub) 514{ 515 struct uniphier_aio_chip *chip = sub->aio->chip; 516 struct device *dev = &sub->aio->chip->pdev->dev; 517 struct regmap *r = sub->aio->chip->regmap; 518 u32 v_pll[] = { 519 OPORTMXCTR2_ACLKSEL_A1, OPORTMXCTR2_ACLKSEL_F1, 520 OPORTMXCTR2_ACLKSEL_A2, OPORTMXCTR2_ACLKSEL_F2, 521 OPORTMXCTR2_ACLKSEL_A2PLL, 522 OPORTMXCTR2_ACLKSEL_RX1, 523 }; 524 u32 v_div[] = { 525 OPORTMXCTR2_DACCKSEL_1_2, OPORTMXCTR2_DACCKSEL_1_3, 526 OPORTMXCTR2_DACCKSEL_1_1, OPORTMXCTR2_DACCKSEL_2_3, 527 }; 528 u32 v; 529 530 if (sub->swm->dir == PORT_DIR_OUTPUT) { 531 if (sub->swm->type == PORT_TYPE_I2S) { 532 if (sub->aio->pll_out >= ARRAY_SIZE(v_pll)) { 533 dev_err(dev, "PLL(%d) is invalid\n", 534 sub->aio->pll_out); 535 return -EINVAL; 536 } 537 if (sub->aio->plldiv >= ARRAY_SIZE(v_div)) { 538 dev_err(dev, "PLL divider(%d) is invalid\n", 539 sub->aio->plldiv); 540 return -EINVAL; 541 } 542 543 v = v_pll[sub->aio->pll_out] | 544 OPORTMXCTR2_MSSEL_MASTER | 545 v_div[sub->aio->plldiv]; 546 547 switch (chip->plls[sub->aio->pll_out].freq) { 548 case 0: 549 case 36864000: 550 case 33868800: 551 v |= OPORTMXCTR2_EXTLSIFSSEL_36; 552 break; 553 default: 554 v |= OPORTMXCTR2_EXTLSIFSSEL_24; 555 break; 556 } 557 } else if (sub->swm->type == PORT_TYPE_EVE) { 558 v = OPORTMXCTR2_ACLKSEL_A2PLL | 559 OPORTMXCTR2_MSSEL_MASTER | 560 OPORTMXCTR2_EXTLSIFSSEL_36 | 561 OPORTMXCTR2_DACCKSEL_1_2; 562 } else if (sub->swm->type == PORT_TYPE_SPDIF) { 563 if (sub->aio->pll_out >= ARRAY_SIZE(v_pll)) { 564 dev_err(dev, "PLL(%d) is invalid\n", 565 sub->aio->pll_out); 566 return -EINVAL; 567 } 568 v = v_pll[sub->aio->pll_out] | 569 OPORTMXCTR2_MSSEL_MASTER | 570 OPORTMXCTR2_DACCKSEL_1_2; 571 572 switch (chip->plls[sub->aio->pll_out].freq) { 573 case 0: 574 case 36864000: 575 case 33868800: 576 v |= OPORTMXCTR2_EXTLSIFSSEL_36; 577 break; 578 default: 579 v |= OPORTMXCTR2_EXTLSIFSSEL_24; 580 break; 581 } 582 } else { 583 v = OPORTMXCTR2_ACLKSEL_A1 | 584 OPORTMXCTR2_MSSEL_MASTER | 585 OPORTMXCTR2_EXTLSIFSSEL_36 | 586 OPORTMXCTR2_DACCKSEL_1_2; 587 } 588 regmap_write(r, OPORTMXCTR2(sub->swm->oport.map), v); 589 } else { 590 v = IPORTMXCTR2_ACLKSEL_A1 | 591 IPORTMXCTR2_MSSEL_SLAVE | 592 IPORTMXCTR2_EXTLSIFSSEL_36 | 593 IPORTMXCTR2_DACCKSEL_1_2; 594 regmap_write(r, IPORTMXCTR2(sub->swm->iport.map), v); 595 } 596 597 return 0; 598} 599 600/** 601 * aio_port_set_param - set parameters of AIO port block 602 * @sub: the AIO substream pointer 603 * @pass_through: Zero if sound data is LPCM, otherwise if data is not LPCM. 604 * This parameter has no effect if substream is I2S or PCM. 605 * @params: hardware parameters of ALSA 606 * 607 * Set suitable setting to input/output port block of AIO to process the 608 * specified in params. 609 * 610 * Return: Zero if successful, otherwise a negative value on error. 611 */ 612int aio_port_set_param(struct uniphier_aio_sub *sub, int pass_through, 613 const struct snd_pcm_hw_params *params) 614{ 615 struct regmap *r = sub->aio->chip->regmap; 616 unsigned int rate; 617 u32 v; 618 int ret; 619 620 if (!pass_through) { 621 if (sub->swm->type == PORT_TYPE_EVE || 622 sub->swm->type == PORT_TYPE_CONV) { 623 rate = 48000; 624 } else { 625 rate = params_rate(params); 626 } 627 628 ret = aio_port_set_ch(sub); 629 if (ret) 630 return ret; 631 632 ret = aio_port_set_rate(sub, rate); 633 if (ret) 634 return ret; 635 636 ret = aio_port_set_fmt(sub); 637 if (ret) 638 return ret; 639 } 640 641 ret = aio_port_set_clk(sub); 642 if (ret) 643 return ret; 644 645 if (sub->swm->dir == PORT_DIR_OUTPUT) { 646 if (pass_through) 647 v = OPORTMXCTR3_SRCSEL_STREAM | 648 OPORTMXCTR3_VALID_STREAM; 649 else 650 v = OPORTMXCTR3_SRCSEL_PCM | 651 OPORTMXCTR3_VALID_PCM; 652 653 v |= OPORTMXCTR3_IECTHUR_IECOUT | 654 OPORTMXCTR3_PMSEL_PAUSE | 655 OPORTMXCTR3_PMSW_MUTE_OFF; 656 regmap_write(r, OPORTMXCTR3(sub->swm->oport.map), v); 657 } else { 658 regmap_write(r, IPORTMXACLKSEL0EX(sub->swm->iport.map), 659 IPORTMXACLKSEL0EX_ACLKSEL0EX_INTERNAL); 660 regmap_write(r, IPORTMXEXNOE(sub->swm->iport.map), 661 IPORTMXEXNOE_PCMINOE_INPUT); 662 } 663 664 return 0; 665} 666 667/** 668 * aio_port_set_enable - start or stop of AIO port block 669 * @sub: the AIO substream pointer 670 * @enable: zero to stop the block, otherwise to start 671 * 672 * Start or stop the signal input/output port block of AIO. 673 */ 674void aio_port_set_enable(struct uniphier_aio_sub *sub, int enable) 675{ 676 struct regmap *r = sub->aio->chip->regmap; 677 678 if (sub->swm->dir == PORT_DIR_OUTPUT) { 679 regmap_write(r, OPORTMXPATH(sub->swm->oport.map), 680 sub->swm->oif.map); 681 682 regmap_update_bits(r, OPORTMXMASK(sub->swm->oport.map), 683 OPORTMXMASK_IUDXMSK_MASK | 684 OPORTMXMASK_IUXCKMSK_MASK | 685 OPORTMXMASK_DXMSK_MASK | 686 OPORTMXMASK_XCKMSK_MASK, 687 OPORTMXMASK_IUDXMSK_OFF | 688 OPORTMXMASK_IUXCKMSK_OFF | 689 OPORTMXMASK_DXMSK_OFF | 690 OPORTMXMASK_XCKMSK_OFF); 691 692 if (enable) 693 regmap_write(r, AOUTENCTR0, BIT(sub->swm->oport.map)); 694 else 695 regmap_write(r, AOUTENCTR1, BIT(sub->swm->oport.map)); 696 } else { 697 regmap_update_bits(r, IPORTMXMASK(sub->swm->iport.map), 698 IPORTMXMASK_IUXCKMSK_MASK | 699 IPORTMXMASK_XCKMSK_MASK, 700 IPORTMXMASK_IUXCKMSK_OFF | 701 IPORTMXMASK_XCKMSK_OFF); 702 703 if (enable) 704 regmap_update_bits(r, 705 IPORTMXCTR2(sub->swm->iport.map), 706 IPORTMXCTR2_REQEN_MASK, 707 IPORTMXCTR2_REQEN_ENABLE); 708 else 709 regmap_update_bits(r, 710 IPORTMXCTR2(sub->swm->iport.map), 711 IPORTMXCTR2_REQEN_MASK, 712 IPORTMXCTR2_REQEN_DISABLE); 713 } 714} 715 716/** 717 * aio_port_get_volume - get volume of AIO port block 718 * @sub: the AIO substream pointer 719 * 720 * Return: current volume, range is 0x0000 - 0xffff 721 */ 722int aio_port_get_volume(struct uniphier_aio_sub *sub) 723{ 724 struct regmap *r = sub->aio->chip->regmap; 725 u32 v; 726 727 regmap_read(r, OPORTMXTYVOLGAINSTATUS(sub->swm->oport.map, 0), &v); 728 729 return FIELD_GET(OPORTMXTYVOLGAINSTATUS_CUR_MASK, v); 730} 731 732/** 733 * aio_port_set_volume - set volume of AIO port block 734 * @sub: the AIO substream pointer 735 * @vol: target volume, range is 0x0000 - 0xffff. 736 * 737 * Change digital volume and perfome fade-out/fade-in effect for specified 738 * output slot of port. Gained PCM value can calculate as the following: 739 * Gained = Original * vol / 0x4000 740 */ 741void aio_port_set_volume(struct uniphier_aio_sub *sub, int vol) 742{ 743 struct regmap *r = sub->aio->chip->regmap; 744 int oport_map = sub->swm->oport.map; 745 int cur, diff, slope = 0, fs; 746 747 if (sub->swm->dir == PORT_DIR_INPUT) 748 return; 749 750 cur = aio_port_get_volume(sub); 751 diff = abs(vol - cur); 752 fs = params_rate(&sub->params); 753 if (fs) 754 slope = diff / AUD_VOL_FADE_TIME * 1000 / fs; 755 slope = max(1, slope); 756 757 regmap_update_bits(r, OPORTMXTYVOLPARA1(oport_map, 0), 758 OPORTMXTYVOLPARA1_SLOPEU_MASK, slope << 16); 759 regmap_update_bits(r, OPORTMXTYVOLPARA2(oport_map, 0), 760 OPORTMXTYVOLPARA2_TARGET_MASK, vol); 761 762 if (cur < vol) 763 regmap_update_bits(r, OPORTMXTYVOLPARA2(oport_map, 0), 764 OPORTMXTYVOLPARA2_FADE_MASK, 765 OPORTMXTYVOLPARA2_FADE_FADEIN); 766 else 767 regmap_update_bits(r, OPORTMXTYVOLPARA2(oport_map, 0), 768 OPORTMXTYVOLPARA2_FADE_MASK, 769 OPORTMXTYVOLPARA2_FADE_FADEOUT); 770 771 regmap_write(r, AOUTFADECTR0, BIT(oport_map)); 772} 773 774/** 775 * aio_if_set_param - set parameters of AIO DMA I/F block 776 * @sub: the AIO substream pointer 777 * @pass_through: Zero if sound data is LPCM, otherwise if data is not LPCM. 778 * This parameter has no effect if substream is I2S or PCM. 779 * 780 * Set suitable setting to DMA interface block of AIO to process the 781 * specified in settings. 782 * 783 * Return: Zero if successful, otherwise a negative value on error. 784 */ 785int aio_if_set_param(struct uniphier_aio_sub *sub, int pass_through) 786{ 787 struct regmap *r = sub->aio->chip->regmap; 788 u32 memfmt, v; 789 790 if (sub->swm->dir == PORT_DIR_OUTPUT) { 791 if (pass_through) { 792 v = PBOUTMXCTR0_ENDIAN_0123 | 793 PBOUTMXCTR0_MEMFMT_STREAM; 794 } else { 795 switch (params_channels(&sub->params)) { 796 case 2: 797 memfmt = PBOUTMXCTR0_MEMFMT_2CH; 798 break; 799 case 6: 800 memfmt = PBOUTMXCTR0_MEMFMT_6CH; 801 break; 802 case 8: 803 memfmt = PBOUTMXCTR0_MEMFMT_8CH; 804 break; 805 default: 806 return -EINVAL; 807 } 808 v = PBOUTMXCTR0_ENDIAN_3210 | memfmt; 809 } 810 811 regmap_write(r, PBOUTMXCTR0(sub->swm->oif.map), v); 812 regmap_write(r, PBOUTMXCTR1(sub->swm->oif.map), 0); 813 } else { 814 regmap_write(r, PBINMXCTR(sub->swm->iif.map), 815 PBINMXCTR_NCONNECT_CONNECT | 816 PBINMXCTR_INOUTSEL_IN | 817 (sub->swm->iport.map << PBINMXCTR_PBINSEL_SHIFT) | 818 PBINMXCTR_ENDIAN_3210 | 819 PBINMXCTR_MEMFMT_D0); 820 } 821 822 return 0; 823} 824 825/** 826 * aio_oport_set_stream_type - set parameters of AIO playback port block 827 * @sub: the AIO substream pointer 828 * @pc: Pc type of IEC61937 829 * 830 * Set special setting to output port block of AIO to output the stream 831 * via S/PDIF. 832 * 833 * Return: Zero if successful, otherwise a negative value on error. 834 */ 835int aio_oport_set_stream_type(struct uniphier_aio_sub *sub, 836 enum IEC61937_PC pc) 837{ 838 struct regmap *r = sub->aio->chip->regmap; 839 u32 repet = 0, pause = OPORTMXPAUDAT_PAUSEPC_CMN; 840 841 switch (pc) { 842 case IEC61937_PC_AC3: 843 repet = OPORTMXREPET_STRLENGTH_AC3 | 844 OPORTMXREPET_PMLENGTH_AC3; 845 pause |= OPORTMXPAUDAT_PAUSEPD_AC3; 846 break; 847 case IEC61937_PC_MPA: 848 repet = OPORTMXREPET_STRLENGTH_MPA | 849 OPORTMXREPET_PMLENGTH_MPA; 850 pause |= OPORTMXPAUDAT_PAUSEPD_MPA; 851 break; 852 case IEC61937_PC_MP3: 853 repet = OPORTMXREPET_STRLENGTH_MP3 | 854 OPORTMXREPET_PMLENGTH_MP3; 855 pause |= OPORTMXPAUDAT_PAUSEPD_MP3; 856 break; 857 case IEC61937_PC_DTS1: 858 repet = OPORTMXREPET_STRLENGTH_DTS1 | 859 OPORTMXREPET_PMLENGTH_DTS1; 860 pause |= OPORTMXPAUDAT_PAUSEPD_DTS1; 861 break; 862 case IEC61937_PC_DTS2: 863 repet = OPORTMXREPET_STRLENGTH_DTS2 | 864 OPORTMXREPET_PMLENGTH_DTS2; 865 pause |= OPORTMXPAUDAT_PAUSEPD_DTS2; 866 break; 867 case IEC61937_PC_DTS3: 868 repet = OPORTMXREPET_STRLENGTH_DTS3 | 869 OPORTMXREPET_PMLENGTH_DTS3; 870 pause |= OPORTMXPAUDAT_PAUSEPD_DTS3; 871 break; 872 case IEC61937_PC_AAC: 873 repet = OPORTMXREPET_STRLENGTH_AAC | 874 OPORTMXREPET_PMLENGTH_AAC; 875 pause |= OPORTMXPAUDAT_PAUSEPD_AAC; 876 break; 877 case IEC61937_PC_PAUSE: 878 /* Do nothing */ 879 break; 880 } 881 882 regmap_write(r, OPORTMXREPET(sub->swm->oport.map), repet); 883 regmap_write(r, OPORTMXPAUDAT(sub->swm->oport.map), pause); 884 885 return 0; 886} 887 888/** 889 * aio_src_reset - reset AIO SRC block 890 * @sub: the AIO substream pointer 891 * 892 * Resets the digital signal input/output port with sampling rate converter 893 * block of AIO. 894 * This function has no effect if substream is not supported rate converter. 895 */ 896void aio_src_reset(struct uniphier_aio_sub *sub) 897{ 898 struct regmap *r = sub->aio->chip->regmap; 899 900 if (sub->swm->dir != PORT_DIR_OUTPUT) 901 return; 902 903 regmap_write(r, AOUTSRCRSTCTR0, BIT(sub->swm->oport.map)); 904 regmap_write(r, AOUTSRCRSTCTR1, BIT(sub->swm->oport.map)); 905} 906 907/** 908 * aio_src_set_param - set parameters of AIO SRC block 909 * @sub: the AIO substream pointer 910 * @params: hardware parameters of ALSA 911 * 912 * Set suitable setting to input/output port with sampling rate converter 913 * block of AIO to process the specified in params. 914 * This function has no effect if substream is not supported rate converter. 915 * 916 * Return: Zero if successful, otherwise a negative value on error. 917 */ 918int aio_src_set_param(struct uniphier_aio_sub *sub, 919 const struct snd_pcm_hw_params *params) 920{ 921 struct regmap *r = sub->aio->chip->regmap; 922 u32 v; 923 924 if (sub->swm->dir != PORT_DIR_OUTPUT) 925 return 0; 926 927 regmap_write(r, OPORTMXSRC1CTR(sub->swm->oport.map), 928 OPORTMXSRC1CTR_THMODE_SRC | 929 OPORTMXSRC1CTR_SRCPATH_CALC | 930 OPORTMXSRC1CTR_SYNC_ASYNC | 931 OPORTMXSRC1CTR_FSIIPSEL_INNER | 932 OPORTMXSRC1CTR_FSISEL_ACLK); 933 934 switch (params_rate(params)) { 935 default: 936 case 48000: 937 v = OPORTMXRATE_I_ACLKSEL_APLLA1 | 938 OPORTMXRATE_I_MCKSEL_36 | 939 OPORTMXRATE_I_FSSEL_48; 940 break; 941 case 44100: 942 v = OPORTMXRATE_I_ACLKSEL_APLLA2 | 943 OPORTMXRATE_I_MCKSEL_33 | 944 OPORTMXRATE_I_FSSEL_44_1; 945 break; 946 case 32000: 947 v = OPORTMXRATE_I_ACLKSEL_APLLA1 | 948 OPORTMXRATE_I_MCKSEL_36 | 949 OPORTMXRATE_I_FSSEL_32; 950 break; 951 } 952 953 regmap_write(r, OPORTMXRATE_I(sub->swm->oport.map), 954 v | OPORTMXRATE_I_ACLKSRC_APLL | 955 OPORTMXRATE_I_LRCKSTP_STOP); 956 regmap_update_bits(r, OPORTMXRATE_I(sub->swm->oport.map), 957 OPORTMXRATE_I_LRCKSTP_MASK, 958 OPORTMXRATE_I_LRCKSTP_START); 959 960 return 0; 961} 962 963int aio_srcif_set_param(struct uniphier_aio_sub *sub) 964{ 965 struct regmap *r = sub->aio->chip->regmap; 966 967 regmap_write(r, PBINMXCTR(sub->swm->iif.map), 968 PBINMXCTR_NCONNECT_CONNECT | 969 PBINMXCTR_INOUTSEL_OUT | 970 (sub->swm->oport.map << PBINMXCTR_PBINSEL_SHIFT) | 971 PBINMXCTR_ENDIAN_3210 | 972 PBINMXCTR_MEMFMT_D0); 973 974 return 0; 975} 976 977int aio_srcch_set_param(struct uniphier_aio_sub *sub) 978{ 979 struct regmap *r = sub->aio->chip->regmap; 980 981 regmap_write(r, CDA2D_CHMXCTRL1(sub->swm->och.map), 982 CDA2D_CHMXCTRL1_INDSIZE_INFINITE); 983 984 regmap_write(r, CDA2D_CHMXSRCAMODE(sub->swm->och.map), 985 CDA2D_CHMXAMODE_ENDIAN_3210 | 986 CDA2D_CHMXAMODE_AUPDT_FIX | 987 CDA2D_CHMXAMODE_TYPE_NORMAL); 988 989 regmap_write(r, CDA2D_CHMXDSTAMODE(sub->swm->och.map), 990 CDA2D_CHMXAMODE_ENDIAN_3210 | 991 CDA2D_CHMXAMODE_AUPDT_INC | 992 CDA2D_CHMXAMODE_TYPE_RING | 993 (sub->swm->och.map << CDA2D_CHMXAMODE_RSSEL_SHIFT)); 994 995 return 0; 996} 997 998void aio_srcch_set_enable(struct uniphier_aio_sub *sub, int enable) 999{ 1000 struct regmap *r = sub->aio->chip->regmap; 1001 u32 v; 1002 1003 if (enable) 1004 v = CDA2D_STRT0_STOP_START; 1005 else 1006 v = CDA2D_STRT0_STOP_STOP; 1007 1008 regmap_write(r, CDA2D_STRT0, 1009 v | BIT(sub->swm->och.map)); 1010} 1011 1012int aiodma_ch_set_param(struct uniphier_aio_sub *sub) 1013{ 1014 struct regmap *r = sub->aio->chip->regmap; 1015 u32 v; 1016 1017 regmap_write(r, CDA2D_CHMXCTRL1(sub->swm->ch.map), 1018 CDA2D_CHMXCTRL1_INDSIZE_INFINITE); 1019 1020 v = CDA2D_CHMXAMODE_ENDIAN_3210 | 1021 CDA2D_CHMXAMODE_AUPDT_INC | 1022 CDA2D_CHMXAMODE_TYPE_NORMAL | 1023 (sub->swm->rb.map << CDA2D_CHMXAMODE_RSSEL_SHIFT); 1024 if (sub->swm->dir == PORT_DIR_OUTPUT) 1025 regmap_write(r, CDA2D_CHMXSRCAMODE(sub->swm->ch.map), v); 1026 else 1027 regmap_write(r, CDA2D_CHMXDSTAMODE(sub->swm->ch.map), v); 1028 1029 return 0; 1030} 1031 1032void aiodma_ch_set_enable(struct uniphier_aio_sub *sub, int enable) 1033{ 1034 struct regmap *r = sub->aio->chip->regmap; 1035 1036 if (enable) { 1037 regmap_write(r, CDA2D_STRT0, 1038 CDA2D_STRT0_STOP_START | BIT(sub->swm->ch.map)); 1039 1040 regmap_update_bits(r, INTRBIM(0), 1041 BIT(sub->swm->rb.map), 1042 BIT(sub->swm->rb.map)); 1043 } else { 1044 regmap_write(r, CDA2D_STRT0, 1045 CDA2D_STRT0_STOP_STOP | BIT(sub->swm->ch.map)); 1046 1047 regmap_update_bits(r, INTRBIM(0), 1048 BIT(sub->swm->rb.map), 1049 0); 1050 } 1051} 1052 1053static u64 aiodma_rb_get_rp(struct uniphier_aio_sub *sub) 1054{ 1055 struct regmap *r = sub->aio->chip->regmap; 1056 u32 pos_u, pos_l; 1057 int i; 1058 1059 regmap_write(r, CDA2D_RDPTRLOAD, 1060 CDA2D_RDPTRLOAD_LSFLAG_STORE | BIT(sub->swm->rb.map)); 1061 /* Wait for setup */ 1062 for (i = 0; i < 6; i++) 1063 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &pos_l); 1064 1065 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &pos_l); 1066 regmap_read(r, CDA2D_RBMXRDPTRU(sub->swm->rb.map), &pos_u); 1067 pos_u = FIELD_GET(CDA2D_RBMXPTRU_PTRU_MASK, pos_u); 1068 1069 return ((u64)pos_u << 32) | pos_l; 1070} 1071 1072static void aiodma_rb_set_rp(struct uniphier_aio_sub *sub, u64 pos) 1073{ 1074 struct regmap *r = sub->aio->chip->regmap; 1075 u32 tmp; 1076 int i; 1077 1078 regmap_write(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), (u32)pos); 1079 regmap_write(r, CDA2D_RBMXRDPTRU(sub->swm->rb.map), (u32)(pos >> 32)); 1080 regmap_write(r, CDA2D_RDPTRLOAD, BIT(sub->swm->rb.map)); 1081 /* Wait for setup */ 1082 for (i = 0; i < 6; i++) 1083 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &tmp); 1084} 1085 1086static u64 aiodma_rb_get_wp(struct uniphier_aio_sub *sub) 1087{ 1088 struct regmap *r = sub->aio->chip->regmap; 1089 u32 pos_u, pos_l; 1090 int i; 1091 1092 regmap_write(r, CDA2D_WRPTRLOAD, 1093 CDA2D_WRPTRLOAD_LSFLAG_STORE | BIT(sub->swm->rb.map)); 1094 /* Wait for setup */ 1095 for (i = 0; i < 6; i++) 1096 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &pos_l); 1097 1098 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &pos_l); 1099 regmap_read(r, CDA2D_RBMXWRPTRU(sub->swm->rb.map), &pos_u); 1100 pos_u = FIELD_GET(CDA2D_RBMXPTRU_PTRU_MASK, pos_u); 1101 1102 return ((u64)pos_u << 32) | pos_l; 1103} 1104 1105static void aiodma_rb_set_wp(struct uniphier_aio_sub *sub, u64 pos) 1106{ 1107 struct regmap *r = sub->aio->chip->regmap; 1108 u32 tmp; 1109 int i; 1110 1111 regmap_write(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), 1112 lower_32_bits(pos)); 1113 regmap_write(r, CDA2D_RBMXWRPTRU(sub->swm->rb.map), 1114 upper_32_bits(pos)); 1115 regmap_write(r, CDA2D_WRPTRLOAD, BIT(sub->swm->rb.map)); 1116 /* Wait for setup */ 1117 for (i = 0; i < 6; i++) 1118 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &tmp); 1119} 1120 1121int aiodma_rb_set_threshold(struct uniphier_aio_sub *sub, u64 size, u32 th) 1122{ 1123 struct regmap *r = sub->aio->chip->regmap; 1124 1125 if (size <= th) 1126 return -EINVAL; 1127 1128 regmap_write(r, CDA2D_RBMXBTH(sub->swm->rb.map), th); 1129 regmap_write(r, CDA2D_RBMXRTH(sub->swm->rb.map), th); 1130 1131 return 0; 1132} 1133 1134int aiodma_rb_set_buffer(struct uniphier_aio_sub *sub, u64 start, u64 end, 1135 int period) 1136{ 1137 struct regmap *r = sub->aio->chip->regmap; 1138 u64 size = end - start; 1139 int ret; 1140 1141 if (end < start || period < 0) 1142 return -EINVAL; 1143 1144 regmap_write(r, CDA2D_RBMXCNFG(sub->swm->rb.map), 0); 1145 regmap_write(r, CDA2D_RBMXBGNADRS(sub->swm->rb.map), 1146 lower_32_bits(start)); 1147 regmap_write(r, CDA2D_RBMXBGNADRSU(sub->swm->rb.map), 1148 upper_32_bits(start)); 1149 regmap_write(r, CDA2D_RBMXENDADRS(sub->swm->rb.map), 1150 lower_32_bits(end)); 1151 regmap_write(r, CDA2D_RBMXENDADRSU(sub->swm->rb.map), 1152 upper_32_bits(end)); 1153 1154 regmap_write(r, CDA2D_RBADRSLOAD, BIT(sub->swm->rb.map)); 1155 1156 ret = aiodma_rb_set_threshold(sub, size, 2 * period); 1157 if (ret) 1158 return ret; 1159 1160 if (sub->swm->dir == PORT_DIR_OUTPUT) { 1161 aiodma_rb_set_rp(sub, start); 1162 aiodma_rb_set_wp(sub, end - period); 1163 1164 regmap_update_bits(r, CDA2D_RBMXIE(sub->swm->rb.map), 1165 CDA2D_RBMXIX_SPACE, 1166 CDA2D_RBMXIX_SPACE); 1167 } else { 1168 aiodma_rb_set_rp(sub, end - period); 1169 aiodma_rb_set_wp(sub, start); 1170 1171 regmap_update_bits(r, CDA2D_RBMXIE(sub->swm->rb.map), 1172 CDA2D_RBMXIX_REMAIN, 1173 CDA2D_RBMXIX_REMAIN); 1174 } 1175 1176 sub->threshold = 2 * period; 1177 sub->rd_offs = 0; 1178 sub->wr_offs = 0; 1179 sub->rd_org = 0; 1180 sub->wr_org = 0; 1181 sub->rd_total = 0; 1182 sub->wr_total = 0; 1183 1184 return 0; 1185} 1186 1187void aiodma_rb_sync(struct uniphier_aio_sub *sub, u64 start, u64 size, 1188 int period) 1189{ 1190 if (sub->swm->dir == PORT_DIR_OUTPUT) { 1191 sub->rd_offs = aiodma_rb_get_rp(sub) - start; 1192 1193 if (sub->use_mmap) { 1194 sub->threshold = 2 * period; 1195 aiodma_rb_set_threshold(sub, size, 2 * period); 1196 1197 sub->wr_offs = sub->rd_offs - period; 1198 if (sub->rd_offs < period) 1199 sub->wr_offs += size; 1200 } 1201 aiodma_rb_set_wp(sub, sub->wr_offs + start); 1202 } else { 1203 sub->wr_offs = aiodma_rb_get_wp(sub) - start; 1204 1205 if (sub->use_mmap) { 1206 sub->threshold = 2 * period; 1207 aiodma_rb_set_threshold(sub, size, 2 * period); 1208 1209 sub->rd_offs = sub->wr_offs - period; 1210 if (sub->wr_offs < period) 1211 sub->rd_offs += size; 1212 } 1213 aiodma_rb_set_rp(sub, sub->rd_offs + start); 1214 } 1215 1216 sub->rd_total += sub->rd_offs - sub->rd_org; 1217 if (sub->rd_offs < sub->rd_org) 1218 sub->rd_total += size; 1219 sub->wr_total += sub->wr_offs - sub->wr_org; 1220 if (sub->wr_offs < sub->wr_org) 1221 sub->wr_total += size; 1222 1223 sub->rd_org = sub->rd_offs; 1224 sub->wr_org = sub->wr_offs; 1225} 1226 1227bool aiodma_rb_is_irq(struct uniphier_aio_sub *sub) 1228{ 1229 struct regmap *r = sub->aio->chip->regmap; 1230 u32 ir; 1231 1232 regmap_read(r, CDA2D_RBMXIR(sub->swm->rb.map), &ir); 1233 1234 if (sub->swm->dir == PORT_DIR_OUTPUT) 1235 return !!(ir & CDA2D_RBMXIX_SPACE); 1236 else 1237 return !!(ir & CDA2D_RBMXIX_REMAIN); 1238} 1239 1240void aiodma_rb_clear_irq(struct uniphier_aio_sub *sub) 1241{ 1242 struct regmap *r = sub->aio->chip->regmap; 1243 1244 if (sub->swm->dir == PORT_DIR_OUTPUT) 1245 regmap_write(r, CDA2D_RBMXIR(sub->swm->rb.map), 1246 CDA2D_RBMXIX_SPACE); 1247 else 1248 regmap_write(r, CDA2D_RBMXIR(sub->swm->rb.map), 1249 CDA2D_RBMXIX_REMAIN); 1250}