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 <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
This commit is contained in:
Simon Glass
2019-02-16 20:24:54 -07:00
committed by Bin Meng
parent e65f9ef9f2
commit 2850266965
5 changed files with 157 additions and 4 deletions

View File

@@ -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[] = {

View File

@@ -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);