rockchip_i2s.c 20.6 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-only
2 3 4 5 6 7 8 9
/* sound/soc/rockchip/rockchip_i2s.c
 *
 * ALSA SoC Audio Layer - Rockchip I2S Controller driver
 *
 * Copyright (c) 2014 Rockchip Electronics Co. Ltd.
 * Author: Jianqun <jay.xu@rock-chips.com>
 */

10
#include <linux/module.h>
11
#include <linux/mfd/syscon.h>
12 13
#include <linux/delay.h>
#include <linux/of_gpio.h>
14
#include <linux/of_device.h>
15
#include <linux/clk.h>
16
#include <linux/pinctrl/consumer.h>
17 18
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
19
#include <linux/spinlock.h>
20 21 22 23 24 25 26
#include <sound/pcm_params.h>
#include <sound/dmaengine_pcm.h>

#include "rockchip_i2s.h"

#define DRV_NAME "rockchip-i2s"

27 28 29 30 31
struct rk_i2s_pins {
	u32 reg_offset;
	u32 shift;
};

32 33 34 35 36 37 38 39 40 41
struct rk_i2s_dev {
	struct device *dev;

	struct clk *hclk;
	struct clk *mclk;

	struct snd_dmaengine_dai_dma_data capture_dma_data;
	struct snd_dmaengine_dai_dma_data playback_dma_data;

	struct regmap *regmap;
42
	struct regmap *grf;
43

44 45 46
	bool has_capture;
	bool has_playback;

47 48 49 50 51 52 53
/*
 * Used to indicate the tx/rx status.
 * I2S controller hopes to start the tx and rx together,
 * also to stop them when they are both try to stop.
*/
	bool tx_start;
	bool rx_start;
54
	bool is_master_mode;
55
	const struct rk_i2s_pins *pins;
56
	unsigned int bclk_ratio;
57
	spinlock_t lock; /* tx/rx lock */
58 59 60
	struct pinctrl *pinctrl;
	struct pinctrl_state *bclk_on;
	struct pinctrl_state *bclk_off;
61 62
};

63 64 65 66 67
static int i2s_pinctrl_select_bclk_on(struct rk_i2s_dev *i2s)
{
	int ret = 0;

	if (!IS_ERR(i2s->pinctrl) && !IS_ERR_OR_NULL(i2s->bclk_on))
68
		ret = pinctrl_select_state(i2s->pinctrl, i2s->bclk_on);
69 70 71 72 73 74 75 76 77 78 79 80 81

	if (ret)
		dev_err(i2s->dev, "bclk enable failed %d\n", ret);

	return ret;
}

static int i2s_pinctrl_select_bclk_off(struct rk_i2s_dev *i2s)
{

	int ret = 0;

	if (!IS_ERR(i2s->pinctrl) && !IS_ERR_OR_NULL(i2s->bclk_off))
82
		ret = pinctrl_select_state(i2s->pinctrl, i2s->bclk_off);
83 84 85 86 87 88 89

	if (ret)
		dev_err(i2s->dev, "bclk disable failed %d\n", ret);

	return ret;
}

90 91 92 93
static int i2s_runtime_suspend(struct device *dev)
{
	struct rk_i2s_dev *i2s = dev_get_drvdata(dev);

94
	regcache_cache_only(i2s->regmap, true);
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
	clk_disable_unprepare(i2s->mclk);

	return 0;
}

static int i2s_runtime_resume(struct device *dev)
{
	struct rk_i2s_dev *i2s = dev_get_drvdata(dev);
	int ret;

	ret = clk_prepare_enable(i2s->mclk);
	if (ret) {
		dev_err(i2s->dev, "clock enable failed %d\n", ret);
		return ret;
	}

111 112 113 114 115 116 117 118
	regcache_cache_only(i2s->regmap, false);
	regcache_mark_dirty(i2s->regmap);

	ret = regcache_sync(i2s->regmap);
	if (ret)
		clk_disable_unprepare(i2s->mclk);

	return ret;
119 120 121 122 123 124 125
}

static inline struct rk_i2s_dev *to_info(struct snd_soc_dai *dai)
{
	return snd_soc_dai_get_drvdata(dai);
}

126
static int rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
127 128 129
{
	unsigned int val = 0;
	int retry = 10;
130
	int ret = 0;
131

132
	spin_lock(&i2s->lock);
133
	if (on) {
134
		ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
135 136
					 I2S_DMACR_TDE_ENABLE,
					 I2S_DMACR_TDE_ENABLE);
137 138 139
		if (ret < 0)
			goto end;
		ret = regmap_update_bits(i2s->regmap, I2S_XFER,
140 141
					 I2S_XFER_TXS_START | I2S_XFER_RXS_START,
					 I2S_XFER_TXS_START | I2S_XFER_RXS_START);
142 143
		if (ret < 0)
			goto end;
144
		i2s->tx_start = true;
145
	} else {
146 147
		i2s->tx_start = false;

148
		ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
149 150
					 I2S_DMACR_TDE_ENABLE,
					 I2S_DMACR_TDE_DISABLE);
151 152
		if (ret < 0)
			goto end;
153

154
		if (!i2s->rx_start) {
155
			ret = regmap_update_bits(i2s->regmap, I2S_XFER,
156 157
						 I2S_XFER_TXS_START | I2S_XFER_RXS_START,
						 I2S_XFER_TXS_STOP | I2S_XFER_RXS_STOP);
158 159
			if (ret < 0)
				goto end;
160
			udelay(150);
161
			ret = regmap_update_bits(i2s->regmap, I2S_CLR,
162 163
						 I2S_CLR_TXC | I2S_CLR_RXC,
						 I2S_CLR_TXC | I2S_CLR_RXC);
164 165
			if (ret < 0)
				goto end;
166
			regmap_read(i2s->regmap, I2S_CLR, &val);
167 168 169 170 171 172 173 174 175

			/* Should wait for clear operation to finish */
			while (val) {
				regmap_read(i2s->regmap, I2S_CLR, &val);
				retry--;
				if (!retry) {
					dev_warn(i2s->dev, "fail to clear\n");
					break;
				}
176 177 178
			}
		}
	}
179
end:
180
	spin_unlock(&i2s->lock);
181 182 183 184
	if (ret < 0)
		dev_err(i2s->dev, "lrclk update failed\n");

	return ret;
185 186
}

187
static int rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
188 189 190
{
	unsigned int val = 0;
	int retry = 10;
191
	int ret = 0;
192

193
	spin_lock(&i2s->lock);
194
	if (on) {
195
		ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
196 197
					 I2S_DMACR_RDE_ENABLE,
					 I2S_DMACR_RDE_ENABLE);
198 199
		if (ret < 0)
			goto end;
200

201
		ret = regmap_update_bits(i2s->regmap, I2S_XFER,
202 203
					 I2S_XFER_TXS_START | I2S_XFER_RXS_START,
					 I2S_XFER_TXS_START | I2S_XFER_RXS_START);
204 205
		if (ret < 0)
			goto end;
206
		i2s->rx_start = true;
207
	} else {
208 209
		i2s->rx_start = false;

210
		ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
211 212
					 I2S_DMACR_RDE_ENABLE,
					 I2S_DMACR_RDE_DISABLE);
213 214
		if (ret < 0)
			goto end;
215

216
		if (!i2s->tx_start) {
217
			ret = regmap_update_bits(i2s->regmap, I2S_XFER,
218 219
						 I2S_XFER_TXS_START | I2S_XFER_RXS_START,
						 I2S_XFER_TXS_STOP | I2S_XFER_RXS_STOP);
220 221
			if (ret < 0)
				goto end;
222
			udelay(150);
223
			ret = regmap_update_bits(i2s->regmap, I2S_CLR,
224 225
						 I2S_CLR_TXC | I2S_CLR_RXC,
						 I2S_CLR_TXC | I2S_CLR_RXC);
226 227
			if (ret < 0)
				goto end;
228
			regmap_read(i2s->regmap, I2S_CLR, &val);
229 230 231 232 233 234 235 236
			/* Should wait for clear operation to finish */
			while (val) {
				regmap_read(i2s->regmap, I2S_CLR, &val);
				retry--;
				if (!retry) {
					dev_warn(i2s->dev, "fail to clear\n");
					break;
				}
237 238 239
			}
		}
	}
240
end:
241
	spin_unlock(&i2s->lock);
242 243 244 245
	if (ret < 0)
		dev_err(i2s->dev, "lrclk update failed\n");

	return ret;
246 247 248 249 250 251 252
}

static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
				unsigned int fmt)
{
	struct rk_i2s_dev *i2s = to_info(cpu_dai);
	unsigned int mask = 0, val = 0;
253
	int ret = 0;
254

255
	pm_runtime_get_sync(cpu_dai->dev);
256
	mask = I2S_CKR_MSS_MASK;
257 258
	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
	case SND_SOC_DAIFMT_BP_FP:
259 260
		/* Set source clock in Master mode */
		val = I2S_CKR_MSS_MASTER;
261
		i2s->is_master_mode = true;
262
		break;
263
	case SND_SOC_DAIFMT_BC_FC:
264
		val = I2S_CKR_MSS_SLAVE;
265
		i2s->is_master_mode = false;
266 267
		break;
	default:
268 269
		ret = -EINVAL;
		goto err_pm_put;
270 271 272 273
	}

	regmap_update_bits(i2s->regmap, I2S_CKR, mask, val);

274
	mask = I2S_CKR_CKP_MASK | I2S_CKR_TLP_MASK | I2S_CKR_RLP_MASK;
275 276
	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
	case SND_SOC_DAIFMT_NB_NF:
277 278 279 280 281 282 283 284
		val = I2S_CKR_CKP_NORMAL |
		      I2S_CKR_TLP_NORMAL |
		      I2S_CKR_RLP_NORMAL;
		break;
	case SND_SOC_DAIFMT_NB_IF:
		val = I2S_CKR_CKP_NORMAL |
		      I2S_CKR_TLP_INVERTED |
		      I2S_CKR_RLP_INVERTED;
285 286
		break;
	case SND_SOC_DAIFMT_IB_NF:
287 288 289 290 291 292 293 294
		val = I2S_CKR_CKP_INVERTED |
		      I2S_CKR_TLP_NORMAL |
		      I2S_CKR_RLP_NORMAL;
		break;
	case SND_SOC_DAIFMT_IB_IF:
		val = I2S_CKR_CKP_INVERTED |
		      I2S_CKR_TLP_INVERTED |
		      I2S_CKR_RLP_INVERTED;
295 296
		break;
	default:
297 298
		ret = -EINVAL;
		goto err_pm_put;
299 300 301 302 303
	}

	regmap_update_bits(i2s->regmap, I2S_CKR, mask, val);

	mask = I2S_TXCR_IBM_MASK | I2S_TXCR_TFS_MASK | I2S_TXCR_PBM_MASK;
304 305 306 307 308 309 310 311 312 313
	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
	case SND_SOC_DAIFMT_RIGHT_J:
		val = I2S_TXCR_IBM_RSJM;
		break;
	case SND_SOC_DAIFMT_LEFT_J:
		val = I2S_TXCR_IBM_LSJM;
		break;
	case SND_SOC_DAIFMT_I2S:
		val = I2S_TXCR_IBM_NORMAL;
		break;
314
	case SND_SOC_DAIFMT_DSP_A: /* PCM delay 1 bit mode */
315 316
		val = I2S_TXCR_TFS_PCM | I2S_TXCR_PBM_MODE(1);
		break;
317 318 319
	case SND_SOC_DAIFMT_DSP_B: /* PCM no delay mode */
		val = I2S_TXCR_TFS_PCM;
		break;
320
	default:
321 322
		ret = -EINVAL;
		goto err_pm_put;
323 324 325 326
	}

	regmap_update_bits(i2s->regmap, I2S_TXCR, mask, val);

327
	mask = I2S_RXCR_IBM_MASK | I2S_RXCR_TFS_MASK | I2S_RXCR_PBM_MASK;
328 329 330 331 332 333 334 335 336 337
	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
	case SND_SOC_DAIFMT_RIGHT_J:
		val = I2S_RXCR_IBM_RSJM;
		break;
	case SND_SOC_DAIFMT_LEFT_J:
		val = I2S_RXCR_IBM_LSJM;
		break;
	case SND_SOC_DAIFMT_I2S:
		val = I2S_RXCR_IBM_NORMAL;
		break;
338
	case SND_SOC_DAIFMT_DSP_A: /* PCM delay 1 bit mode */
339 340
		val = I2S_RXCR_TFS_PCM | I2S_RXCR_PBM_MODE(1);
		break;
341 342 343
	case SND_SOC_DAIFMT_DSP_B: /* PCM no delay mode */
		val = I2S_RXCR_TFS_PCM;
		break;
344
	default:
345 346
		ret = -EINVAL;
		goto err_pm_put;
347 348 349 350
	}

	regmap_update_bits(i2s->regmap, I2S_RXCR, mask, val);

351 352 353 354
err_pm_put:
	pm_runtime_put(cpu_dai->dev);

	return ret;
355 356 357 358 359 360 361
}

static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
				  struct snd_pcm_hw_params *params,
				  struct snd_soc_dai *dai)
{
	struct rk_i2s_dev *i2s = to_info(dai);
362
	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
363
	unsigned int val = 0;
364 365 366 367
	unsigned int mclk_rate, bclk_rate, div_bclk, div_lrck;

	if (i2s->is_master_mode) {
		mclk_rate = clk_get_rate(i2s->mclk);
368
		bclk_rate = i2s->bclk_ratio * params_rate(params);
369
		if (!bclk_rate)
370 371
			return -EINVAL;

372
		div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate);
373 374 375 376 377 378 379 380 381 382 383
		div_lrck = bclk_rate / params_rate(params);
		regmap_update_bits(i2s->regmap, I2S_CKR,
				   I2S_CKR_MDIV_MASK,
				   I2S_CKR_MDIV(div_bclk));

		regmap_update_bits(i2s->regmap, I2S_CKR,
				   I2S_CKR_TSD_MASK |
				   I2S_CKR_RSD_MASK,
				   I2S_CKR_TSD(div_lrck) |
				   I2S_CKR_RSD(div_lrck));
	}
384 385 386 387 388 389 390 391 392 393 394 395 396 397

	switch (params_format(params)) {
	case SNDRV_PCM_FORMAT_S8:
		val |= I2S_TXCR_VDW(8);
		break;
	case SNDRV_PCM_FORMAT_S16_LE:
		val |= I2S_TXCR_VDW(16);
		break;
	case SNDRV_PCM_FORMAT_S20_3LE:
		val |= I2S_TXCR_VDW(20);
		break;
	case SNDRV_PCM_FORMAT_S24_LE:
		val |= I2S_TXCR_VDW(24);
		break;
398 399 400
	case SNDRV_PCM_FORMAT_S32_LE:
		val |= I2S_TXCR_VDW(32);
		break;
401 402 403 404
	default:
		return -EINVAL;
	}

405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432
	switch (params_channels(params)) {
	case 8:
		val |= I2S_CHN_8;
		break;
	case 6:
		val |= I2S_CHN_6;
		break;
	case 4:
		val |= I2S_CHN_4;
		break;
	case 2:
		val |= I2S_CHN_2;
		break;
	default:
		dev_err(i2s->dev, "invalid channel: %d\n",
			params_channels(params));
		return -EINVAL;
	}

	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
		regmap_update_bits(i2s->regmap, I2S_RXCR,
				   I2S_RXCR_VDW_MASK | I2S_RXCR_CSR_MASK,
				   val);
	else
		regmap_update_bits(i2s->regmap, I2S_TXCR,
				   I2S_TXCR_VDW_MASK | I2S_TXCR_CSR_MASK,
				   val);

433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456
	if (!IS_ERR(i2s->grf) && i2s->pins) {
		regmap_read(i2s->regmap, I2S_TXCR, &val);
		val &= I2S_TXCR_CSR_MASK;

		switch (val) {
		case I2S_CHN_4:
			val = I2S_IO_4CH_OUT_6CH_IN;
			break;
		case I2S_CHN_6:
			val = I2S_IO_6CH_OUT_4CH_IN;
			break;
		case I2S_CHN_8:
			val = I2S_IO_8CH_OUT_2CH_IN;
			break;
		default:
			val = I2S_IO_2CH_OUT_8CH_IN;
			break;
		}

		val <<= i2s->pins->shift;
		val |= (I2S_IO_DIRECTION_MASK << i2s->pins->shift) << 16;
		regmap_write(i2s->grf, i2s->pins->reg_offset, val);
	}

457 458 459 460
	regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK,
			   I2S_DMACR_TDL(16));
	regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK,
			   I2S_DMACR_RDL(16));
461

462
	val = I2S_CKR_TRCM_TXRX;
463
	if (dai->driver->symmetric_rate && rtd->dai_link->symmetric_rate)
464
		val = I2S_CKR_TRCM_TXONLY;
465 466 467 468

	regmap_update_bits(i2s->regmap, I2S_CKR,
			   I2S_CKR_TRCM_MASK,
			   val);
469 470 471 472 473 474 475 476 477 478 479 480 481 482
	return 0;
}

static int rockchip_i2s_trigger(struct snd_pcm_substream *substream,
				int cmd, struct snd_soc_dai *dai)
{
	struct rk_i2s_dev *i2s = to_info(dai);
	int ret = 0;

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
	case SNDRV_PCM_TRIGGER_RESUME:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
483
			ret = rockchip_snd_rxctrl(i2s, 1);
484
		else
485 486 487 488
			ret = rockchip_snd_txctrl(i2s, 1);
		if (ret < 0)
			return ret;
		i2s_pinctrl_select_bclk_on(i2s);
489 490 491 492
		break;
	case SNDRV_PCM_TRIGGER_SUSPEND:
	case SNDRV_PCM_TRIGGER_STOP:
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
493 494 495 496 497 498 499 500 501
		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
			if (!i2s->tx_start)
				i2s_pinctrl_select_bclk_off(i2s);
			ret = rockchip_snd_rxctrl(i2s, 0);
		} else {
			if (!i2s->rx_start)
				i2s_pinctrl_select_bclk_off(i2s);
			ret = rockchip_snd_txctrl(i2s, 0);
		}
502 503 504 505 506 507 508 509 510
		break;
	default:
		ret = -EINVAL;
		break;
	}

	return ret;
}

511 512 513 514 515 516 517 518 519 520
static int rockchip_i2s_set_bclk_ratio(struct snd_soc_dai *dai,
				       unsigned int ratio)
{
	struct rk_i2s_dev *i2s = to_info(dai);

	i2s->bclk_ratio = ratio;

	return 0;
}

521 522 523 524 525 526
static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
				   unsigned int freq, int dir)
{
	struct rk_i2s_dev *i2s = to_info(cpu_dai);
	int ret;

527 528 529
	if (freq == 0)
		return 0;

530 531 532 533 534 535 536
	ret = clk_set_rate(i2s->mclk, freq);
	if (ret)
		dev_err(i2s->dev, "Fail to set mclk %d\n", ret);

	return ret;
}

537 538 539 540
static int rockchip_i2s_dai_probe(struct snd_soc_dai *dai)
{
	struct rk_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai);

541 542 543
	snd_soc_dai_init_dma_data(dai,
		i2s->has_playback ? &i2s->playback_dma_data : NULL,
		i2s->has_capture  ? &i2s->capture_dma_data  : NULL);
544 545 546 547

	return 0;
}

548 549
static const struct snd_soc_dai_ops rockchip_i2s_dai_ops = {
	.hw_params = rockchip_i2s_hw_params,
550
	.set_bclk_ratio	= rockchip_i2s_set_bclk_ratio,
551
	.set_sysclk = rockchip_i2s_set_sysclk,
552
	.set_fmt = rockchip_i2s_set_fmt,
553 554 555 556
	.trigger = rockchip_i2s_trigger,
};

static struct snd_soc_dai_driver rockchip_i2s_dai = {
557
	.probe = rockchip_i2s_dai_probe,
558
	.ops = &rockchip_i2s_dai_ops,
559
	.symmetric_rate = 1,
560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592
};

static const struct snd_soc_component_driver rockchip_i2s_component = {
	.name = DRV_NAME,
};

static bool rockchip_i2s_wr_reg(struct device *dev, unsigned int reg)
{
	switch (reg) {
	case I2S_TXCR:
	case I2S_RXCR:
	case I2S_CKR:
	case I2S_DMACR:
	case I2S_INTCR:
	case I2S_XFER:
	case I2S_CLR:
	case I2S_TXDR:
		return true;
	default:
		return false;
	}
}

static bool rockchip_i2s_rd_reg(struct device *dev, unsigned int reg)
{
	switch (reg) {
	case I2S_TXCR:
	case I2S_RXCR:
	case I2S_CKR:
	case I2S_DMACR:
	case I2S_INTCR:
	case I2S_XFER:
	case I2S_CLR:
593
	case I2S_TXDR:
594
	case I2S_RXDR:
595 596
	case I2S_FIFOLR:
	case I2S_INTSR:
597 598 599 600 601 602 603 604 605 606
		return true;
	default:
		return false;
	}
}

static bool rockchip_i2s_volatile_reg(struct device *dev, unsigned int reg)
{
	switch (reg) {
	case I2S_INTSR:
607
	case I2S_CLR:
608 609 610
	case I2S_FIFOLR:
	case I2S_TXDR:
	case I2S_RXDR:
611 612 613 614 615 616 617 618 619
		return true;
	default:
		return false;
	}
}

static bool rockchip_i2s_precious_reg(struct device *dev, unsigned int reg)
{
	switch (reg) {
620 621
	case I2S_RXDR:
		return true;
622 623 624 625 626
	default:
		return false;
	}
}

627 628 629 630 631 632 633 634
static const struct reg_default rockchip_i2s_reg_defaults[] = {
	{0x00, 0x0000000f},
	{0x04, 0x0000000f},
	{0x08, 0x00071f1f},
	{0x10, 0x001f0000},
	{0x14, 0x01f00000},
};

635 636 637 638 639
static const struct regmap_config rockchip_i2s_regmap_config = {
	.reg_bits = 32,
	.reg_stride = 4,
	.val_bits = 32,
	.max_register = I2S_RXDR,
640 641
	.reg_defaults = rockchip_i2s_reg_defaults,
	.num_reg_defaults = ARRAY_SIZE(rockchip_i2s_reg_defaults),
642 643 644 645 646 647 648
	.writeable_reg = rockchip_i2s_wr_reg,
	.readable_reg = rockchip_i2s_rd_reg,
	.volatile_reg = rockchip_i2s_volatile_reg,
	.precious_reg = rockchip_i2s_precious_reg,
	.cache_type = REGCACHE_FLAT,
};

649 650 651 652 653
static const struct rk_i2s_pins rk3399_i2s_pins = {
	.reg_offset = 0xe220,
	.shift = 11,
};

654
static const struct of_device_id rockchip_i2s_match[] __maybe_unused = {
655 656 657
	{ .compatible = "rockchip,px30-i2s", },
	{ .compatible = "rockchip,rk1808-i2s", },
	{ .compatible = "rockchip,rk3036-i2s", },
658
	{ .compatible = "rockchip,rk3066-i2s", },
659
	{ .compatible = "rockchip,rk3128-i2s", },
660
	{ .compatible = "rockchip,rk3188-i2s", },
661
	{ .compatible = "rockchip,rk3228-i2s", },
662
	{ .compatible = "rockchip,rk3288-i2s", },
663 664 665 666
	{ .compatible = "rockchip,rk3308-i2s", },
	{ .compatible = "rockchip,rk3328-i2s", },
	{ .compatible = "rockchip,rk3366-i2s", },
	{ .compatible = "rockchip,rk3368-i2s", },
667
	{ .compatible = "rockchip,rk3399-i2s", .data = &rk3399_i2s_pins },
668
	{ .compatible = "rockchip,rv1126-i2s", },
669 670 671
	{},
};

672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 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 740
static int rockchip_i2s_init_dai(struct rk_i2s_dev *i2s, struct resource *res,
				 struct snd_soc_dai_driver **dp)
{
	struct device_node *node = i2s->dev->of_node;
	struct snd_soc_dai_driver *dai;
	struct property *dma_names;
	const char *dma_name;
	unsigned int val;

	of_property_for_each_string(node, "dma-names", dma_names, dma_name) {
		if (!strcmp(dma_name, "tx"))
			i2s->has_playback = true;
		if (!strcmp(dma_name, "rx"))
			i2s->has_capture = true;
	}

	dai = devm_kmemdup(i2s->dev, &rockchip_i2s_dai,
			   sizeof(*dai), GFP_KERNEL);
	if (!dai)
		return -ENOMEM;

	if (i2s->has_playback) {
		dai->playback.stream_name = "Playback";
		dai->playback.channels_min = 2;
		dai->playback.channels_max = 8;
		dai->playback.rates = SNDRV_PCM_RATE_8000_192000;
		dai->playback.formats = SNDRV_PCM_FMTBIT_S8 |
					SNDRV_PCM_FMTBIT_S16_LE |
					SNDRV_PCM_FMTBIT_S20_3LE |
					SNDRV_PCM_FMTBIT_S24_LE |
					SNDRV_PCM_FMTBIT_S32_LE;

		i2s->playback_dma_data.addr = res->start + I2S_TXDR;
		i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
		i2s->playback_dma_data.maxburst = 8;

		if (!of_property_read_u32(node, "rockchip,playback-channels", &val)) {
			if (val >= 2 && val <= 8)
				dai->playback.channels_max = val;
		}
	}

	if (i2s->has_capture) {
		dai->capture.stream_name = "Capture";
		dai->capture.channels_min = 2;
		dai->capture.channels_max = 8;
		dai->capture.rates = SNDRV_PCM_RATE_8000_192000;
		dai->capture.formats = SNDRV_PCM_FMTBIT_S8 |
				       SNDRV_PCM_FMTBIT_S16_LE |
				       SNDRV_PCM_FMTBIT_S20_3LE |
				       SNDRV_PCM_FMTBIT_S24_LE |
				       SNDRV_PCM_FMTBIT_S32_LE;

		i2s->capture_dma_data.addr = res->start + I2S_RXDR;
		i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
		i2s->capture_dma_data.maxburst = 8;

		if (!of_property_read_u32(node, "rockchip,capture-channels", &val)) {
			if (val >= 2 && val <= 8)
				dai->capture.channels_max = val;
		}
	}

	if (dp)
		*dp = dai;

	return 0;
}

741 742
static int rockchip_i2s_probe(struct platform_device *pdev)
{
743
	struct device_node *node = pdev->dev.of_node;
744
	const struct of_device_id *of_id;
745
	struct rk_i2s_dev *i2s;
746
	struct snd_soc_dai_driver *dai;
747 748 749 750 751
	struct resource *res;
	void __iomem *regs;
	int ret;

	i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
752
	if (!i2s)
753 754
		return -ENOMEM;

755
	spin_lock_init(&i2s->lock);
756 757 758 759 760 761 762 763 764 765 766
	i2s->dev = &pdev->dev;

	i2s->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf");
	if (!IS_ERR(i2s->grf)) {
		of_id = of_match_device(rockchip_i2s_match, &pdev->dev);
		if (!of_id || !of_id->data)
			return -EINVAL;

		i2s->pins = of_id->data;
	}

767 768 769 770 771 772
	/* try to prepare related clocks */
	i2s->hclk = devm_clk_get(&pdev->dev, "i2s_hclk");
	if (IS_ERR(i2s->hclk)) {
		dev_err(&pdev->dev, "Can't retrieve i2s bus clock\n");
		return PTR_ERR(i2s->hclk);
	}
773 774 775 776 777
	ret = clk_prepare_enable(i2s->hclk);
	if (ret) {
		dev_err(i2s->dev, "hclock enable failed %d\n", ret);
		return ret;
	}
778 779 780 781

	i2s->mclk = devm_clk_get(&pdev->dev, "i2s_clk");
	if (IS_ERR(i2s->mclk)) {
		dev_err(&pdev->dev, "Can't retrieve i2s master clock\n");
782 783
		ret = PTR_ERR(i2s->mclk);
		goto err_clk;
784 785
	}

786
	regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
787 788 789 790
	if (IS_ERR(regs)) {
		ret = PTR_ERR(regs);
		goto err_clk;
	}
791 792 793 794 795 796

	i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
					    &rockchip_i2s_regmap_config);
	if (IS_ERR(i2s->regmap)) {
		dev_err(&pdev->dev,
			"Failed to initialise managed register map\n");
797 798
		ret = PTR_ERR(i2s->regmap);
		goto err_clk;
799 800
	}

801
	i2s->bclk_ratio = 64;
802 803
	i2s->pinctrl = devm_pinctrl_get(&pdev->dev);

804 805 806 807 808 809
	if (!IS_ERR(i2s->pinctrl)) {
		i2s->bclk_on = pinctrl_lookup_state(i2s->pinctrl, "bclk_on");
		if (!IS_ERR_OR_NULL(i2s->bclk_on)) {
			i2s->bclk_off = pinctrl_lookup_state(i2s->pinctrl, "bclk_off");
			if (IS_ERR_OR_NULL(i2s->bclk_off)) {
				dev_err(&pdev->dev, "failed to find i2s bclk_off\n");
810
				ret = -EINVAL;
811 812
				goto err_clk;
			}
813
		}
814
	} else {
815
		dev_dbg(&pdev->dev, "failed to find i2s pinctrl\n");
816
	}
817

818
	i2s_pinctrl_select_bclk_off(i2s);
819

820 821 822 823 824 825 826 827 828
	dev_set_drvdata(&pdev->dev, i2s);

	pm_runtime_enable(&pdev->dev);
	if (!pm_runtime_enabled(&pdev->dev)) {
		ret = i2s_runtime_resume(&pdev->dev);
		if (ret)
			goto err_pm_disable;
	}

829 830
	ret = rockchip_i2s_init_dai(i2s, res, &dai);
	if (ret)
831
		goto err_pm_disable;
832

833 834
	ret = devm_snd_soc_register_component(&pdev->dev,
					      &rockchip_i2s_component,
835
					      dai, 1);
836

837 838 839 840 841
	if (ret) {
		dev_err(&pdev->dev, "Could not register DAI\n");
		goto err_suspend;
	}

842
	ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
843 844
	if (ret) {
		dev_err(&pdev->dev, "Could not register PCM\n");
845
		goto err_suspend;
846 847 848 849 850 851 852 853 854
	}

	return 0;

err_suspend:
	if (!pm_runtime_status_suspended(&pdev->dev))
		i2s_runtime_suspend(&pdev->dev);
err_pm_disable:
	pm_runtime_disable(&pdev->dev);
855 856
err_clk:
	clk_disable_unprepare(i2s->hclk);
857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893
	return ret;
}

static int rockchip_i2s_remove(struct platform_device *pdev)
{
	struct rk_i2s_dev *i2s = dev_get_drvdata(&pdev->dev);

	pm_runtime_disable(&pdev->dev);
	if (!pm_runtime_status_suspended(&pdev->dev))
		i2s_runtime_suspend(&pdev->dev);

	clk_disable_unprepare(i2s->hclk);

	return 0;
}

static const struct dev_pm_ops rockchip_i2s_pm_ops = {
	SET_RUNTIME_PM_OPS(i2s_runtime_suspend, i2s_runtime_resume,
			   NULL)
};

static struct platform_driver rockchip_i2s_driver = {
	.probe = rockchip_i2s_probe,
	.remove = rockchip_i2s_remove,
	.driver = {
		.name = DRV_NAME,
		.of_match_table = of_match_ptr(rockchip_i2s_match),
		.pm = &rockchip_i2s_pm_ops,
	},
};
module_platform_driver(rockchip_i2s_driver);

MODULE_DESCRIPTION("ROCKCHIP IIS ASoC Interface");
MODULE_AUTHOR("jianqun <jay.xu@rock-chips.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" DRV_NAME);
MODULE_DEVICE_TABLE(of, rockchip_i2s_match);