fsl_sai.c 29.5 KB
Newer Older
1 2 3 4 5
// SPDX-License-Identifier: GPL-2.0+
//
// Freescale ALSA SoC Digital Audio Interface (SAI) driver.
//
// Copyright 2012-2015 Freescale Semiconductor, Inc.
6 7 8 9 10 11

#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/dmaengine.h>
#include <linux/module.h>
#include <linux/of_address.h>
L
Lucas Stach 已提交
12
#include <linux/of_device.h>
13
#include <linux/pm_runtime.h>
14
#include <linux/regmap.h>
15
#include <linux/slab.h>
16
#include <linux/time.h>
17 18 19
#include <sound/core.h>
#include <sound/dmaengine_pcm.h>
#include <sound/pcm_params.h>
20 21
#include <linux/mfd/syscon.h>
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
22 23

#include "fsl_sai.h"
24
#include "imx-pcm.h"
25

26 27 28
#define FSL_SAI_FLAGS (FSL_SAI_CSR_SEIE |\
		       FSL_SAI_CSR_FEIE)

29
static const unsigned int fsl_sai_rates[] = {
30 31 32 33 34
	8000, 11025, 12000, 16000, 22050,
	24000, 32000, 44100, 48000, 64000,
	88200, 96000, 176400, 192000
};

35
static const struct snd_pcm_hw_constraint_list fsl_sai_rate_constraints = {
36 37 38 39
	.count = ARRAY_SIZE(fsl_sai_rates),
	.list = fsl_sai_rates,
};

40 41 42
static irqreturn_t fsl_sai_isr(int irq, void *devid)
{
	struct fsl_sai *sai = (struct fsl_sai *)devid;
43
	unsigned int ofs = sai->soc_data->reg_offset;
44
	struct device *dev = &sai->pdev->dev;
45 46 47 48 49 50 51 52
	u32 flags, xcsr, mask;
	bool irq_none = true;

	/*
	 * Both IRQ status bits and IRQ mask bits are in the xCSR but
	 * different shifts. And we here create a mask only for those
	 * IRQs that we activated.
	 */
53 54 55
	mask = (FSL_SAI_FLAGS >> FSL_SAI_CSR_xIE_SHIFT) << FSL_SAI_CSR_xF_SHIFT;

	/* Tx IRQ */
56
	regmap_read(sai->regmap, FSL_SAI_TCSR(ofs), &xcsr);
57 58 59 60 61 62
	flags = xcsr & mask;

	if (flags)
		irq_none = false;
	else
		goto irq_rx;
63

64
	if (flags & FSL_SAI_CSR_WSF)
65 66
		dev_dbg(dev, "isr: Start of Tx word detected\n");

67
	if (flags & FSL_SAI_CSR_SEF)
68
		dev_dbg(dev, "isr: Tx Frame sync error detected\n");
69

70
	if (flags & FSL_SAI_CSR_FEF) {
71
		dev_dbg(dev, "isr: Transmit underrun detected\n");
72 73 74 75
		/* FIFO reset for safety */
		xcsr |= FSL_SAI_CSR_FR;
	}

76
	if (flags & FSL_SAI_CSR_FWF)
77 78
		dev_dbg(dev, "isr: Enabled transmit FIFO is empty\n");

79
	if (flags & FSL_SAI_CSR_FRF)
80 81
		dev_dbg(dev, "isr: Transmit FIFO watermark has been reached\n");

82 83 84 85
	flags &= FSL_SAI_CSR_xF_W_MASK;
	xcsr &= ~FSL_SAI_CSR_xF_MASK;

	if (flags)
86
		regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), flags | xcsr);
87

88
irq_rx:
89
	/* Rx IRQ */
90
	regmap_read(sai->regmap, FSL_SAI_RCSR(ofs), &xcsr);
91
	flags = xcsr & mask;
92

93 94 95 96 97 98
	if (flags)
		irq_none = false;
	else
		goto out;

	if (flags & FSL_SAI_CSR_WSF)
99 100
		dev_dbg(dev, "isr: Start of Rx word detected\n");

101
	if (flags & FSL_SAI_CSR_SEF)
102
		dev_dbg(dev, "isr: Rx Frame sync error detected\n");
103

104
	if (flags & FSL_SAI_CSR_FEF) {
105
		dev_dbg(dev, "isr: Receive overflow detected\n");
106 107 108 109
		/* FIFO reset for safety */
		xcsr |= FSL_SAI_CSR_FR;
	}

110
	if (flags & FSL_SAI_CSR_FWF)
111 112
		dev_dbg(dev, "isr: Enabled receive FIFO is full\n");

113
	if (flags & FSL_SAI_CSR_FRF)
114 115
		dev_dbg(dev, "isr: Receive FIFO watermark has been reached\n");

116 117
	flags &= FSL_SAI_CSR_xF_W_MASK;
	xcsr &= ~FSL_SAI_CSR_xF_MASK;
118

119
	if (flags)
120
		regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), flags | xcsr);
121 122 123 124 125 126

out:
	if (irq_none)
		return IRQ_NONE;
	else
		return IRQ_HANDLED;
127 128
}

129 130 131 132 133 134 135 136 137 138 139
static int fsl_sai_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
				u32 rx_mask, int slots, int slot_width)
{
	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);

	sai->slots = slots;
	sai->slot_width = slot_width;

	return 0;
}

140 141 142 143
static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
		int clk_id, unsigned int freq, int fsl_dir)
{
	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
144
	unsigned int ofs = sai->soc_data->reg_offset;
145 146
	bool tx = fsl_dir == FSL_FMT_TRANSMITTER;
	u32 val_cr2 = 0;
X
Xiubo Li 已提交
147

148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
	switch (clk_id) {
	case FSL_SAI_CLK_BUS:
		val_cr2 |= FSL_SAI_CR2_MSEL_BUS;
		break;
	case FSL_SAI_CLK_MAST1:
		val_cr2 |= FSL_SAI_CR2_MSEL_MCLK1;
		break;
	case FSL_SAI_CLK_MAST2:
		val_cr2 |= FSL_SAI_CR2_MSEL_MCLK2;
		break;
	case FSL_SAI_CLK_MAST3:
		val_cr2 |= FSL_SAI_CR2_MSEL_MCLK3;
		break;
	default:
		return -EINVAL;
	}
X
Xiubo Li 已提交
164

165
	regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
166
			   FSL_SAI_CR2_MSEL_MASK, val_cr2);
167 168 169 170 171 172 173

	return 0;
}

static int fsl_sai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
		int clk_id, unsigned int freq, int dir)
{
174
	int ret;
175 176 177 178 179 180 181

	if (dir == SND_SOC_CLOCK_IN)
		return 0;

	ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq,
					FSL_FMT_TRANSMITTER);
	if (ret) {
182
		dev_err(cpu_dai->dev, "Cannot set tx sysclk: %d\n", ret);
183
		return ret;
184 185 186 187
	}

	ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq,
					FSL_FMT_RECEIVER);
188
	if (ret)
189
		dev_err(cpu_dai->dev, "Cannot set rx sysclk: %d\n", ret);
190

191
	return ret;
192 193 194 195 196 197
}

static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
				unsigned int fmt, int fsl_dir)
{
	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
198
	unsigned int ofs = sai->soc_data->reg_offset;
199 200
	bool tx = fsl_dir == FSL_FMT_TRANSMITTER;
	u32 val_cr2 = 0, val_cr4 = 0;
201

202
	if (!sai->is_lsb_first)
203
		val_cr4 |= FSL_SAI_CR4_MF;
204

205
	/* DAI mode */
206 207
	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
	case SND_SOC_DAIFMT_I2S:
208 209 210 211 212 213
		/*
		 * Frame low, 1clk before data, one word length for frame sync,
		 * frame sync starts one serial clock cycle earlier,
		 * that is, together with the last bit of the previous
		 * data word.
		 */
214
		val_cr2 |= FSL_SAI_CR2_BCP;
215 216 217
		val_cr4 |= FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP;
		break;
	case SND_SOC_DAIFMT_LEFT_J:
218 219 220 221
		/*
		 * Frame high, one word length for frame sync,
		 * frame sync asserts with the first bit of the frame.
		 */
222
		val_cr2 |= FSL_SAI_CR2_BCP;
223
		break;
224 225 226 227 228 229 230
	case SND_SOC_DAIFMT_DSP_A:
		/*
		 * Frame high, 1clk before data, one bit for frame sync,
		 * frame sync starts one serial clock cycle earlier,
		 * that is, together with the last bit of the previous
		 * data word.
		 */
231
		val_cr2 |= FSL_SAI_CR2_BCP;
232 233 234 235 236 237 238 239
		val_cr4 |= FSL_SAI_CR4_FSE;
		sai->is_dsp_mode = true;
		break;
	case SND_SOC_DAIFMT_DSP_B:
		/*
		 * Frame high, one bit for frame sync,
		 * frame sync asserts with the first bit of the frame.
		 */
240
		val_cr2 |= FSL_SAI_CR2_BCP;
241 242
		sai->is_dsp_mode = true;
		break;
243 244
	case SND_SOC_DAIFMT_RIGHT_J:
		/* To be done */
245 246 247 248
	default:
		return -EINVAL;
	}

249
	/* DAI clock inversion */
250 251
	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
	case SND_SOC_DAIFMT_IB_IF:
252 253 254
		/* Invert both clocks */
		val_cr2 ^= FSL_SAI_CR2_BCP;
		val_cr4 ^= FSL_SAI_CR4_FSP;
255 256
		break;
	case SND_SOC_DAIFMT_IB_NF:
257 258
		/* Invert bit clock */
		val_cr2 ^= FSL_SAI_CR2_BCP;
259 260
		break;
	case SND_SOC_DAIFMT_NB_IF:
261 262
		/* Invert frame clock */
		val_cr4 ^= FSL_SAI_CR4_FSP;
263 264
		break;
	case SND_SOC_DAIFMT_NB_NF:
265
		/* Nothing to do for both normal cases */
266 267 268 269 270
		break;
	default:
		return -EINVAL;
	}

271
	/* DAI clock master masks */
272 273 274 275
	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
	case SND_SOC_DAIFMT_CBS_CFS:
		val_cr2 |= FSL_SAI_CR2_BCD_MSTR;
		val_cr4 |= FSL_SAI_CR4_FSD_MSTR;
276
		sai->is_slave_mode = false;
277 278
		break;
	case SND_SOC_DAIFMT_CBM_CFM:
279
		sai->is_slave_mode = true;
280
		break;
281 282
	case SND_SOC_DAIFMT_CBS_CFM:
		val_cr2 |= FSL_SAI_CR2_BCD_MSTR;
283
		sai->is_slave_mode = false;
284 285 286
		break;
	case SND_SOC_DAIFMT_CBM_CFS:
		val_cr4 |= FSL_SAI_CR4_FSD_MSTR;
287
		sai->is_slave_mode = true;
288
		break;
289 290 291 292
	default:
		return -EINVAL;
	}

293
	regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
294
			   FSL_SAI_CR2_BCP | FSL_SAI_CR2_BCD_MSTR, val_cr2);
295
	regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
296 297
			   FSL_SAI_CR4_MF | FSL_SAI_CR4_FSE |
			   FSL_SAI_CR4_FSP | FSL_SAI_CR4_FSD_MSTR, val_cr4);
298 299 300 301 302 303

	return 0;
}

static int fsl_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
{
304
	int ret;
305 306 307

	ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_TRANSMITTER);
	if (ret) {
308
		dev_err(cpu_dai->dev, "Cannot set tx format: %d\n", ret);
309
		return ret;
310 311 312
	}

	ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_RECEIVER);
313
	if (ret)
314
		dev_err(cpu_dai->dev, "Cannot set rx format: %d\n", ret);
315

316
	return ret;
317 318
}

319 320 321
static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
{
	struct fsl_sai *sai = snd_soc_dai_get_drvdata(dai);
322
	unsigned int ofs = sai->soc_data->reg_offset;
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
	unsigned long clk_rate;
	u32 savediv = 0, ratio, savesub = freq;
	u32 id;
	int ret = 0;

	/* Don't apply to slave mode */
	if (sai->is_slave_mode)
		return 0;

	for (id = 0; id < FSL_SAI_MCLK_MAX; id++) {
		clk_rate = clk_get_rate(sai->mclk_clk[id]);
		if (!clk_rate)
			continue;

		ratio = clk_rate / freq;

		ret = clk_rate - ratio * freq;

		/*
		 * Drop the source that can not be
		 * divided into the required rate.
		 */
		if (ret != 0 && clk_rate / ret < 1000)
			continue;

		dev_dbg(dai->dev,
			"ratio %d for freq %dHz based on clock %ldHz\n",
			ratio, freq, clk_rate);

		if (ratio % 2 == 0 && ratio >= 2 && ratio <= 512)
			ratio /= 2;
		else
			continue;

		if (ret < savesub) {
			savediv = ratio;
			sai->mclk_id[tx] = id;
			savesub = ret;
		}

		if (ret == 0)
			break;
	}

	if (savediv == 0) {
		dev_err(dai->dev, "failed to derive required %cx rate: %d\n",
				tx ? 'T' : 'R', freq);
		return -EINVAL;
	}

373 374 375 376 377 378 379 380 381 382 383 384
	/*
	 * 1) For Asynchronous mode, we must set RCR2 register for capture, and
	 *    set TCR2 register for playback.
	 * 2) For Tx sync with Rx clock, we must set RCR2 register for playback
	 *    and capture.
	 * 3) For Rx sync with Tx clock, we must set TCR2 register for playback
	 *    and capture.
	 * 4) For Tx and Rx are both Synchronous with another SAI, we just
	 *    ignore it.
	 */
	if ((sai->synchronous[TX] && !sai->synchronous[RX]) ||
	    (!tx && !sai->synchronous[RX])) {
385
		regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs),
386 387
				   FSL_SAI_CR2_MSEL_MASK,
				   FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
388
		regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs),
389
				   FSL_SAI_CR2_DIV_MASK, savediv - 1);
390 391
	} else if ((sai->synchronous[RX] && !sai->synchronous[TX]) ||
		   (tx && !sai->synchronous[TX])) {
392
		regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs),
393 394
				   FSL_SAI_CR2_MSEL_MASK,
				   FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
395
		regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs),
396 397 398 399 400 401 402 403 404
				   FSL_SAI_CR2_DIV_MASK, savediv - 1);
	}

	dev_dbg(dai->dev, "best fit: clock id=%d, div=%d, deviation =%d\n",
			sai->mclk_id[tx], savediv, savesub);

	return 0;
}

405 406 407 408
static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
		struct snd_pcm_hw_params *params,
		struct snd_soc_dai *cpu_dai)
{
409
	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
410
	unsigned int ofs = sai->soc_data->reg_offset;
411
	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
412
	unsigned int channels = params_channels(params);
413
	u32 word_width = params_width(params);
414
	u32 val_cr4 = 0, val_cr5 = 0;
415 416
	u32 slots = (channels == 1) ? 2 : channels;
	u32 slot_width = word_width;
417 418
	int ret;

419 420 421 422 423 424
	if (sai->slots)
		slots = sai->slots;

	if (sai->slot_width)
		slot_width = sai->slot_width;

425 426
	if (!sai->is_slave_mode) {
		ret = fsl_sai_set_bclk(cpu_dai, tx,
427
				slots * slot_width * params_rate(params));
428 429 430 431 432 433 434 435 436 437 438 439
		if (ret)
			return ret;

		/* Do not enable the clock if it is already enabled */
		if (!(sai->mclk_streams & BIT(substream->stream))) {
			ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[tx]]);
			if (ret)
				return ret;

			sai->mclk_streams |= BIT(substream->stream);
		}
	}
440

441
	if (!sai->is_dsp_mode)
442
		val_cr4 |= FSL_SAI_CR4_SYWD(slot_width);
443

444 445
	val_cr5 |= FSL_SAI_CR5_WNW(slot_width);
	val_cr5 |= FSL_SAI_CR5_W0W(slot_width);
446

447
	if (sai->is_lsb_first)
448
		val_cr5 |= FSL_SAI_CR5_FBT(0);
449 450
	else
		val_cr5 |= FSL_SAI_CR5_FBT(word_width - 1);
451

452
	val_cr4 |= FSL_SAI_CR4_FRSZ(slots);
453

454 455 456 457 458 459 460 461 462
	/*
	 * For SAI master mode, when Tx(Rx) sync with Rx(Tx) clock, Rx(Tx) will
	 * generate bclk and frame clock for Tx(Rx), we should set RCR4(TCR4),
	 * RCR5(TCR5) and RMR(TMR) for playback(capture), or there will be sync
	 * error.
	 */

	if (!sai->is_slave_mode) {
		if (!sai->synchronous[TX] && sai->synchronous[RX] && !tx) {
463
			regmap_update_bits(sai->regmap, FSL_SAI_TCR4(ofs),
464 465
				FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
				val_cr4);
466
			regmap_update_bits(sai->regmap, FSL_SAI_TCR5(ofs),
467 468 469 470 471
				FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
				FSL_SAI_CR5_FBT_MASK, val_cr5);
			regmap_write(sai->regmap, FSL_SAI_TMR,
				~0UL - ((1 << channels) - 1));
		} else if (!sai->synchronous[RX] && sai->synchronous[TX] && tx) {
472
			regmap_update_bits(sai->regmap, FSL_SAI_RCR4(ofs),
473 474
				FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
				val_cr4);
475
			regmap_update_bits(sai->regmap, FSL_SAI_RCR5(ofs),
476 477 478 479 480 481
				FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
				FSL_SAI_CR5_FBT_MASK, val_cr5);
			regmap_write(sai->regmap, FSL_SAI_RMR,
				~0UL - ((1 << channels) - 1));
		}
	}
482

483
	regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
484 485
			   FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
			   val_cr4);
486
	regmap_update_bits(sai->regmap, FSL_SAI_xCR5(tx, ofs),
487 488 489
			   FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
			   FSL_SAI_CR5_FBT_MASK, val_cr5);
	regmap_write(sai->regmap, FSL_SAI_xMR(tx), ~0UL - ((1 << channels) - 1));
490 491 492 493

	return 0;
}

494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509
static int fsl_sai_hw_free(struct snd_pcm_substream *substream,
		struct snd_soc_dai *cpu_dai)
{
	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;

	if (!sai->is_slave_mode &&
			sai->mclk_streams & BIT(substream->stream)) {
		clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[tx]]);
		sai->mclk_streams &= ~BIT(substream->stream);
	}

	return 0;
}


510 511 512 513
static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
		struct snd_soc_dai *cpu_dai)
{
	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
514 515
	unsigned int ofs = sai->soc_data->reg_offset;

516
	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
517
	u32 xcsr, count = 100;
518

519
	/*
520 521 522
	 * Asynchronous mode: Clear SYNC for both Tx and Rx.
	 * Rx sync with Tx clocks: Clear SYNC for Tx, set it for Rx.
	 * Tx sync with Rx clocks: Clear SYNC for Rx, set it for Tx.
523
	 */
524 525 526
	regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs), FSL_SAI_CR2_SYNC,
			   sai->synchronous[TX] ? FSL_SAI_CR2_SYNC : 0);
	regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs), FSL_SAI_CR2_SYNC,
527
			   sai->synchronous[RX] ? FSL_SAI_CR2_SYNC : 0);
528

529 530 531 532
	/*
	 * It is recommended that the transmitter is the last enabled
	 * and the first disabled.
	 */
533 534 535 536
	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
	case SNDRV_PCM_TRIGGER_RESUME:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
537
		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
538 539
				   FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE);

540
		regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs),
541
				   FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
542
		regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs),
543
				   FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
544

545
		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
546
				   FSL_SAI_CSR_xIE_MASK, FSL_SAI_FLAGS);
547 548 549 550
		break;
	case SNDRV_PCM_TRIGGER_STOP:
	case SNDRV_PCM_TRIGGER_SUSPEND:
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
551
		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
552
				   FSL_SAI_CSR_FRDE, 0);
553
		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
554
				   FSL_SAI_CSR_xIE_MASK, 0);
555

556
		/* Check if the opposite FRDE is also disabled */
557
		regmap_read(sai->regmap, FSL_SAI_xCSR(!tx, ofs), &xcsr);
558
		if (!(xcsr & FSL_SAI_CSR_FRDE)) {
559
			/* Disable both directions and reset their FIFOs */
560
			regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs),
561
					   FSL_SAI_CSR_TERE, 0);
562
			regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs),
563 564 565 566 567
					   FSL_SAI_CSR_TERE, 0);

			/* TERE will remain set till the end of current frame */
			do {
				udelay(10);
568 569
				regmap_read(sai->regmap,
					    FSL_SAI_xCSR(tx, ofs), &xcsr);
570 571
			} while (--count && xcsr & FSL_SAI_CSR_TERE);

572
			regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs),
573
					   FSL_SAI_CSR_FR, FSL_SAI_CSR_FR);
574
			regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs),
575
					   FSL_SAI_CSR_FR, FSL_SAI_CSR_FR);
576 577 578 579 580 581 582 583 584 585

			/*
			 * For sai master mode, after several open/close sai,
			 * there will be no frame clock, and can't recover
			 * anymore. Add software reset to fix this issue.
			 * This is a hardware bug, and will be fix in the
			 * next sai version.
			 */
			if (!sai->is_slave_mode) {
				/* Software Reset for both Tx and Rx */
586 587 588 589
				regmap_write(sai->regmap, FSL_SAI_TCSR(ofs),
					     FSL_SAI_CSR_SR);
				regmap_write(sai->regmap, FSL_SAI_RCSR(ofs),
					     FSL_SAI_CSR_SR);
590
				/* Clear SR bit to finish the reset */
591 592
				regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0);
				regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0);
593
			}
594 595 596 597 598 599 600 601 602 603 604 605 606
		}
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static int fsl_sai_startup(struct snd_pcm_substream *substream,
		struct snd_soc_dai *cpu_dai)
{
	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
607
	unsigned int ofs = sai->soc_data->reg_offset;
608
	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
609 610
	int ret;

611
	regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs),
612
			   FSL_SAI_CR3_TRCE_MASK,
613 614
			   FSL_SAI_CR3_TRCE);

615 616 617 618
	ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
			SNDRV_PCM_HW_PARAM_RATE, &fsl_sai_rate_constraints);

	return ret;
619 620 621 622 623 624
}

static void fsl_sai_shutdown(struct snd_pcm_substream *substream,
		struct snd_soc_dai *cpu_dai)
{
	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
625
	unsigned int ofs = sai->soc_data->reg_offset;
626
	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
627

628
	regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs),
629
			   FSL_SAI_CR3_TRCE_MASK, 0);
630 631 632 633 634
}

static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
	.set_sysclk	= fsl_sai_set_dai_sysclk,
	.set_fmt	= fsl_sai_set_dai_fmt,
635
	.set_tdm_slot	= fsl_sai_set_dai_tdm_slot,
636
	.hw_params	= fsl_sai_hw_params,
637
	.hw_free	= fsl_sai_hw_free,
638 639 640 641 642 643 644 645
	.trigger	= fsl_sai_trigger,
	.startup	= fsl_sai_startup,
	.shutdown	= fsl_sai_shutdown,
};

static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai)
{
	struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev);
646
	unsigned int ofs = sai->soc_data->reg_offset;
647

648
	/* Software Reset for both Tx and Rx */
649 650
	regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR);
	regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR);
651
	/* Clear SR bit to finish the reset */
652 653
	regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0);
	regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0);
654

655 656
	regmap_update_bits(sai->regmap, FSL_SAI_TCR1(ofs),
			   FSL_SAI_CR1_RFW_MASK,
657
			   sai->soc_data->fifo_depth - FSL_SAI_MAXBURST_TX);
658 659
	regmap_update_bits(sai->regmap, FSL_SAI_RCR1(ofs),
			   FSL_SAI_CR1_RFW_MASK, FSL_SAI_MAXBURST_RX - 1);
660

661 662
	snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx,
				&sai->dma_params_rx);
663 664 665 666 667 668 669 670 671

	snd_soc_dai_set_drvdata(cpu_dai, sai);

	return 0;
}

static struct snd_soc_dai_driver fsl_sai_dai = {
	.probe = fsl_sai_dai_probe,
	.playback = {
672
		.stream_name = "CPU-Playback",
673
		.channels_min = 1,
674
		.channels_max = 32,
675 676 677
		.rate_min = 8000,
		.rate_max = 192000,
		.rates = SNDRV_PCM_RATE_KNOT,
678 679 680
		.formats = FSL_SAI_FORMATS,
	},
	.capture = {
681
		.stream_name = "CPU-Capture",
682
		.channels_min = 1,
683
		.channels_max = 32,
684 685 686
		.rate_min = 8000,
		.rate_max = 192000,
		.rates = SNDRV_PCM_RATE_KNOT,
687 688 689 690 691 692 693 694 695
		.formats = FSL_SAI_FORMATS,
	},
	.ops = &fsl_sai_pcm_dai_ops,
};

static const struct snd_soc_component_driver fsl_component = {
	.name           = "fsl-sai",
};

696 697 698 699 700 701
static struct reg_default fsl_sai_reg_defaults_ofs0[] = {
	{FSL_SAI_TCR1(0), 0},
	{FSL_SAI_TCR2(0), 0},
	{FSL_SAI_TCR3(0), 0},
	{FSL_SAI_TCR4(0), 0},
	{FSL_SAI_TCR5(0), 0},
702 703 704 705 706 707 708 709
	{FSL_SAI_TDR0, 0},
	{FSL_SAI_TDR1, 0},
	{FSL_SAI_TDR2, 0},
	{FSL_SAI_TDR3, 0},
	{FSL_SAI_TDR4, 0},
	{FSL_SAI_TDR5, 0},
	{FSL_SAI_TDR6, 0},
	{FSL_SAI_TDR7, 0},
710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739
	{FSL_SAI_TMR, 0},
	{FSL_SAI_RCR1(0), 0},
	{FSL_SAI_RCR2(0), 0},
	{FSL_SAI_RCR3(0), 0},
	{FSL_SAI_RCR4(0), 0},
	{FSL_SAI_RCR5(0), 0},
	{FSL_SAI_RMR, 0},
};

static struct reg_default fsl_sai_reg_defaults_ofs8[] = {
	{FSL_SAI_TCR1(8), 0},
	{FSL_SAI_TCR2(8), 0},
	{FSL_SAI_TCR3(8), 0},
	{FSL_SAI_TCR4(8), 0},
	{FSL_SAI_TCR5(8), 0},
	{FSL_SAI_TDR0, 0},
	{FSL_SAI_TDR1, 0},
	{FSL_SAI_TDR2, 0},
	{FSL_SAI_TDR3, 0},
	{FSL_SAI_TDR4, 0},
	{FSL_SAI_TDR5, 0},
	{FSL_SAI_TDR6, 0},
	{FSL_SAI_TDR7, 0},
	{FSL_SAI_TMR, 0},
	{FSL_SAI_RCR1(8), 0},
	{FSL_SAI_RCR2(8), 0},
	{FSL_SAI_RCR3(8), 0},
	{FSL_SAI_RCR4(8), 0},
	{FSL_SAI_RCR5(8), 0},
	{FSL_SAI_RMR, 0},
740 741
};

742 743
static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg)
{
744 745 746 747 748 749 750 751 752
	struct fsl_sai *sai = dev_get_drvdata(dev);
	unsigned int ofs = sai->soc_data->reg_offset;

	if (reg >= FSL_SAI_TCSR(ofs) && reg <= FSL_SAI_TCR5(ofs))
		return true;

	if (reg >= FSL_SAI_RCSR(ofs) && reg <= FSL_SAI_RCR5(ofs))
		return true;

753
	switch (reg) {
754 755 756 757 758 759 760 761
	case FSL_SAI_TFR0:
	case FSL_SAI_TFR1:
	case FSL_SAI_TFR2:
	case FSL_SAI_TFR3:
	case FSL_SAI_TFR4:
	case FSL_SAI_TFR5:
	case FSL_SAI_TFR6:
	case FSL_SAI_TFR7:
762
	case FSL_SAI_TMR:
763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778
	case FSL_SAI_RDR0:
	case FSL_SAI_RDR1:
	case FSL_SAI_RDR2:
	case FSL_SAI_RDR3:
	case FSL_SAI_RDR4:
	case FSL_SAI_RDR5:
	case FSL_SAI_RDR6:
	case FSL_SAI_RDR7:
	case FSL_SAI_RFR0:
	case FSL_SAI_RFR1:
	case FSL_SAI_RFR2:
	case FSL_SAI_RFR3:
	case FSL_SAI_RFR4:
	case FSL_SAI_RFR5:
	case FSL_SAI_RFR6:
	case FSL_SAI_RFR7:
779 780 781 782 783 784 785 786 787
	case FSL_SAI_RMR:
		return true;
	default:
		return false;
	}
}

static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg)
{
788 789 790 791 792 793
	struct fsl_sai *sai = dev_get_drvdata(dev);
	unsigned int ofs = sai->soc_data->reg_offset;

	if (reg == FSL_SAI_TCSR(ofs) || reg == FSL_SAI_RCSR(ofs))
		return true;

794
	switch (reg) {
795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818
	case FSL_SAI_TFR0:
	case FSL_SAI_TFR1:
	case FSL_SAI_TFR2:
	case FSL_SAI_TFR3:
	case FSL_SAI_TFR4:
	case FSL_SAI_TFR5:
	case FSL_SAI_TFR6:
	case FSL_SAI_TFR7:
	case FSL_SAI_RFR0:
	case FSL_SAI_RFR1:
	case FSL_SAI_RFR2:
	case FSL_SAI_RFR3:
	case FSL_SAI_RFR4:
	case FSL_SAI_RFR5:
	case FSL_SAI_RFR6:
	case FSL_SAI_RFR7:
	case FSL_SAI_RDR0:
	case FSL_SAI_RDR1:
	case FSL_SAI_RDR2:
	case FSL_SAI_RDR3:
	case FSL_SAI_RDR4:
	case FSL_SAI_RDR5:
	case FSL_SAI_RDR6:
	case FSL_SAI_RDR7:
819 820 821 822 823 824 825 826
		return true;
	default:
		return false;
	}
}

static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg)
{
827 828 829 830 831 832 833 834 835
	struct fsl_sai *sai = dev_get_drvdata(dev);
	unsigned int ofs = sai->soc_data->reg_offset;

	if (reg >= FSL_SAI_TCSR(ofs) && reg <= FSL_SAI_TCR5(ofs))
		return true;

	if (reg >= FSL_SAI_RCSR(ofs) && reg <= FSL_SAI_RCR5(ofs))
		return true;

836
	switch (reg) {
837 838 839 840 841 842 843 844
	case FSL_SAI_TDR0:
	case FSL_SAI_TDR1:
	case FSL_SAI_TDR2:
	case FSL_SAI_TDR3:
	case FSL_SAI_TDR4:
	case FSL_SAI_TDR5:
	case FSL_SAI_TDR6:
	case FSL_SAI_TDR7:
845 846 847 848 849 850 851 852
	case FSL_SAI_TMR:
	case FSL_SAI_RMR:
		return true;
	default:
		return false;
	}
}

853
static struct regmap_config fsl_sai_regmap_config = {
854 855 856
	.reg_bits = 32,
	.reg_stride = 4,
	.val_bits = 32,
857
	.fast_io = true,
858 859

	.max_register = FSL_SAI_RMR,
860 861
	.reg_defaults = fsl_sai_reg_defaults_ofs0,
	.num_reg_defaults = ARRAY_SIZE(fsl_sai_reg_defaults_ofs0),
862 863 864
	.readable_reg = fsl_sai_readable_reg,
	.volatile_reg = fsl_sai_volatile_reg,
	.writeable_reg = fsl_sai_writeable_reg,
865
	.cache_type = REGCACHE_FLAT,
866 867
};

868 869
static int fsl_sai_probe(struct platform_device *pdev)
{
870
	struct device_node *np = pdev->dev.of_node;
871
	struct fsl_sai *sai;
872
	struct regmap *gpr;
873
	struct resource *res;
874
	void __iomem *base;
875 876
	char tmp[8];
	int irq, ret, i;
877
	int index;
878 879 880 881 882

	sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL);
	if (!sai)
		return -ENOMEM;

883
	sai->pdev = pdev;
L
Lucas Stach 已提交
884
	sai->soc_data = of_device_get_match_data(&pdev->dev);
885

886
	sai->is_lsb_first = of_property_read_bool(np, "lsb-first");
887

888
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
889 890 891 892
	base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(base))
		return PTR_ERR(base);

893 894 895 896 897 898
	if (sai->soc_data->reg_offset == 8) {
		fsl_sai_regmap_config.reg_defaults = fsl_sai_reg_defaults_ofs8;
		fsl_sai_regmap_config.num_reg_defaults =
			ARRAY_SIZE(fsl_sai_reg_defaults_ofs8);
	}

899
	sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
900 901 902 903 904 905
			"bus", base, &fsl_sai_regmap_config);

	/* Compatible with old DTB cases */
	if (IS_ERR(sai->regmap))
		sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
				"sai", base, &fsl_sai_regmap_config);
906 907 908
	if (IS_ERR(sai->regmap)) {
		dev_err(&pdev->dev, "regmap init failed\n");
		return PTR_ERR(sai->regmap);
909 910
	}

911 912 913 914 915 916 917 918
	/* No error out for old DTB cases but only mark the clock NULL */
	sai->bus_clk = devm_clk_get(&pdev->dev, "bus");
	if (IS_ERR(sai->bus_clk)) {
		dev_err(&pdev->dev, "failed to get bus clock: %ld\n",
				PTR_ERR(sai->bus_clk));
		sai->bus_clk = NULL;
	}

919 920 921
	sai->mclk_clk[0] = sai->bus_clk;
	for (i = 1; i < FSL_SAI_MCLK_MAX; i++) {
		sprintf(tmp, "mclk%d", i);
922 923 924 925 926 927 928 929
		sai->mclk_clk[i] = devm_clk_get(&pdev->dev, tmp);
		if (IS_ERR(sai->mclk_clk[i])) {
			dev_err(&pdev->dev, "failed to get mclk%d clock: %ld\n",
					i + 1, PTR_ERR(sai->mclk_clk[i]));
			sai->mclk_clk[i] = NULL;
		}
	}

930
	irq = platform_get_irq(pdev, 0);
931
	if (irq < 0)
932 933 934 935 936 937 938 939
		return irq;

	ret = devm_request_irq(&pdev->dev, irq, fsl_sai_isr, 0, np->name, sai);
	if (ret) {
		dev_err(&pdev->dev, "failed to claim irq %u\n", irq);
		return ret;
	}

940 941 942 943 944 945 946
	/* Sync Tx with Rx as default by following old DT binding */
	sai->synchronous[RX] = true;
	sai->synchronous[TX] = false;
	fsl_sai_dai.symmetric_rates = 1;
	fsl_sai_dai.symmetric_channels = 1;
	fsl_sai_dai.symmetric_samplebits = 1;

947 948 949 950 951 952 953
	if (of_find_property(np, "fsl,sai-synchronous-rx", NULL) &&
	    of_find_property(np, "fsl,sai-asynchronous", NULL)) {
		/* error out if both synchronous and asynchronous are present */
		dev_err(&pdev->dev, "invalid binding for synchronous mode\n");
		return -EINVAL;
	}

954 955 956 957 958 959 960 961 962 963 964 965 966
	if (of_find_property(np, "fsl,sai-synchronous-rx", NULL)) {
		/* Sync Rx with Tx */
		sai->synchronous[RX] = false;
		sai->synchronous[TX] = true;
	} else if (of_find_property(np, "fsl,sai-asynchronous", NULL)) {
		/* Discard all settings for asynchronous mode */
		sai->synchronous[RX] = false;
		sai->synchronous[TX] = false;
		fsl_sai_dai.symmetric_rates = 0;
		fsl_sai_dai.symmetric_channels = 0;
		fsl_sai_dai.symmetric_samplebits = 0;
	}

967
	if (of_find_property(np, "fsl,sai-mclk-direction-output", NULL) &&
F
Fabio Estevam 已提交
968
	    of_device_is_compatible(np, "fsl,imx6ul-sai")) {
969 970 971 972 973 974 975 976 977 978 979 980 981 982
		gpr = syscon_regmap_lookup_by_compatible("fsl,imx6ul-iomuxc-gpr");
		if (IS_ERR(gpr)) {
			dev_err(&pdev->dev, "cannot find iomuxc registers\n");
			return PTR_ERR(gpr);
		}

		index = of_alias_get_id(np, "sai");
		if (index < 0)
			return index;

		regmap_update_bits(gpr, IOMUXC_GPR1, MCLK_DIR(index),
				   MCLK_DIR(index));
	}

983 984
	sai->dma_params_rx.addr = res->start + FSL_SAI_RDR0;
	sai->dma_params_tx.addr = res->start + FSL_SAI_TDR0;
985 986 987 988 989
	sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX;
	sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX;

	platform_set_drvdata(pdev, sai);

990 991
	pm_runtime_enable(&pdev->dev);

992 993 994 995 996
	ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component,
			&fsl_sai_dai, 1);
	if (ret)
		return ret;

L
Lucas Stach 已提交
997
	if (sai->soc_data->use_imx_pcm)
998
		return imx_pcm_dma_init(pdev, IMX_SAI_DMABUF_SIZE);
999
	else
1000
		return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
1001 1002
}

1003 1004 1005
static int fsl_sai_remove(struct platform_device *pdev)
{
	pm_runtime_disable(&pdev->dev);
1006 1007

	return 0;
1008 1009
}

L
Lucas Stach 已提交
1010 1011
static const struct fsl_sai_soc_data fsl_sai_vf610_data = {
	.use_imx_pcm = false,
1012
	.fifo_depth = 32,
1013
	.reg_offset = 0,
L
Lucas Stach 已提交
1014 1015 1016 1017
};

static const struct fsl_sai_soc_data fsl_sai_imx6sx_data = {
	.use_imx_pcm = true,
1018
	.fifo_depth = 32,
1019
	.reg_offset = 0,
L
Lucas Stach 已提交
1020 1021
};

1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033
static const struct fsl_sai_soc_data fsl_sai_imx7ulp_data = {
	.use_imx_pcm = true,
	.fifo_depth = 16,
	.reg_offset = 8,
};

static const struct fsl_sai_soc_data fsl_sai_imx8mq_data = {
	.use_imx_pcm = true,
	.fifo_depth = 128,
	.reg_offset = 8,
};

1034 1035 1036 1037 1038 1039
static const struct fsl_sai_soc_data fsl_sai_imx8qm_data = {
	.use_imx_pcm = true,
	.fifo_depth = 64,
	.reg_offset = 0,
};

1040
static const struct of_device_id fsl_sai_ids[] = {
L
Lucas Stach 已提交
1041 1042 1043
	{ .compatible = "fsl,vf610-sai", .data = &fsl_sai_vf610_data },
	{ .compatible = "fsl,imx6sx-sai", .data = &fsl_sai_imx6sx_data },
	{ .compatible = "fsl,imx6ul-sai", .data = &fsl_sai_imx6sx_data },
1044 1045
	{ .compatible = "fsl,imx7ulp-sai", .data = &fsl_sai_imx7ulp_data },
	{ .compatible = "fsl,imx8mq-sai", .data = &fsl_sai_imx8mq_data },
1046
	{ .compatible = "fsl,imx8qm-sai", .data = &fsl_sai_imx8qm_data },
1047 1048
	{ /* sentinel */ }
};
1049
MODULE_DEVICE_TABLE(of, fsl_sai_ids);
1050

1051 1052
#ifdef CONFIG_PM
static int fsl_sai_runtime_suspend(struct device *dev)
1053 1054 1055
{
	struct fsl_sai *sai = dev_get_drvdata(dev);

1056 1057 1058 1059 1060 1061 1062 1063
	if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE))
		clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[0]]);

	if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK))
		clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[1]]);

	clk_disable_unprepare(sai->bus_clk);

1064 1065 1066 1067 1068 1069
	regcache_cache_only(sai->regmap, true);
	regcache_mark_dirty(sai->regmap);

	return 0;
}

1070
static int fsl_sai_runtime_resume(struct device *dev)
1071 1072
{
	struct fsl_sai *sai = dev_get_drvdata(dev);
1073
	unsigned int ofs = sai->soc_data->reg_offset;
1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092
	int ret;

	ret = clk_prepare_enable(sai->bus_clk);
	if (ret) {
		dev_err(dev, "failed to enable bus clock: %d\n", ret);
		return ret;
	}

	if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK)) {
		ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[1]]);
		if (ret)
			goto disable_bus_clk;
	}

	if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE)) {
		ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[0]]);
		if (ret)
			goto disable_tx_clk;
	}
1093 1094

	regcache_cache_only(sai->regmap, false);
1095 1096
	regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR);
	regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR);
1097
	usleep_range(1000, 2000);
1098 1099
	regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0);
	regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0);
1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116

	ret = regcache_sync(sai->regmap);
	if (ret)
		goto disable_rx_clk;

	return 0;

disable_rx_clk:
	if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE))
		clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[0]]);
disable_tx_clk:
	if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK))
		clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[1]]);
disable_bus_clk:
	clk_disable_unprepare(sai->bus_clk);

	return ret;
1117
}
1118
#endif /* CONFIG_PM */
1119 1120

static const struct dev_pm_ops fsl_sai_pm_ops = {
1121 1122 1123 1124
	SET_RUNTIME_PM_OPS(fsl_sai_runtime_suspend,
			   fsl_sai_runtime_resume, NULL)
	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
				pm_runtime_force_resume)
1125 1126
};

1127 1128
static struct platform_driver fsl_sai_driver = {
	.probe = fsl_sai_probe,
1129
	.remove = fsl_sai_remove,
1130 1131
	.driver = {
		.name = "fsl-sai",
1132
		.pm = &fsl_sai_pm_ops,
1133 1134 1135 1136 1137 1138 1139 1140 1141
		.of_match_table = fsl_sai_ids,
	},
};
module_platform_driver(fsl_sai_driver);

MODULE_DESCRIPTION("Freescale Soc SAI Interface");
MODULE_AUTHOR("Xiubo Li, <Li.Xiubo@freescale.com>");
MODULE_ALIAS("platform:fsl-sai");
MODULE_LICENSE("GPL");