brintos

brintos / linux-shallow public Read only

0
0
Text · 20.4 KiB · 4315da4 Raw
883 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* sound/soc/rockchip/rockchip_i2s.c3 *4 * ALSA SoC Audio Layer - Rockchip I2S Controller driver5 *6 * Copyright (c) 2014 Rockchip Electronics Co. Ltd.7 * Author: Jianqun <jay.xu@rock-chips.com>8 */9 10#include <linux/module.h>11#include <linux/mfd/syscon.h>12#include <linux/delay.h>13#include <linux/of.h>14#include <linux/clk.h>15#include <linux/pinctrl/consumer.h>16#include <linux/pm_runtime.h>17#include <linux/regmap.h>18#include <linux/spinlock.h>19#include <sound/pcm_params.h>20#include <sound/dmaengine_pcm.h>21 22#include "rockchip_i2s.h"23 24#define DRV_NAME "rockchip-i2s"25 26struct rk_i2s_pins {27	u32 reg_offset;28	u32 shift;29};30 31struct rk_i2s_dev {32	struct device *dev;33 34	struct clk *hclk;35	struct clk *mclk;36 37	struct snd_dmaengine_dai_dma_data capture_dma_data;38	struct snd_dmaengine_dai_dma_data playback_dma_data;39 40	struct regmap *regmap;41	struct regmap *grf;42 43	bool has_capture;44	bool has_playback;45 46/*47 * Used to indicate the tx/rx status.48 * I2S controller hopes to start the tx and rx together,49 * also to stop them when they are both try to stop.50*/51	bool tx_start;52	bool rx_start;53	bool is_master_mode;54	const struct rk_i2s_pins *pins;55	unsigned int bclk_ratio;56	spinlock_t lock; /* tx/rx lock */57	struct pinctrl *pinctrl;58	struct pinctrl_state *bclk_on;59	struct pinctrl_state *bclk_off;60};61 62static int i2s_pinctrl_select_bclk_on(struct rk_i2s_dev *i2s)63{64	int ret = 0;65 66	if (!IS_ERR(i2s->pinctrl) && !IS_ERR_OR_NULL(i2s->bclk_on))67		ret = pinctrl_select_state(i2s->pinctrl, i2s->bclk_on);68 69	if (ret)70		dev_err(i2s->dev, "bclk enable failed %d\n", ret);71 72	return ret;73}74 75static int i2s_pinctrl_select_bclk_off(struct rk_i2s_dev *i2s)76{77 78	int ret = 0;79 80	if (!IS_ERR(i2s->pinctrl) && !IS_ERR_OR_NULL(i2s->bclk_off))81		ret = pinctrl_select_state(i2s->pinctrl, i2s->bclk_off);82 83	if (ret)84		dev_err(i2s->dev, "bclk disable failed %d\n", ret);85 86	return ret;87}88 89static int i2s_runtime_suspend(struct device *dev)90{91	struct rk_i2s_dev *i2s = dev_get_drvdata(dev);92 93	regcache_cache_only(i2s->regmap, true);94	clk_disable_unprepare(i2s->mclk);95 96	return 0;97}98 99static int i2s_runtime_resume(struct device *dev)100{101	struct rk_i2s_dev *i2s = dev_get_drvdata(dev);102	int ret;103 104	ret = clk_prepare_enable(i2s->mclk);105	if (ret) {106		dev_err(i2s->dev, "clock enable failed %d\n", ret);107		return ret;108	}109 110	regcache_cache_only(i2s->regmap, false);111	regcache_mark_dirty(i2s->regmap);112 113	ret = regcache_sync(i2s->regmap);114	if (ret)115		clk_disable_unprepare(i2s->mclk);116 117	return ret;118}119 120static inline struct rk_i2s_dev *to_info(struct snd_soc_dai *dai)121{122	return snd_soc_dai_get_drvdata(dai);123}124 125static int rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)126{127	unsigned int val = 0;128	int ret = 0;129 130	spin_lock(&i2s->lock);131	if (on) {132		ret = regmap_update_bits(i2s->regmap, I2S_DMACR,133					 I2S_DMACR_TDE_ENABLE,134					 I2S_DMACR_TDE_ENABLE);135		if (ret < 0)136			goto end;137		ret = regmap_update_bits(i2s->regmap, I2S_XFER,138					 I2S_XFER_TXS_START | I2S_XFER_RXS_START,139					 I2S_XFER_TXS_START | I2S_XFER_RXS_START);140		if (ret < 0)141			goto end;142		i2s->tx_start = true;143	} else {144		i2s->tx_start = false;145 146		ret = regmap_update_bits(i2s->regmap, I2S_DMACR,147					 I2S_DMACR_TDE_ENABLE,148					 I2S_DMACR_TDE_DISABLE);149		if (ret < 0)150			goto end;151 152		if (!i2s->rx_start) {153			ret = regmap_update_bits(i2s->regmap, I2S_XFER,154						 I2S_XFER_TXS_START | I2S_XFER_RXS_START,155						 I2S_XFER_TXS_STOP | I2S_XFER_RXS_STOP);156			if (ret < 0)157				goto end;158			udelay(150);159			ret = regmap_update_bits(i2s->regmap, I2S_CLR,160						 I2S_CLR_TXC | I2S_CLR_RXC,161						 I2S_CLR_TXC | I2S_CLR_RXC);162			if (ret < 0)163				goto end;164			ret = regmap_read_poll_timeout_atomic(i2s->regmap,165							      I2S_CLR,166							      val,167							      val == 0,168							      20,169							      200);170			if (ret < 0)171				dev_warn(i2s->dev, "fail to clear: %d\n", ret);172		}173	}174end:175	spin_unlock(&i2s->lock);176	if (ret < 0)177		dev_err(i2s->dev, "lrclk update failed\n");178 179	return ret;180}181 182static int rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)183{184	unsigned int val = 0;185	int ret = 0;186 187	spin_lock(&i2s->lock);188	if (on) {189		ret = regmap_update_bits(i2s->regmap, I2S_DMACR,190					 I2S_DMACR_RDE_ENABLE,191					 I2S_DMACR_RDE_ENABLE);192		if (ret < 0)193			goto end;194 195		ret = regmap_update_bits(i2s->regmap, I2S_XFER,196					 I2S_XFER_TXS_START | I2S_XFER_RXS_START,197					 I2S_XFER_TXS_START | I2S_XFER_RXS_START);198		if (ret < 0)199			goto end;200		i2s->rx_start = true;201	} else {202		i2s->rx_start = false;203 204		ret = regmap_update_bits(i2s->regmap, I2S_DMACR,205					 I2S_DMACR_RDE_ENABLE,206					 I2S_DMACR_RDE_DISABLE);207		if (ret < 0)208			goto end;209 210		if (!i2s->tx_start) {211			ret = regmap_update_bits(i2s->regmap, I2S_XFER,212						 I2S_XFER_TXS_START | I2S_XFER_RXS_START,213						 I2S_XFER_TXS_STOP | I2S_XFER_RXS_STOP);214			if (ret < 0)215				goto end;216			udelay(150);217			ret = regmap_update_bits(i2s->regmap, I2S_CLR,218						 I2S_CLR_TXC | I2S_CLR_RXC,219						 I2S_CLR_TXC | I2S_CLR_RXC);220			if (ret < 0)221				goto end;222			ret = regmap_read_poll_timeout_atomic(i2s->regmap,223							      I2S_CLR,224							      val,225							      val == 0,226							      20,227							      200);228			if (ret < 0)229				dev_warn(i2s->dev, "fail to clear: %d\n", ret);230		}231	}232end:233	spin_unlock(&i2s->lock);234	if (ret < 0)235		dev_err(i2s->dev, "lrclk update failed\n");236 237	return ret;238}239 240static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,241				unsigned int fmt)242{243	struct rk_i2s_dev *i2s = to_info(cpu_dai);244	unsigned int mask = 0, val = 0;245	int ret = 0;246 247	pm_runtime_get_sync(cpu_dai->dev);248	mask = I2S_CKR_MSS_MASK;249	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {250	case SND_SOC_DAIFMT_BP_FP:251		/* Set source clock in Master mode */252		val = I2S_CKR_MSS_MASTER;253		i2s->is_master_mode = true;254		break;255	case SND_SOC_DAIFMT_BC_FC:256		val = I2S_CKR_MSS_SLAVE;257		i2s->is_master_mode = false;258		break;259	default:260		ret = -EINVAL;261		goto err_pm_put;262	}263 264	regmap_update_bits(i2s->regmap, I2S_CKR, mask, val);265 266	mask = I2S_CKR_CKP_MASK | I2S_CKR_TLP_MASK | I2S_CKR_RLP_MASK;267	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {268	case SND_SOC_DAIFMT_NB_NF:269		val = I2S_CKR_CKP_NORMAL |270		      I2S_CKR_TLP_NORMAL |271		      I2S_CKR_RLP_NORMAL;272		break;273	case SND_SOC_DAIFMT_NB_IF:274		val = I2S_CKR_CKP_NORMAL |275		      I2S_CKR_TLP_INVERTED |276		      I2S_CKR_RLP_INVERTED;277		break;278	case SND_SOC_DAIFMT_IB_NF:279		val = I2S_CKR_CKP_INVERTED |280		      I2S_CKR_TLP_NORMAL |281		      I2S_CKR_RLP_NORMAL;282		break;283	case SND_SOC_DAIFMT_IB_IF:284		val = I2S_CKR_CKP_INVERTED |285		      I2S_CKR_TLP_INVERTED |286		      I2S_CKR_RLP_INVERTED;287		break;288	default:289		ret = -EINVAL;290		goto err_pm_put;291	}292 293	regmap_update_bits(i2s->regmap, I2S_CKR, mask, val);294 295	mask = I2S_TXCR_IBM_MASK | I2S_TXCR_TFS_MASK | I2S_TXCR_PBM_MASK;296	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {297	case SND_SOC_DAIFMT_RIGHT_J:298		val = I2S_TXCR_IBM_RSJM;299		break;300	case SND_SOC_DAIFMT_LEFT_J:301		val = I2S_TXCR_IBM_LSJM;302		break;303	case SND_SOC_DAIFMT_I2S:304		val = I2S_TXCR_IBM_NORMAL;305		break;306	case SND_SOC_DAIFMT_DSP_A: /* PCM delay 1 bit mode */307		val = I2S_TXCR_TFS_PCM | I2S_TXCR_PBM_MODE(1);308		break;309	case SND_SOC_DAIFMT_DSP_B: /* PCM no delay mode */310		val = I2S_TXCR_TFS_PCM;311		break;312	default:313		ret = -EINVAL;314		goto err_pm_put;315	}316 317	regmap_update_bits(i2s->regmap, I2S_TXCR, mask, val);318 319	mask = I2S_RXCR_IBM_MASK | I2S_RXCR_TFS_MASK | I2S_RXCR_PBM_MASK;320	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {321	case SND_SOC_DAIFMT_RIGHT_J:322		val = I2S_RXCR_IBM_RSJM;323		break;324	case SND_SOC_DAIFMT_LEFT_J:325		val = I2S_RXCR_IBM_LSJM;326		break;327	case SND_SOC_DAIFMT_I2S:328		val = I2S_RXCR_IBM_NORMAL;329		break;330	case SND_SOC_DAIFMT_DSP_A: /* PCM delay 1 bit mode */331		val = I2S_RXCR_TFS_PCM | I2S_RXCR_PBM_MODE(1);332		break;333	case SND_SOC_DAIFMT_DSP_B: /* PCM no delay mode */334		val = I2S_RXCR_TFS_PCM;335		break;336	default:337		ret = -EINVAL;338		goto err_pm_put;339	}340 341	regmap_update_bits(i2s->regmap, I2S_RXCR, mask, val);342 343err_pm_put:344	pm_runtime_put(cpu_dai->dev);345 346	return ret;347}348 349static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,350				  struct snd_pcm_hw_params *params,351				  struct snd_soc_dai *dai)352{353	struct rk_i2s_dev *i2s = to_info(dai);354	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);355	unsigned int val = 0;356	unsigned int mclk_rate, bclk_rate, div_bclk, div_lrck;357 358	if (i2s->is_master_mode) {359		mclk_rate = clk_get_rate(i2s->mclk);360		bclk_rate = i2s->bclk_ratio * params_rate(params);361		if (!bclk_rate)362			return -EINVAL;363 364		div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate);365		div_lrck = bclk_rate / params_rate(params);366		regmap_update_bits(i2s->regmap, I2S_CKR,367				   I2S_CKR_MDIV_MASK,368				   I2S_CKR_MDIV(div_bclk));369 370		regmap_update_bits(i2s->regmap, I2S_CKR,371				   I2S_CKR_TSD_MASK |372				   I2S_CKR_RSD_MASK,373				   I2S_CKR_TSD(div_lrck) |374				   I2S_CKR_RSD(div_lrck));375	}376 377	switch (params_format(params)) {378	case SNDRV_PCM_FORMAT_S8:379		val |= I2S_TXCR_VDW(8);380		break;381	case SNDRV_PCM_FORMAT_S16_LE:382		val |= I2S_TXCR_VDW(16);383		break;384	case SNDRV_PCM_FORMAT_S20_3LE:385		val |= I2S_TXCR_VDW(20);386		break;387	case SNDRV_PCM_FORMAT_S24_LE:388		val |= I2S_TXCR_VDW(24);389		break;390	case SNDRV_PCM_FORMAT_S32_LE:391		val |= I2S_TXCR_VDW(32);392		break;393	default:394		return -EINVAL;395	}396 397	switch (params_channels(params)) {398	case 8:399		val |= I2S_CHN_8;400		break;401	case 6:402		val |= I2S_CHN_6;403		break;404	case 4:405		val |= I2S_CHN_4;406		break;407	case 2:408		val |= I2S_CHN_2;409		break;410	default:411		dev_err(i2s->dev, "invalid channel: %d\n",412			params_channels(params));413		return -EINVAL;414	}415 416	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)417		regmap_update_bits(i2s->regmap, I2S_RXCR,418				   I2S_RXCR_VDW_MASK | I2S_RXCR_CSR_MASK,419				   val);420	else421		regmap_update_bits(i2s->regmap, I2S_TXCR,422				   I2S_TXCR_VDW_MASK | I2S_TXCR_CSR_MASK,423				   val);424 425	if (!IS_ERR(i2s->grf) && i2s->pins) {426		regmap_read(i2s->regmap, I2S_TXCR, &val);427		val &= I2S_TXCR_CSR_MASK;428 429		switch (val) {430		case I2S_CHN_4:431			val = I2S_IO_4CH_OUT_6CH_IN;432			break;433		case I2S_CHN_6:434			val = I2S_IO_6CH_OUT_4CH_IN;435			break;436		case I2S_CHN_8:437			val = I2S_IO_8CH_OUT_2CH_IN;438			break;439		default:440			val = I2S_IO_2CH_OUT_8CH_IN;441			break;442		}443 444		val <<= i2s->pins->shift;445		val |= (I2S_IO_DIRECTION_MASK << i2s->pins->shift) << 16;446		regmap_write(i2s->grf, i2s->pins->reg_offset, val);447	}448 449	regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK,450			   I2S_DMACR_TDL(16));451	regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK,452			   I2S_DMACR_RDL(16));453 454	val = I2S_CKR_TRCM_TXRX;455	if (dai->driver->symmetric_rate && rtd->dai_link->symmetric_rate)456		val = I2S_CKR_TRCM_TXONLY;457 458	regmap_update_bits(i2s->regmap, I2S_CKR,459			   I2S_CKR_TRCM_MASK,460			   val);461	return 0;462}463 464static int rockchip_i2s_trigger(struct snd_pcm_substream *substream,465				int cmd, struct snd_soc_dai *dai)466{467	struct rk_i2s_dev *i2s = to_info(dai);468	int ret = 0;469 470	switch (cmd) {471	case SNDRV_PCM_TRIGGER_START:472	case SNDRV_PCM_TRIGGER_RESUME:473	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:474		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)475			ret = rockchip_snd_rxctrl(i2s, 1);476		else477			ret = rockchip_snd_txctrl(i2s, 1);478		if (ret < 0)479			return ret;480		i2s_pinctrl_select_bclk_on(i2s);481		break;482	case SNDRV_PCM_TRIGGER_SUSPEND:483	case SNDRV_PCM_TRIGGER_STOP:484	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:485		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {486			if (!i2s->tx_start)487				i2s_pinctrl_select_bclk_off(i2s);488			ret = rockchip_snd_rxctrl(i2s, 0);489		} else {490			if (!i2s->rx_start)491				i2s_pinctrl_select_bclk_off(i2s);492			ret = rockchip_snd_txctrl(i2s, 0);493		}494		break;495	default:496		ret = -EINVAL;497		break;498	}499 500	return ret;501}502 503static int rockchip_i2s_set_bclk_ratio(struct snd_soc_dai *dai,504				       unsigned int ratio)505{506	struct rk_i2s_dev *i2s = to_info(dai);507 508	i2s->bclk_ratio = ratio;509 510	return 0;511}512 513static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,514				   unsigned int freq, int dir)515{516	struct rk_i2s_dev *i2s = to_info(cpu_dai);517	int ret;518 519	if (freq == 0)520		return 0;521 522	ret = clk_set_rate(i2s->mclk, freq);523	if (ret)524		dev_err(i2s->dev, "Fail to set mclk %d\n", ret);525 526	return ret;527}528 529static int rockchip_i2s_dai_probe(struct snd_soc_dai *dai)530{531	struct rk_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai);532 533	snd_soc_dai_init_dma_data(dai,534		i2s->has_playback ? &i2s->playback_dma_data : NULL,535		i2s->has_capture  ? &i2s->capture_dma_data  : NULL);536 537	return 0;538}539 540static const struct snd_soc_dai_ops rockchip_i2s_dai_ops = {541	.probe = rockchip_i2s_dai_probe,542	.hw_params = rockchip_i2s_hw_params,543	.set_bclk_ratio	= rockchip_i2s_set_bclk_ratio,544	.set_sysclk = rockchip_i2s_set_sysclk,545	.set_fmt = rockchip_i2s_set_fmt,546	.trigger = rockchip_i2s_trigger,547};548 549static struct snd_soc_dai_driver rockchip_i2s_dai = {550	.ops = &rockchip_i2s_dai_ops,551	.symmetric_rate = 1,552};553 554static const struct snd_soc_component_driver rockchip_i2s_component = {555	.name = DRV_NAME,556	.legacy_dai_naming = 1,557};558 559static bool rockchip_i2s_wr_reg(struct device *dev, unsigned int reg)560{561	switch (reg) {562	case I2S_TXCR:563	case I2S_RXCR:564	case I2S_CKR:565	case I2S_DMACR:566	case I2S_INTCR:567	case I2S_XFER:568	case I2S_CLR:569	case I2S_TXDR:570		return true;571	default:572		return false;573	}574}575 576static bool rockchip_i2s_rd_reg(struct device *dev, unsigned int reg)577{578	switch (reg) {579	case I2S_TXCR:580	case I2S_RXCR:581	case I2S_CKR:582	case I2S_DMACR:583	case I2S_INTCR:584	case I2S_XFER:585	case I2S_CLR:586	case I2S_TXDR:587	case I2S_RXDR:588	case I2S_FIFOLR:589	case I2S_INTSR:590		return true;591	default:592		return false;593	}594}595 596static bool rockchip_i2s_volatile_reg(struct device *dev, unsigned int reg)597{598	switch (reg) {599	case I2S_INTSR:600	case I2S_CLR:601	case I2S_FIFOLR:602	case I2S_TXDR:603	case I2S_RXDR:604		return true;605	default:606		return false;607	}608}609 610static bool rockchip_i2s_precious_reg(struct device *dev, unsigned int reg)611{612	switch (reg) {613	case I2S_RXDR:614		return true;615	default:616		return false;617	}618}619 620static const struct reg_default rockchip_i2s_reg_defaults[] = {621	{0x00, 0x0000000f},622	{0x04, 0x0000000f},623	{0x08, 0x00071f1f},624	{0x10, 0x001f0000},625	{0x14, 0x01f00000},626};627 628static const struct regmap_config rockchip_i2s_regmap_config = {629	.reg_bits = 32,630	.reg_stride = 4,631	.val_bits = 32,632	.max_register = I2S_RXDR,633	.reg_defaults = rockchip_i2s_reg_defaults,634	.num_reg_defaults = ARRAY_SIZE(rockchip_i2s_reg_defaults),635	.writeable_reg = rockchip_i2s_wr_reg,636	.readable_reg = rockchip_i2s_rd_reg,637	.volatile_reg = rockchip_i2s_volatile_reg,638	.precious_reg = rockchip_i2s_precious_reg,639	.cache_type = REGCACHE_FLAT,640};641 642static const struct rk_i2s_pins rk3399_i2s_pins = {643	.reg_offset = 0xe220,644	.shift = 11,645};646 647static const struct of_device_id rockchip_i2s_match[] __maybe_unused = {648	{ .compatible = "rockchip,px30-i2s", },649	{ .compatible = "rockchip,rk1808-i2s", },650	{ .compatible = "rockchip,rk3036-i2s", },651	{ .compatible = "rockchip,rk3066-i2s", },652	{ .compatible = "rockchip,rk3128-i2s", },653	{ .compatible = "rockchip,rk3188-i2s", },654	{ .compatible = "rockchip,rk3228-i2s", },655	{ .compatible = "rockchip,rk3288-i2s", },656	{ .compatible = "rockchip,rk3308-i2s", },657	{ .compatible = "rockchip,rk3328-i2s", },658	{ .compatible = "rockchip,rk3366-i2s", },659	{ .compatible = "rockchip,rk3368-i2s", },660	{ .compatible = "rockchip,rk3399-i2s", .data = &rk3399_i2s_pins },661	{ .compatible = "rockchip,rk3588-i2s", },662	{ .compatible = "rockchip,rv1126-i2s", },663	{},664};665 666static int rockchip_i2s_init_dai(struct rk_i2s_dev *i2s, struct resource *res,667				 struct snd_soc_dai_driver **dp)668{669	struct device_node *node = i2s->dev->of_node;670	struct snd_soc_dai_driver *dai;671	struct property *dma_names;672	const char *dma_name;673	unsigned int val;674 675	of_property_for_each_string(node, "dma-names", dma_names, dma_name) {676		if (!strcmp(dma_name, "tx"))677			i2s->has_playback = true;678		if (!strcmp(dma_name, "rx"))679			i2s->has_capture = true;680	}681 682	dai = devm_kmemdup(i2s->dev, &rockchip_i2s_dai,683			   sizeof(*dai), GFP_KERNEL);684	if (!dai)685		return -ENOMEM;686 687	if (i2s->has_playback) {688		dai->playback.stream_name = "Playback";689		dai->playback.channels_min = 2;690		dai->playback.channels_max = 8;691		dai->playback.rates = SNDRV_PCM_RATE_8000_192000;692		dai->playback.formats = SNDRV_PCM_FMTBIT_S8 |693					SNDRV_PCM_FMTBIT_S16_LE |694					SNDRV_PCM_FMTBIT_S20_3LE |695					SNDRV_PCM_FMTBIT_S24_LE |696					SNDRV_PCM_FMTBIT_S32_LE;697 698		i2s->playback_dma_data.addr = res->start + I2S_TXDR;699		i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;700		i2s->playback_dma_data.maxburst = 8;701 702		if (!of_property_read_u32(node, "rockchip,playback-channels", &val)) {703			if (val >= 2 && val <= 8)704				dai->playback.channels_max = val;705		}706	}707 708	if (i2s->has_capture) {709		dai->capture.stream_name = "Capture";710		dai->capture.channels_min = 2;711		dai->capture.channels_max = 8;712		dai->capture.rates = SNDRV_PCM_RATE_8000_192000;713		dai->capture.formats = SNDRV_PCM_FMTBIT_S8 |714				       SNDRV_PCM_FMTBIT_S16_LE |715				       SNDRV_PCM_FMTBIT_S20_3LE |716				       SNDRV_PCM_FMTBIT_S24_LE |717				       SNDRV_PCM_FMTBIT_S32_LE;718 719		i2s->capture_dma_data.addr = res->start + I2S_RXDR;720		i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;721		i2s->capture_dma_data.maxburst = 8;722 723		if (!of_property_read_u32(node, "rockchip,capture-channels", &val)) {724			if (val >= 2 && val <= 8)725				dai->capture.channels_max = val;726		}727	}728 729	if (dp)730		*dp = dai;731 732	return 0;733}734 735static int rockchip_i2s_probe(struct platform_device *pdev)736{737	struct device_node *node = pdev->dev.of_node;738	struct rk_i2s_dev *i2s;739	struct snd_soc_dai_driver *dai;740	struct resource *res;741	void __iomem *regs;742	int ret;743 744	i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);745	if (!i2s)746		return -ENOMEM;747 748	spin_lock_init(&i2s->lock);749	i2s->dev = &pdev->dev;750 751	i2s->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf");752	if (!IS_ERR(i2s->grf)) {753		i2s->pins = device_get_match_data(&pdev->dev);754		if (!i2s->pins)755			return -EINVAL;756 757	}758 759	/* try to prepare related clocks */760	i2s->hclk = devm_clk_get(&pdev->dev, "i2s_hclk");761	if (IS_ERR(i2s->hclk)) {762		dev_err(&pdev->dev, "Can't retrieve i2s bus clock\n");763		return PTR_ERR(i2s->hclk);764	}765	ret = clk_prepare_enable(i2s->hclk);766	if (ret) {767		dev_err(i2s->dev, "hclock enable failed %d\n", ret);768		return ret;769	}770 771	i2s->mclk = devm_clk_get(&pdev->dev, "i2s_clk");772	if (IS_ERR(i2s->mclk)) {773		dev_err(&pdev->dev, "Can't retrieve i2s master clock\n");774		ret = PTR_ERR(i2s->mclk);775		goto err_clk;776	}777 778	regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);779	if (IS_ERR(regs)) {780		ret = PTR_ERR(regs);781		goto err_clk;782	}783 784	i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs,785					    &rockchip_i2s_regmap_config);786	if (IS_ERR(i2s->regmap)) {787		dev_err(&pdev->dev,788			"Failed to initialise managed register map\n");789		ret = PTR_ERR(i2s->regmap);790		goto err_clk;791	}792 793	i2s->bclk_ratio = 64;794	i2s->pinctrl = devm_pinctrl_get(&pdev->dev);795	if (!IS_ERR(i2s->pinctrl)) {796		i2s->bclk_on = pinctrl_lookup_state(i2s->pinctrl, "bclk_on");797		if (!IS_ERR_OR_NULL(i2s->bclk_on)) {798			i2s->bclk_off = pinctrl_lookup_state(i2s->pinctrl, "bclk_off");799			if (IS_ERR_OR_NULL(i2s->bclk_off)) {800				dev_err(&pdev->dev, "failed to find i2s bclk_off\n");801				ret = -EINVAL;802				goto err_clk;803			}804		}805	} else {806		dev_dbg(&pdev->dev, "failed to find i2s pinctrl\n");807	}808 809	i2s_pinctrl_select_bclk_off(i2s);810 811	dev_set_drvdata(&pdev->dev, i2s);812 813	pm_runtime_enable(&pdev->dev);814	if (!pm_runtime_enabled(&pdev->dev)) {815		ret = i2s_runtime_resume(&pdev->dev);816		if (ret)817			goto err_pm_disable;818	}819 820	ret = rockchip_i2s_init_dai(i2s, res, &dai);821	if (ret)822		goto err_pm_disable;823 824	ret = devm_snd_soc_register_component(&pdev->dev,825					      &rockchip_i2s_component,826					      dai, 1);827 828	if (ret) {829		dev_err(&pdev->dev, "Could not register DAI\n");830		goto err_suspend;831	}832 833	ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);834	if (ret) {835		dev_err(&pdev->dev, "Could not register PCM\n");836		goto err_suspend;837	}838 839	return 0;840 841err_suspend:842	if (!pm_runtime_status_suspended(&pdev->dev))843		i2s_runtime_suspend(&pdev->dev);844err_pm_disable:845	pm_runtime_disable(&pdev->dev);846err_clk:847	clk_disable_unprepare(i2s->hclk);848	return ret;849}850 851static void rockchip_i2s_remove(struct platform_device *pdev)852{853	struct rk_i2s_dev *i2s = dev_get_drvdata(&pdev->dev);854 855	pm_runtime_disable(&pdev->dev);856	if (!pm_runtime_status_suspended(&pdev->dev))857		i2s_runtime_suspend(&pdev->dev);858 859	clk_disable_unprepare(i2s->hclk);860}861 862static const struct dev_pm_ops rockchip_i2s_pm_ops = {863	SET_RUNTIME_PM_OPS(i2s_runtime_suspend, i2s_runtime_resume,864			   NULL)865};866 867static struct platform_driver rockchip_i2s_driver = {868	.probe = rockchip_i2s_probe,869	.remove = rockchip_i2s_remove,870	.driver = {871		.name = DRV_NAME,872		.of_match_table = of_match_ptr(rockchip_i2s_match),873		.pm = &rockchip_i2s_pm_ops,874	},875};876module_platform_driver(rockchip_i2s_driver);877 878MODULE_DESCRIPTION("ROCKCHIP IIS ASoC Interface");879MODULE_AUTHOR("jianqun <jay.xu@rock-chips.com>");880MODULE_LICENSE("GPL v2");881MODULE_ALIAS("platform:" DRV_NAME);882MODULE_DEVICE_TABLE(of, rockchip_i2s_match);883