0001
0002
0003
0004
0005
0006
0007 #include <linux/bitfield.h>
0008 #include <linux/errno.h>
0009 #include <linux/kernel.h>
0010 #include <linux/module.h>
0011 #include <sound/core.h>
0012 #include <sound/pcm.h>
0013 #include <sound/pcm_params.h>
0014 #include <sound/soc.h>
0015
0016 #include "aio.h"
0017 #include "aio-reg.h"
0018
0019 static u64 rb_cnt(u64 wr, u64 rd, u64 len)
0020 {
0021 if (rd <= wr)
0022 return wr - rd;
0023 else
0024 return len - (rd - wr);
0025 }
0026
0027 static u64 rb_cnt_to_end(u64 wr, u64 rd, u64 len)
0028 {
0029 if (rd <= wr)
0030 return wr - rd;
0031 else
0032 return len - rd;
0033 }
0034
0035 static u64 rb_space(u64 wr, u64 rd, u64 len)
0036 {
0037 if (rd <= wr)
0038 return len - (wr - rd) - 8;
0039 else
0040 return rd - wr - 8;
0041 }
0042
0043 static u64 rb_space_to_end(u64 wr, u64 rd, u64 len)
0044 {
0045 if (rd > wr)
0046 return rd - wr - 8;
0047 else if (rd > 0)
0048 return len - wr;
0049 else
0050 return len - wr - 8;
0051 }
0052
0053 u64 aio_rb_cnt(struct uniphier_aio_sub *sub)
0054 {
0055 return rb_cnt(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
0056 }
0057
0058 u64 aio_rbt_cnt_to_end(struct uniphier_aio_sub *sub)
0059 {
0060 return rb_cnt_to_end(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
0061 }
0062
0063 u64 aio_rb_space(struct uniphier_aio_sub *sub)
0064 {
0065 return rb_space(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
0066 }
0067
0068 u64 aio_rb_space_to_end(struct uniphier_aio_sub *sub)
0069 {
0070 return rb_space_to_end(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
0071 }
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084 void aio_iecout_set_enable(struct uniphier_aio_chip *chip, bool enable)
0085 {
0086 struct regmap *r = chip->regmap_sg;
0087
0088 if (!r)
0089 return;
0090
0091 regmap_write(r, SG_AOUTEN, (enable) ? ~0 : 0);
0092 }
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105 int aio_chip_set_pll(struct uniphier_aio_chip *chip, int pll_id,
0106 unsigned int freq)
0107 {
0108 struct device *dev = &chip->pdev->dev;
0109 struct regmap *r = chip->regmap;
0110 int shift;
0111 u32 v;
0112
0113
0114 if (freq == 0)
0115 return 0;
0116
0117 switch (pll_id) {
0118 case AUD_PLL_A1:
0119 shift = 0;
0120 break;
0121 case AUD_PLL_F1:
0122 shift = 1;
0123 break;
0124 case AUD_PLL_A2:
0125 shift = 2;
0126 break;
0127 case AUD_PLL_F2:
0128 shift = 3;
0129 break;
0130 default:
0131 dev_err(dev, "PLL(%d) not supported\n", pll_id);
0132 return -EINVAL;
0133 }
0134
0135 switch (freq) {
0136 case 36864000:
0137 v = A2APLLCTR1_APLLX_36MHZ;
0138 break;
0139 case 33868800:
0140 v = A2APLLCTR1_APLLX_33MHZ;
0141 break;
0142 default:
0143 dev_err(dev, "PLL frequency not supported(%d)\n", freq);
0144 return -EINVAL;
0145 }
0146 chip->plls[pll_id].freq = freq;
0147
0148 regmap_update_bits(r, A2APLLCTR1, A2APLLCTR1_APLLX_MASK << shift,
0149 v << shift);
0150
0151 return 0;
0152 }
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165 void aio_chip_init(struct uniphier_aio_chip *chip)
0166 {
0167 struct regmap *r = chip->regmap;
0168
0169 regmap_update_bits(r, A2APLLCTR0,
0170 A2APLLCTR0_APLLXPOW_MASK,
0171 A2APLLCTR0_APLLXPOW_PWON);
0172
0173 regmap_update_bits(r, A2EXMCLKSEL0,
0174 A2EXMCLKSEL0_EXMCLK_MASK,
0175 A2EXMCLKSEL0_EXMCLK_OUTPUT);
0176
0177 regmap_update_bits(r, A2AIOINPUTSEL, A2AIOINPUTSEL_RXSEL_MASK,
0178 A2AIOINPUTSEL_RXSEL_PCMI1_HDMIRX1 |
0179 A2AIOINPUTSEL_RXSEL_PCMI2_SIF |
0180 A2AIOINPUTSEL_RXSEL_PCMI3_EVEA |
0181 A2AIOINPUTSEL_RXSEL_IECI1_HDMIRX1);
0182
0183 if (chip->chip_spec->addr_ext)
0184 regmap_update_bits(r, CDA2D_TEST, CDA2D_TEST_DDR_MODE_MASK,
0185 CDA2D_TEST_DDR_MODE_EXTON0);
0186 else
0187 regmap_update_bits(r, CDA2D_TEST, CDA2D_TEST_DDR_MODE_MASK,
0188 CDA2D_TEST_DDR_MODE_EXTOFF1);
0189 }
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200 int aio_init(struct uniphier_aio_sub *sub)
0201 {
0202 struct device *dev = &sub->aio->chip->pdev->dev;
0203 struct regmap *r = sub->aio->chip->regmap;
0204
0205 regmap_write(r, A2RBNMAPCTR0(sub->swm->rb.hw),
0206 MAPCTR0_EN | sub->swm->rb.map);
0207 regmap_write(r, A2CHNMAPCTR0(sub->swm->ch.hw),
0208 MAPCTR0_EN | sub->swm->ch.map);
0209
0210 switch (sub->swm->type) {
0211 case PORT_TYPE_I2S:
0212 case PORT_TYPE_SPDIF:
0213 case PORT_TYPE_EVE:
0214 if (sub->swm->dir == PORT_DIR_INPUT) {
0215 regmap_write(r, A2IIFNMAPCTR0(sub->swm->iif.hw),
0216 MAPCTR0_EN | sub->swm->iif.map);
0217 regmap_write(r, A2IPORTNMAPCTR0(sub->swm->iport.hw),
0218 MAPCTR0_EN | sub->swm->iport.map);
0219 } else {
0220 regmap_write(r, A2OIFNMAPCTR0(sub->swm->oif.hw),
0221 MAPCTR0_EN | sub->swm->oif.map);
0222 regmap_write(r, A2OPORTNMAPCTR0(sub->swm->oport.hw),
0223 MAPCTR0_EN | sub->swm->oport.map);
0224 }
0225 break;
0226 case PORT_TYPE_CONV:
0227 regmap_write(r, A2OIFNMAPCTR0(sub->swm->oif.hw),
0228 MAPCTR0_EN | sub->swm->oif.map);
0229 regmap_write(r, A2OPORTNMAPCTR0(sub->swm->oport.hw),
0230 MAPCTR0_EN | sub->swm->oport.map);
0231 regmap_write(r, A2CHNMAPCTR0(sub->swm->och.hw),
0232 MAPCTR0_EN | sub->swm->och.map);
0233 regmap_write(r, A2IIFNMAPCTR0(sub->swm->iif.hw),
0234 MAPCTR0_EN | sub->swm->iif.map);
0235 break;
0236 default:
0237 dev_err(dev, "Unknown port type %d.\n", sub->swm->type);
0238 return -EINVAL;
0239 }
0240
0241 return 0;
0242 }
0243
0244
0245
0246
0247
0248
0249
0250 void aio_port_reset(struct uniphier_aio_sub *sub)
0251 {
0252 struct regmap *r = sub->aio->chip->regmap;
0253
0254 if (sub->swm->dir == PORT_DIR_OUTPUT) {
0255 regmap_write(r, AOUTRSTCTR0, BIT(sub->swm->oport.map));
0256 regmap_write(r, AOUTRSTCTR1, BIT(sub->swm->oport.map));
0257 } else {
0258 regmap_update_bits(r, IPORTMXRSTCTR(sub->swm->iport.map),
0259 IPORTMXRSTCTR_RSTPI_MASK,
0260 IPORTMXRSTCTR_RSTPI_RESET);
0261 regmap_update_bits(r, IPORTMXRSTCTR(sub->swm->iport.map),
0262 IPORTMXRSTCTR_RSTPI_MASK,
0263 IPORTMXRSTCTR_RSTPI_RELEASE);
0264 }
0265 }
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277 static int aio_port_set_ch(struct uniphier_aio_sub *sub)
0278 {
0279 struct regmap *r = sub->aio->chip->regmap;
0280 u32 slotsel_2ch[] = {
0281 0, 0, 0, 0, 0,
0282 };
0283 u32 slotsel_multi[] = {
0284 OPORTMXTYSLOTCTR_SLOTSEL_SLOT0,
0285 OPORTMXTYSLOTCTR_SLOTSEL_SLOT1,
0286 OPORTMXTYSLOTCTR_SLOTSEL_SLOT2,
0287 OPORTMXTYSLOTCTR_SLOTSEL_SLOT3,
0288 OPORTMXTYSLOTCTR_SLOTSEL_SLOT4,
0289 };
0290 u32 mode, *slotsel;
0291 int i;
0292
0293 switch (params_channels(&sub->params)) {
0294 case 8:
0295 case 6:
0296 mode = OPORTMXTYSLOTCTR_MODE;
0297 slotsel = slotsel_multi;
0298 break;
0299 case 2:
0300 mode = 0;
0301 slotsel = slotsel_2ch;
0302 break;
0303 default:
0304 return -EINVAL;
0305 }
0306
0307 for (i = 0; i < AUD_MAX_SLOTSEL; i++) {
0308 regmap_update_bits(r, OPORTMXTYSLOTCTR(sub->swm->oport.map, i),
0309 OPORTMXTYSLOTCTR_MODE, mode);
0310 regmap_update_bits(r, OPORTMXTYSLOTCTR(sub->swm->oport.map, i),
0311 OPORTMXTYSLOTCTR_SLOTSEL_MASK, slotsel[i]);
0312 }
0313
0314 return 0;
0315 }
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329 static int aio_port_set_rate(struct uniphier_aio_sub *sub, int rate)
0330 {
0331 struct regmap *r = sub->aio->chip->regmap;
0332 struct device *dev = &sub->aio->chip->pdev->dev;
0333 u32 v;
0334
0335 if (sub->swm->dir == PORT_DIR_OUTPUT) {
0336 switch (rate) {
0337 case 8000:
0338 v = OPORTMXCTR1_FSSEL_8;
0339 break;
0340 case 11025:
0341 v = OPORTMXCTR1_FSSEL_11_025;
0342 break;
0343 case 12000:
0344 v = OPORTMXCTR1_FSSEL_12;
0345 break;
0346 case 16000:
0347 v = OPORTMXCTR1_FSSEL_16;
0348 break;
0349 case 22050:
0350 v = OPORTMXCTR1_FSSEL_22_05;
0351 break;
0352 case 24000:
0353 v = OPORTMXCTR1_FSSEL_24;
0354 break;
0355 case 32000:
0356 v = OPORTMXCTR1_FSSEL_32;
0357 break;
0358 case 44100:
0359 v = OPORTMXCTR1_FSSEL_44_1;
0360 break;
0361 case 48000:
0362 v = OPORTMXCTR1_FSSEL_48;
0363 break;
0364 case 88200:
0365 v = OPORTMXCTR1_FSSEL_88_2;
0366 break;
0367 case 96000:
0368 v = OPORTMXCTR1_FSSEL_96;
0369 break;
0370 case 176400:
0371 v = OPORTMXCTR1_FSSEL_176_4;
0372 break;
0373 case 192000:
0374 v = OPORTMXCTR1_FSSEL_192;
0375 break;
0376 default:
0377 dev_err(dev, "Rate not supported(%d)\n", rate);
0378 return -EINVAL;
0379 }
0380
0381 regmap_update_bits(r, OPORTMXCTR1(sub->swm->oport.map),
0382 OPORTMXCTR1_FSSEL_MASK, v);
0383 } else {
0384 switch (rate) {
0385 case 8000:
0386 v = IPORTMXCTR1_FSSEL_8;
0387 break;
0388 case 11025:
0389 v = IPORTMXCTR1_FSSEL_11_025;
0390 break;
0391 case 12000:
0392 v = IPORTMXCTR1_FSSEL_12;
0393 break;
0394 case 16000:
0395 v = IPORTMXCTR1_FSSEL_16;
0396 break;
0397 case 22050:
0398 v = IPORTMXCTR1_FSSEL_22_05;
0399 break;
0400 case 24000:
0401 v = IPORTMXCTR1_FSSEL_24;
0402 break;
0403 case 32000:
0404 v = IPORTMXCTR1_FSSEL_32;
0405 break;
0406 case 44100:
0407 v = IPORTMXCTR1_FSSEL_44_1;
0408 break;
0409 case 48000:
0410 v = IPORTMXCTR1_FSSEL_48;
0411 break;
0412 case 88200:
0413 v = IPORTMXCTR1_FSSEL_88_2;
0414 break;
0415 case 96000:
0416 v = IPORTMXCTR1_FSSEL_96;
0417 break;
0418 case 176400:
0419 v = IPORTMXCTR1_FSSEL_176_4;
0420 break;
0421 case 192000:
0422 v = IPORTMXCTR1_FSSEL_192;
0423 break;
0424 default:
0425 dev_err(dev, "Rate not supported(%d)\n", rate);
0426 return -EINVAL;
0427 }
0428
0429 regmap_update_bits(r, IPORTMXCTR1(sub->swm->iport.map),
0430 IPORTMXCTR1_FSSEL_MASK, v);
0431 }
0432
0433 return 0;
0434 }
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448 static int aio_port_set_fmt(struct uniphier_aio_sub *sub)
0449 {
0450 struct regmap *r = sub->aio->chip->regmap;
0451 struct device *dev = &sub->aio->chip->pdev->dev;
0452 u32 v;
0453
0454 if (sub->swm->dir == PORT_DIR_OUTPUT) {
0455 switch (sub->aio->fmt) {
0456 case SND_SOC_DAIFMT_LEFT_J:
0457 v = OPORTMXCTR1_I2SLRSEL_LEFT;
0458 break;
0459 case SND_SOC_DAIFMT_RIGHT_J:
0460 v = OPORTMXCTR1_I2SLRSEL_RIGHT;
0461 break;
0462 case SND_SOC_DAIFMT_I2S:
0463 v = OPORTMXCTR1_I2SLRSEL_I2S;
0464 break;
0465 default:
0466 dev_err(dev, "Format is not supported(%d)\n",
0467 sub->aio->fmt);
0468 return -EINVAL;
0469 }
0470
0471 v |= OPORTMXCTR1_OUTBITSEL_24;
0472 regmap_update_bits(r, OPORTMXCTR1(sub->swm->oport.map),
0473 OPORTMXCTR1_I2SLRSEL_MASK |
0474 OPORTMXCTR1_OUTBITSEL_MASK, v);
0475 } else {
0476 switch (sub->aio->fmt) {
0477 case SND_SOC_DAIFMT_LEFT_J:
0478 v = IPORTMXCTR1_LRSEL_LEFT;
0479 break;
0480 case SND_SOC_DAIFMT_RIGHT_J:
0481 v = IPORTMXCTR1_LRSEL_RIGHT;
0482 break;
0483 case SND_SOC_DAIFMT_I2S:
0484 v = IPORTMXCTR1_LRSEL_I2S;
0485 break;
0486 default:
0487 dev_err(dev, "Format is not supported(%d)\n",
0488 sub->aio->fmt);
0489 return -EINVAL;
0490 }
0491
0492 v |= IPORTMXCTR1_OUTBITSEL_24 |
0493 IPORTMXCTR1_CHSEL_ALL;
0494 regmap_update_bits(r, IPORTMXCTR1(sub->swm->iport.map),
0495 IPORTMXCTR1_LRSEL_MASK |
0496 IPORTMXCTR1_OUTBITSEL_MASK |
0497 IPORTMXCTR1_CHSEL_MASK, v);
0498 }
0499
0500 return 0;
0501 }
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513 static int aio_port_set_clk(struct uniphier_aio_sub *sub)
0514 {
0515 struct uniphier_aio_chip *chip = sub->aio->chip;
0516 struct device *dev = &sub->aio->chip->pdev->dev;
0517 struct regmap *r = sub->aio->chip->regmap;
0518 u32 v_pll[] = {
0519 OPORTMXCTR2_ACLKSEL_A1, OPORTMXCTR2_ACLKSEL_F1,
0520 OPORTMXCTR2_ACLKSEL_A2, OPORTMXCTR2_ACLKSEL_F2,
0521 OPORTMXCTR2_ACLKSEL_A2PLL,
0522 OPORTMXCTR2_ACLKSEL_RX1,
0523 };
0524 u32 v_div[] = {
0525 OPORTMXCTR2_DACCKSEL_1_2, OPORTMXCTR2_DACCKSEL_1_3,
0526 OPORTMXCTR2_DACCKSEL_1_1, OPORTMXCTR2_DACCKSEL_2_3,
0527 };
0528 u32 v;
0529
0530 if (sub->swm->dir == PORT_DIR_OUTPUT) {
0531 if (sub->swm->type == PORT_TYPE_I2S) {
0532 if (sub->aio->pll_out >= ARRAY_SIZE(v_pll)) {
0533 dev_err(dev, "PLL(%d) is invalid\n",
0534 sub->aio->pll_out);
0535 return -EINVAL;
0536 }
0537 if (sub->aio->plldiv >= ARRAY_SIZE(v_div)) {
0538 dev_err(dev, "PLL divider(%d) is invalid\n",
0539 sub->aio->plldiv);
0540 return -EINVAL;
0541 }
0542
0543 v = v_pll[sub->aio->pll_out] |
0544 OPORTMXCTR2_MSSEL_MASTER |
0545 v_div[sub->aio->plldiv];
0546
0547 switch (chip->plls[sub->aio->pll_out].freq) {
0548 case 0:
0549 case 36864000:
0550 case 33868800:
0551 v |= OPORTMXCTR2_EXTLSIFSSEL_36;
0552 break;
0553 default:
0554 v |= OPORTMXCTR2_EXTLSIFSSEL_24;
0555 break;
0556 }
0557 } else if (sub->swm->type == PORT_TYPE_EVE) {
0558 v = OPORTMXCTR2_ACLKSEL_A2PLL |
0559 OPORTMXCTR2_MSSEL_MASTER |
0560 OPORTMXCTR2_EXTLSIFSSEL_36 |
0561 OPORTMXCTR2_DACCKSEL_1_2;
0562 } else if (sub->swm->type == PORT_TYPE_SPDIF) {
0563 if (sub->aio->pll_out >= ARRAY_SIZE(v_pll)) {
0564 dev_err(dev, "PLL(%d) is invalid\n",
0565 sub->aio->pll_out);
0566 return -EINVAL;
0567 }
0568 v = v_pll[sub->aio->pll_out] |
0569 OPORTMXCTR2_MSSEL_MASTER |
0570 OPORTMXCTR2_DACCKSEL_1_2;
0571
0572 switch (chip->plls[sub->aio->pll_out].freq) {
0573 case 0:
0574 case 36864000:
0575 case 33868800:
0576 v |= OPORTMXCTR2_EXTLSIFSSEL_36;
0577 break;
0578 default:
0579 v |= OPORTMXCTR2_EXTLSIFSSEL_24;
0580 break;
0581 }
0582 } else {
0583 v = OPORTMXCTR2_ACLKSEL_A1 |
0584 OPORTMXCTR2_MSSEL_MASTER |
0585 OPORTMXCTR2_EXTLSIFSSEL_36 |
0586 OPORTMXCTR2_DACCKSEL_1_2;
0587 }
0588 regmap_write(r, OPORTMXCTR2(sub->swm->oport.map), v);
0589 } else {
0590 v = IPORTMXCTR2_ACLKSEL_A1 |
0591 IPORTMXCTR2_MSSEL_SLAVE |
0592 IPORTMXCTR2_EXTLSIFSSEL_36 |
0593 IPORTMXCTR2_DACCKSEL_1_2;
0594 regmap_write(r, IPORTMXCTR2(sub->swm->iport.map), v);
0595 }
0596
0597 return 0;
0598 }
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612 int aio_port_set_param(struct uniphier_aio_sub *sub, int pass_through,
0613 const struct snd_pcm_hw_params *params)
0614 {
0615 struct regmap *r = sub->aio->chip->regmap;
0616 unsigned int rate;
0617 u32 v;
0618 int ret;
0619
0620 if (!pass_through) {
0621 if (sub->swm->type == PORT_TYPE_EVE ||
0622 sub->swm->type == PORT_TYPE_CONV) {
0623 rate = 48000;
0624 } else {
0625 rate = params_rate(params);
0626 }
0627
0628 ret = aio_port_set_ch(sub);
0629 if (ret)
0630 return ret;
0631
0632 ret = aio_port_set_rate(sub, rate);
0633 if (ret)
0634 return ret;
0635
0636 ret = aio_port_set_fmt(sub);
0637 if (ret)
0638 return ret;
0639 }
0640
0641 ret = aio_port_set_clk(sub);
0642 if (ret)
0643 return ret;
0644
0645 if (sub->swm->dir == PORT_DIR_OUTPUT) {
0646 if (pass_through)
0647 v = OPORTMXCTR3_SRCSEL_STREAM |
0648 OPORTMXCTR3_VALID_STREAM;
0649 else
0650 v = OPORTMXCTR3_SRCSEL_PCM |
0651 OPORTMXCTR3_VALID_PCM;
0652
0653 v |= OPORTMXCTR3_IECTHUR_IECOUT |
0654 OPORTMXCTR3_PMSEL_PAUSE |
0655 OPORTMXCTR3_PMSW_MUTE_OFF;
0656 regmap_write(r, OPORTMXCTR3(sub->swm->oport.map), v);
0657 } else {
0658 regmap_write(r, IPORTMXACLKSEL0EX(sub->swm->iport.map),
0659 IPORTMXACLKSEL0EX_ACLKSEL0EX_INTERNAL);
0660 regmap_write(r, IPORTMXEXNOE(sub->swm->iport.map),
0661 IPORTMXEXNOE_PCMINOE_INPUT);
0662 }
0663
0664 return 0;
0665 }
0666
0667
0668
0669
0670
0671
0672
0673
0674 void aio_port_set_enable(struct uniphier_aio_sub *sub, int enable)
0675 {
0676 struct regmap *r = sub->aio->chip->regmap;
0677
0678 if (sub->swm->dir == PORT_DIR_OUTPUT) {
0679 regmap_write(r, OPORTMXPATH(sub->swm->oport.map),
0680 sub->swm->oif.map);
0681
0682 regmap_update_bits(r, OPORTMXMASK(sub->swm->oport.map),
0683 OPORTMXMASK_IUDXMSK_MASK |
0684 OPORTMXMASK_IUXCKMSK_MASK |
0685 OPORTMXMASK_DXMSK_MASK |
0686 OPORTMXMASK_XCKMSK_MASK,
0687 OPORTMXMASK_IUDXMSK_OFF |
0688 OPORTMXMASK_IUXCKMSK_OFF |
0689 OPORTMXMASK_DXMSK_OFF |
0690 OPORTMXMASK_XCKMSK_OFF);
0691
0692 if (enable)
0693 regmap_write(r, AOUTENCTR0, BIT(sub->swm->oport.map));
0694 else
0695 regmap_write(r, AOUTENCTR1, BIT(sub->swm->oport.map));
0696 } else {
0697 regmap_update_bits(r, IPORTMXMASK(sub->swm->iport.map),
0698 IPORTMXMASK_IUXCKMSK_MASK |
0699 IPORTMXMASK_XCKMSK_MASK,
0700 IPORTMXMASK_IUXCKMSK_OFF |
0701 IPORTMXMASK_XCKMSK_OFF);
0702
0703 if (enable)
0704 regmap_update_bits(r,
0705 IPORTMXCTR2(sub->swm->iport.map),
0706 IPORTMXCTR2_REQEN_MASK,
0707 IPORTMXCTR2_REQEN_ENABLE);
0708 else
0709 regmap_update_bits(r,
0710 IPORTMXCTR2(sub->swm->iport.map),
0711 IPORTMXCTR2_REQEN_MASK,
0712 IPORTMXCTR2_REQEN_DISABLE);
0713 }
0714 }
0715
0716
0717
0718
0719
0720
0721
0722 int aio_port_get_volume(struct uniphier_aio_sub *sub)
0723 {
0724 struct regmap *r = sub->aio->chip->regmap;
0725 u32 v;
0726
0727 regmap_read(r, OPORTMXTYVOLGAINSTATUS(sub->swm->oport.map, 0), &v);
0728
0729 return FIELD_GET(OPORTMXTYVOLGAINSTATUS_CUR_MASK, v);
0730 }
0731
0732
0733
0734
0735
0736
0737
0738
0739
0740
0741 void aio_port_set_volume(struct uniphier_aio_sub *sub, int vol)
0742 {
0743 struct regmap *r = sub->aio->chip->regmap;
0744 int oport_map = sub->swm->oport.map;
0745 int cur, diff, slope = 0, fs;
0746
0747 if (sub->swm->dir == PORT_DIR_INPUT)
0748 return;
0749
0750 cur = aio_port_get_volume(sub);
0751 diff = abs(vol - cur);
0752 fs = params_rate(&sub->params);
0753 if (fs)
0754 slope = diff / AUD_VOL_FADE_TIME * 1000 / fs;
0755 slope = max(1, slope);
0756
0757 regmap_update_bits(r, OPORTMXTYVOLPARA1(oport_map, 0),
0758 OPORTMXTYVOLPARA1_SLOPEU_MASK, slope << 16);
0759 regmap_update_bits(r, OPORTMXTYVOLPARA2(oport_map, 0),
0760 OPORTMXTYVOLPARA2_TARGET_MASK, vol);
0761
0762 if (cur < vol)
0763 regmap_update_bits(r, OPORTMXTYVOLPARA2(oport_map, 0),
0764 OPORTMXTYVOLPARA2_FADE_MASK,
0765 OPORTMXTYVOLPARA2_FADE_FADEIN);
0766 else
0767 regmap_update_bits(r, OPORTMXTYVOLPARA2(oport_map, 0),
0768 OPORTMXTYVOLPARA2_FADE_MASK,
0769 OPORTMXTYVOLPARA2_FADE_FADEOUT);
0770
0771 regmap_write(r, AOUTFADECTR0, BIT(oport_map));
0772 }
0773
0774
0775
0776
0777
0778
0779
0780
0781
0782
0783
0784
0785 int aio_if_set_param(struct uniphier_aio_sub *sub, int pass_through)
0786 {
0787 struct regmap *r = sub->aio->chip->regmap;
0788 u32 memfmt, v;
0789
0790 if (sub->swm->dir == PORT_DIR_OUTPUT) {
0791 if (pass_through) {
0792 v = PBOUTMXCTR0_ENDIAN_0123 |
0793 PBOUTMXCTR0_MEMFMT_STREAM;
0794 } else {
0795 switch (params_channels(&sub->params)) {
0796 case 2:
0797 memfmt = PBOUTMXCTR0_MEMFMT_2CH;
0798 break;
0799 case 6:
0800 memfmt = PBOUTMXCTR0_MEMFMT_6CH;
0801 break;
0802 case 8:
0803 memfmt = PBOUTMXCTR0_MEMFMT_8CH;
0804 break;
0805 default:
0806 return -EINVAL;
0807 }
0808 v = PBOUTMXCTR0_ENDIAN_3210 | memfmt;
0809 }
0810
0811 regmap_write(r, PBOUTMXCTR0(sub->swm->oif.map), v);
0812 regmap_write(r, PBOUTMXCTR1(sub->swm->oif.map), 0);
0813 } else {
0814 regmap_write(r, PBINMXCTR(sub->swm->iif.map),
0815 PBINMXCTR_NCONNECT_CONNECT |
0816 PBINMXCTR_INOUTSEL_IN |
0817 (sub->swm->iport.map << PBINMXCTR_PBINSEL_SHIFT) |
0818 PBINMXCTR_ENDIAN_3210 |
0819 PBINMXCTR_MEMFMT_D0);
0820 }
0821
0822 return 0;
0823 }
0824
0825
0826
0827
0828
0829
0830
0831
0832
0833
0834
0835 int aio_oport_set_stream_type(struct uniphier_aio_sub *sub,
0836 enum IEC61937_PC pc)
0837 {
0838 struct regmap *r = sub->aio->chip->regmap;
0839 u32 repet = 0, pause = OPORTMXPAUDAT_PAUSEPC_CMN;
0840
0841 switch (pc) {
0842 case IEC61937_PC_AC3:
0843 repet = OPORTMXREPET_STRLENGTH_AC3 |
0844 OPORTMXREPET_PMLENGTH_AC3;
0845 pause |= OPORTMXPAUDAT_PAUSEPD_AC3;
0846 break;
0847 case IEC61937_PC_MPA:
0848 repet = OPORTMXREPET_STRLENGTH_MPA |
0849 OPORTMXREPET_PMLENGTH_MPA;
0850 pause |= OPORTMXPAUDAT_PAUSEPD_MPA;
0851 break;
0852 case IEC61937_PC_MP3:
0853 repet = OPORTMXREPET_STRLENGTH_MP3 |
0854 OPORTMXREPET_PMLENGTH_MP3;
0855 pause |= OPORTMXPAUDAT_PAUSEPD_MP3;
0856 break;
0857 case IEC61937_PC_DTS1:
0858 repet = OPORTMXREPET_STRLENGTH_DTS1 |
0859 OPORTMXREPET_PMLENGTH_DTS1;
0860 pause |= OPORTMXPAUDAT_PAUSEPD_DTS1;
0861 break;
0862 case IEC61937_PC_DTS2:
0863 repet = OPORTMXREPET_STRLENGTH_DTS2 |
0864 OPORTMXREPET_PMLENGTH_DTS2;
0865 pause |= OPORTMXPAUDAT_PAUSEPD_DTS2;
0866 break;
0867 case IEC61937_PC_DTS3:
0868 repet = OPORTMXREPET_STRLENGTH_DTS3 |
0869 OPORTMXREPET_PMLENGTH_DTS3;
0870 pause |= OPORTMXPAUDAT_PAUSEPD_DTS3;
0871 break;
0872 case IEC61937_PC_AAC:
0873 repet = OPORTMXREPET_STRLENGTH_AAC |
0874 OPORTMXREPET_PMLENGTH_AAC;
0875 pause |= OPORTMXPAUDAT_PAUSEPD_AAC;
0876 break;
0877 case IEC61937_PC_PAUSE:
0878
0879 break;
0880 }
0881
0882 regmap_write(r, OPORTMXREPET(sub->swm->oport.map), repet);
0883 regmap_write(r, OPORTMXPAUDAT(sub->swm->oport.map), pause);
0884
0885 return 0;
0886 }
0887
0888
0889
0890
0891
0892
0893
0894
0895
0896 void aio_src_reset(struct uniphier_aio_sub *sub)
0897 {
0898 struct regmap *r = sub->aio->chip->regmap;
0899
0900 if (sub->swm->dir != PORT_DIR_OUTPUT)
0901 return;
0902
0903 regmap_write(r, AOUTSRCRSTCTR0, BIT(sub->swm->oport.map));
0904 regmap_write(r, AOUTSRCRSTCTR1, BIT(sub->swm->oport.map));
0905 }
0906
0907
0908
0909
0910
0911
0912
0913
0914
0915
0916
0917
0918 int aio_src_set_param(struct uniphier_aio_sub *sub,
0919 const struct snd_pcm_hw_params *params)
0920 {
0921 struct regmap *r = sub->aio->chip->regmap;
0922 u32 v;
0923
0924 if (sub->swm->dir != PORT_DIR_OUTPUT)
0925 return 0;
0926
0927 regmap_write(r, OPORTMXSRC1CTR(sub->swm->oport.map),
0928 OPORTMXSRC1CTR_THMODE_SRC |
0929 OPORTMXSRC1CTR_SRCPATH_CALC |
0930 OPORTMXSRC1CTR_SYNC_ASYNC |
0931 OPORTMXSRC1CTR_FSIIPSEL_INNER |
0932 OPORTMXSRC1CTR_FSISEL_ACLK);
0933
0934 switch (params_rate(params)) {
0935 default:
0936 case 48000:
0937 v = OPORTMXRATE_I_ACLKSEL_APLLA1 |
0938 OPORTMXRATE_I_MCKSEL_36 |
0939 OPORTMXRATE_I_FSSEL_48;
0940 break;
0941 case 44100:
0942 v = OPORTMXRATE_I_ACLKSEL_APLLA2 |
0943 OPORTMXRATE_I_MCKSEL_33 |
0944 OPORTMXRATE_I_FSSEL_44_1;
0945 break;
0946 case 32000:
0947 v = OPORTMXRATE_I_ACLKSEL_APLLA1 |
0948 OPORTMXRATE_I_MCKSEL_36 |
0949 OPORTMXRATE_I_FSSEL_32;
0950 break;
0951 }
0952
0953 regmap_write(r, OPORTMXRATE_I(sub->swm->oport.map),
0954 v | OPORTMXRATE_I_ACLKSRC_APLL |
0955 OPORTMXRATE_I_LRCKSTP_STOP);
0956 regmap_update_bits(r, OPORTMXRATE_I(sub->swm->oport.map),
0957 OPORTMXRATE_I_LRCKSTP_MASK,
0958 OPORTMXRATE_I_LRCKSTP_START);
0959
0960 return 0;
0961 }
0962
0963 int aio_srcif_set_param(struct uniphier_aio_sub *sub)
0964 {
0965 struct regmap *r = sub->aio->chip->regmap;
0966
0967 regmap_write(r, PBINMXCTR(sub->swm->iif.map),
0968 PBINMXCTR_NCONNECT_CONNECT |
0969 PBINMXCTR_INOUTSEL_OUT |
0970 (sub->swm->oport.map << PBINMXCTR_PBINSEL_SHIFT) |
0971 PBINMXCTR_ENDIAN_3210 |
0972 PBINMXCTR_MEMFMT_D0);
0973
0974 return 0;
0975 }
0976
0977 int aio_srcch_set_param(struct uniphier_aio_sub *sub)
0978 {
0979 struct regmap *r = sub->aio->chip->regmap;
0980
0981 regmap_write(r, CDA2D_CHMXCTRL1(sub->swm->och.map),
0982 CDA2D_CHMXCTRL1_INDSIZE_INFINITE);
0983
0984 regmap_write(r, CDA2D_CHMXSRCAMODE(sub->swm->och.map),
0985 CDA2D_CHMXAMODE_ENDIAN_3210 |
0986 CDA2D_CHMXAMODE_AUPDT_FIX |
0987 CDA2D_CHMXAMODE_TYPE_NORMAL);
0988
0989 regmap_write(r, CDA2D_CHMXDSTAMODE(sub->swm->och.map),
0990 CDA2D_CHMXAMODE_ENDIAN_3210 |
0991 CDA2D_CHMXAMODE_AUPDT_INC |
0992 CDA2D_CHMXAMODE_TYPE_RING |
0993 (sub->swm->och.map << CDA2D_CHMXAMODE_RSSEL_SHIFT));
0994
0995 return 0;
0996 }
0997
0998 void aio_srcch_set_enable(struct uniphier_aio_sub *sub, int enable)
0999 {
1000 struct regmap *r = sub->aio->chip->regmap;
1001 u32 v;
1002
1003 if (enable)
1004 v = CDA2D_STRT0_STOP_START;
1005 else
1006 v = CDA2D_STRT0_STOP_STOP;
1007
1008 regmap_write(r, CDA2D_STRT0,
1009 v | BIT(sub->swm->och.map));
1010 }
1011
1012 int aiodma_ch_set_param(struct uniphier_aio_sub *sub)
1013 {
1014 struct regmap *r = sub->aio->chip->regmap;
1015 u32 v;
1016
1017 regmap_write(r, CDA2D_CHMXCTRL1(sub->swm->ch.map),
1018 CDA2D_CHMXCTRL1_INDSIZE_INFINITE);
1019
1020 v = CDA2D_CHMXAMODE_ENDIAN_3210 |
1021 CDA2D_CHMXAMODE_AUPDT_INC |
1022 CDA2D_CHMXAMODE_TYPE_NORMAL |
1023 (sub->swm->rb.map << CDA2D_CHMXAMODE_RSSEL_SHIFT);
1024 if (sub->swm->dir == PORT_DIR_OUTPUT)
1025 regmap_write(r, CDA2D_CHMXSRCAMODE(sub->swm->ch.map), v);
1026 else
1027 regmap_write(r, CDA2D_CHMXDSTAMODE(sub->swm->ch.map), v);
1028
1029 return 0;
1030 }
1031
1032 void aiodma_ch_set_enable(struct uniphier_aio_sub *sub, int enable)
1033 {
1034 struct regmap *r = sub->aio->chip->regmap;
1035
1036 if (enable) {
1037 regmap_write(r, CDA2D_STRT0,
1038 CDA2D_STRT0_STOP_START | BIT(sub->swm->ch.map));
1039
1040 regmap_update_bits(r, INTRBIM(0),
1041 BIT(sub->swm->rb.map),
1042 BIT(sub->swm->rb.map));
1043 } else {
1044 regmap_write(r, CDA2D_STRT0,
1045 CDA2D_STRT0_STOP_STOP | BIT(sub->swm->ch.map));
1046
1047 regmap_update_bits(r, INTRBIM(0),
1048 BIT(sub->swm->rb.map),
1049 0);
1050 }
1051 }
1052
1053 static u64 aiodma_rb_get_rp(struct uniphier_aio_sub *sub)
1054 {
1055 struct regmap *r = sub->aio->chip->regmap;
1056 u32 pos_u, pos_l;
1057 int i;
1058
1059 regmap_write(r, CDA2D_RDPTRLOAD,
1060 CDA2D_RDPTRLOAD_LSFLAG_STORE | BIT(sub->swm->rb.map));
1061
1062 for (i = 0; i < 6; i++)
1063 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &pos_l);
1064
1065 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &pos_l);
1066 regmap_read(r, CDA2D_RBMXRDPTRU(sub->swm->rb.map), &pos_u);
1067 pos_u = FIELD_GET(CDA2D_RBMXPTRU_PTRU_MASK, pos_u);
1068
1069 return ((u64)pos_u << 32) | pos_l;
1070 }
1071
1072 static void aiodma_rb_set_rp(struct uniphier_aio_sub *sub, u64 pos)
1073 {
1074 struct regmap *r = sub->aio->chip->regmap;
1075 u32 tmp;
1076 int i;
1077
1078 regmap_write(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), (u32)pos);
1079 regmap_write(r, CDA2D_RBMXRDPTRU(sub->swm->rb.map), (u32)(pos >> 32));
1080 regmap_write(r, CDA2D_RDPTRLOAD, BIT(sub->swm->rb.map));
1081
1082 for (i = 0; i < 6; i++)
1083 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &tmp);
1084 }
1085
1086 static u64 aiodma_rb_get_wp(struct uniphier_aio_sub *sub)
1087 {
1088 struct regmap *r = sub->aio->chip->regmap;
1089 u32 pos_u, pos_l;
1090 int i;
1091
1092 regmap_write(r, CDA2D_WRPTRLOAD,
1093 CDA2D_WRPTRLOAD_LSFLAG_STORE | BIT(sub->swm->rb.map));
1094
1095 for (i = 0; i < 6; i++)
1096 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &pos_l);
1097
1098 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &pos_l);
1099 regmap_read(r, CDA2D_RBMXWRPTRU(sub->swm->rb.map), &pos_u);
1100 pos_u = FIELD_GET(CDA2D_RBMXPTRU_PTRU_MASK, pos_u);
1101
1102 return ((u64)pos_u << 32) | pos_l;
1103 }
1104
1105 static void aiodma_rb_set_wp(struct uniphier_aio_sub *sub, u64 pos)
1106 {
1107 struct regmap *r = sub->aio->chip->regmap;
1108 u32 tmp;
1109 int i;
1110
1111 regmap_write(r, CDA2D_RBMXWRPTR(sub->swm->rb.map),
1112 lower_32_bits(pos));
1113 regmap_write(r, CDA2D_RBMXWRPTRU(sub->swm->rb.map),
1114 upper_32_bits(pos));
1115 regmap_write(r, CDA2D_WRPTRLOAD, BIT(sub->swm->rb.map));
1116
1117 for (i = 0; i < 6; i++)
1118 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &tmp);
1119 }
1120
1121 int aiodma_rb_set_threshold(struct uniphier_aio_sub *sub, u64 size, u32 th)
1122 {
1123 struct regmap *r = sub->aio->chip->regmap;
1124
1125 if (size <= th)
1126 return -EINVAL;
1127
1128 regmap_write(r, CDA2D_RBMXBTH(sub->swm->rb.map), th);
1129 regmap_write(r, CDA2D_RBMXRTH(sub->swm->rb.map), th);
1130
1131 return 0;
1132 }
1133
1134 int aiodma_rb_set_buffer(struct uniphier_aio_sub *sub, u64 start, u64 end,
1135 int period)
1136 {
1137 struct regmap *r = sub->aio->chip->regmap;
1138 u64 size = end - start;
1139 int ret;
1140
1141 if (end < start || period < 0)
1142 return -EINVAL;
1143
1144 regmap_write(r, CDA2D_RBMXCNFG(sub->swm->rb.map), 0);
1145 regmap_write(r, CDA2D_RBMXBGNADRS(sub->swm->rb.map),
1146 lower_32_bits(start));
1147 regmap_write(r, CDA2D_RBMXBGNADRSU(sub->swm->rb.map),
1148 upper_32_bits(start));
1149 regmap_write(r, CDA2D_RBMXENDADRS(sub->swm->rb.map),
1150 lower_32_bits(end));
1151 regmap_write(r, CDA2D_RBMXENDADRSU(sub->swm->rb.map),
1152 upper_32_bits(end));
1153
1154 regmap_write(r, CDA2D_RBADRSLOAD, BIT(sub->swm->rb.map));
1155
1156 ret = aiodma_rb_set_threshold(sub, size, 2 * period);
1157 if (ret)
1158 return ret;
1159
1160 if (sub->swm->dir == PORT_DIR_OUTPUT) {
1161 aiodma_rb_set_rp(sub, start);
1162 aiodma_rb_set_wp(sub, end - period);
1163
1164 regmap_update_bits(r, CDA2D_RBMXIE(sub->swm->rb.map),
1165 CDA2D_RBMXIX_SPACE,
1166 CDA2D_RBMXIX_SPACE);
1167 } else {
1168 aiodma_rb_set_rp(sub, end - period);
1169 aiodma_rb_set_wp(sub, start);
1170
1171 regmap_update_bits(r, CDA2D_RBMXIE(sub->swm->rb.map),
1172 CDA2D_RBMXIX_REMAIN,
1173 CDA2D_RBMXIX_REMAIN);
1174 }
1175
1176 sub->threshold = 2 * period;
1177 sub->rd_offs = 0;
1178 sub->wr_offs = 0;
1179 sub->rd_org = 0;
1180 sub->wr_org = 0;
1181 sub->rd_total = 0;
1182 sub->wr_total = 0;
1183
1184 return 0;
1185 }
1186
1187 void aiodma_rb_sync(struct uniphier_aio_sub *sub, u64 start, u64 size,
1188 int period)
1189 {
1190 if (sub->swm->dir == PORT_DIR_OUTPUT) {
1191 sub->rd_offs = aiodma_rb_get_rp(sub) - start;
1192
1193 if (sub->use_mmap) {
1194 sub->threshold = 2 * period;
1195 aiodma_rb_set_threshold(sub, size, 2 * period);
1196
1197 sub->wr_offs = sub->rd_offs - period;
1198 if (sub->rd_offs < period)
1199 sub->wr_offs += size;
1200 }
1201 aiodma_rb_set_wp(sub, sub->wr_offs + start);
1202 } else {
1203 sub->wr_offs = aiodma_rb_get_wp(sub) - start;
1204
1205 if (sub->use_mmap) {
1206 sub->threshold = 2 * period;
1207 aiodma_rb_set_threshold(sub, size, 2 * period);
1208
1209 sub->rd_offs = sub->wr_offs - period;
1210 if (sub->wr_offs < period)
1211 sub->rd_offs += size;
1212 }
1213 aiodma_rb_set_rp(sub, sub->rd_offs + start);
1214 }
1215
1216 sub->rd_total += sub->rd_offs - sub->rd_org;
1217 if (sub->rd_offs < sub->rd_org)
1218 sub->rd_total += size;
1219 sub->wr_total += sub->wr_offs - sub->wr_org;
1220 if (sub->wr_offs < sub->wr_org)
1221 sub->wr_total += size;
1222
1223 sub->rd_org = sub->rd_offs;
1224 sub->wr_org = sub->wr_offs;
1225 }
1226
1227 bool aiodma_rb_is_irq(struct uniphier_aio_sub *sub)
1228 {
1229 struct regmap *r = sub->aio->chip->regmap;
1230 u32 ir;
1231
1232 regmap_read(r, CDA2D_RBMXIR(sub->swm->rb.map), &ir);
1233
1234 if (sub->swm->dir == PORT_DIR_OUTPUT)
1235 return !!(ir & CDA2D_RBMXIX_SPACE);
1236 else
1237 return !!(ir & CDA2D_RBMXIX_REMAIN);
1238 }
1239
1240 void aiodma_rb_clear_irq(struct uniphier_aio_sub *sub)
1241 {
1242 struct regmap *r = sub->aio->chip->regmap;
1243
1244 if (sub->swm->dir == PORT_DIR_OUTPUT)
1245 regmap_write(r, CDA2D_RBMXIR(sub->swm->rb.map),
1246 CDA2D_RBMXIX_SPACE);
1247 else
1248 regmap_write(r, CDA2D_RBMXIR(sub->swm->rb.map),
1249 CDA2D_RBMXIX_REMAIN);
1250 }