]> asedeno.scripts.mit.edu Git - linux.git/blob - sound/soc/sunxi/sun4i-i2s.c
ASoC: sun4i-i2s: Fix LRCK and BCLK polarity offsets on newer SoCs
[linux.git] / sound / soc / sunxi / sun4i-i2s.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2015 Andrea Venturi
4  * Andrea Venturi <be17068@iperbole.bo.it>
5  *
6  * Copyright (C) 2016 Maxime Ripard
7  * Maxime Ripard <maxime.ripard@free-electrons.com>
8  */
9
10 #include <linux/clk.h>
11 #include <linux/dmaengine.h>
12 #include <linux/module.h>
13 #include <linux/of_device.h>
14 #include <linux/platform_device.h>
15 #include <linux/pm_runtime.h>
16 #include <linux/regmap.h>
17 #include <linux/reset.h>
18
19 #include <sound/dmaengine_pcm.h>
20 #include <sound/pcm_params.h>
21 #include <sound/soc.h>
22 #include <sound/soc-dai.h>
23
24 #define SUN4I_I2S_CTRL_REG              0x00
25 #define SUN4I_I2S_CTRL_SDO_EN_MASK              GENMASK(11, 8)
26 #define SUN4I_I2S_CTRL_SDO_EN(sdo)                      BIT(8 + (sdo))
27 #define SUN4I_I2S_CTRL_MODE_MASK                BIT(5)
28 #define SUN4I_I2S_CTRL_MODE_SLAVE                       (1 << 5)
29 #define SUN4I_I2S_CTRL_MODE_MASTER                      (0 << 5)
30 #define SUN4I_I2S_CTRL_TX_EN                    BIT(2)
31 #define SUN4I_I2S_CTRL_RX_EN                    BIT(1)
32 #define SUN4I_I2S_CTRL_GL_EN                    BIT(0)
33
34 #define SUN4I_I2S_FMT0_REG              0x04
35 #define SUN4I_I2S_FMT0_LRCLK_POLARITY_MASK      BIT(7)
36 #define SUN4I_I2S_FMT0_LRCLK_POLARITY_INVERTED          (1 << 7)
37 #define SUN4I_I2S_FMT0_LRCLK_POLARITY_NORMAL            (0 << 7)
38 #define SUN4I_I2S_FMT0_BCLK_POLARITY_MASK       BIT(6)
39 #define SUN4I_I2S_FMT0_BCLK_POLARITY_INVERTED           (1 << 6)
40 #define SUN4I_I2S_FMT0_BCLK_POLARITY_NORMAL             (0 << 6)
41 #define SUN4I_I2S_FMT0_SR_MASK                  GENMASK(5, 4)
42 #define SUN4I_I2S_FMT0_SR(sr)                           ((sr) << 4)
43 #define SUN4I_I2S_FMT0_WSS_MASK                 GENMASK(3, 2)
44 #define SUN4I_I2S_FMT0_WSS(wss)                         ((wss) << 2)
45 #define SUN4I_I2S_FMT0_FMT_MASK                 GENMASK(1, 0)
46 #define SUN4I_I2S_FMT0_FMT_RIGHT_J                      (2 << 0)
47 #define SUN4I_I2S_FMT0_FMT_LEFT_J                       (1 << 0)
48 #define SUN4I_I2S_FMT0_FMT_I2S                          (0 << 0)
49
50 #define SUN4I_I2S_FMT1_REG              0x08
51 #define SUN4I_I2S_FIFO_TX_REG           0x0c
52 #define SUN4I_I2S_FIFO_RX_REG           0x10
53
54 #define SUN4I_I2S_FIFO_CTRL_REG         0x14
55 #define SUN4I_I2S_FIFO_CTRL_FLUSH_TX            BIT(25)
56 #define SUN4I_I2S_FIFO_CTRL_FLUSH_RX            BIT(24)
57 #define SUN4I_I2S_FIFO_CTRL_TX_MODE_MASK        BIT(2)
58 #define SUN4I_I2S_FIFO_CTRL_TX_MODE(mode)               ((mode) << 2)
59 #define SUN4I_I2S_FIFO_CTRL_RX_MODE_MASK        GENMASK(1, 0)
60 #define SUN4I_I2S_FIFO_CTRL_RX_MODE(mode)               (mode)
61
62 #define SUN4I_I2S_FIFO_STA_REG          0x18
63
64 #define SUN4I_I2S_DMA_INT_CTRL_REG      0x1c
65 #define SUN4I_I2S_DMA_INT_CTRL_TX_DRQ_EN        BIT(7)
66 #define SUN4I_I2S_DMA_INT_CTRL_RX_DRQ_EN        BIT(3)
67
68 #define SUN4I_I2S_INT_STA_REG           0x20
69
70 #define SUN4I_I2S_CLK_DIV_REG           0x24
71 #define SUN4I_I2S_CLK_DIV_MCLK_EN               BIT(7)
72 #define SUN4I_I2S_CLK_DIV_BCLK_MASK             GENMASK(6, 4)
73 #define SUN4I_I2S_CLK_DIV_BCLK(bclk)                    ((bclk) << 4)
74 #define SUN4I_I2S_CLK_DIV_MCLK_MASK             GENMASK(3, 0)
75 #define SUN4I_I2S_CLK_DIV_MCLK(mclk)                    ((mclk) << 0)
76
77 #define SUN4I_I2S_TX_CNT_REG            0x28
78 #define SUN4I_I2S_RX_CNT_REG            0x2c
79
80 #define SUN4I_I2S_TX_CHAN_SEL_REG       0x30
81 #define SUN4I_I2S_CHAN_SEL_MASK                 GENMASK(2, 0)
82 #define SUN4I_I2S_CHAN_SEL(num_chan)            (((num_chan) - 1) << 0)
83
84 #define SUN4I_I2S_TX_CHAN_MAP_REG       0x34
85 #define SUN4I_I2S_TX_CHAN_MAP(chan, sample)     ((sample) << (chan << 2))
86
87 #define SUN4I_I2S_RX_CHAN_SEL_REG       0x38
88 #define SUN4I_I2S_RX_CHAN_MAP_REG       0x3c
89
90 /* Defines required for sun8i-h3 support */
91 #define SUN8I_I2S_CTRL_BCLK_OUT                 BIT(18)
92 #define SUN8I_I2S_CTRL_LRCK_OUT                 BIT(17)
93
94 #define SUN8I_I2S_CTRL_MODE_MASK                GENMASK(5, 4)
95 #define SUN8I_I2S_CTRL_MODE_RIGHT               (2 << 4)
96 #define SUN8I_I2S_CTRL_MODE_LEFT                (1 << 4)
97 #define SUN8I_I2S_CTRL_MODE_PCM                 (0 << 4)
98
99 #define SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK      BIT(19)
100 #define SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED          (1 << 19)
101 #define SUN8I_I2S_FMT0_LRCLK_POLARITY_NORMAL            (0 << 19)
102 #define SUN8I_I2S_FMT0_LRCK_PERIOD_MASK         GENMASK(17, 8)
103 #define SUN8I_I2S_FMT0_LRCK_PERIOD(period)      ((period - 1) << 8)
104 #define SUN8I_I2S_FMT0_BCLK_POLARITY_MASK       BIT(7)
105 #define SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED           (1 << 7)
106 #define SUN8I_I2S_FMT0_BCLK_POLARITY_NORMAL             (0 << 7)
107
108 #define SUN8I_I2S_INT_STA_REG           0x0c
109 #define SUN8I_I2S_FIFO_TX_REG           0x20
110
111 #define SUN8I_I2S_CHAN_CFG_REG          0x30
112 #define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK     GENMASK(6, 4)
113 #define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(chan)    ((chan - 1) << 4)
114 #define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK     GENMASK(2, 0)
115 #define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(chan)    (chan - 1)
116
117 #define SUN8I_I2S_TX_CHAN_MAP_REG       0x44
118 #define SUN8I_I2S_TX_CHAN_SEL_REG       0x34
119 #define SUN8I_I2S_TX_CHAN_OFFSET_MASK           GENMASK(13, 12)
120 #define SUN8I_I2S_TX_CHAN_OFFSET(offset)        (offset << 12)
121 #define SUN8I_I2S_TX_CHAN_EN_MASK               GENMASK(11, 4)
122 #define SUN8I_I2S_TX_CHAN_EN(num_chan)          (((1 << num_chan) - 1) << 4)
123
124 #define SUN8I_I2S_RX_CHAN_SEL_REG       0x54
125 #define SUN8I_I2S_RX_CHAN_MAP_REG       0x58
126
127 struct sun4i_i2s;
128
129 /**
130  * struct sun4i_i2s_quirks - Differences between SoC variants.
131  *
132  * @has_reset: SoC needs reset deasserted.
133  * @has_fmt_set_lrck_period: SoC requires lrclk period to be set.
134  * @reg_offset_txdata: offset of the tx fifo.
135  * @sun4i_i2s_regmap: regmap config to use.
136  * @field_clkdiv_mclk_en: regmap field to enable mclk output.
137  * @field_fmt_wss: regmap field to set word select size.
138  * @field_fmt_sr: regmap field to set sample resolution.
139  */
140 struct sun4i_i2s_quirks {
141         bool                            has_reset;
142         bool                            has_fmt_set_lrck_period;
143         unsigned int                    reg_offset_txdata;      /* TX FIFO */
144         const struct regmap_config      *sun4i_i2s_regmap;
145
146         /* Register fields for i2s */
147         struct reg_field                field_clkdiv_mclk_en;
148         struct reg_field                field_fmt_wss;
149         struct reg_field                field_fmt_sr;
150
151         const struct sun4i_i2s_clk_div  *bclk_dividers;
152         unsigned int                    num_bclk_dividers;
153         const struct sun4i_i2s_clk_div  *mclk_dividers;
154         unsigned int                    num_mclk_dividers;
155
156         unsigned long (*get_bclk_parent_rate)(const struct sun4i_i2s *);
157         s8      (*get_sr)(const struct sun4i_i2s *, int);
158         s8      (*get_wss)(const struct sun4i_i2s *, int);
159         int     (*set_chan_cfg)(const struct sun4i_i2s *,
160                                 const struct snd_pcm_hw_params *);
161         int     (*set_fmt)(const struct sun4i_i2s *, unsigned int);
162 };
163
164 struct sun4i_i2s {
165         struct clk      *bus_clk;
166         struct clk      *mod_clk;
167         struct regmap   *regmap;
168         struct reset_control *rst;
169
170         unsigned int    mclk_freq;
171
172         struct snd_dmaengine_dai_dma_data       capture_dma_data;
173         struct snd_dmaengine_dai_dma_data       playback_dma_data;
174
175         /* Register fields for i2s */
176         struct regmap_field     *field_clkdiv_mclk_en;
177         struct regmap_field     *field_fmt_wss;
178         struct regmap_field     *field_fmt_sr;
179
180         const struct sun4i_i2s_quirks   *variant;
181 };
182
183 struct sun4i_i2s_clk_div {
184         u8      div;
185         u8      val;
186 };
187
188 static const struct sun4i_i2s_clk_div sun4i_i2s_bclk_div[] = {
189         { .div = 2, .val = 0 },
190         { .div = 4, .val = 1 },
191         { .div = 6, .val = 2 },
192         { .div = 8, .val = 3 },
193         { .div = 12, .val = 4 },
194         { .div = 16, .val = 5 },
195         /* TODO - extend divide ratio supported by newer SoCs */
196 };
197
198 static const struct sun4i_i2s_clk_div sun4i_i2s_mclk_div[] = {
199         { .div = 1, .val = 0 },
200         { .div = 2, .val = 1 },
201         { .div = 4, .val = 2 },
202         { .div = 6, .val = 3 },
203         { .div = 8, .val = 4 },
204         { .div = 12, .val = 5 },
205         { .div = 16, .val = 6 },
206         { .div = 24, .val = 7 },
207         /* TODO - extend divide ratio supported by newer SoCs */
208 };
209
210 static const struct sun4i_i2s_clk_div sun8i_i2s_clk_div[] = {
211         { .div = 1, .val = 1 },
212         { .div = 2, .val = 2 },
213         { .div = 4, .val = 3 },
214         { .div = 6, .val = 4 },
215         { .div = 8, .val = 5 },
216         { .div = 12, .val = 6 },
217         { .div = 16, .val = 7 },
218         { .div = 24, .val = 8 },
219         { .div = 32, .val = 9 },
220         { .div = 48, .val = 10 },
221         { .div = 64, .val = 11 },
222         { .div = 96, .val = 12 },
223         { .div = 128, .val = 13 },
224         { .div = 176, .val = 14 },
225         { .div = 192, .val = 15 },
226 };
227
228 static unsigned long sun4i_i2s_get_bclk_parent_rate(const struct sun4i_i2s *i2s)
229 {
230         return i2s->mclk_freq;
231 }
232
233 static unsigned long sun8i_i2s_get_bclk_parent_rate(const struct sun4i_i2s *i2s)
234 {
235         return clk_get_rate(i2s->mod_clk);
236 }
237
238 static int sun4i_i2s_get_bclk_div(struct sun4i_i2s *i2s,
239                                   unsigned long parent_rate,
240                                   unsigned int sampling_rate,
241                                   unsigned int word_size)
242 {
243         const struct sun4i_i2s_clk_div *dividers = i2s->variant->bclk_dividers;
244         int div = parent_rate / sampling_rate / word_size / 2;
245         int i;
246
247         for (i = 0; i < i2s->variant->num_bclk_dividers; i++) {
248                 const struct sun4i_i2s_clk_div *bdiv = &dividers[i];
249
250                 if (bdiv->div == div)
251                         return bdiv->val;
252         }
253
254         return -EINVAL;
255 }
256
257 static int sun4i_i2s_get_mclk_div(struct sun4i_i2s *i2s,
258                                   unsigned long parent_rate,
259                                   unsigned long mclk_rate)
260 {
261         const struct sun4i_i2s_clk_div *dividers = i2s->variant->mclk_dividers;
262         int div = parent_rate / mclk_rate;
263         int i;
264
265         for (i = 0; i < i2s->variant->num_mclk_dividers; i++) {
266                 const struct sun4i_i2s_clk_div *mdiv = &dividers[i];
267
268                 if (mdiv->div == div)
269                         return mdiv->val;
270         }
271
272         return -EINVAL;
273 }
274
275 static int sun4i_i2s_oversample_rates[] = { 128, 192, 256, 384, 512, 768 };
276 static bool sun4i_i2s_oversample_is_valid(unsigned int oversample)
277 {
278         int i;
279
280         for (i = 0; i < ARRAY_SIZE(sun4i_i2s_oversample_rates); i++)
281                 if (sun4i_i2s_oversample_rates[i] == oversample)
282                         return true;
283
284         return false;
285 }
286
287 static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai,
288                                   unsigned int rate,
289                                   unsigned int word_size)
290 {
291         struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
292         unsigned int oversample_rate, clk_rate, bclk_parent_rate;
293         int bclk_div, mclk_div;
294         int ret;
295
296         switch (rate) {
297         case 176400:
298         case 88200:
299         case 44100:
300         case 22050:
301         case 11025:
302                 clk_rate = 22579200;
303                 break;
304
305         case 192000:
306         case 128000:
307         case 96000:
308         case 64000:
309         case 48000:
310         case 32000:
311         case 24000:
312         case 16000:
313         case 12000:
314         case 8000:
315                 clk_rate = 24576000;
316                 break;
317
318         default:
319                 dev_err(dai->dev, "Unsupported sample rate: %u\n", rate);
320                 return -EINVAL;
321         }
322
323         ret = clk_set_rate(i2s->mod_clk, clk_rate);
324         if (ret)
325                 return ret;
326
327         oversample_rate = i2s->mclk_freq / rate;
328         if (!sun4i_i2s_oversample_is_valid(oversample_rate)) {
329                 dev_err(dai->dev, "Unsupported oversample rate: %d\n",
330                         oversample_rate);
331                 return -EINVAL;
332         }
333
334         bclk_parent_rate = i2s->variant->get_bclk_parent_rate(i2s);
335         bclk_div = sun4i_i2s_get_bclk_div(i2s, bclk_parent_rate,
336                                           rate, word_size);
337         if (bclk_div < 0) {
338                 dev_err(dai->dev, "Unsupported BCLK divider: %d\n", bclk_div);
339                 return -EINVAL;
340         }
341
342         mclk_div = sun4i_i2s_get_mclk_div(i2s, clk_rate, i2s->mclk_freq);
343         if (mclk_div < 0) {
344                 dev_err(dai->dev, "Unsupported MCLK divider: %d\n", mclk_div);
345                 return -EINVAL;
346         }
347
348         regmap_write(i2s->regmap, SUN4I_I2S_CLK_DIV_REG,
349                      SUN4I_I2S_CLK_DIV_BCLK(bclk_div) |
350                      SUN4I_I2S_CLK_DIV_MCLK(mclk_div));
351
352         regmap_field_write(i2s->field_clkdiv_mclk_en, 1);
353
354         /* Set sync period */
355         if (i2s->variant->has_fmt_set_lrck_period)
356                 regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG,
357                                    SUN8I_I2S_FMT0_LRCK_PERIOD_MASK,
358                                    SUN8I_I2S_FMT0_LRCK_PERIOD(32));
359
360         return 0;
361 }
362
363 static s8 sun4i_i2s_get_sr(const struct sun4i_i2s *i2s, int width)
364 {
365         if (width < 16 || width > 24)
366                 return -EINVAL;
367
368         if (width % 4)
369                 return -EINVAL;
370
371         return (width - 16) / 4;
372 }
373
374 static s8 sun4i_i2s_get_wss(const struct sun4i_i2s *i2s, int width)
375 {
376         if (width < 16 || width > 32)
377                 return -EINVAL;
378
379         if (width % 4)
380                 return -EINVAL;
381
382         return (width - 16) / 4;
383 }
384
385 static s8 sun8i_i2s_get_sr_wss(const struct sun4i_i2s *i2s, int width)
386 {
387         if (width % 4)
388                 return -EINVAL;
389
390         if (width < 8 || width > 32)
391                 return -EINVAL;
392
393         return (width - 8) / 4 + 1;
394 }
395
396 static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
397                                   const struct snd_pcm_hw_params *params)
398 {
399         unsigned int channels = params_channels(params);
400
401         if (channels != 2)
402                 return -EINVAL;
403
404         /* Map the channels for playback and capture */
405         regmap_write(i2s->regmap, SUN4I_I2S_TX_CHAN_MAP_REG, 0x76543210);
406         regmap_write(i2s->regmap, SUN4I_I2S_RX_CHAN_MAP_REG, 0x00003210);
407
408         /* Configure the channels */
409         regmap_update_bits(i2s->regmap, SUN4I_I2S_TX_CHAN_SEL_REG,
410                            SUN4I_I2S_CHAN_SEL_MASK,
411                            SUN4I_I2S_CHAN_SEL(channels));
412         regmap_update_bits(i2s->regmap, SUN4I_I2S_RX_CHAN_SEL_REG,
413                            SUN4I_I2S_CHAN_SEL_MASK,
414                            SUN4I_I2S_CHAN_SEL(channels));
415
416         return 0;
417 }
418
419 static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
420                                   const struct snd_pcm_hw_params *params)
421 {
422         unsigned int channels = params_channels(params);
423
424         if (channels != 2)
425                 return -EINVAL;
426
427         /* Map the channels for playback and capture */
428         regmap_write(i2s->regmap, SUN8I_I2S_TX_CHAN_MAP_REG, 0x76543210);
429         regmap_write(i2s->regmap, SUN8I_I2S_RX_CHAN_MAP_REG, 0x76543210);
430
431         /* Configure the channels */
432         regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG,
433                            SUN4I_I2S_CHAN_SEL_MASK,
434                            SUN4I_I2S_CHAN_SEL(channels));
435
436         regmap_update_bits(i2s->regmap, SUN8I_I2S_RX_CHAN_SEL_REG,
437                            SUN4I_I2S_CHAN_SEL_MASK,
438                            SUN4I_I2S_CHAN_SEL(channels));
439
440         regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG,
441                            SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK,
442                            SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(channels));
443         regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG,
444                            SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK,
445                            SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(channels));
446
447         regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG,
448                            SUN8I_I2S_TX_CHAN_EN_MASK,
449                            SUN8I_I2S_TX_CHAN_EN(channels));
450
451         return 0;
452 }
453
454 static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream,
455                                struct snd_pcm_hw_params *params,
456                                struct snd_soc_dai *dai)
457 {
458         struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
459         int ret, sr, wss;
460         u32 width;
461
462         ret = i2s->variant->set_chan_cfg(i2s, params);
463         if (ret < 0) {
464                 dev_err(dai->dev, "Invalid channel configuration\n");
465                 return ret;
466         }
467
468         switch (params_physical_width(params)) {
469         case 16:
470                 width = DMA_SLAVE_BUSWIDTH_2_BYTES;
471                 break;
472         default:
473                 dev_err(dai->dev, "Unsupported physical sample width: %d\n",
474                         params_physical_width(params));
475                 return -EINVAL;
476         }
477         i2s->playback_dma_data.addr_width = width;
478
479         sr = i2s->variant->get_sr(i2s, params_width(params));
480         if (sr < 0)
481                 return -EINVAL;
482
483         wss = i2s->variant->get_wss(i2s, params_width(params));
484         if (wss < 0)
485                 return -EINVAL;
486
487         regmap_field_write(i2s->field_fmt_wss, wss);
488         regmap_field_write(i2s->field_fmt_sr, sr);
489
490         return sun4i_i2s_set_clk_rate(dai, params_rate(params),
491                                       params_width(params));
492 }
493
494 static int sun4i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
495                                  unsigned int fmt)
496 {
497         u32 val;
498
499         /* DAI clock polarity */
500         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
501         case SND_SOC_DAIFMT_IB_IF:
502                 /* Invert both clocks */
503                 val = SUN4I_I2S_FMT0_BCLK_POLARITY_INVERTED |
504                       SUN4I_I2S_FMT0_LRCLK_POLARITY_INVERTED;
505                 break;
506         case SND_SOC_DAIFMT_IB_NF:
507                 /* Invert bit clock */
508                 val = SUN4I_I2S_FMT0_BCLK_POLARITY_INVERTED;
509                 break;
510         case SND_SOC_DAIFMT_NB_IF:
511                 /* Invert frame clock */
512                 val = SUN4I_I2S_FMT0_LRCLK_POLARITY_INVERTED;
513                 break;
514         case SND_SOC_DAIFMT_NB_NF:
515                 val = 0;
516                 break;
517         default:
518                 return -EINVAL;
519         }
520
521         regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG,
522                            SUN4I_I2S_FMT0_LRCLK_POLARITY_MASK |
523                            SUN4I_I2S_FMT0_BCLK_POLARITY_MASK,
524                            val);
525
526         /* DAI Mode */
527         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
528         case SND_SOC_DAIFMT_I2S:
529                 val = SUN4I_I2S_FMT0_FMT_I2S;
530                 break;
531
532         case SND_SOC_DAIFMT_LEFT_J:
533                 val = SUN4I_I2S_FMT0_FMT_LEFT_J;
534                 break;
535
536         case SND_SOC_DAIFMT_RIGHT_J:
537                 val = SUN4I_I2S_FMT0_FMT_RIGHT_J;
538                 break;
539
540         default:
541                 return -EINVAL;
542         }
543
544         regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG,
545                            SUN4I_I2S_FMT0_FMT_MASK, val);
546
547         /* DAI clock master masks */
548         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
549         case SND_SOC_DAIFMT_CBS_CFS:
550                 /* BCLK and LRCLK master */
551                 val = SUN4I_I2S_CTRL_MODE_MASTER;
552                 break;
553
554         case SND_SOC_DAIFMT_CBM_CFM:
555                 /* BCLK and LRCLK slave */
556                 val = SUN4I_I2S_CTRL_MODE_SLAVE;
557                 break;
558
559         default:
560                 return -EINVAL;
561         }
562         regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
563                            SUN4I_I2S_CTRL_MODE_MASK, val);
564         return 0;
565 }
566
567 static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
568                                  unsigned int fmt)
569 {
570         u32 mode, val;
571         u8 offset;
572
573         /* DAI clock polarity */
574         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
575         case SND_SOC_DAIFMT_IB_IF:
576                 /* Invert both clocks */
577                 val = SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED |
578                       SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED;
579                 break;
580         case SND_SOC_DAIFMT_IB_NF:
581                 /* Invert bit clock */
582                 val = SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED;
583                 break;
584         case SND_SOC_DAIFMT_NB_IF:
585                 /* Invert frame clock */
586                 val = SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED;
587                 break;
588         case SND_SOC_DAIFMT_NB_NF:
589                 val = 0;
590                 break;
591         default:
592                 return -EINVAL;
593         }
594
595         regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG,
596                            SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK |
597                            SUN8I_I2S_FMT0_BCLK_POLARITY_MASK,
598                            val);
599
600         /* DAI Mode */
601         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
602         case SND_SOC_DAIFMT_I2S:
603                 mode = SUN8I_I2S_CTRL_MODE_LEFT;
604                 offset = 1;
605                 break;
606
607         case SND_SOC_DAIFMT_LEFT_J:
608                 mode = SUN8I_I2S_CTRL_MODE_LEFT;
609                 offset = 0;
610                 break;
611
612         case SND_SOC_DAIFMT_RIGHT_J:
613                 mode = SUN8I_I2S_CTRL_MODE_RIGHT;
614                 offset = 0;
615                 break;
616
617         default:
618                 return -EINVAL;
619         }
620
621         regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
622                            SUN8I_I2S_CTRL_MODE_MASK, mode);
623         regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG,
624                            SUN8I_I2S_TX_CHAN_OFFSET_MASK,
625                            SUN8I_I2S_TX_CHAN_OFFSET(offset));
626         regmap_update_bits(i2s->regmap, SUN8I_I2S_RX_CHAN_SEL_REG,
627                            SUN8I_I2S_TX_CHAN_OFFSET_MASK,
628                            SUN8I_I2S_TX_CHAN_OFFSET(offset));
629
630         /* DAI clock master masks */
631         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
632         case SND_SOC_DAIFMT_CBS_CFS:
633                 /* BCLK and LRCLK master */
634                 val = SUN8I_I2S_CTRL_BCLK_OUT | SUN8I_I2S_CTRL_LRCK_OUT;
635                 break;
636
637         case SND_SOC_DAIFMT_CBM_CFM:
638                 /* BCLK and LRCLK slave */
639                 val = 0;
640                 break;
641
642         default:
643                 return -EINVAL;
644         }
645
646         regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
647                            SUN8I_I2S_CTRL_BCLK_OUT | SUN8I_I2S_CTRL_LRCK_OUT,
648                            val);
649
650         return 0;
651 }
652
653 static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
654 {
655         struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
656         int ret;
657
658         ret = i2s->variant->set_fmt(i2s, fmt);
659         if (ret) {
660                 dev_err(dai->dev, "Unsupported format configuration\n");
661                 return ret;
662         }
663
664         /* Set significant bits in our FIFOs */
665         regmap_update_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG,
666                            SUN4I_I2S_FIFO_CTRL_TX_MODE_MASK |
667                            SUN4I_I2S_FIFO_CTRL_RX_MODE_MASK,
668                            SUN4I_I2S_FIFO_CTRL_TX_MODE(1) |
669                            SUN4I_I2S_FIFO_CTRL_RX_MODE(1));
670         return 0;
671 }
672
673 static void sun4i_i2s_start_capture(struct sun4i_i2s *i2s)
674 {
675         /* Flush RX FIFO */
676         regmap_update_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG,
677                            SUN4I_I2S_FIFO_CTRL_FLUSH_RX,
678                            SUN4I_I2S_FIFO_CTRL_FLUSH_RX);
679
680         /* Clear RX counter */
681         regmap_write(i2s->regmap, SUN4I_I2S_RX_CNT_REG, 0);
682
683         /* Enable RX Block */
684         regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
685                            SUN4I_I2S_CTRL_RX_EN,
686                            SUN4I_I2S_CTRL_RX_EN);
687
688         /* Enable RX DRQ */
689         regmap_update_bits(i2s->regmap, SUN4I_I2S_DMA_INT_CTRL_REG,
690                            SUN4I_I2S_DMA_INT_CTRL_RX_DRQ_EN,
691                            SUN4I_I2S_DMA_INT_CTRL_RX_DRQ_EN);
692 }
693
694 static void sun4i_i2s_start_playback(struct sun4i_i2s *i2s)
695 {
696         /* Flush TX FIFO */
697         regmap_update_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG,
698                            SUN4I_I2S_FIFO_CTRL_FLUSH_TX,
699                            SUN4I_I2S_FIFO_CTRL_FLUSH_TX);
700
701         /* Clear TX counter */
702         regmap_write(i2s->regmap, SUN4I_I2S_TX_CNT_REG, 0);
703
704         /* Enable TX Block */
705         regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
706                            SUN4I_I2S_CTRL_TX_EN,
707                            SUN4I_I2S_CTRL_TX_EN);
708
709         /* Enable TX DRQ */
710         regmap_update_bits(i2s->regmap, SUN4I_I2S_DMA_INT_CTRL_REG,
711                            SUN4I_I2S_DMA_INT_CTRL_TX_DRQ_EN,
712                            SUN4I_I2S_DMA_INT_CTRL_TX_DRQ_EN);
713 }
714
715 static void sun4i_i2s_stop_capture(struct sun4i_i2s *i2s)
716 {
717         /* Disable RX Block */
718         regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
719                            SUN4I_I2S_CTRL_RX_EN,
720                            0);
721
722         /* Disable RX DRQ */
723         regmap_update_bits(i2s->regmap, SUN4I_I2S_DMA_INT_CTRL_REG,
724                            SUN4I_I2S_DMA_INT_CTRL_RX_DRQ_EN,
725                            0);
726 }
727
728 static void sun4i_i2s_stop_playback(struct sun4i_i2s *i2s)
729 {
730         /* Disable TX Block */
731         regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
732                            SUN4I_I2S_CTRL_TX_EN,
733                            0);
734
735         /* Disable TX DRQ */
736         regmap_update_bits(i2s->regmap, SUN4I_I2S_DMA_INT_CTRL_REG,
737                            SUN4I_I2S_DMA_INT_CTRL_TX_DRQ_EN,
738                            0);
739 }
740
741 static int sun4i_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
742                              struct snd_soc_dai *dai)
743 {
744         struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
745
746         switch (cmd) {
747         case SNDRV_PCM_TRIGGER_START:
748         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
749         case SNDRV_PCM_TRIGGER_RESUME:
750                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
751                         sun4i_i2s_start_playback(i2s);
752                 else
753                         sun4i_i2s_start_capture(i2s);
754                 break;
755
756         case SNDRV_PCM_TRIGGER_STOP:
757         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
758         case SNDRV_PCM_TRIGGER_SUSPEND:
759                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
760                         sun4i_i2s_stop_playback(i2s);
761                 else
762                         sun4i_i2s_stop_capture(i2s);
763                 break;
764
765         default:
766                 return -EINVAL;
767         }
768
769         return 0;
770 }
771
772 static int sun4i_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id,
773                                 unsigned int freq, int dir)
774 {
775         struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
776
777         if (clk_id != 0)
778                 return -EINVAL;
779
780         i2s->mclk_freq = freq;
781
782         return 0;
783 }
784
785 static const struct snd_soc_dai_ops sun4i_i2s_dai_ops = {
786         .hw_params      = sun4i_i2s_hw_params,
787         .set_fmt        = sun4i_i2s_set_fmt,
788         .set_sysclk     = sun4i_i2s_set_sysclk,
789         .trigger        = sun4i_i2s_trigger,
790 };
791
792 static int sun4i_i2s_dai_probe(struct snd_soc_dai *dai)
793 {
794         struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
795
796         snd_soc_dai_init_dma_data(dai,
797                                   &i2s->playback_dma_data,
798                                   &i2s->capture_dma_data);
799
800         snd_soc_dai_set_drvdata(dai, i2s);
801
802         return 0;
803 }
804
805 static struct snd_soc_dai_driver sun4i_i2s_dai = {
806         .probe = sun4i_i2s_dai_probe,
807         .capture = {
808                 .stream_name = "Capture",
809                 .channels_min = 2,
810                 .channels_max = 2,
811                 .rates = SNDRV_PCM_RATE_8000_192000,
812                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
813         },
814         .playback = {
815                 .stream_name = "Playback",
816                 .channels_min = 2,
817                 .channels_max = 2,
818                 .rates = SNDRV_PCM_RATE_8000_192000,
819                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
820         },
821         .ops = &sun4i_i2s_dai_ops,
822         .symmetric_rates = 1,
823 };
824
825 static const struct snd_soc_component_driver sun4i_i2s_component = {
826         .name   = "sun4i-dai",
827 };
828
829 static bool sun4i_i2s_rd_reg(struct device *dev, unsigned int reg)
830 {
831         switch (reg) {
832         case SUN4I_I2S_FIFO_TX_REG:
833                 return false;
834
835         default:
836                 return true;
837         }
838 }
839
840 static bool sun4i_i2s_wr_reg(struct device *dev, unsigned int reg)
841 {
842         switch (reg) {
843         case SUN4I_I2S_FIFO_RX_REG:
844         case SUN4I_I2S_FIFO_STA_REG:
845                 return false;
846
847         default:
848                 return true;
849         }
850 }
851
852 static bool sun4i_i2s_volatile_reg(struct device *dev, unsigned int reg)
853 {
854         switch (reg) {
855         case SUN4I_I2S_FIFO_RX_REG:
856         case SUN4I_I2S_INT_STA_REG:
857         case SUN4I_I2S_RX_CNT_REG:
858         case SUN4I_I2S_TX_CNT_REG:
859                 return true;
860
861         default:
862                 return false;
863         }
864 }
865
866 static bool sun8i_i2s_rd_reg(struct device *dev, unsigned int reg)
867 {
868         switch (reg) {
869         case SUN8I_I2S_FIFO_TX_REG:
870                 return false;
871
872         default:
873                 return true;
874         }
875 }
876
877 static bool sun8i_i2s_volatile_reg(struct device *dev, unsigned int reg)
878 {
879         if (reg == SUN8I_I2S_INT_STA_REG)
880                 return true;
881         if (reg == SUN8I_I2S_FIFO_TX_REG)
882                 return false;
883
884         return sun4i_i2s_volatile_reg(dev, reg);
885 }
886
887 static const struct reg_default sun4i_i2s_reg_defaults[] = {
888         { SUN4I_I2S_CTRL_REG, 0x00000000 },
889         { SUN4I_I2S_FMT0_REG, 0x0000000c },
890         { SUN4I_I2S_FMT1_REG, 0x00004020 },
891         { SUN4I_I2S_FIFO_CTRL_REG, 0x000400f0 },
892         { SUN4I_I2S_DMA_INT_CTRL_REG, 0x00000000 },
893         { SUN4I_I2S_CLK_DIV_REG, 0x00000000 },
894         { SUN4I_I2S_TX_CHAN_SEL_REG, 0x00000001 },
895         { SUN4I_I2S_TX_CHAN_MAP_REG, 0x76543210 },
896         { SUN4I_I2S_RX_CHAN_SEL_REG, 0x00000001 },
897         { SUN4I_I2S_RX_CHAN_MAP_REG, 0x00003210 },
898 };
899
900 static const struct reg_default sun8i_i2s_reg_defaults[] = {
901         { SUN4I_I2S_CTRL_REG, 0x00060000 },
902         { SUN4I_I2S_FMT0_REG, 0x00000033 },
903         { SUN4I_I2S_FMT1_REG, 0x00000030 },
904         { SUN4I_I2S_FIFO_CTRL_REG, 0x000400f0 },
905         { SUN4I_I2S_DMA_INT_CTRL_REG, 0x00000000 },
906         { SUN4I_I2S_CLK_DIV_REG, 0x00000000 },
907         { SUN8I_I2S_CHAN_CFG_REG, 0x00000000 },
908         { SUN8I_I2S_TX_CHAN_SEL_REG, 0x00000000 },
909         { SUN8I_I2S_TX_CHAN_MAP_REG, 0x00000000 },
910         { SUN8I_I2S_RX_CHAN_SEL_REG, 0x00000000 },
911         { SUN8I_I2S_RX_CHAN_MAP_REG, 0x00000000 },
912 };
913
914 static const struct regmap_config sun4i_i2s_regmap_config = {
915         .reg_bits       = 32,
916         .reg_stride     = 4,
917         .val_bits       = 32,
918         .max_register   = SUN4I_I2S_RX_CHAN_MAP_REG,
919
920         .cache_type     = REGCACHE_FLAT,
921         .reg_defaults   = sun4i_i2s_reg_defaults,
922         .num_reg_defaults       = ARRAY_SIZE(sun4i_i2s_reg_defaults),
923         .writeable_reg  = sun4i_i2s_wr_reg,
924         .readable_reg   = sun4i_i2s_rd_reg,
925         .volatile_reg   = sun4i_i2s_volatile_reg,
926 };
927
928 static const struct regmap_config sun8i_i2s_regmap_config = {
929         .reg_bits       = 32,
930         .reg_stride     = 4,
931         .val_bits       = 32,
932         .max_register   = SUN8I_I2S_RX_CHAN_MAP_REG,
933         .cache_type     = REGCACHE_FLAT,
934         .reg_defaults   = sun8i_i2s_reg_defaults,
935         .num_reg_defaults       = ARRAY_SIZE(sun8i_i2s_reg_defaults),
936         .writeable_reg  = sun4i_i2s_wr_reg,
937         .readable_reg   = sun8i_i2s_rd_reg,
938         .volatile_reg   = sun8i_i2s_volatile_reg,
939 };
940
941 static int sun4i_i2s_runtime_resume(struct device *dev)
942 {
943         struct sun4i_i2s *i2s = dev_get_drvdata(dev);
944         int ret;
945
946         ret = clk_prepare_enable(i2s->bus_clk);
947         if (ret) {
948                 dev_err(dev, "Failed to enable bus clock\n");
949                 return ret;
950         }
951
952         regcache_cache_only(i2s->regmap, false);
953         regcache_mark_dirty(i2s->regmap);
954
955         ret = regcache_sync(i2s->regmap);
956         if (ret) {
957                 dev_err(dev, "Failed to sync regmap cache\n");
958                 goto err_disable_clk;
959         }
960
961         /* Enable the whole hardware block */
962         regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
963                            SUN4I_I2S_CTRL_GL_EN, SUN4I_I2S_CTRL_GL_EN);
964
965         /* Enable the first output line */
966         regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
967                            SUN4I_I2S_CTRL_SDO_EN_MASK,
968                            SUN4I_I2S_CTRL_SDO_EN(0));
969
970         ret = clk_prepare_enable(i2s->mod_clk);
971         if (ret) {
972                 dev_err(dev, "Failed to enable module clock\n");
973                 goto err_disable_clk;
974         }
975
976         return 0;
977
978 err_disable_clk:
979         clk_disable_unprepare(i2s->bus_clk);
980         return ret;
981 }
982
983 static int sun4i_i2s_runtime_suspend(struct device *dev)
984 {
985         struct sun4i_i2s *i2s = dev_get_drvdata(dev);
986
987         clk_disable_unprepare(i2s->mod_clk);
988
989         /* Disable our output lines */
990         regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
991                            SUN4I_I2S_CTRL_SDO_EN_MASK, 0);
992
993         /* Disable the whole hardware block */
994         regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
995                            SUN4I_I2S_CTRL_GL_EN, 0);
996
997         regcache_cache_only(i2s->regmap, true);
998
999         clk_disable_unprepare(i2s->bus_clk);
1000
1001         return 0;
1002 }
1003
1004 static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = {
1005         .has_reset              = false,
1006         .reg_offset_txdata      = SUN4I_I2S_FIFO_TX_REG,
1007         .sun4i_i2s_regmap       = &sun4i_i2s_regmap_config,
1008         .field_clkdiv_mclk_en   = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7),
1009         .field_fmt_wss          = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3),
1010         .field_fmt_sr           = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
1011         .bclk_dividers          = sun4i_i2s_bclk_div,
1012         .num_bclk_dividers      = ARRAY_SIZE(sun4i_i2s_bclk_div),
1013         .mclk_dividers          = sun4i_i2s_mclk_div,
1014         .num_mclk_dividers      = ARRAY_SIZE(sun4i_i2s_mclk_div),
1015         .get_bclk_parent_rate   = sun4i_i2s_get_bclk_parent_rate,
1016         .get_sr                 = sun4i_i2s_get_sr,
1017         .get_wss                = sun4i_i2s_get_wss,
1018         .set_chan_cfg           = sun4i_i2s_set_chan_cfg,
1019         .set_fmt                = sun4i_i2s_set_soc_fmt,
1020 };
1021
1022 static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
1023         .has_reset              = true,
1024         .reg_offset_txdata      = SUN4I_I2S_FIFO_TX_REG,
1025         .sun4i_i2s_regmap       = &sun4i_i2s_regmap_config,
1026         .field_clkdiv_mclk_en   = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7),
1027         .field_fmt_wss          = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3),
1028         .field_fmt_sr           = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
1029         .bclk_dividers          = sun4i_i2s_bclk_div,
1030         .num_bclk_dividers      = ARRAY_SIZE(sun4i_i2s_bclk_div),
1031         .mclk_dividers          = sun4i_i2s_mclk_div,
1032         .num_mclk_dividers      = ARRAY_SIZE(sun4i_i2s_mclk_div),
1033         .get_bclk_parent_rate   = sun4i_i2s_get_bclk_parent_rate,
1034         .get_sr                 = sun4i_i2s_get_sr,
1035         .get_wss                = sun4i_i2s_get_wss,
1036         .set_chan_cfg           = sun4i_i2s_set_chan_cfg,
1037         .set_fmt                = sun4i_i2s_set_soc_fmt,
1038 };
1039
1040 static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = {
1041         .has_reset              = true,
1042         .reg_offset_txdata      = SUN8I_I2S_FIFO_TX_REG,
1043         .sun4i_i2s_regmap       = &sun4i_i2s_regmap_config,
1044         .field_clkdiv_mclk_en   = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7),
1045         .field_fmt_wss          = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3),
1046         .field_fmt_sr           = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
1047         .bclk_dividers          = sun8i_i2s_clk_div,
1048         .num_bclk_dividers      = ARRAY_SIZE(sun8i_i2s_clk_div),
1049         .mclk_dividers          = sun8i_i2s_clk_div,
1050         .num_mclk_dividers      = ARRAY_SIZE(sun8i_i2s_clk_div),
1051         .get_bclk_parent_rate   = sun8i_i2s_get_bclk_parent_rate,
1052         .get_sr                 = sun8i_i2s_get_sr_wss,
1053         .get_wss                = sun8i_i2s_get_sr_wss,
1054         .set_chan_cfg           = sun8i_i2s_set_chan_cfg,
1055         .set_fmt                = sun8i_i2s_set_soc_fmt,
1056 };
1057
1058 static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = {
1059         .has_reset              = true,
1060         .reg_offset_txdata      = SUN8I_I2S_FIFO_TX_REG,
1061         .sun4i_i2s_regmap       = &sun8i_i2s_regmap_config,
1062         .has_fmt_set_lrck_period = true,
1063         .field_clkdiv_mclk_en   = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8),
1064         .field_fmt_wss          = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 2),
1065         .field_fmt_sr           = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 6),
1066         .bclk_dividers          = sun8i_i2s_clk_div,
1067         .num_bclk_dividers      = ARRAY_SIZE(sun8i_i2s_clk_div),
1068         .mclk_dividers          = sun8i_i2s_clk_div,
1069         .num_mclk_dividers      = ARRAY_SIZE(sun8i_i2s_clk_div),
1070         .get_bclk_parent_rate   = sun8i_i2s_get_bclk_parent_rate,
1071         .get_sr                 = sun8i_i2s_get_sr_wss,
1072         .get_wss                = sun8i_i2s_get_sr_wss,
1073         .set_chan_cfg           = sun8i_i2s_set_chan_cfg,
1074         .set_fmt                = sun8i_i2s_set_soc_fmt,
1075 };
1076
1077 static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = {
1078         .has_reset              = true,
1079         .reg_offset_txdata      = SUN8I_I2S_FIFO_TX_REG,
1080         .sun4i_i2s_regmap       = &sun4i_i2s_regmap_config,
1081         .field_clkdiv_mclk_en   = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7),
1082         .field_fmt_wss          = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3),
1083         .field_fmt_sr           = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
1084         .bclk_dividers          = sun4i_i2s_bclk_div,
1085         .num_bclk_dividers      = ARRAY_SIZE(sun4i_i2s_bclk_div),
1086         .mclk_dividers          = sun4i_i2s_mclk_div,
1087         .num_mclk_dividers      = ARRAY_SIZE(sun4i_i2s_mclk_div),
1088         .get_bclk_parent_rate   = sun4i_i2s_get_bclk_parent_rate,
1089         .get_sr                 = sun4i_i2s_get_sr,
1090         .get_wss                = sun4i_i2s_get_wss,
1091         .set_chan_cfg           = sun4i_i2s_set_chan_cfg,
1092         .set_fmt                = sun4i_i2s_set_soc_fmt,
1093 };
1094
1095 static int sun4i_i2s_init_regmap_fields(struct device *dev,
1096                                         struct sun4i_i2s *i2s)
1097 {
1098         i2s->field_clkdiv_mclk_en =
1099                 devm_regmap_field_alloc(dev, i2s->regmap,
1100                                         i2s->variant->field_clkdiv_mclk_en);
1101         if (IS_ERR(i2s->field_clkdiv_mclk_en))
1102                 return PTR_ERR(i2s->field_clkdiv_mclk_en);
1103
1104         i2s->field_fmt_wss =
1105                         devm_regmap_field_alloc(dev, i2s->regmap,
1106                                                 i2s->variant->field_fmt_wss);
1107         if (IS_ERR(i2s->field_fmt_wss))
1108                 return PTR_ERR(i2s->field_fmt_wss);
1109
1110         i2s->field_fmt_sr =
1111                         devm_regmap_field_alloc(dev, i2s->regmap,
1112                                                 i2s->variant->field_fmt_sr);
1113         if (IS_ERR(i2s->field_fmt_sr))
1114                 return PTR_ERR(i2s->field_fmt_sr);
1115
1116         return 0;
1117 }
1118
1119 static int sun4i_i2s_probe(struct platform_device *pdev)
1120 {
1121         struct sun4i_i2s *i2s;
1122         struct resource *res;
1123         void __iomem *regs;
1124         int irq, ret;
1125
1126         i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
1127         if (!i2s)
1128                 return -ENOMEM;
1129         platform_set_drvdata(pdev, i2s);
1130
1131         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1132         regs = devm_ioremap_resource(&pdev->dev, res);
1133         if (IS_ERR(regs))
1134                 return PTR_ERR(regs);
1135
1136         irq = platform_get_irq(pdev, 0);
1137         if (irq < 0)
1138                 return irq;
1139
1140         i2s->variant = of_device_get_match_data(&pdev->dev);
1141         if (!i2s->variant) {
1142                 dev_err(&pdev->dev, "Failed to determine the quirks to use\n");
1143                 return -ENODEV;
1144         }
1145
1146         i2s->bus_clk = devm_clk_get(&pdev->dev, "apb");
1147         if (IS_ERR(i2s->bus_clk)) {
1148                 dev_err(&pdev->dev, "Can't get our bus clock\n");
1149                 return PTR_ERR(i2s->bus_clk);
1150         }
1151
1152         i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
1153                                             i2s->variant->sun4i_i2s_regmap);
1154         if (IS_ERR(i2s->regmap)) {
1155                 dev_err(&pdev->dev, "Regmap initialisation failed\n");
1156                 return PTR_ERR(i2s->regmap);
1157         }
1158
1159         i2s->mod_clk = devm_clk_get(&pdev->dev, "mod");
1160         if (IS_ERR(i2s->mod_clk)) {
1161                 dev_err(&pdev->dev, "Can't get our mod clock\n");
1162                 return PTR_ERR(i2s->mod_clk);
1163         }
1164
1165         if (i2s->variant->has_reset) {
1166                 i2s->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL);
1167                 if (IS_ERR(i2s->rst)) {
1168                         dev_err(&pdev->dev, "Failed to get reset control\n");
1169                         return PTR_ERR(i2s->rst);
1170                 }
1171         }
1172
1173         if (!IS_ERR(i2s->rst)) {
1174                 ret = reset_control_deassert(i2s->rst);
1175                 if (ret) {
1176                         dev_err(&pdev->dev,
1177                                 "Failed to deassert the reset control\n");
1178                         return -EINVAL;
1179                 }
1180         }
1181
1182         i2s->playback_dma_data.addr = res->start +
1183                                         i2s->variant->reg_offset_txdata;
1184         i2s->playback_dma_data.maxburst = 8;
1185
1186         i2s->capture_dma_data.addr = res->start + SUN4I_I2S_FIFO_RX_REG;
1187         i2s->capture_dma_data.maxburst = 8;
1188
1189         pm_runtime_enable(&pdev->dev);
1190         if (!pm_runtime_enabled(&pdev->dev)) {
1191                 ret = sun4i_i2s_runtime_resume(&pdev->dev);
1192                 if (ret)
1193                         goto err_pm_disable;
1194         }
1195
1196         ret = sun4i_i2s_init_regmap_fields(&pdev->dev, i2s);
1197         if (ret) {
1198                 dev_err(&pdev->dev, "Could not initialise regmap fields\n");
1199                 goto err_suspend;
1200         }
1201
1202         ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
1203         if (ret) {
1204                 dev_err(&pdev->dev, "Could not register PCM\n");
1205                 goto err_suspend;
1206         }
1207
1208         ret = devm_snd_soc_register_component(&pdev->dev,
1209                                               &sun4i_i2s_component,
1210                                               &sun4i_i2s_dai, 1);
1211         if (ret) {
1212                 dev_err(&pdev->dev, "Could not register DAI\n");
1213                 goto err_suspend;
1214         }
1215
1216         return 0;
1217
1218 err_suspend:
1219         if (!pm_runtime_status_suspended(&pdev->dev))
1220                 sun4i_i2s_runtime_suspend(&pdev->dev);
1221 err_pm_disable:
1222         pm_runtime_disable(&pdev->dev);
1223         if (!IS_ERR(i2s->rst))
1224                 reset_control_assert(i2s->rst);
1225
1226         return ret;
1227 }
1228
1229 static int sun4i_i2s_remove(struct platform_device *pdev)
1230 {
1231         struct sun4i_i2s *i2s = dev_get_drvdata(&pdev->dev);
1232
1233         pm_runtime_disable(&pdev->dev);
1234         if (!pm_runtime_status_suspended(&pdev->dev))
1235                 sun4i_i2s_runtime_suspend(&pdev->dev);
1236
1237         if (!IS_ERR(i2s->rst))
1238                 reset_control_assert(i2s->rst);
1239
1240         return 0;
1241 }
1242
1243 static const struct of_device_id sun4i_i2s_match[] = {
1244         {
1245                 .compatible = "allwinner,sun4i-a10-i2s",
1246                 .data = &sun4i_a10_i2s_quirks,
1247         },
1248         {
1249                 .compatible = "allwinner,sun6i-a31-i2s",
1250                 .data = &sun6i_a31_i2s_quirks,
1251         },
1252         {
1253                 .compatible = "allwinner,sun8i-a83t-i2s",
1254                 .data = &sun8i_a83t_i2s_quirks,
1255         },
1256         {
1257                 .compatible = "allwinner,sun8i-h3-i2s",
1258                 .data = &sun8i_h3_i2s_quirks,
1259         },
1260         {
1261                 .compatible = "allwinner,sun50i-a64-codec-i2s",
1262                 .data = &sun50i_a64_codec_i2s_quirks,
1263         },
1264         {}
1265 };
1266 MODULE_DEVICE_TABLE(of, sun4i_i2s_match);
1267
1268 static const struct dev_pm_ops sun4i_i2s_pm_ops = {
1269         .runtime_resume         = sun4i_i2s_runtime_resume,
1270         .runtime_suspend        = sun4i_i2s_runtime_suspend,
1271 };
1272
1273 static struct platform_driver sun4i_i2s_driver = {
1274         .probe  = sun4i_i2s_probe,
1275         .remove = sun4i_i2s_remove,
1276         .driver = {
1277                 .name           = "sun4i-i2s",
1278                 .of_match_table = sun4i_i2s_match,
1279                 .pm             = &sun4i_i2s_pm_ops,
1280         },
1281 };
1282 module_platform_driver(sun4i_i2s_driver);
1283
1284 MODULE_AUTHOR("Andrea Venturi <be17068@iperbole.bo.it>");
1285 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
1286 MODULE_DESCRIPTION("Allwinner A10 I2S driver");
1287 MODULE_LICENSE("GPL");