[alsa-devel] [PATCH v2 0/5] ASoC: OMAP4: Add support for HDMI audio
This is to add support for HDMI audio on OMAP4 chips. This work has two parts: DSS implementation and ASoC implementation. This set of patches presents the ASoC implementation. The approach is to utilize the DSS HDMI driver to act as an ASoC codec. This set of patches adds the ASoC CPU DAI and machine drivers. These drivers will utilize the ASoC HDMI codec provided in the DSS HDMI driver. DSS part of the implementation is currently under review in the linux-omap list.
The DSS HDMI driver controls the availability of HDMI output and audio can be played only when the HDMI video device is enabled and the video timing in use is one of the CEA-861-D video timings supported by the OMAP4 HDMI IP.
This implementation is for Basic Audio as defined in CEA-861-D: 16 bit/sample linear PCM 2-channel audio with sample rates of 32, 44.1 and 48kHz. As described in the HDMI specification, support for Basic Audio is mandatory for HDMI sinks and does not require of EDID parsing.
Additionally, this implementation supports 24-bit samples in 32-bit words. Further audio capabilities such as more sample rates and multichannel audio will be added in the future when EDID parsing is available for HDMI driver.
This implementation is based on on: * OMAP4: DSS2: Add dss_dss_clk opt clock for OMAP4, by Sumit Semwal (http://gitorious.org/linux-omap-dss2/linux/commit/0da5637569bb9bf93e6930cd1c...) * Kernel 2.6.39-rc7 (git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git v2.6.39-rc7)
* v1 of OMAP4: DSS2: HDMI: Add support for audio http://www.mail-archive.com/linux-omap@vger.kernel.org/msg49011.html
In order to validate functionality, it is necessary to utilize the DSS HDMI ASoC codec. The complete implementation, DSS and ASoC parts, is available at: git://gitorious.org/omap-audio/linux-audio.git ricardon/topic/hdmi-audio-v2
Validation was performed on HDMI TV. Penguins were present on the display and audio playback was performed with aplay at 32, 44.1 and 48kHz with S16_LE and S24_LE sample formats. Validation was performed on SDP4430 ES2.1 and ES2.2 and Panda ES2.1 and ES2.0.
Changes from V1: 1. Moved check of HDMI power state from CPU DAI start-up to machine hw_params. 2. Improved error handling when checking HDMI power-state. 3. Removed build-time conditionals for HDMI devices. 4. Added MODULE_ALIASes to drivers. 5. Merged CPU DAI header patch with its driver patch. 6. Use dev_err to print error messages. 7. Removed unnecessary calls to set_drvdata. 8. Corrected e-mail addresses of authors. 9. Corrected indentation.
Ricardo Neri (5): OMAP4: HDMI: Add OMAP device for HDMI audio CPU DAI OMAP4: Add device for HDMI OMAP4 audio for ASoC machine driver ASoC: OMAP: Add CPU DAI driver for HDMI ASoC: OMAP4: Add HDMI Audio machine driver for OMAP4 boards ASoC: OMAP: Update Makefile and Kconfig for HDMI audio
arch/arm/mach-omap2/devices.c | 26 ++++++ sound/soc/omap/Kconfig | 11 +++ sound/soc/omap/Makefile | 4 + sound/soc/omap/omap-hdmi.c | 158 ++++++++++++++++++++++++++++++++++++++ sound/soc/omap/omap-hdmi.h | 36 +++++++++ sound/soc/omap/omap4-hdmi-card.c | 129 +++++++++++++++++++++++++++++++ 6 files changed, 364 insertions(+), 0 deletions(-) create mode 100644 sound/soc/omap/omap-hdmi.c create mode 100644 sound/soc/omap/omap-hdmi.h create mode 100644 sound/soc/omap/omap4-hdmi-card.c
Add device for HDMI audio. This device uses hwmod data from dss_hdmi. This device is to be used by the ASoC HDMI CPU DAI to obtain base memory address and DMA request number.
Signed-off-by: Ricardo Neri ricardo.neri@ti.com --- arch/arm/mach-omap2/devices.c | 16 ++++++++++++++++ 1 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 7b85585..56e2e98 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -313,6 +313,22 @@ OMAP_MCBSP_PLATFORM_DEVICE(5);
static void omap_init_audio(void) { + struct omap_hwmod *oh_hdmi; + struct omap_device *od_hdmi; + char *oh_hdmi_name = "dss_hdmi"; + char *dev_hdmi_name = "hdmi-audio-dai"; + + if (cpu_is_omap44xx()) { + oh_hdmi = omap_hwmod_lookup(oh_hdmi_name); + WARN(!oh_hdmi, "%s: could not find omap_hwmod for %s\n", + __func__, oh_hdmi_name); + + od_hdmi = omap_device_build(dev_hdmi_name, -1, oh_hdmi, NULL, 0, + NULL, 0, false); + WARN(IS_ERR(od_hdmi), "%s: could not build omap_device for %s\n", + __func__, dev_hdmi_name); + } + platform_device_register(&omap_mcbsp1); platform_device_register(&omap_mcbsp2); if (cpu_is_omap243x() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
This device is used by the OMAP4 HDMI audio machine driver to register the HDMI sound card.
Signed-off-by: Ricardo Neri ricardo.neri@ti.com --- arch/arm/mach-omap2/devices.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 56e2e98..6add0d2 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -300,6 +300,14 @@ static struct platform_device omap_pcm = { };
/* + * Device for the ASoC OMAP4 HDMI machine driver + */ +static struct platform_device omap4_hdmi_audio = { + .name = "omap4-hdmi-audio", + .id = -1, +}; + +/* * OMAP2420 has 2 McBSP ports * OMAP2430 has 5 McBSP ports * OMAP3 has 5 McBSP ports @@ -327,6 +335,8 @@ static void omap_init_audio(void) NULL, 0, false); WARN(IS_ERR(od_hdmi), "%s: could not build omap_device for %s\n", __func__, dev_hdmi_name); + + platform_device_register(&omap4_hdmi_audio); }
platform_device_register(&omap_mcbsp1);
Addition of the HDMI CPU DAI driver for OMAP4. This driver is in charge of configuring DMA settings for HDMI. Also, it finds the HDMI video device and determines if audio playback can proceed.
Signed-off-by: Ricardo Neri ricardo.neri@ti.com --- sound/soc/omap/omap-hdmi.c | 158 ++++++++++++++++++++++++++++++++++++++++++++ sound/soc/omap/omap-hdmi.h | 36 ++++++++++ 2 files changed, 194 insertions(+), 0 deletions(-) create mode 100644 sound/soc/omap/omap-hdmi.c create mode 100644 sound/soc/omap/omap-hdmi.h
diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c new file mode 100644 index 0000000..36c6eae --- /dev/null +++ b/sound/soc/omap/omap-hdmi.c @@ -0,0 +1,158 @@ +/* + * omap-hdmi.c + * + * OMAP ALSA SoC DAI driver for HDMI audio on OMAP4 processors. + * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ + * Authors: Jorge Candelaria jorge.candelaria@ti.com + * Ricardo Neri ricardo.neri@ti.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/device.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/initval.h> +#include <sound/soc.h> + +#include <plat/dma.h> +#include "omap-pcm.h" +#include "omap-hdmi.h" + +#define DRV_NAME "hdmi-audio-dai" + +static struct omap_pcm_dma_data omap_hdmi_dai_dma_params = { + .name = "HDMI playback", + .sync_mode = OMAP_DMA_SYNC_PACKET, +}; + +static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + int err; + /* + * Make sure that the period bytes are multiple of the DMA packet size. + * Largest packet size we use is 32 32-bit words = 128 bytes + */ + err = snd_pcm_hw_constraint_step(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128); + if (err < 0) + return err; + + return 0; +} + +static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + int err = 0; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + omap_hdmi_dai_dma_params.packet_size = 16; + break; + case SNDRV_PCM_FORMAT_S24_LE: + omap_hdmi_dai_dma_params.packet_size = 32; + break; + default: + err = -EINVAL; + } + + omap_hdmi_dai_dma_params.data_type = OMAP_DMA_DATA_TYPE_S32; + + snd_soc_dai_set_dma_data(dai, substream, + &omap_hdmi_dai_dma_params); + + return err; +} + +static struct snd_soc_dai_ops omap_hdmi_dai_ops = { + .startup = omap_hdmi_dai_startup, + .hw_params = omap_hdmi_dai_hw_params, +}; + +static struct snd_soc_dai_driver omap_hdmi_dai = { + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = OMAP_HDMI_RATES, + .formats = OMAP_HDMI_FORMATS, + }, + .ops = &omap_hdmi_dai_ops, +}; + +static __devinit int omap_hdmi_probe(struct platform_device *pdev) +{ + int ret; + struct resource *hdmi_rsrc; + + hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!hdmi_rsrc) { + dev_err(&pdev->dev, "Cannot obtain IORESOURCE_MEM HDMI\n"); + return -EINVAL; + } + + omap_hdmi_dai_dma_params.port_addr = hdmi_rsrc->start + + OMAP_HDMI_AUDIO_DMA_PORT; + + hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_DMA, 0); + if (!hdmi_rsrc) { + dev_err(&pdev->dev, "Cannot obtain IORESOURCE_DMA HDMI\n"); + return -EINVAL; + } + + omap_hdmi_dai_dma_params.dma_req = hdmi_rsrc->start; + + ret = snd_soc_register_dai(&pdev->dev, &omap_hdmi_dai); + return ret; +} + +static int __devexit omap_hdmi_remove(struct platform_device *pdev) +{ + snd_soc_unregister_dai(&pdev->dev); + return 0; +} + +static struct platform_driver hdmi_dai_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, + .probe = omap_hdmi_probe, + .remove = __devexit_p(omap_hdmi_remove), +}; + +static int __init hdmi_dai_init(void) +{ + return platform_driver_register(&hdmi_dai_driver); +} +module_init(hdmi_dai_init); + +static void __exit hdmi_dai_exit(void) +{ + platform_driver_unregister(&hdmi_dai_driver); +} +module_exit(hdmi_dai_exit); + +MODULE_AUTHOR("Jorge Candelaria jorge.candelaria@ti.com"); +MODULE_AUTHOR("Ricardo Neri ricardo.neri@ti.com"); +MODULE_DESCRIPTION("OMAP HDMI SoC Interface"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/sound/soc/omap/omap-hdmi.h b/sound/soc/omap/omap-hdmi.h new file mode 100644 index 0000000..34c298d --- /dev/null +++ b/sound/soc/omap/omap-hdmi.h @@ -0,0 +1,36 @@ +/* + * omap-hdmi.h + * + * Definitions for OMAP ALSA SoC DAI driver for HDMI audio on OMAP4 processors. + * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ + * Authors: Jorge Candelaria jorge.candelaria@ti.com + * Ricardo Neri ricardo.neri@ti.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __OMAP_HDMI_H__ +#define __OMAP_HDMI_H__ + +#define OMAP_HDMI_AUDIO_DMA_PORT 0x8c + +#define OMAP_HDMI_RATES (SNDRV_PCM_RATE_32000 | \ + SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) + +#define OMAP_HDMI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE) + +#endif
On Sun, May 15, 2011 at 04:36:33AM -0500, Ricardo Neri wrote:
Addition of the HDMI CPU DAI driver for OMAP4. This driver is in charge of configuring DMA settings for HDMI. Also, it finds the HDMI video device and determines if audio playback can proceed.
Signed-off-by: Ricardo Neri ricardo.neri@ti.com
Acked-by: Mark Brown broonie@opensource.wolfsonmicro.com
Add machine driver for HDMI audio on OMAP4 boards. This driver is in charge of putting together the HDMI audio codec and the CPU DAI and register the HDMI sound card with ALSA.
Signed-off-by: Ricardo Neri ricardo.neri@ti.com --- sound/soc/omap/omap4-hdmi-card.c | 129 ++++++++++++++++++++++++++++++++++++++ 1 files changed, 129 insertions(+), 0 deletions(-) create mode 100644 sound/soc/omap/omap4-hdmi-card.c
diff --git a/sound/soc/omap/omap4-hdmi-card.c b/sound/soc/omap/omap4-hdmi-card.c new file mode 100644 index 0000000..b7fb812 --- /dev/null +++ b/sound/soc/omap/omap4-hdmi-card.c @@ -0,0 +1,129 @@ +/* + * omap4-hdmi-card.c + * + * OMAP ALSA SoC machine driver for TI OMAP4 HDMI + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * Author: Ricardo Neri ricardo.neri@ti.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include <sound/pcm.h> +#include <sound/soc.h> +#include <asm/mach-types.h> +#include <plat/display.h> + +#define DRV_NAME "omap4-hdmi-audio" + +static int omap4_hdmi_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + int i; + struct omap_overlay_manager *mgr = NULL; + struct device *dev = substream->pcm->card->dev; + + /* Find DSS HDMI device */ + for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) { + mgr = omap_dss_get_overlay_manager(i); + if (mgr && mgr->device + && mgr->device->type == OMAP_DISPLAY_TYPE_HDMI) + break; + } + + if (i == omap_dss_get_num_overlay_managers()) { + dev_err(dev, "HDMI display device not found!\n"); + return -ENODEV; + } + + /* Make sure HDMI is power-on to avoid L3 interconnect errors */ + if (mgr->device->state != OMAP_DSS_DISPLAY_ACTIVE) { + dev_err(dev, "HDMI display is not active!\n"); + return -EIO; + } + + return 0; +} + +static struct snd_soc_ops omap4_hdmi_dai_ops = { + .hw_params = omap4_hdmi_dai_hw_params, +}; + +static struct snd_soc_dai_link omap4_hdmi_dai = { + .name = "HDMI", + .stream_name = "HDMI", + .cpu_dai_name = "hdmi-audio-dai", + .platform_name = "omap-pcm-audio", + .codec_name = "omapdss_hdmi", + .codec_dai_name = "hdmi-audio-codec", + .ops = &omap4_hdmi_dai_ops, +}; + +static struct snd_soc_card snd_soc_omap4_hdmi = { + .name = "OMAP4HDMI", + .dai_link = &omap4_hdmi_dai, + .num_links = 1, +}; + +static __devinit int omap4_hdmi_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &snd_soc_omap4_hdmi; + int ret; + + card->dev = &pdev->dev; + + ret = snd_soc_register_card(card); + if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); + card->dev = NULL; + return ret; + } + return 0; +} + +static int __devexit omap4_hdmi_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + + snd_soc_unregister_card(card); + card->dev = NULL; + return 0; +} + +static struct platform_driver omap4_hdmi_driver = { + .driver = { + .name = "omap4-hdmi-audio", + .owner = THIS_MODULE, + }, + .probe = omap4_hdmi_probe, + .remove = __devexit_p(omap4_hdmi_remove), +}; + +static int __init omap4_hdmi_init(void) +{ + return platform_driver_register(&omap4_hdmi_driver); +} +module_init(omap4_hdmi_init); + +static void __exit omap4_hdmi_exit(void) +{ + platform_driver_unregister(&omap4_hdmi_driver); +} +module_exit(omap4_hdmi_exit); + +MODULE_AUTHOR("Ricardo Neri ricardo.neri@ti.com"); +MODULE_DESCRIPTION("OMAP4 HDMI machine ASoC driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRV_NAME);
On Sun, May 15, 2011 at 04:36:34AM -0500, Ricardo Neri wrote:
Add machine driver for HDMI audio on OMAP4 boards. This driver is in charge of putting together the HDMI audio codec and the CPU DAI and register the HDMI sound card with ALSA.
Signed-off-by: Ricardo Neri ricardo.neri@ti.com
Acked-by: Mark Brown broonie@opensource.wolfsonmicro.com
Update Makefile and Kconfig to build HDMI audio support for OMAP4 SDP and Panda boards.
Signed-off-by: Ricardo Neri ricardo.neri@ti.com --- sound/soc/omap/Kconfig | 11 +++++++++++ sound/soc/omap/Makefile | 4 ++++ 2 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index b592298..e8ca5be 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -9,6 +9,9 @@ config SND_OMAP_SOC_MCBSP config SND_OMAP_SOC_MCPDM tristate
+config SND_OMAP_SOC_HDMI + tristate + config SND_OMAP_SOC_N810 tristate "SoC Audio support for Nokia N810" depends on SND_OMAP_SOC && MACH_NOKIA_N810 && I2C @@ -108,6 +111,14 @@ config SND_OMAP_SOC_SDP4430 Say Y if you want to add support for SoC audio on Texas Instruments SDP4430.
+config SND_OMAP_SOC_OMAP4_HDMI + tristate "SoC Audio support for Texas Instruments OMAP4 HDMI" + depends on SND_OMAP_SOC && OMAP4_DSS_HDMI && OMAP2_DSS && ARCH_OMAP4 + select SND_OMAP_SOC_HDMI + help + Say Y if you want to add support for SoC HDMI audio on Texas Instruments + OMAP4 chips + config SND_OMAP_SOC_OMAP3_PANDORA tristate "SoC Audio support for OMAP3 Pandora" depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_PANDORA diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile index ba9fc65..8016642 100644 --- a/sound/soc/omap/Makefile +++ b/sound/soc/omap/Makefile @@ -2,10 +2,12 @@ snd-soc-omap-objs := omap-pcm.o snd-soc-omap-mcbsp-objs := omap-mcbsp.o snd-soc-omap-mcpdm-objs := omap-mcpdm.o mcpdm.o +snd-soc-omap-hdmi-objs := omap-hdmi.o
obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o obj-$(CONFIG_SND_OMAP_SOC_MCPDM) += snd-soc-omap-mcpdm.o +obj-$(CONFIG_SND_OMAP_SOC_HDMI) += snd-soc-omap-hdmi.o
# OMAP Machine Support snd-soc-n810-objs := n810.o @@ -22,6 +24,7 @@ snd-soc-omap3pandora-objs := omap3pandora.o snd-soc-omap3beagle-objs := omap3beagle.o snd-soc-zoom2-objs := zoom2.o snd-soc-igep0020-objs := igep0020.o +snd-soc-omap4-hdmi-objs := omap4-hdmi-card.o
obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o @@ -37,3 +40,4 @@ obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o obj-$(CONFIG_SND_OMAP_SOC_IGEP0020) += snd-soc-igep0020.o +obj-$(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) += snd-soc-omap4-hdmi.o
On Sun, May 15, 2011 at 04:36:35AM -0500, Ricardo Neri wrote:
Update Makefile and Kconfig to build HDMI audio support for OMAP4 SDP and Panda boards.
Signed-off-by: Ricardo Neri ricardo.neri@ti.com
Acked-by: Mark Brown broonie@opensource.wolfsonmicro.com
participants (2)
-
Mark Brown
-
Ricardo Neri