xref: /OK3568_Linux_fs/u-boot/drivers/sound/rockchip-i2s.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier:     GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * (C) Copyright 2018 Rockchip Electronics Co., Ltd
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #include <clk.h>
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <dm.h>
9*4882a593Smuzhiyun #include <errno.h>
10*4882a593Smuzhiyun #include <malloc.h>
11*4882a593Smuzhiyun #include <asm/io.h>
12*4882a593Smuzhiyun #include <sound.h>
13*4882a593Smuzhiyun #include "rockchip-i2s.h"
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #define I2S_FIFO_LENGTH (31)
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun struct rk_i2s_dev {
18*4882a593Smuzhiyun 	void *regbase;
19*4882a593Smuzhiyun 	struct clk mclk;
20*4882a593Smuzhiyun };
21*4882a593Smuzhiyun 
i2s_reg_readl(struct rk_i2s_dev * dev,u32 offset)22*4882a593Smuzhiyun static inline u32 i2s_reg_readl(struct rk_i2s_dev *dev, u32 offset)
23*4882a593Smuzhiyun {
24*4882a593Smuzhiyun 	return readl(dev->regbase + offset);
25*4882a593Smuzhiyun }
26*4882a593Smuzhiyun 
i2s_reg_writel(struct rk_i2s_dev * dev,u32 offset,u32 val)27*4882a593Smuzhiyun static inline void i2s_reg_writel(struct rk_i2s_dev *dev, u32 offset, u32 val)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun 	writel(val, dev->regbase + offset);
30*4882a593Smuzhiyun }
31*4882a593Smuzhiyun 
i2s_reg_update_bits(struct rk_i2s_dev * dev,u32 offset,u32 mask,u32 val)32*4882a593Smuzhiyun static inline void i2s_reg_update_bits(struct rk_i2s_dev *dev, u32 offset,
33*4882a593Smuzhiyun 				       u32 mask, u32 val)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun 	u32 tmp, orig;
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun 	orig = readl(dev->regbase + offset);
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 	tmp = orig & ~mask;
40*4882a593Smuzhiyun 	tmp |= val & mask;
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun 	if (tmp != orig)
43*4882a593Smuzhiyun 		writel(tmp, dev->regbase + offset);
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun 
dump_regs(struct rk_i2s_dev * dev)46*4882a593Smuzhiyun static void dump_regs(struct rk_i2s_dev *dev)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun 	int i = 0;
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	for (i = 0; i <= I2S_RXDR; i += 4)
51*4882a593Smuzhiyun 		debug("0x%02x: 0x%08x\n", i, readl(dev->regbase + i));
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun 
rk_i2s_hw_params(struct udevice * udev,unsigned int samplerate,unsigned int fmt,unsigned int channels)54*4882a593Smuzhiyun static int rk_i2s_hw_params(struct udevice *udev, unsigned int samplerate,
55*4882a593Smuzhiyun 			    unsigned int fmt, unsigned int channels)
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun 	struct rk_i2s_dev *dev = dev_get_priv(udev);
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 	/* set fmt */
60*4882a593Smuzhiyun 	i2s_reg_update_bits(dev, I2S_CKR,
61*4882a593Smuzhiyun 			    I2S_CKR_MSS_MASK, I2S_CKR_MSS_MASTER);
62*4882a593Smuzhiyun 	i2s_reg_update_bits(dev, I2S_TXCR,
63*4882a593Smuzhiyun 			    I2S_TXCR_IBM_MASK, I2S_TXCR_IBM_NORMAL);
64*4882a593Smuzhiyun 	i2s_reg_update_bits(dev, I2S_RXCR,
65*4882a593Smuzhiyun 			    I2S_RXCR_IBM_MASK, I2S_RXCR_IBM_NORMAL);
66*4882a593Smuzhiyun 	/* set div */
67*4882a593Smuzhiyun 	i2s_reg_update_bits(dev, I2S_CKR,
68*4882a593Smuzhiyun 			    I2S_CKR_TSD_MASK | I2S_CKR_RSD_MASK,
69*4882a593Smuzhiyun 			    I2S_CKR_TSD(64) | I2S_CKR_RSD(64));
70*4882a593Smuzhiyun 	i2s_reg_update_bits(dev, I2S_CKR,
71*4882a593Smuzhiyun 			    I2S_CKR_MDIV_MASK, I2S_CKR_MDIV(4));
72*4882a593Smuzhiyun 	/* set hwparams */
73*4882a593Smuzhiyun 	i2s_reg_update_bits(dev, I2S_TXCR,
74*4882a593Smuzhiyun 			    I2S_TXCR_VDW_MASK |
75*4882a593Smuzhiyun 			    I2S_TXCR_CSR_MASK,
76*4882a593Smuzhiyun 			    I2S_TXCR_VDW(16) |
77*4882a593Smuzhiyun 			    I2S_TXCR_CHN_2);
78*4882a593Smuzhiyun 	i2s_reg_update_bits(dev, I2S_RXCR,
79*4882a593Smuzhiyun 			    I2S_RXCR_CSR_MASK |
80*4882a593Smuzhiyun 			    I2S_RXCR_VDW_MASK,
81*4882a593Smuzhiyun 			    I2S_TXCR_VDW(16) |
82*4882a593Smuzhiyun 			    I2S_TXCR_CHN_2);
83*4882a593Smuzhiyun 	i2s_reg_update_bits(dev, I2S_DMACR,
84*4882a593Smuzhiyun 			    I2S_DMACR_TDL_MASK | I2S_DMACR_RDL_MASK,
85*4882a593Smuzhiyun 			    I2S_DMACR_TDL(16) | I2S_DMACR_RDL(16));
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	return 0;
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun 
rk_i2s_txctrl(struct rk_i2s_dev * dev,int on)90*4882a593Smuzhiyun static void rk_i2s_txctrl(struct rk_i2s_dev *dev, int on)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun 	if (on) {
93*4882a593Smuzhiyun 		i2s_reg_update_bits(dev, I2S_XFER,
94*4882a593Smuzhiyun 				    I2S_XFER_TXS_MASK | I2S_XFER_RXS_MASK,
95*4882a593Smuzhiyun 				    I2S_XFER_TXS_START | I2S_XFER_RXS_START);
96*4882a593Smuzhiyun 	} else {
97*4882a593Smuzhiyun 		i2s_reg_update_bits(dev, I2S_XFER,
98*4882a593Smuzhiyun 				    I2S_XFER_TXS_MASK |
99*4882a593Smuzhiyun 				    I2S_XFER_RXS_MASK,
100*4882a593Smuzhiyun 				    I2S_XFER_TXS_STOP |
101*4882a593Smuzhiyun 				    I2S_XFER_RXS_STOP);
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 		i2s_reg_update_bits(dev, I2S_CLR,
104*4882a593Smuzhiyun 				    I2S_CLR_TXC_MASK | I2S_CLR_RXC_MASK,
105*4882a593Smuzhiyun 				    I2S_CLR_TXC | I2S_CLR_RXC);
106*4882a593Smuzhiyun 	}
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun 
rk_i2s_transfer_tx_data(struct udevice * udev,unsigned int * data,unsigned long data_size)109*4882a593Smuzhiyun static int rk_i2s_transfer_tx_data(struct udevice *udev, unsigned int *data,
110*4882a593Smuzhiyun 				   unsigned long data_size)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun 	struct rk_i2s_dev *dev = dev_get_priv(udev);
113*4882a593Smuzhiyun 	u32 val;
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 	if (data_size < I2S_FIFO_LENGTH) {
116*4882a593Smuzhiyun 		debug("%s : invalid data size\n", __func__);
117*4882a593Smuzhiyun 		return -EINVAL;
118*4882a593Smuzhiyun 	}
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	rk_i2s_txctrl(dev, 1);
121*4882a593Smuzhiyun 	while (data_size > 0) {
122*4882a593Smuzhiyun 		val = i2s_reg_readl(dev, I2S_FIFOLR);
123*4882a593Smuzhiyun 		if (val < I2S_FIFO_LENGTH) {
124*4882a593Smuzhiyun 			i2s_reg_writel(dev, I2S_TXDR, *data++);
125*4882a593Smuzhiyun 			data_size--;
126*4882a593Smuzhiyun 		}
127*4882a593Smuzhiyun 	}
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	return 0;
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun 
rk_i2s_set_sysclk(struct udevice * dev,unsigned int freq)132*4882a593Smuzhiyun static int rk_i2s_set_sysclk(struct udevice *dev, unsigned int freq)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun 	struct rk_i2s_dev *i2s = dev_get_priv(dev);
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	clk_set_rate(&i2s->mclk, freq);
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	return 0;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun static const struct snd_soc_dai_ops rockchip_i2s_ops = {
142*4882a593Smuzhiyun 	.hw_params = rk_i2s_hw_params,
143*4882a593Smuzhiyun 	.set_sysclk = rk_i2s_set_sysclk,
144*4882a593Smuzhiyun 	.transfer = rk_i2s_transfer_tx_data,
145*4882a593Smuzhiyun };
146*4882a593Smuzhiyun 
rockchip_i2s_probe(struct udevice * dev)147*4882a593Smuzhiyun static int rockchip_i2s_probe(struct udevice *dev)
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun 	struct rk_i2s_dev *i2s = dev_get_priv(dev);
150*4882a593Smuzhiyun 	int ret;
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	i2s->regbase = dev_read_addr_ptr(dev);
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	ret = clk_get_by_name(dev, "i2s_clk", &i2s->mclk);
155*4882a593Smuzhiyun 	if (ret) {
156*4882a593Smuzhiyun 		printf("%s get i2s mclk fail!\n", __func__);
157*4882a593Smuzhiyun 		return -EINVAL;
158*4882a593Smuzhiyun 	}
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	dump_regs(i2s);
161*4882a593Smuzhiyun 	return 0;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun static const struct udevice_id rockchip_i2s_ids[] = {
165*4882a593Smuzhiyun 	{ .compatible = "rockchip,px30-i2s", },
166*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk3036-i2s", },
167*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk3066-i2s", },
168*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk3128-i2s", },
169*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk3188-i2s", },
170*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk3288-i2s", },
171*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk3328-i2s", },
172*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk3368-i2s", },
173*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk3399-i2s", },
174*4882a593Smuzhiyun 	{ }
175*4882a593Smuzhiyun };
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun U_BOOT_DRIVER(rockchip_i2s) = {
178*4882a593Smuzhiyun 	.name = "rockchip_i2s",
179*4882a593Smuzhiyun 	.id = UCLASS_I2S,
180*4882a593Smuzhiyun 	.of_match = rockchip_i2s_ids,
181*4882a593Smuzhiyun 	.probe = rockchip_i2s_probe,
182*4882a593Smuzhiyun 	.priv_auto_alloc_size = sizeof(struct rk_i2s_dev),
183*4882a593Smuzhiyun 	.ops = &rockchip_i2s_ops,
184*4882a593Smuzhiyun };
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun UCLASS_DRIVER(i2s) = {
187*4882a593Smuzhiyun 	.id = UCLASS_I2S,
188*4882a593Smuzhiyun 	.name = "i2s_bus",
189*4882a593Smuzhiyun };
190