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