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