source: src/linux/universal/linux-4.9/sound/soc/sunxi/sun4i-i2s.c @ 31859

Last change on this file since 31859 was 31859, checked in by brainslayer, 2 months ago

kernel update

File size: 18.3 KB
Line 
1/*
2 * Copyright (C) 2015 Andrea Venturi
3 * Andrea Venturi <be17068@iperbole.bo.it>
4 *
5 * Copyright (C) 2016 Maxime Ripard
6 * Maxime Ripard <maxime.ripard@free-electrons.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 */
13
14#include <linux/clk.h>
15#include <linux/dmaengine.h>
16#include <linux/module.h>
17#include <linux/of_device.h>
18#include <linux/platform_device.h>
19#include <linux/pm_runtime.h>
20#include <linux/regmap.h>
21#include <linux/reset.h>
22
23#include <sound/dmaengine_pcm.h>
24#include <sound/pcm_params.h>
25#include <sound/soc.h>
26#include <sound/soc-dai.h>
27
28#define SUN4I_I2S_CTRL_REG              0x00
29#define SUN4I_I2S_CTRL_SDO_EN_MASK              GENMASK(11, 8)
30#define SUN4I_I2S_CTRL_SDO_EN(sdo)                      BIT(8 + (sdo))
31#define SUN4I_I2S_CTRL_MODE_MASK                BIT(5)
32#define SUN4I_I2S_CTRL_MODE_SLAVE                       (1 << 5)
33#define SUN4I_I2S_CTRL_MODE_MASTER                      (0 << 5)
34#define SUN4I_I2S_CTRL_TX_EN                    BIT(2)
35#define SUN4I_I2S_CTRL_RX_EN                    BIT(1)
36#define SUN4I_I2S_CTRL_GL_EN                    BIT(0)
37
38#define SUN4I_I2S_FMT0_REG              0x04
39#define SUN4I_I2S_FMT0_LRCLK_POLARITY_MASK      BIT(7)
40#define SUN4I_I2S_FMT0_LRCLK_POLARITY_INVERTED          (1 << 7)
41#define SUN4I_I2S_FMT0_LRCLK_POLARITY_NORMAL            (0 << 7)
42#define SUN4I_I2S_FMT0_BCLK_POLARITY_MASK       BIT(6)
43#define SUN4I_I2S_FMT0_BCLK_POLARITY_INVERTED           (1 << 6)
44#define SUN4I_I2S_FMT0_BCLK_POLARITY_NORMAL             (0 << 6)
45#define SUN4I_I2S_FMT0_SR_MASK                  GENMASK(5, 4)
46#define SUN4I_I2S_FMT0_SR(sr)                           ((sr) << 4)
47#define SUN4I_I2S_FMT0_WSS_MASK                 GENMASK(3, 2)
48#define SUN4I_I2S_FMT0_WSS(wss)                         ((wss) << 2)
49#define SUN4I_I2S_FMT0_FMT_MASK                 GENMASK(1, 0)
50#define SUN4I_I2S_FMT0_FMT_RIGHT_J                      (2 << 0)
51#define SUN4I_I2S_FMT0_FMT_LEFT_J                       (1 << 0)
52#define SUN4I_I2S_FMT0_FMT_I2S                          (0 << 0)
53
54#define SUN4I_I2S_FMT1_REG              0x08
55#define SUN4I_I2S_FIFO_TX_REG           0x0c
56#define SUN4I_I2S_FIFO_RX_REG           0x10
57
58#define SUN4I_I2S_FIFO_CTRL_REG         0x14
59#define SUN4I_I2S_FIFO_CTRL_FLUSH_TX            BIT(25)
60#define SUN4I_I2S_FIFO_CTRL_FLUSH_RX            BIT(24)
61#define SUN4I_I2S_FIFO_CTRL_TX_MODE_MASK        BIT(2)
62#define SUN4I_I2S_FIFO_CTRL_TX_MODE(mode)               ((mode) << 2)
63#define SUN4I_I2S_FIFO_CTRL_RX_MODE_MASK        GENMASK(1, 0)
64#define SUN4I_I2S_FIFO_CTRL_RX_MODE(mode)               (mode)
65
66#define SUN4I_I2S_FIFO_STA_REG          0x18
67
68#define SUN4I_I2S_DMA_INT_CTRL_REG      0x1c
69#define SUN4I_I2S_DMA_INT_CTRL_TX_DRQ_EN        BIT(7)
70#define SUN4I_I2S_DMA_INT_CTRL_RX_DRQ_EN        BIT(3)
71
72#define SUN4I_I2S_INT_STA_REG           0x20
73
74#define SUN4I_I2S_CLK_DIV_REG           0x24
75#define SUN4I_I2S_CLK_DIV_MCLK_EN               BIT(7)
76#define SUN4I_I2S_CLK_DIV_BCLK_MASK             GENMASK(6, 4)
77#define SUN4I_I2S_CLK_DIV_BCLK(bclk)                    ((bclk) << 4)
78#define SUN4I_I2S_CLK_DIV_MCLK_MASK             GENMASK(3, 0)
79#define SUN4I_I2S_CLK_DIV_MCLK(mclk)                    ((mclk) << 0)
80
81#define SUN4I_I2S_RX_CNT_REG            0x28
82#define SUN4I_I2S_TX_CNT_REG            0x2c
83
84#define SUN4I_I2S_TX_CHAN_SEL_REG       0x30
85#define SUN4I_I2S_TX_CHAN_SEL(num_chan)         (((num_chan) - 1) << 0)
86
87#define SUN4I_I2S_TX_CHAN_MAP_REG       0x34
88#define SUN4I_I2S_TX_CHAN_MAP(chan, sample)     ((sample) << (chan << 2))
89
90#define SUN4I_I2S_RX_CHAN_SEL_REG       0x38
91#define SUN4I_I2S_RX_CHAN_MAP_REG       0x3c
92
93struct sun4i_i2s {
94        struct clk      *bus_clk;
95        struct clk      *mod_clk;
96        struct regmap   *regmap;
97        struct reset_control *rst;
98
99        struct snd_dmaengine_dai_dma_data       playback_dma_data;
100};
101
102struct sun4i_i2s_clk_div {
103        u8      div;
104        u8      val;
105};
106
107static const struct sun4i_i2s_clk_div sun4i_i2s_bclk_div[] = {
108        { .div = 2, .val = 0 },
109        { .div = 4, .val = 1 },
110        { .div = 6, .val = 2 },
111        { .div = 8, .val = 3 },
112        { .div = 12, .val = 4 },
113        { .div = 16, .val = 5 },
114};
115
116static const struct sun4i_i2s_clk_div sun4i_i2s_mclk_div[] = {
117        { .div = 1, .val = 0 },
118        { .div = 2, .val = 1 },
119        { .div = 4, .val = 2 },
120        { .div = 6, .val = 3 },
121        { .div = 8, .val = 4 },
122        { .div = 12, .val = 5 },
123        { .div = 16, .val = 6 },
124        { .div = 24, .val = 7 },
125};
126
127static int sun4i_i2s_get_bclk_div(struct sun4i_i2s *i2s,
128                                  unsigned int oversample_rate,
129                                  unsigned int word_size)
130{
131        int div = oversample_rate / word_size / 2;
132        int i;
133
134        for (i = 0; i < ARRAY_SIZE(sun4i_i2s_bclk_div); i++) {
135                const struct sun4i_i2s_clk_div *bdiv = &sun4i_i2s_bclk_div[i];
136
137                if (bdiv->div == div)
138                        return bdiv->val;
139        }
140
141        return -EINVAL;
142}
143
144static int sun4i_i2s_get_mclk_div(struct sun4i_i2s *i2s,
145                                  unsigned int oversample_rate,
146                                  unsigned int module_rate,
147                                  unsigned int sampling_rate)
148{
149        int div = module_rate / sampling_rate / oversample_rate;
150        int i;
151
152        for (i = 0; i < ARRAY_SIZE(sun4i_i2s_mclk_div); i++) {
153                const struct sun4i_i2s_clk_div *mdiv = &sun4i_i2s_mclk_div[i];
154
155                if (mdiv->div == div)
156                        return mdiv->val;
157        }
158
159        return -EINVAL;
160}
161
162static int sun4i_i2s_oversample_rates[] = { 128, 192, 256, 384, 512, 768 };
163
164static int sun4i_i2s_set_clk_rate(struct sun4i_i2s *i2s,
165                                  unsigned int rate,
166                                  unsigned int word_size)
167{
168        unsigned int clk_rate;
169        int bclk_div, mclk_div;
170        int ret, i;
171
172        switch (rate) {
173        case 176400:
174        case 88200:
175        case 44100:
176        case 22050:
177        case 11025:
178                clk_rate = 22579200;
179                break;
180
181        case 192000:
182        case 128000:
183        case 96000:
184        case 64000:
185        case 48000:
186        case 32000:
187        case 24000:
188        case 16000:
189        case 12000:
190        case 8000:
191                clk_rate = 24576000;
192                break;
193
194        default:
195                return -EINVAL;
196        }
197
198        ret = clk_set_rate(i2s->mod_clk, clk_rate);
199        if (ret)
200                return ret;
201
202        /* Always favor the highest oversampling rate */
203        for (i = (ARRAY_SIZE(sun4i_i2s_oversample_rates) - 1); i >= 0; i--) {
204                unsigned int oversample_rate = sun4i_i2s_oversample_rates[i];
205
206                bclk_div = sun4i_i2s_get_bclk_div(i2s, oversample_rate,
207                                                  word_size);
208                mclk_div = sun4i_i2s_get_mclk_div(i2s, oversample_rate,
209                                                  clk_rate,
210                                                  rate);
211
212                if ((bclk_div >= 0) && (mclk_div >= 0))
213                        break;
214        }
215
216        if ((bclk_div < 0) || (mclk_div < 0))
217                return -EINVAL;
218
219        regmap_write(i2s->regmap, SUN4I_I2S_CLK_DIV_REG,
220                     SUN4I_I2S_CLK_DIV_BCLK(bclk_div) |
221                     SUN4I_I2S_CLK_DIV_MCLK(mclk_div) |
222                     SUN4I_I2S_CLK_DIV_MCLK_EN);
223
224        return 0;
225}
226
227static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream,
228                               struct snd_pcm_hw_params *params,
229                               struct snd_soc_dai *dai)
230{
231        struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
232        int sr, wss;
233        u32 width;
234
235        if (params_channels(params) != 2)
236                return -EINVAL;
237
238        switch (params_physical_width(params)) {
239        case 16:
240                width = DMA_SLAVE_BUSWIDTH_2_BYTES;
241                break;
242        default:
243                return -EINVAL;
244        }
245        i2s->playback_dma_data.addr_width = width;
246
247        switch (params_width(params)) {
248        case 16:
249                sr = 0;
250                wss = 0;
251                break;
252
253        default:
254                return -EINVAL;
255        }
256
257        regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG,
258                           SUN4I_I2S_FMT0_WSS_MASK | SUN4I_I2S_FMT0_SR_MASK,
259                           SUN4I_I2S_FMT0_WSS(wss) | SUN4I_I2S_FMT0_SR(sr));
260
261        return sun4i_i2s_set_clk_rate(i2s, params_rate(params),
262                                      params_width(params));
263}
264
265static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
266{
267        struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
268        u32 val;
269
270        /* DAI Mode */
271        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
272        case SND_SOC_DAIFMT_I2S:
273                val = SUN4I_I2S_FMT0_FMT_I2S;
274                break;
275        case SND_SOC_DAIFMT_LEFT_J:
276                val = SUN4I_I2S_FMT0_FMT_LEFT_J;
277                break;
278        case SND_SOC_DAIFMT_RIGHT_J:
279                val = SUN4I_I2S_FMT0_FMT_RIGHT_J;
280                break;
281        default:
282                return -EINVAL;
283        }
284
285        regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG,
286                           SUN4I_I2S_FMT0_FMT_MASK,
287                           val);
288
289        /* DAI clock polarity */
290        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
291        case SND_SOC_DAIFMT_IB_IF:
292                /* Invert both clocks */
293                val = SUN4I_I2S_FMT0_BCLK_POLARITY_INVERTED |
294                        SUN4I_I2S_FMT0_LRCLK_POLARITY_INVERTED;
295                break;
296        case SND_SOC_DAIFMT_IB_NF:
297                /* Invert bit clock */
298                val = SUN4I_I2S_FMT0_BCLK_POLARITY_INVERTED |
299                        SUN4I_I2S_FMT0_LRCLK_POLARITY_NORMAL;
300                break;
301        case SND_SOC_DAIFMT_NB_IF:
302                /* Invert frame clock */
303                val = SUN4I_I2S_FMT0_LRCLK_POLARITY_INVERTED |
304                        SUN4I_I2S_FMT0_BCLK_POLARITY_NORMAL;
305                break;
306        case SND_SOC_DAIFMT_NB_NF:
307                /* Nothing to do for both normal cases */
308                val = SUN4I_I2S_FMT0_BCLK_POLARITY_NORMAL |
309                        SUN4I_I2S_FMT0_LRCLK_POLARITY_NORMAL;
310                break;
311        default:
312                return -EINVAL;
313        }
314
315        regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG,
316                           SUN4I_I2S_FMT0_BCLK_POLARITY_MASK |
317                           SUN4I_I2S_FMT0_LRCLK_POLARITY_MASK,
318                           val);
319
320        /* DAI clock master masks */
321        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
322        case SND_SOC_DAIFMT_CBS_CFS:
323                /* BCLK and LRCLK master */
324                val = SUN4I_I2S_CTRL_MODE_MASTER;
325                break;
326        case SND_SOC_DAIFMT_CBM_CFM:
327                /* BCLK and LRCLK slave */
328                val = SUN4I_I2S_CTRL_MODE_SLAVE;
329                break;
330        default:
331                return -EINVAL;
332        }
333
334        regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
335                           SUN4I_I2S_CTRL_MODE_MASK,
336                           val);
337
338        /* Set significant bits in our FIFOs */
339        regmap_update_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG,
340                           SUN4I_I2S_FIFO_CTRL_TX_MODE_MASK |
341                           SUN4I_I2S_FIFO_CTRL_RX_MODE_MASK,
342                           SUN4I_I2S_FIFO_CTRL_TX_MODE(1) |
343                           SUN4I_I2S_FIFO_CTRL_RX_MODE(1));
344        return 0;
345}
346
347static void sun4i_i2s_start_playback(struct sun4i_i2s *i2s)
348{
349        /* Flush TX FIFO */
350        regmap_update_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG,
351                           SUN4I_I2S_FIFO_CTRL_FLUSH_TX,
352                           SUN4I_I2S_FIFO_CTRL_FLUSH_TX);
353
354        /* Clear TX counter */
355        regmap_write(i2s->regmap, SUN4I_I2S_TX_CNT_REG, 0);
356
357        /* Enable TX Block */
358        regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
359                           SUN4I_I2S_CTRL_TX_EN,
360                           SUN4I_I2S_CTRL_TX_EN);
361
362        /* Enable TX DRQ */
363        regmap_update_bits(i2s->regmap, SUN4I_I2S_DMA_INT_CTRL_REG,
364                           SUN4I_I2S_DMA_INT_CTRL_TX_DRQ_EN,
365                           SUN4I_I2S_DMA_INT_CTRL_TX_DRQ_EN);
366}
367
368
369static void sun4i_i2s_stop_playback(struct sun4i_i2s *i2s)
370{
371        /* Disable TX Block */
372        regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
373                           SUN4I_I2S_CTRL_TX_EN,
374                           0);
375
376        /* Disable TX DRQ */
377        regmap_update_bits(i2s->regmap, SUN4I_I2S_DMA_INT_CTRL_REG,
378                           SUN4I_I2S_DMA_INT_CTRL_TX_DRQ_EN,
379                           0);
380}
381
382static int sun4i_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
383                             struct snd_soc_dai *dai)
384{
385        struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
386
387        switch (cmd) {
388        case SNDRV_PCM_TRIGGER_START:
389        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
390        case SNDRV_PCM_TRIGGER_RESUME:
391                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
392                        sun4i_i2s_start_playback(i2s);
393                else
394                        return -EINVAL;
395                break;
396
397        case SNDRV_PCM_TRIGGER_STOP:
398        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
399        case SNDRV_PCM_TRIGGER_SUSPEND:
400                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
401                        sun4i_i2s_stop_playback(i2s);
402                else
403                        return -EINVAL;
404                break;
405
406        default:
407                return -EINVAL;
408        }
409
410        return 0;
411}
412
413static int sun4i_i2s_startup(struct snd_pcm_substream *substream,
414                             struct snd_soc_dai *dai)
415{
416        struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
417
418        /* Enable the whole hardware block */
419        regmap_write(i2s->regmap, SUN4I_I2S_CTRL_REG,
420                     SUN4I_I2S_CTRL_GL_EN);
421
422        /* Enable the first output line */
423        regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
424                           SUN4I_I2S_CTRL_SDO_EN_MASK,
425                           SUN4I_I2S_CTRL_SDO_EN(0));
426
427        /* Enable the first two channels */
428        regmap_write(i2s->regmap, SUN4I_I2S_TX_CHAN_SEL_REG,
429                     SUN4I_I2S_TX_CHAN_SEL(2));
430
431        /* Map them to the two first samples coming in */
432        regmap_write(i2s->regmap, SUN4I_I2S_TX_CHAN_MAP_REG,
433                     SUN4I_I2S_TX_CHAN_MAP(0, 0) | SUN4I_I2S_TX_CHAN_MAP(1, 1));
434
435        return clk_prepare_enable(i2s->mod_clk);
436}
437
438static void sun4i_i2s_shutdown(struct snd_pcm_substream *substream,
439                               struct snd_soc_dai *dai)
440{
441        struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
442
443        clk_disable_unprepare(i2s->mod_clk);
444
445        /* Disable our output lines */
446        regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
447                           SUN4I_I2S_CTRL_SDO_EN_MASK, 0);
448
449        /* Disable the whole hardware block */
450        regmap_write(i2s->regmap, SUN4I_I2S_CTRL_REG, 0);
451}
452
453static const struct snd_soc_dai_ops sun4i_i2s_dai_ops = {
454        .hw_params      = sun4i_i2s_hw_params,
455        .set_fmt        = sun4i_i2s_set_fmt,
456        .shutdown       = sun4i_i2s_shutdown,
457        .startup        = sun4i_i2s_startup,
458        .trigger        = sun4i_i2s_trigger,
459};
460
461static int sun4i_i2s_dai_probe(struct snd_soc_dai *dai)
462{
463        struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
464
465        snd_soc_dai_init_dma_data(dai, &i2s->playback_dma_data, NULL);
466
467        snd_soc_dai_set_drvdata(dai, i2s);
468
469        return 0;
470}
471
472static struct snd_soc_dai_driver sun4i_i2s_dai = {
473        .probe = sun4i_i2s_dai_probe,
474        .playback = {
475                .stream_name = "Playback",
476                .channels_min = 2,
477                .channels_max = 2,
478                .rates = SNDRV_PCM_RATE_8000_192000,
479                .formats = SNDRV_PCM_FMTBIT_S16_LE,
480        },
481        .ops = &sun4i_i2s_dai_ops,
482        .symmetric_rates = 1,
483};
484
485static const struct snd_soc_component_driver sun4i_i2s_component = {
486        .name   = "sun4i-dai",
487};
488
489static bool sun4i_i2s_rd_reg(struct device *dev, unsigned int reg)
490{
491        switch (reg) {
492        case SUN4I_I2S_FIFO_TX_REG:
493                return false;
494
495        default:
496                return true;
497        }
498}
499
500static bool sun4i_i2s_wr_reg(struct device *dev, unsigned int reg)
501{
502        switch (reg) {
503        case SUN4I_I2S_FIFO_RX_REG:
504        case SUN4I_I2S_FIFO_STA_REG:
505                return false;
506
507        default:
508                return true;
509        }
510}
511
512static bool sun4i_i2s_volatile_reg(struct device *dev, unsigned int reg)
513{
514        switch (reg) {
515        case SUN4I_I2S_FIFO_RX_REG:
516        case SUN4I_I2S_INT_STA_REG:
517        case SUN4I_I2S_RX_CNT_REG:
518        case SUN4I_I2S_TX_CNT_REG:
519                return true;
520
521        default:
522                return false;
523        }
524}
525
526static const struct reg_default sun4i_i2s_reg_defaults[] = {
527        { SUN4I_I2S_CTRL_REG, 0x00000000 },
528        { SUN4I_I2S_FMT0_REG, 0x0000000c },
529        { SUN4I_I2S_FMT1_REG, 0x00004020 },
530        { SUN4I_I2S_FIFO_CTRL_REG, 0x000400f0 },
531        { SUN4I_I2S_DMA_INT_CTRL_REG, 0x00000000 },
532        { SUN4I_I2S_CLK_DIV_REG, 0x00000000 },
533        { SUN4I_I2S_TX_CHAN_SEL_REG, 0x00000001 },
534        { SUN4I_I2S_TX_CHAN_MAP_REG, 0x76543210 },
535        { SUN4I_I2S_RX_CHAN_SEL_REG, 0x00000001 },
536        { SUN4I_I2S_RX_CHAN_MAP_REG, 0x00003210 },
537};
538
539static const struct regmap_config sun4i_i2s_regmap_config = {
540        .reg_bits       = 32,
541        .reg_stride     = 4,
542        .val_bits       = 32,
543        .max_register   = SUN4I_I2S_RX_CHAN_MAP_REG,
544
545        .cache_type     = REGCACHE_FLAT,
546        .reg_defaults   = sun4i_i2s_reg_defaults,
547        .num_reg_defaults       = ARRAY_SIZE(sun4i_i2s_reg_defaults),
548        .writeable_reg  = sun4i_i2s_wr_reg,
549        .readable_reg   = sun4i_i2s_rd_reg,
550        .volatile_reg   = sun4i_i2s_volatile_reg,
551};
552
553static int sun4i_i2s_runtime_resume(struct device *dev)
554{
555        struct sun4i_i2s *i2s = dev_get_drvdata(dev);
556        int ret;
557
558        ret = clk_prepare_enable(i2s->bus_clk);
559        if (ret) {
560                dev_err(dev, "Failed to enable bus clock\n");
561                return ret;
562        }
563
564        regcache_cache_only(i2s->regmap, false);
565        regcache_mark_dirty(i2s->regmap);
566
567        ret = regcache_sync(i2s->regmap);
568        if (ret) {
569                dev_err(dev, "Failed to sync regmap cache\n");
570                goto err_disable_clk;
571        }
572
573        return 0;
574
575err_disable_clk:
576        clk_disable_unprepare(i2s->bus_clk);
577        return ret;
578}
579
580static int sun4i_i2s_runtime_suspend(struct device *dev)
581{
582        struct sun4i_i2s *i2s = dev_get_drvdata(dev);
583
584        regcache_cache_only(i2s->regmap, true);
585
586        clk_disable_unprepare(i2s->bus_clk);
587
588        return 0;
589}
590
591struct sun4i_i2s_quirks {
592        bool has_reset;
593};
594
595static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = {
596        .has_reset      = false,
597};
598
599static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
600        .has_reset      = true,
601};
602
603static int sun4i_i2s_probe(struct platform_device *pdev)
604{
605        struct sun4i_i2s *i2s;
606        const struct sun4i_i2s_quirks *quirks;
607        struct resource *res;
608        void __iomem *regs;
609        int irq, ret;
610
611        i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
612        if (!i2s)
613                return -ENOMEM;
614        platform_set_drvdata(pdev, i2s);
615
616        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
617        regs = devm_ioremap_resource(&pdev->dev, res);
618        if (IS_ERR(regs))
619                return PTR_ERR(regs);
620
621        irq = platform_get_irq(pdev, 0);
622        if (irq < 0) {
623                dev_err(&pdev->dev, "Can't retrieve our interrupt\n");
624                return irq;
625        }
626
627        quirks = of_device_get_match_data(&pdev->dev);
628        if (!quirks) {
629                dev_err(&pdev->dev, "Failed to determine the quirks to use\n");
630                return -ENODEV;
631        }
632
633        i2s->bus_clk = devm_clk_get(&pdev->dev, "apb");
634        if (IS_ERR(i2s->bus_clk)) {
635                dev_err(&pdev->dev, "Can't get our bus clock\n");
636                return PTR_ERR(i2s->bus_clk);
637        }
638
639        i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
640                                            &sun4i_i2s_regmap_config);
641        if (IS_ERR(i2s->regmap)) {
642                dev_err(&pdev->dev, "Regmap initialisation failed\n");
643                return PTR_ERR(i2s->regmap);
644        }
645
646        i2s->mod_clk = devm_clk_get(&pdev->dev, "mod");
647        if (IS_ERR(i2s->mod_clk)) {
648                dev_err(&pdev->dev, "Can't get our mod clock\n");
649                return PTR_ERR(i2s->mod_clk);
650        }
651
652        if (quirks->has_reset) {
653                i2s->rst = devm_reset_control_get(&pdev->dev, NULL);
654                if (IS_ERR(i2s->rst)) {
655                        dev_err(&pdev->dev, "Failed to get reset control\n");
656                        return PTR_ERR(i2s->rst);
657                }
658        }
659
660        if (!IS_ERR(i2s->rst)) {
661                ret = reset_control_deassert(i2s->rst);
662                if (ret) {
663                        dev_err(&pdev->dev,
664                                "Failed to deassert the reset control\n");
665                        return -EINVAL;
666                }
667        }
668
669        i2s->playback_dma_data.addr = res->start + SUN4I_I2S_FIFO_TX_REG;
670        i2s->playback_dma_data.maxburst = 4;
671
672        pm_runtime_enable(&pdev->dev);
673        if (!pm_runtime_enabled(&pdev->dev)) {
674                ret = sun4i_i2s_runtime_resume(&pdev->dev);
675                if (ret)
676                        goto err_pm_disable;
677        }
678
679        ret = devm_snd_soc_register_component(&pdev->dev,
680                                              &sun4i_i2s_component,
681                                              &sun4i_i2s_dai, 1);
682        if (ret) {
683                dev_err(&pdev->dev, "Could not register DAI\n");
684                goto err_suspend;
685        }
686
687        ret = snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
688        if (ret) {
689                dev_err(&pdev->dev, "Could not register PCM\n");
690                goto err_suspend;
691        }
692
693        return 0;
694
695err_suspend:
696        if (!pm_runtime_status_suspended(&pdev->dev))
697                sun4i_i2s_runtime_suspend(&pdev->dev);
698err_pm_disable:
699        pm_runtime_disable(&pdev->dev);
700        if (!IS_ERR(i2s->rst))
701                reset_control_assert(i2s->rst);
702
703        return ret;
704}
705
706static int sun4i_i2s_remove(struct platform_device *pdev)
707{
708        struct sun4i_i2s *i2s = dev_get_drvdata(&pdev->dev);
709
710        snd_dmaengine_pcm_unregister(&pdev->dev);
711
712        pm_runtime_disable(&pdev->dev);
713        if (!pm_runtime_status_suspended(&pdev->dev))
714                sun4i_i2s_runtime_suspend(&pdev->dev);
715
716        if (!IS_ERR(i2s->rst))
717                reset_control_assert(i2s->rst);
718
719        return 0;
720}
721
722static const struct of_device_id sun4i_i2s_match[] = {
723        {
724                .compatible = "allwinner,sun4i-a10-i2s",
725                .data = &sun4i_a10_i2s_quirks,
726        },
727        {
728                .compatible = "allwinner,sun6i-a31-i2s",
729                .data = &sun6i_a31_i2s_quirks,
730        },
731        {}
732};
733MODULE_DEVICE_TABLE(of, sun4i_i2s_match);
734
735static const struct dev_pm_ops sun4i_i2s_pm_ops = {
736        .runtime_resume         = sun4i_i2s_runtime_resume,
737        .runtime_suspend        = sun4i_i2s_runtime_suspend,
738};
739
740static struct platform_driver sun4i_i2s_driver = {
741        .probe  = sun4i_i2s_probe,
742        .remove = sun4i_i2s_remove,
743        .driver = {
744                .name           = "sun4i-i2s",
745                .of_match_table = sun4i_i2s_match,
746                .pm             = &sun4i_i2s_pm_ops,
747        },
748};
749module_platform_driver(sun4i_i2s_driver);
750
751MODULE_AUTHOR("Andrea Venturi <be17068@iperbole.bo.it>");
752MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
753MODULE_DESCRIPTION("Allwinner A10 I2S driver");
754MODULE_LICENSE("GPL");
Note: See TracBrowser for help on using the repository browser.