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