2 * Copyright (C) 2014-2015 Broadcom Corporation
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation version 2.
8 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
9 * kind, whether express or implied; without even the implied warranty
10 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 #include <linux/clk.h>
14 #include <linux/delay.h>
15 #include <linux/init.h>
17 #include <linux/module.h>
18 #include <linux/of_device.h>
19 #include <linux/slab.h>
20 #include <sound/core.h>
21 #include <sound/pcm.h>
22 #include <sound/pcm_params.h>
23 #include <sound/soc.h>
24 #include <sound/soc-dai.h>
26 #include "cygnus-ssp.h"
28 #define DEFAULT_VCO 1354750204
30 #define CYGNUS_TDM_RATE \
31 (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | \
32 SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_22050 | \
33 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
36 #define CAPTURE_FCI_ID_BASE 0x180
37 #define CYGNUS_SSP_TRISTATE_MASK 0x001fff
38 #define CYGNUS_PLLCLKSEL_MASK 0xf
40 /* Used with stream_on field to indicate which streams are active */
41 #define PLAYBACK_STREAM_MASK BIT(0)
42 #define CAPTURE_STREAM_MASK BIT(1)
44 #define I2S_STREAM_CFG_MASK 0xff003ff
45 #define I2S_CAP_STREAM_CFG_MASK 0xf0
46 #define SPDIF_STREAM_CFG_MASK 0x3ff
47 #define CH_GRP_STEREO 0x1
49 /* Begin register offset defines */
50 #define AUD_MISC_SEROUT_OE_REG_BASE 0x01c
51 #define AUD_MISC_SEROUT_SPDIF_OE 12
52 #define AUD_MISC_SEROUT_MCLK_OE 3
53 #define AUD_MISC_SEROUT_LRCK_OE 2
54 #define AUD_MISC_SEROUT_SCLK_OE 1
55 #define AUD_MISC_SEROUT_SDAT_OE 0
57 /* AUD_FMM_BF_CTRL_xxx regs */
58 #define BF_DST_CFG0_OFFSET 0x100
59 #define BF_DST_CFG1_OFFSET 0x104
60 #define BF_DST_CFG2_OFFSET 0x108
62 #define BF_DST_CTRL0_OFFSET 0x130
63 #define BF_DST_CTRL1_OFFSET 0x134
64 #define BF_DST_CTRL2_OFFSET 0x138
66 #define BF_SRC_CFG0_OFFSET 0x148
67 #define BF_SRC_CFG1_OFFSET 0x14c
68 #define BF_SRC_CFG2_OFFSET 0x150
69 #define BF_SRC_CFG3_OFFSET 0x154
71 #define BF_SRC_CTRL0_OFFSET 0x1c0
72 #define BF_SRC_CTRL1_OFFSET 0x1c4
73 #define BF_SRC_CTRL2_OFFSET 0x1c8
74 #define BF_SRC_CTRL3_OFFSET 0x1cc
76 #define BF_SRC_GRP0_OFFSET 0x1fc
77 #define BF_SRC_GRP1_OFFSET 0x200
78 #define BF_SRC_GRP2_OFFSET 0x204
79 #define BF_SRC_GRP3_OFFSET 0x208
81 #define BF_SRC_GRP_EN_OFFSET 0x320
82 #define BF_SRC_GRP_FLOWON_OFFSET 0x324
83 #define BF_SRC_GRP_SYNC_DIS_OFFSET 0x328
85 /* AUD_FMM_IOP_OUT_I2S_xxx regs */
86 #define OUT_I2S_0_STREAM_CFG_OFFSET 0xa00
87 #define OUT_I2S_0_CFG_OFFSET 0xa04
88 #define OUT_I2S_0_MCLK_CFG_OFFSET 0xa0c
90 #define OUT_I2S_1_STREAM_CFG_OFFSET 0xa40
91 #define OUT_I2S_1_CFG_OFFSET 0xa44
92 #define OUT_I2S_1_MCLK_CFG_OFFSET 0xa4c
94 #define OUT_I2S_2_STREAM_CFG_OFFSET 0xa80
95 #define OUT_I2S_2_CFG_OFFSET 0xa84
96 #define OUT_I2S_2_MCLK_CFG_OFFSET 0xa8c
98 /* AUD_FMM_IOP_OUT_SPDIF_xxx regs */
99 #define SPDIF_STREAM_CFG_OFFSET 0xac0
100 #define SPDIF_CTRL_OFFSET 0xac4
101 #define SPDIF_FORMAT_CFG_OFFSET 0xad8
102 #define SPDIF_MCLK_CFG_OFFSET 0xadc
104 /* AUD_FMM_IOP_PLL_0_xxx regs */
105 #define IOP_PLL_0_MACRO_OFFSET 0xb00
106 #define IOP_PLL_0_MDIV_Ch0_OFFSET 0xb14
107 #define IOP_PLL_0_MDIV_Ch1_OFFSET 0xb18
108 #define IOP_PLL_0_MDIV_Ch2_OFFSET 0xb1c
110 #define IOP_PLL_0_ACTIVE_MDIV_Ch0_OFFSET 0xb30
111 #define IOP_PLL_0_ACTIVE_MDIV_Ch1_OFFSET 0xb34
112 #define IOP_PLL_0_ACTIVE_MDIV_Ch2_OFFSET 0xb38
114 /* AUD_FMM_IOP_xxx regs */
115 #define IOP_PLL_0_CONTROL_OFFSET 0xb04
116 #define IOP_PLL_0_USER_NDIV_OFFSET 0xb08
117 #define IOP_PLL_0_ACTIVE_NDIV_OFFSET 0xb20
118 #define IOP_PLL_0_RESET_OFFSET 0xb5c
120 /* AUD_FMM_IOP_IN_I2S_xxx regs */
121 #define IN_I2S_0_STREAM_CFG_OFFSET 0x00
122 #define IN_I2S_0_CFG_OFFSET 0x04
123 #define IN_I2S_1_STREAM_CFG_OFFSET 0x40
124 #define IN_I2S_1_CFG_OFFSET 0x44
125 #define IN_I2S_2_STREAM_CFG_OFFSET 0x80
126 #define IN_I2S_2_CFG_OFFSET 0x84
128 /* AUD_FMM_IOP_MISC_xxx regs */
129 #define IOP_SW_INIT_LOGIC 0x1c0
131 /* End register offset defines */
134 /* AUD_FMM_IOP_OUT_I2S_x_MCLK_CFG_0_REG */
135 #define I2S_OUT_MCLKRATE_SHIFT 16
137 /* AUD_FMM_IOP_OUT_I2S_x_MCLK_CFG_REG */
138 #define I2S_OUT_PLLCLKSEL_SHIFT 0
140 /* AUD_FMM_IOP_OUT_I2S_x_STREAM_CFG */
141 #define I2S_OUT_STREAM_ENA 31
142 #define I2S_OUT_STREAM_CFG_GROUP_ID 20
143 #define I2S_OUT_STREAM_CFG_CHANNEL_GROUPING 24
145 /* AUD_FMM_IOP_IN_I2S_x_CAP */
146 #define I2S_IN_STREAM_CFG_CAP_ENA 31
147 #define I2S_IN_STREAM_CFG_0_GROUP_ID 4
149 /* AUD_FMM_IOP_OUT_I2S_x_I2S_CFG_REG */
150 #define I2S_OUT_CFGX_CLK_ENA 0
151 #define I2S_OUT_CFGX_DATA_ENABLE 1
152 #define I2S_OUT_CFGX_DATA_ALIGNMENT 6
153 #define I2S_OUT_CFGX_BITS_PER_SLOT 13
154 #define I2S_OUT_CFGX_VALID_SLOT 14
155 #define I2S_OUT_CFGX_FSYNC_WIDTH 18
156 #define I2S_OUT_CFGX_SCLKS_PER_1FS_DIV32 26
157 #define I2S_OUT_CFGX_SLAVE_MODE 30
158 #define I2S_OUT_CFGX_TDM_MODE 31
160 /* AUD_FMM_BF_CTRL_SOURCECH_CFGx_REG */
161 #define BF_SRC_CFGX_SFIFO_ENA 0
162 #define BF_SRC_CFGX_BUFFER_PAIR_ENABLE 1
163 #define BF_SRC_CFGX_SAMPLE_CH_MODE 2
164 #define BF_SRC_CFGX_SFIFO_SZ_DOUBLE 5
165 #define BF_SRC_CFGX_NOT_PAUSE_WHEN_EMPTY 10
166 #define BF_SRC_CFGX_BIT_RES 20
167 #define BF_SRC_CFGX_PROCESS_SEQ_ID_VALID 31
169 /* AUD_FMM_BF_CTRL_DESTCH_CFGx_REG */
170 #define BF_DST_CFGX_CAP_ENA 0
171 #define BF_DST_CFGX_BUFFER_PAIR_ENABLE 1
172 #define BF_DST_CFGX_DFIFO_SZ_DOUBLE 2
173 #define BF_DST_CFGX_NOT_PAUSE_WHEN_FULL 11
174 #define BF_DST_CFGX_FCI_ID 12
175 #define BF_DST_CFGX_CAP_MODE 24
176 #define BF_DST_CFGX_PROC_SEQ_ID_VALID 31
178 /* AUD_FMM_IOP_OUT_SPDIF_xxx */
179 #define SPDIF_0_OUT_DITHER_ENA 3
180 #define SPDIF_0_OUT_STREAM_ENA 31
182 /* AUD_FMM_IOP_PLL_0_USER */
183 #define IOP_PLL_0_USER_NDIV_FRAC 10
185 /* AUD_FMM_IOP_PLL_0_ACTIVE */
186 #define IOP_PLL_0_ACTIVE_NDIV_FRAC 10
189 #define INIT_SSP_REGS(num) (struct cygnus_ssp_regs){ \
190 .i2s_stream_cfg = OUT_I2S_ ##num## _STREAM_CFG_OFFSET, \
191 .i2s_cap_stream_cfg = IN_I2S_ ##num## _STREAM_CFG_OFFSET, \
192 .i2s_cfg = OUT_I2S_ ##num## _CFG_OFFSET, \
193 .i2s_cap_cfg = IN_I2S_ ##num## _CFG_OFFSET, \
194 .i2s_mclk_cfg = OUT_I2S_ ##num## _MCLK_CFG_OFFSET, \
195 .bf_destch_ctrl = BF_DST_CTRL ##num## _OFFSET, \
196 .bf_destch_cfg = BF_DST_CFG ##num## _OFFSET, \
197 .bf_sourcech_ctrl = BF_SRC_CTRL ##num## _OFFSET, \
198 .bf_sourcech_cfg = BF_SRC_CFG ##num## _OFFSET, \
199 .bf_sourcech_grp = BF_SRC_GRP ##num## _OFFSET \
202 struct pll_macro_entry
{
208 * PLL has 3 output channels (1x, 2x, and 4x). Below are
209 * the common MCLK frequencies used by audio driver
211 static const struct pll_macro_entry pll_predef_mclk
[] = {
237 /* List of valid frame sizes for tdm mode */
238 static const int ssp_valid_tdm_framesize
[] = {32, 64, 128, 256, 512};
241 * Use this relationship to derive the sampling rate (lrclk)
242 * lrclk = (mclk) / ((2*mclk_to_sclk_ratio) * (32 * SCLK))).
244 * Use mclk and pll_ch from the table above
246 * Valid SCLK = 0/1/2/4/8/12
248 * mclk_to_sclk_ratio = number of MCLK per SCLK. Division is twice the
249 * value programmed in this field.
250 * Valid mclk_to_sclk_ratio = 1 through to 15
252 * eg: To set lrclk = 48khz, set mclk = 12288000, mclk_to_sclk_ratio = 2,
255 struct _ssp_clk_coeff
{
262 static const struct _ssp_clk_coeff ssp_clk_coeff
[] = {
263 { 4096000, 32, 16000, 4},
264 { 4096000, 32, 32000, 2},
265 { 4096000, 64, 8000, 4},
266 { 4096000, 64, 16000, 2},
267 { 4096000, 64, 32000, 1},
268 { 4096000, 128, 8000, 2},
269 { 4096000, 128, 16000, 1},
270 { 4096000, 256, 8000, 1},
272 { 6144000, 32, 16000, 6},
273 { 6144000, 32, 32000, 3},
274 { 6144000, 32, 48000, 2},
275 { 6144000, 32, 96000, 1},
276 { 6144000, 64, 8000, 6},
277 { 6144000, 64, 16000, 3},
278 { 6144000, 64, 48000, 1},
279 { 6144000, 128, 8000, 3},
281 { 8192000, 32, 32000, 4},
282 { 8192000, 64, 16000, 4},
283 { 8192000, 64, 32000, 2},
284 { 8192000, 128, 8000, 4},
285 { 8192000, 128, 16000, 2},
286 { 8192000, 128, 32000, 1},
287 { 8192000, 256, 8000, 2},
288 { 8192000, 256, 16000, 1},
289 { 8192000, 512, 8000, 1},
291 {12288000, 32, 32000, 6},
292 {12288000, 32, 48000, 4},
293 {12288000, 32, 96000, 2},
294 {12288000, 32, 192000, 1},
295 {12288000, 64, 16000, 6},
296 {12288000, 64, 32000, 3},
297 {12288000, 64, 48000, 2},
298 {12288000, 64, 96000, 1},
299 {12288000, 128, 8000, 6},
300 {12288000, 128, 16000, 3},
301 {12288000, 128, 48000, 1},
302 {12288000, 256, 8000, 3},
304 {16384000, 64, 32000, 4},
305 {16384000, 128, 16000, 4},
306 {16384000, 128, 32000, 2},
307 {16384000, 256, 8000, 4},
308 {16384000, 256, 16000, 2},
309 {16384000, 256, 32000, 1},
310 {16384000, 512, 8000, 2},
311 {16384000, 512, 16000, 1},
313 {24576000, 32, 96000, 4},
314 {24576000, 32, 192000, 2},
315 {24576000, 64, 32000, 6},
316 {24576000, 64, 48000, 4},
317 {24576000, 64, 96000, 2},
318 {24576000, 64, 192000, 1},
319 {24576000, 128, 16000, 6},
320 {24576000, 128, 32000, 3},
321 {24576000, 128, 48000, 2},
322 {24576000, 256, 8000, 6},
323 {24576000, 256, 16000, 3},
324 {24576000, 256, 48000, 1},
325 {24576000, 512, 8000, 3},
327 {49152000, 32, 192000, 4},
328 {49152000, 64, 96000, 4},
329 {49152000, 64, 192000, 2},
330 {49152000, 128, 32000, 6},
331 {49152000, 128, 48000, 4},
332 {49152000, 128, 96000, 2},
333 {49152000, 128, 192000, 1},
334 {49152000, 256, 16000, 6},
335 {49152000, 256, 32000, 3},
336 {49152000, 256, 48000, 2},
337 {49152000, 256, 96000, 1},
338 {49152000, 512, 8000, 6},
339 {49152000, 512, 16000, 3},
340 {49152000, 512, 48000, 1},
342 { 5644800, 32, 22050, 4},
343 { 5644800, 32, 44100, 2},
344 { 5644800, 32, 88200, 1},
345 { 5644800, 64, 11025, 4},
346 { 5644800, 64, 22050, 2},
347 { 5644800, 64, 44100, 1},
349 {11289600, 32, 44100, 4},
350 {11289600, 32, 88200, 2},
351 {11289600, 32, 176400, 1},
352 {11289600, 64, 22050, 4},
353 {11289600, 64, 44100, 2},
354 {11289600, 64, 88200, 1},
355 {11289600, 128, 11025, 4},
356 {11289600, 128, 22050, 2},
357 {11289600, 128, 44100, 1},
359 {22579200, 32, 88200, 4},
360 {22579200, 32, 176400, 2},
361 {22579200, 64, 44100, 4},
362 {22579200, 64, 88200, 2},
363 {22579200, 64, 176400, 1},
364 {22579200, 128, 22050, 4},
365 {22579200, 128, 44100, 2},
366 {22579200, 128, 88200, 1},
367 {22579200, 256, 11025, 4},
368 {22579200, 256, 22050, 2},
369 {22579200, 256, 44100, 1},
371 {45158400, 32, 176400, 4},
372 {45158400, 64, 88200, 4},
373 {45158400, 64, 176400, 2},
374 {45158400, 128, 44100, 4},
375 {45158400, 128, 88200, 2},
376 {45158400, 128, 176400, 1},
377 {45158400, 256, 22050, 4},
378 {45158400, 256, 44100, 2},
379 {45158400, 256, 88200, 1},
380 {45158400, 512, 11025, 4},
381 {45158400, 512, 22050, 2},
382 {45158400, 512, 44100, 1},
385 static struct cygnus_aio_port
*cygnus_dai_get_portinfo(struct snd_soc_dai
*dai
)
387 struct cygnus_audio
*cygaud
= snd_soc_dai_get_drvdata(dai
);
389 return &cygaud
->portinfo
[dai
->id
];
392 static int audio_ssp_init_portregs(struct cygnus_aio_port
*aio
)
397 switch (aio
->port_type
) {
399 value
= readl(aio
->cygaud
->audio
+ aio
->regs
.i2s_stream_cfg
);
400 value
&= ~I2S_STREAM_CFG_MASK
;
404 aio
->cygaud
->audio
+ aio
->regs
.bf_sourcech_grp
);
406 /* Configure the AUD_FMM_IOP_OUT_I2S_x_STREAM_CFG reg */
407 value
|= aio
->portnum
<< I2S_OUT_STREAM_CFG_GROUP_ID
;
408 value
|= aio
->portnum
; /* FCI ID is the port num */
409 value
|= CH_GRP_STEREO
<< I2S_OUT_STREAM_CFG_CHANNEL_GROUPING
;
410 writel(value
, aio
->cygaud
->audio
+ aio
->regs
.i2s_stream_cfg
);
412 /* Configure the AUD_FMM_BF_CTRL_SOURCECH_CFGX reg */
413 value
= readl(aio
->cygaud
->audio
+ aio
->regs
.bf_sourcech_cfg
);
414 value
&= ~BIT(BF_SRC_CFGX_NOT_PAUSE_WHEN_EMPTY
);
415 value
|= BIT(BF_SRC_CFGX_SFIFO_SZ_DOUBLE
);
416 value
|= BIT(BF_SRC_CFGX_PROCESS_SEQ_ID_VALID
);
417 writel(value
, aio
->cygaud
->audio
+ aio
->regs
.bf_sourcech_cfg
);
419 /* Configure the AUD_FMM_IOP_IN_I2S_x_CAP_STREAM_CFG_0 reg */
420 value
= readl(aio
->cygaud
->i2s_in
+
421 aio
->regs
.i2s_cap_stream_cfg
);
422 value
&= ~I2S_CAP_STREAM_CFG_MASK
;
423 value
|= aio
->portnum
<< I2S_IN_STREAM_CFG_0_GROUP_ID
;
424 writel(value
, aio
->cygaud
->i2s_in
+
425 aio
->regs
.i2s_cap_stream_cfg
);
427 /* Configure the AUD_FMM_BF_CTRL_DESTCH_CFGX_REG_BASE reg */
428 fci_id
= CAPTURE_FCI_ID_BASE
+ aio
->portnum
;
430 value
= readl(aio
->cygaud
->audio
+ aio
->regs
.bf_destch_cfg
);
431 value
|= BIT(BF_DST_CFGX_DFIFO_SZ_DOUBLE
);
432 value
&= ~BIT(BF_DST_CFGX_NOT_PAUSE_WHEN_FULL
);
433 value
|= (fci_id
<< BF_DST_CFGX_FCI_ID
);
434 value
|= BIT(BF_DST_CFGX_PROC_SEQ_ID_VALID
);
435 writel(value
, aio
->cygaud
->audio
+ aio
->regs
.bf_destch_cfg
);
437 /* Enable the transmit pin for this port */
438 value
= readl(aio
->cygaud
->audio
+ AUD_MISC_SEROUT_OE_REG_BASE
);
439 value
&= ~BIT((aio
->portnum
* 4) + AUD_MISC_SEROUT_SDAT_OE
);
440 writel(value
, aio
->cygaud
->audio
+ AUD_MISC_SEROUT_OE_REG_BASE
);
443 writel(aio
->portnum
, aio
->cygaud
->audio
+ BF_SRC_GRP3_OFFSET
);
445 value
= readl(aio
->cygaud
->audio
+ SPDIF_CTRL_OFFSET
);
446 value
|= BIT(SPDIF_0_OUT_DITHER_ENA
);
447 writel(value
, aio
->cygaud
->audio
+ SPDIF_CTRL_OFFSET
);
449 /* Enable and set the FCI ID for the SPDIF channel */
450 value
= readl(aio
->cygaud
->audio
+ SPDIF_STREAM_CFG_OFFSET
);
451 value
&= ~SPDIF_STREAM_CFG_MASK
;
452 value
|= aio
->portnum
; /* FCI ID is the port num */
453 value
|= BIT(SPDIF_0_OUT_STREAM_ENA
);
454 writel(value
, aio
->cygaud
->audio
+ SPDIF_STREAM_CFG_OFFSET
);
456 value
= readl(aio
->cygaud
->audio
+ aio
->regs
.bf_sourcech_cfg
);
457 value
&= ~BIT(BF_SRC_CFGX_NOT_PAUSE_WHEN_EMPTY
);
458 value
|= BIT(BF_SRC_CFGX_SFIFO_SZ_DOUBLE
);
459 value
|= BIT(BF_SRC_CFGX_PROCESS_SEQ_ID_VALID
);
460 writel(value
, aio
->cygaud
->audio
+ aio
->regs
.bf_sourcech_cfg
);
462 /* Enable the spdif output pin */
463 value
= readl(aio
->cygaud
->audio
+ AUD_MISC_SEROUT_OE_REG_BASE
);
464 value
&= ~BIT(AUD_MISC_SEROUT_SPDIF_OE
);
465 writel(value
, aio
->cygaud
->audio
+ AUD_MISC_SEROUT_OE_REG_BASE
);
468 dev_err(aio
->cygaud
->dev
, "Port not supported\n");
475 static void audio_ssp_in_enable(struct cygnus_aio_port
*aio
)
479 value
= readl(aio
->cygaud
->audio
+ aio
->regs
.bf_destch_cfg
);
480 value
|= BIT(BF_DST_CFGX_CAP_ENA
);
481 writel(value
, aio
->cygaud
->audio
+ aio
->regs
.bf_destch_cfg
);
483 writel(0x1, aio
->cygaud
->audio
+ aio
->regs
.bf_destch_ctrl
);
485 value
= readl(aio
->cygaud
->audio
+ aio
->regs
.i2s_cfg
);
486 value
|= BIT(I2S_OUT_CFGX_CLK_ENA
);
487 value
|= BIT(I2S_OUT_CFGX_DATA_ENABLE
);
488 writel(value
, aio
->cygaud
->audio
+ aio
->regs
.i2s_cfg
);
490 value
= readl(aio
->cygaud
->i2s_in
+ aio
->regs
.i2s_cap_stream_cfg
);
491 value
|= BIT(I2S_IN_STREAM_CFG_CAP_ENA
);
492 writel(value
, aio
->cygaud
->i2s_in
+ aio
->regs
.i2s_cap_stream_cfg
);
494 aio
->streams_on
|= CAPTURE_STREAM_MASK
;
497 static void audio_ssp_in_disable(struct cygnus_aio_port
*aio
)
501 value
= readl(aio
->cygaud
->i2s_in
+ aio
->regs
.i2s_cap_stream_cfg
);
502 value
&= ~BIT(I2S_IN_STREAM_CFG_CAP_ENA
);
503 writel(value
, aio
->cygaud
->i2s_in
+ aio
->regs
.i2s_cap_stream_cfg
);
505 aio
->streams_on
&= ~CAPTURE_STREAM_MASK
;
507 /* If both playback and capture are off */
508 if (!aio
->streams_on
) {
509 value
= readl(aio
->cygaud
->audio
+ aio
->regs
.i2s_cfg
);
510 value
&= ~BIT(I2S_OUT_CFGX_CLK_ENA
);
511 value
&= ~BIT(I2S_OUT_CFGX_DATA_ENABLE
);
512 writel(value
, aio
->cygaud
->audio
+ aio
->regs
.i2s_cfg
);
515 writel(0x0, aio
->cygaud
->audio
+ aio
->regs
.bf_destch_ctrl
);
517 value
= readl(aio
->cygaud
->audio
+ aio
->regs
.bf_destch_cfg
);
518 value
&= ~BIT(BF_DST_CFGX_CAP_ENA
);
519 writel(value
, aio
->cygaud
->audio
+ aio
->regs
.bf_destch_cfg
);
522 static int audio_ssp_out_enable(struct cygnus_aio_port
*aio
)
527 switch (aio
->port_type
) {
529 value
= readl(aio
->cygaud
->audio
+ aio
->regs
.i2s_stream_cfg
);
530 value
|= BIT(I2S_OUT_STREAM_ENA
);
531 writel(value
, aio
->cygaud
->audio
+ aio
->regs
.i2s_stream_cfg
);
533 writel(1, aio
->cygaud
->audio
+ aio
->regs
.bf_sourcech_ctrl
);
535 value
= readl(aio
->cygaud
->audio
+ aio
->regs
.i2s_cfg
);
536 value
|= BIT(I2S_OUT_CFGX_CLK_ENA
);
537 value
|= BIT(I2S_OUT_CFGX_DATA_ENABLE
);
538 writel(value
, aio
->cygaud
->audio
+ aio
->regs
.i2s_cfg
);
540 value
= readl(aio
->cygaud
->audio
+ aio
->regs
.bf_sourcech_cfg
);
541 value
|= BIT(BF_SRC_CFGX_SFIFO_ENA
);
542 writel(value
, aio
->cygaud
->audio
+ aio
->regs
.bf_sourcech_cfg
);
544 aio
->streams_on
|= PLAYBACK_STREAM_MASK
;
547 value
= readl(aio
->cygaud
->audio
+ SPDIF_FORMAT_CFG_OFFSET
);
549 writel(value
, aio
->cygaud
->audio
+ SPDIF_FORMAT_CFG_OFFSET
);
551 writel(1, aio
->cygaud
->audio
+ aio
->regs
.bf_sourcech_ctrl
);
553 value
= readl(aio
->cygaud
->audio
+ aio
->regs
.bf_sourcech_cfg
);
554 value
|= BIT(BF_SRC_CFGX_SFIFO_ENA
);
555 writel(value
, aio
->cygaud
->audio
+ aio
->regs
.bf_sourcech_cfg
);
558 dev_err(aio
->cygaud
->dev
,
559 "Port not supported %d\n", aio
->portnum
);
566 static int audio_ssp_out_disable(struct cygnus_aio_port
*aio
)
571 switch (aio
->port_type
) {
573 aio
->streams_on
&= ~PLAYBACK_STREAM_MASK
;
575 /* If both playback and capture are off */
576 if (!aio
->streams_on
) {
577 value
= readl(aio
->cygaud
->audio
+ aio
->regs
.i2s_cfg
);
578 value
&= ~BIT(I2S_OUT_CFGX_CLK_ENA
);
579 value
&= ~BIT(I2S_OUT_CFGX_DATA_ENABLE
);
580 writel(value
, aio
->cygaud
->audio
+ aio
->regs
.i2s_cfg
);
583 /* set group_sync_dis = 1 */
584 value
= readl(aio
->cygaud
->audio
+ BF_SRC_GRP_SYNC_DIS_OFFSET
);
585 value
|= BIT(aio
->portnum
);
586 writel(value
, aio
->cygaud
->audio
+ BF_SRC_GRP_SYNC_DIS_OFFSET
);
588 writel(0, aio
->cygaud
->audio
+ aio
->regs
.bf_sourcech_ctrl
);
590 value
= readl(aio
->cygaud
->audio
+ aio
->regs
.bf_sourcech_cfg
);
591 value
&= ~BIT(BF_SRC_CFGX_SFIFO_ENA
);
592 writel(value
, aio
->cygaud
->audio
+ aio
->regs
.bf_sourcech_cfg
);
594 /* set group_sync_dis = 0 */
595 value
= readl(aio
->cygaud
->audio
+ BF_SRC_GRP_SYNC_DIS_OFFSET
);
596 value
&= ~BIT(aio
->portnum
);
597 writel(value
, aio
->cygaud
->audio
+ BF_SRC_GRP_SYNC_DIS_OFFSET
);
599 value
= readl(aio
->cygaud
->audio
+ aio
->regs
.i2s_stream_cfg
);
600 value
&= ~BIT(I2S_OUT_STREAM_ENA
);
601 writel(value
, aio
->cygaud
->audio
+ aio
->regs
.i2s_stream_cfg
);
603 /* IOP SW INIT on OUT_I2S_x */
604 value
= readl(aio
->cygaud
->i2s_in
+ IOP_SW_INIT_LOGIC
);
605 value
|= BIT(aio
->portnum
);
606 writel(value
, aio
->cygaud
->i2s_in
+ IOP_SW_INIT_LOGIC
);
607 value
&= ~BIT(aio
->portnum
);
608 writel(value
, aio
->cygaud
->i2s_in
+ IOP_SW_INIT_LOGIC
);
611 value
= readl(aio
->cygaud
->audio
+ SPDIF_FORMAT_CFG_OFFSET
);
613 writel(value
, aio
->cygaud
->audio
+ SPDIF_FORMAT_CFG_OFFSET
);
614 writel(0, aio
->cygaud
->audio
+ aio
->regs
.bf_sourcech_ctrl
);
616 value
= readl(aio
->cygaud
->audio
+ aio
->regs
.bf_sourcech_cfg
);
617 value
&= ~BIT(BF_SRC_CFGX_SFIFO_ENA
);
618 writel(value
, aio
->cygaud
->audio
+ aio
->regs
.bf_sourcech_cfg
);
621 dev_err(aio
->cygaud
->dev
,
622 "Port not supported %d\n", aio
->portnum
);
629 static int pll_configure_mclk(struct cygnus_audio
*cygaud
, u32 mclk
,
630 struct cygnus_aio_port
*aio
)
634 const struct pll_macro_entry
*p_entry
;
637 for (i
= 0; i
< ARRAY_SIZE(pll_predef_mclk
); i
++) {
638 p_entry
= &pll_predef_mclk
[i
];
639 if (p_entry
->mclk
== mclk
) {
646 "%s No valid mclk freq (%u) found!\n", __func__
, mclk
);
650 ch_clk
= cygaud
->audio_clk
[p_entry
->pll_ch_num
];
652 if ((aio
->clk_trace
.cap_en
) && (!aio
->clk_trace
.cap_clk_en
)) {
653 error
= clk_prepare_enable(ch_clk
);
655 dev_err(cygaud
->dev
, "%s clk_prepare_enable failed %d\n",
659 aio
->clk_trace
.cap_clk_en
= true;
662 if ((aio
->clk_trace
.play_en
) && (!aio
->clk_trace
.play_clk_en
)) {
663 error
= clk_prepare_enable(ch_clk
);
665 dev_err(cygaud
->dev
, "%s clk_prepare_enable failed %d\n",
669 aio
->clk_trace
.play_clk_en
= true;
672 error
= clk_set_rate(ch_clk
, mclk
);
674 dev_err(cygaud
->dev
, "%s Set MCLK rate failed: %d\n",
679 return p_entry
->pll_ch_num
;
682 static int cygnus_ssp_set_clocks(struct cygnus_aio_port
*aio
,
683 struct cygnus_audio
*cygaud
)
689 const struct _ssp_clk_coeff
*p_entry
= NULL
;
691 for (i
= 0; i
< ARRAY_SIZE(ssp_clk_coeff
); i
++) {
692 p_entry
= &ssp_clk_coeff
[i
];
693 if ((p_entry
->rate
== aio
->lrclk
) &&
694 (p_entry
->sclk_rate
== aio
->bit_per_frame
) &&
695 (p_entry
->mclk
== aio
->mclk
)) {
701 dev_err(aio
->cygaud
->dev
,
702 "No valid match found in ssp_clk_coeff array\n");
703 dev_err(aio
->cygaud
->dev
, "lrclk = %u, bits/frame = %u, mclk = %u\n",
704 aio
->lrclk
, aio
->bit_per_frame
, aio
->mclk
);
708 sclk
= aio
->bit_per_frame
;
711 /* sclks_per_1fs_div = sclk cycles/32 */
714 switch (aio
->port_type
) {
716 /* Set number of bitclks per frame */
717 value
= readl(aio
->cygaud
->audio
+ aio
->regs
.i2s_cfg
);
718 value
&= ~(mask
<< I2S_OUT_CFGX_SCLKS_PER_1FS_DIV32
);
719 value
|= sclk
<< I2S_OUT_CFGX_SCLKS_PER_1FS_DIV32
;
720 writel(value
, aio
->cygaud
->audio
+ aio
->regs
.i2s_cfg
);
721 dev_dbg(aio
->cygaud
->dev
,
722 "SCLKS_PER_1FS_DIV32 = 0x%x\n", value
);
727 dev_err(aio
->cygaud
->dev
, "Unknown port type\n");
731 /* Set MCLK_RATE ssp port (spdif and ssp are the same) */
732 value
= readl(aio
->cygaud
->audio
+ aio
->regs
.i2s_mclk_cfg
);
733 value
&= ~(0xf << I2S_OUT_MCLKRATE_SHIFT
);
734 value
|= (p_entry
->mclk_rate
<< I2S_OUT_MCLKRATE_SHIFT
);
735 writel(value
, aio
->cygaud
->audio
+ aio
->regs
.i2s_mclk_cfg
);
737 dev_dbg(aio
->cygaud
->dev
, "mclk cfg reg = 0x%x\n", value
);
738 dev_dbg(aio
->cygaud
->dev
, "bits per frame = %u, mclk = %u Hz, lrclk = %u Hz\n",
739 aio
->bit_per_frame
, aio
->mclk
, aio
->lrclk
);
743 static int cygnus_ssp_hw_params(struct snd_pcm_substream
*substream
,
744 struct snd_pcm_hw_params
*params
,
745 struct snd_soc_dai
*dai
)
747 struct cygnus_aio_port
*aio
= cygnus_dai_get_portinfo(dai
);
748 struct cygnus_audio
*cygaud
= snd_soc_dai_get_drvdata(dai
);
754 dev_dbg(aio
->cygaud
->dev
, "%s port = %d\n", __func__
, aio
->portnum
);
755 dev_dbg(aio
->cygaud
->dev
, "params_channels %d\n",
756 params_channels(params
));
757 dev_dbg(aio
->cygaud
->dev
, "rate %d\n", params_rate(params
));
758 dev_dbg(aio
->cygaud
->dev
, "format %d\n", params_format(params
));
760 rate
= params_rate(params
);
763 case CYGNUS_SSPMODE_TDM
:
764 if ((rate
== 192000) && (params_channels(params
) > 4)) {
765 dev_err(aio
->cygaud
->dev
, "Cannot run %d channels at %dHz\n",
766 params_channels(params
), rate
);
770 case CYGNUS_SSPMODE_I2S
:
771 aio
->bit_per_frame
= 64; /* I2S must be 64 bit per frame */
774 dev_err(aio
->cygaud
->dev
,
775 "%s port running in unknown mode\n", __func__
);
779 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
780 value
= readl(aio
->cygaud
->audio
+ aio
->regs
.bf_sourcech_cfg
);
781 value
&= ~BIT(BF_SRC_CFGX_BUFFER_PAIR_ENABLE
);
782 /* Configure channels as mono or stereo/TDM */
783 if (params_channels(params
) == 1)
784 value
|= BIT(BF_SRC_CFGX_SAMPLE_CH_MODE
);
786 value
&= ~BIT(BF_SRC_CFGX_SAMPLE_CH_MODE
);
787 writel(value
, aio
->cygaud
->audio
+ aio
->regs
.bf_sourcech_cfg
);
789 switch (params_format(params
)) {
790 case SNDRV_PCM_FORMAT_S8
:
791 if (aio
->port_type
== PORT_SPDIF
) {
792 dev_err(aio
->cygaud
->dev
,
793 "SPDIF does not support 8bit format\n");
799 case SNDRV_PCM_FORMAT_S16_LE
:
803 case SNDRV_PCM_FORMAT_S32_LE
:
804 /* 32 bit mode is coded as 0 */
812 value
= readl(aio
->cygaud
->audio
+ aio
->regs
.bf_sourcech_cfg
);
813 value
&= ~(mask
<< BF_SRC_CFGX_BIT_RES
);
814 value
|= (bitres
<< BF_SRC_CFGX_BIT_RES
);
815 writel(value
, aio
->cygaud
->audio
+ aio
->regs
.bf_sourcech_cfg
);
819 switch (params_format(params
)) {
820 case SNDRV_PCM_FORMAT_S16_LE
:
821 value
= readl(aio
->cygaud
->audio
+
822 aio
->regs
.bf_destch_cfg
);
823 value
|= BIT(BF_DST_CFGX_CAP_MODE
);
824 writel(value
, aio
->cygaud
->audio
+
825 aio
->regs
.bf_destch_cfg
);
828 case SNDRV_PCM_FORMAT_S32_LE
:
829 value
= readl(aio
->cygaud
->audio
+
830 aio
->regs
.bf_destch_cfg
);
831 value
&= ~BIT(BF_DST_CFGX_CAP_MODE
);
832 writel(value
, aio
->cygaud
->audio
+
833 aio
->regs
.bf_destch_cfg
);
844 ret
= cygnus_ssp_set_clocks(aio
, cygaud
);
850 * This function sets the mclk frequency for pll clock
852 static int cygnus_ssp_set_sysclk(struct snd_soc_dai
*dai
,
853 int clk_id
, unsigned int freq
, int dir
)
857 struct cygnus_aio_port
*aio
= cygnus_dai_get_portinfo(dai
);
858 struct cygnus_audio
*cygaud
= snd_soc_dai_get_drvdata(dai
);
860 dev_dbg(aio
->cygaud
->dev
,
861 "%s Enter port = %d\n", __func__
, aio
->portnum
);
862 sel
= pll_configure_mclk(cygaud
, freq
, aio
);
864 dev_err(aio
->cygaud
->dev
,
865 "%s Setting mclk failed.\n", __func__
);
871 dev_dbg(aio
->cygaud
->dev
, "%s Setting MCLKSEL to %d\n", __func__
, sel
);
872 value
= readl(aio
->cygaud
->audio
+ aio
->regs
.i2s_mclk_cfg
);
873 value
&= ~(0xf << I2S_OUT_PLLCLKSEL_SHIFT
);
874 value
|= (sel
<< I2S_OUT_PLLCLKSEL_SHIFT
);
875 writel(value
, aio
->cygaud
->audio
+ aio
->regs
.i2s_mclk_cfg
);
880 static int cygnus_ssp_startup(struct snd_pcm_substream
*substream
,
881 struct snd_soc_dai
*dai
)
883 struct cygnus_aio_port
*aio
= cygnus_dai_get_portinfo(dai
);
885 snd_soc_dai_set_dma_data(dai
, substream
, aio
);
886 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
887 aio
->clk_trace
.play_en
= true;
889 aio
->clk_trace
.cap_en
= true;
894 static void cygnus_ssp_shutdown(struct snd_pcm_substream
*substream
,
895 struct snd_soc_dai
*dai
)
897 struct cygnus_aio_port
*aio
= cygnus_dai_get_portinfo(dai
);
899 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
900 aio
->clk_trace
.play_en
= false;
902 aio
->clk_trace
.cap_en
= false;
904 if (!aio
->is_slave
) {
907 val
= readl(aio
->cygaud
->audio
+ aio
->regs
.i2s_mclk_cfg
);
908 val
&= CYGNUS_PLLCLKSEL_MASK
;
909 if (val
>= ARRAY_SIZE(aio
->cygaud
->audio_clk
)) {
910 dev_err(aio
->cygaud
->dev
, "Clk index %u is out of bounds\n",
915 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
916 if (aio
->clk_trace
.play_clk_en
) {
917 clk_disable_unprepare(aio
->cygaud
->
919 aio
->clk_trace
.play_clk_en
= false;
922 if (aio
->clk_trace
.cap_clk_en
) {
923 clk_disable_unprepare(aio
->cygaud
->
925 aio
->clk_trace
.cap_clk_en
= false;
933 * 31 Yes TDM Mode (1 = TDM, 0 = i2s)
934 * 30 Yes Slave Mode (1 = Slave, 0 = Master)
935 * 29:26 No Sclks per frame
937 * 17:14 No Valid Slots
938 * 13 No Bits (1 = 16 bits, 0 = 32 bits)
939 * 12:08 No Bits per samp
940 * 07 Yes Justifcation (1 = LSB, 0 = MSB)
941 * 06 Yes Alignment (1 = Delay 1 clk, 0 = no delay
942 * 05 Yes SCLK polarity (1 = Rising, 0 = Falling)
943 * 04 Yes LRCLK Polarity (1 = High for left, 0 = Low for left)
944 * 03:02 Yes Reserved - write as zero
948 #define I2S_OUT_CFG_REG_UPDATE_MASK 0x3C03FF03
950 /* Input cfg is same as output, but the FS width is not a valid field */
951 #define I2S_IN_CFG_REG_UPDATE_MASK (I2S_OUT_CFG_REG_UPDATE_MASK | 0x03FC0000)
953 int cygnus_ssp_set_custom_fsync_width(struct snd_soc_dai
*cpu_dai
, int len
)
955 struct cygnus_aio_port
*aio
= cygnus_dai_get_portinfo(cpu_dai
);
957 if ((len
> 0) && (len
< 256)) {
958 aio
->fsync_width
= len
;
965 static int cygnus_ssp_set_fmt(struct snd_soc_dai
*cpu_dai
, unsigned int fmt
)
967 struct cygnus_aio_port
*aio
= cygnus_dai_get_portinfo(cpu_dai
);
975 dev_dbg(aio
->cygaud
->dev
, "%s Enter fmt: %x\n", __func__
, fmt
);
977 if (aio
->port_type
== PORT_SPDIF
)
982 switch (fmt
& SND_SOC_DAIFMT_MASTER_MASK
) {
983 case SND_SOC_DAIFMT_CBM_CFM
:
984 ssp_newcfg
|= BIT(I2S_OUT_CFGX_SLAVE_MODE
);
987 case SND_SOC_DAIFMT_CBS_CFS
:
988 ssp_newcfg
&= ~BIT(I2S_OUT_CFGX_SLAVE_MODE
);
995 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
996 case SND_SOC_DAIFMT_I2S
:
997 ssp_newcfg
|= BIT(I2S_OUT_CFGX_DATA_ALIGNMENT
);
998 ssp_newcfg
|= BIT(I2S_OUT_CFGX_FSYNC_WIDTH
);
999 aio
->mode
= CYGNUS_SSPMODE_I2S
;
1002 case SND_SOC_DAIFMT_DSP_A
:
1003 case SND_SOC_DAIFMT_DSP_B
:
1004 ssp_newcfg
|= BIT(I2S_OUT_CFGX_TDM_MODE
);
1006 /* DSP_A = data after FS, DSP_B = data during FS */
1007 if ((fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) == SND_SOC_DAIFMT_DSP_A
)
1008 ssp_newcfg
|= BIT(I2S_OUT_CFGX_DATA_ALIGNMENT
);
1010 if ((aio
->fsync_width
> 0) && (aio
->fsync_width
< 256))
1012 (aio
->fsync_width
<< I2S_OUT_CFGX_FSYNC_WIDTH
);
1014 ssp_newcfg
|= BIT(I2S_OUT_CFGX_FSYNC_WIDTH
);
1016 aio
->mode
= CYGNUS_SSPMODE_TDM
;
1025 * Retain bits we do not want to update, then OR in new bits
1027 ssp_curcfg
= readl(aio
->cygaud
->audio
+ aio
->regs
.i2s_cfg
);
1028 ssp_outcfg
= (ssp_curcfg
& I2S_OUT_CFG_REG_UPDATE_MASK
) | ssp_newcfg
;
1029 writel(ssp_outcfg
, aio
->cygaud
->audio
+ aio
->regs
.i2s_cfg
);
1033 * Retain bits we do not want to update, then OR in new bits
1035 ssp_curcfg
= readl(aio
->cygaud
->i2s_in
+ aio
->regs
.i2s_cap_cfg
);
1036 ssp_incfg
= (ssp_curcfg
& I2S_IN_CFG_REG_UPDATE_MASK
) | ssp_newcfg
;
1037 writel(ssp_incfg
, aio
->cygaud
->i2s_in
+ aio
->regs
.i2s_cap_cfg
);
1039 val
= readl(aio
->cygaud
->audio
+ AUD_MISC_SEROUT_OE_REG_BASE
);
1042 * Configure the word clk and bit clk as output or tristate
1043 * Each port has 4 bits for controlling its pins.
1044 * Shift the mask based upon port number.
1046 mask
= BIT(AUD_MISC_SEROUT_LRCK_OE
)
1047 | BIT(AUD_MISC_SEROUT_SCLK_OE
)
1048 | BIT(AUD_MISC_SEROUT_MCLK_OE
);
1049 mask
= mask
<< (aio
->portnum
* 4);
1051 /* Set bit for tri-state */
1054 /* Clear bit for drive */
1057 dev_dbg(aio
->cygaud
->dev
, "%s Set OE bits 0x%x\n", __func__
, val
);
1058 writel(val
, aio
->cygaud
->audio
+ AUD_MISC_SEROUT_OE_REG_BASE
);
1063 static int cygnus_ssp_trigger(struct snd_pcm_substream
*substream
, int cmd
,
1064 struct snd_soc_dai
*dai
)
1066 struct cygnus_aio_port
*aio
= cygnus_dai_get_portinfo(dai
);
1067 struct cygnus_audio
*cygaud
= snd_soc_dai_get_drvdata(dai
);
1069 dev_dbg(aio
->cygaud
->dev
,
1070 "%s cmd %d at port = %d\n", __func__
, cmd
, aio
->portnum
);
1073 case SNDRV_PCM_TRIGGER_START
:
1074 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
1075 case SNDRV_PCM_TRIGGER_RESUME
:
1076 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
1077 audio_ssp_out_enable(aio
);
1079 audio_ssp_in_enable(aio
);
1080 cygaud
->active_ports
++;
1084 case SNDRV_PCM_TRIGGER_STOP
:
1085 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
1086 case SNDRV_PCM_TRIGGER_SUSPEND
:
1087 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
1088 audio_ssp_out_disable(aio
);
1090 audio_ssp_in_disable(aio
);
1091 cygaud
->active_ports
--;
1101 static int cygnus_set_dai_tdm_slot(struct snd_soc_dai
*cpu_dai
,
1102 unsigned int tx_mask
, unsigned int rx_mask
, int slots
, int slot_width
)
1104 struct cygnus_aio_port
*aio
= cygnus_dai_get_portinfo(cpu_dai
);
1106 int bits_per_slot
= 0; /* default to 32-bits per slot */
1108 unsigned int active_slots
;
1112 if (tx_mask
!= rx_mask
) {
1113 dev_err(aio
->cygaud
->dev
,
1114 "%s tx_mask must equal rx_mask\n", __func__
);
1118 active_slots
= hweight32(tx_mask
);
1120 if ((active_slots
< 0) || (active_slots
> 16))
1123 /* Slot value must be even */
1124 if (active_slots
% 2)
1127 /* We encode 16 slots as 0 in the reg */
1128 if (active_slots
== 16)
1131 /* Slot Width is either 16 or 32 */
1132 switch (slot_width
) {
1141 dev_warn(aio
->cygaud
->dev
,
1142 "%s Defaulting Slot Width to 32\n", __func__
);
1145 frame_bits
= slots
* slot_width
;
1147 for (i
= 0; i
< ARRAY_SIZE(ssp_valid_tdm_framesize
); i
++) {
1148 if (ssp_valid_tdm_framesize
[i
] == frame_bits
) {
1155 dev_err(aio
->cygaud
->dev
,
1156 "%s In TDM mode, frame bits INVALID (%d)\n",
1157 __func__
, frame_bits
);
1161 aio
->bit_per_frame
= frame_bits
;
1163 dev_dbg(aio
->cygaud
->dev
, "%s active_slots %u, bits per frame %d\n",
1164 __func__
, active_slots
, frame_bits
);
1166 /* Set capture side of ssp port */
1167 value
= readl(aio
->cygaud
->i2s_in
+ aio
->regs
.i2s_cap_cfg
);
1168 value
&= ~(0xf << I2S_OUT_CFGX_VALID_SLOT
);
1169 value
|= (active_slots
<< I2S_OUT_CFGX_VALID_SLOT
);
1170 value
&= ~BIT(I2S_OUT_CFGX_BITS_PER_SLOT
);
1171 value
|= (bits_per_slot
<< I2S_OUT_CFGX_BITS_PER_SLOT
);
1172 writel(value
, aio
->cygaud
->i2s_in
+ aio
->regs
.i2s_cap_cfg
);
1174 /* Set playback side of ssp port */
1175 value
= readl(aio
->cygaud
->audio
+ aio
->regs
.i2s_cfg
);
1176 value
&= ~(0xf << I2S_OUT_CFGX_VALID_SLOT
);
1177 value
|= (active_slots
<< I2S_OUT_CFGX_VALID_SLOT
);
1178 value
&= ~BIT(I2S_OUT_CFGX_BITS_PER_SLOT
);
1179 value
|= (bits_per_slot
<< I2S_OUT_CFGX_BITS_PER_SLOT
);
1180 writel(value
, aio
->cygaud
->audio
+ aio
->regs
.i2s_cfg
);
1185 #ifdef CONFIG_PM_SLEEP
1186 static int cygnus_ssp_suspend(struct snd_soc_dai
*cpu_dai
)
1188 struct cygnus_aio_port
*aio
= cygnus_dai_get_portinfo(cpu_dai
);
1190 if (!aio
->is_slave
) {
1193 val
= readl(aio
->cygaud
->audio
+ aio
->regs
.i2s_mclk_cfg
);
1194 val
&= CYGNUS_PLLCLKSEL_MASK
;
1195 if (val
>= ARRAY_SIZE(aio
->cygaud
->audio_clk
)) {
1196 dev_err(aio
->cygaud
->dev
, "Clk index %u is out of bounds\n",
1201 if (aio
->clk_trace
.cap_clk_en
)
1202 clk_disable_unprepare(aio
->cygaud
->audio_clk
[val
]);
1203 if (aio
->clk_trace
.play_clk_en
)
1204 clk_disable_unprepare(aio
->cygaud
->audio_clk
[val
]);
1206 aio
->pll_clk_num
= val
;
1212 static int cygnus_ssp_resume(struct snd_soc_dai
*cpu_dai
)
1214 struct cygnus_aio_port
*aio
= cygnus_dai_get_portinfo(cpu_dai
);
1217 if (!aio
->is_slave
) {
1218 if (aio
->clk_trace
.cap_clk_en
) {
1219 error
= clk_prepare_enable(aio
->cygaud
->
1220 audio_clk
[aio
->pll_clk_num
]);
1222 dev_err(aio
->cygaud
->dev
, "%s clk_prepare_enable failed\n",
1227 if (aio
->clk_trace
.play_clk_en
) {
1228 error
= clk_prepare_enable(aio
->cygaud
->
1229 audio_clk
[aio
->pll_clk_num
]);
1231 if (aio
->clk_trace
.cap_clk_en
)
1232 clk_disable_unprepare(aio
->cygaud
->
1233 audio_clk
[aio
->pll_clk_num
]);
1234 dev_err(aio
->cygaud
->dev
, "%s clk_prepare_enable failed\n",
1244 #define cygnus_ssp_suspend NULL
1245 #define cygnus_ssp_resume NULL
1248 static const struct snd_soc_dai_ops cygnus_ssp_dai_ops
= {
1249 .startup
= cygnus_ssp_startup
,
1250 .shutdown
= cygnus_ssp_shutdown
,
1251 .trigger
= cygnus_ssp_trigger
,
1252 .hw_params
= cygnus_ssp_hw_params
,
1253 .set_fmt
= cygnus_ssp_set_fmt
,
1254 .set_sysclk
= cygnus_ssp_set_sysclk
,
1255 .set_tdm_slot
= cygnus_set_dai_tdm_slot
,
1259 #define INIT_CPU_DAI(num) { \
1260 .name = "cygnus-ssp" #num, \
1262 .channels_min = 1, \
1263 .channels_max = 16, \
1264 .rates = CYGNUS_TDM_RATE | SNDRV_PCM_RATE_88200 | \
1265 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | \
1266 SNDRV_PCM_RATE_192000, \
1267 .formats = SNDRV_PCM_FMTBIT_S8 | \
1268 SNDRV_PCM_FMTBIT_S16_LE | \
1269 SNDRV_PCM_FMTBIT_S32_LE, \
1272 .channels_min = 2, \
1273 .channels_max = 16, \
1274 .rates = CYGNUS_TDM_RATE | SNDRV_PCM_RATE_88200 | \
1275 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | \
1276 SNDRV_PCM_RATE_192000, \
1277 .formats = SNDRV_PCM_FMTBIT_S16_LE | \
1278 SNDRV_PCM_FMTBIT_S32_LE, \
1280 .ops = &cygnus_ssp_dai_ops, \
1281 .suspend = cygnus_ssp_suspend, \
1282 .resume = cygnus_ssp_resume, \
1285 static const struct snd_soc_dai_driver cygnus_ssp_dai_info
[] = {
1291 static struct snd_soc_dai_driver cygnus_spdif_dai_info
= {
1292 .name
= "cygnus-spdif",
1296 .rates
= CYGNUS_TDM_RATE
| SNDRV_PCM_RATE_88200
|
1297 SNDRV_PCM_RATE_96000
| SNDRV_PCM_RATE_176400
|
1298 SNDRV_PCM_RATE_192000
,
1299 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
1300 SNDRV_PCM_FMTBIT_S32_LE
,
1302 .ops
= &cygnus_ssp_dai_ops
,
1303 .suspend
= cygnus_ssp_suspend
,
1304 .resume
= cygnus_ssp_resume
,
1307 static struct snd_soc_dai_driver cygnus_ssp_dai
[CYGNUS_MAX_PORTS
];
1309 static const struct snd_soc_component_driver cygnus_ssp_component
= {
1310 .name
= "cygnus-audio",
1314 * Return < 0 if error
1315 * Return 0 if disabled
1316 * Return 1 if enabled and node is parsed successfully
1318 static int parse_ssp_child_node(struct platform_device
*pdev
,
1319 struct device_node
*dn
,
1320 struct cygnus_audio
*cygaud
,
1321 struct snd_soc_dai_driver
*p_dai
)
1323 struct cygnus_aio_port
*aio
;
1324 struct cygnus_ssp_regs ssp_regs
[3];
1327 enum cygnus_audio_port_type port_type
;
1329 if (of_property_read_u32(dn
, "reg", &rawval
)) {
1330 dev_err(&pdev
->dev
, "Missing reg property\n");
1337 ssp_regs
[0] = INIT_SSP_REGS(0);
1338 port_type
= PORT_TDM
;
1341 ssp_regs
[1] = INIT_SSP_REGS(1);
1342 port_type
= PORT_TDM
;
1345 ssp_regs
[2] = INIT_SSP_REGS(2);
1346 port_type
= PORT_TDM
;
1349 port_type
= PORT_SPDIF
;
1352 dev_err(&pdev
->dev
, "Bad value for reg %u\n", rawval
);
1356 aio
= &cygaud
->portinfo
[portnum
];
1357 aio
->cygaud
= cygaud
;
1358 aio
->portnum
= portnum
;
1359 aio
->port_type
= port_type
;
1360 aio
->fsync_width
= -1;
1362 switch (port_type
) {
1364 aio
->regs
= ssp_regs
[portnum
];
1365 *p_dai
= cygnus_ssp_dai_info
[portnum
];
1366 aio
->mode
= CYGNUS_SSPMODE_UNKNOWN
;
1370 aio
->regs
.bf_sourcech_cfg
= BF_SRC_CFG3_OFFSET
;
1371 aio
->regs
.bf_sourcech_ctrl
= BF_SRC_CTRL3_OFFSET
;
1372 aio
->regs
.i2s_mclk_cfg
= SPDIF_MCLK_CFG_OFFSET
;
1373 aio
->regs
.i2s_stream_cfg
= SPDIF_STREAM_CFG_OFFSET
;
1374 *p_dai
= cygnus_spdif_dai_info
;
1376 /* For the purposes of this code SPDIF can be I2S mode */
1377 aio
->mode
= CYGNUS_SSPMODE_I2S
;
1380 dev_err(&pdev
->dev
, "Bad value for port_type %d\n", port_type
);
1384 dev_dbg(&pdev
->dev
, "%s portnum = %d\n", __func__
, aio
->portnum
);
1385 aio
->streams_on
= 0;
1386 aio
->cygaud
->dev
= &pdev
->dev
;
1387 aio
->clk_trace
.play_en
= false;
1388 aio
->clk_trace
.cap_en
= false;
1390 audio_ssp_init_portregs(aio
);
1394 static int audio_clk_init(struct platform_device
*pdev
,
1395 struct cygnus_audio
*cygaud
)
1398 char clk_name
[PROP_LEN_MAX
];
1400 for (i
= 0; i
< ARRAY_SIZE(cygaud
->audio_clk
); i
++) {
1401 snprintf(clk_name
, PROP_LEN_MAX
, "ch%d_audio", i
);
1403 cygaud
->audio_clk
[i
] = devm_clk_get(&pdev
->dev
, clk_name
);
1404 if (IS_ERR(cygaud
->audio_clk
[i
]))
1405 return PTR_ERR(cygaud
->audio_clk
[i
]);
1411 static int cygnus_ssp_probe(struct platform_device
*pdev
)
1413 struct device
*dev
= &pdev
->dev
;
1414 struct device_node
*child_node
;
1415 struct resource
*res
= pdev
->resource
;
1416 struct cygnus_audio
*cygaud
;
1419 int active_port_count
;
1421 cygaud
= devm_kzalloc(dev
, sizeof(struct cygnus_audio
), GFP_KERNEL
);
1425 dev_set_drvdata(dev
, cygaud
);
1427 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "aud");
1428 cygaud
->audio
= devm_ioremap_resource(dev
, res
);
1429 if (IS_ERR(cygaud
->audio
))
1430 return PTR_ERR(cygaud
->audio
);
1432 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "i2s_in");
1433 cygaud
->i2s_in
= devm_ioremap_resource(dev
, res
);
1434 if (IS_ERR(cygaud
->i2s_in
))
1435 return PTR_ERR(cygaud
->i2s_in
);
1437 /* Tri-state all controlable pins until we know that we need them */
1438 writel(CYGNUS_SSP_TRISTATE_MASK
,
1439 cygaud
->audio
+ AUD_MISC_SEROUT_OE_REG_BASE
);
1441 node_count
= of_get_child_count(pdev
->dev
.of_node
);
1442 if ((node_count
< 1) || (node_count
> CYGNUS_MAX_PORTS
)) {
1443 dev_err(dev
, "child nodes is %d. Must be between 1 and %d\n",
1444 node_count
, CYGNUS_MAX_PORTS
);
1448 active_port_count
= 0;
1450 for_each_available_child_of_node(pdev
->dev
.of_node
, child_node
) {
1451 err
= parse_ssp_child_node(pdev
, child_node
, cygaud
,
1452 &cygnus_ssp_dai
[active_port_count
]);
1454 /* negative is err, 0 is active and good, 1 is disabled */
1458 dev_dbg(dev
, "Activating DAI: %s\n",
1459 cygnus_ssp_dai
[active_port_count
].name
);
1460 active_port_count
++;
1465 cygaud
->active_ports
= 0;
1467 dev_dbg(dev
, "Registering %d DAIs\n", active_port_count
);
1468 err
= snd_soc_register_component(dev
, &cygnus_ssp_component
,
1469 cygnus_ssp_dai
, active_port_count
);
1471 dev_err(dev
, "snd_soc_register_dai failed\n");
1475 cygaud
->irq_num
= platform_get_irq(pdev
, 0);
1476 if (cygaud
->irq_num
<= 0) {
1477 dev_err(dev
, "platform_get_irq failed\n");
1478 err
= cygaud
->irq_num
;
1482 err
= audio_clk_init(pdev
, cygaud
);
1484 dev_err(dev
, "audio clock initialization failed\n");
1488 err
= cygnus_soc_platform_register(dev
, cygaud
);
1490 dev_err(dev
, "platform reg error %d\n", err
);
1497 snd_soc_unregister_component(dev
);
1501 static int cygnus_ssp_remove(struct platform_device
*pdev
)
1503 cygnus_soc_platform_unregister(&pdev
->dev
);
1504 snd_soc_unregister_component(&pdev
->dev
);
1509 static const struct of_device_id cygnus_ssp_of_match
[] = {
1510 { .compatible
= "brcm,cygnus-audio" },
1513 MODULE_DEVICE_TABLE(of
, cygnus_ssp_of_match
);
1515 static struct platform_driver cygnus_ssp_driver
= {
1516 .probe
= cygnus_ssp_probe
,
1517 .remove
= cygnus_ssp_remove
,
1519 .name
= "cygnus-ssp",
1520 .of_match_table
= cygnus_ssp_of_match
,
1524 module_platform_driver(cygnus_ssp_driver
);
1526 MODULE_ALIAS("platform:cygnus-ssp");
1527 MODULE_LICENSE("GPL v2");
1528 MODULE_AUTHOR("Broadcom");
1529 MODULE_DESCRIPTION("Cygnus ASoC SSP Interface");