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