blob: bc904696d82075a701acf4b6f240022936344dad [file] [log] [blame]
Timur Tabi17467f22008-01-11 18:15:26 +01001/*
2 * Freescale SSI ALSA SoC Digital Audio Interface (DAI) driver
3 *
4 * Author: Timur Tabi <timur@freescale.com>
5 *
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00006 * Copyright 2007-2010 Freescale Semiconductor, Inc.
7 *
8 * This file is licensed under the terms of the GNU General Public License
9 * version 2. This program is licensed "as is" without any warranty of any
10 * kind, whether express or implied.
Markus Pargmannde623ec2013-07-27 13:31:53 +020011 *
12 *
13 * Some notes why imx-pcm-fiq is used instead of DMA on some boards:
14 *
15 * The i.MX SSI core has some nasty limitations in AC97 mode. While most
16 * sane processor vendors have a FIFO per AC97 slot, the i.MX has only
17 * one FIFO which combines all valid receive slots. We cannot even select
18 * which slots we want to receive. The WM9712 with which this driver
19 * was developed with always sends GPIO status data in slot 12 which
20 * we receive in our (PCM-) data stream. The only chance we have is to
21 * manually skip this data in the FIQ handler. With sampling rates different
22 * from 48000Hz not every frame has valid receive data, so the ratio
23 * between pcm data and GPIO status data changes. Our FIQ handler is not
24 * able to handle this, hence this driver only works with 48000Hz sampling
25 * rate.
26 * Reading and writing AC97 registers is another challenge. The core
27 * provides us status bits when the read register is updated with *another*
28 * value. When we read the same register two times (and the register still
29 * contains the same value) these status bits are not set. We work
30 * around this by not polling these bits but only wait a fixed delay.
Timur Tabi17467f22008-01-11 18:15:26 +010031 */
32
33#include <linux/init.h>
Shawn Guodfa1a102012-03-16 16:56:42 +080034#include <linux/io.h>
Timur Tabi17467f22008-01-11 18:15:26 +010035#include <linux/module.h>
36#include <linux/interrupt.h>
Shawn Guo95cd98f2012-03-29 10:53:41 +080037#include <linux/clk.h>
Markus Pargmann9368acc2013-12-20 14:11:29 +010038#include <linux/debugfs.h>
Timur Tabi17467f22008-01-11 18:15:26 +010039#include <linux/device.h>
40#include <linux/delay.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090041#include <linux/slab.h>
Nicolin Chenaafa85e2013-12-12 18:44:45 +080042#include <linux/spinlock.h>
Shawn Guodfa1a102012-03-16 16:56:42 +080043#include <linux/of_address.h>
44#include <linux/of_irq.h>
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +000045#include <linux/of_platform.h>
Timur Tabi17467f22008-01-11 18:15:26 +010046
Timur Tabi17467f22008-01-11 18:15:26 +010047#include <sound/core.h>
48#include <sound/pcm.h>
49#include <sound/pcm_params.h>
50#include <sound/initval.h>
51#include <sound/soc.h>
Lars-Peter Clausena8909c92013-04-03 11:06:04 +020052#include <sound/dmaengine_pcm.h>
Timur Tabi17467f22008-01-11 18:15:26 +010053
Timur Tabi17467f22008-01-11 18:15:26 +010054#include "fsl_ssi.h"
Shawn Guo09ce1112012-03-16 16:56:43 +080055#include "imx-pcm.h"
Timur Tabi17467f22008-01-11 18:15:26 +010056
Shawn Guodfa1a102012-03-16 16:56:42 +080057#ifdef PPC
58#define read_ssi(addr) in_be32(addr)
59#define write_ssi(val, addr) out_be32(addr, val)
60#define write_ssi_mask(addr, clear, set) clrsetbits_be32(addr, clear, set)
Mark Brown0a9eaa32013-07-19 11:40:13 +010061#else
Shawn Guodfa1a102012-03-16 16:56:42 +080062#define read_ssi(addr) readl(addr)
63#define write_ssi(val, addr) writel(val, addr)
64/*
65 * FIXME: Proper locking should be added at write_ssi_mask caller level
66 * to ensure this register read/modify/write sequence is race free.
67 */
68static inline void write_ssi_mask(u32 __iomem *addr, u32 clear, u32 set)
69{
70 u32 val = readl(addr);
71 val = (val & ~clear) | set;
72 writel(val, addr);
73}
74#endif
75
Timur Tabi17467f22008-01-11 18:15:26 +010076/**
77 * FSLSSI_I2S_RATES: sample rates supported by the I2S
78 *
79 * This driver currently only supports the SSI running in I2S slave mode,
80 * which means the codec determines the sample rate. Therefore, we tell
81 * ALSA that we support all rates and let the codec driver decide what rates
82 * are really supported.
83 */
84#define FSLSSI_I2S_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \
85 SNDRV_PCM_RATE_CONTINUOUS)
86
87/**
88 * FSLSSI_I2S_FORMATS: audio formats supported by the SSI
89 *
90 * This driver currently only supports the SSI running in I2S slave mode.
91 *
92 * The SSI has a limitation in that the samples must be in the same byte
93 * order as the host CPU. This is because when multiple bytes are written
94 * to the STX register, the bytes and bits must be written in the same
95 * order. The STX is a shift register, so all the bits need to be aligned
96 * (bit-endianness must match byte-endianness). Processors typically write
97 * the bits within a byte in the same order that the bytes of a word are
98 * written in. So if the host CPU is big-endian, then only big-endian
99 * samples will be written to STX properly.
100 */
101#ifdef __BIG_ENDIAN
102#define FSLSSI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | \
103 SNDRV_PCM_FMTBIT_S18_3BE | SNDRV_PCM_FMTBIT_S20_3BE | \
104 SNDRV_PCM_FMTBIT_S24_3BE | SNDRV_PCM_FMTBIT_S24_BE)
105#else
106#define FSLSSI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
107 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE | \
108 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE)
109#endif
110
Timur Tabid5a908b2009-03-26 11:42:38 -0500111/* SIER bitflag of interrupts to enable */
112#define SIER_FLAGS (CCSR_SSI_SIER_TFRC_EN | CCSR_SSI_SIER_TDMAE | \
113 CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TUE0_EN | \
114 CCSR_SSI_SIER_TUE1_EN | CCSR_SSI_SIER_RFRC_EN | \
115 CCSR_SSI_SIER_RDMAE | CCSR_SSI_SIER_RIE | \
116 CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_ROE1_EN)
117
Markus Pargmann9368acc2013-12-20 14:11:29 +0100118#define FSLSSI_SIER_DBG_RX_FLAGS (CCSR_SSI_SIER_RFF0_EN | \
119 CCSR_SSI_SIER_RLS_EN | CCSR_SSI_SIER_RFS_EN | \
120 CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_RFRC_EN)
121#define FSLSSI_SIER_DBG_TX_FLAGS (CCSR_SSI_SIER_TFE0_EN | \
122 CCSR_SSI_SIER_TLS_EN | CCSR_SSI_SIER_TFS_EN | \
123 CCSR_SSI_SIER_TUE0_EN | CCSR_SSI_SIER_TFRC_EN)
124#define FSLSSI_SISR_MASK (FSLSSI_SIER_DBG_RX_FLAGS | FSLSSI_SIER_DBG_TX_FLAGS)
125
Markus Pargmannc1953bf2013-12-20 14:11:30 +0100126
127enum fsl_ssi_type {
128 FSL_SSI_MCP8610,
129 FSL_SSI_MX21,
Markus Pargmann0888efd2013-12-20 14:11:31 +0100130 FSL_SSI_MX35,
Markus Pargmannc1953bf2013-12-20 14:11:30 +0100131 FSL_SSI_MX51,
132};
133
Timur Tabi17467f22008-01-11 18:15:26 +0100134/**
135 * fsl_ssi_private: per-SSI private data
136 *
Timur Tabi17467f22008-01-11 18:15:26 +0100137 * @ssi: pointer to the SSI's registers
138 * @ssi_phys: physical address of the SSI registers
139 * @irq: IRQ of this SSI
Timur Tabi17467f22008-01-11 18:15:26 +0100140 * @playback: the number of playback streams opened
141 * @capture: the number of capture streams opened
142 * @cpu_dai: the CPU DAI for this device
143 * @dev_attr: the sysfs device attribute structure
144 * @stats: SSI statistics
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000145 * @name: name for this device
Timur Tabi17467f22008-01-11 18:15:26 +0100146 */
147struct fsl_ssi_private {
Timur Tabi17467f22008-01-11 18:15:26 +0100148 struct ccsr_ssi __iomem *ssi;
149 dma_addr_t ssi_phys;
150 unsigned int irq;
Timur Tabi8e9d8692010-08-06 12:16:12 -0500151 unsigned int fifo_depth;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000152 struct snd_soc_dai_driver cpu_dai_drv;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000153 struct platform_device *pdev;
Timur Tabi17467f22008-01-11 18:15:26 +0100154
Markus Pargmann0888efd2013-12-20 14:11:31 +0100155 enum fsl_ssi_type hw_type;
Shawn Guo09ce1112012-03-16 16:56:43 +0800156 bool new_binding;
157 bool ssi_on_imx;
Markus Pargmanncd7f0292013-08-19 17:05:58 +0200158 bool imx_ac97;
Markus Pargmannde623ec2013-07-27 13:31:53 +0200159 bool use_dma;
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800160 bool baudclk_locked;
Markus Pargmann2841be92013-12-20 14:11:28 +0100161 bool irq_stats;
Nicolin Chen2924a992013-12-02 23:29:03 +0800162 u8 i2s_mode;
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800163 spinlock_t baudclk_lock;
164 struct clk *baudclk;
Shawn Guo95cd98f2012-03-29 10:53:41 +0800165 struct clk *clk;
Lars-Peter Clausena8909c92013-04-03 11:06:04 +0200166 struct snd_dmaengine_dai_dma_data dma_params_tx;
167 struct snd_dmaengine_dai_dma_data dma_params_rx;
168 struct imx_dma_data filter_data_tx;
169 struct imx_dma_data filter_data_rx;
Markus Pargmannde623ec2013-07-27 13:31:53 +0200170 struct imx_pcm_fiq_params fiq_params;
Shawn Guo09ce1112012-03-16 16:56:43 +0800171
Timur Tabi17467f22008-01-11 18:15:26 +0100172 struct {
173 unsigned int rfrc;
174 unsigned int tfrc;
175 unsigned int cmdau;
176 unsigned int cmddu;
177 unsigned int rxt;
178 unsigned int rdr1;
179 unsigned int rdr0;
180 unsigned int tde1;
181 unsigned int tde0;
182 unsigned int roe1;
183 unsigned int roe0;
184 unsigned int tue1;
185 unsigned int tue0;
186 unsigned int tfs;
187 unsigned int rfs;
188 unsigned int tls;
189 unsigned int rls;
190 unsigned int rff1;
191 unsigned int rff0;
192 unsigned int tfe1;
193 unsigned int tfe0;
194 } stats;
Markus Pargmann9368acc2013-12-20 14:11:29 +0100195 struct dentry *dbg_dir;
196 struct dentry *dbg_stats;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000197
198 char name[1];
Timur Tabi17467f22008-01-11 18:15:26 +0100199};
200
Markus Pargmannc1953bf2013-12-20 14:11:30 +0100201static const struct of_device_id fsl_ssi_ids[] = {
202 { .compatible = "fsl,mpc8610-ssi", .data = (void *) FSL_SSI_MCP8610},
203 { .compatible = "fsl,imx51-ssi", .data = (void *) FSL_SSI_MX51},
Markus Pargmann0888efd2013-12-20 14:11:31 +0100204 { .compatible = "fsl,imx35-ssi", .data = (void *) FSL_SSI_MX35},
Markus Pargmannc1953bf2013-12-20 14:11:30 +0100205 { .compatible = "fsl,imx21-ssi", .data = (void *) FSL_SSI_MX21},
206 {}
207};
208MODULE_DEVICE_TABLE(of, fsl_ssi_ids);
209
Timur Tabi17467f22008-01-11 18:15:26 +0100210/**
211 * fsl_ssi_isr: SSI interrupt handler
212 *
213 * Although it's possible to use the interrupt handler to send and receive
214 * data to/from the SSI, we use the DMA instead. Programming is more
215 * complicated, but the performance is much better.
216 *
217 * This interrupt handler is used only to gather statistics.
218 *
219 * @irq: IRQ of the SSI device
220 * @dev_id: pointer to the ssi_private structure for this SSI device
221 */
222static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
223{
224 struct fsl_ssi_private *ssi_private = dev_id;
225 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
226 irqreturn_t ret = IRQ_NONE;
227 __be32 sisr;
Markus Pargmann0888efd2013-12-20 14:11:31 +0100228 __be32 sisr2;
229 __be32 sisr_write_mask = 0;
230
231 switch (ssi_private->hw_type) {
232 case FSL_SSI_MX21:
233 sisr_write_mask = 0;
234 break;
235
236 case FSL_SSI_MCP8610:
237 case FSL_SSI_MX35:
238 sisr_write_mask = CCSR_SSI_SISR_RFRC | CCSR_SSI_SISR_TFRC |
239 CCSR_SSI_SISR_ROE0 | CCSR_SSI_SISR_ROE1 |
240 CCSR_SSI_SISR_TUE0 | CCSR_SSI_SISR_TUE1;
241 break;
242
243 case FSL_SSI_MX51:
244 sisr_write_mask = CCSR_SSI_SISR_ROE0 | CCSR_SSI_SISR_ROE1 |
245 CCSR_SSI_SISR_TUE0 | CCSR_SSI_SISR_TUE1;
246 break;
247 }
Timur Tabi17467f22008-01-11 18:15:26 +0100248
249 /* We got an interrupt, so read the status register to see what we
250 were interrupted for. We mask it with the Interrupt Enable register
251 so that we only check for events that we're interested in.
252 */
Markus Pargmann9368acc2013-12-20 14:11:29 +0100253 sisr = read_ssi(&ssi->sisr) & FSLSSI_SISR_MASK;
Timur Tabi17467f22008-01-11 18:15:26 +0100254
255 if (sisr & CCSR_SSI_SISR_RFRC) {
256 ssi_private->stats.rfrc++;
Timur Tabi17467f22008-01-11 18:15:26 +0100257 ret = IRQ_HANDLED;
258 }
259
260 if (sisr & CCSR_SSI_SISR_TFRC) {
261 ssi_private->stats.tfrc++;
Timur Tabi17467f22008-01-11 18:15:26 +0100262 ret = IRQ_HANDLED;
263 }
264
265 if (sisr & CCSR_SSI_SISR_CMDAU) {
266 ssi_private->stats.cmdau++;
267 ret = IRQ_HANDLED;
268 }
269
270 if (sisr & CCSR_SSI_SISR_CMDDU) {
271 ssi_private->stats.cmddu++;
272 ret = IRQ_HANDLED;
273 }
274
275 if (sisr & CCSR_SSI_SISR_RXT) {
276 ssi_private->stats.rxt++;
277 ret = IRQ_HANDLED;
278 }
279
280 if (sisr & CCSR_SSI_SISR_RDR1) {
281 ssi_private->stats.rdr1++;
282 ret = IRQ_HANDLED;
283 }
284
285 if (sisr & CCSR_SSI_SISR_RDR0) {
286 ssi_private->stats.rdr0++;
287 ret = IRQ_HANDLED;
288 }
289
290 if (sisr & CCSR_SSI_SISR_TDE1) {
291 ssi_private->stats.tde1++;
292 ret = IRQ_HANDLED;
293 }
294
295 if (sisr & CCSR_SSI_SISR_TDE0) {
296 ssi_private->stats.tde0++;
297 ret = IRQ_HANDLED;
298 }
299
300 if (sisr & CCSR_SSI_SISR_ROE1) {
301 ssi_private->stats.roe1++;
Timur Tabi17467f22008-01-11 18:15:26 +0100302 ret = IRQ_HANDLED;
303 }
304
305 if (sisr & CCSR_SSI_SISR_ROE0) {
306 ssi_private->stats.roe0++;
Timur Tabi17467f22008-01-11 18:15:26 +0100307 ret = IRQ_HANDLED;
308 }
309
310 if (sisr & CCSR_SSI_SISR_TUE1) {
311 ssi_private->stats.tue1++;
Timur Tabi17467f22008-01-11 18:15:26 +0100312 ret = IRQ_HANDLED;
313 }
314
315 if (sisr & CCSR_SSI_SISR_TUE0) {
316 ssi_private->stats.tue0++;
Timur Tabi17467f22008-01-11 18:15:26 +0100317 ret = IRQ_HANDLED;
318 }
319
320 if (sisr & CCSR_SSI_SISR_TFS) {
321 ssi_private->stats.tfs++;
322 ret = IRQ_HANDLED;
323 }
324
325 if (sisr & CCSR_SSI_SISR_RFS) {
326 ssi_private->stats.rfs++;
327 ret = IRQ_HANDLED;
328 }
329
330 if (sisr & CCSR_SSI_SISR_TLS) {
331 ssi_private->stats.tls++;
332 ret = IRQ_HANDLED;
333 }
334
335 if (sisr & CCSR_SSI_SISR_RLS) {
336 ssi_private->stats.rls++;
337 ret = IRQ_HANDLED;
338 }
339
340 if (sisr & CCSR_SSI_SISR_RFF1) {
341 ssi_private->stats.rff1++;
342 ret = IRQ_HANDLED;
343 }
344
345 if (sisr & CCSR_SSI_SISR_RFF0) {
346 ssi_private->stats.rff0++;
347 ret = IRQ_HANDLED;
348 }
349
350 if (sisr & CCSR_SSI_SISR_TFE1) {
351 ssi_private->stats.tfe1++;
352 ret = IRQ_HANDLED;
353 }
354
355 if (sisr & CCSR_SSI_SISR_TFE0) {
356 ssi_private->stats.tfe0++;
357 ret = IRQ_HANDLED;
358 }
359
Markus Pargmann0888efd2013-12-20 14:11:31 +0100360 sisr2 = sisr & sisr_write_mask;
Timur Tabi17467f22008-01-11 18:15:26 +0100361 /* Clear the bits that we set */
362 if (sisr2)
Shawn Guodfa1a102012-03-16 16:56:42 +0800363 write_ssi(sisr2, &ssi->sisr);
Timur Tabi17467f22008-01-11 18:15:26 +0100364
365 return ret;
366}
367
Markus Pargmann9368acc2013-12-20 14:11:29 +0100368#if IS_ENABLED(CONFIG_DEBUG_FS)
369/* Show the statistics of a flag only if its interrupt is enabled. The
370 * compiler will optimze this code to a no-op if the interrupt is not
371 * enabled.
372 */
373#define SIER_SHOW(flag, name) \
374 do { \
375 if (FSLSSI_SISR_MASK & CCSR_SSI_SIER_##flag) \
376 seq_printf(s, #name "=%u\n", ssi_private->stats.name); \
377 } while (0)
378
379
380/**
381 * fsl_sysfs_ssi_show: display SSI statistics
382 *
383 * Display the statistics for the current SSI device. To avoid confusion,
384 * we only show those counts that are enabled.
385 */
386static ssize_t fsl_ssi_stats_show(struct seq_file *s, void *unused)
387{
388 struct fsl_ssi_private *ssi_private = s->private;
389
390 SIER_SHOW(RFRC_EN, rfrc);
391 SIER_SHOW(TFRC_EN, tfrc);
392 SIER_SHOW(CMDAU_EN, cmdau);
393 SIER_SHOW(CMDDU_EN, cmddu);
394 SIER_SHOW(RXT_EN, rxt);
395 SIER_SHOW(RDR1_EN, rdr1);
396 SIER_SHOW(RDR0_EN, rdr0);
397 SIER_SHOW(TDE1_EN, tde1);
398 SIER_SHOW(TDE0_EN, tde0);
399 SIER_SHOW(ROE1_EN, roe1);
400 SIER_SHOW(ROE0_EN, roe0);
401 SIER_SHOW(TUE1_EN, tue1);
402 SIER_SHOW(TUE0_EN, tue0);
403 SIER_SHOW(TFS_EN, tfs);
404 SIER_SHOW(RFS_EN, rfs);
405 SIER_SHOW(TLS_EN, tls);
406 SIER_SHOW(RLS_EN, rls);
407 SIER_SHOW(RFF1_EN, rff1);
408 SIER_SHOW(RFF0_EN, rff0);
409 SIER_SHOW(TFE1_EN, tfe1);
410 SIER_SHOW(TFE0_EN, tfe0);
411
412 return 0;
413}
414
415static int fsl_ssi_stats_open(struct inode *inode, struct file *file)
416{
417 return single_open(file, fsl_ssi_stats_show, inode->i_private);
418}
419
420static const struct file_operations fsl_ssi_stats_ops = {
421 .open = fsl_ssi_stats_open,
422 .read = seq_read,
423 .llseek = seq_lseek,
424 .release = single_release,
425};
426
427static int fsl_ssi_debugfs_create(struct fsl_ssi_private *ssi_private,
428 struct device *dev)
429{
430 ssi_private->dbg_dir = debugfs_create_dir(dev_name(dev), NULL);
431 if (!ssi_private->dbg_dir)
432 return -ENOMEM;
433
434 ssi_private->dbg_stats = debugfs_create_file("stats", S_IRUGO,
435 ssi_private->dbg_dir, ssi_private, &fsl_ssi_stats_ops);
436 if (!ssi_private->dbg_stats) {
437 debugfs_remove(ssi_private->dbg_dir);
438 return -ENOMEM;
439 }
440
441 return 0;
442}
443
444static void fsl_ssi_debugfs_remove(struct fsl_ssi_private *ssi_private)
445{
446 debugfs_remove(ssi_private->dbg_stats);
447 debugfs_remove(ssi_private->dbg_dir);
448}
449
450#else
451
452static int fsl_ssi_debugfs_create(struct fsl_ssi_private *ssi_private,
453 struct device *dev)
454{
455 return 0;
456}
457
458static void fsl_ssi_debugfs_remove(struct fsl_ssi_private *ssi_private)
459{
460}
461
462#endif /* IS_ENABLED(CONFIG_DEBUG_FS) */
463
Markus Pargmannd8764642013-11-20 10:04:15 +0100464static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private)
465{
466 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
467
468 /*
469 * Setup the clock control register
470 */
471 write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
472 &ssi->stccr);
473 write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
474 &ssi->srccr);
475
476 /*
477 * Enable AC97 mode and startup the SSI
478 */
479 write_ssi(CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV,
480 &ssi->sacnt);
481 write_ssi(0xff, &ssi->saccdis);
482 write_ssi(0x300, &ssi->saccen);
483
484 /*
485 * Enable SSI, Transmit and Receive. AC97 has to communicate with the
486 * codec before a stream is started.
487 */
488 write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN |
489 CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE);
490
491 write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor);
492}
493
Markus Pargmanncd7f0292013-08-19 17:05:58 +0200494static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private)
495{
496 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
Markus Pargmanncd7f0292013-08-19 17:05:58 +0200497 u8 wm;
498 int synchronous = ssi_private->cpu_dai_drv.symmetric_rates;
499
500 if (ssi_private->imx_ac97)
Nicolin Chen2924a992013-12-02 23:29:03 +0800501 ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET;
Markus Pargmanncd7f0292013-08-19 17:05:58 +0200502 else
Nicolin Chen2924a992013-12-02 23:29:03 +0800503 ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE;
Markus Pargmanncd7f0292013-08-19 17:05:58 +0200504
505 /*
506 * Section 16.5 of the MPC8610 reference manual says that the SSI needs
507 * to be disabled before updating the registers we set here.
508 */
509 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0);
510
511 /*
512 * Program the SSI into I2S Slave Non-Network Synchronous mode. Also
513 * enable the transmit and receive FIFO.
514 *
515 * FIXME: Little-endian samples require a different shift dir
516 */
517 write_ssi_mask(&ssi->scr,
518 CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN,
519 CCSR_SSI_SCR_TFR_CLK_DIS |
Nicolin Chen2924a992013-12-02 23:29:03 +0800520 ssi_private->i2s_mode |
Markus Pargmanncd7f0292013-08-19 17:05:58 +0200521 (synchronous ? CCSR_SSI_SCR_SYN : 0));
522
523 write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 |
524 CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS |
525 CCSR_SSI_STCR_TSCKP, &ssi->stcr);
526
527 write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 |
528 CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS |
529 CCSR_SSI_SRCR_RSCKP, &ssi->srcr);
530 /*
531 * The DC and PM bits are only used if the SSI is the clock master.
532 */
533
534 /*
535 * Set the watermark for transmit FIFI 0 and receive FIFO 0. We don't
536 * use FIFO 1. We program the transmit water to signal a DMA transfer
537 * if there are only two (or fewer) elements left in the FIFO. Two
538 * elements equals one frame (left channel, right channel). This value,
539 * however, depends on the depth of the transmit buffer.
540 *
541 * We set the watermark on the same level as the DMA burstsize. For
542 * fiq it is probably better to use the biggest possible watermark
543 * size.
544 */
545 if (ssi_private->use_dma)
546 wm = ssi_private->fifo_depth - 2;
547 else
548 wm = ssi_private->fifo_depth;
549
550 write_ssi(CCSR_SSI_SFCSR_TFWM0(wm) | CCSR_SSI_SFCSR_RFWM0(wm) |
551 CCSR_SSI_SFCSR_TFWM1(wm) | CCSR_SSI_SFCSR_RFWM1(wm),
552 &ssi->sfcsr);
553
554 /*
Markus Pargmanncd7f0292013-08-19 17:05:58 +0200555 * For ac97 interrupts are enabled with the startup of the substream
556 * because it is also running without an active substream. Normally SSI
557 * is only enabled when there is a substream.
558 */
Markus Pargmannd8764642013-11-20 10:04:15 +0100559 if (ssi_private->imx_ac97)
560 fsl_ssi_setup_ac97(ssi_private);
Markus Pargmanncd7f0292013-08-19 17:05:58 +0200561
562 return 0;
563}
564
565
Timur Tabi17467f22008-01-11 18:15:26 +0100566/**
567 * fsl_ssi_startup: create a new substream
568 *
569 * This is the first function called when a stream is opened.
570 *
571 * If this is the first stream open, then grab the IRQ and program most of
572 * the SSI registers.
573 */
Mark Browndee89c42008-11-18 22:11:38 +0000574static int fsl_ssi_startup(struct snd_pcm_substream *substream,
575 struct snd_soc_dai *dai)
Timur Tabi17467f22008-01-11 18:15:26 +0100576{
577 struct snd_soc_pcm_runtime *rtd = substream->private_data;
Timur Tabi5e538ec2011-09-13 12:59:37 -0500578 struct fsl_ssi_private *ssi_private =
579 snd_soc_dai_get_drvdata(rtd->cpu_dai);
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800580 unsigned long flags;
Timur Tabi17467f22008-01-11 18:15:26 +0100581
Nicolin Chen07a94832013-12-03 18:38:07 +0800582 /* First, we only do fsl_ssi_setup() when SSI is going to be active.
583 * Second, fsl_ssi_setup was already called by ac97_init earlier if
584 * the driver is in ac97 mode.
Timur Tabi17467f22008-01-11 18:15:26 +0100585 */
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800586 if (!dai->active && !ssi_private->imx_ac97) {
Nicolin Chen07a94832013-12-03 18:38:07 +0800587 fsl_ssi_setup(ssi_private);
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800588 spin_lock_irqsave(&ssi_private->baudclk_lock, flags);
589 ssi_private->baudclk_locked = false;
590 spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
591 }
Timur Tabibe41e942008-07-28 17:04:39 -0500592
Timur Tabi17467f22008-01-11 18:15:26 +0100593 return 0;
594}
595
596/**
Timur Tabi85ef2372009-02-05 17:56:02 -0600597 * fsl_ssi_hw_params - program the sample size
Timur Tabi17467f22008-01-11 18:15:26 +0100598 *
599 * Most of the SSI registers have been programmed in the startup function,
600 * but the word length must be programmed here. Unfortunately, programming
601 * the SxCCR.WL bits requires the SSI to be temporarily disabled. This can
602 * cause a problem with supporting simultaneous playback and capture. If
603 * the SSI is already playing a stream, then that stream may be temporarily
604 * stopped when you start capture.
605 *
606 * Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the
607 * clock master.
608 */
Timur Tabi85ef2372009-02-05 17:56:02 -0600609static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
610 struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai)
Timur Tabi17467f22008-01-11 18:15:26 +0100611{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000612 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
Timur Tabi5e538ec2011-09-13 12:59:37 -0500613 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
Nicolin Chen2924a992013-12-02 23:29:03 +0800614 unsigned int channels = params_channels(hw_params);
Timur Tabi5e538ec2011-09-13 12:59:37 -0500615 unsigned int sample_size =
616 snd_pcm_format_width(params_format(hw_params));
617 u32 wl = CCSR_SSI_SxCCR_WL(sample_size);
Shawn Guodfa1a102012-03-16 16:56:42 +0800618 int enabled = read_ssi(&ssi->scr) & CCSR_SSI_SCR_SSIEN;
Timur Tabi17467f22008-01-11 18:15:26 +0100619
Timur Tabi5e538ec2011-09-13 12:59:37 -0500620 /*
621 * If we're in synchronous mode, and the SSI is already enabled,
622 * then STCCR is already set properly.
623 */
624 if (enabled && ssi_private->cpu_dai_drv.symmetric_rates)
625 return 0;
Timur Tabi17467f22008-01-11 18:15:26 +0100626
Timur Tabi5e538ec2011-09-13 12:59:37 -0500627 /*
628 * FIXME: The documentation says that SxCCR[WL] should not be
629 * modified while the SSI is enabled. The only time this can
630 * happen is if we're trying to do simultaneous playback and
631 * capture in asynchronous mode. Unfortunately, I have been enable
632 * to get that to work at all on the P1022DS. Therefore, we don't
633 * bother to disable/enable the SSI when setting SxCCR[WL], because
634 * the SSI will stop anyway. Maybe one day, this will get fixed.
635 */
Timur Tabi17467f22008-01-11 18:15:26 +0100636
Timur Tabi5e538ec2011-09-13 12:59:37 -0500637 /* In synchronous mode, the SSI uses STCCR for capture */
638 if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ||
639 ssi_private->cpu_dai_drv.symmetric_rates)
Shawn Guodfa1a102012-03-16 16:56:42 +0800640 write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl);
Timur Tabi5e538ec2011-09-13 12:59:37 -0500641 else
Shawn Guodfa1a102012-03-16 16:56:42 +0800642 write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl);
Timur Tabi17467f22008-01-11 18:15:26 +0100643
Nicolin Chen2924a992013-12-02 23:29:03 +0800644 if (!ssi_private->imx_ac97)
645 write_ssi_mask(&ssi->scr,
646 CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK,
647 channels == 1 ? 0 : ssi_private->i2s_mode);
648
Timur Tabi17467f22008-01-11 18:15:26 +0100649 return 0;
650}
651
652/**
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800653 * fsl_ssi_set_dai_fmt - configure Digital Audio Interface Format.
654 */
655static int fsl_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
656{
657 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
658 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
659 u32 strcr = 0, stcr, srcr, scr, mask;
660
661 scr = read_ssi(&ssi->scr) & ~(CCSR_SSI_SCR_SYN | CCSR_SSI_SCR_I2S_MODE_MASK);
662 scr |= CCSR_SSI_SCR_NET;
663
664 mask = CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFDIR | CCSR_SSI_STCR_TXDIR |
665 CCSR_SSI_STCR_TSCKP | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TFSL |
666 CCSR_SSI_STCR_TEFS;
667 stcr = read_ssi(&ssi->stcr) & ~mask;
668 srcr = read_ssi(&ssi->srcr) & ~mask;
669
670 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
671 case SND_SOC_DAIFMT_I2S:
672 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
673 case SND_SOC_DAIFMT_CBS_CFS:
674 ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_MASTER;
675 break;
676 case SND_SOC_DAIFMT_CBM_CFM:
677 ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE;
678 break;
679 default:
680 return -EINVAL;
681 }
682 scr |= ssi_private->i2s_mode;
683
684 /* Data on rising edge of bclk, frame low, 1clk before data */
685 strcr |= CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TSCKP |
686 CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TEFS;
687 break;
688 case SND_SOC_DAIFMT_LEFT_J:
689 /* Data on rising edge of bclk, frame high */
690 strcr |= CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TSCKP;
691 break;
692 case SND_SOC_DAIFMT_DSP_A:
693 /* Data on rising edge of bclk, frame high, 1clk before data */
694 strcr |= CCSR_SSI_STCR_TFSL | CCSR_SSI_STCR_TSCKP |
695 CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TEFS;
696 break;
697 case SND_SOC_DAIFMT_DSP_B:
698 /* Data on rising edge of bclk, frame high */
699 strcr |= CCSR_SSI_STCR_TFSL | CCSR_SSI_STCR_TSCKP |
700 CCSR_SSI_STCR_TXBIT0;
701 break;
702 default:
703 return -EINVAL;
704 }
705
706 /* DAI clock inversion */
707 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
708 case SND_SOC_DAIFMT_NB_NF:
709 /* Nothing to do for both normal cases */
710 break;
711 case SND_SOC_DAIFMT_IB_NF:
712 /* Invert bit clock */
713 strcr ^= CCSR_SSI_STCR_TSCKP;
714 break;
715 case SND_SOC_DAIFMT_NB_IF:
716 /* Invert frame clock */
717 strcr ^= CCSR_SSI_STCR_TFSI;
718 break;
719 case SND_SOC_DAIFMT_IB_IF:
720 /* Invert both clocks */
721 strcr ^= CCSR_SSI_STCR_TSCKP;
722 strcr ^= CCSR_SSI_STCR_TFSI;
723 break;
724 default:
725 return -EINVAL;
726 }
727
728 /* DAI clock master masks */
729 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
730 case SND_SOC_DAIFMT_CBS_CFS:
731 strcr |= CCSR_SSI_STCR_TFDIR | CCSR_SSI_STCR_TXDIR;
732 scr |= CCSR_SSI_SCR_SYS_CLK_EN;
733 break;
734 case SND_SOC_DAIFMT_CBM_CFM:
735 scr &= ~CCSR_SSI_SCR_SYS_CLK_EN;
736 break;
737 default:
738 return -EINVAL;
739 }
740
741 stcr |= strcr;
742 srcr |= strcr;
743
744 if (ssi_private->cpu_dai_drv.symmetric_rates) {
745 /* Need to clear RXDIR when using SYNC mode */
746 srcr &= ~CCSR_SSI_SRCR_RXDIR;
747 scr |= CCSR_SSI_SCR_SYN;
748 }
749
750 write_ssi(stcr, &ssi->stcr);
751 write_ssi(srcr, &ssi->srcr);
752 write_ssi(scr, &ssi->scr);
753
754 return 0;
755}
756
757/**
758 * fsl_ssi_set_dai_sysclk - configure Digital Audio Interface bit clock
759 *
760 * Note: This function can be only called when using SSI as DAI master
761 *
762 * Quick instruction for parameters:
763 * freq: Output BCLK frequency = samplerate * 32 (fixed) * channels
764 * dir: SND_SOC_CLOCK_OUT -> TxBCLK, SND_SOC_CLOCK_IN -> RxBCLK.
765 */
766static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
767 int clk_id, unsigned int freq, int dir)
768{
769 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
770 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
771 int synchronous = ssi_private->cpu_dai_drv.symmetric_rates, ret;
772 u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
773 unsigned long flags, clkrate, baudrate, tmprate;
774 u64 sub, savesub = 100000;
775
776 /* Don't apply it to any non-baudclk circumstance */
777 if (IS_ERR(ssi_private->baudclk))
778 return -EINVAL;
779
780 /* It should be already enough to divide clock by setting pm alone */
781 psr = 0;
782 div2 = 0;
783
784 factor = (div2 + 1) * (7 * psr + 1) * 2;
785
786 for (i = 0; i < 255; i++) {
787 /* The bclk rate must be smaller than 1/5 sysclk rate */
788 if (factor * (i + 1) < 5)
789 continue;
790
791 tmprate = freq * factor * (i + 2);
792 clkrate = clk_round_rate(ssi_private->baudclk, tmprate);
793
794 do_div(clkrate, factor);
795 afreq = (u32)clkrate / (i + 1);
796
797 if (freq == afreq)
798 sub = 0;
799 else if (freq / afreq == 1)
800 sub = freq - afreq;
801 else if (afreq / freq == 1)
802 sub = afreq - freq;
803 else
804 continue;
805
806 /* Calculate the fraction */
807 sub *= 100000;
808 do_div(sub, freq);
809
810 if (sub < savesub) {
811 baudrate = tmprate;
812 savesub = sub;
813 pm = i;
814 }
815
816 /* We are lucky */
817 if (savesub == 0)
818 break;
819 }
820
821 /* No proper pm found if it is still remaining the initial value */
822 if (pm == 999) {
823 dev_err(cpu_dai->dev, "failed to handle the required sysclk\n");
824 return -EINVAL;
825 }
826
827 stccr = CCSR_SSI_SxCCR_PM(pm + 1) | (div2 ? CCSR_SSI_SxCCR_DIV2 : 0) |
828 (psr ? CCSR_SSI_SxCCR_PSR : 0);
829 mask = CCSR_SSI_SxCCR_PM_MASK | CCSR_SSI_SxCCR_DIV2 | CCSR_SSI_SxCCR_PSR;
830
831 if (dir == SND_SOC_CLOCK_OUT || synchronous)
832 write_ssi_mask(&ssi->stccr, mask, stccr);
833 else
834 write_ssi_mask(&ssi->srccr, mask, stccr);
835
836 spin_lock_irqsave(&ssi_private->baudclk_lock, flags);
837 if (!ssi_private->baudclk_locked) {
838 ret = clk_set_rate(ssi_private->baudclk, baudrate);
839 if (ret) {
840 spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
841 dev_err(cpu_dai->dev, "failed to set baudclk rate\n");
842 return -EINVAL;
843 }
844 ssi_private->baudclk_locked = true;
845 }
846 spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
847
848 return 0;
849}
850
851/**
852 * fsl_ssi_set_dai_tdm_slot - set TDM slot number
853 *
854 * Note: This function can be only called when using SSI as DAI master
855 */
856static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
857 u32 rx_mask, int slots, int slot_width)
858{
859 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
860 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
861 u32 val;
862
863 /* The slot number should be >= 2 if using Network mode or I2S mode */
864 val = read_ssi(&ssi->scr) & (CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_NET);
865 if (val && slots < 2) {
866 dev_err(cpu_dai->dev, "slot number should be >= 2 in I2S or NET\n");
867 return -EINVAL;
868 }
869
870 write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_DC_MASK,
871 CCSR_SSI_SxCCR_DC(slots));
872 write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_DC_MASK,
873 CCSR_SSI_SxCCR_DC(slots));
874
875 /* The register SxMSKs needs SSI to provide essential clock due to
876 * hardware design. So we here temporarily enable SSI to set them.
877 */
878 val = read_ssi(&ssi->scr) & CCSR_SSI_SCR_SSIEN;
879 write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN);
880
881 write_ssi(tx_mask, &ssi->stmsk);
882 write_ssi(rx_mask, &ssi->srmsk);
883
884 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, val);
885
886 return 0;
887}
888
889/**
Timur Tabi17467f22008-01-11 18:15:26 +0100890 * fsl_ssi_trigger: start and stop the DMA transfer.
891 *
892 * This function is called by ALSA to start, stop, pause, and resume the DMA
893 * transfer of data.
894 *
895 * The DMA channel is in external master start and pause mode, which
896 * means the SSI completely controls the flow of data.
897 */
Mark Browndee89c42008-11-18 22:11:38 +0000898static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
899 struct snd_soc_dai *dai)
Timur Tabi17467f22008-01-11 18:15:26 +0100900{
901 struct snd_soc_pcm_runtime *rtd = substream->private_data;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000902 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
Timur Tabi17467f22008-01-11 18:15:26 +0100903 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
Michael Grzeschik9b443e32013-08-19 17:06:00 +0200904 unsigned int sier_bits;
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800905 unsigned long flags;
Michael Grzeschik9b443e32013-08-19 17:06:00 +0200906
907 /*
908 * Enable only the interrupts and DMA requests
909 * that are needed for the channel. As the fiq
910 * is polling for this bits, we have to ensure
911 * that this are aligned with the preallocated
912 * buffers
913 */
914
915 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
916 if (ssi_private->use_dma)
917 sier_bits = SIER_FLAGS;
918 else
919 sier_bits = CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TFE0_EN;
920 } else {
921 if (ssi_private->use_dma)
922 sier_bits = SIER_FLAGS;
923 else
924 sier_bits = CCSR_SSI_SIER_RIE | CCSR_SSI_SIER_RFF0_EN;
925 }
Timur Tabi17467f22008-01-11 18:15:26 +0100926
927 switch (cmd) {
928 case SNDRV_PCM_TRIGGER_START:
Timur Tabi17467f22008-01-11 18:15:26 +0100929 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
Timur Tabia4d11fe2009-03-25 18:20:37 -0500930 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
Shawn Guodfa1a102012-03-16 16:56:42 +0800931 write_ssi_mask(&ssi->scr, 0,
Timur Tabibe41e942008-07-28 17:04:39 -0500932 CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE);
Timur Tabia4d11fe2009-03-25 18:20:37 -0500933 else
Shawn Guodfa1a102012-03-16 16:56:42 +0800934 write_ssi_mask(&ssi->scr, 0,
Timur Tabibe41e942008-07-28 17:04:39 -0500935 CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE);
Timur Tabi17467f22008-01-11 18:15:26 +0100936 break;
937
938 case SNDRV_PCM_TRIGGER_STOP:
Timur Tabi17467f22008-01-11 18:15:26 +0100939 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
940 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
Shawn Guodfa1a102012-03-16 16:56:42 +0800941 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_TE, 0);
Timur Tabi17467f22008-01-11 18:15:26 +0100942 else
Shawn Guodfa1a102012-03-16 16:56:42 +0800943 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0);
Nicolin Chenb2c119b2013-07-10 18:43:54 +0800944
Markus Pargmanncd7f0292013-08-19 17:05:58 +0200945 if (!ssi_private->imx_ac97 && (read_ssi(&ssi->scr) &
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800946 (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0) {
Nicolin Chenb2c119b2013-07-10 18:43:54 +0800947 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0);
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800948 spin_lock_irqsave(&ssi_private->baudclk_lock, flags);
949 ssi_private->baudclk_locked = false;
950 spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
951 }
Timur Tabi17467f22008-01-11 18:15:26 +0100952 break;
953
954 default:
955 return -EINVAL;
956 }
957
Michael Grzeschik9b443e32013-08-19 17:06:00 +0200958 write_ssi(sier_bits, &ssi->sier);
959
Timur Tabi17467f22008-01-11 18:15:26 +0100960 return 0;
961}
962
Lars-Peter Clausenfc8ba7f2013-04-15 19:19:58 +0200963static int fsl_ssi_dai_probe(struct snd_soc_dai *dai)
964{
965 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai);
966
Markus Pargmannde623ec2013-07-27 13:31:53 +0200967 if (ssi_private->ssi_on_imx && ssi_private->use_dma) {
Lars-Peter Clausenfc8ba7f2013-04-15 19:19:58 +0200968 dai->playback_dma_data = &ssi_private->dma_params_tx;
969 dai->capture_dma_data = &ssi_private->dma_params_rx;
970 }
971
972 return 0;
973}
974
Lars-Peter Clausen85e76522011-11-23 11:40:40 +0100975static const struct snd_soc_dai_ops fsl_ssi_dai_ops = {
Eric Miao6335d052009-03-03 09:41:00 +0800976 .startup = fsl_ssi_startup,
977 .hw_params = fsl_ssi_hw_params,
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800978 .set_fmt = fsl_ssi_set_dai_fmt,
979 .set_sysclk = fsl_ssi_set_dai_sysclk,
980 .set_tdm_slot = fsl_ssi_set_dai_tdm_slot,
Eric Miao6335d052009-03-03 09:41:00 +0800981 .trigger = fsl_ssi_trigger,
Eric Miao6335d052009-03-03 09:41:00 +0800982};
983
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000984/* Template for the CPU dai driver structure */
985static struct snd_soc_dai_driver fsl_ssi_dai_template = {
Lars-Peter Clausenfc8ba7f2013-04-15 19:19:58 +0200986 .probe = fsl_ssi_dai_probe,
Timur Tabi17467f22008-01-11 18:15:26 +0100987 .playback = {
Nicolin Chen2924a992013-12-02 23:29:03 +0800988 .channels_min = 1,
Timur Tabi17467f22008-01-11 18:15:26 +0100989 .channels_max = 2,
990 .rates = FSLSSI_I2S_RATES,
991 .formats = FSLSSI_I2S_FORMATS,
992 },
993 .capture = {
Nicolin Chen2924a992013-12-02 23:29:03 +0800994 .channels_min = 1,
Timur Tabi17467f22008-01-11 18:15:26 +0100995 .channels_max = 2,
996 .rates = FSLSSI_I2S_RATES,
997 .formats = FSLSSI_I2S_FORMATS,
998 },
Eric Miao6335d052009-03-03 09:41:00 +0800999 .ops = &fsl_ssi_dai_ops,
Timur Tabi17467f22008-01-11 18:15:26 +01001000};
1001
Kuninori Morimoto3580aa12013-03-21 03:32:04 -07001002static const struct snd_soc_component_driver fsl_ssi_component = {
1003 .name = "fsl-ssi",
1004};
1005
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001006/**
1007 * fsl_ssi_ac97_trigger: start and stop the AC97 receive/transmit.
1008 *
1009 * This function is called by ALSA to start, stop, pause, and resume the
1010 * transfer of data.
1011 */
1012static int fsl_ssi_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
1013 struct snd_soc_dai *dai)
1014{
1015 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1016 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(
1017 rtd->cpu_dai);
1018 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
1019
1020 switch (cmd) {
1021 case SNDRV_PCM_TRIGGER_START:
1022 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1023 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1024 write_ssi_mask(&ssi->sier, 0, CCSR_SSI_SIER_TIE |
1025 CCSR_SSI_SIER_TFE0_EN);
1026 else
1027 write_ssi_mask(&ssi->sier, 0, CCSR_SSI_SIER_RIE |
1028 CCSR_SSI_SIER_RFF0_EN);
1029 break;
1030
1031 case SNDRV_PCM_TRIGGER_STOP:
1032 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1033 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1034 write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_TIE |
1035 CCSR_SSI_SIER_TFE0_EN, 0);
1036 else
1037 write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_RIE |
1038 CCSR_SSI_SIER_RFF0_EN, 0);
1039 break;
1040
1041 default:
1042 return -EINVAL;
1043 }
1044
1045 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1046 write_ssi(CCSR_SSI_SOR_TX_CLR, &ssi->sor);
1047 else
1048 write_ssi(CCSR_SSI_SOR_RX_CLR, &ssi->sor);
1049
1050 return 0;
1051}
1052
1053static const struct snd_soc_dai_ops fsl_ssi_ac97_dai_ops = {
1054 .startup = fsl_ssi_startup,
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001055 .trigger = fsl_ssi_ac97_trigger,
1056};
1057
1058static struct snd_soc_dai_driver fsl_ssi_ac97_dai = {
1059 .ac97_control = 1,
1060 .playback = {
1061 .stream_name = "AC97 Playback",
1062 .channels_min = 2,
1063 .channels_max = 2,
1064 .rates = SNDRV_PCM_RATE_8000_48000,
1065 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1066 },
1067 .capture = {
1068 .stream_name = "AC97 Capture",
1069 .channels_min = 2,
1070 .channels_max = 2,
1071 .rates = SNDRV_PCM_RATE_48000,
1072 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1073 },
1074 .ops = &fsl_ssi_ac97_dai_ops,
1075};
1076
1077
1078static struct fsl_ssi_private *fsl_ac97_data;
1079
1080static void fsl_ssi_ac97_init(void)
1081{
1082 fsl_ssi_setup(fsl_ac97_data);
1083}
1084
Sachin Kamata851a2b2013-09-13 15:22:17 +05301085static void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001086 unsigned short val)
1087{
1088 struct ccsr_ssi *ssi = fsl_ac97_data->ssi;
1089 unsigned int lreg;
1090 unsigned int lval;
1091
1092 if (reg > 0x7f)
1093 return;
1094
1095
1096 lreg = reg << 12;
1097 write_ssi(lreg, &ssi->sacadd);
1098
1099 lval = val << 4;
1100 write_ssi(lval , &ssi->sacdat);
1101
1102 write_ssi_mask(&ssi->sacnt, CCSR_SSI_SACNT_RDWR_MASK,
1103 CCSR_SSI_SACNT_WR);
1104 udelay(100);
1105}
1106
Sachin Kamata851a2b2013-09-13 15:22:17 +05301107static unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97,
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001108 unsigned short reg)
1109{
1110 struct ccsr_ssi *ssi = fsl_ac97_data->ssi;
1111
1112 unsigned short val = -1;
1113 unsigned int lreg;
1114
1115 lreg = (reg & 0x7f) << 12;
1116 write_ssi(lreg, &ssi->sacadd);
1117 write_ssi_mask(&ssi->sacnt, CCSR_SSI_SACNT_RDWR_MASK,
1118 CCSR_SSI_SACNT_RD);
1119
1120 udelay(100);
1121
1122 val = (read_ssi(&ssi->sacdat) >> 4) & 0xffff;
1123
1124 return val;
1125}
1126
1127static struct snd_ac97_bus_ops fsl_ssi_ac97_ops = {
1128 .read = fsl_ssi_ac97_read,
1129 .write = fsl_ssi_ac97_write,
1130};
1131
Timur Tabi17467f22008-01-11 18:15:26 +01001132/**
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001133 * Make every character in a string lower-case
Timur Tabi17467f22008-01-11 18:15:26 +01001134 */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001135static void make_lowercase(char *s)
Timur Tabi17467f22008-01-11 18:15:26 +01001136{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001137 char *p = s;
1138 char c;
1139
1140 while ((c = *p)) {
1141 if ((c >= 'A') && (c <= 'Z'))
1142 *p = c + ('a' - 'A');
1143 p++;
1144 }
1145}
1146
Bill Pembertona0a3d512012-12-07 09:26:16 -05001147static int fsl_ssi_probe(struct platform_device *pdev)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001148{
Timur Tabi17467f22008-01-11 18:15:26 +01001149 struct fsl_ssi_private *ssi_private;
1150 int ret = 0;
Timur Tabi87a06322010-08-03 17:55:28 -05001151 struct device_attribute *dev_attr = NULL;
Timur Tabi38fec722010-08-19 15:26:58 -05001152 struct device_node *np = pdev->dev.of_node;
Markus Pargmannc1953bf2013-12-20 14:11:30 +01001153 const struct of_device_id *of_id;
1154 enum fsl_ssi_type hw_type;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001155 const char *p, *sprop;
Timur Tabi8e9d8692010-08-06 12:16:12 -05001156 const uint32_t *iprop;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001157 struct resource res;
1158 char name[64];
Lars-Peter Clausen312bb4f2013-03-22 14:12:12 +01001159 bool shared;
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001160 bool ac97 = false;
Timur Tabi17467f22008-01-11 18:15:26 +01001161
Timur Tabiff713342010-08-04 17:51:08 -05001162 /* SSIs that are not connected on the board should have a
1163 * status = "disabled"
1164 * property in their device tree nodes.
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001165 */
Timur Tabiff713342010-08-04 17:51:08 -05001166 if (!of_device_is_available(np))
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001167 return -ENODEV;
1168
Markus Pargmannc1953bf2013-12-20 14:11:30 +01001169 of_id = of_match_device(fsl_ssi_ids, &pdev->dev);
1170 if (!of_id)
1171 return -EINVAL;
1172 hw_type = (enum fsl_ssi_type) of_id->data;
1173
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001174 /* We only support the SSI in "I2S Slave" mode */
1175 sprop = of_get_property(np, "fsl,mode", NULL);
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001176 if (!sprop) {
1177 dev_err(&pdev->dev, "fsl,mode property is necessary\n");
1178 return -EINVAL;
1179 }
1180 if (!strcmp(sprop, "ac97-slave")) {
1181 ac97 = true;
1182 } else if (strcmp(sprop, "i2s-slave")) {
Timur Tabi38fec722010-08-19 15:26:58 -05001183 dev_notice(&pdev->dev, "mode %s is unsupported\n", sprop);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001184 return -ENODEV;
Timur Tabi17467f22008-01-11 18:15:26 +01001185 }
Timur Tabi17467f22008-01-11 18:15:26 +01001186
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001187 /* The DAI name is the last part of the full name of the node. */
1188 p = strrchr(np->full_name, '/') + 1;
Fabio Estevamb0a47472013-07-17 02:00:38 -03001189 ssi_private = devm_kzalloc(&pdev->dev, sizeof(*ssi_private) + strlen(p),
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001190 GFP_KERNEL);
1191 if (!ssi_private) {
Timur Tabi38fec722010-08-19 15:26:58 -05001192 dev_err(&pdev->dev, "could not allocate DAI object\n");
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001193 return -ENOMEM;
1194 }
Timur Tabi17467f22008-01-11 18:15:26 +01001195
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001196 strcpy(ssi_private->name, p);
Timur Tabi17467f22008-01-11 18:15:26 +01001197
Markus Pargmannde623ec2013-07-27 13:31:53 +02001198 ssi_private->use_dma = !of_property_read_bool(np,
1199 "fsl,fiq-stream-filter");
Markus Pargmann0888efd2013-12-20 14:11:31 +01001200 ssi_private->hw_type = hw_type;
Markus Pargmannde623ec2013-07-27 13:31:53 +02001201
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001202 if (ac97) {
1203 memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_ac97_dai,
1204 sizeof(fsl_ssi_ac97_dai));
1205
1206 fsl_ac97_data = ssi_private;
1207 ssi_private->imx_ac97 = true;
1208
1209 snd_soc_set_ac97_ops_of_reset(&fsl_ssi_ac97_ops, pdev);
1210 } else {
1211 /* Initialize this copy of the CPU DAI driver structure */
1212 memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template,
1213 sizeof(fsl_ssi_dai_template));
1214 }
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001215 ssi_private->cpu_dai_drv.name = ssi_private->name;
1216
1217 /* Get the addresses and IRQ */
1218 ret = of_address_to_resource(np, 0, &res);
1219 if (ret) {
Timur Tabi38fec722010-08-19 15:26:58 -05001220 dev_err(&pdev->dev, "could not determine device resources\n");
Fabio Estevamb0a47472013-07-17 02:00:38 -03001221 return ret;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001222 }
Timur Tabi147dfe92011-06-08 15:02:55 -05001223 ssi_private->ssi = of_iomap(np, 0);
1224 if (!ssi_private->ssi) {
1225 dev_err(&pdev->dev, "could not map device resources\n");
Fabio Estevamb0a47472013-07-17 02:00:38 -03001226 return -ENOMEM;
Timur Tabi147dfe92011-06-08 15:02:55 -05001227 }
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001228 ssi_private->ssi_phys = res.start;
Timur Tabi1fab6ca2011-08-16 18:47:45 -04001229
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001230 ssi_private->irq = irq_of_parse_and_map(np, 0);
Chen Gangd60336e2013-09-23 11:36:21 +08001231 if (!ssi_private->irq) {
Timur Tabi1fab6ca2011-08-16 18:47:45 -04001232 dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
Fabio Estevamb0a47472013-07-17 02:00:38 -03001233 return -ENXIO;
Timur Tabi1fab6ca2011-08-16 18:47:45 -04001234 }
1235
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001236 /* Are the RX and the TX clocks locked? */
Nicolin Chen07a94832013-12-03 18:38:07 +08001237 if (!of_find_property(np, "fsl,ssi-asynchronous", NULL)) {
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001238 ssi_private->cpu_dai_drv.symmetric_rates = 1;
Nicolin Chen07a94832013-12-03 18:38:07 +08001239 ssi_private->cpu_dai_drv.symmetric_channels = 1;
1240 ssi_private->cpu_dai_drv.symmetric_samplebits = 1;
1241 }
Timur Tabi17467f22008-01-11 18:15:26 +01001242
Timur Tabi8e9d8692010-08-06 12:16:12 -05001243 /* Determine the FIFO depth. */
1244 iprop = of_get_property(np, "fsl,fifo-depth", NULL);
1245 if (iprop)
Timur Tabi147dfe92011-06-08 15:02:55 -05001246 ssi_private->fifo_depth = be32_to_cpup(iprop);
Timur Tabi8e9d8692010-08-06 12:16:12 -05001247 else
1248 /* Older 8610 DTs didn't have the fifo-depth property */
1249 ssi_private->fifo_depth = 8;
1250
Nicolin Chenaafa85e2013-12-12 18:44:45 +08001251 ssi_private->baudclk_locked = false;
1252 spin_lock_init(&ssi_private->baudclk_lock);
1253
Markus Pargmannc1953bf2013-12-20 14:11:30 +01001254 if (hw_type == FSL_SSI_MX21 || hw_type == FSL_SSI_MX51 ||
1255 hw_type == FSL_SSI_MX35) {
Shawn Guo09ce1112012-03-16 16:56:43 +08001256 u32 dma_events[2];
1257 ssi_private->ssi_on_imx = true;
Shawn Guo95cd98f2012-03-29 10:53:41 +08001258
Fabio Estevamb0a47472013-07-17 02:00:38 -03001259 ssi_private->clk = devm_clk_get(&pdev->dev, NULL);
Shawn Guo95cd98f2012-03-29 10:53:41 +08001260 if (IS_ERR(ssi_private->clk)) {
1261 ret = PTR_ERR(ssi_private->clk);
1262 dev_err(&pdev->dev, "could not get clock: %d\n", ret);
Fabio Estevamb0a47472013-07-17 02:00:38 -03001263 goto error_irqmap;
Shawn Guo95cd98f2012-03-29 10:53:41 +08001264 }
Fabio Estevamede32d32013-07-17 02:00:39 -03001265 ret = clk_prepare_enable(ssi_private->clk);
1266 if (ret) {
1267 dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n",
1268 ret);
1269 goto error_irqmap;
1270 }
Shawn Guo95cd98f2012-03-29 10:53:41 +08001271
Nicolin Chenaafa85e2013-12-12 18:44:45 +08001272 /* For those SLAVE implementations, we ingore non-baudclk cases
1273 * and, instead, abandon MASTER mode that needs baud clock.
1274 */
1275 ssi_private->baudclk = devm_clk_get(&pdev->dev, "baud");
1276 if (IS_ERR(ssi_private->baudclk))
Fabio Estevamff1b15a2014-01-07 08:00:13 -02001277 dev_warn(&pdev->dev, "could not get baud clock: %ld\n",
Alexander Shiyan6873ee42014-01-05 10:21:16 +04001278 PTR_ERR(ssi_private->baudclk));
Nicolin Chenaafa85e2013-12-12 18:44:45 +08001279 else
1280 clk_prepare_enable(ssi_private->baudclk);
1281
Shawn Guo09ce1112012-03-16 16:56:43 +08001282 /*
1283 * We have burstsize be "fifo_depth - 2" to match the SSI
1284 * watermark setting in fsl_ssi_startup().
1285 */
Lars-Peter Clausena8909c92013-04-03 11:06:04 +02001286 ssi_private->dma_params_tx.maxburst =
Shawn Guo09ce1112012-03-16 16:56:43 +08001287 ssi_private->fifo_depth - 2;
Lars-Peter Clausena8909c92013-04-03 11:06:04 +02001288 ssi_private->dma_params_rx.maxburst =
Shawn Guo09ce1112012-03-16 16:56:43 +08001289 ssi_private->fifo_depth - 2;
Lars-Peter Clausena8909c92013-04-03 11:06:04 +02001290 ssi_private->dma_params_tx.addr =
Shawn Guo09ce1112012-03-16 16:56:43 +08001291 ssi_private->ssi_phys + offsetof(struct ccsr_ssi, stx0);
Lars-Peter Clausena8909c92013-04-03 11:06:04 +02001292 ssi_private->dma_params_rx.addr =
Shawn Guo09ce1112012-03-16 16:56:43 +08001293 ssi_private->ssi_phys + offsetof(struct ccsr_ssi, srx0);
Lars-Peter Clausena8909c92013-04-03 11:06:04 +02001294 ssi_private->dma_params_tx.filter_data =
1295 &ssi_private->filter_data_tx;
1296 ssi_private->dma_params_rx.filter_data =
1297 &ssi_private->filter_data_rx;
Markus Pargmann3a5e5172013-07-27 13:31:54 +02001298 if (!of_property_read_bool(pdev->dev.of_node, "dmas") &&
1299 ssi_private->use_dma) {
1300 /*
1301 * FIXME: This is a temporary solution until all
1302 * necessary dma drivers support the generic dma
1303 * bindings.
1304 */
1305 ret = of_property_read_u32_array(pdev->dev.of_node,
Shawn Guo09ce1112012-03-16 16:56:43 +08001306 "fsl,ssi-dma-events", dma_events, 2);
Markus Pargmann3a5e5172013-07-27 13:31:54 +02001307 if (ret && ssi_private->use_dma) {
1308 dev_err(&pdev->dev, "could not get dma events but fsl-ssi is configured to use DMA\n");
1309 goto error_clk;
1310 }
Shawn Guo09ce1112012-03-16 16:56:43 +08001311 }
Shawn Guob46b3732012-03-28 15:34:56 +08001312
Lars-Peter Clausen312bb4f2013-03-22 14:12:12 +01001313 shared = of_device_is_compatible(of_get_parent(np),
1314 "fsl,spba-bus");
1315
Lars-Peter Clausena8909c92013-04-03 11:06:04 +02001316 imx_pcm_dma_params_init_data(&ssi_private->filter_data_tx,
Nicolin Chen32bd8cd2013-07-25 17:41:41 +08001317 dma_events[0], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI);
Lars-Peter Clausena8909c92013-04-03 11:06:04 +02001318 imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx,
Nicolin Chen32bd8cd2013-07-25 17:41:41 +08001319 dma_events[1], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI);
Markus Pargmann0888efd2013-12-20 14:11:31 +01001320 }
1321
1322 /*
1323 * Enable interrupts only for MCP8610 and MX51. The other MXs have
1324 * different writeable interrupt status registers.
1325 */
1326 if (ssi_private->use_dma) {
Michael Grzeschikf0377082013-08-19 17:06:01 +02001327 /* The 'name' should not have any slashes in it. */
1328 ret = devm_request_irq(&pdev->dev, ssi_private->irq,
1329 fsl_ssi_isr, 0, ssi_private->name,
1330 ssi_private);
Markus Pargmann2841be92013-12-20 14:11:28 +01001331 ssi_private->irq_stats = true;
Michael Grzeschikf0377082013-08-19 17:06:01 +02001332 if (ret < 0) {
1333 dev_err(&pdev->dev, "could not claim irq %u\n",
1334 ssi_private->irq);
1335 goto error_irqmap;
1336 }
Shawn Guo09ce1112012-03-16 16:56:43 +08001337 }
1338
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001339 /* Register with ASoC */
Timur Tabi38fec722010-08-19 15:26:58 -05001340 dev_set_drvdata(&pdev->dev, ssi_private);
Mark Brown3f4b7832008-12-03 19:26:35 +00001341
Kuninori Morimoto3580aa12013-03-21 03:32:04 -07001342 ret = snd_soc_register_component(&pdev->dev, &fsl_ssi_component,
1343 &ssi_private->cpu_dai_drv, 1);
Timur Tabi87a06322010-08-03 17:55:28 -05001344 if (ret) {
Timur Tabi38fec722010-08-19 15:26:58 -05001345 dev_err(&pdev->dev, "failed to register DAI: %d\n", ret);
Timur Tabi1fab6ca2011-08-16 18:47:45 -04001346 goto error_dev;
Mark Brown3f4b7832008-12-03 19:26:35 +00001347 }
Timur Tabi17467f22008-01-11 18:15:26 +01001348
Markus Pargmann9368acc2013-12-20 14:11:29 +01001349 ret = fsl_ssi_debugfs_create(ssi_private, &pdev->dev);
1350 if (ret)
1351 goto error_dbgfs;
1352
Shawn Guo09ce1112012-03-16 16:56:43 +08001353 if (ssi_private->ssi_on_imx) {
Markus Pargmannde623ec2013-07-27 13:31:53 +02001354 if (!ssi_private->use_dma) {
1355
1356 /*
1357 * Some boards use an incompatible codec. To get it
1358 * working, we are using imx-fiq-pcm-audio, that
1359 * can handle those codecs. DMA is not possible in this
1360 * situation.
1361 */
1362
1363 ssi_private->fiq_params.irq = ssi_private->irq;
1364 ssi_private->fiq_params.base = ssi_private->ssi;
1365 ssi_private->fiq_params.dma_params_rx =
1366 &ssi_private->dma_params_rx;
1367 ssi_private->fiq_params.dma_params_tx =
1368 &ssi_private->dma_params_tx;
1369
1370 ret = imx_pcm_fiq_init(pdev, &ssi_private->fiq_params);
1371 if (ret)
Markus Pargmann2841be92013-12-20 14:11:28 +01001372 goto error_pcm;
Markus Pargmannde623ec2013-07-27 13:31:53 +02001373 } else {
1374 ret = imx_pcm_dma_init(pdev);
1375 if (ret)
Markus Pargmann2841be92013-12-20 14:11:28 +01001376 goto error_pcm;
Markus Pargmannde623ec2013-07-27 13:31:53 +02001377 }
Shawn Guo09ce1112012-03-16 16:56:43 +08001378 }
1379
1380 /*
1381 * If codec-handle property is missing from SSI node, we assume
1382 * that the machine driver uses new binding which does not require
1383 * SSI driver to trigger machine driver's probe.
1384 */
1385 if (!of_get_property(np, "codec-handle", NULL)) {
1386 ssi_private->new_binding = true;
1387 goto done;
1388 }
1389
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001390 /* Trigger the machine driver's probe function. The platform driver
Shawn Guo2b81ec62012-03-09 00:59:46 +08001391 * name of the machine driver is taken from /compatible property of the
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001392 * device tree. We also pass the address of the CPU DAI driver
1393 * structure.
1394 */
Shawn Guo2b81ec62012-03-09 00:59:46 +08001395 sprop = of_get_property(of_find_node_by_path("/"), "compatible", NULL);
1396 /* Sometimes the compatible name has a "fsl," prefix, so we strip it. */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001397 p = strrchr(sprop, ',');
1398 if (p)
1399 sprop = p + 1;
1400 snprintf(name, sizeof(name), "snd-soc-%s", sprop);
1401 make_lowercase(name);
1402
1403 ssi_private->pdev =
Timur Tabi38fec722010-08-19 15:26:58 -05001404 platform_device_register_data(&pdev->dev, name, 0, NULL, 0);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001405 if (IS_ERR(ssi_private->pdev)) {
1406 ret = PTR_ERR(ssi_private->pdev);
Timur Tabi38fec722010-08-19 15:26:58 -05001407 dev_err(&pdev->dev, "failed to register platform: %d\n", ret);
Timur Tabi1fab6ca2011-08-16 18:47:45 -04001408 goto error_dai;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001409 }
1410
Shawn Guo09ce1112012-03-16 16:56:43 +08001411done:
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001412 if (ssi_private->imx_ac97)
1413 fsl_ssi_ac97_init();
1414
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001415 return 0;
Timur Tabi87a06322010-08-03 17:55:28 -05001416
Timur Tabi1fab6ca2011-08-16 18:47:45 -04001417error_dai:
Markus Pargmann2841be92013-12-20 14:11:28 +01001418 if (ssi_private->ssi_on_imx && !ssi_private->use_dma)
1419 imx_pcm_fiq_exit(pdev);
1420
1421error_pcm:
Markus Pargmann9368acc2013-12-20 14:11:29 +01001422 fsl_ssi_debugfs_remove(ssi_private);
1423
1424error_dbgfs:
Kuninori Morimoto3580aa12013-03-21 03:32:04 -07001425 snd_soc_unregister_component(&pdev->dev);
Timur Tabi1fab6ca2011-08-16 18:47:45 -04001426
1427error_dev:
Timur Tabi1fab6ca2011-08-16 18:47:45 -04001428 device_remove_file(&pdev->dev, dev_attr);
1429
Shawn Guo95cd98f2012-03-29 10:53:41 +08001430error_clk:
Nicolin Chenaafa85e2013-12-12 18:44:45 +08001431 if (ssi_private->ssi_on_imx) {
1432 if (!IS_ERR(ssi_private->baudclk))
1433 clk_disable_unprepare(ssi_private->baudclk);
Shawn Guo95cd98f2012-03-29 10:53:41 +08001434 clk_disable_unprepare(ssi_private->clk);
Nicolin Chenaafa85e2013-12-12 18:44:45 +08001435 }
Timur Tabi1fab6ca2011-08-16 18:47:45 -04001436
1437error_irqmap:
Markus Pargmann2841be92013-12-20 14:11:28 +01001438 if (ssi_private->irq_stats)
1439 irq_dispose_mapping(ssi_private->irq);
Timur Tabi1fab6ca2011-08-16 18:47:45 -04001440
Timur Tabi87a06322010-08-03 17:55:28 -05001441 return ret;
Timur Tabi17467f22008-01-11 18:15:26 +01001442}
Timur Tabi17467f22008-01-11 18:15:26 +01001443
Timur Tabi38fec722010-08-19 15:26:58 -05001444static int fsl_ssi_remove(struct platform_device *pdev)
Timur Tabi17467f22008-01-11 18:15:26 +01001445{
Timur Tabi38fec722010-08-19 15:26:58 -05001446 struct fsl_ssi_private *ssi_private = dev_get_drvdata(&pdev->dev);
Timur Tabi17467f22008-01-11 18:15:26 +01001447
Markus Pargmann9368acc2013-12-20 14:11:29 +01001448 fsl_ssi_debugfs_remove(ssi_private);
1449
Shawn Guo09ce1112012-03-16 16:56:43 +08001450 if (!ssi_private->new_binding)
1451 platform_device_unregister(ssi_private->pdev);
Kuninori Morimoto3580aa12013-03-21 03:32:04 -07001452 snd_soc_unregister_component(&pdev->dev);
Nicolin Chenaafa85e2013-12-12 18:44:45 +08001453 if (ssi_private->ssi_on_imx) {
1454 if (!IS_ERR(ssi_private->baudclk))
1455 clk_disable_unprepare(ssi_private->baudclk);
Fabio Estevam0783e642013-08-17 18:13:00 -03001456 clk_disable_unprepare(ssi_private->clk);
Nicolin Chenaafa85e2013-12-12 18:44:45 +08001457 }
Markus Pargmann2841be92013-12-20 14:11:28 +01001458 if (ssi_private->irq_stats)
1459 irq_dispose_mapping(ssi_private->irq);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001460
1461 return 0;
Timur Tabi17467f22008-01-11 18:15:26 +01001462}
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001463
Grant Likelyf07eb222011-02-22 21:05:04 -07001464static struct platform_driver fsl_ssi_driver = {
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001465 .driver = {
1466 .name = "fsl-ssi-dai",
1467 .owner = THIS_MODULE,
1468 .of_match_table = fsl_ssi_ids,
1469 },
1470 .probe = fsl_ssi_probe,
1471 .remove = fsl_ssi_remove,
1472};
Timur Tabi17467f22008-01-11 18:15:26 +01001473
Axel Linba0a7e02011-11-25 10:10:55 +08001474module_platform_driver(fsl_ssi_driver);
Timur Tabia454dad2009-03-05 17:23:37 -06001475
Fabio Estevamf3142802013-07-20 16:16:01 -03001476MODULE_ALIAS("platform:fsl-ssi-dai");
Timur Tabi17467f22008-01-11 18:15:26 +01001477MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
1478MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver");
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001479MODULE_LICENSE("GPL v2");