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