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