2 * Copyright (C) 2015 Andrea Venturi
3 * Andrea Venturi <be17068@iperbole.bo.it>
5 * Copyright (C) 2016 Maxime Ripard
6 * Maxime Ripard <maxime.ripard@free-electrons.com>
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.
14 #include <linux/clk.h>
15 #include <linux/dmaengine.h>
16 #include <linux/module.h>
17 #include <linux/platform_device.h>
18 #include <linux/pm_runtime.h>
19 #include <linux/regmap.h>
21 #include <sound/dmaengine_pcm.h>
22 #include <sound/pcm_params.h>
23 #include <sound/soc.h>
24 #include <sound/soc-dai.h>
26 #define SUN4I_I2S_CTRL_REG 0x00
27 #define SUN4I_I2S_CTRL_SDO_EN_MASK GENMASK(11, 8)
28 #define SUN4I_I2S_CTRL_SDO_EN(sdo) BIT(8 + (sdo))
29 #define SUN4I_I2S_CTRL_MODE_MASK BIT(5)
30 #define SUN4I_I2S_CTRL_MODE_SLAVE (1 << 5)
31 #define SUN4I_I2S_CTRL_MODE_MASTER (0 << 5)
32 #define SUN4I_I2S_CTRL_TX_EN BIT(2)
33 #define SUN4I_I2S_CTRL_RX_EN BIT(1)
34 #define SUN4I_I2S_CTRL_GL_EN BIT(0)
36 #define SUN4I_I2S_FMT0_REG 0x04
37 #define SUN4I_I2S_FMT0_LRCLK_POLARITY_MASK BIT(7)
38 #define SUN4I_I2S_FMT0_LRCLK_POLARITY_INVERTED (1 << 7)
39 #define SUN4I_I2S_FMT0_LRCLK_POLARITY_NORMAL (0 << 7)
40 #define SUN4I_I2S_FMT0_BCLK_POLARITY_MASK BIT(6)
41 #define SUN4I_I2S_FMT0_BCLK_POLARITY_INVERTED (1 << 6)
42 #define SUN4I_I2S_FMT0_BCLK_POLARITY_NORMAL (0 << 6)
43 #define SUN4I_I2S_FMT0_SR_MASK GENMASK(5, 4)
44 #define SUN4I_I2S_FMT0_SR(sr) ((sr) << 4)
45 #define SUN4I_I2S_FMT0_WSS_MASK GENMASK(3, 2)
46 #define SUN4I_I2S_FMT0_WSS(wss) ((wss) << 2)
47 #define SUN4I_I2S_FMT0_FMT_MASK GENMASK(1, 0)
48 #define SUN4I_I2S_FMT0_FMT_RIGHT_J (2 << 0)
49 #define SUN4I_I2S_FMT0_FMT_LEFT_J (1 << 0)
50 #define SUN4I_I2S_FMT0_FMT_I2S (0 << 0)
52 #define SUN4I_I2S_FMT1_REG 0x08
53 #define SUN4I_I2S_FIFO_TX_REG 0x0c
54 #define SUN4I_I2S_FIFO_RX_REG 0x10
56 #define SUN4I_I2S_FIFO_CTRL_REG 0x14
57 #define SUN4I_I2S_FIFO_CTRL_FLUSH_TX BIT(25)
58 #define SUN4I_I2S_FIFO_CTRL_FLUSH_RX BIT(24)
59 #define SUN4I_I2S_FIFO_CTRL_TX_MODE_MASK BIT(2)
60 #define SUN4I_I2S_FIFO_CTRL_TX_MODE(mode) ((mode) << 2)
61 #define SUN4I_I2S_FIFO_CTRL_RX_MODE_MASK GENMASK(1, 0)
62 #define SUN4I_I2S_FIFO_CTRL_RX_MODE(mode) (mode)
64 #define SUN4I_I2S_FIFO_STA_REG 0x18
66 #define SUN4I_I2S_DMA_INT_CTRL_REG 0x1c
67 #define SUN4I_I2S_DMA_INT_CTRL_TX_DRQ_EN BIT(7)
68 #define SUN4I_I2S_DMA_INT_CTRL_RX_DRQ_EN BIT(3)
70 #define SUN4I_I2S_INT_STA_REG 0x20
72 #define SUN4I_I2S_CLK_DIV_REG 0x24
73 #define SUN4I_I2S_CLK_DIV_MCLK_EN BIT(7)
74 #define SUN4I_I2S_CLK_DIV_BCLK_MASK GENMASK(6, 4)
75 #define SUN4I_I2S_CLK_DIV_BCLK(bclk) ((bclk) << 4)
76 #define SUN4I_I2S_CLK_DIV_MCLK_MASK GENMASK(3, 0)
77 #define SUN4I_I2S_CLK_DIV_MCLK(mclk) ((mclk) << 0)
79 #define SUN4I_I2S_RX_CNT_REG 0x28
80 #define SUN4I_I2S_TX_CNT_REG 0x2c
82 #define SUN4I_I2S_TX_CHAN_SEL_REG 0x30
83 #define SUN4I_I2S_TX_CHAN_SEL(num_chan) (((num_chan) - 1) << 0)
85 #define SUN4I_I2S_TX_CHAN_MAP_REG 0x34
86 #define SUN4I_I2S_TX_CHAN_MAP(chan, sample) ((sample) << (chan << 2))
88 #define SUN4I_I2S_RX_CHAN_SEL_REG 0x38
89 #define SUN4I_I2S_RX_CHAN_MAP_REG 0x3c
94 struct regmap
*regmap
;
96 unsigned int mclk_freq
;
98 struct snd_dmaengine_dai_dma_data capture_dma_data
;
99 struct snd_dmaengine_dai_dma_data playback_dma_data
;
102 struct sun4i_i2s_clk_div
{
107 static 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 },
116 static 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 },
127 static int sun4i_i2s_get_bclk_div(struct sun4i_i2s
*i2s
,
128 unsigned int oversample_rate
,
129 unsigned int word_size
)
131 int div
= oversample_rate
/ word_size
/ 2;
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
];
137 if (bdiv
->div
== div
)
144 static 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
)
149 int div
= module_rate
/ sampling_rate
/ oversample_rate
;
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
];
155 if (mdiv
->div
== div
)
162 static int sun4i_i2s_oversample_rates
[] = { 128, 192, 256, 384, 512, 768 };
163 static bool sun4i_i2s_oversample_is_valid(unsigned int oversample
)
167 for (i
= 0; i
< ARRAY_SIZE(sun4i_i2s_oversample_rates
); i
++)
168 if (sun4i_i2s_oversample_rates
[i
] == oversample
)
174 static int sun4i_i2s_set_clk_rate(struct sun4i_i2s
*i2s
,
176 unsigned int word_size
)
178 unsigned int oversample_rate
, clk_rate
;
179 int bclk_div
, mclk_div
;
208 ret
= clk_set_rate(i2s
->mod_clk
, clk_rate
);
212 oversample_rate
= i2s
->mclk_freq
/ rate
;
213 if (!sun4i_i2s_oversample_is_valid(oversample_rate
))
216 bclk_div
= sun4i_i2s_get_bclk_div(i2s
, oversample_rate
,
221 mclk_div
= sun4i_i2s_get_mclk_div(i2s
, oversample_rate
,
226 regmap_write(i2s
->regmap
, SUN4I_I2S_CLK_DIV_REG
,
227 SUN4I_I2S_CLK_DIV_BCLK(bclk_div
) |
228 SUN4I_I2S_CLK_DIV_MCLK(mclk_div
) |
229 SUN4I_I2S_CLK_DIV_MCLK_EN
);
234 static int sun4i_i2s_hw_params(struct snd_pcm_substream
*substream
,
235 struct snd_pcm_hw_params
*params
,
236 struct snd_soc_dai
*dai
)
238 struct sun4i_i2s
*i2s
= snd_soc_dai_get_drvdata(dai
);
242 if (params_channels(params
) != 2)
245 switch (params_physical_width(params
)) {
247 width
= DMA_SLAVE_BUSWIDTH_2_BYTES
;
252 i2s
->playback_dma_data
.addr_width
= width
;
254 switch (params_width(params
)) {
264 regmap_update_bits(i2s
->regmap
, SUN4I_I2S_FMT0_REG
,
265 SUN4I_I2S_FMT0_WSS_MASK
| SUN4I_I2S_FMT0_SR_MASK
,
266 SUN4I_I2S_FMT0_WSS(wss
) | SUN4I_I2S_FMT0_SR(sr
));
268 return sun4i_i2s_set_clk_rate(i2s
, params_rate(params
),
269 params_width(params
));
272 static int sun4i_i2s_set_fmt(struct snd_soc_dai
*dai
, unsigned int fmt
)
274 struct sun4i_i2s
*i2s
= snd_soc_dai_get_drvdata(dai
);
278 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
279 case SND_SOC_DAIFMT_I2S
:
280 val
= SUN4I_I2S_FMT0_FMT_I2S
;
282 case SND_SOC_DAIFMT_LEFT_J
:
283 val
= SUN4I_I2S_FMT0_FMT_LEFT_J
;
285 case SND_SOC_DAIFMT_RIGHT_J
:
286 val
= SUN4I_I2S_FMT0_FMT_RIGHT_J
;
292 regmap_update_bits(i2s
->regmap
, SUN4I_I2S_FMT0_REG
,
293 SUN4I_I2S_FMT0_FMT_MASK
,
296 /* DAI clock polarity */
297 switch (fmt
& SND_SOC_DAIFMT_INV_MASK
) {
298 case SND_SOC_DAIFMT_IB_IF
:
299 /* Invert both clocks */
300 val
= SUN4I_I2S_FMT0_BCLK_POLARITY_INVERTED
|
301 SUN4I_I2S_FMT0_LRCLK_POLARITY_INVERTED
;
303 case SND_SOC_DAIFMT_IB_NF
:
304 /* Invert bit clock */
305 val
= SUN4I_I2S_FMT0_BCLK_POLARITY_INVERTED
|
306 SUN4I_I2S_FMT0_LRCLK_POLARITY_NORMAL
;
308 case SND_SOC_DAIFMT_NB_IF
:
309 /* Invert frame clock */
310 val
= SUN4I_I2S_FMT0_LRCLK_POLARITY_INVERTED
|
311 SUN4I_I2S_FMT0_BCLK_POLARITY_NORMAL
;
313 case SND_SOC_DAIFMT_NB_NF
:
314 /* Nothing to do for both normal cases */
315 val
= SUN4I_I2S_FMT0_BCLK_POLARITY_NORMAL
|
316 SUN4I_I2S_FMT0_LRCLK_POLARITY_NORMAL
;
322 regmap_update_bits(i2s
->regmap
, SUN4I_I2S_FMT0_REG
,
323 SUN4I_I2S_FMT0_BCLK_POLARITY_MASK
|
324 SUN4I_I2S_FMT0_LRCLK_POLARITY_MASK
,
327 /* DAI clock master masks */
328 switch (fmt
& SND_SOC_DAIFMT_MASTER_MASK
) {
329 case SND_SOC_DAIFMT_CBS_CFS
:
330 /* BCLK and LRCLK master */
331 val
= SUN4I_I2S_CTRL_MODE_MASTER
;
333 case SND_SOC_DAIFMT_CBM_CFM
:
334 /* BCLK and LRCLK slave */
335 val
= SUN4I_I2S_CTRL_MODE_SLAVE
;
341 regmap_update_bits(i2s
->regmap
, SUN4I_I2S_CTRL_REG
,
342 SUN4I_I2S_CTRL_MODE_MASK
,
345 /* Set significant bits in our FIFOs */
346 regmap_update_bits(i2s
->regmap
, SUN4I_I2S_FIFO_CTRL_REG
,
347 SUN4I_I2S_FIFO_CTRL_TX_MODE_MASK
|
348 SUN4I_I2S_FIFO_CTRL_RX_MODE_MASK
,
349 SUN4I_I2S_FIFO_CTRL_TX_MODE(1) |
350 SUN4I_I2S_FIFO_CTRL_RX_MODE(1));
354 static void sun4i_i2s_start_capture(struct sun4i_i2s
*i2s
)
357 regmap_update_bits(i2s
->regmap
, SUN4I_I2S_FIFO_CTRL_REG
,
358 SUN4I_I2S_FIFO_CTRL_FLUSH_RX
,
359 SUN4I_I2S_FIFO_CTRL_FLUSH_RX
);
361 /* Clear RX counter */
362 regmap_write(i2s
->regmap
, SUN4I_I2S_RX_CNT_REG
, 0);
364 /* Enable RX Block */
365 regmap_update_bits(i2s
->regmap
, SUN4I_I2S_CTRL_REG
,
366 SUN4I_I2S_CTRL_RX_EN
,
367 SUN4I_I2S_CTRL_RX_EN
);
370 regmap_update_bits(i2s
->regmap
, SUN4I_I2S_DMA_INT_CTRL_REG
,
371 SUN4I_I2S_DMA_INT_CTRL_RX_DRQ_EN
,
372 SUN4I_I2S_DMA_INT_CTRL_RX_DRQ_EN
);
375 static void sun4i_i2s_start_playback(struct sun4i_i2s
*i2s
)
378 regmap_update_bits(i2s
->regmap
, SUN4I_I2S_FIFO_CTRL_REG
,
379 SUN4I_I2S_FIFO_CTRL_FLUSH_TX
,
380 SUN4I_I2S_FIFO_CTRL_FLUSH_TX
);
382 /* Clear TX counter */
383 regmap_write(i2s
->regmap
, SUN4I_I2S_TX_CNT_REG
, 0);
385 /* Enable TX Block */
386 regmap_update_bits(i2s
->regmap
, SUN4I_I2S_CTRL_REG
,
387 SUN4I_I2S_CTRL_TX_EN
,
388 SUN4I_I2S_CTRL_TX_EN
);
391 regmap_update_bits(i2s
->regmap
, SUN4I_I2S_DMA_INT_CTRL_REG
,
392 SUN4I_I2S_DMA_INT_CTRL_TX_DRQ_EN
,
393 SUN4I_I2S_DMA_INT_CTRL_TX_DRQ_EN
);
396 static void sun4i_i2s_stop_capture(struct sun4i_i2s
*i2s
)
398 /* Disable RX Block */
399 regmap_update_bits(i2s
->regmap
, SUN4I_I2S_CTRL_REG
,
400 SUN4I_I2S_CTRL_RX_EN
,
404 regmap_update_bits(i2s
->regmap
, SUN4I_I2S_DMA_INT_CTRL_REG
,
405 SUN4I_I2S_DMA_INT_CTRL_RX_DRQ_EN
,
409 static void sun4i_i2s_stop_playback(struct sun4i_i2s
*i2s
)
411 /* Disable TX Block */
412 regmap_update_bits(i2s
->regmap
, SUN4I_I2S_CTRL_REG
,
413 SUN4I_I2S_CTRL_TX_EN
,
417 regmap_update_bits(i2s
->regmap
, SUN4I_I2S_DMA_INT_CTRL_REG
,
418 SUN4I_I2S_DMA_INT_CTRL_TX_DRQ_EN
,
422 static int sun4i_i2s_trigger(struct snd_pcm_substream
*substream
, int cmd
,
423 struct snd_soc_dai
*dai
)
425 struct sun4i_i2s
*i2s
= snd_soc_dai_get_drvdata(dai
);
428 case SNDRV_PCM_TRIGGER_START
:
429 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
430 case SNDRV_PCM_TRIGGER_RESUME
:
431 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
432 sun4i_i2s_start_playback(i2s
);
434 sun4i_i2s_start_capture(i2s
);
437 case SNDRV_PCM_TRIGGER_STOP
:
438 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
439 case SNDRV_PCM_TRIGGER_SUSPEND
:
440 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
441 sun4i_i2s_stop_playback(i2s
);
443 sun4i_i2s_stop_capture(i2s
);
453 static int sun4i_i2s_startup(struct snd_pcm_substream
*substream
,
454 struct snd_soc_dai
*dai
)
456 struct sun4i_i2s
*i2s
= snd_soc_dai_get_drvdata(dai
);
458 /* Enable the whole hardware block */
459 regmap_write(i2s
->regmap
, SUN4I_I2S_CTRL_REG
,
460 SUN4I_I2S_CTRL_GL_EN
);
462 /* Enable the first output line */
463 regmap_update_bits(i2s
->regmap
, SUN4I_I2S_CTRL_REG
,
464 SUN4I_I2S_CTRL_SDO_EN_MASK
,
465 SUN4I_I2S_CTRL_SDO_EN(0));
467 /* Enable the first two channels */
468 regmap_write(i2s
->regmap
, SUN4I_I2S_TX_CHAN_SEL_REG
,
469 SUN4I_I2S_TX_CHAN_SEL(2));
471 /* Map them to the two first samples coming in */
472 regmap_write(i2s
->regmap
, SUN4I_I2S_TX_CHAN_MAP_REG
,
473 SUN4I_I2S_TX_CHAN_MAP(0, 0) | SUN4I_I2S_TX_CHAN_MAP(1, 1));
475 return clk_prepare_enable(i2s
->mod_clk
);
478 static void sun4i_i2s_shutdown(struct snd_pcm_substream
*substream
,
479 struct snd_soc_dai
*dai
)
481 struct sun4i_i2s
*i2s
= snd_soc_dai_get_drvdata(dai
);
483 clk_disable_unprepare(i2s
->mod_clk
);
485 /* Disable our output lines */
486 regmap_update_bits(i2s
->regmap
, SUN4I_I2S_CTRL_REG
,
487 SUN4I_I2S_CTRL_SDO_EN_MASK
, 0);
489 /* Disable the whole hardware block */
490 regmap_write(i2s
->regmap
, SUN4I_I2S_CTRL_REG
, 0);
493 static int sun4i_i2s_set_sysclk(struct snd_soc_dai
*dai
, int clk_id
,
494 unsigned int freq
, int dir
)
496 struct sun4i_i2s
*i2s
= snd_soc_dai_get_drvdata(dai
);
501 i2s
->mclk_freq
= freq
;
506 static const struct snd_soc_dai_ops sun4i_i2s_dai_ops
= {
507 .hw_params
= sun4i_i2s_hw_params
,
508 .set_fmt
= sun4i_i2s_set_fmt
,
509 .set_sysclk
= sun4i_i2s_set_sysclk
,
510 .shutdown
= sun4i_i2s_shutdown
,
511 .startup
= sun4i_i2s_startup
,
512 .trigger
= sun4i_i2s_trigger
,
515 static int sun4i_i2s_dai_probe(struct snd_soc_dai
*dai
)
517 struct sun4i_i2s
*i2s
= snd_soc_dai_get_drvdata(dai
);
519 snd_soc_dai_init_dma_data(dai
,
520 &i2s
->playback_dma_data
,
521 &i2s
->capture_dma_data
);
523 snd_soc_dai_set_drvdata(dai
, i2s
);
528 static struct snd_soc_dai_driver sun4i_i2s_dai
= {
529 .probe
= sun4i_i2s_dai_probe
,
531 .stream_name
= "Capture",
534 .rates
= SNDRV_PCM_RATE_8000_192000
,
535 .formats
= SNDRV_PCM_FMTBIT_S16_LE
,
538 .stream_name
= "Playback",
541 .rates
= SNDRV_PCM_RATE_8000_192000
,
542 .formats
= SNDRV_PCM_FMTBIT_S16_LE
,
544 .ops
= &sun4i_i2s_dai_ops
,
545 .symmetric_rates
= 1,
548 static const struct snd_soc_component_driver sun4i_i2s_component
= {
552 static bool sun4i_i2s_rd_reg(struct device
*dev
, unsigned int reg
)
555 case SUN4I_I2S_FIFO_TX_REG
:
563 static bool sun4i_i2s_wr_reg(struct device
*dev
, unsigned int reg
)
566 case SUN4I_I2S_FIFO_RX_REG
:
567 case SUN4I_I2S_FIFO_STA_REG
:
575 static bool sun4i_i2s_volatile_reg(struct device
*dev
, unsigned int reg
)
578 case SUN4I_I2S_FIFO_RX_REG
:
579 case SUN4I_I2S_INT_STA_REG
:
580 case SUN4I_I2S_RX_CNT_REG
:
581 case SUN4I_I2S_TX_CNT_REG
:
589 static const struct reg_default sun4i_i2s_reg_defaults
[] = {
590 { SUN4I_I2S_CTRL_REG
, 0x00000000 },
591 { SUN4I_I2S_FMT0_REG
, 0x0000000c },
592 { SUN4I_I2S_FMT1_REG
, 0x00004020 },
593 { SUN4I_I2S_FIFO_CTRL_REG
, 0x000400f0 },
594 { SUN4I_I2S_DMA_INT_CTRL_REG
, 0x00000000 },
595 { SUN4I_I2S_CLK_DIV_REG
, 0x00000000 },
596 { SUN4I_I2S_TX_CHAN_SEL_REG
, 0x00000001 },
597 { SUN4I_I2S_TX_CHAN_MAP_REG
, 0x76543210 },
598 { SUN4I_I2S_RX_CHAN_SEL_REG
, 0x00000001 },
599 { SUN4I_I2S_RX_CHAN_MAP_REG
, 0x00003210 },
602 static const struct regmap_config sun4i_i2s_regmap_config
= {
606 .max_register
= SUN4I_I2S_RX_CHAN_MAP_REG
,
608 .cache_type
= REGCACHE_FLAT
,
609 .reg_defaults
= sun4i_i2s_reg_defaults
,
610 .num_reg_defaults
= ARRAY_SIZE(sun4i_i2s_reg_defaults
),
611 .writeable_reg
= sun4i_i2s_wr_reg
,
612 .readable_reg
= sun4i_i2s_rd_reg
,
613 .volatile_reg
= sun4i_i2s_volatile_reg
,
616 static int sun4i_i2s_runtime_resume(struct device
*dev
)
618 struct sun4i_i2s
*i2s
= dev_get_drvdata(dev
);
621 ret
= clk_prepare_enable(i2s
->bus_clk
);
623 dev_err(dev
, "Failed to enable bus clock\n");
627 regcache_cache_only(i2s
->regmap
, false);
628 regcache_mark_dirty(i2s
->regmap
);
630 ret
= regcache_sync(i2s
->regmap
);
632 dev_err(dev
, "Failed to sync regmap cache\n");
633 goto err_disable_clk
;
639 clk_disable_unprepare(i2s
->bus_clk
);
643 static int sun4i_i2s_runtime_suspend(struct device
*dev
)
645 struct sun4i_i2s
*i2s
= dev_get_drvdata(dev
);
647 regcache_cache_only(i2s
->regmap
, true);
649 clk_disable_unprepare(i2s
->bus_clk
);
654 static int sun4i_i2s_probe(struct platform_device
*pdev
)
656 struct sun4i_i2s
*i2s
;
657 struct resource
*res
;
661 i2s
= devm_kzalloc(&pdev
->dev
, sizeof(*i2s
), GFP_KERNEL
);
664 platform_set_drvdata(pdev
, i2s
);
666 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
667 regs
= devm_ioremap_resource(&pdev
->dev
, res
);
669 return PTR_ERR(regs
);
671 irq
= platform_get_irq(pdev
, 0);
673 dev_err(&pdev
->dev
, "Can't retrieve our interrupt\n");
677 i2s
->bus_clk
= devm_clk_get(&pdev
->dev
, "apb");
678 if (IS_ERR(i2s
->bus_clk
)) {
679 dev_err(&pdev
->dev
, "Can't get our bus clock\n");
680 return PTR_ERR(i2s
->bus_clk
);
683 i2s
->regmap
= devm_regmap_init_mmio(&pdev
->dev
, regs
,
684 &sun4i_i2s_regmap_config
);
685 if (IS_ERR(i2s
->regmap
)) {
686 dev_err(&pdev
->dev
, "Regmap initialisation failed\n");
687 return PTR_ERR(i2s
->regmap
);
690 i2s
->mod_clk
= devm_clk_get(&pdev
->dev
, "mod");
691 if (IS_ERR(i2s
->mod_clk
)) {
692 dev_err(&pdev
->dev
, "Can't get our mod clock\n");
693 return PTR_ERR(i2s
->mod_clk
);
696 i2s
->playback_dma_data
.addr
= res
->start
+ SUN4I_I2S_FIFO_TX_REG
;
697 i2s
->playback_dma_data
.maxburst
= 4;
699 i2s
->capture_dma_data
.addr
= res
->start
+ SUN4I_I2S_FIFO_RX_REG
;
700 i2s
->capture_dma_data
.maxburst
= 4;
702 pm_runtime_enable(&pdev
->dev
);
703 if (!pm_runtime_enabled(&pdev
->dev
)) {
704 ret
= sun4i_i2s_runtime_resume(&pdev
->dev
);
709 ret
= devm_snd_soc_register_component(&pdev
->dev
,
710 &sun4i_i2s_component
,
713 dev_err(&pdev
->dev
, "Could not register DAI\n");
717 ret
= snd_dmaengine_pcm_register(&pdev
->dev
, NULL
, 0);
719 dev_err(&pdev
->dev
, "Could not register PCM\n");
726 if (!pm_runtime_status_suspended(&pdev
->dev
))
727 sun4i_i2s_runtime_suspend(&pdev
->dev
);
729 pm_runtime_disable(&pdev
->dev
);
734 static int sun4i_i2s_remove(struct platform_device
*pdev
)
736 snd_dmaengine_pcm_unregister(&pdev
->dev
);
738 pm_runtime_disable(&pdev
->dev
);
739 if (!pm_runtime_status_suspended(&pdev
->dev
))
740 sun4i_i2s_runtime_suspend(&pdev
->dev
);
745 static const struct of_device_id sun4i_i2s_match
[] = {
746 { .compatible
= "allwinner,sun4i-a10-i2s", },
749 MODULE_DEVICE_TABLE(of
, sun4i_i2s_match
);
751 static const struct dev_pm_ops sun4i_i2s_pm_ops
= {
752 .runtime_resume
= sun4i_i2s_runtime_resume
,
753 .runtime_suspend
= sun4i_i2s_runtime_suspend
,
756 static struct platform_driver sun4i_i2s_driver
= {
757 .probe
= sun4i_i2s_probe
,
758 .remove
= sun4i_i2s_remove
,
761 .of_match_table
= sun4i_i2s_match
,
762 .pm
= &sun4i_i2s_pm_ops
,
765 module_platform_driver(sun4i_i2s_driver
);
767 MODULE_AUTHOR("Andrea Venturi <be17068@iperbole.bo.it>");
768 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
769 MODULE_DESCRIPTION("Allwinner A10 I2S driver");
770 MODULE_LICENSE("GPL");