From 2850266965ade165f913a66f679a0449faf21180 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 16 Feb 2019 20:24:54 -0700 Subject: sound: Add uclass operations for beeping Some audio codecs such as Intel HDA do not need to use digital data to play sounds, but instead have a way to emit beeps. Add this interface as an option. If the beep interface is not supported, then the sound uclass falls back to the I2S interface. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/sound/sandbox.c | 46 +++++++++++++++++++++++++++++++++++++++++--- drivers/sound/sound-uclass.c | 34 +++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 4 deletions(-) (limited to 'drivers/sound') diff --git a/drivers/sound/sandbox.c b/drivers/sound/sandbox.c index b0b07f3239..600523160f 100644 --- a/drivers/sound/sandbox.c +++ b/drivers/sound/sandbox.c @@ -24,7 +24,9 @@ struct sandbox_i2s_priv { struct sandbox_sound_priv { int setup_called; - int sum; /* Use to sum the provided audio data */ + int sum; /* Use to sum the provided audio data */ + bool allow_beep; /* true to allow the start_beep() interface */ + int frequency_hz; /* Beep frequency if active, else 0 */ }; void sandbox_get_codec_params(struct udevice *dev, int *interfacep, int *ratep, @@ -61,6 +63,20 @@ int sandbox_get_sound_sum(struct udevice *dev) return priv->sum; } +void sandbox_set_allow_beep(struct udevice *dev, bool allow) +{ + struct sandbox_sound_priv *priv = dev_get_priv(dev); + + priv->allow_beep = allow; +} + +int sandbox_get_beep_frequency(struct udevice *dev) +{ + struct sandbox_sound_priv *priv = dev_get_priv(dev); + + return priv->frequency_hz; +} + static int sandbox_codec_set_params(struct udevice *dev, int interface, int rate, int mclk_freq, int bits_per_sample, uint channels) @@ -128,6 +144,28 @@ static int sandbox_sound_play(struct udevice *dev, void *data, uint data_size) return i2s_tx_data(uc_priv->i2s, data, data_size); } +int sandbox_sound_start_beep(struct udevice *dev, int frequency_hz) +{ + struct sandbox_sound_priv *priv = dev_get_priv(dev); + + if (!priv->allow_beep) + return -ENOSYS; + priv->frequency_hz = frequency_hz; + + return 0; +} + +int sandbox_sound_stop_beep(struct udevice *dev) +{ + struct sandbox_sound_priv *priv = dev_get_priv(dev); + + if (!priv->allow_beep) + return -ENOSYS; + priv->frequency_hz = 0; + + return 0; +} + static int sandbox_sound_probe(struct udevice *dev) { return sound_find_codec_i2s(dev); @@ -169,8 +207,10 @@ U_BOOT_DRIVER(sandbox_i2s) = { }; static const struct sound_ops sandbox_sound_ops = { - .setup = sandbox_sound_setup, - .play = sandbox_sound_play, + .setup = sandbox_sound_setup, + .play = sandbox_sound_play, + .start_beep = sandbox_sound_start_beep, + .stop_beep = sandbox_sound_stop_beep, }; static const struct udevice_id sandbox_sound_ids[] = { diff --git a/drivers/sound/sound-uclass.c b/drivers/sound/sound-uclass.c index 067660623b..d49f29bcd5 100644 --- a/drivers/sound/sound-uclass.c +++ b/drivers/sound/sound-uclass.c @@ -31,10 +31,30 @@ int sound_play(struct udevice *dev, void *data, uint data_size) return ops->play(dev, data, data_size); } +int sound_start_beep(struct udevice *dev, int frequency_hz) +{ + struct sound_ops *ops = sound_get_ops(dev); + + if (!ops->start_beep) + return -ENOSYS; + + return ops->start_beep(dev, frequency_hz); +} + +int sound_stop_beep(struct udevice *dev) +{ + struct sound_ops *ops = sound_get_ops(dev); + + if (!ops->stop_beep) + return -ENOSYS; + + return ops->stop_beep(dev); +} + int sound_beep(struct udevice *dev, int msecs, int frequency_hz) { struct sound_uc_priv *uc_priv = dev_get_uclass_priv(dev); - struct i2s_uc_priv *i2s_uc_priv = dev_get_uclass_priv(uc_priv->i2s); + struct i2s_uc_priv *i2s_uc_priv; unsigned short *data; uint data_size; int ret; @@ -43,7 +63,19 @@ int sound_beep(struct udevice *dev, int msecs, int frequency_hz) if (ret && ret != -EALREADY) return ret; + /* Try using the beep interface if available */ + ret = sound_start_beep(dev, frequency_hz); + if (ret != -ENOSYS) { + if (ret) + return ret; + mdelay(msecs); + ret = sound_stop_beep(dev); + + return ret; + } + /* Buffer length computation */ + i2s_uc_priv = dev_get_uclass_priv(uc_priv->i2s); data_size = i2s_uc_priv->samplingrate * i2s_uc_priv->channels; data_size *= (i2s_uc_priv->bitspersample / SOUND_BITS_IN_BYTE); data = malloc(data_size); -- cgit v1.2.3