diff --git a/drivers/sound/Kconfig b/drivers/sound/Kconfig index dbb43509f2..9f31d8d3c1 100644 --- a/drivers/sound/Kconfig +++ b/drivers/sound/Kconfig @@ -56,6 +56,12 @@ config SOUND_RK817 Enable the rk809/rk817 audio codec. This is connected via I2S for audio data and I2C for codec control. +config SOUND_ROCKCHIP + bool "Support Rockchip Simple Sound Card" + depends on I2S_ROCKCHIP + help + Enable the Rockchip Simple Sound Card. + config SOUND_SANDBOX bool "Support sandbox emulated audio codec" depends on SANDBOX && SOUND diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile index acb0238a5e..f07887fd5d 100644 --- a/drivers/sound/Makefile +++ b/drivers/sound/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_SOUND_SANDBOX) += sandbox.o obj-$(CONFIG_SOUND_WM8994) += wm8994.o obj-$(CONFIG_SOUND_MAX98095) += max98095.o obj-$(CONFIG_SOUND_RK817) += rk817_codec.o +obj-$(CONFIG_SOUND_ROCKCHIP) += rockchip-sound.o diff --git a/drivers/sound/rockchip-sound.c b/drivers/sound/rockchip-sound.c new file mode 100644 index 0000000000..cf58725907 --- /dev/null +++ b/drivers/sound/rockchip-sound.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2018 Rockchip Electronics Co., Ltd + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WAV_SIZE (5 * 1024 * 1024) /* BYTE */ +#define SAMPLERATE 44100 + +static struct udevice *i2s_dev, *codec_dev; + +static int load_audio_wav(void *buf, const char *wav_name, int size) +{ + int ret = 0; +#ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE + ret = rockchip_read_resource_file(buf, wav_name, 0, size); +#endif + + return ret; +} + +static int sound_hw_params(struct udevice *dev, unsigned int samplerate, + unsigned int fmt, unsigned int channels) +{ + const struct snd_soc_dai_ops *ops = dev_get_driver_ops(dev); + + if (!ops || !ops->hw_params) + return -ENOTSUPP; + + return ops->hw_params(dev, samplerate, fmt, channels); +} + +static int sound_startup(struct udevice *dev) +{ + const struct snd_soc_dai_ops *ops = dev_get_driver_ops(dev); + + if (!ops || !ops->startup) + return -ENOTSUPP; + + return ops->startup(dev); +} + +static int sound_set_sysclk(struct udevice *dev, unsigned int freq) +{ + const struct snd_soc_dai_ops *ops = dev_get_driver_ops(dev); + + if (!ops || !ops->set_sysclk) + return -ENOTSUPP; + + return ops->set_sysclk(dev, freq); +} + +int sound_init(const void *blob) +{ + int ret; + + ret = uclass_get_device(UCLASS_I2S, 0, &i2s_dev); + if (ret) { + if (ret != -ENODEV) { + printf("Get i2s device failed: %d\n", ret); + return ret; + } + return 0; + } + + ret = uclass_get_device(UCLASS_CODEC, 0, &codec_dev); + if (ret) { + if (ret != -ENODEV) { + printf("Get codec device failed: %d\n", ret); + return ret; + } + return 0; + } + + sound_set_sysclk(i2s_dev, SAMPLERATE * 256); + sound_hw_params(i2s_dev, SAMPLERATE, 16, 2); + sound_hw_params(codec_dev, SAMPLERATE, 16, 2); + sound_startup(i2s_dev); + sound_startup(codec_dev); + + return ret; +} + +static int _sound_play(struct udevice *dev, unsigned int *data, + unsigned long data_size) +{ + const struct snd_soc_dai_ops *ops = dev_get_driver_ops(dev); + + if (!ops || !ops->transfer) + return -ENOTSUPP; + + return ops->transfer(dev, data, data_size); +} + +int sound_play(u32 msec, u32 frequency) +{ + unsigned int *buf; + unsigned long buf_size; + unsigned int ret = 0; + + buf_size = WAV_SIZE; + + buf = malloc(buf_size); + if (!buf) { + debug("%s: buf malloc failed\n", __func__); + return -ENOMEM; + } + ret = load_audio_wav(buf, "boot.wav", buf_size); + /* if boot.wav not find, use sound_create_square_wave */ + if (ret <= 0) + sound_create_square_wave((unsigned short *)buf, + buf_size / sizeof(unsigned short), + frequency); + + ret = _sound_play(i2s_dev, buf, (buf_size / sizeof(int))); + free(buf); + + return ret; +}