
Add a UCLASS_SOUND driver for Texas Instruments SoCs which ties together the tlv320aic3106 audio codec and MCASP I2S controller. Enable audio playback functionality by taking a data pointer and data size as the sound data. The uboot sound play command takes time and frequency as input and creates the data for a beep sound with the given parameters, which is then passed to the sound play function.
The code is based on the samsung sound driver[1] in uboot.
Link: https://gitlab.com/u-boot/u-boot/-/blob/master/drivers/sound/samsung_sound.c [1]
Signed-off-by: Scaria Kochidanadu s-kochidanadu@ti.com --- MAINTAINERS | 1 + drivers/sound/Kconfig | 10 ++++ drivers/sound/Makefile | 1 + drivers/sound/ti_sound.c | 119 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+) create mode 100644 drivers/sound/ti_sound.c
diff --git a/MAINTAINERS b/MAINTAINERS index f8afd7d51e..785afff1a7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -738,6 +738,7 @@ F: drivers/reset/reset-ti-sci.c F: drivers/rtc/davinci.c F: drivers/serial/serial_omap.c F: drivers/soc/ti/ +F: drivers/sound/ti_sound.c F: drivers/sysreset/sysreset-ti-sci.c F: drivers/thermal/ti-bandgap.c F: drivers/timer/omap-timer.c diff --git a/drivers/sound/Kconfig b/drivers/sound/Kconfig index 0948d8caab..be9f18b6c7 100644 --- a/drivers/sound/Kconfig +++ b/drivers/sound/Kconfig @@ -148,4 +148,14 @@ config SOUND_WM8994 audio data and I2C for codec control. At present it only works with the Samsung I2S driver.
+config I2S_TI + bool "Enable I2S support for AM62x SoCs" + depends on I2S + help + TI AM62x SoCs support an I2S interface for sending audio + data to an audio codec. This option enables support for this, + using one of the available audio codec drivers. Enabling this + option provides an implementation for sound_init() and + sound_play(). + endmenu diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile index 9b40c8012f..95aaa8521c 100644 --- a/drivers/sound/Makefile +++ b/drivers/sound/Makefile @@ -23,3 +23,4 @@ obj-$(CONFIG_SOUND_I8254) += i8254_beep.o obj-$(CONFIG_SOUND_RT5677) += rt5677.o obj-$(CONFIG_INTEL_BROADWELL) += broadwell_i2s.o broadwell_sound.o obj-$(CONFIG_SOUND_IVYBRIDGE) += ivybridge_sound.o +obj-$(CONFIG_I2S_TI) += ti_sound.o diff --git a/drivers/sound/ti_sound.c b/drivers/sound/ti_sound.c new file mode 100644 index 0000000000..a424a99b72 --- /dev/null +++ b/drivers/sound/ti_sound.c @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2024 Texas Instruments Incorporated - https://www.ti.com/ + * Scaria M Kochidanadu, s-kochidanadu@ti.com + * + * based on the uboot samsung sound driver, which is + * + * Copyright 2018 Google, LLC + * Written by Simon Glass sjg@chromium.org + */ + +#include <asm/u-boot.h> /* boot information for Linux kernel */ +/* Pull in stuff for the build system */ +#ifdef DO_DEPS_ONLY +#include <env_internal.h> +#endif +#include <audio_codec.h> +#include <dm.h> +#include <i2s.h> +#include <log.h> +#include <sound.h> +#include <asm/gpio.h> + +static int ti_sound_setup(struct udevice *dev) +{ + struct sound_uc_priv *uc_priv = dev_get_uclass_priv(dev); + struct i2s_uc_priv *i2s_priv = dev_get_uclass_priv(uc_priv->i2s); + int ret; + + if (uc_priv->setup_done) + return -EALREADY; + + ret = audio_codec_set_params(uc_priv->codec, i2s_priv->id, + i2s_priv->samplingrate, + i2s_priv->samplingrate * i2s_priv->rfs, + i2s_priv->bitspersample, + i2s_priv->channels); + + if (ret) { + return ret; + printf("failed in set_params\n"); + } + uc_priv->setup_done = true; + + return 0; +} + +static int ti_sound_play(struct udevice *dev, void *data, uint data_size) +{ + struct sound_uc_priv *uc_priv = dev_get_uclass_priv(dev); + + return i2s_tx_data(uc_priv->i2s, data, data_size); +} + +static int ti_sound_stop_play(struct udevice *dev) +{ + /* This function is necassary to satisfy the function calls + * in the Uboot command: sound play + */ + return 0; +} + +static int ti_sound_probe(struct udevice *dev) +{ + struct sound_uc_priv *uc_priv = dev_get_uclass_priv(dev); + struct ofnode_phandle_args args; + ofnode node; + int ret; + + ret = uclass_get_device_by_phandle(UCLASS_AUDIO_CODEC, dev, + "ti,codec", + &uc_priv->codec); + if (ret) { + debug("Failed to probe audio codec\n"); + return ret; + } + + node = ofnode_find_subnode(dev_ofnode(dev), "simple-audio-card,cpu"); + if (!ofnode_valid(node)) { + debug("Failed to find /cpu subnode\n"); + return -EINVAL; + } + + ret = ofnode_parse_phandle_with_args(node, "sound-dai", + "#sound-dai-cells", 0, 0, &args); + if (ret) { + debug("Cannot find phandle: %d\n", ret); + return ret; + } + + ret = uclass_get_device_by_ofnode(UCLASS_I2S, args.node, &uc_priv->i2s); + if (ret) { + debug("Cannot find i2s: %d\n", ret); + return ret; + } + debug("Probed sound '%s' with codec '%s' and i2s '%s'\n", dev->name, + uc_priv->codec->name, uc_priv->i2s->name); + + return 0; +} + +static const struct sound_ops ti_sound_ops = { + .setup = ti_sound_setup, + .play = ti_sound_play, + .stop_play = ti_sound_stop_play, +}; + +static const struct udevice_id ti_sound_ids[] = { + { .compatible = "simple-audio-card" }, + { } +}; + +U_BOOT_DRIVER(ti_sound) = { + .name = "ti_sound", + .id = UCLASS_SOUND, + .of_match = ti_sound_ids, + .probe = ti_sound_probe, + .ops = &ti_sound_ops, +};