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