root/sound/soc/uniphier/aio-core.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rb_cnt
  2. rb_cnt_to_end
  3. rb_space
  4. rb_space_to_end
  5. aio_rb_cnt
  6. aio_rbt_cnt_to_end
  7. aio_rb_space
  8. aio_rb_space_to_end
  9. aio_iecout_set_enable
  10. aio_chip_set_pll
  11. aio_chip_init
  12. aio_init
  13. aio_port_reset
  14. aio_port_set_ch
  15. aio_port_set_rate
  16. aio_port_set_fmt
  17. aio_port_set_clk
  18. aio_port_set_param
  19. aio_port_set_enable
  20. aio_port_get_volume
  21. aio_port_set_volume
  22. aio_if_set_param
  23. aio_oport_set_stream_type
  24. aio_src_reset
  25. aio_src_set_param
  26. aio_srcif_set_param
  27. aio_srcch_set_param
  28. aio_srcch_set_enable
  29. aiodma_ch_set_param
  30. aiodma_ch_set_enable
  31. aiodma_rb_get_rp
  32. aiodma_rb_set_rp
  33. aiodma_rb_get_wp
  34. aiodma_rb_set_wp
  35. aiodma_rb_set_threshold
  36. aiodma_rb_set_buffer
  37. aiodma_rb_sync
  38. aiodma_rb_is_irq
  39. aiodma_rb_clear_irq

   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  * @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  */
 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  * @ch : count of channels
 271  *
 272  * Set suitable slot selecting to input/output port block of AIO.
 273  *
 274  * This function may return error if non-PCM substream.
 275  *
 276  * Return: Zero if successful, otherwise a negative value on error.
 277  */
 278 static int aio_port_set_ch(struct uniphier_aio_sub *sub)
 279 {
 280         struct regmap *r = sub->aio->chip->regmap;
 281         u32 slotsel_2ch[] = {
 282                 0, 0, 0, 0, 0,
 283         };
 284         u32 slotsel_multi[] = {
 285                 OPORTMXTYSLOTCTR_SLOTSEL_SLOT0,
 286                 OPORTMXTYSLOTCTR_SLOTSEL_SLOT1,
 287                 OPORTMXTYSLOTCTR_SLOTSEL_SLOT2,
 288                 OPORTMXTYSLOTCTR_SLOTSEL_SLOT3,
 289                 OPORTMXTYSLOTCTR_SLOTSEL_SLOT4,
 290         };
 291         u32 mode, *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         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         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 }

/* [<][>][^][v][top][bottom][index][help] */