xref: /OK3568_Linux_fs/u-boot/drivers/sound/rockchip-sound.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 <dm.h>
7*4882a593Smuzhiyun #include <malloc.h>
8*4882a593Smuzhiyun #include <common.h>
9*4882a593Smuzhiyun #include <asm/io.h>
10*4882a593Smuzhiyun #include <linux/libfdt.h>
11*4882a593Smuzhiyun #include <fdtdec.h>
12*4882a593Smuzhiyun #include <i2s.h>
13*4882a593Smuzhiyun #include <sound.h>
14*4882a593Smuzhiyun #include <asm/arch-rockchip/resource_img.h>
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #define WAV_SIZE		(5 * 1024 * 1024) /* BYTE */
17*4882a593Smuzhiyun #define SAMPLERATE		44100
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun static struct udevice *i2s_dev, *codec_dev;
20*4882a593Smuzhiyun 
load_audio_wav(void * buf,const char * wav_name,int size)21*4882a593Smuzhiyun static int load_audio_wav(void *buf, const char *wav_name, int size)
22*4882a593Smuzhiyun {
23*4882a593Smuzhiyun 	int ret = 0;
24*4882a593Smuzhiyun #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE
25*4882a593Smuzhiyun 	ret = rockchip_read_resource_file(buf, wav_name, 0, size);
26*4882a593Smuzhiyun #endif
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun 	return ret;
29*4882a593Smuzhiyun }
30*4882a593Smuzhiyun 
sound_hw_params(struct udevice * dev,unsigned int samplerate,unsigned int fmt,unsigned int channels)31*4882a593Smuzhiyun static int sound_hw_params(struct udevice *dev, unsigned int samplerate,
32*4882a593Smuzhiyun 			   unsigned int fmt, unsigned int channels)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun 	const struct snd_soc_dai_ops *ops = dev_get_driver_ops(dev);
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun 	if (!ops || !ops->hw_params)
37*4882a593Smuzhiyun 		return -ENOTSUPP;
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 	return ops->hw_params(dev, samplerate, fmt, channels);
40*4882a593Smuzhiyun }
41*4882a593Smuzhiyun 
sound_startup(struct udevice * dev)42*4882a593Smuzhiyun static int sound_startup(struct udevice *dev)
43*4882a593Smuzhiyun {
44*4882a593Smuzhiyun 	const struct snd_soc_dai_ops *ops = dev_get_driver_ops(dev);
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	if (!ops || !ops->startup)
47*4882a593Smuzhiyun 		return -ENOTSUPP;
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 	return ops->startup(dev);
50*4882a593Smuzhiyun }
51*4882a593Smuzhiyun 
sound_set_sysclk(struct udevice * dev,unsigned int freq)52*4882a593Smuzhiyun static int sound_set_sysclk(struct udevice *dev, unsigned int freq)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun 	const struct snd_soc_dai_ops *ops = dev_get_driver_ops(dev);
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 	if (!ops || !ops->set_sysclk)
57*4882a593Smuzhiyun 		return -ENOTSUPP;
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 	return ops->set_sysclk(dev, freq);
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun 
sound_init(const void * blob)62*4882a593Smuzhiyun int sound_init(const void *blob)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun 	int ret;
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 	ret = uclass_get_device(UCLASS_I2S, 0, &i2s_dev);
67*4882a593Smuzhiyun 	if (ret) {
68*4882a593Smuzhiyun 		if (ret != -ENODEV) {
69*4882a593Smuzhiyun 			printf("Get i2s device failed: %d\n", ret);
70*4882a593Smuzhiyun 			return ret;
71*4882a593Smuzhiyun 		}
72*4882a593Smuzhiyun 		return 0;
73*4882a593Smuzhiyun 	}
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	ret = uclass_get_device(UCLASS_CODEC, 0, &codec_dev);
76*4882a593Smuzhiyun 	if (ret) {
77*4882a593Smuzhiyun 		if (ret != -ENODEV) {
78*4882a593Smuzhiyun 			printf("Get codec device failed: %d\n", ret);
79*4882a593Smuzhiyun 			return ret;
80*4882a593Smuzhiyun 		}
81*4882a593Smuzhiyun 		return 0;
82*4882a593Smuzhiyun 	}
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	sound_set_sysclk(i2s_dev, SAMPLERATE * 256);
85*4882a593Smuzhiyun 	sound_hw_params(i2s_dev, SAMPLERATE, 16, 2);
86*4882a593Smuzhiyun 	sound_hw_params(codec_dev, SAMPLERATE, 16, 2);
87*4882a593Smuzhiyun 	sound_startup(i2s_dev);
88*4882a593Smuzhiyun 	sound_startup(codec_dev);
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	return ret;
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun 
_sound_play(struct udevice * dev,unsigned int * data,unsigned long data_size)93*4882a593Smuzhiyun static int _sound_play(struct udevice *dev, unsigned int *data,
94*4882a593Smuzhiyun 		       unsigned long data_size)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 	const struct snd_soc_dai_ops *ops = dev_get_driver_ops(dev);
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	if (!ops || !ops->transfer)
99*4882a593Smuzhiyun 		return -ENOTSUPP;
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	return ops->transfer(dev, data, data_size);
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun 
sound_play(u32 msec,u32 frequency)104*4882a593Smuzhiyun int sound_play(u32 msec, u32 frequency)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun 	unsigned int *buf;
107*4882a593Smuzhiyun 	unsigned long buf_size;
108*4882a593Smuzhiyun 	unsigned int ret = 0;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	buf_size = WAV_SIZE;
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	buf = malloc(buf_size);
113*4882a593Smuzhiyun 	if (!buf) {
114*4882a593Smuzhiyun 		debug("%s: buf malloc failed\n", __func__);
115*4882a593Smuzhiyun 		return -ENOMEM;
116*4882a593Smuzhiyun 	}
117*4882a593Smuzhiyun 	ret = load_audio_wav(buf, "boot.wav", buf_size);
118*4882a593Smuzhiyun 	/* if boot.wav not find, use sound_create_square_wave */
119*4882a593Smuzhiyun 	if (ret <= 0)
120*4882a593Smuzhiyun 		sound_create_square_wave((unsigned short *)buf,
121*4882a593Smuzhiyun 					 buf_size / sizeof(unsigned short),
122*4882a593Smuzhiyun 					 frequency);
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	ret = _sound_play(i2s_dev, buf, (buf_size / sizeof(int)));
125*4882a593Smuzhiyun 	free(buf);
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	return ret;
128*4882a593Smuzhiyun }
129