fsl_sai.c 31.8 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 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
/**
 * fsl_sai_dir_is_synced - Check if stream is synced by the opposite stream
 *
 * SAI supports synchronous mode using bit/frame clocks of either Transmitter's
 * or Receiver's for both streams. This function is used to check if clocks of
 * the stream's are synced by the opposite stream.
 *
 * @sai: SAI context
 * @dir: stream direction
 */
static inline bool fsl_sai_dir_is_synced(struct fsl_sai *sai, int dir)
{
	int adir = (dir == TX) ? RX : TX;

	/* current dir in async mode while opposite dir in sync mode */
	return !sai->synchronous[dir] && sai->synchronous[adir];
}

58 59 60
static irqreturn_t fsl_sai_isr(int irq, void *devid)
{
	struct fsl_sai *sai = (struct fsl_sai *)devid;
61
	unsigned int ofs = sai->soc_data->reg_offset;
62
	struct device *dev = &sai->pdev->dev;
63 64 65 66 67 68 69 70
	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.
	 */
71 72 73
	mask = (FSL_SAI_FLAGS >> FSL_SAI_CSR_xIE_SHIFT) << FSL_SAI_CSR_xF_SHIFT;

	/* Tx IRQ */
74
	regmap_read(sai->regmap, FSL_SAI_TCSR(ofs), &xcsr);
75 76 77 78 79 80
	flags = xcsr & mask;

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

82
	if (flags & FSL_SAI_CSR_WSF)
83 84
		dev_dbg(dev, "isr: Start of Tx word detected\n");

85
	if (flags & FSL_SAI_CSR_SEF)
86
		dev_dbg(dev, "isr: Tx Frame sync error detected\n");
87

88
	if (flags & FSL_SAI_CSR_FEF) {
89
		dev_dbg(dev, "isr: Transmit underrun detected\n");
90 91 92 93
		/* FIFO reset for safety */
		xcsr |= FSL_SAI_CSR_FR;
	}

94
	if (flags & FSL_SAI_CSR_FWF)
95 96
		dev_dbg(dev, "isr: Enabled transmit FIFO is empty\n");

97
	if (flags & FSL_SAI_CSR_FRF)
98 99
		dev_dbg(dev, "isr: Transmit FIFO watermark has been reached\n");

100 101 102 103
	flags &= FSL_SAI_CSR_xF_W_MASK;
	xcsr &= ~FSL_SAI_CSR_xF_MASK;

	if (flags)
104
		regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), flags | xcsr);
105

106
irq_rx:
107
	/* Rx IRQ */
108
	regmap_read(sai->regmap, FSL_SAI_RCSR(ofs), &xcsr);
109
	flags = xcsr & mask;
110

111 112 113 114 115 116
	if (flags)
		irq_none = false;
	else
		goto out;

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

119
	if (flags & FSL_SAI_CSR_SEF)
120
		dev_dbg(dev, "isr: Rx Frame sync error detected\n");
121

122
	if (flags & FSL_SAI_CSR_FEF) {
123
		dev_dbg(dev, "isr: Receive overflow detected\n");
124 125 126 127
		/* FIFO reset for safety */
		xcsr |= FSL_SAI_CSR_FR;
	}

128
	if (flags & FSL_SAI_CSR_FWF)
129 130
		dev_dbg(dev, "isr: Enabled receive FIFO is full\n");

131
	if (flags & FSL_SAI_CSR_FRF)
132 133
		dev_dbg(dev, "isr: Receive FIFO watermark has been reached\n");

134 135
	flags &= FSL_SAI_CSR_xF_W_MASK;
	xcsr &= ~FSL_SAI_CSR_xF_MASK;
136

137
	if (flags)
138
		regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), flags | xcsr);
139 140 141 142 143 144

out:
	if (irq_none)
		return IRQ_NONE;
	else
		return IRQ_HANDLED;
145 146
}

147 148 149 150 151 152 153 154 155 156 157
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;
}

158 159 160 161 162 163 164 165 166 167
static int fsl_sai_set_dai_bclk_ratio(struct snd_soc_dai *dai,
				      unsigned int ratio)
{
	struct fsl_sai *sai = snd_soc_dai_get_drvdata(dai);

	sai->bclk_ratio = ratio;

	return 0;
}

168 169 170 171
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);
172
	unsigned int ofs = sai->soc_data->reg_offset;
173 174
	bool tx = fsl_dir == FSL_FMT_TRANSMITTER;
	u32 val_cr2 = 0;
X
Xiubo Li 已提交
175

176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
	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 已提交
192

193
	regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
194
			   FSL_SAI_CR2_MSEL_MASK, val_cr2);
195 196 197 198 199 200 201

	return 0;
}

static int fsl_sai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
		int clk_id, unsigned int freq, int dir)
{
202
	int ret;
203 204 205 206 207 208 209

	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) {
210
		dev_err(cpu_dai->dev, "Cannot set tx sysclk: %d\n", ret);
211
		return ret;
212 213 214 215
	}

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

219
	return ret;
220 221 222 223 224 225
}

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);
226
	unsigned int ofs = sai->soc_data->reg_offset;
227 228
	bool tx = fsl_dir == FSL_FMT_TRANSMITTER;
	u32 val_cr2 = 0, val_cr4 = 0;
229

230
	if (!sai->is_lsb_first)
231
		val_cr4 |= FSL_SAI_CR4_MF;
232

233
	/* DAI mode */
234 235
	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
	case SND_SOC_DAIFMT_I2S:
236 237 238 239 240 241
		/*
		 * 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.
		 */
242
		val_cr2 |= FSL_SAI_CR2_BCP;
243 244 245
		val_cr4 |= FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP;
		break;
	case SND_SOC_DAIFMT_LEFT_J:
246 247 248 249
		/*
		 * Frame high, one word length for frame sync,
		 * frame sync asserts with the first bit of the frame.
		 */
250
		val_cr2 |= FSL_SAI_CR2_BCP;
251
		break;
252 253 254 255 256 257 258
	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.
		 */
259
		val_cr2 |= FSL_SAI_CR2_BCP;
260 261 262 263 264 265 266 267
		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.
		 */
268
		val_cr2 |= FSL_SAI_CR2_BCP;
269 270
		sai->is_dsp_mode = true;
		break;
271 272
	case SND_SOC_DAIFMT_RIGHT_J:
		/* To be done */
273 274 275 276
	default:
		return -EINVAL;
	}

277
	/* DAI clock inversion */
278 279
	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
	case SND_SOC_DAIFMT_IB_IF:
280 281 282
		/* Invert both clocks */
		val_cr2 ^= FSL_SAI_CR2_BCP;
		val_cr4 ^= FSL_SAI_CR4_FSP;
283 284
		break;
	case SND_SOC_DAIFMT_IB_NF:
285 286
		/* Invert bit clock */
		val_cr2 ^= FSL_SAI_CR2_BCP;
287 288
		break;
	case SND_SOC_DAIFMT_NB_IF:
289 290
		/* Invert frame clock */
		val_cr4 ^= FSL_SAI_CR4_FSP;
291 292
		break;
	case SND_SOC_DAIFMT_NB_NF:
293
		/* Nothing to do for both normal cases */
294 295 296 297 298
		break;
	default:
		return -EINVAL;
	}

299
	/* DAI clock master masks */
300 301 302 303
	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;
304
		sai->is_slave_mode = false;
305 306
		break;
	case SND_SOC_DAIFMT_CBM_CFM:
307
		sai->is_slave_mode = true;
308
		break;
309 310
	case SND_SOC_DAIFMT_CBS_CFM:
		val_cr2 |= FSL_SAI_CR2_BCD_MSTR;
311
		sai->is_slave_mode = false;
312 313 314
		break;
	case SND_SOC_DAIFMT_CBM_CFS:
		val_cr4 |= FSL_SAI_CR4_FSD_MSTR;
315
		sai->is_slave_mode = true;
316
		break;
317 318 319 320
	default:
		return -EINVAL;
	}

321
	regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
322
			   FSL_SAI_CR2_BCP | FSL_SAI_CR2_BCD_MSTR, val_cr2);
323
	regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
324 325
			   FSL_SAI_CR4_MF | FSL_SAI_CR4_FSE |
			   FSL_SAI_CR4_FSP | FSL_SAI_CR4_FSD_MSTR, val_cr4);
326 327 328 329 330 331

	return 0;
}

static int fsl_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
{
332
	int ret;
333 334 335

	ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_TRANSMITTER);
	if (ret) {
336
		dev_err(cpu_dai->dev, "Cannot set tx format: %d\n", ret);
337
		return ret;
338 339 340
	}

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

344
	return ret;
345 346
}

347 348 349
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);
350
	unsigned int ofs = sai->soc_data->reg_offset;
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
	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;
	}

401 402 403 404 405 406 407 408 409 410 411 412
	/*
	 * 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])) {
413
		regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs),
414 415
				   FSL_SAI_CR2_MSEL_MASK,
				   FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
416
		regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs),
417
				   FSL_SAI_CR2_DIV_MASK, savediv - 1);
418 419
	} else if ((sai->synchronous[RX] && !sai->synchronous[TX]) ||
		   (tx && !sai->synchronous[TX])) {
420
		regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs),
421 422
				   FSL_SAI_CR2_MSEL_MASK,
				   FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
423
		regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs),
424 425 426 427 428 429 430 431 432
				   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;
}

433 434 435 436
static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
		struct snd_pcm_hw_params *params,
		struct snd_soc_dai *cpu_dai)
{
437
	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
438
	unsigned int ofs = sai->soc_data->reg_offset;
439
	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
440
	unsigned int channels = params_channels(params);
441
	u32 word_width = params_width(params);
442
	u32 val_cr4 = 0, val_cr5 = 0;
443 444
	u32 slots = (channels == 1) ? 2 : channels;
	u32 slot_width = word_width;
445 446
	int ret;

447 448 449 450 451 452
	if (sai->slots)
		slots = sai->slots;

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

453
	if (!sai->is_slave_mode) {
454 455 456 457 458 459 460 461
		if (sai->bclk_ratio)
			ret = fsl_sai_set_bclk(cpu_dai, tx,
					       sai->bclk_ratio *
					       params_rate(params));
		else
			ret = fsl_sai_set_bclk(cpu_dai, tx,
					       slots * slot_width *
					       params_rate(params));
462 463 464 465 466 467 468 469 470 471 472 473
		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);
		}
	}
474

475
	if (!sai->is_dsp_mode)
476
		val_cr4 |= FSL_SAI_CR4_SYWD(slot_width);
477

478 479
	val_cr5 |= FSL_SAI_CR5_WNW(slot_width);
	val_cr5 |= FSL_SAI_CR5_W0W(slot_width);
480

481
	if (sai->is_lsb_first)
482
		val_cr5 |= FSL_SAI_CR5_FBT(0);
483 484
	else
		val_cr5 |= FSL_SAI_CR5_FBT(word_width - 1);
485

486
	val_cr4 |= FSL_SAI_CR4_FRSZ(slots);
487

488 489 490
	/*
	 * 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),
491
	 * RCR5(TCR5) for playback(capture), or there will be sync error.
492 493 494 495
	 */

	if (!sai->is_slave_mode) {
		if (!sai->synchronous[TX] && sai->synchronous[RX] && !tx) {
496
			regmap_update_bits(sai->regmap, FSL_SAI_TCR4(ofs),
497 498
				FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
				val_cr4);
499
			regmap_update_bits(sai->regmap, FSL_SAI_TCR5(ofs),
500 501 502
				FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
				FSL_SAI_CR5_FBT_MASK, val_cr5);
		} else if (!sai->synchronous[RX] && sai->synchronous[TX] && tx) {
503
			regmap_update_bits(sai->regmap, FSL_SAI_RCR4(ofs),
504 505
				FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
				val_cr4);
506
			regmap_update_bits(sai->regmap, FSL_SAI_RCR5(ofs),
507 508 509 510
				FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
				FSL_SAI_CR5_FBT_MASK, val_cr5);
		}
	}
511

512
	regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
513 514
			   FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
			   val_cr4);
515
	regmap_update_bits(sai->regmap, FSL_SAI_xCR5(tx, ofs),
516 517 518
			   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));
519 520 521 522

	return 0;
}

523 524 525 526 527 528 529 530 531 532 533 534 535 536 537
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;
}

538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569
static void fsl_sai_config_disable(struct fsl_sai *sai, int dir)
{
	unsigned int ofs = sai->soc_data->reg_offset;
	bool tx = dir == TX;
	u32 xcsr, count = 100;

	regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
			   FSL_SAI_CSR_TERE, 0);

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

	regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
			   FSL_SAI_CSR_FR, FSL_SAI_CSR_FR);

	/*
	 * 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 */
		regmap_write(sai->regmap, FSL_SAI_xCSR(tx, ofs), FSL_SAI_CSR_SR);
		/* Clear SR bit to finish the reset */
		regmap_write(sai->regmap, FSL_SAI_xCSR(tx, ofs), 0);
	}
}
570

571 572 573 574
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);
575 576
	unsigned int ofs = sai->soc_data->reg_offset;

577
	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
578 579 580
	int adir = tx ? RX : TX;
	int dir = tx ? TX : RX;
	u32 xcsr;
581

582
	/*
583 584 585
	 * 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.
586
	 */
587 588 589
	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,
590
			   sai->synchronous[RX] ? FSL_SAI_CR2_SYNC : 0);
591

592 593 594 595
	/*
	 * It is recommended that the transmitter is the last enabled
	 * and the first disabled.
	 */
596 597 598 599
	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
	case SNDRV_PCM_TRIGGER_RESUME:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
600
		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
601 602
				   FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE);

603
		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
604
				   FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
605 606 607 608 609 610 611 612 613 614 615 616 617 618
		/*
		 * Enable the opposite direction for synchronous mode
		 * 1. Tx sync with Rx: only set RE for Rx; set TE & RE for Tx
		 * 2. Rx sync with Tx: only set TE for Tx; set RE & TE for Rx
		 *
		 * RM recommends to enable RE after TE for case 1 and to enable
		 * TE after RE for case 2, but we here may not always guarantee
		 * that happens: "arecord 1.wav; aplay 2.wav" in case 1 enables
		 * TE after RE, which is against what RM recommends but should
		 * be safe to do, judging by years of testing results.
		 */
		if (fsl_sai_dir_is_synced(sai, adir))
			regmap_update_bits(sai->regmap, FSL_SAI_xCSR((!tx), ofs),
					   FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
619

620
		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
621
				   FSL_SAI_CSR_xIE_MASK, FSL_SAI_FLAGS);
622 623 624 625
		break;
	case SNDRV_PCM_TRIGGER_STOP:
	case SNDRV_PCM_TRIGGER_SUSPEND:
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
626
		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
627
				   FSL_SAI_CSR_FRDE, 0);
628
		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
629
				   FSL_SAI_CSR_xIE_MASK, 0);
630

631
		/* Check if the opposite FRDE is also disabled */
632
		regmap_read(sai->regmap, FSL_SAI_xCSR(!tx, ofs), &xcsr);
633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649

		/*
		 * If opposite stream provides clocks for synchronous mode and
		 * it is inactive, disable it before disabling the current one
		 */
		if (fsl_sai_dir_is_synced(sai, adir) && !(xcsr & FSL_SAI_CSR_FRDE))
			fsl_sai_config_disable(sai, adir);

		/*
		 * Disable current stream if either of:
		 * 1. current stream doesn't provide clocks for synchronous mode
		 * 2. current stream provides clocks for synchronous mode but no
		 *    more stream is active.
		 */
		if (!fsl_sai_dir_is_synced(sai, dir) || !(xcsr & FSL_SAI_CSR_FRDE))
			fsl_sai_config_disable(sai, dir);

650 651 652 653 654 655 656 657 658 659 660 661
		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);
662
	unsigned int ofs = sai->soc_data->reg_offset;
663
	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
664 665
	int ret;

666
	regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs),
667
			   FSL_SAI_CR3_TRCE_MASK,
668 669
			   FSL_SAI_CR3_TRCE);

670 671 672 673 674 675 676 677 678 679
	/*
	 * EDMA controller needs period size to be a multiple of
	 * tx/rx maxburst
	 */
	if (sai->soc_data->use_edma)
		snd_pcm_hw_constraint_step(substream->runtime, 0,
					   SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
					   tx ? sai->dma_params_tx.maxburst :
					   sai->dma_params_rx.maxburst);

680 681 682 683
	ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
			SNDRV_PCM_HW_PARAM_RATE, &fsl_sai_rate_constraints);

	return ret;
684 685 686 687 688 689
}

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);
690
	unsigned int ofs = sai->soc_data->reg_offset;
691
	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
692

693
	regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs),
694
			   FSL_SAI_CR3_TRCE_MASK, 0);
695 696 697
}

static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
698
	.set_bclk_ratio	= fsl_sai_set_dai_bclk_ratio,
699 700
	.set_sysclk	= fsl_sai_set_dai_sysclk,
	.set_fmt	= fsl_sai_set_dai_fmt,
701
	.set_tdm_slot	= fsl_sai_set_dai_tdm_slot,
702
	.hw_params	= fsl_sai_hw_params,
703
	.hw_free	= fsl_sai_hw_free,
704 705 706 707 708 709 710 711
	.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);
712
	unsigned int ofs = sai->soc_data->reg_offset;
713

714
	/* Software Reset for both Tx and Rx */
715 716
	regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR);
	regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR);
717
	/* Clear SR bit to finish the reset */
718 719
	regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0);
	regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0);
720

721
	regmap_update_bits(sai->regmap, FSL_SAI_TCR1(ofs),
722
			   FSL_SAI_CR1_RFW_MASK(sai->soc_data->fifo_depth),
723
			   sai->soc_data->fifo_depth - FSL_SAI_MAXBURST_TX);
724
	regmap_update_bits(sai->regmap, FSL_SAI_RCR1(ofs),
725 726
			   FSL_SAI_CR1_RFW_MASK(sai->soc_data->fifo_depth),
			   FSL_SAI_MAXBURST_RX - 1);
727

728 729
	snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx,
				&sai->dma_params_rx);
730 731 732 733 734 735 736 737 738

	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 = {
739
		.stream_name = "CPU-Playback",
740
		.channels_min = 1,
741
		.channels_max = 32,
742 743 744
		.rate_min = 8000,
		.rate_max = 192000,
		.rates = SNDRV_PCM_RATE_KNOT,
745 746 747
		.formats = FSL_SAI_FORMATS,
	},
	.capture = {
748
		.stream_name = "CPU-Capture",
749
		.channels_min = 1,
750
		.channels_max = 32,
751 752 753
		.rate_min = 8000,
		.rate_max = 192000,
		.rates = SNDRV_PCM_RATE_KNOT,
754 755 756 757 758 759 760 761 762
		.formats = FSL_SAI_FORMATS,
	},
	.ops = &fsl_sai_pcm_dai_ops,
};

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

763 764 765 766 767 768
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},
769 770 771 772 773 774 775 776
	{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},
777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806
	{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},
807 808
};

809 810
static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg)
{
811 812 813 814 815 816 817 818 819
	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;

820
	switch (reg) {
821 822 823 824 825 826 827 828
	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:
829
	case FSL_SAI_TMR:
830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845
	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:
846 847 848 849 850 851 852 853 854
	case FSL_SAI_RMR:
		return true;
	default:
		return false;
	}
}

static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg)
{
855 856 857 858 859 860
	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;

861
	switch (reg) {
862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885
	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:
886 887 888 889 890 891 892 893
		return true;
	default:
		return false;
	}
}

static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg)
{
894 895 896 897 898 899 900 901 902
	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;

903
	switch (reg) {
904 905 906 907 908 909 910 911
	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:
912 913 914 915 916 917 918 919
	case FSL_SAI_TMR:
	case FSL_SAI_RMR:
		return true;
	default:
		return false;
	}
}

920
static struct regmap_config fsl_sai_regmap_config = {
921 922 923
	.reg_bits = 32,
	.reg_stride = 4,
	.val_bits = 32,
924
	.fast_io = true,
925 926

	.max_register = FSL_SAI_RMR,
927 928
	.reg_defaults = fsl_sai_reg_defaults_ofs0,
	.num_reg_defaults = ARRAY_SIZE(fsl_sai_reg_defaults_ofs0),
929 930 931
	.readable_reg = fsl_sai_readable_reg,
	.volatile_reg = fsl_sai_volatile_reg,
	.writeable_reg = fsl_sai_writeable_reg,
932
	.cache_type = REGCACHE_FLAT,
933 934
};

935 936
static int fsl_sai_probe(struct platform_device *pdev)
{
937
	struct device_node *np = pdev->dev.of_node;
938
	struct fsl_sai *sai;
939
	struct regmap *gpr;
940
	struct resource *res;
941
	void __iomem *base;
942 943
	char tmp[8];
	int irq, ret, i;
944
	int index;
945 946 947 948 949

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

950
	sai->pdev = pdev;
L
Lucas Stach 已提交
951
	sai->soc_data = of_device_get_match_data(&pdev->dev);
952

953
	sai->is_lsb_first = of_property_read_bool(np, "lsb-first");
954

955
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
956 957 958 959
	base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(base))
		return PTR_ERR(base);

960 961 962 963 964 965
	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);
	}

966
	sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
967 968 969 970 971 972
			"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);
973 974 975
	if (IS_ERR(sai->regmap)) {
		dev_err(&pdev->dev, "regmap init failed\n");
		return PTR_ERR(sai->regmap);
976 977
	}

978 979 980 981 982 983 984 985
	/* 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;
	}

986 987 988
	sai->mclk_clk[0] = sai->bus_clk;
	for (i = 1; i < FSL_SAI_MCLK_MAX; i++) {
		sprintf(tmp, "mclk%d", i);
989 990 991 992 993 994 995 996
		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;
		}
	}

997
	irq = platform_get_irq(pdev, 0);
998
	if (irq < 0)
999 1000
		return irq;

M
Michael Walle 已提交
1001 1002
	ret = devm_request_irq(&pdev->dev, irq, fsl_sai_isr, IRQF_SHARED,
			       np->name, sai);
1003 1004 1005 1006 1007
	if (ret) {
		dev_err(&pdev->dev, "failed to claim irq %u\n", irq);
		return ret;
	}

1008 1009 1010 1011 1012 1013 1014
	/* 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;

1015 1016 1017 1018 1019 1020 1021
	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;
	}

1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
	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;
	}

1035
	if (of_find_property(np, "fsl,sai-mclk-direction-output", NULL) &&
F
Fabio Estevam 已提交
1036
	    of_device_is_compatible(np, "fsl,imx6ul-sai")) {
1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050
		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));
	}

1051 1052
	sai->dma_params_rx.addr = res->start + FSL_SAI_RDR0;
	sai->dma_params_tx.addr = res->start + FSL_SAI_TDR0;
1053 1054 1055 1056 1057
	sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX;
	sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX;

	platform_set_drvdata(pdev, sai);

1058
	pm_runtime_enable(&pdev->dev);
1059
	regcache_cache_only(sai->regmap, true);
1060

1061 1062 1063
	ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component,
			&fsl_sai_dai, 1);
	if (ret)
1064
		goto err_pm_disable;
1065

1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
	if (sai->soc_data->use_imx_pcm) {
		ret = imx_pcm_dma_init(pdev, IMX_SAI_DMABUF_SIZE);
		if (ret)
			goto err_pm_disable;
	} else {
		ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
		if (ret)
			goto err_pm_disable;
	}

	return ret;

err_pm_disable:
	pm_runtime_disable(&pdev->dev);

	return ret;
1082 1083
}

1084 1085 1086
static int fsl_sai_remove(struct platform_device *pdev)
{
	pm_runtime_disable(&pdev->dev);
1087 1088

	return 0;
1089 1090
}

L
Lucas Stach 已提交
1091 1092
static const struct fsl_sai_soc_data fsl_sai_vf610_data = {
	.use_imx_pcm = false,
1093
	.use_edma = false,
1094
	.fifo_depth = 32,
1095
	.reg_offset = 0,
L
Lucas Stach 已提交
1096 1097 1098 1099
};

static const struct fsl_sai_soc_data fsl_sai_imx6sx_data = {
	.use_imx_pcm = true,
1100
	.use_edma = false,
1101
	.fifo_depth = 32,
1102
	.reg_offset = 0,
L
Lucas Stach 已提交
1103 1104
};

1105 1106
static const struct fsl_sai_soc_data fsl_sai_imx7ulp_data = {
	.use_imx_pcm = true,
1107
	.use_edma = false,
1108 1109 1110 1111 1112 1113
	.fifo_depth = 16,
	.reg_offset = 8,
};

static const struct fsl_sai_soc_data fsl_sai_imx8mq_data = {
	.use_imx_pcm = true,
1114
	.use_edma = false,
1115 1116 1117 1118
	.fifo_depth = 128,
	.reg_offset = 8,
};

1119 1120
static const struct fsl_sai_soc_data fsl_sai_imx8qm_data = {
	.use_imx_pcm = true,
1121
	.use_edma = true,
1122 1123 1124 1125
	.fifo_depth = 64,
	.reg_offset = 0,
};

1126
static const struct of_device_id fsl_sai_ids[] = {
L
Lucas Stach 已提交
1127 1128 1129
	{ .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 },
1130 1131
	{ .compatible = "fsl,imx7ulp-sai", .data = &fsl_sai_imx7ulp_data },
	{ .compatible = "fsl,imx8mq-sai", .data = &fsl_sai_imx8mq_data },
1132
	{ .compatible = "fsl,imx8qm-sai", .data = &fsl_sai_imx8qm_data },
1133 1134
	{ /* sentinel */ }
};
1135
MODULE_DEVICE_TABLE(of, fsl_sai_ids);
1136

1137 1138
#ifdef CONFIG_PM
static int fsl_sai_runtime_suspend(struct device *dev)
1139 1140 1141
{
	struct fsl_sai *sai = dev_get_drvdata(dev);

1142 1143 1144 1145 1146 1147 1148 1149
	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);

1150 1151 1152 1153 1154
	regcache_cache_only(sai->regmap, true);

	return 0;
}

1155
static int fsl_sai_runtime_resume(struct device *dev)
1156 1157
{
	struct fsl_sai *sai = dev_get_drvdata(dev);
1158
	unsigned int ofs = sai->soc_data->reg_offset;
1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177
	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;
	}
1178 1179

	regcache_cache_only(sai->regmap, false);
1180
	regcache_mark_dirty(sai->regmap);
1181 1182
	regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR);
	regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR);
1183
	usleep_range(1000, 2000);
1184 1185
	regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0);
	regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0);
1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202

	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;
1203
}
1204
#endif /* CONFIG_PM */
1205 1206

static const struct dev_pm_ops fsl_sai_pm_ops = {
1207 1208 1209 1210
	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)
1211 1212
};

1213 1214
static struct platform_driver fsl_sai_driver = {
	.probe = fsl_sai_probe,
1215
	.remove = fsl_sai_remove,
1216 1217
	.driver = {
		.name = "fsl-sai",
1218
		.pm = &fsl_sai_pm_ops,
1219 1220 1221 1222 1223 1224 1225 1226 1227
		.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");