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