blob: 40dfd8a3648408a2cc76bb6e4c4c3872c8e28ac3 [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>
Timur Tabi17467f22008-01-11 18:15:26 +010038#include <linux/device.h>
39#include <linux/delay.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090040#include <linux/slab.h>
Nicolin Chenaafa85e2013-12-12 18:44:45 +080041#include <linux/spinlock.h>
Mark Brown9c72a042014-04-15 12:02:02 +010042#include <linux/of.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
57/**
58 * FSLSSI_I2S_RATES: sample rates supported by the I2S
59 *
60 * This driver currently only supports the SSI running in I2S slave mode,
61 * which means the codec determines the sample rate. Therefore, we tell
62 * ALSA that we support all rates and let the codec driver decide what rates
63 * are really supported.
64 */
Lars-Peter Clausen24710c92014-01-11 10:24:41 +010065#define FSLSSI_I2S_RATES SNDRV_PCM_RATE_CONTINUOUS
Timur Tabi17467f22008-01-11 18:15:26 +010066
67/**
68 * FSLSSI_I2S_FORMATS: audio formats supported by the SSI
69 *
Timur Tabi17467f22008-01-11 18:15:26 +010070 * The SSI has a limitation in that the samples must be in the same byte
71 * order as the host CPU. This is because when multiple bytes are written
72 * to the STX register, the bytes and bits must be written in the same
73 * order. The STX is a shift register, so all the bits need to be aligned
74 * (bit-endianness must match byte-endianness). Processors typically write
75 * the bits within a byte in the same order that the bytes of a word are
76 * written in. So if the host CPU is big-endian, then only big-endian
77 * samples will be written to STX properly.
78 */
79#ifdef __BIG_ENDIAN
80#define FSLSSI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | \
81 SNDRV_PCM_FMTBIT_S18_3BE | SNDRV_PCM_FMTBIT_S20_3BE | \
82 SNDRV_PCM_FMTBIT_S24_3BE | SNDRV_PCM_FMTBIT_S24_BE)
83#else
84#define FSLSSI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
85 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE | \
86 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE)
87#endif
88
Markus Pargmann9368acc2013-12-20 14:11:29 +010089#define FSLSSI_SIER_DBG_RX_FLAGS (CCSR_SSI_SIER_RFF0_EN | \
90 CCSR_SSI_SIER_RLS_EN | CCSR_SSI_SIER_RFS_EN | \
91 CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_RFRC_EN)
92#define FSLSSI_SIER_DBG_TX_FLAGS (CCSR_SSI_SIER_TFE0_EN | \
93 CCSR_SSI_SIER_TLS_EN | CCSR_SSI_SIER_TFS_EN | \
94 CCSR_SSI_SIER_TUE0_EN | CCSR_SSI_SIER_TFRC_EN)
Markus Pargmannc1953bf2013-12-20 14:11:30 +010095
96enum fsl_ssi_type {
97 FSL_SSI_MCP8610,
98 FSL_SSI_MX21,
Markus Pargmann0888efd2013-12-20 14:11:31 +010099 FSL_SSI_MX35,
Markus Pargmannc1953bf2013-12-20 14:11:30 +0100100 FSL_SSI_MX51,
101};
102
Markus Pargmann4e6ec0d2013-12-20 14:11:33 +0100103struct fsl_ssi_reg_val {
104 u32 sier;
105 u32 srcr;
106 u32 stcr;
107 u32 scr;
108};
109
110struct fsl_ssi_rxtx_reg_val {
111 struct fsl_ssi_reg_val rx;
112 struct fsl_ssi_reg_val tx;
113};
Zidan Wang05cf2372015-09-18 11:09:12 +0800114
115static const struct reg_default fsl_ssi_reg_defaults[] = {
Zidan Wangf4faa292015-10-26 15:19:05 +0800116 {CCSR_SSI_SCR, 0x00000000},
117 {CCSR_SSI_SIER, 0x00003003},
118 {CCSR_SSI_STCR, 0x00000200},
119 {CCSR_SSI_SRCR, 0x00000200},
120 {CCSR_SSI_STCCR, 0x00040000},
121 {CCSR_SSI_SRCCR, 0x00040000},
122 {CCSR_SSI_SACNT, 0x00000000},
123 {CCSR_SSI_STMSK, 0x00000000},
124 {CCSR_SSI_SRMSK, 0x00000000},
125 {CCSR_SSI_SACCEN, 0x00000000},
126 {CCSR_SSI_SACCDIS, 0x00000000},
Zidan Wang05cf2372015-09-18 11:09:12 +0800127};
128
129static bool fsl_ssi_readable_reg(struct device *dev, unsigned int reg)
130{
131 switch (reg) {
132 case CCSR_SSI_SACCEN:
133 case CCSR_SSI_SACCDIS:
134 return false;
135 default:
136 return true;
137 }
138}
139
140static bool fsl_ssi_volatile_reg(struct device *dev, unsigned int reg)
141{
142 switch (reg) {
143 case CCSR_SSI_STX0:
144 case CCSR_SSI_STX1:
145 case CCSR_SSI_SRX0:
146 case CCSR_SSI_SRX1:
147 case CCSR_SSI_SISR:
148 case CCSR_SSI_SFCSR:
Maciej S. Szmigiero3f1c2412015-12-20 21:30:25 +0100149 case CCSR_SSI_SACNT:
Zidan Wang05cf2372015-09-18 11:09:12 +0800150 case CCSR_SSI_SACADD:
151 case CCSR_SSI_SACDAT:
152 case CCSR_SSI_SATAG:
153 case CCSR_SSI_SACCST:
154 return true;
155 default:
156 return false;
157 }
158}
159
Maciej S. Szmigierof51e3d52015-12-20 21:31:48 +0100160static bool fsl_ssi_precious_reg(struct device *dev, unsigned int reg)
161{
162 switch (reg) {
163 case CCSR_SSI_SRX0:
164 case CCSR_SSI_SRX1:
165 case CCSR_SSI_SISR:
166 case CCSR_SSI_SACADD:
167 case CCSR_SSI_SACDAT:
168 case CCSR_SSI_SATAG:
169 return true;
170 default:
171 return false;
172 }
173}
174
Zidan Wang05cf2372015-09-18 11:09:12 +0800175static bool fsl_ssi_writeable_reg(struct device *dev, unsigned int reg)
176{
177 switch (reg) {
178 case CCSR_SSI_SRX0:
179 case CCSR_SSI_SRX1:
180 case CCSR_SSI_SACCST:
181 return false;
182 default:
183 return true;
184 }
185}
186
Markus Pargmann43248122014-05-27 10:24:25 +0200187static const struct regmap_config fsl_ssi_regconfig = {
188 .max_register = CCSR_SSI_SACCDIS,
189 .reg_bits = 32,
190 .val_bits = 32,
191 .reg_stride = 4,
192 .val_format_endian = REGMAP_ENDIAN_NATIVE,
Zidan Wang05cf2372015-09-18 11:09:12 +0800193 .reg_defaults = fsl_ssi_reg_defaults,
194 .num_reg_defaults = ARRAY_SIZE(fsl_ssi_reg_defaults),
195 .readable_reg = fsl_ssi_readable_reg,
196 .volatile_reg = fsl_ssi_volatile_reg,
Maciej S. Szmigierof51e3d52015-12-20 21:31:48 +0100197 .precious_reg = fsl_ssi_precious_reg,
Zidan Wang05cf2372015-09-18 11:09:12 +0800198 .writeable_reg = fsl_ssi_writeable_reg,
199 .cache_type = REGCACHE_RBTREE,
Markus Pargmann43248122014-05-27 10:24:25 +0200200};
Timur Tabid5a908b2009-03-26 11:42:38 -0500201
Sascha Hauerfcdbade2014-05-27 10:24:18 +0200202struct fsl_ssi_soc_data {
203 bool imx;
204 bool offline_config;
205 u32 sisr_write_mask;
206};
207
Timur Tabi17467f22008-01-11 18:15:26 +0100208/**
209 * fsl_ssi_private: per-SSI private data
210 *
Markus Pargmann43248122014-05-27 10:24:25 +0200211 * @reg: Pointer to the regmap registers
Timur Tabi17467f22008-01-11 18:15:26 +0100212 * @irq: IRQ of this SSI
Markus Pargmann737a6b42014-05-27 10:24:24 +0200213 * @cpu_dai_drv: CPU DAI driver for this device
214 *
215 * @dai_fmt: DAI configuration this device is currently used with
216 * @i2s_mode: i2s and network mode configuration of the device. Is used to
217 * switch between normal and i2s/network mode
218 * mode depending on the number of channels
219 * @use_dma: DMA is used or FIQ with stream filter
220 * @use_dual_fifo: DMA with support for both FIFOs used
221 * @fifo_deph: Depth of the SSI FIFOs
222 * @rxtx_reg_val: Specific register settings for receive/transmit configuration
223 *
224 * @clk: SSI clock
225 * @baudclk: SSI baud clock for master mode
226 * @baudclk_streams: Active streams that are using baudclk
227 * @bitclk_freq: bitclock frequency set by .set_dai_sysclk
228 *
229 * @dma_params_tx: DMA transmit parameters
230 * @dma_params_rx: DMA receive parameters
231 * @ssi_phys: physical address of the SSI registers
232 *
233 * @fiq_params: FIQ stream filtering parameters
234 *
235 * @pdev: Pointer to pdev used for deprecated fsl-ssi sound card
236 *
237 * @dbg_stats: Debugging statistics
238 *
Xiubo Lidcfcf2c2015-08-12 14:38:18 +0800239 * @soc: SoC specific data
Timur Tabi17467f22008-01-11 18:15:26 +0100240 */
241struct fsl_ssi_private {
Markus Pargmann43248122014-05-27 10:24:25 +0200242 struct regmap *regs;
Fabio Estevam9e446ad2015-01-14 10:48:59 -0200243 int irq;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000244 struct snd_soc_dai_driver cpu_dai_drv;
Timur Tabi17467f22008-01-11 18:15:26 +0100245
Markus Pargmann737a6b42014-05-27 10:24:24 +0200246 unsigned int dai_fmt;
247 u8 i2s_mode;
Markus Pargmannde623ec2013-07-27 13:31:53 +0200248 bool use_dma;
Nicolin Chen0da9e552013-11-13 22:55:26 +0800249 bool use_dual_fifo;
Shengjiu Wangf4a43ca2014-09-16 10:13:16 +0800250 bool has_ipg_clk_name;
Markus Pargmann737a6b42014-05-27 10:24:24 +0200251 unsigned int fifo_depth;
252 struct fsl_ssi_rxtx_reg_val rxtx_reg_val;
253
Shawn Guo95cd98f2012-03-29 10:53:41 +0800254 struct clk *clk;
Markus Pargmann737a6b42014-05-27 10:24:24 +0200255 struct clk *baudclk;
Markus Pargmannd429d8e2014-05-27 10:24:23 +0200256 unsigned int baudclk_streams;
Sascha Hauer8dd51e22014-05-27 10:24:20 +0200257 unsigned int bitclk_freq;
Markus Pargmann737a6b42014-05-27 10:24:24 +0200258
Maciej S. Szmigiero3f1c2412015-12-20 21:30:25 +0100259 /* regcache for volatile regs */
Zidan Wang05cf2372015-09-18 11:09:12 +0800260 u32 regcache_sfcsr;
Maciej S. Szmigiero3f1c2412015-12-20 21:30:25 +0100261 u32 regcache_sacnt;
Zidan Wang05cf2372015-09-18 11:09:12 +0800262
Markus Pargmann737a6b42014-05-27 10:24:24 +0200263 /* DMA params */
Lars-Peter Clausena8909c92013-04-03 11:06:04 +0200264 struct snd_dmaengine_dai_dma_data dma_params_tx;
265 struct snd_dmaengine_dai_dma_data dma_params_rx;
Markus Pargmann737a6b42014-05-27 10:24:24 +0200266 dma_addr_t ssi_phys;
267
268 /* params for non-dma FIQ stream filtered mode */
Markus Pargmannde623ec2013-07-27 13:31:53 +0200269 struct imx_pcm_fiq_params fiq_params;
Markus Pargmann737a6b42014-05-27 10:24:24 +0200270
271 /* Used when using fsl-ssi as sound-card. This is only used by ppc and
272 * should be replaced with simple-sound-card. */
273 struct platform_device *pdev;
Shawn Guo09ce1112012-03-16 16:56:43 +0800274
Markus Pargmannf138e622014-04-28 12:54:43 +0200275 struct fsl_ssi_dbg dbg_stats;
Sascha Hauerfcdbade2014-05-27 10:24:18 +0200276
277 const struct fsl_ssi_soc_data *soc;
Timur Tabi17467f22008-01-11 18:15:26 +0100278};
279
Markus Pargmann171d6832014-04-28 12:54:48 +0200280/*
281 * imx51 and later SoCs have a slightly different IP that allows the
282 * SSI configuration while the SSI unit is running.
283 *
284 * More important, it is necessary on those SoCs to configure the
285 * sperate TX/RX DMA bits just before starting the stream
286 * (fsl_ssi_trigger). The SDMA unit has to be configured before fsl_ssi
287 * sends any DMA requests to the SDMA unit, otherwise it is not defined
288 * how the SDMA unit handles the DMA request.
289 *
290 * SDMA units are present on devices starting at imx35 but the imx35
291 * reference manual states that the DMA bits should not be changed
292 * while the SSI unit is running (SSIEN). So we support the necessary
293 * online configuration of fsl-ssi starting at imx51.
294 */
Markus Pargmann171d6832014-04-28 12:54:48 +0200295
Sascha Hauerfcdbade2014-05-27 10:24:18 +0200296static struct fsl_ssi_soc_data fsl_ssi_mpc8610 = {
297 .imx = false,
298 .offline_config = true,
299 .sisr_write_mask = CCSR_SSI_SISR_RFRC | CCSR_SSI_SISR_TFRC |
300 CCSR_SSI_SISR_ROE0 | CCSR_SSI_SISR_ROE1 |
301 CCSR_SSI_SISR_TUE0 | CCSR_SSI_SISR_TUE1,
302};
303
304static struct fsl_ssi_soc_data fsl_ssi_imx21 = {
305 .imx = true,
306 .offline_config = true,
307 .sisr_write_mask = 0,
308};
309
310static struct fsl_ssi_soc_data fsl_ssi_imx35 = {
311 .imx = true,
312 .offline_config = true,
313 .sisr_write_mask = CCSR_SSI_SISR_RFRC | CCSR_SSI_SISR_TFRC |
314 CCSR_SSI_SISR_ROE0 | CCSR_SSI_SISR_ROE1 |
315 CCSR_SSI_SISR_TUE0 | CCSR_SSI_SISR_TUE1,
316};
317
318static struct fsl_ssi_soc_data fsl_ssi_imx51 = {
319 .imx = true,
320 .offline_config = false,
321 .sisr_write_mask = CCSR_SSI_SISR_ROE0 | CCSR_SSI_SISR_ROE1 |
322 CCSR_SSI_SISR_TUE0 | CCSR_SSI_SISR_TUE1,
323};
324
325static const struct of_device_id fsl_ssi_ids[] = {
326 { .compatible = "fsl,mpc8610-ssi", .data = &fsl_ssi_mpc8610 },
327 { .compatible = "fsl,imx51-ssi", .data = &fsl_ssi_imx51 },
328 { .compatible = "fsl,imx35-ssi", .data = &fsl_ssi_imx35 },
329 { .compatible = "fsl,imx21-ssi", .data = &fsl_ssi_imx21 },
330 {}
331};
332MODULE_DEVICE_TABLE(of, fsl_ssi_ids);
333
334static bool fsl_ssi_is_ac97(struct fsl_ssi_private *ssi_private)
335{
Adam Thomson5b64c172015-09-16 10:13:19 +0100336 return (ssi_private->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) ==
337 SND_SOC_DAIFMT_AC97;
Markus Pargmann171d6832014-04-28 12:54:48 +0200338}
339
Sascha Hauer8dd51e22014-05-27 10:24:20 +0200340static bool fsl_ssi_is_i2s_master(struct fsl_ssi_private *ssi_private)
341{
342 return (ssi_private->dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) ==
343 SND_SOC_DAIFMT_CBS_CFS;
344}
345
Fabio Falzoicf4f7fc2014-08-04 17:08:07 +0200346static bool fsl_ssi_is_i2s_cbm_cfs(struct fsl_ssi_private *ssi_private)
347{
348 return (ssi_private->dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) ==
349 SND_SOC_DAIFMT_CBM_CFS;
350}
Timur Tabi17467f22008-01-11 18:15:26 +0100351/**
352 * fsl_ssi_isr: SSI interrupt handler
353 *
354 * Although it's possible to use the interrupt handler to send and receive
355 * data to/from the SSI, we use the DMA instead. Programming is more
356 * complicated, but the performance is much better.
357 *
358 * This interrupt handler is used only to gather statistics.
359 *
360 * @irq: IRQ of the SSI device
361 * @dev_id: pointer to the ssi_private structure for this SSI device
362 */
363static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
364{
365 struct fsl_ssi_private *ssi_private = dev_id;
Markus Pargmann43248122014-05-27 10:24:25 +0200366 struct regmap *regs = ssi_private->regs;
Timur Tabi17467f22008-01-11 18:15:26 +0100367 __be32 sisr;
Markus Pargmann0888efd2013-12-20 14:11:31 +0100368 __be32 sisr2;
Timur Tabi17467f22008-01-11 18:15:26 +0100369
370 /* We got an interrupt, so read the status register to see what we
371 were interrupted for. We mask it with the Interrupt Enable register
372 so that we only check for events that we're interested in.
373 */
Markus Pargmann43248122014-05-27 10:24:25 +0200374 regmap_read(regs, CCSR_SSI_SISR, &sisr);
Timur Tabi17467f22008-01-11 18:15:26 +0100375
Sascha Hauerfcdbade2014-05-27 10:24:18 +0200376 sisr2 = sisr & ssi_private->soc->sisr_write_mask;
Timur Tabi17467f22008-01-11 18:15:26 +0100377 /* Clear the bits that we set */
378 if (sisr2)
Markus Pargmann43248122014-05-27 10:24:25 +0200379 regmap_write(regs, CCSR_SSI_SISR, sisr2);
Timur Tabi17467f22008-01-11 18:15:26 +0100380
Markus Pargmannf138e622014-04-28 12:54:43 +0200381 fsl_ssi_dbg_isr(&ssi_private->dbg_stats, sisr);
382
383 return IRQ_HANDLED;
Timur Tabi17467f22008-01-11 18:15:26 +0100384}
385
Markus Pargmann4e6ec0d2013-12-20 14:11:33 +0100386/*
387 * Enable/Disable all rx/tx config flags at once.
388 */
389static void fsl_ssi_rxtx_config(struct fsl_ssi_private *ssi_private,
390 bool enable)
391{
Markus Pargmann43248122014-05-27 10:24:25 +0200392 struct regmap *regs = ssi_private->regs;
Markus Pargmann4e6ec0d2013-12-20 14:11:33 +0100393 struct fsl_ssi_rxtx_reg_val *vals = &ssi_private->rxtx_reg_val;
394
395 if (enable) {
Markus Pargmann43248122014-05-27 10:24:25 +0200396 regmap_update_bits(regs, CCSR_SSI_SIER,
397 vals->rx.sier | vals->tx.sier,
398 vals->rx.sier | vals->tx.sier);
399 regmap_update_bits(regs, CCSR_SSI_SRCR,
400 vals->rx.srcr | vals->tx.srcr,
401 vals->rx.srcr | vals->tx.srcr);
402 regmap_update_bits(regs, CCSR_SSI_STCR,
403 vals->rx.stcr | vals->tx.stcr,
404 vals->rx.stcr | vals->tx.stcr);
Markus Pargmann4e6ec0d2013-12-20 14:11:33 +0100405 } else {
Markus Pargmann43248122014-05-27 10:24:25 +0200406 regmap_update_bits(regs, CCSR_SSI_SRCR,
407 vals->rx.srcr | vals->tx.srcr, 0);
408 regmap_update_bits(regs, CCSR_SSI_STCR,
409 vals->rx.stcr | vals->tx.stcr, 0);
410 regmap_update_bits(regs, CCSR_SSI_SIER,
411 vals->rx.sier | vals->tx.sier, 0);
Markus Pargmann4e6ec0d2013-12-20 14:11:33 +0100412 }
413}
414
415/*
Markus Pargmann65c961c2014-04-28 12:54:42 +0200416 * Calculate the bits that have to be disabled for the current stream that is
417 * getting disabled. This keeps the bits enabled that are necessary for the
418 * second stream to work if 'stream_active' is true.
419 *
420 * Detailed calculation:
421 * These are the values that need to be active after disabling. For non-active
422 * second stream, this is 0:
423 * vals_stream * !!stream_active
424 *
425 * The following computes the overall differences between the setup for the
426 * to-disable stream and the active stream, a simple XOR:
427 * vals_disable ^ (vals_stream * !!(stream_active))
428 *
429 * The full expression adds a mask on all values we care about
430 */
431#define fsl_ssi_disable_val(vals_disable, vals_stream, stream_active) \
432 ((vals_disable) & \
433 ((vals_disable) ^ ((vals_stream) * (u32)!!(stream_active))))
434
435/*
Markus Pargmann4e6ec0d2013-12-20 14:11:33 +0100436 * Enable/Disable a ssi configuration. You have to pass either
437 * ssi_private->rxtx_reg_val.rx or tx as vals parameter.
438 */
439static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable,
440 struct fsl_ssi_reg_val *vals)
441{
Markus Pargmann43248122014-05-27 10:24:25 +0200442 struct regmap *regs = ssi_private->regs;
Markus Pargmann4e6ec0d2013-12-20 14:11:33 +0100443 struct fsl_ssi_reg_val *avals;
Markus Pargmann43248122014-05-27 10:24:25 +0200444 int nr_active_streams;
445 u32 scr_val;
Markus Pargmann65c961c2014-04-28 12:54:42 +0200446 int keep_active;
447
Markus Pargmann43248122014-05-27 10:24:25 +0200448 regmap_read(regs, CCSR_SSI_SCR, &scr_val);
449
450 nr_active_streams = !!(scr_val & CCSR_SSI_SCR_TE) +
451 !!(scr_val & CCSR_SSI_SCR_RE);
452
Markus Pargmann65c961c2014-04-28 12:54:42 +0200453 if (nr_active_streams - 1 > 0)
454 keep_active = 1;
455 else
456 keep_active = 0;
Markus Pargmann4e6ec0d2013-12-20 14:11:33 +0100457
458 /* Find the other direction values rx or tx which we do not want to
459 * modify */
460 if (&ssi_private->rxtx_reg_val.rx == vals)
461 avals = &ssi_private->rxtx_reg_val.tx;
462 else
463 avals = &ssi_private->rxtx_reg_val.rx;
464
465 /* If vals should be disabled, start with disabling the unit */
466 if (!enable) {
Markus Pargmann65c961c2014-04-28 12:54:42 +0200467 u32 scr = fsl_ssi_disable_val(vals->scr, avals->scr,
468 keep_active);
Markus Pargmann43248122014-05-27 10:24:25 +0200469 regmap_update_bits(regs, CCSR_SSI_SCR, scr, 0);
Markus Pargmann4e6ec0d2013-12-20 14:11:33 +0100470 }
471
472 /*
473 * We are running on a SoC which does not support online SSI
474 * reconfiguration, so we have to enable all necessary flags at once
475 * even if we do not use them later (capture and playback configuration)
476 */
Sascha Hauerfcdbade2014-05-27 10:24:18 +0200477 if (ssi_private->soc->offline_config) {
Markus Pargmann4e6ec0d2013-12-20 14:11:33 +0100478 if ((enable && !nr_active_streams) ||
Markus Pargmann65c961c2014-04-28 12:54:42 +0200479 (!enable && !keep_active))
Markus Pargmann4e6ec0d2013-12-20 14:11:33 +0100480 fsl_ssi_rxtx_config(ssi_private, enable);
481
482 goto config_done;
483 }
484
485 /*
486 * Configure single direction units while the SSI unit is running
487 * (online configuration)
488 */
489 if (enable) {
Markus Pargmann43248122014-05-27 10:24:25 +0200490 regmap_update_bits(regs, CCSR_SSI_SIER, vals->sier, vals->sier);
491 regmap_update_bits(regs, CCSR_SSI_SRCR, vals->srcr, vals->srcr);
492 regmap_update_bits(regs, CCSR_SSI_STCR, vals->stcr, vals->stcr);
Markus Pargmann4e6ec0d2013-12-20 14:11:33 +0100493 } else {
494 u32 sier;
495 u32 srcr;
496 u32 stcr;
497
498 /*
499 * Disabling the necessary flags for one of rx/tx while the
500 * other stream is active is a little bit more difficult. We
501 * have to disable only those flags that differ between both
502 * streams (rx XOR tx) and that are set in the stream that is
503 * disabled now. Otherwise we could alter flags of the other
504 * stream
505 */
506
507 /* These assignments are simply vals without bits set in avals*/
Markus Pargmann65c961c2014-04-28 12:54:42 +0200508 sier = fsl_ssi_disable_val(vals->sier, avals->sier,
509 keep_active);
510 srcr = fsl_ssi_disable_val(vals->srcr, avals->srcr,
511 keep_active);
512 stcr = fsl_ssi_disable_val(vals->stcr, avals->stcr,
513 keep_active);
Markus Pargmann4e6ec0d2013-12-20 14:11:33 +0100514
Markus Pargmann43248122014-05-27 10:24:25 +0200515 regmap_update_bits(regs, CCSR_SSI_SRCR, srcr, 0);
516 regmap_update_bits(regs, CCSR_SSI_STCR, stcr, 0);
517 regmap_update_bits(regs, CCSR_SSI_SIER, sier, 0);
Markus Pargmann4e6ec0d2013-12-20 14:11:33 +0100518 }
519
520config_done:
521 /* Enabling of subunits is done after configuration */
522 if (enable)
Markus Pargmann43248122014-05-27 10:24:25 +0200523 regmap_update_bits(regs, CCSR_SSI_SCR, vals->scr, vals->scr);
Markus Pargmann4e6ec0d2013-12-20 14:11:33 +0100524}
525
526
527static void fsl_ssi_rx_config(struct fsl_ssi_private *ssi_private, bool enable)
528{
529 fsl_ssi_config(ssi_private, enable, &ssi_private->rxtx_reg_val.rx);
530}
531
532static void fsl_ssi_tx_config(struct fsl_ssi_private *ssi_private, bool enable)
533{
534 fsl_ssi_config(ssi_private, enable, &ssi_private->rxtx_reg_val.tx);
535}
536
Markus Pargmann6de83872013-12-20 14:11:34 +0100537/*
538 * Setup rx/tx register values used to enable/disable the streams. These will
539 * be used later in fsl_ssi_config to setup the streams without the need to
540 * check for all different SSI modes.
541 */
542static void fsl_ssi_setup_reg_vals(struct fsl_ssi_private *ssi_private)
543{
544 struct fsl_ssi_rxtx_reg_val *reg = &ssi_private->rxtx_reg_val;
545
546 reg->rx.sier = CCSR_SSI_SIER_RFF0_EN;
547 reg->rx.srcr = CCSR_SSI_SRCR_RFEN0;
548 reg->rx.scr = 0;
549 reg->tx.sier = CCSR_SSI_SIER_TFE0_EN;
550 reg->tx.stcr = CCSR_SSI_STCR_TFEN0;
551 reg->tx.scr = 0;
552
Markus Pargmann171d6832014-04-28 12:54:48 +0200553 if (!fsl_ssi_is_ac97(ssi_private)) {
Markus Pargmann6de83872013-12-20 14:11:34 +0100554 reg->rx.scr = CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE;
555 reg->rx.sier |= CCSR_SSI_SIER_RFF0_EN;
556 reg->tx.scr = CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE;
557 reg->tx.sier |= CCSR_SSI_SIER_TFE0_EN;
558 }
559
560 if (ssi_private->use_dma) {
561 reg->rx.sier |= CCSR_SSI_SIER_RDMAE;
562 reg->tx.sier |= CCSR_SSI_SIER_TDMAE;
563 } else {
564 reg->rx.sier |= CCSR_SSI_SIER_RIE;
565 reg->tx.sier |= CCSR_SSI_SIER_TIE;
566 }
567
568 reg->rx.sier |= FSLSSI_SIER_DBG_RX_FLAGS;
569 reg->tx.sier |= FSLSSI_SIER_DBG_TX_FLAGS;
570}
571
Markus Pargmannd8764642013-11-20 10:04:15 +0100572static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private)
573{
Markus Pargmann43248122014-05-27 10:24:25 +0200574 struct regmap *regs = ssi_private->regs;
Markus Pargmannd8764642013-11-20 10:04:15 +0100575
576 /*
577 * Setup the clock control register
578 */
Markus Pargmann43248122014-05-27 10:24:25 +0200579 regmap_write(regs, CCSR_SSI_STCCR,
580 CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13));
581 regmap_write(regs, CCSR_SSI_SRCCR,
582 CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13));
Markus Pargmannd8764642013-11-20 10:04:15 +0100583
584 /*
585 * Enable AC97 mode and startup the SSI
586 */
Markus Pargmann43248122014-05-27 10:24:25 +0200587 regmap_write(regs, CCSR_SSI_SACNT,
588 CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV);
589 regmap_write(regs, CCSR_SSI_SACCDIS, 0xff);
590 regmap_write(regs, CCSR_SSI_SACCEN, 0x300);
Markus Pargmannd8764642013-11-20 10:04:15 +0100591
592 /*
593 * Enable SSI, Transmit and Receive. AC97 has to communicate with the
594 * codec before a stream is started.
595 */
Markus Pargmann43248122014-05-27 10:24:25 +0200596 regmap_update_bits(regs, CCSR_SSI_SCR,
597 CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE,
598 CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE);
Markus Pargmannd8764642013-11-20 10:04:15 +0100599
Markus Pargmann43248122014-05-27 10:24:25 +0200600 regmap_write(regs, CCSR_SSI_SOR, CCSR_SSI_SOR_WAIT(3));
Markus Pargmannd8764642013-11-20 10:04:15 +0100601}
602
Timur Tabi17467f22008-01-11 18:15:26 +0100603/**
604 * fsl_ssi_startup: create a new substream
605 *
606 * This is the first function called when a stream is opened.
607 *
608 * If this is the first stream open, then grab the IRQ and program most of
609 * the SSI registers.
610 */
Mark Browndee89c42008-11-18 22:11:38 +0000611static int fsl_ssi_startup(struct snd_pcm_substream *substream,
612 struct snd_soc_dai *dai)
Timur Tabi17467f22008-01-11 18:15:26 +0100613{
614 struct snd_soc_pcm_runtime *rtd = substream->private_data;
Timur Tabi5e538ec2011-09-13 12:59:37 -0500615 struct fsl_ssi_private *ssi_private =
616 snd_soc_dai_get_drvdata(rtd->cpu_dai);
Shengjiu Wangf4a43ca2014-09-16 10:13:16 +0800617 int ret;
618
619 ret = clk_prepare_enable(ssi_private->clk);
620 if (ret)
621 return ret;
Timur Tabi17467f22008-01-11 18:15:26 +0100622
Nicolin Chen0da9e552013-11-13 22:55:26 +0800623 /* When using dual fifo mode, it is safer to ensure an even period
624 * size. If appearing to an odd number while DMA always starts its
625 * task from fifo0, fifo1 would be neglected at the end of each
626 * period. But SSI would still access fifo1 with an invalid data.
627 */
628 if (ssi_private->use_dual_fifo)
629 snd_pcm_hw_constraint_step(substream->runtime, 0,
630 SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2);
631
Timur Tabi17467f22008-01-11 18:15:26 +0100632 return 0;
633}
634
635/**
Shengjiu Wangf4a43ca2014-09-16 10:13:16 +0800636 * fsl_ssi_shutdown: shutdown the SSI
637 *
638 */
639static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
640 struct snd_soc_dai *dai)
641{
642 struct snd_soc_pcm_runtime *rtd = substream->private_data;
643 struct fsl_ssi_private *ssi_private =
644 snd_soc_dai_get_drvdata(rtd->cpu_dai);
645
646 clk_disable_unprepare(ssi_private->clk);
647
648}
649
650/**
Sascha Hauer8dd51e22014-05-27 10:24:20 +0200651 * fsl_ssi_set_bclk - configure Digital Audio Interface bit clock
Sascha Haueree9daad2014-04-28 12:54:52 +0200652 *
653 * Note: This function can be only called when using SSI as DAI master
654 *
655 * Quick instruction for parameters:
656 * freq: Output BCLK frequency = samplerate * 32 (fixed) * channels
657 * dir: SND_SOC_CLOCK_OUT -> TxBCLK, SND_SOC_CLOCK_IN -> RxBCLK.
658 */
Sascha Hauer8dd51e22014-05-27 10:24:20 +0200659static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream,
660 struct snd_soc_dai *cpu_dai,
661 struct snd_pcm_hw_params *hw_params)
Sascha Haueree9daad2014-04-28 12:54:52 +0200662{
663 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
Markus Pargmann43248122014-05-27 10:24:25 +0200664 struct regmap *regs = ssi_private->regs;
Sascha Haueree9daad2014-04-28 12:54:52 +0200665 int synchronous = ssi_private->cpu_dai_drv.symmetric_rates, ret;
666 u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
Sascha Hauerd8ced472014-05-27 10:24:21 +0200667 unsigned long clkrate, baudrate, tmprate;
Sascha Haueree9daad2014-04-28 12:54:52 +0200668 u64 sub, savesub = 100000;
Sascha Hauer8dd51e22014-05-27 10:24:20 +0200669 unsigned int freq;
Markus Pargmannd429d8e2014-05-27 10:24:23 +0200670 bool baudclk_is_used;
Sascha Hauer8dd51e22014-05-27 10:24:20 +0200671
672 /* Prefer the explicitly set bitclock frequency */
673 if (ssi_private->bitclk_freq)
674 freq = ssi_private->bitclk_freq;
675 else
676 freq = params_channels(hw_params) * 32 * params_rate(hw_params);
Sascha Haueree9daad2014-04-28 12:54:52 +0200677
678 /* Don't apply it to any non-baudclk circumstance */
679 if (IS_ERR(ssi_private->baudclk))
680 return -EINVAL;
681
Markus Pargmannd429d8e2014-05-27 10:24:23 +0200682 baudclk_is_used = ssi_private->baudclk_streams & ~(BIT(substream->stream));
683
Sascha Haueree9daad2014-04-28 12:54:52 +0200684 /* It should be already enough to divide clock by setting pm alone */
685 psr = 0;
686 div2 = 0;
687
688 factor = (div2 + 1) * (7 * psr + 1) * 2;
689
690 for (i = 0; i < 255; i++) {
Nicolin Chen6c8ca302015-03-04 21:05:04 -0800691 tmprate = freq * factor * (i + 1);
Markus Pargmannd429d8e2014-05-27 10:24:23 +0200692
693 if (baudclk_is_used)
694 clkrate = clk_get_rate(ssi_private->baudclk);
695 else
696 clkrate = clk_round_rate(ssi_private->baudclk, tmprate);
Sascha Haueree9daad2014-04-28 12:54:52 +0200697
Nicolin Chen541b03ad62015-02-10 21:31:43 -0800698 /*
699 * Hardware limitation: The bclk rate must be
700 * never greater than 1/5 IPG clock rate
701 */
702 if (clkrate * 5 > clk_get_rate(ssi_private->clk))
703 continue;
704
Timur Tabiacf2c602014-06-13 07:42:40 -0500705 clkrate /= factor;
706 afreq = clkrate / (i + 1);
Sascha Haueree9daad2014-04-28 12:54:52 +0200707
708 if (freq == afreq)
709 sub = 0;
710 else if (freq / afreq == 1)
711 sub = freq - afreq;
712 else if (afreq / freq == 1)
713 sub = afreq - freq;
714 else
715 continue;
716
717 /* Calculate the fraction */
718 sub *= 100000;
719 do_div(sub, freq);
720
Juergen Borleisebac95a2015-07-03 12:39:36 +0200721 if (sub < savesub && !(i == 0 && psr == 0 && div2 == 0)) {
Sascha Haueree9daad2014-04-28 12:54:52 +0200722 baudrate = tmprate;
723 savesub = sub;
724 pm = i;
725 }
726
727 /* We are lucky */
728 if (savesub == 0)
729 break;
730 }
731
732 /* No proper pm found if it is still remaining the initial value */
733 if (pm == 999) {
734 dev_err(cpu_dai->dev, "failed to handle the required sysclk\n");
735 return -EINVAL;
736 }
737
738 stccr = CCSR_SSI_SxCCR_PM(pm + 1) | (div2 ? CCSR_SSI_SxCCR_DIV2 : 0) |
739 (psr ? CCSR_SSI_SxCCR_PSR : 0);
740 mask = CCSR_SSI_SxCCR_PM_MASK | CCSR_SSI_SxCCR_DIV2 |
741 CCSR_SSI_SxCCR_PSR;
742
Sascha Hauer8dd51e22014-05-27 10:24:20 +0200743 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || synchronous)
Markus Pargmann43248122014-05-27 10:24:25 +0200744 regmap_update_bits(regs, CCSR_SSI_STCCR, mask, stccr);
Sascha Haueree9daad2014-04-28 12:54:52 +0200745 else
Markus Pargmann43248122014-05-27 10:24:25 +0200746 regmap_update_bits(regs, CCSR_SSI_SRCCR, mask, stccr);
Sascha Haueree9daad2014-04-28 12:54:52 +0200747
Markus Pargmannd429d8e2014-05-27 10:24:23 +0200748 if (!baudclk_is_used) {
Sascha Haueree9daad2014-04-28 12:54:52 +0200749 ret = clk_set_rate(ssi_private->baudclk, baudrate);
750 if (ret) {
Sascha Haueree9daad2014-04-28 12:54:52 +0200751 dev_err(cpu_dai->dev, "failed to set baudclk rate\n");
752 return -EINVAL;
753 }
Sascha Haueree9daad2014-04-28 12:54:52 +0200754 }
Sascha Haueree9daad2014-04-28 12:54:52 +0200755
756 return 0;
757}
758
Sascha Hauer8dd51e22014-05-27 10:24:20 +0200759static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
760 int clk_id, unsigned int freq, int dir)
761{
762 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
763
764 ssi_private->bitclk_freq = freq;
765
766 return 0;
767}
768
Sascha Haueree9daad2014-04-28 12:54:52 +0200769/**
Timur Tabi85ef2372009-02-05 17:56:02 -0600770 * fsl_ssi_hw_params - program the sample size
Timur Tabi17467f22008-01-11 18:15:26 +0100771 *
772 * Most of the SSI registers have been programmed in the startup function,
773 * but the word length must be programmed here. Unfortunately, programming
774 * the SxCCR.WL bits requires the SSI to be temporarily disabled. This can
775 * cause a problem with supporting simultaneous playback and capture. If
776 * the SSI is already playing a stream, then that stream may be temporarily
777 * stopped when you start capture.
778 *
779 * Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the
780 * clock master.
781 */
Timur Tabi85ef2372009-02-05 17:56:02 -0600782static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
783 struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai)
Timur Tabi17467f22008-01-11 18:15:26 +0100784{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000785 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
Markus Pargmann43248122014-05-27 10:24:25 +0200786 struct regmap *regs = ssi_private->regs;
Nicolin Chen2924a992013-12-02 23:29:03 +0800787 unsigned int channels = params_channels(hw_params);
Zidan Wang4ca73042015-11-24 15:32:09 +0800788 unsigned int sample_size = params_width(hw_params);
Timur Tabi5e538ec2011-09-13 12:59:37 -0500789 u32 wl = CCSR_SSI_SxCCR_WL(sample_size);
Sascha Hauer8dd51e22014-05-27 10:24:20 +0200790 int ret;
Markus Pargmann43248122014-05-27 10:24:25 +0200791 u32 scr_val;
792 int enabled;
793
794 regmap_read(regs, CCSR_SSI_SCR, &scr_val);
795 enabled = scr_val & CCSR_SSI_SCR_SSIEN;
Timur Tabi17467f22008-01-11 18:15:26 +0100796
Timur Tabi5e538ec2011-09-13 12:59:37 -0500797 /*
798 * If we're in synchronous mode, and the SSI is already enabled,
799 * then STCCR is already set properly.
800 */
801 if (enabled && ssi_private->cpu_dai_drv.symmetric_rates)
802 return 0;
Timur Tabi17467f22008-01-11 18:15:26 +0100803
Sascha Hauer8dd51e22014-05-27 10:24:20 +0200804 if (fsl_ssi_is_i2s_master(ssi_private)) {
805 ret = fsl_ssi_set_bclk(substream, cpu_dai, hw_params);
806 if (ret)
807 return ret;
Markus Pargmannd429d8e2014-05-27 10:24:23 +0200808
809 /* Do not enable the clock if it is already enabled */
810 if (!(ssi_private->baudclk_streams & BIT(substream->stream))) {
811 ret = clk_prepare_enable(ssi_private->baudclk);
812 if (ret)
813 return ret;
814
815 ssi_private->baudclk_streams |= BIT(substream->stream);
816 }
Sascha Hauer8dd51e22014-05-27 10:24:20 +0200817 }
818
Fabio Falzoicf4f7fc2014-08-04 17:08:07 +0200819 if (!fsl_ssi_is_ac97(ssi_private)) {
820 u8 i2smode;
821 /*
822 * Switch to normal net mode in order to have a frame sync
823 * signal every 32 bits instead of 16 bits
824 */
825 if (fsl_ssi_is_i2s_cbm_cfs(ssi_private) && sample_size == 16)
826 i2smode = CCSR_SSI_SCR_I2S_MODE_NORMAL |
827 CCSR_SSI_SCR_NET;
828 else
829 i2smode = ssi_private->i2s_mode;
830
831 regmap_update_bits(regs, CCSR_SSI_SCR,
832 CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK,
833 channels == 1 ? 0 : i2smode);
834 }
835
Timur Tabi5e538ec2011-09-13 12:59:37 -0500836 /*
837 * FIXME: The documentation says that SxCCR[WL] should not be
838 * modified while the SSI is enabled. The only time this can
839 * happen is if we're trying to do simultaneous playback and
840 * capture in asynchronous mode. Unfortunately, I have been enable
841 * to get that to work at all on the P1022DS. Therefore, we don't
842 * bother to disable/enable the SSI when setting SxCCR[WL], because
843 * the SSI will stop anyway. Maybe one day, this will get fixed.
844 */
Timur Tabi17467f22008-01-11 18:15:26 +0100845
Timur Tabi5e538ec2011-09-13 12:59:37 -0500846 /* In synchronous mode, the SSI uses STCCR for capture */
847 if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ||
848 ssi_private->cpu_dai_drv.symmetric_rates)
Markus Pargmann43248122014-05-27 10:24:25 +0200849 regmap_update_bits(regs, CCSR_SSI_STCCR, CCSR_SSI_SxCCR_WL_MASK,
850 wl);
Timur Tabi5e538ec2011-09-13 12:59:37 -0500851 else
Markus Pargmann43248122014-05-27 10:24:25 +0200852 regmap_update_bits(regs, CCSR_SSI_SRCCR, CCSR_SSI_SxCCR_WL_MASK,
853 wl);
Timur Tabi17467f22008-01-11 18:15:26 +0100854
855 return 0;
856}
857
Markus Pargmannd429d8e2014-05-27 10:24:23 +0200858static int fsl_ssi_hw_free(struct snd_pcm_substream *substream,
859 struct snd_soc_dai *cpu_dai)
860{
861 struct snd_soc_pcm_runtime *rtd = substream->private_data;
862 struct fsl_ssi_private *ssi_private =
863 snd_soc_dai_get_drvdata(rtd->cpu_dai);
864
865 if (fsl_ssi_is_i2s_master(ssi_private) &&
866 ssi_private->baudclk_streams & BIT(substream->stream)) {
867 clk_disable_unprepare(ssi_private->baudclk);
868 ssi_private->baudclk_streams &= ~BIT(substream->stream);
869 }
870
871 return 0;
872}
873
Michael Trimarchi85151462014-09-18 20:38:09 +0200874static int _fsl_ssi_set_dai_fmt(struct device *dev,
875 struct fsl_ssi_private *ssi_private,
876 unsigned int fmt)
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800877{
Markus Pargmann43248122014-05-27 10:24:25 +0200878 struct regmap *regs = ssi_private->regs;
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800879 u32 strcr = 0, stcr, srcr, scr, mask;
Markus Pargmann2b0db992014-03-15 13:44:09 +0100880 u8 wm;
881
Markus Pargmann171d6832014-04-28 12:54:48 +0200882 ssi_private->dai_fmt = fmt;
883
Markus Pargmannd429d8e2014-05-27 10:24:23 +0200884 if (fsl_ssi_is_i2s_master(ssi_private) && IS_ERR(ssi_private->baudclk)) {
Michael Trimarchi85151462014-09-18 20:38:09 +0200885 dev_err(dev, "baudclk is missing which is necessary for master mode\n");
Markus Pargmannd429d8e2014-05-27 10:24:23 +0200886 return -EINVAL;
887 }
888
Markus Pargmann2b0db992014-03-15 13:44:09 +0100889 fsl_ssi_setup_reg_vals(ssi_private);
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800890
Markus Pargmann43248122014-05-27 10:24:25 +0200891 regmap_read(regs, CCSR_SSI_SCR, &scr);
892 scr &= ~(CCSR_SSI_SCR_SYN | CCSR_SSI_SCR_I2S_MODE_MASK);
Markus Pargmann50489472014-04-28 12:54:51 +0200893 scr |= CCSR_SSI_SCR_SYNC_TX_FS;
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800894
895 mask = CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFDIR | CCSR_SSI_STCR_TXDIR |
896 CCSR_SSI_STCR_TSCKP | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TFSL |
897 CCSR_SSI_STCR_TEFS;
Markus Pargmann43248122014-05-27 10:24:25 +0200898 regmap_read(regs, CCSR_SSI_STCR, &stcr);
899 regmap_read(regs, CCSR_SSI_SRCR, &srcr);
900 stcr &= ~mask;
901 srcr &= ~mask;
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800902
Markus Pargmann07a28db2014-03-15 13:44:10 +0100903 ssi_private->i2s_mode = CCSR_SSI_SCR_NET;
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800904 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
905 case SND_SOC_DAIFMT_I2S:
906 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
Fabio Falzoicf4f7fc2014-08-04 17:08:07 +0200907 case SND_SOC_DAIFMT_CBM_CFS:
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800908 case SND_SOC_DAIFMT_CBS_CFS:
Markus Pargmann07a28db2014-03-15 13:44:10 +0100909 ssi_private->i2s_mode |= CCSR_SSI_SCR_I2S_MODE_MASTER;
Markus Pargmann43248122014-05-27 10:24:25 +0200910 regmap_update_bits(regs, CCSR_SSI_STCCR,
911 CCSR_SSI_SxCCR_DC_MASK,
912 CCSR_SSI_SxCCR_DC(2));
913 regmap_update_bits(regs, CCSR_SSI_SRCCR,
914 CCSR_SSI_SxCCR_DC_MASK,
915 CCSR_SSI_SxCCR_DC(2));
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800916 break;
917 case SND_SOC_DAIFMT_CBM_CFM:
Markus Pargmann07a28db2014-03-15 13:44:10 +0100918 ssi_private->i2s_mode |= CCSR_SSI_SCR_I2S_MODE_SLAVE;
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800919 break;
920 default:
921 return -EINVAL;
922 }
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800923
924 /* Data on rising edge of bclk, frame low, 1clk before data */
925 strcr |= CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TSCKP |
926 CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TEFS;
927 break;
928 case SND_SOC_DAIFMT_LEFT_J:
929 /* Data on rising edge of bclk, frame high */
930 strcr |= CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TSCKP;
931 break;
932 case SND_SOC_DAIFMT_DSP_A:
933 /* Data on rising edge of bclk, frame high, 1clk before data */
934 strcr |= CCSR_SSI_STCR_TFSL | CCSR_SSI_STCR_TSCKP |
935 CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TEFS;
936 break;
937 case SND_SOC_DAIFMT_DSP_B:
938 /* Data on rising edge of bclk, frame high */
939 strcr |= CCSR_SSI_STCR_TFSL | CCSR_SSI_STCR_TSCKP |
940 CCSR_SSI_STCR_TXBIT0;
941 break;
Markus Pargmann2b0db992014-03-15 13:44:09 +0100942 case SND_SOC_DAIFMT_AC97:
Markus Pargmann07a28db2014-03-15 13:44:10 +0100943 ssi_private->i2s_mode |= CCSR_SSI_SCR_I2S_MODE_NORMAL;
Markus Pargmann2b0db992014-03-15 13:44:09 +0100944 break;
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800945 default:
946 return -EINVAL;
947 }
Markus Pargmann2b0db992014-03-15 13:44:09 +0100948 scr |= ssi_private->i2s_mode;
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800949
950 /* DAI clock inversion */
951 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
952 case SND_SOC_DAIFMT_NB_NF:
953 /* Nothing to do for both normal cases */
954 break;
955 case SND_SOC_DAIFMT_IB_NF:
956 /* Invert bit clock */
957 strcr ^= CCSR_SSI_STCR_TSCKP;
958 break;
959 case SND_SOC_DAIFMT_NB_IF:
960 /* Invert frame clock */
961 strcr ^= CCSR_SSI_STCR_TFSI;
962 break;
963 case SND_SOC_DAIFMT_IB_IF:
964 /* Invert both clocks */
965 strcr ^= CCSR_SSI_STCR_TSCKP;
966 strcr ^= CCSR_SSI_STCR_TFSI;
967 break;
968 default:
969 return -EINVAL;
970 }
971
972 /* DAI clock master masks */
973 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
974 case SND_SOC_DAIFMT_CBS_CFS:
975 strcr |= CCSR_SSI_STCR_TFDIR | CCSR_SSI_STCR_TXDIR;
976 scr |= CCSR_SSI_SCR_SYS_CLK_EN;
977 break;
978 case SND_SOC_DAIFMT_CBM_CFM:
979 scr &= ~CCSR_SSI_SCR_SYS_CLK_EN;
980 break;
Fabio Falzoicf4f7fc2014-08-04 17:08:07 +0200981 case SND_SOC_DAIFMT_CBM_CFS:
982 strcr &= ~CCSR_SSI_STCR_TXDIR;
983 strcr |= CCSR_SSI_STCR_TFDIR;
984 scr &= ~CCSR_SSI_SCR_SYS_CLK_EN;
985 break;
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800986 default:
Maciej S. Szmigierodce03322015-08-05 17:29:02 +0200987 if (!fsl_ssi_is_ac97(ssi_private))
988 return -EINVAL;
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800989 }
990
991 stcr |= strcr;
992 srcr |= strcr;
993
Maciej S. Szmigierodce03322015-08-05 17:29:02 +0200994 if (ssi_private->cpu_dai_drv.symmetric_rates
995 || fsl_ssi_is_ac97(ssi_private)) {
996 /* Need to clear RXDIR when using SYNC or AC97 mode */
Nicolin Chenaafa85e2013-12-12 18:44:45 +0800997 srcr &= ~CCSR_SSI_SRCR_RXDIR;
998 scr |= CCSR_SSI_SCR_SYN;
999 }
1000
Markus Pargmann43248122014-05-27 10:24:25 +02001001 regmap_write(regs, CCSR_SSI_STCR, stcr);
1002 regmap_write(regs, CCSR_SSI_SRCR, srcr);
1003 regmap_write(regs, CCSR_SSI_SCR, scr);
Nicolin Chenaafa85e2013-12-12 18:44:45 +08001004
Markus Pargmann2b0db992014-03-15 13:44:09 +01001005 /*
1006 * Set the watermark for transmit FIFI 0 and receive FIFO 0. We don't
1007 * use FIFO 1. We program the transmit water to signal a DMA transfer
1008 * if there are only two (or fewer) elements left in the FIFO. Two
1009 * elements equals one frame (left channel, right channel). This value,
1010 * however, depends on the depth of the transmit buffer.
1011 *
1012 * We set the watermark on the same level as the DMA burstsize. For
1013 * fiq it is probably better to use the biggest possible watermark
1014 * size.
1015 */
1016 if (ssi_private->use_dma)
1017 wm = ssi_private->fifo_depth - 2;
1018 else
1019 wm = ssi_private->fifo_depth;
1020
Markus Pargmann43248122014-05-27 10:24:25 +02001021 regmap_write(regs, CCSR_SSI_SFCSR,
1022 CCSR_SSI_SFCSR_TFWM0(wm) | CCSR_SSI_SFCSR_RFWM0(wm) |
1023 CCSR_SSI_SFCSR_TFWM1(wm) | CCSR_SSI_SFCSR_RFWM1(wm));
Markus Pargmann2b0db992014-03-15 13:44:09 +01001024
1025 if (ssi_private->use_dual_fifo) {
Markus Pargmann43248122014-05-27 10:24:25 +02001026 regmap_update_bits(regs, CCSR_SSI_SRCR, CCSR_SSI_SRCR_RFEN1,
Markus Pargmann2b0db992014-03-15 13:44:09 +01001027 CCSR_SSI_SRCR_RFEN1);
Markus Pargmann43248122014-05-27 10:24:25 +02001028 regmap_update_bits(regs, CCSR_SSI_STCR, CCSR_SSI_STCR_TFEN1,
Markus Pargmann2b0db992014-03-15 13:44:09 +01001029 CCSR_SSI_STCR_TFEN1);
Markus Pargmann43248122014-05-27 10:24:25 +02001030 regmap_update_bits(regs, CCSR_SSI_SCR, CCSR_SSI_SCR_TCH_EN,
Markus Pargmann2b0db992014-03-15 13:44:09 +01001031 CCSR_SSI_SCR_TCH_EN);
1032 }
1033
Adam Thomson5b64c172015-09-16 10:13:19 +01001034 if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_AC97)
Markus Pargmann2b0db992014-03-15 13:44:09 +01001035 fsl_ssi_setup_ac97(ssi_private);
1036
Nicolin Chenaafa85e2013-12-12 18:44:45 +08001037 return 0;
Markus Pargmann85e59af2014-05-27 10:24:19 +02001038
1039}
1040
1041/**
1042 * fsl_ssi_set_dai_fmt - configure Digital Audio Interface Format.
1043 */
1044static int fsl_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
1045{
1046 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
1047
Michael Trimarchi85151462014-09-18 20:38:09 +02001048 return _fsl_ssi_set_dai_fmt(cpu_dai->dev, ssi_private, fmt);
Nicolin Chenaafa85e2013-12-12 18:44:45 +08001049}
1050
1051/**
Nicolin Chenaafa85e2013-12-12 18:44:45 +08001052 * fsl_ssi_set_dai_tdm_slot - set TDM slot number
1053 *
1054 * Note: This function can be only called when using SSI as DAI master
1055 */
1056static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
1057 u32 rx_mask, int slots, int slot_width)
1058{
1059 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
Markus Pargmann43248122014-05-27 10:24:25 +02001060 struct regmap *regs = ssi_private->regs;
Nicolin Chenaafa85e2013-12-12 18:44:45 +08001061 u32 val;
1062
1063 /* The slot number should be >= 2 if using Network mode or I2S mode */
Markus Pargmann43248122014-05-27 10:24:25 +02001064 regmap_read(regs, CCSR_SSI_SCR, &val);
1065 val &= CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_NET;
Nicolin Chenaafa85e2013-12-12 18:44:45 +08001066 if (val && slots < 2) {
1067 dev_err(cpu_dai->dev, "slot number should be >= 2 in I2S or NET\n");
1068 return -EINVAL;
1069 }
1070
Markus Pargmann43248122014-05-27 10:24:25 +02001071 regmap_update_bits(regs, CCSR_SSI_STCCR, CCSR_SSI_SxCCR_DC_MASK,
Nicolin Chenaafa85e2013-12-12 18:44:45 +08001072 CCSR_SSI_SxCCR_DC(slots));
Markus Pargmann43248122014-05-27 10:24:25 +02001073 regmap_update_bits(regs, CCSR_SSI_SRCCR, CCSR_SSI_SxCCR_DC_MASK,
Nicolin Chenaafa85e2013-12-12 18:44:45 +08001074 CCSR_SSI_SxCCR_DC(slots));
1075
1076 /* The register SxMSKs needs SSI to provide essential clock due to
1077 * hardware design. So we here temporarily enable SSI to set them.
1078 */
Markus Pargmann43248122014-05-27 10:24:25 +02001079 regmap_read(regs, CCSR_SSI_SCR, &val);
1080 val &= CCSR_SSI_SCR_SSIEN;
1081 regmap_update_bits(regs, CCSR_SSI_SCR, CCSR_SSI_SCR_SSIEN,
1082 CCSR_SSI_SCR_SSIEN);
Nicolin Chenaafa85e2013-12-12 18:44:45 +08001083
Lars-Peter Clausend0077aa2015-01-12 10:27:18 +01001084 regmap_write(regs, CCSR_SSI_STMSK, ~tx_mask);
1085 regmap_write(regs, CCSR_SSI_SRMSK, ~rx_mask);
Nicolin Chenaafa85e2013-12-12 18:44:45 +08001086
Markus Pargmann43248122014-05-27 10:24:25 +02001087 regmap_update_bits(regs, CCSR_SSI_SCR, CCSR_SSI_SCR_SSIEN, val);
Nicolin Chenaafa85e2013-12-12 18:44:45 +08001088
1089 return 0;
1090}
1091
1092/**
Timur Tabi17467f22008-01-11 18:15:26 +01001093 * fsl_ssi_trigger: start and stop the DMA transfer.
1094 *
1095 * This function is called by ALSA to start, stop, pause, and resume the DMA
1096 * transfer of data.
1097 *
1098 * The DMA channel is in external master start and pause mode, which
1099 * means the SSI completely controls the flow of data.
1100 */
Mark Browndee89c42008-11-18 22:11:38 +00001101static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
1102 struct snd_soc_dai *dai)
Timur Tabi17467f22008-01-11 18:15:26 +01001103{
1104 struct snd_soc_pcm_runtime *rtd = substream->private_data;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001105 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
Markus Pargmann43248122014-05-27 10:24:25 +02001106 struct regmap *regs = ssi_private->regs;
Michael Grzeschik9b443e32013-08-19 17:06:00 +02001107
Timur Tabi17467f22008-01-11 18:15:26 +01001108 switch (cmd) {
1109 case SNDRV_PCM_TRIGGER_START:
Fabio Estevamb20e53a2014-05-23 02:38:56 -03001110 case SNDRV_PCM_TRIGGER_RESUME:
Timur Tabi17467f22008-01-11 18:15:26 +01001111 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
Timur Tabia4d11fe2009-03-25 18:20:37 -05001112 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
Markus Pargmann6de83872013-12-20 14:11:34 +01001113 fsl_ssi_tx_config(ssi_private, true);
Timur Tabia4d11fe2009-03-25 18:20:37 -05001114 else
Markus Pargmann6de83872013-12-20 14:11:34 +01001115 fsl_ssi_rx_config(ssi_private, true);
Timur Tabi17467f22008-01-11 18:15:26 +01001116 break;
1117
1118 case SNDRV_PCM_TRIGGER_STOP:
Fabio Estevamb20e53a2014-05-23 02:38:56 -03001119 case SNDRV_PCM_TRIGGER_SUSPEND:
Timur Tabi17467f22008-01-11 18:15:26 +01001120 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1121 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
Markus Pargmann6de83872013-12-20 14:11:34 +01001122 fsl_ssi_tx_config(ssi_private, false);
Timur Tabi17467f22008-01-11 18:15:26 +01001123 else
Markus Pargmann6de83872013-12-20 14:11:34 +01001124 fsl_ssi_rx_config(ssi_private, false);
Timur Tabi17467f22008-01-11 18:15:26 +01001125 break;
1126
1127 default:
1128 return -EINVAL;
1129 }
1130
Markus Pargmann171d6832014-04-28 12:54:48 +02001131 if (fsl_ssi_is_ac97(ssi_private)) {
Markus Pargmanna5a7ee72013-12-20 14:11:35 +01001132 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
Markus Pargmann43248122014-05-27 10:24:25 +02001133 regmap_write(regs, CCSR_SSI_SOR, CCSR_SSI_SOR_TX_CLR);
Markus Pargmanna5a7ee72013-12-20 14:11:35 +01001134 else
Markus Pargmann43248122014-05-27 10:24:25 +02001135 regmap_write(regs, CCSR_SSI_SOR, CCSR_SSI_SOR_RX_CLR);
Markus Pargmanna5a7ee72013-12-20 14:11:35 +01001136 }
Michael Grzeschik9b443e32013-08-19 17:06:00 +02001137
Timur Tabi17467f22008-01-11 18:15:26 +01001138 return 0;
1139}
1140
Lars-Peter Clausenfc8ba7f2013-04-15 19:19:58 +02001141static int fsl_ssi_dai_probe(struct snd_soc_dai *dai)
1142{
1143 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai);
1144
Sascha Hauerfcdbade2014-05-27 10:24:18 +02001145 if (ssi_private->soc->imx && ssi_private->use_dma) {
Lars-Peter Clausenfc8ba7f2013-04-15 19:19:58 +02001146 dai->playback_dma_data = &ssi_private->dma_params_tx;
1147 dai->capture_dma_data = &ssi_private->dma_params_rx;
1148 }
1149
1150 return 0;
1151}
1152
Lars-Peter Clausen85e76522011-11-23 11:40:40 +01001153static const struct snd_soc_dai_ops fsl_ssi_dai_ops = {
Eric Miao6335d052009-03-03 09:41:00 +08001154 .startup = fsl_ssi_startup,
Shengjiu Wangf4a43ca2014-09-16 10:13:16 +08001155 .shutdown = fsl_ssi_shutdown,
Eric Miao6335d052009-03-03 09:41:00 +08001156 .hw_params = fsl_ssi_hw_params,
Markus Pargmannd429d8e2014-05-27 10:24:23 +02001157 .hw_free = fsl_ssi_hw_free,
Nicolin Chenaafa85e2013-12-12 18:44:45 +08001158 .set_fmt = fsl_ssi_set_dai_fmt,
1159 .set_sysclk = fsl_ssi_set_dai_sysclk,
1160 .set_tdm_slot = fsl_ssi_set_dai_tdm_slot,
Eric Miao6335d052009-03-03 09:41:00 +08001161 .trigger = fsl_ssi_trigger,
Eric Miao6335d052009-03-03 09:41:00 +08001162};
1163
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001164/* Template for the CPU dai driver structure */
1165static struct snd_soc_dai_driver fsl_ssi_dai_template = {
Lars-Peter Clausenfc8ba7f2013-04-15 19:19:58 +02001166 .probe = fsl_ssi_dai_probe,
Timur Tabi17467f22008-01-11 18:15:26 +01001167 .playback = {
Nicolin Chene3655002014-07-30 11:10:29 +08001168 .stream_name = "CPU-Playback",
Nicolin Chen2924a992013-12-02 23:29:03 +08001169 .channels_min = 1,
Timur Tabi17467f22008-01-11 18:15:26 +01001170 .channels_max = 2,
1171 .rates = FSLSSI_I2S_RATES,
1172 .formats = FSLSSI_I2S_FORMATS,
1173 },
1174 .capture = {
Nicolin Chene3655002014-07-30 11:10:29 +08001175 .stream_name = "CPU-Capture",
Nicolin Chen2924a992013-12-02 23:29:03 +08001176 .channels_min = 1,
Timur Tabi17467f22008-01-11 18:15:26 +01001177 .channels_max = 2,
1178 .rates = FSLSSI_I2S_RATES,
1179 .formats = FSLSSI_I2S_FORMATS,
1180 },
Eric Miao6335d052009-03-03 09:41:00 +08001181 .ops = &fsl_ssi_dai_ops,
Timur Tabi17467f22008-01-11 18:15:26 +01001182};
1183
Kuninori Morimoto3580aa12013-03-21 03:32:04 -07001184static const struct snd_soc_component_driver fsl_ssi_component = {
1185 .name = "fsl-ssi",
1186};
1187
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001188static struct snd_soc_dai_driver fsl_ssi_ac97_dai = {
Lars-Peter Clausenbc263212014-11-10 22:41:52 +01001189 .bus_control = true,
Maciej S. Szmigiero793e3e92015-08-05 17:22:53 +02001190 .probe = fsl_ssi_dai_probe,
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001191 .playback = {
1192 .stream_name = "AC97 Playback",
1193 .channels_min = 2,
1194 .channels_max = 2,
1195 .rates = SNDRV_PCM_RATE_8000_48000,
1196 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1197 },
1198 .capture = {
1199 .stream_name = "AC97 Capture",
1200 .channels_min = 2,
1201 .channels_max = 2,
1202 .rates = SNDRV_PCM_RATE_48000,
1203 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1204 },
Markus Pargmanna5a7ee72013-12-20 14:11:35 +01001205 .ops = &fsl_ssi_dai_ops,
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001206};
1207
1208
1209static struct fsl_ssi_private *fsl_ac97_data;
1210
Sachin Kamata851a2b2013-09-13 15:22:17 +05301211static void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001212 unsigned short val)
1213{
Markus Pargmann43248122014-05-27 10:24:25 +02001214 struct regmap *regs = fsl_ac97_data->regs;
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001215 unsigned int lreg;
1216 unsigned int lval;
Maciej S. Szmigiero8277df32015-08-05 17:21:35 +02001217 int ret;
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001218
1219 if (reg > 0x7f)
1220 return;
1221
Maciej S. Szmigiero8277df32015-08-05 17:21:35 +02001222 ret = clk_prepare_enable(fsl_ac97_data->clk);
1223 if (ret) {
1224 pr_err("ac97 write clk_prepare_enable failed: %d\n",
1225 ret);
1226 return;
1227 }
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001228
1229 lreg = reg << 12;
Markus Pargmann43248122014-05-27 10:24:25 +02001230 regmap_write(regs, CCSR_SSI_SACADD, lreg);
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001231
1232 lval = val << 4;
Markus Pargmann43248122014-05-27 10:24:25 +02001233 regmap_write(regs, CCSR_SSI_SACDAT, lval);
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001234
Markus Pargmann43248122014-05-27 10:24:25 +02001235 regmap_update_bits(regs, CCSR_SSI_SACNT, CCSR_SSI_SACNT_RDWR_MASK,
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001236 CCSR_SSI_SACNT_WR);
1237 udelay(100);
Maciej S. Szmigiero8277df32015-08-05 17:21:35 +02001238
1239 clk_disable_unprepare(fsl_ac97_data->clk);
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001240}
1241
Sachin Kamata851a2b2013-09-13 15:22:17 +05301242static unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97,
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001243 unsigned short reg)
1244{
Markus Pargmann43248122014-05-27 10:24:25 +02001245 struct regmap *regs = fsl_ac97_data->regs;
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001246
1247 unsigned short val = -1;
Markus Pargmann43248122014-05-27 10:24:25 +02001248 u32 reg_val;
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001249 unsigned int lreg;
Maciej S. Szmigiero8277df32015-08-05 17:21:35 +02001250 int ret;
1251
1252 ret = clk_prepare_enable(fsl_ac97_data->clk);
1253 if (ret) {
1254 pr_err("ac97 read clk_prepare_enable failed: %d\n",
1255 ret);
1256 return -1;
1257 }
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001258
1259 lreg = (reg & 0x7f) << 12;
Markus Pargmann43248122014-05-27 10:24:25 +02001260 regmap_write(regs, CCSR_SSI_SACADD, lreg);
1261 regmap_update_bits(regs, CCSR_SSI_SACNT, CCSR_SSI_SACNT_RDWR_MASK,
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001262 CCSR_SSI_SACNT_RD);
1263
1264 udelay(100);
1265
Markus Pargmann43248122014-05-27 10:24:25 +02001266 regmap_read(regs, CCSR_SSI_SACDAT, &reg_val);
1267 val = (reg_val >> 4) & 0xffff;
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001268
Maciej S. Szmigiero8277df32015-08-05 17:21:35 +02001269 clk_disable_unprepare(fsl_ac97_data->clk);
1270
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001271 return val;
1272}
1273
1274static struct snd_ac97_bus_ops fsl_ssi_ac97_ops = {
1275 .read = fsl_ssi_ac97_read,
1276 .write = fsl_ssi_ac97_write,
1277};
1278
Timur Tabi17467f22008-01-11 18:15:26 +01001279/**
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001280 * Make every character in a string lower-case
Timur Tabi17467f22008-01-11 18:15:26 +01001281 */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001282static void make_lowercase(char *s)
Timur Tabi17467f22008-01-11 18:15:26 +01001283{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001284 char *p = s;
1285 char c;
1286
1287 while ((c = *p)) {
1288 if ((c >= 'A') && (c <= 'Z'))
1289 *p = c + ('a' - 'A');
1290 p++;
1291 }
1292}
1293
Markus Pargmann49da09e2014-04-28 12:54:45 +02001294static int fsl_ssi_imx_probe(struct platform_device *pdev,
Markus Pargmann4d9b7922014-04-28 12:54:47 +02001295 struct fsl_ssi_private *ssi_private, void __iomem *iomem)
Markus Pargmann49da09e2014-04-28 12:54:45 +02001296{
1297 struct device_node *np = pdev->dev.of_node;
Markus Pargmanned0f16042014-04-28 12:54:46 +02001298 u32 dmas[4];
Markus Pargmann49da09e2014-04-28 12:54:45 +02001299 int ret;
1300
Shengjiu Wangf4a43ca2014-09-16 10:13:16 +08001301 if (ssi_private->has_ipg_clk_name)
1302 ssi_private->clk = devm_clk_get(&pdev->dev, "ipg");
1303 else
1304 ssi_private->clk = devm_clk_get(&pdev->dev, NULL);
Markus Pargmann49da09e2014-04-28 12:54:45 +02001305 if (IS_ERR(ssi_private->clk)) {
1306 ret = PTR_ERR(ssi_private->clk);
1307 dev_err(&pdev->dev, "could not get clock: %d\n", ret);
1308 return ret;
1309 }
1310
Shengjiu Wangf4a43ca2014-09-16 10:13:16 +08001311 if (!ssi_private->has_ipg_clk_name) {
1312 ret = clk_prepare_enable(ssi_private->clk);
1313 if (ret) {
1314 dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", ret);
1315 return ret;
1316 }
Markus Pargmann49da09e2014-04-28 12:54:45 +02001317 }
1318
Xiubo Lidcfcf2c2015-08-12 14:38:18 +08001319 /* For those SLAVE implementations, we ignore non-baudclk cases
Markus Pargmann49da09e2014-04-28 12:54:45 +02001320 * and, instead, abandon MASTER mode that needs baud clock.
1321 */
1322 ssi_private->baudclk = devm_clk_get(&pdev->dev, "baud");
1323 if (IS_ERR(ssi_private->baudclk))
1324 dev_dbg(&pdev->dev, "could not get baud clock: %ld\n",
1325 PTR_ERR(ssi_private->baudclk));
Markus Pargmann49da09e2014-04-28 12:54:45 +02001326
1327 /*
1328 * We have burstsize be "fifo_depth - 2" to match the SSI
1329 * watermark setting in fsl_ssi_startup().
1330 */
1331 ssi_private->dma_params_tx.maxburst = ssi_private->fifo_depth - 2;
1332 ssi_private->dma_params_rx.maxburst = ssi_private->fifo_depth - 2;
Markus Pargmann43248122014-05-27 10:24:25 +02001333 ssi_private->dma_params_tx.addr = ssi_private->ssi_phys + CCSR_SSI_STX0;
1334 ssi_private->dma_params_rx.addr = ssi_private->ssi_phys + CCSR_SSI_SRX0;
Markus Pargmann49da09e2014-04-28 12:54:45 +02001335
Maciej S. Szmigiero90aff152015-03-04 22:48:30 +01001336 ret = of_property_read_u32_array(np, "dmas", dmas, 4);
Markus Pargmanned0f16042014-04-28 12:54:46 +02001337 if (ssi_private->use_dma && !ret && dmas[2] == IMX_DMATYPE_SSI_DUAL) {
Markus Pargmann49da09e2014-04-28 12:54:45 +02001338 ssi_private->use_dual_fifo = true;
1339 /* When using dual fifo mode, we need to keep watermark
1340 * as even numbers due to dma script limitation.
1341 */
1342 ssi_private->dma_params_tx.maxburst &= ~0x1;
1343 ssi_private->dma_params_rx.maxburst &= ~0x1;
1344 }
1345
Markus Pargmann4d9b7922014-04-28 12:54:47 +02001346 if (!ssi_private->use_dma) {
1347
1348 /*
1349 * Some boards use an incompatible codec. To get it
1350 * working, we are using imx-fiq-pcm-audio, that
1351 * can handle those codecs. DMA is not possible in this
1352 * situation.
1353 */
1354
1355 ssi_private->fiq_params.irq = ssi_private->irq;
1356 ssi_private->fiq_params.base = iomem;
1357 ssi_private->fiq_params.dma_params_rx =
1358 &ssi_private->dma_params_rx;
1359 ssi_private->fiq_params.dma_params_tx =
1360 &ssi_private->dma_params_tx;
1361
1362 ret = imx_pcm_fiq_init(pdev, &ssi_private->fiq_params);
1363 if (ret)
1364 goto error_pcm;
1365 } else {
Shengjiu Wang0d69e0d2015-06-23 18:23:53 +08001366 ret = imx_pcm_dma_init(pdev, IMX_SSI_DMABUF_SIZE);
Markus Pargmann4d9b7922014-04-28 12:54:47 +02001367 if (ret)
1368 goto error_pcm;
1369 }
1370
Markus Pargmann49da09e2014-04-28 12:54:45 +02001371 return 0;
Markus Pargmann4d9b7922014-04-28 12:54:47 +02001372
1373error_pcm:
Markus Pargmann4d9b7922014-04-28 12:54:47 +02001374
Shengjiu Wangf4a43ca2014-09-16 10:13:16 +08001375 if (!ssi_private->has_ipg_clk_name)
1376 clk_disable_unprepare(ssi_private->clk);
Markus Pargmann4d9b7922014-04-28 12:54:47 +02001377 return ret;
Markus Pargmann49da09e2014-04-28 12:54:45 +02001378}
1379
1380static void fsl_ssi_imx_clean(struct platform_device *pdev,
1381 struct fsl_ssi_private *ssi_private)
1382{
Markus Pargmann4d9b7922014-04-28 12:54:47 +02001383 if (!ssi_private->use_dma)
1384 imx_pcm_fiq_exit(pdev);
Shengjiu Wangf4a43ca2014-09-16 10:13:16 +08001385 if (!ssi_private->has_ipg_clk_name)
1386 clk_disable_unprepare(ssi_private->clk);
Markus Pargmann49da09e2014-04-28 12:54:45 +02001387}
1388
Bill Pembertona0a3d512012-12-07 09:26:16 -05001389static int fsl_ssi_probe(struct platform_device *pdev)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001390{
Timur Tabi17467f22008-01-11 18:15:26 +01001391 struct fsl_ssi_private *ssi_private;
1392 int ret = 0;
Timur Tabi38fec722010-08-19 15:26:58 -05001393 struct device_node *np = pdev->dev.of_node;
Markus Pargmannc1953bf2013-12-20 14:11:30 +01001394 const struct of_device_id *of_id;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001395 const char *p, *sprop;
Timur Tabi8e9d8692010-08-06 12:16:12 -05001396 const uint32_t *iprop;
Fabio Estevamca264182015-04-10 07:12:29 -03001397 struct resource *res;
Markus Pargmann43248122014-05-27 10:24:25 +02001398 void __iomem *iomem;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001399 char name[64];
Timur Tabi17467f22008-01-11 18:15:26 +01001400
Markus Pargmannc1953bf2013-12-20 14:11:30 +01001401 of_id = of_match_device(fsl_ssi_ids, &pdev->dev);
Sascha Hauerfcdbade2014-05-27 10:24:18 +02001402 if (!of_id || !of_id->data)
Markus Pargmannc1953bf2013-12-20 14:11:30 +01001403 return -EINVAL;
Markus Pargmannc1953bf2013-12-20 14:11:30 +01001404
Markus Pargmann2a1d1022014-04-28 12:54:44 +02001405 ssi_private = devm_kzalloc(&pdev->dev, sizeof(*ssi_private),
1406 GFP_KERNEL);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001407 if (!ssi_private) {
Timur Tabi38fec722010-08-19 15:26:58 -05001408 dev_err(&pdev->dev, "could not allocate DAI object\n");
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001409 return -ENOMEM;
1410 }
Timur Tabi17467f22008-01-11 18:15:26 +01001411
Sascha Hauerfcdbade2014-05-27 10:24:18 +02001412 ssi_private->soc = of_id->data;
1413
Markus Pargmann85e59af2014-05-27 10:24:19 +02001414 sprop = of_get_property(np, "fsl,mode", NULL);
1415 if (sprop) {
1416 if (!strcmp(sprop, "ac97-slave"))
1417 ssi_private->dai_fmt = SND_SOC_DAIFMT_AC97;
Markus Pargmann85e59af2014-05-27 10:24:19 +02001418 }
1419
Markus Pargmannde623ec2013-07-27 13:31:53 +02001420 ssi_private->use_dma = !of_property_read_bool(np,
1421 "fsl,fiq-stream-filter");
1422
Markus Pargmann85e59af2014-05-27 10:24:19 +02001423 if (fsl_ssi_is_ac97(ssi_private)) {
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001424 memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_ac97_dai,
1425 sizeof(fsl_ssi_ac97_dai));
1426
1427 fsl_ac97_data = ssi_private;
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001428
Maciej S. Szmigiero04143d62015-08-05 17:25:31 +02001429 ret = snd_soc_set_ac97_ops_of_reset(&fsl_ssi_ac97_ops, pdev);
1430 if (ret) {
1431 dev_err(&pdev->dev, "could not set AC'97 ops\n");
1432 return ret;
1433 }
Markus Pargmanncd7f0292013-08-19 17:05:58 +02001434 } else {
1435 /* Initialize this copy of the CPU DAI driver structure */
1436 memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template,
1437 sizeof(fsl_ssi_dai_template));
1438 }
Markus Pargmann2a1d1022014-04-28 12:54:44 +02001439 ssi_private->cpu_dai_drv.name = dev_name(&pdev->dev);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001440
Fabio Estevamca264182015-04-10 07:12:29 -03001441 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1442 iomem = devm_ioremap_resource(&pdev->dev, res);
1443 if (IS_ERR(iomem))
1444 return PTR_ERR(iomem);
1445 ssi_private->ssi_phys = res->start;
Markus Pargmann43248122014-05-27 10:24:25 +02001446
Shengjiu Wangf4a43ca2014-09-16 10:13:16 +08001447 ret = of_property_match_string(np, "clock-names", "ipg");
1448 if (ret < 0) {
1449 ssi_private->has_ipg_clk_name = false;
1450 ssi_private->regs = devm_regmap_init_mmio(&pdev->dev, iomem,
Markus Pargmann43248122014-05-27 10:24:25 +02001451 &fsl_ssi_regconfig);
Shengjiu Wangf4a43ca2014-09-16 10:13:16 +08001452 } else {
1453 ssi_private->has_ipg_clk_name = true;
1454 ssi_private->regs = devm_regmap_init_mmio_clk(&pdev->dev,
1455 "ipg", iomem, &fsl_ssi_regconfig);
1456 }
Markus Pargmann43248122014-05-27 10:24:25 +02001457 if (IS_ERR(ssi_private->regs)) {
1458 dev_err(&pdev->dev, "Failed to init register map\n");
1459 return PTR_ERR(ssi_private->regs);
1460 }
Timur Tabi1fab6ca2011-08-16 18:47:45 -04001461
Fabio Estevam2ffa5312014-12-01 19:57:14 -02001462 ssi_private->irq = platform_get_irq(pdev, 0);
Fabio Estevam28ecc0b2015-04-15 00:08:15 -03001463 if (ssi_private->irq < 0) {
Fabio Estevam0c123252015-01-07 13:44:32 -02001464 dev_err(&pdev->dev, "no irq for node %s\n", pdev->name);
Fabio Estevam64aa5f52015-01-07 19:45:40 -02001465 return ssi_private->irq;
Timur Tabi1fab6ca2011-08-16 18:47:45 -04001466 }
1467
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001468 /* Are the RX and the TX clocks locked? */
Nicolin Chen07a94832013-12-03 18:38:07 +08001469 if (!of_find_property(np, "fsl,ssi-asynchronous", NULL)) {
Maciej S. Szmigiero06cb3732015-08-05 17:24:10 +02001470 if (!fsl_ssi_is_ac97(ssi_private))
1471 ssi_private->cpu_dai_drv.symmetric_rates = 1;
1472
Nicolin Chen07a94832013-12-03 18:38:07 +08001473 ssi_private->cpu_dai_drv.symmetric_channels = 1;
1474 ssi_private->cpu_dai_drv.symmetric_samplebits = 1;
1475 }
Timur Tabi17467f22008-01-11 18:15:26 +01001476
Timur Tabi8e9d8692010-08-06 12:16:12 -05001477 /* Determine the FIFO depth. */
1478 iprop = of_get_property(np, "fsl,fifo-depth", NULL);
1479 if (iprop)
Timur Tabi147dfe92011-06-08 15:02:55 -05001480 ssi_private->fifo_depth = be32_to_cpup(iprop);
Timur Tabi8e9d8692010-08-06 12:16:12 -05001481 else
1482 /* Older 8610 DTs didn't have the fifo-depth property */
1483 ssi_private->fifo_depth = 8;
1484
Markus Pargmann4d9b7922014-04-28 12:54:47 +02001485 dev_set_drvdata(&pdev->dev, ssi_private);
1486
Sascha Hauerfcdbade2014-05-27 10:24:18 +02001487 if (ssi_private->soc->imx) {
Markus Pargmann43248122014-05-27 10:24:25 +02001488 ret = fsl_ssi_imx_probe(pdev, ssi_private, iomem);
Markus Pargmann49da09e2014-04-28 12:54:45 +02001489 if (ret)
Fabio Estevam2ffa5312014-12-01 19:57:14 -02001490 return ret;
Markus Pargmann0888efd2013-12-20 14:11:31 +01001491 }
1492
Fabio Estevam299e7e92015-04-09 14:56:41 -03001493 ret = devm_snd_soc_register_component(&pdev->dev, &fsl_ssi_component,
1494 &ssi_private->cpu_dai_drv, 1);
Markus Pargmann4d9b7922014-04-28 12:54:47 +02001495 if (ret) {
1496 dev_err(&pdev->dev, "failed to register DAI: %d\n", ret);
1497 goto error_asoc_register;
1498 }
1499
Markus Pargmann0888efd2013-12-20 14:11:31 +01001500 if (ssi_private->use_dma) {
Michael Grzeschikf0377082013-08-19 17:06:01 +02001501 ret = devm_request_irq(&pdev->dev, ssi_private->irq,
Markus Pargmann171d6832014-04-28 12:54:48 +02001502 fsl_ssi_isr, 0, dev_name(&pdev->dev),
Michael Grzeschikf0377082013-08-19 17:06:01 +02001503 ssi_private);
1504 if (ret < 0) {
1505 dev_err(&pdev->dev, "could not claim irq %u\n",
1506 ssi_private->irq);
Fabio Estevam299e7e92015-04-09 14:56:41 -03001507 goto error_asoc_register;
Michael Grzeschikf0377082013-08-19 17:06:01 +02001508 }
Shawn Guo09ce1112012-03-16 16:56:43 +08001509 }
1510
Markus Pargmannf138e622014-04-28 12:54:43 +02001511 ret = fsl_ssi_debugfs_create(&ssi_private->dbg_stats, &pdev->dev);
Markus Pargmann9368acc2013-12-20 14:11:29 +01001512 if (ret)
Fabio Estevam299e7e92015-04-09 14:56:41 -03001513 goto error_asoc_register;
Shawn Guo09ce1112012-03-16 16:56:43 +08001514
1515 /*
1516 * If codec-handle property is missing from SSI node, we assume
1517 * that the machine driver uses new binding which does not require
1518 * SSI driver to trigger machine driver's probe.
1519 */
Markus Pargmann171d6832014-04-28 12:54:48 +02001520 if (!of_get_property(np, "codec-handle", NULL))
Shawn Guo09ce1112012-03-16 16:56:43 +08001521 goto done;
Shawn Guo09ce1112012-03-16 16:56:43 +08001522
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001523 /* Trigger the machine driver's probe function. The platform driver
Shawn Guo2b81ec62012-03-09 00:59:46 +08001524 * name of the machine driver is taken from /compatible property of the
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001525 * device tree. We also pass the address of the CPU DAI driver
1526 * structure.
1527 */
Shawn Guo2b81ec62012-03-09 00:59:46 +08001528 sprop = of_get_property(of_find_node_by_path("/"), "compatible", NULL);
1529 /* Sometimes the compatible name has a "fsl," prefix, so we strip it. */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001530 p = strrchr(sprop, ',');
1531 if (p)
1532 sprop = p + 1;
1533 snprintf(name, sizeof(name), "snd-soc-%s", sprop);
1534 make_lowercase(name);
1535
1536 ssi_private->pdev =
Timur Tabi38fec722010-08-19 15:26:58 -05001537 platform_device_register_data(&pdev->dev, name, 0, NULL, 0);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001538 if (IS_ERR(ssi_private->pdev)) {
1539 ret = PTR_ERR(ssi_private->pdev);
Timur Tabi38fec722010-08-19 15:26:58 -05001540 dev_err(&pdev->dev, "failed to register platform: %d\n", ret);
Markus Pargmann4d9b7922014-04-28 12:54:47 +02001541 goto error_sound_card;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001542 }
1543
Shawn Guo09ce1112012-03-16 16:56:43 +08001544done:
Markus Pargmann85e59af2014-05-27 10:24:19 +02001545 if (ssi_private->dai_fmt)
Michael Trimarchi85151462014-09-18 20:38:09 +02001546 _fsl_ssi_set_dai_fmt(&pdev->dev, ssi_private,
1547 ssi_private->dai_fmt);
Markus Pargmann85e59af2014-05-27 10:24:19 +02001548
Maciej S. Szmigiero8ed0c842015-08-05 17:26:44 +02001549 if (fsl_ssi_is_ac97(ssi_private)) {
1550 u32 ssi_idx;
1551
1552 ret = of_property_read_u32(np, "cell-index", &ssi_idx);
1553 if (ret) {
1554 dev_err(&pdev->dev, "cannot get SSI index property\n");
1555 goto error_sound_card;
1556 }
1557
1558 ssi_private->pdev =
1559 platform_device_register_data(NULL,
1560 "ac97-codec", ssi_idx, NULL, 0);
1561 if (IS_ERR(ssi_private->pdev)) {
1562 ret = PTR_ERR(ssi_private->pdev);
1563 dev_err(&pdev->dev,
1564 "failed to register AC97 codec platform: %d\n",
1565 ret);
1566 goto error_sound_card;
1567 }
1568 }
1569
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001570 return 0;
Timur Tabi87a06322010-08-03 17:55:28 -05001571
Markus Pargmann4d9b7922014-04-28 12:54:47 +02001572error_sound_card:
Markus Pargmannf138e622014-04-28 12:54:43 +02001573 fsl_ssi_debugfs_remove(&ssi_private->dbg_stats);
Markus Pargmann9368acc2013-12-20 14:11:29 +01001574
Markus Pargmann4d9b7922014-04-28 12:54:47 +02001575error_asoc_register:
Sascha Hauerfcdbade2014-05-27 10:24:18 +02001576 if (ssi_private->soc->imx)
Markus Pargmann49da09e2014-04-28 12:54:45 +02001577 fsl_ssi_imx_clean(pdev, ssi_private);
Timur Tabi1fab6ca2011-08-16 18:47:45 -04001578
Timur Tabi87a06322010-08-03 17:55:28 -05001579 return ret;
Timur Tabi17467f22008-01-11 18:15:26 +01001580}
Timur Tabi17467f22008-01-11 18:15:26 +01001581
Timur Tabi38fec722010-08-19 15:26:58 -05001582static int fsl_ssi_remove(struct platform_device *pdev)
Timur Tabi17467f22008-01-11 18:15:26 +01001583{
Timur Tabi38fec722010-08-19 15:26:58 -05001584 struct fsl_ssi_private *ssi_private = dev_get_drvdata(&pdev->dev);
Timur Tabi17467f22008-01-11 18:15:26 +01001585
Markus Pargmannf138e622014-04-28 12:54:43 +02001586 fsl_ssi_debugfs_remove(&ssi_private->dbg_stats);
Markus Pargmann9368acc2013-12-20 14:11:29 +01001587
Markus Pargmann171d6832014-04-28 12:54:48 +02001588 if (ssi_private->pdev)
Shawn Guo09ce1112012-03-16 16:56:43 +08001589 platform_device_unregister(ssi_private->pdev);
Markus Pargmann49da09e2014-04-28 12:54:45 +02001590
Sascha Hauerfcdbade2014-05-27 10:24:18 +02001591 if (ssi_private->soc->imx)
Markus Pargmann49da09e2014-04-28 12:54:45 +02001592 fsl_ssi_imx_clean(pdev, ssi_private);
1593
Maciej S. Szmigiero04143d62015-08-05 17:25:31 +02001594 if (fsl_ssi_is_ac97(ssi_private))
1595 snd_soc_set_ac97_ops(NULL);
1596
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001597 return 0;
Timur Tabi17467f22008-01-11 18:15:26 +01001598}
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001599
Zidan Wang05cf2372015-09-18 11:09:12 +08001600#ifdef CONFIG_PM_SLEEP
1601static int fsl_ssi_suspend(struct device *dev)
1602{
1603 struct fsl_ssi_private *ssi_private = dev_get_drvdata(dev);
1604 struct regmap *regs = ssi_private->regs;
1605
1606 regmap_read(regs, CCSR_SSI_SFCSR,
1607 &ssi_private->regcache_sfcsr);
Maciej S. Szmigiero3f1c2412015-12-20 21:30:25 +01001608 regmap_read(regs, CCSR_SSI_SACNT,
1609 &ssi_private->regcache_sacnt);
Zidan Wang05cf2372015-09-18 11:09:12 +08001610
1611 regcache_cache_only(regs, true);
1612 regcache_mark_dirty(regs);
1613
1614 return 0;
1615}
1616
1617static int fsl_ssi_resume(struct device *dev)
1618{
1619 struct fsl_ssi_private *ssi_private = dev_get_drvdata(dev);
1620 struct regmap *regs = ssi_private->regs;
1621
1622 regcache_cache_only(regs, false);
1623
1624 regmap_update_bits(regs, CCSR_SSI_SFCSR,
1625 CCSR_SSI_SFCSR_RFWM1_MASK | CCSR_SSI_SFCSR_TFWM1_MASK |
1626 CCSR_SSI_SFCSR_RFWM0_MASK | CCSR_SSI_SFCSR_TFWM0_MASK,
1627 ssi_private->regcache_sfcsr);
Maciej S. Szmigiero3f1c2412015-12-20 21:30:25 +01001628 regmap_write(regs, CCSR_SSI_SACNT,
1629 ssi_private->regcache_sacnt);
Zidan Wang05cf2372015-09-18 11:09:12 +08001630
1631 return regcache_sync(regs);
1632}
1633#endif /* CONFIG_PM_SLEEP */
1634
1635static const struct dev_pm_ops fsl_ssi_pm = {
1636 SET_SYSTEM_SLEEP_PM_OPS(fsl_ssi_suspend, fsl_ssi_resume)
1637};
1638
Grant Likelyf07eb222011-02-22 21:05:04 -07001639static struct platform_driver fsl_ssi_driver = {
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001640 .driver = {
1641 .name = "fsl-ssi-dai",
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001642 .of_match_table = fsl_ssi_ids,
Zidan Wang05cf2372015-09-18 11:09:12 +08001643 .pm = &fsl_ssi_pm,
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001644 },
1645 .probe = fsl_ssi_probe,
1646 .remove = fsl_ssi_remove,
1647};
Timur Tabi17467f22008-01-11 18:15:26 +01001648
Axel Linba0a7e02011-11-25 10:10:55 +08001649module_platform_driver(fsl_ssi_driver);
Timur Tabia454dad2009-03-05 17:23:37 -06001650
Fabio Estevamf3142802013-07-20 16:16:01 -03001651MODULE_ALIAS("platform:fsl-ssi-dai");
Timur Tabi17467f22008-01-11 18:15:26 +01001652MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
1653MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver");
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001654MODULE_LICENSE("GPL v2");