xref: /openbmc/u-boot/drivers/sound/sandbox.c (revision 2ca47137)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2013 Google, Inc
4  */
5 
6 #include <common.h>
7 #include <audio_codec.h>
8 #include <dm.h>
9 #include <i2s.h>
10 #include <sound.h>
11 #include <asm/sdl.h>
12 
13 struct sandbox_codec_priv {
14 	int interface;
15 	int rate;
16 	int mclk_freq;
17 	int bits_per_sample;
18 	uint channels;
19 };
20 
21 struct sandbox_i2s_priv {
22 	int sum;	/* Use to sum the provided audio data */
23 };
24 
25 struct sandbox_sound_priv {
26 	int setup_called;
27 	int sum;		/* Use to sum the provided audio data */
28 	bool allow_beep;	/* true to allow the start_beep() interface */
29 	int frequency_hz;	/* Beep frequency if active, else 0 */
30 };
31 
32 void sandbox_get_codec_params(struct udevice *dev, int *interfacep, int *ratep,
33 			      int *mclk_freqp, int *bits_per_samplep,
34 			      uint *channelsp)
35 {
36 	struct sandbox_codec_priv *priv = dev_get_priv(dev);
37 
38 	*interfacep = priv->interface;
39 	*ratep = priv->rate;
40 	*mclk_freqp = priv->mclk_freq;
41 	*bits_per_samplep = priv->bits_per_sample;
42 	*channelsp = priv->channels;
43 }
44 
45 int sandbox_get_i2s_sum(struct udevice *dev)
46 {
47 	struct sandbox_i2s_priv *priv = dev_get_priv(dev);
48 
49 	return priv->sum;
50 }
51 
52 int sandbox_get_setup_called(struct udevice *dev)
53 {
54 	struct sandbox_sound_priv *priv = dev_get_priv(dev);
55 
56 	return priv->setup_called;
57 }
58 
59 int sandbox_get_sound_sum(struct udevice *dev)
60 {
61 	struct sandbox_sound_priv *priv = dev_get_priv(dev);
62 
63 	return priv->sum;
64 }
65 
66 void sandbox_set_allow_beep(struct udevice *dev, bool allow)
67 {
68 	struct sandbox_sound_priv *priv = dev_get_priv(dev);
69 
70 	priv->allow_beep = allow;
71 }
72 
73 int sandbox_get_beep_frequency(struct udevice *dev)
74 {
75 	struct sandbox_sound_priv *priv = dev_get_priv(dev);
76 
77 	return priv->frequency_hz;
78 }
79 
80 static int sandbox_codec_set_params(struct udevice *dev, int interface,
81 				    int rate, int mclk_freq,
82 				    int bits_per_sample, uint channels)
83 {
84 	struct sandbox_codec_priv *priv = dev_get_priv(dev);
85 
86 	priv->interface = interface;
87 	priv->rate = rate;
88 	priv->mclk_freq = mclk_freq;
89 	priv->bits_per_sample = bits_per_sample;
90 	priv->channels = channels;
91 
92 	return 0;
93 }
94 
95 static int sandbox_i2s_tx_data(struct udevice *dev, void *data,
96 			       uint data_size)
97 {
98 	struct sandbox_i2s_priv *priv = dev_get_priv(dev);
99 	int i;
100 
101 	for (i = 0; i < data_size; i++)
102 		priv->sum += ((uint8_t *)data)[i];
103 
104 	return sandbox_sdl_sound_play(data, data_size);
105 }
106 
107 static int sandbox_i2s_probe(struct udevice *dev)
108 {
109 	struct i2s_uc_priv *uc_priv = dev_get_uclass_priv(dev);
110 
111 	/* Use hard-coded values here */
112 	uc_priv->rfs = 256;
113 	uc_priv->bfs = 32;
114 	uc_priv->audio_pll_clk = 192000000;
115 	uc_priv->samplingrate = 48000;
116 	uc_priv->bitspersample = 16;
117 	uc_priv->channels = 2;
118 	uc_priv->id = 1;
119 
120 	/* Ignore any error here - we'll just have no sound */
121 	sandbox_sdl_sound_init(uc_priv->samplingrate, uc_priv->channels);
122 
123 	return 0;
124 }
125 
126 static int sandbox_sound_setup(struct udevice *dev)
127 {
128 	struct sandbox_sound_priv *priv = dev_get_priv(dev);
129 
130 	priv->setup_called++;
131 
132 	return 0;
133 }
134 
135 static int sandbox_sound_play(struct udevice *dev, void *data, uint data_size)
136 {
137 	struct sound_uc_priv *uc_priv = dev_get_uclass_priv(dev);
138 	struct sandbox_sound_priv *priv = dev_get_priv(dev);
139 	int i;
140 
141 	for (i = 0; i < data_size; i++)
142 		priv->sum += ((uint8_t *)data)[i];
143 
144 	return i2s_tx_data(uc_priv->i2s, data, data_size);
145 }
146 
147 int sandbox_sound_start_beep(struct udevice *dev, int frequency_hz)
148 {
149 	struct sandbox_sound_priv *priv = dev_get_priv(dev);
150 
151 	if (!priv->allow_beep)
152 		return -ENOSYS;
153 	priv->frequency_hz = frequency_hz;
154 
155 	return 0;
156 }
157 
158 int sandbox_sound_stop_beep(struct udevice *dev)
159 {
160 	struct sandbox_sound_priv *priv = dev_get_priv(dev);
161 
162 	if (!priv->allow_beep)
163 		return -ENOSYS;
164 	priv->frequency_hz = 0;
165 
166 	return 0;
167 }
168 
169 static int sandbox_sound_probe(struct udevice *dev)
170 {
171 	return sound_find_codec_i2s(dev);
172 }
173 
174 static const struct audio_codec_ops sandbox_codec_ops = {
175 	.set_params	= sandbox_codec_set_params,
176 };
177 
178 static const struct udevice_id sandbox_codec_ids[] = {
179 	{ .compatible = "sandbox,audio-codec" },
180 	{ }
181 };
182 
183 U_BOOT_DRIVER(sandbox_codec) = {
184 	.name		= "sandbox_codec",
185 	.id		= UCLASS_AUDIO_CODEC,
186 	.of_match	= sandbox_codec_ids,
187 	.ops		= &sandbox_codec_ops,
188 	.priv_auto_alloc_size	= sizeof(struct sandbox_codec_priv),
189 };
190 
191 static const struct i2s_ops sandbox_i2s_ops = {
192 	.tx_data	= sandbox_i2s_tx_data,
193 };
194 
195 static const struct udevice_id sandbox_i2s_ids[] = {
196 	{ .compatible = "sandbox,i2s" },
197 	{ }
198 };
199 
200 U_BOOT_DRIVER(sandbox_i2s) = {
201 	.name		= "sandbox_i2s",
202 	.id		= UCLASS_I2S,
203 	.of_match	= sandbox_i2s_ids,
204 	.ops		= &sandbox_i2s_ops,
205 	.probe		= sandbox_i2s_probe,
206 	.priv_auto_alloc_size	= sizeof(struct sandbox_i2s_priv),
207 };
208 
209 static const struct sound_ops sandbox_sound_ops = {
210 	.setup		= sandbox_sound_setup,
211 	.play		= sandbox_sound_play,
212 	.start_beep	= sandbox_sound_start_beep,
213 	.stop_beep	= sandbox_sound_stop_beep,
214 };
215 
216 static const struct udevice_id sandbox_sound_ids[] = {
217 	{ .compatible = "sandbox,sound" },
218 	{ }
219 };
220 
221 U_BOOT_DRIVER(sandbox_sound) = {
222 	.name		= "sandbox_sound",
223 	.id		= UCLASS_SOUND,
224 	.of_match	= sandbox_sound_ids,
225 	.ops		= &sandbox_sound_ops,
226 	.priv_auto_alloc_size	= sizeof(struct sandbox_sound_priv),
227 	.probe		= sandbox_sound_probe,
228 };
229