From 28564486866fa889b78264360022c94836fa8072 Mon Sep 17 00:00:00 2001 From: Viorel Suman Date: Tue, 13 Oct 2020 15:17:32 +0300 Subject: ASoC: fsl_xcvr: Add XCVR ASoC CPU DAI driver XCVR (Audio Transceiver) is a on-chip functional module found on i.MX8MP. It support HDMI2.1 eARC, HDMI1.4 ARC and SPDIF. Signed-off-by: Viorel Suman Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/20201013121733.83684-2-viorel.suman@oss.nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'sound/soc/fsl/Kconfig') diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 3f76ff71ea47..d04b64d32dc1 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -95,6 +95,16 @@ config SND_SOC_FSL_EASRC destination sample rate. It is a new design module compare with the old ASRC. +config SND_SOC_FSL_XCVR + tristate "NXP Audio Transceiver (XCVR) module support" + select REGMAP_MMIO + select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n + select SND_SOC_GENERIC_DMAENGINE_PCM + help + Say Y if you want to add Audio Transceiver (XCVR) support for NXP + iMX CPUs. XCVR is a digital module that supports HDMI2.1 eARC, + HDMI1.4 ARC and SPDIF. + config SND_SOC_FSL_UTILS tristate -- cgit v1.2.3 From 8a24c834c053ef1b0cdefbd9c5bcb487cbc5068f Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Mon, 2 Nov 2020 09:52:27 +0800 Subject: ASoC: fsl_aud2htx: Add aud2htx module driver The AUD2HTX is a digital module that provides a bridge between the Audio Subsystem and the HDMI RTX Subsystem. This module includes intermediate storage to queue SDMA transactions prior to being synchronized and passed to the HDMI RTX Subsystem over the Audio Link. The AUD2HTX contains a DMA request routed to the SDMA module. This DMA request is controlled based on the watermark level in the 32-entry sample buffer. Signed-off-by: Shengjiu Wang Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/1604281947-26874-2-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 5 + sound/soc/fsl/Makefile | 2 + sound/soc/fsl/fsl_aud2htx.c | 311 ++++++++++++++++++++++++++++++++++++++++++++ sound/soc/fsl/fsl_aud2htx.h | 67 ++++++++++ 4 files changed, 385 insertions(+) create mode 100644 sound/soc/fsl/fsl_aud2htx.c create mode 100644 sound/soc/fsl/fsl_aud2htx.h (limited to 'sound/soc/fsl/Kconfig') diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index d04b64d32dc1..52a562215008 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -105,6 +105,11 @@ config SND_SOC_FSL_XCVR iMX CPUs. XCVR is a digital module that supports HDMI2.1 eARC, HDMI1.4 ARC and SPDIF. +config SND_SOC_FSL_AUD2HTX + tristate "AUDIO TO HDMI TX module support" + help + Say Y if you want to add AUDIO TO HDMI TX support for NXP. + config SND_SOC_FSL_UTILS tristate diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 1d2231f9cc47..2181b7f9f677 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -26,6 +26,7 @@ snd-soc-fsl-dma-objs := fsl_dma.o snd-soc-fsl-mqs-objs := fsl_mqs.o snd-soc-fsl-easrc-objs := fsl_easrc.o snd-soc-fsl-xcvr-objs := fsl_xcvr.o +snd-soc-fsl-aud2htx-objs := fsl_aud2htx.o obj-$(CONFIG_SND_SOC_FSL_AUDMIX) += snd-soc-fsl-audmix.o obj-$(CONFIG_SND_SOC_FSL_ASOC_CARD) += snd-soc-fsl-asoc-card.o @@ -40,6 +41,7 @@ obj-$(CONFIG_SND_SOC_FSL_MQS) += snd-soc-fsl-mqs.o obj-$(CONFIG_SND_SOC_FSL_EASRC) += snd-soc-fsl-easrc.o obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o obj-$(CONFIG_SND_SOC_FSL_XCVR) += snd-soc-fsl-xcvr.o +obj-$(CONFIG_SND_SOC_FSL_AUD2HTX) += snd-soc-fsl-aud2htx.o # MPC5200 Platform Support obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o diff --git a/sound/soc/fsl/fsl_aud2htx.c b/sound/soc/fsl/fsl_aud2htx.c new file mode 100644 index 000000000000..124aeb70f24e --- /dev/null +++ b/sound/soc/fsl/fsl_aud2htx.c @@ -0,0 +1,311 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright 2020 NXP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fsl_aud2htx.h" +#include "imx-pcm.h" + +static int fsl_aud2htx_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct fsl_aud2htx *aud2htx = snd_soc_dai_get_drvdata(dai); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + regmap_update_bits(aud2htx->regmap, AUD2HTX_CTRL, + AUD2HTX_CTRL_EN, AUD2HTX_CTRL_EN); + regmap_update_bits(aud2htx->regmap, AUD2HTX_CTRL_EXT, + AUD2HTX_CTRE_DE, AUD2HTX_CTRE_DE); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + regmap_update_bits(aud2htx->regmap, AUD2HTX_CTRL_EXT, + AUD2HTX_CTRE_DE, 0); + regmap_update_bits(aud2htx->regmap, AUD2HTX_CTRL, + AUD2HTX_CTRL_EN, 0); + break; + default: + return -EINVAL; + } + return 0; +} + +static const struct snd_soc_dai_ops fsl_aud2htx_dai_ops = { + .trigger = fsl_aud2htx_trigger, +}; + +static int fsl_aud2htx_dai_probe(struct snd_soc_dai *cpu_dai) +{ + struct fsl_aud2htx *aud2htx = dev_get_drvdata(cpu_dai->dev); + + /* DMA request when number of entries < WTMK_LOW */ + regmap_update_bits(aud2htx->regmap, AUD2HTX_CTRL_EXT, + AUD2HTX_CTRE_DT_MASK, 0); + + /* Disable interrupts*/ + regmap_update_bits(aud2htx->regmap, AUD2HTX_IRQ_MASK, + AUD2HTX_WM_HIGH_IRQ_MASK | + AUD2HTX_WM_LOW_IRQ_MASK | + AUD2HTX_OVF_MASK, + AUD2HTX_WM_HIGH_IRQ_MASK | + AUD2HTX_WM_LOW_IRQ_MASK | + AUD2HTX_OVF_MASK); + + /* Configure watermark */ + regmap_update_bits(aud2htx->regmap, AUD2HTX_CTRL_EXT, + AUD2HTX_CTRE_WL_MASK, + AUD2HTX_WTMK_LOW << AUD2HTX_CTRE_WL_SHIFT); + regmap_update_bits(aud2htx->regmap, AUD2HTX_CTRL_EXT, + AUD2HTX_CTRE_WH_MASK, + AUD2HTX_WTMK_HIGH << AUD2HTX_CTRE_WH_SHIFT); + + snd_soc_dai_init_dma_data(cpu_dai, &aud2htx->dma_params_tx, + &aud2htx->dma_params_rx); + + return 0; +} + +static struct snd_soc_dai_driver fsl_aud2htx_dai = { + .probe = fsl_aud2htx_dai_probe, + .playback = { + .stream_name = "CPU-Playback", + .channels_min = 1, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_176400 | + SNDRV_PCM_RATE_192000, + .formats = FSL_AUD2HTX_FORMATS, + }, + .ops = &fsl_aud2htx_dai_ops, +}; + +static const struct snd_soc_component_driver fsl_aud2htx_component = { + .name = "fsl-aud2htx", +}; + +static const struct reg_default fsl_aud2htx_reg_defaults[] = { + {AUD2HTX_CTRL, 0x00000000}, + {AUD2HTX_CTRL_EXT, 0x00000000}, + {AUD2HTX_WR, 0x00000000}, + {AUD2HTX_STATUS, 0x00000000}, + {AUD2HTX_IRQ_NOMASK, 0x00000000}, + {AUD2HTX_IRQ_MASKED, 0x00000000}, + {AUD2HTX_IRQ_MASK, 0x00000000}, +}; + +static bool fsl_aud2htx_readable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case AUD2HTX_CTRL: + case AUD2HTX_CTRL_EXT: + case AUD2HTX_STATUS: + case AUD2HTX_IRQ_NOMASK: + case AUD2HTX_IRQ_MASKED: + case AUD2HTX_IRQ_MASK: + return true; + default: + return false; + } +} + +static bool fsl_aud2htx_writeable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case AUD2HTX_CTRL: + case AUD2HTX_CTRL_EXT: + case AUD2HTX_WR: + case AUD2HTX_IRQ_NOMASK: + case AUD2HTX_IRQ_MASKED: + case AUD2HTX_IRQ_MASK: + return true; + default: + return false; + } +} + +static bool fsl_aud2htx_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case AUD2HTX_STATUS: + case AUD2HTX_IRQ_NOMASK: + case AUD2HTX_IRQ_MASKED: + return true; + default: + return false; + } +} + +static const struct regmap_config fsl_aud2htx_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + + .max_register = AUD2HTX_IRQ_MASK, + .reg_defaults = fsl_aud2htx_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(fsl_aud2htx_reg_defaults), + .readable_reg = fsl_aud2htx_readable_reg, + .volatile_reg = fsl_aud2htx_volatile_reg, + .writeable_reg = fsl_aud2htx_writeable_reg, + .cache_type = REGCACHE_RBTREE, +}; + +static const struct of_device_id fsl_aud2htx_dt_ids[] = { + { .compatible = "fsl,imx8mp-aud2htx",}, + {} +}; +MODULE_DEVICE_TABLE(of, fsl_aud2htx_dt_ids); + +static irqreturn_t fsl_aud2htx_isr(int irq, void *dev_id) +{ + return IRQ_HANDLED; +} + +static int fsl_aud2htx_probe(struct platform_device *pdev) +{ + struct fsl_aud2htx *aud2htx; + struct resource *res; + void __iomem *regs; + int ret, irq; + + aud2htx = devm_kzalloc(&pdev->dev, sizeof(*aud2htx), GFP_KERNEL); + if (!aud2htx) + return -ENOMEM; + + aud2htx->pdev = pdev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(regs)) { + dev_err(&pdev->dev, "failed ioremap\n"); + return PTR_ERR(regs); + } + + aud2htx->regmap = devm_regmap_init_mmio(&pdev->dev, regs, + &fsl_aud2htx_regmap_config); + if (IS_ERR(aud2htx->regmap)) { + dev_err(&pdev->dev, "failed to init regmap"); + return PTR_ERR(aud2htx->regmap); + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "no irq for node %s\n", + dev_name(&pdev->dev)); + return irq; + } + + ret = devm_request_irq(&pdev->dev, irq, fsl_aud2htx_isr, 0, + dev_name(&pdev->dev), aud2htx); + if (ret) { + dev_err(&pdev->dev, "failed to claim irq %u: %d\n", irq, ret); + return ret; + } + + aud2htx->bus_clk = devm_clk_get(&pdev->dev, "bus"); + if (IS_ERR(aud2htx->bus_clk)) { + dev_err(&pdev->dev, "failed to get mem clock\n"); + return PTR_ERR(aud2htx->bus_clk); + } + + aud2htx->dma_params_tx.chan_name = "tx"; + aud2htx->dma_params_tx.maxburst = AUD2HTX_MAXBURST; + aud2htx->dma_params_tx.addr = res->start + AUD2HTX_WR; + + platform_set_drvdata(pdev, aud2htx); + pm_runtime_enable(&pdev->dev); + + regcache_cache_only(aud2htx->regmap, true); + + ret = devm_snd_soc_register_component(&pdev->dev, + &fsl_aud2htx_component, + &fsl_aud2htx_dai, 1); + if (ret) { + dev_err(&pdev->dev, "failed to register ASoC DAI\n"); + return ret; + } + + ret = imx_pcm_dma_init(pdev, IMX_DEFAULT_DMABUF_SIZE); + if (ret) + dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret); + + return ret; +} + +static int fsl_aud2htx_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static int fsl_aud2htx_runtime_suspend(struct device *dev) +{ + struct fsl_aud2htx *aud2htx = dev_get_drvdata(dev); + + regcache_cache_only(aud2htx->regmap, true); + clk_disable_unprepare(aud2htx->bus_clk); + + return 0; +} + +static int fsl_aud2htx_runtime_resume(struct device *dev) +{ + struct fsl_aud2htx *aud2htx = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(aud2htx->bus_clk); + if (ret) + return ret; + + regcache_cache_only(aud2htx->regmap, false); + regcache_mark_dirty(aud2htx->regmap); + regcache_sync(aud2htx->regmap); + + return 0; +} + +static const struct dev_pm_ops fsl_aud2htx_pm_ops = { + SET_RUNTIME_PM_OPS(fsl_aud2htx_runtime_suspend, + fsl_aud2htx_runtime_resume, + NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static struct platform_driver fsl_aud2htx_driver = { + .probe = fsl_aud2htx_probe, + .remove = fsl_aud2htx_remove, + .driver = { + .name = "fsl-aud2htx", + .pm = &fsl_aud2htx_pm_ops, + .of_match_table = fsl_aud2htx_dt_ids, + }, +}; +module_platform_driver(fsl_aud2htx_driver); + +MODULE_AUTHOR("Shengjiu Wang "); +MODULE_DESCRIPTION("NXP AUD2HTX driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/fsl/fsl_aud2htx.h b/sound/soc/fsl/fsl_aud2htx.h new file mode 100644 index 000000000000..ad70d6a7694c --- /dev/null +++ b/sound/soc/fsl/fsl_aud2htx.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2020 NXP + */ + +#ifndef _FSL_AUD2HTX_H +#define _FSL_AUD2HTX_H + +#define FSL_AUD2HTX_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +/* AUD2HTX Register Map */ +#define AUD2HTX_CTRL 0x0 /* AUD2HTX Control Register */ +#define AUD2HTX_CTRL_EXT 0x4 /* AUD2HTX Control Extended Register */ +#define AUD2HTX_WR 0x8 /* AUD2HTX Write Register */ +#define AUD2HTX_STATUS 0xC /* AUD2HTX Status Register */ +#define AUD2HTX_IRQ_NOMASK 0x10 /* AUD2HTX Nonmasked Interrupt Flags Register */ +#define AUD2HTX_IRQ_MASKED 0x14 /* AUD2HTX Masked Interrupt Flags Register */ +#define AUD2HTX_IRQ_MASK 0x18 /* AUD2HTX IRQ Masks Register */ + +/* AUD2HTX Control Register */ +#define AUD2HTX_CTRL_EN BIT(0) + +/* AUD2HTX Control Extended Register */ +#define AUD2HTX_CTRE_DE BIT(0) +#define AUD2HTX_CTRE_DT_SHIFT 0x1 +#define AUD2HTX_CTRE_DT_WIDTH 0x2 +#define AUD2HTX_CTRE_DT_MASK ((BIT(AUD2HTX_CTRE_DT_WIDTH) - 1) \ + << AUD2HTX_CTRE_DT_SHIFT) +#define AUD2HTX_CTRE_WL_SHIFT 16 +#define AUD2HTX_CTRE_WL_WIDTH 5 +#define AUD2HTX_CTRE_WL_MASK ((BIT(AUD2HTX_CTRE_WL_WIDTH) - 1) \ + << AUD2HTX_CTRE_WL_SHIFT) +#define AUD2HTX_CTRE_WH_SHIFT 24 +#define AUD2HTX_CTRE_WH_WIDTH 5 +#define AUD2HTX_CTRE_WH_MASK ((BIT(AUD2HTX_CTRE_WH_WIDTH) - 1) \ + << AUD2HTX_CTRE_WH_SHIFT) + +/* AUD2HTX IRQ Masks Register */ +#define AUD2HTX_WM_HIGH_IRQ_MASK BIT(2) +#define AUD2HTX_WM_LOW_IRQ_MASK BIT(1) +#define AUD2HTX_OVF_MASK BIT(0) + +#define AUD2HTX_FIFO_DEPTH 0x20 +#define AUD2HTX_WTMK_LOW 0x10 +#define AUD2HTX_WTMK_HIGH 0x10 +#define AUD2HTX_MAXBURST 0x10 + +/** + * fsl_aud2htx: AUD2HTX private data + * + * @pdev: platform device pointer + * @regmap: regmap handler + * @bus_clk: clock source to access register + * @dma_params_rx: DMA parameters for receive channel + * @dma_params_tx: DMA parameters for transmit channel + */ +struct fsl_aud2htx { + struct platform_device *pdev; + struct regmap *regmap; + struct clk *bus_clk; + + struct snd_dmaengine_dai_dma_data dma_params_rx; + struct snd_dmaengine_dai_dma_data dma_params_tx; +}; + +#endif /* _FSL_AUD2HTX_H */ -- cgit v1.2.3 From 9c9fd07eb481cbfc89efa7820b3bb2b4a55eb303 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 10 Nov 2020 17:39:32 -0300 Subject: ASoC: wm1133-ev1: Remove unused driver Since commit c93197b0041d ("ARM: imx: Remove i.MX31 board files"), the MACH_MX31ADS_WM1133_EV1 non-DT platform is no longer supported, so get rid of its machine audio driver too. Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20201110203937.25684-1-festevam@gmail.com Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 11 -- sound/soc/fsl/Makefile | 2 - sound/soc/fsl/wm1133-ev1.c | 289 --------------------------------------------- 3 files changed, 302 deletions(-) delete mode 100644 sound/soc/fsl/wm1133-ev1.c (limited to 'sound/soc/fsl/Kconfig') diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 52a562215008..3ad547193df8 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -239,17 +239,6 @@ config SND_SOC_IMX_SSI comment "SoC Audio support for Freescale i.MX boards:" -config SND_MXC_SOC_WM1133_EV1 - tristate "Audio on the i.MX31ADS with WM1133-EV1 fitted" - depends on MACH_MX31ADS_WM1133_EV1 - select SND_SOC_WM8350 - select SND_SOC_IMX_PCM_FIQ - select SND_SOC_IMX_AUDMUX - select SND_SOC_IMX_SSI - help - Enable support for audio on the i.MX31ADS with the WM1133-EV1 - PMIC board with WM8835x fitted. - config SND_SOC_MX27VIS_AIC32X4 tristate "SoC audio support for Visstrim M10 boards" depends on MACH_IMX27_VISSTRIM_M10 && I2C diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 2181b7f9f677..8d3e40415050 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -65,7 +65,6 @@ obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o snd-soc-phycore-ac97-objs := phycore-ac97.o snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o -snd-soc-wm1133-ev1-objs := wm1133-ev1.o snd-soc-imx-es8328-objs := imx-es8328.o snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o snd-soc-imx-spdif-objs := imx-spdif.o @@ -75,7 +74,6 @@ snd-soc-imx-audmix-objs := imx-audmix.o obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o -obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o obj-$(CONFIG_SND_SOC_IMX_ES8328) += snd-soc-imx-es8328.o obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o diff --git a/sound/soc/fsl/wm1133-ev1.c b/sound/soc/fsl/wm1133-ev1.c deleted file mode 100644 index 99611a037ada..000000000000 --- a/sound/soc/fsl/wm1133-ev1.c +++ /dev/null @@ -1,289 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -// -// wm1133-ev1.c - Audio for WM1133-EV1 on i.MX31ADS -// -// Copyright (c) 2010 Wolfson Microelectronics plc -// Author: Mark Brown -// -// Based on an earlier driver for the same hardware by Liam Girdwood. - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "imx-ssi.h" -#include "../codecs/wm8350.h" -#include "imx-audmux.h" - -/* There is a silicon mic on the board optionally connected via a solder pad - * SP1. Define this to enable it. - */ -#undef USE_SIMIC - -struct _wm8350_audio { - unsigned int channels; - snd_pcm_format_t format; - unsigned int rate; - unsigned int sysclk; - unsigned int bclkdiv; - unsigned int clkdiv; - unsigned int lr_rate; -}; - -/* in order of power consumption per rate (lowest first) */ -static const struct _wm8350_audio wm8350_audio[] = { - /* 16bit mono modes */ - {1, SNDRV_PCM_FORMAT_S16_LE, 8000, 12288000 >> 1, - WM8350_BCLK_DIV_48, WM8350_DACDIV_3, 16,}, - - /* 16 bit stereo modes */ - {2, SNDRV_PCM_FORMAT_S16_LE, 8000, 12288000, - WM8350_BCLK_DIV_48, WM8350_DACDIV_6, 32,}, - {2, SNDRV_PCM_FORMAT_S16_LE, 16000, 12288000, - WM8350_BCLK_DIV_24, WM8350_DACDIV_3, 32,}, - {2, SNDRV_PCM_FORMAT_S16_LE, 32000, 12288000, - WM8350_BCLK_DIV_12, WM8350_DACDIV_1_5, 32,}, - {2, SNDRV_PCM_FORMAT_S16_LE, 48000, 12288000, - WM8350_BCLK_DIV_8, WM8350_DACDIV_1, 32,}, - {2, SNDRV_PCM_FORMAT_S16_LE, 96000, 24576000, - WM8350_BCLK_DIV_8, WM8350_DACDIV_1, 32,}, - {2, SNDRV_PCM_FORMAT_S16_LE, 11025, 11289600, - WM8350_BCLK_DIV_32, WM8350_DACDIV_4, 32,}, - {2, SNDRV_PCM_FORMAT_S16_LE, 22050, 11289600, - WM8350_BCLK_DIV_16, WM8350_DACDIV_2, 32,}, - {2, SNDRV_PCM_FORMAT_S16_LE, 44100, 11289600, - WM8350_BCLK_DIV_8, WM8350_DACDIV_1, 32,}, - {2, SNDRV_PCM_FORMAT_S16_LE, 88200, 22579200, - WM8350_BCLK_DIV_8, WM8350_DACDIV_1, 32,}, - - /* 24bit stereo modes */ - {2, SNDRV_PCM_FORMAT_S24_LE, 48000, 12288000, - WM8350_BCLK_DIV_4, WM8350_DACDIV_1, 64,}, - {2, SNDRV_PCM_FORMAT_S24_LE, 96000, 24576000, - WM8350_BCLK_DIV_4, WM8350_DACDIV_1, 64,}, - {2, SNDRV_PCM_FORMAT_S24_LE, 44100, 11289600, - WM8350_BCLK_DIV_4, WM8350_DACDIV_1, 64,}, - {2, SNDRV_PCM_FORMAT_S24_LE, 88200, 22579200, - WM8350_BCLK_DIV_4, WM8350_DACDIV_1, 64,}, -}; - -static int wm1133_ev1_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); - struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); - int i, found = 0; - snd_pcm_format_t format = params_format(params); - unsigned int rate = params_rate(params); - unsigned int channels = params_channels(params); - - /* find the correct audio parameters */ - for (i = 0; i < ARRAY_SIZE(wm8350_audio); i++) { - if (rate == wm8350_audio[i].rate && - format == wm8350_audio[i].format && - channels == wm8350_audio[i].channels) { - found = 1; - break; - } - } - if (!found) - return -EINVAL; - - /* codec FLL input is 14.75 MHz from MCLK */ - snd_soc_dai_set_pll(codec_dai, 0, 0, 14750000, wm8350_audio[i].sysclk); - - /* TODO: The SSI driver should figure this out for us */ - switch (channels) { - case 2: - snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 0); - break; - case 1: - snd_soc_dai_set_tdm_slot(cpu_dai, 0x1, 0x1, 1, 0); - break; - default: - return -EINVAL; - } - - /* set MCLK as the codec system clock for DAC and ADC */ - snd_soc_dai_set_sysclk(codec_dai, WM8350_MCLK_SEL_PLL_MCLK, - wm8350_audio[i].sysclk, SND_SOC_CLOCK_IN); - - /* set codec BCLK division for sample rate */ - snd_soc_dai_set_clkdiv(codec_dai, WM8350_BCLK_CLKDIV, - wm8350_audio[i].bclkdiv); - - /* DAI is synchronous and clocked with DAC LRCLK & ADC LRC */ - snd_soc_dai_set_clkdiv(codec_dai, - WM8350_DACLR_CLKDIV, wm8350_audio[i].lr_rate); - snd_soc_dai_set_clkdiv(codec_dai, - WM8350_ADCLR_CLKDIV, wm8350_audio[i].lr_rate); - - /* now configure DAC and ADC clocks */ - snd_soc_dai_set_clkdiv(codec_dai, - WM8350_DAC_CLKDIV, wm8350_audio[i].clkdiv); - - snd_soc_dai_set_clkdiv(codec_dai, - WM8350_ADC_CLKDIV, wm8350_audio[i].clkdiv); - - return 0; -} - -static const struct snd_soc_ops wm1133_ev1_ops = { - .hw_params = wm1133_ev1_hw_params, -}; - -static const struct snd_soc_dapm_widget wm1133_ev1_widgets[] = { -#ifdef USE_SIMIC - SND_SOC_DAPM_MIC("SiMIC", NULL), -#endif - SND_SOC_DAPM_MIC("Mic1 Jack", NULL), - SND_SOC_DAPM_MIC("Mic2 Jack", NULL), - SND_SOC_DAPM_LINE("Line In Jack", NULL), - SND_SOC_DAPM_LINE("Line Out Jack", NULL), - SND_SOC_DAPM_HP("Headphone Jack", NULL), -}; - -/* imx32ads soc_card audio map */ -static const struct snd_soc_dapm_route wm1133_ev1_map[] = { - -#ifdef USE_SIMIC - /* SiMIC --> IN1LN (with automatic bias) via SP1 */ - { "IN1LN", NULL, "Mic Bias" }, - { "Mic Bias", NULL, "SiMIC" }, -#endif - - /* Mic 1 Jack --> IN1LN and IN1LP (with automatic bias) */ - { "IN1LN", NULL, "Mic Bias" }, - { "IN1LP", NULL, "Mic1 Jack" }, - { "Mic Bias", NULL, "Mic1 Jack" }, - - /* Mic 2 Jack --> IN1RN and IN1RP (with automatic bias) */ - { "IN1RN", NULL, "Mic Bias" }, - { "IN1RP", NULL, "Mic2 Jack" }, - { "Mic Bias", NULL, "Mic2 Jack" }, - - /* Line in Jack --> AUX (L+R) */ - { "IN3R", NULL, "Line In Jack" }, - { "IN3L", NULL, "Line In Jack" }, - - /* Out1 --> Headphone Jack */ - { "Headphone Jack", NULL, "OUT1R" }, - { "Headphone Jack", NULL, "OUT1L" }, - - /* Out1 --> Line Out Jack */ - { "Line Out Jack", NULL, "OUT2R" }, - { "Line Out Jack", NULL, "OUT2L" }, -}; - -static struct snd_soc_jack hp_jack; - -static struct snd_soc_jack_pin hp_jack_pins[] = { - { .pin = "Headphone Jack", .mask = SND_JACK_HEADPHONE }, -}; - -static struct snd_soc_jack mic_jack; - -static struct snd_soc_jack_pin mic_jack_pins[] = { - { .pin = "Mic1 Jack", .mask = SND_JACK_MICROPHONE }, - { .pin = "Mic2 Jack", .mask = SND_JACK_MICROPHONE }, -}; - -static int wm1133_ev1_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; - - /* Headphone jack detection */ - snd_soc_card_jack_new(rtd->card, "Headphone", SND_JACK_HEADPHONE, - &hp_jack, hp_jack_pins, ARRAY_SIZE(hp_jack_pins)); - wm8350_hp_jack_detect(component, WM8350_JDR, &hp_jack, SND_JACK_HEADPHONE); - - /* Microphone jack detection */ - snd_soc_card_jack_new(rtd->card, "Microphone", - SND_JACK_MICROPHONE | SND_JACK_BTN_0, &mic_jack, - mic_jack_pins, ARRAY_SIZE(mic_jack_pins)); - wm8350_mic_jack_detect(component, &mic_jack, SND_JACK_MICROPHONE, - SND_JACK_BTN_0); - - snd_soc_dapm_force_enable_pin(&rtd->card->dapm, "Mic Bias"); - - return 0; -} - - -SND_SOC_DAILINK_DEFS(ev1, - DAILINK_COMP_ARRAY(COMP_CPU("imx-ssi.0")), - DAILINK_COMP_ARRAY(COMP_CODEC("wm8350-codec.0-0x1a", "wm8350-hifi")), - DAILINK_COMP_ARRAY(COMP_PLATFORM("imx-ssi.0"))); - -static struct snd_soc_dai_link wm1133_ev1_dai = { - .name = "WM1133-EV1", - .stream_name = "Audio", - .init = wm1133_ev1_init, - .ops = &wm1133_ev1_ops, - .symmetric_rates = 1, - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, - SND_SOC_DAILINK_REG(ev1), -}; - -static struct snd_soc_card wm1133_ev1 = { - .name = "WM1133-EV1", - .owner = THIS_MODULE, - .dai_link = &wm1133_ev1_dai, - .num_links = 1, - - .dapm_widgets = wm1133_ev1_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm1133_ev1_widgets), - .dapm_routes = wm1133_ev1_map, - .num_dapm_routes = ARRAY_SIZE(wm1133_ev1_map), -}; - -static struct platform_device *wm1133_ev1_snd_device; - -static int __init wm1133_ev1_audio_init(void) -{ - int ret; - unsigned int ptcr, pdcr; - - /* SSI0 mastered by port 5 */ - ptcr = IMX_AUDMUX_V2_PTCR_SYN | - IMX_AUDMUX_V2_PTCR_TFSDIR | - IMX_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT5_SSI_PINS_5) | - IMX_AUDMUX_V2_PTCR_TCLKDIR | - IMX_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT5_SSI_PINS_5); - pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT5_SSI_PINS_5); - imx_audmux_v2_configure_port(MX31_AUDMUX_PORT1_SSI0, ptcr, pdcr); - - ptcr = IMX_AUDMUX_V2_PTCR_SYN; - pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0); - imx_audmux_v2_configure_port(MX31_AUDMUX_PORT5_SSI_PINS_5, ptcr, pdcr); - - wm1133_ev1_snd_device = platform_device_alloc("soc-audio", -1); - if (!wm1133_ev1_snd_device) - return -ENOMEM; - - platform_set_drvdata(wm1133_ev1_snd_device, &wm1133_ev1); - ret = platform_device_add(wm1133_ev1_snd_device); - - if (ret) - platform_device_put(wm1133_ev1_snd_device); - - return ret; -} -module_init(wm1133_ev1_audio_init); - -static void __exit wm1133_ev1_audio_exit(void) -{ - platform_device_unregister(wm1133_ev1_snd_device); -} -module_exit(wm1133_ev1_audio_exit); - -MODULE_AUTHOR("Mark Brown "); -MODULE_DESCRIPTION("Audio for WM1133-EV1 on i.MX31ADS"); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 3fbb01fb583fd3ddd319f5a547bf10e322301a3f Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 10 Nov 2020 17:39:33 -0300 Subject: ASoC: mx27vis-aic32x4: Remove unused driver Since commit 879c0e5e0ac7 ("ARM: imx: Remove i.MX27 board files"), the MACH_IMX27_VISSTRIM_M10 non-DT platform is no longer supported, so get rid of its machine audio driver too. Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20201110203937.25684-2-festevam@gmail.com Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 11 --- sound/soc/fsl/Makefile | 2 - sound/soc/fsl/mx27vis-aic32x4.c | 214 ---------------------------------------- 3 files changed, 227 deletions(-) delete mode 100644 sound/soc/fsl/mx27vis-aic32x4.c (limited to 'sound/soc/fsl/Kconfig') diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 3ad547193df8..c18ec9310aa7 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -239,17 +239,6 @@ config SND_SOC_IMX_SSI comment "SoC Audio support for Freescale i.MX boards:" -config SND_SOC_MX27VIS_AIC32X4 - tristate "SoC audio support for Visstrim M10 boards" - depends on MACH_IMX27_VISSTRIM_M10 && I2C - select SND_SOC_TLV320AIC32X4 - select SND_SOC_IMX_PCM_DMA - select SND_SOC_IMX_AUDMUX - select SND_SOC_IMX_SSI - help - Say Y if you want to add support for SoC audio on Visstrim SM10 - board with TLV320AIC32X4 codec. - config SND_SOC_PHYCORE_AC97 tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards" depends on MACH_PCM043 || MACH_PCA100 diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 8d3e40415050..5c6058f414be 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -64,7 +64,6 @@ obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o # i.MX Machine Support snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o snd-soc-phycore-ac97-objs := phycore-ac97.o -snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o snd-soc-imx-es8328-objs := imx-es8328.o snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o snd-soc-imx-spdif-objs := imx-spdif.o @@ -73,7 +72,6 @@ snd-soc-imx-audmix-objs := imx-audmix.o obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o -obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o obj-$(CONFIG_SND_SOC_IMX_ES8328) += snd-soc-imx-es8328.o obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o diff --git a/sound/soc/fsl/mx27vis-aic32x4.c b/sound/soc/fsl/mx27vis-aic32x4.c deleted file mode 100644 index 8d3b1897370b..000000000000 --- a/sound/soc/fsl/mx27vis-aic32x4.c +++ /dev/null @@ -1,214 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -// -// mx27vis-aic32x4.c -// -// Copyright 2011 Vista Silicon S.L. -// -// Author: Javier Martin - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../codecs/tlv320aic32x4.h" -#include "imx-ssi.h" -#include "imx-audmux.h" - -#define MX27VIS_AMP_GAIN 0 -#define MX27VIS_AMP_MUTE 1 - -static int mx27vis_amp_gain; -static int mx27vis_amp_mute; -static int mx27vis_amp_gain0_gpio; -static int mx27vis_amp_gain1_gpio; -static int mx27vis_amp_mutel_gpio; -static int mx27vis_amp_muter_gpio; - -static int mx27vis_aic32x4_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); - struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); - int ret; - - ret = snd_soc_dai_set_sysclk(codec_dai, 0, - 25000000, SND_SOC_CLOCK_OUT); - if (ret) { - pr_err("%s: failed setting codec sysclk\n", __func__); - return ret; - } - - ret = snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0, - SND_SOC_CLOCK_IN); - if (ret) { - pr_err("can't set CPU system clock IMX_SSP_SYS_CLK\n"); - return ret; - } - - return 0; -} - -static const struct snd_soc_ops mx27vis_aic32x4_snd_ops = { - .hw_params = mx27vis_aic32x4_hw_params, -}; - -static int mx27vis_amp_set(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - int value = ucontrol->value.integer.value[0]; - unsigned int reg = mc->reg; - int max = mc->max; - - if (value > max) - return -EINVAL; - - switch (reg) { - case MX27VIS_AMP_GAIN: - gpio_set_value(mx27vis_amp_gain0_gpio, value & 1); - gpio_set_value(mx27vis_amp_gain1_gpio, value >> 1); - mx27vis_amp_gain = value; - break; - case MX27VIS_AMP_MUTE: - gpio_set_value(mx27vis_amp_mutel_gpio, value & 1); - gpio_set_value(mx27vis_amp_muter_gpio, value >> 1); - mx27vis_amp_mute = value; - break; - } - return 0; -} - -static int mx27vis_amp_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - - switch (reg) { - case MX27VIS_AMP_GAIN: - ucontrol->value.integer.value[0] = mx27vis_amp_gain; - break; - case MX27VIS_AMP_MUTE: - ucontrol->value.integer.value[0] = mx27vis_amp_mute; - break; - } - return 0; -} - -/* From 6dB to 24dB in steps of 6dB */ -static const DECLARE_TLV_DB_SCALE(mx27vis_amp_tlv, 600, 600, 0); - -static const struct snd_kcontrol_new mx27vis_aic32x4_controls[] = { - SOC_DAPM_PIN_SWITCH("External Mic"), - SOC_SINGLE_EXT_TLV("LO Ext Boost", MX27VIS_AMP_GAIN, 0, 3, 0, - mx27vis_amp_get, mx27vis_amp_set, mx27vis_amp_tlv), - SOC_DOUBLE_EXT("LO Ext Mute Switch", MX27VIS_AMP_MUTE, 0, 1, 1, 0, - mx27vis_amp_get, mx27vis_amp_set), -}; - -static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = { - SND_SOC_DAPM_MIC("External Mic", NULL), -}; - -static const struct snd_soc_dapm_route aic32x4_dapm_routes[] = { - {"Mic Bias", NULL, "External Mic"}, - {"IN1_R", NULL, "Mic Bias"}, - {"IN2_R", NULL, "Mic Bias"}, - {"IN3_R", NULL, "Mic Bias"}, - {"IN1_L", NULL, "Mic Bias"}, - {"IN2_L", NULL, "Mic Bias"}, - {"IN3_L", NULL, "Mic Bias"}, -}; - -SND_SOC_DAILINK_DEFS(hifi, - DAILINK_COMP_ARRAY(COMP_CPU("imx-ssi.0")), - DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic32x4.0-0018", - "tlv320aic32x4-hifi")), - DAILINK_COMP_ARRAY(COMP_PLATFORM("imx-ssi.0"))); - -static struct snd_soc_dai_link mx27vis_aic32x4_dai = { - .name = "tlv320aic32x4", - .stream_name = "TLV320AIC32X4", - .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, - .ops = &mx27vis_aic32x4_snd_ops, - SND_SOC_DAILINK_REG(hifi), -}; - -static struct snd_soc_card mx27vis_aic32x4 = { - .name = "visstrim_m10-audio", - .owner = THIS_MODULE, - .dai_link = &mx27vis_aic32x4_dai, - .num_links = 1, - .controls = mx27vis_aic32x4_controls, - .num_controls = ARRAY_SIZE(mx27vis_aic32x4_controls), - .dapm_widgets = aic32x4_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(aic32x4_dapm_widgets), - .dapm_routes = aic32x4_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes), -}; - -static int mx27vis_aic32x4_probe(struct platform_device *pdev) -{ - struct snd_mx27vis_platform_data *pdata = pdev->dev.platform_data; - int ret; - - if (!pdata) { - dev_err(&pdev->dev, "No platform data supplied\n"); - return -EINVAL; - } - - mx27vis_amp_gain0_gpio = pdata->amp_gain0_gpio; - mx27vis_amp_gain1_gpio = pdata->amp_gain1_gpio; - mx27vis_amp_mutel_gpio = pdata->amp_mutel_gpio; - mx27vis_amp_muter_gpio = pdata->amp_muter_gpio; - - mx27vis_aic32x4.dev = &pdev->dev; - ret = devm_snd_soc_register_card(&pdev->dev, &mx27vis_aic32x4); - if (ret) { - dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", - ret); - return ret; - } - - /* Connect SSI0 as clock slave to SSI1 external pins */ - imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, - IMX_AUDMUX_V1_PCR_SYN | - IMX_AUDMUX_V1_PCR_TFSDIR | - IMX_AUDMUX_V1_PCR_TCLKDIR | - IMX_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1) | - IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1) - ); - imx_audmux_v1_configure_port(MX27_AUDMUX_PPCR1_SSI_PINS_1, - IMX_AUDMUX_V1_PCR_SYN | - IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0) - ); - - return ret; -} - -static struct platform_driver mx27vis_aic32x4_audio_driver = { - .driver = { - .name = "mx27vis", - }, - .probe = mx27vis_aic32x4_probe, -}; - -module_platform_driver(mx27vis_aic32x4_audio_driver); - -MODULE_AUTHOR("Javier Martin "); -MODULE_DESCRIPTION("ALSA SoC AIC32X4 mx27 visstrim"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:mx27vis"); -- cgit v1.2.3 From 440534a0ecfd20235a091fb2a98c2c3adf86834e Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 10 Nov 2020 17:39:34 -0300 Subject: ASoC: phycore-ac97: Remove unused driver Since commit e1324ece2af4 ("ARM: imx: Remove i.MX35 board files"), the MACH_PCM043 and MACH_PCA100 non-DT platform are no longer supported, so get rid of their machine audio driver too. Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20201110203937.25684-3-festevam@gmail.com Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 12 ----- sound/soc/fsl/Makefile | 2 - sound/soc/fsl/phycore-ac97.c | 121 ------------------------------------------- 3 files changed, 135 deletions(-) delete mode 100644 sound/soc/fsl/phycore-ac97.c (limited to 'sound/soc/fsl/Kconfig') diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index c18ec9310aa7..63be2bf5b509 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -239,18 +239,6 @@ config SND_SOC_IMX_SSI comment "SoC Audio support for Freescale i.MX boards:" -config SND_SOC_PHYCORE_AC97 - tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards" - depends on MACH_PCM043 || MACH_PCA100 - select SND_SOC_AC97_BUS - select SND_SOC_WM9712 - select SND_SOC_IMX_PCM_FIQ - select SND_SOC_IMX_AUDMUX - select SND_SOC_IMX_SSI - help - Say Y if you want to add support for SoC audio on Phytec phyCORE - and phyCARD boards in AC97 mode - config SND_SOC_EUKREA_TLV320 tristate "Eukrea TLV320" depends on ARCH_MXC && !ARM64 && I2C diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 5c6058f414be..12755058f877 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -63,7 +63,6 @@ obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o # i.MX Machine Support snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o -snd-soc-phycore-ac97-objs := phycore-ac97.o snd-soc-imx-es8328-objs := imx-es8328.o snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o snd-soc-imx-spdif-objs := imx-spdif.o @@ -71,7 +70,6 @@ snd-soc-imx-mc13783-objs := imx-mc13783.o snd-soc-imx-audmix-objs := imx-audmix.o obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o -obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o obj-$(CONFIG_SND_SOC_IMX_ES8328) += snd-soc-imx-es8328.o obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o diff --git a/sound/soc/fsl/phycore-ac97.c b/sound/soc/fsl/phycore-ac97.c deleted file mode 100644 index e561f7ff1699..000000000000 --- a/sound/soc/fsl/phycore-ac97.c +++ /dev/null @@ -1,121 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -// -// phycore-ac97.c -- SoC audio for imx_phycore in AC97 mode -// -// Copyright 2009 Sascha Hauer, Pengutronix - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "imx-audmux.h" - -static struct snd_soc_card imx_phycore; - -static const struct snd_soc_ops imx_phycore_hifi_ops = { -}; - -SND_SOC_DAILINK_DEFS(hifi, - DAILINK_COMP_ARRAY(COMP_CPU("imx-ssi.0")), - DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-hifi")), - DAILINK_COMP_ARRAY(COMP_PLATFORM("imx-ssi.0"))); - -static struct snd_soc_dai_link imx_phycore_dai_ac97[] = { - { - .name = "HiFi", - .stream_name = "HiFi", - .ops = &imx_phycore_hifi_ops, - SND_SOC_DAILINK_REG(hifi), - }, -}; - -static struct snd_soc_card imx_phycore = { - .name = "PhyCORE-ac97-audio", - .owner = THIS_MODULE, - .dai_link = imx_phycore_dai_ac97, - .num_links = ARRAY_SIZE(imx_phycore_dai_ac97), -}; - -static struct platform_device *imx_phycore_snd_ac97_device; -static struct platform_device *imx_phycore_snd_device; - -static int __init imx_phycore_init(void) -{ - int ret; - - if (machine_is_pca100()) { - imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, - IMX_AUDMUX_V1_PCR_SYN | /* 4wire mode */ - IMX_AUDMUX_V1_PCR_TFCSEL(3) | - IMX_AUDMUX_V1_PCR_TCLKDIR | /* clock is output */ - IMX_AUDMUX_V1_PCR_RXDSEL(3)); - imx_audmux_v1_configure_port(3, - IMX_AUDMUX_V1_PCR_SYN | /* 4wire mode */ - IMX_AUDMUX_V1_PCR_TFCSEL(0) | - IMX_AUDMUX_V1_PCR_TFSDIR | - IMX_AUDMUX_V1_PCR_RXDSEL(0)); - } else if (machine_is_pcm043()) { - imx_audmux_v2_configure_port(3, - IMX_AUDMUX_V2_PTCR_SYN | /* 4wire mode */ - IMX_AUDMUX_V2_PTCR_TFSEL(0) | - IMX_AUDMUX_V2_PTCR_TFSDIR, - IMX_AUDMUX_V2_PDCR_RXDSEL(0)); - imx_audmux_v2_configure_port(0, - IMX_AUDMUX_V2_PTCR_SYN | /* 4wire mode */ - IMX_AUDMUX_V2_PTCR_TCSEL(3) | - IMX_AUDMUX_V2_PTCR_TCLKDIR, /* clock is output */ - IMX_AUDMUX_V2_PDCR_RXDSEL(3)); - } else { - /* return happy. We might run on a totally different machine */ - return 0; - } - - imx_phycore_snd_ac97_device = platform_device_alloc("soc-audio", -1); - if (!imx_phycore_snd_ac97_device) - return -ENOMEM; - - platform_set_drvdata(imx_phycore_snd_ac97_device, &imx_phycore); - ret = platform_device_add(imx_phycore_snd_ac97_device); - if (ret) - goto fail1; - - imx_phycore_snd_device = platform_device_alloc("wm9712-codec", -1); - if (!imx_phycore_snd_device) { - ret = -ENOMEM; - goto fail2; - } - ret = platform_device_add(imx_phycore_snd_device); - - if (ret) { - printk(KERN_ERR "ASoC: Platform device allocation failed\n"); - goto fail3; - } - - return 0; - -fail3: - platform_device_put(imx_phycore_snd_device); -fail2: - platform_device_del(imx_phycore_snd_ac97_device); -fail1: - platform_device_put(imx_phycore_snd_ac97_device); - return ret; -} - -static void __exit imx_phycore_exit(void) -{ - platform_device_unregister(imx_phycore_snd_device); - platform_device_unregister(imx_phycore_snd_ac97_device); -} - -late_initcall(imx_phycore_init); -module_exit(imx_phycore_exit); - -MODULE_AUTHOR("Sascha Hauer "); -MODULE_DESCRIPTION("PhyCORE ALSA SoC driver"); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 83e7e2278680207f1650949db11ba0e1b6fbc3f5 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 10 Nov 2020 17:39:35 -0300 Subject: ASoC: imx-mc13783: Remove unused driver The imx-mc13783 was used on imx27-pdk and imx31-pdk non-DT platforms. Since 5.10-rc1, i.MX has been converted to a DT-only platform and all board files are gone. Remove the imx-mc13783 audio machine driver as there is no user at all. Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20201110203937.25684-4-festevam@gmail.com Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 8 --- sound/soc/fsl/Makefile | 2 - sound/soc/fsl/imx-mc13783.c | 156 -------------------------------------------- 3 files changed, 166 deletions(-) delete mode 100644 sound/soc/fsl/imx-mc13783.c (limited to 'sound/soc/fsl/Kconfig') diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 63be2bf5b509..1536c6d411fa 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -283,14 +283,6 @@ config SND_SOC_IMX_SPDIF Say Y if you want to add support for SoC audio on an i.MX board with a S/DPDIF. -config SND_SOC_IMX_MC13783 - tristate "SoC Audio support for I.MX boards with mc13783" - depends on MFD_MC13XXX && ARM - select SND_SOC_IMX_SSI - select SND_SOC_IMX_AUDMUX - select SND_SOC_MC13783 - select SND_SOC_IMX_PCM_DMA - config SND_SOC_FSL_ASOC_CARD tristate "Generic ASoC Sound Card with ASRC support" depends on OF && I2C diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 12755058f877..5637ebbe8ab2 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -66,12 +66,10 @@ snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o snd-soc-imx-es8328-objs := imx-es8328.o snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o snd-soc-imx-spdif-objs := imx-spdif.o -snd-soc-imx-mc13783-objs := imx-mc13783.o snd-soc-imx-audmix-objs := imx-audmix.o obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o obj-$(CONFIG_SND_SOC_IMX_ES8328) += snd-soc-imx-es8328.o obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o -obj-$(CONFIG_SND_SOC_IMX_MC13783) += snd-soc-imx-mc13783.o obj-$(CONFIG_SND_SOC_IMX_AUDMIX) += snd-soc-imx-audmix.o diff --git a/sound/soc/fsl/imx-mc13783.c b/sound/soc/fsl/imx-mc13783.c deleted file mode 100644 index d9dca7bbcae3..000000000000 --- a/sound/soc/fsl/imx-mc13783.c +++ /dev/null @@ -1,156 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -// -// imx-mc13783.c -- SoC audio for imx based boards with mc13783 codec -// -// Copyright 2012 Philippe Retornaz, -// -// Heavly based on phycore-mc13783: -// Copyright 2009 Sascha Hauer, Pengutronix - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../codecs/mc13783.h" -#include "imx-ssi.h" -#include "imx-audmux.h" - -#define FMT_SSI (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | \ - SND_SOC_DAIFMT_CBM_CFM) - -static int imx_mc13783_hifi_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); - int ret; - - ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 4, 16); - if (ret) - return ret; - - ret = snd_soc_dai_set_sysclk(codec_dai, MC13783_CLK_CLIA, 26000000, 0); - if (ret) - return ret; - - return snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 16); -} - -static const struct snd_soc_ops imx_mc13783_hifi_ops = { - .hw_params = imx_mc13783_hifi_hw_params, -}; - -SND_SOC_DAILINK_DEFS(hifi, - DAILINK_COMP_ARRAY(COMP_CPU("imx-ssi.0")), - DAILINK_COMP_ARRAY(COMP_CODEC("mc13783-codec", "mc13783-hifi")), - DAILINK_COMP_ARRAY(COMP_PLATFORM("imx-ssi.0"))); - -static struct snd_soc_dai_link imx_mc13783_dai_mc13783[] = { - { - .name = "MC13783", - .stream_name = "Sound", - .ops = &imx_mc13783_hifi_ops, - .symmetric_rates = 1, - .dai_fmt = FMT_SSI, - SND_SOC_DAILINK_REG(hifi), - }, -}; - -static const struct snd_soc_dapm_widget imx_mc13783_widget[] = { - SND_SOC_DAPM_MIC("Mic", NULL), - SND_SOC_DAPM_HP("Headphone", NULL), - SND_SOC_DAPM_SPK("Speaker", NULL), -}; - -static const struct snd_soc_dapm_route imx_mc13783_routes[] = { - {"Speaker", NULL, "LSP"}, - {"Headphone", NULL, "HSL"}, - {"Headphone", NULL, "HSR"}, - - {"MC1LIN", NULL, "MC1 Bias"}, - {"MC2IN", NULL, "MC2 Bias"}, - {"MC1 Bias", NULL, "Mic"}, - {"MC2 Bias", NULL, "Mic"}, -}; - -static struct snd_soc_card imx_mc13783 = { - .name = "imx_mc13783", - .owner = THIS_MODULE, - .dai_link = imx_mc13783_dai_mc13783, - .num_links = ARRAY_SIZE(imx_mc13783_dai_mc13783), - .dapm_widgets = imx_mc13783_widget, - .num_dapm_widgets = ARRAY_SIZE(imx_mc13783_widget), - .dapm_routes = imx_mc13783_routes, - .num_dapm_routes = ARRAY_SIZE(imx_mc13783_routes), -}; - -static int imx_mc13783_probe(struct platform_device *pdev) -{ - int ret; - - imx_mc13783.dev = &pdev->dev; - - ret = devm_snd_soc_register_card(&pdev->dev, &imx_mc13783); - if (ret) { - dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", - ret); - return ret; - } - - if (machine_is_mx31_3ds() || machine_is_mx31moboard()) { - imx_audmux_v2_configure_port(MX31_AUDMUX_PORT4_SSI_PINS_4, - IMX_AUDMUX_V2_PTCR_SYN, - IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0) | - IMX_AUDMUX_V2_PDCR_MODE(1) | - IMX_AUDMUX_V2_PDCR_INMMASK(0xfc)); - imx_audmux_v2_configure_port(MX31_AUDMUX_PORT1_SSI0, - IMX_AUDMUX_V2_PTCR_SYN | - IMX_AUDMUX_V2_PTCR_TFSDIR | - IMX_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT4_SSI_PINS_4) | - IMX_AUDMUX_V2_PTCR_TCLKDIR | - IMX_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT4_SSI_PINS_4) | - IMX_AUDMUX_V2_PTCR_RFSDIR | - IMX_AUDMUX_V2_PTCR_RFSEL(MX31_AUDMUX_PORT4_SSI_PINS_4) | - IMX_AUDMUX_V2_PTCR_RCLKDIR | - IMX_AUDMUX_V2_PTCR_RCSEL(MX31_AUDMUX_PORT4_SSI_PINS_4), - IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT4_SSI_PINS_4)); - } else if (machine_is_mx27_3ds()) { - imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, - IMX_AUDMUX_V1_PCR_SYN | - IMX_AUDMUX_V1_PCR_TFSDIR | - IMX_AUDMUX_V1_PCR_TCLKDIR | - IMX_AUDMUX_V1_PCR_RFSDIR | - IMX_AUDMUX_V1_PCR_RCLKDIR | - IMX_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) | - IMX_AUDMUX_V1_PCR_RFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) | - IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) - ); - imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR3_SSI_PINS_4, - IMX_AUDMUX_V1_PCR_SYN | - IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0) - ); - } - - return ret; -} - -static struct platform_driver imx_mc13783_audio_driver = { - .driver = { - .name = "imx_mc13783", - }, - .probe = imx_mc13783_probe, -}; - -module_platform_driver(imx_mc13783_audio_driver); - -MODULE_AUTHOR("Sascha Hauer "); -MODULE_AUTHOR("Philippe Retornaz Date: Tue, 10 Nov 2020 17:39:36 -0300 Subject: ASoC: fsl: eukrea: Remove the SND_SOC_IMX_SSI selection SND_SOC_IMX_SSI was only used by i.MX non-DT platforms. SND_SOC_EUKREA_TLV320 already selects the SND_SOC_FSL_SSI symbol, which is enough. Remove the unneeded SND_SOC_IMX_SSI selection. Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20201110203937.25684-5-festevam@gmail.com Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'sound/soc/fsl/Kconfig') diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 1536c6d411fa..31897fff6c71 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -244,7 +244,6 @@ config SND_SOC_EUKREA_TLV320 depends on ARCH_MXC && !ARM64 && I2C select SND_SOC_TLV320AIC23_I2C select SND_SOC_IMX_AUDMUX - select SND_SOC_IMX_SSI select SND_SOC_FSL_SSI select SND_SOC_IMX_PCM_DMA help -- cgit v1.2.3 From c31da0b196f99c7d95c69bab96e709b72a30f509 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 10 Nov 2020 17:39:37 -0300 Subject: ASoC: imx-ssi: Remove unused driver The imx-ssi driver was only used by i.MX non-DT platforms. Since 5.10-rc1, i.MX has been converted to a DT-only platform and all board files are gone. Remove the imx-ssi audio driver as there are no more users at all. Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20201110203937.25684-6-festevam@gmail.com Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 6 +- sound/soc/fsl/Makefile | 2 - sound/soc/fsl/imx-ssi.c | 651 ------------------------------------------------ 3 files changed, 1 insertion(+), 658 deletions(-) delete mode 100644 sound/soc/fsl/imx-ssi.c (limited to 'sound/soc/fsl/Kconfig') diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 31897fff6c71..a299f61e529e 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -228,15 +228,11 @@ endif # SND_POWERPC_SOC config SND_SOC_IMX_PCM_FIQ tristate - default y if SND_SOC_IMX_SSI=y && (SND_SOC_FSL_SSI=m || SND_SOC_FSL_SPDIF=m) && (MXC_TZIC || MXC_AVIC) + default y if (SND_SOC_FSL_SSI=m || SND_SOC_FSL_SPDIF=m) && (MXC_TZIC || MXC_AVIC) select FIQ if SND_IMX_SOC -config SND_SOC_IMX_SSI - tristate - select SND_SOC_FSL_UTILS - comment "SoC Audio support for Freescale i.MX boards:" config SND_SOC_EUKREA_TLV320 diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 5637ebbe8ab2..0b20e038b65b 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -53,9 +53,7 @@ obj-$(CONFIG_SND_MPC52xx_SOC_PCM030) += pcm030-audio-fabric.o obj-$(CONFIG_SND_MPC52xx_SOC_EFIKA) += efika-audio-fabric.o # i.MX Platform Support -snd-soc-imx-ssi-objs := imx-ssi.o snd-soc-imx-audmux-objs := imx-audmux.o -obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c deleted file mode 100644 index f8488e8f5f5b..000000000000 --- a/sound/soc/fsl/imx-ssi.c +++ /dev/null @@ -1,651 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -// -// imx-ssi.c -- ALSA Soc Audio Layer -// -// Copyright 2009 Sascha Hauer -// -// This code is based on code copyrighted by Freescale, -// Liam Girdwood, Javier Martin and probably others. -// -// The i.MX SSI core has some nasty limitations in AC97 mode. While most -// sane processor vendors have a FIFO per AC97 slot, the i.MX has only -// one FIFO which combines all valid receive slots. We cannot even select -// which slots we want to receive. The WM9712 with which this driver -// was developed with always sends GPIO status data in slot 12 which -// we receive in our (PCM-) data stream. The only chance we have is to -// manually skip this data in the FIQ handler. With sampling rates different -// from 48000Hz not every frame has valid receive data, so the ratio -// between pcm data and GPIO status data changes. Our FIQ handler is not -// able to handle this, hence this driver only works with 48000Hz sampling -// rate. -// Reading and writing AC97 registers is another challenge. The core -// provides us status bits when the read register is updated with *another* -// value. When we read the same register two times (and the register still -// contains the same value) these status bits are not set. We work -// around this by not polling these bits but only wait a fixed delay. - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include "imx-ssi.h" -#include "fsl_utils.h" - -#define SSI_SACNT_DEFAULT (SSI_SACNT_AC97EN | SSI_SACNT_FV) - -/* - * SSI Network Mode or TDM slots configuration. - * Should only be called when port is inactive (i.e. SSIEN = 0). - */ -static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, - unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) -{ - struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai); - u32 sccr; - - sccr = readl(ssi->base + SSI_STCCR); - sccr &= ~SSI_STCCR_DC_MASK; - sccr |= SSI_STCCR_DC(slots - 1); - writel(sccr, ssi->base + SSI_STCCR); - - sccr = readl(ssi->base + SSI_SRCCR); - sccr &= ~SSI_STCCR_DC_MASK; - sccr |= SSI_STCCR_DC(slots - 1); - writel(sccr, ssi->base + SSI_SRCCR); - - writel(~tx_mask, ssi->base + SSI_STMSK); - writel(~rx_mask, ssi->base + SSI_SRMSK); - - return 0; -} - -/* - * SSI DAI format configuration. - * Should only be called when port is inactive (i.e. SSIEN = 0). - */ -static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) -{ - struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai); - u32 strcr = 0, scr; - - scr = readl(ssi->base + SSI_SCR) & ~(SSI_SCR_SYN | SSI_SCR_NET); - - /* DAI mode */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - /* data on rising edge of bclk, frame low 1clk before data */ - strcr |= SSI_STCR_TXBIT0 | SSI_STCR_TSCKP | SSI_STCR_TFSI | - SSI_STCR_TEFS; - scr |= SSI_SCR_NET; - if (ssi->flags & IMX_SSI_USE_I2S_SLAVE) { - scr &= ~SSI_I2S_MODE_MASK; - scr |= SSI_SCR_I2S_MODE_SLAVE; - } - break; - case SND_SOC_DAIFMT_LEFT_J: - /* data on rising edge of bclk, frame high with data */ - strcr |= SSI_STCR_TXBIT0 | SSI_STCR_TSCKP; - break; - case SND_SOC_DAIFMT_DSP_B: - /* data on rising edge of bclk, frame high with data */ - strcr |= SSI_STCR_TXBIT0 | SSI_STCR_TSCKP | SSI_STCR_TFSL; - break; - case SND_SOC_DAIFMT_DSP_A: - /* data on rising edge of bclk, frame high 1clk before data */ - strcr |= SSI_STCR_TXBIT0 | SSI_STCR_TSCKP | SSI_STCR_TFSL | - SSI_STCR_TEFS; - break; - } - - /* DAI clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_IB_IF: - strcr ^= SSI_STCR_TSCKP | SSI_STCR_TFSI; - break; - case SND_SOC_DAIFMT_IB_NF: - strcr ^= SSI_STCR_TSCKP; - break; - case SND_SOC_DAIFMT_NB_IF: - strcr ^= SSI_STCR_TFSI; - break; - case SND_SOC_DAIFMT_NB_NF: - break; - } - - /* DAI clock master masks */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - break; - default: - /* Master mode not implemented, needs handling of clocks. */ - return -EINVAL; - } - - strcr |= SSI_STCR_TFEN0; - - if (ssi->flags & IMX_SSI_NET) - scr |= SSI_SCR_NET; - if (ssi->flags & IMX_SSI_SYN) - scr |= SSI_SCR_SYN; - - writel(strcr, ssi->base + SSI_STCR); - writel(strcr, ssi->base + SSI_SRCR); - writel(scr, ssi->base + SSI_SCR); - - return 0; -} - -/* - * SSI system clock configuration. - * Should only be called when port is inactive (i.e. SSIEN = 0). - */ -static int imx_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai, - int clk_id, unsigned int freq, int dir) -{ - struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai); - u32 scr; - - scr = readl(ssi->base + SSI_SCR); - - switch (clk_id) { - case IMX_SSP_SYS_CLK: - if (dir == SND_SOC_CLOCK_OUT) - scr |= SSI_SCR_SYS_CLK_EN; - else - scr &= ~SSI_SCR_SYS_CLK_EN; - break; - default: - return -EINVAL; - } - - writel(scr, ssi->base + SSI_SCR); - - return 0; -} - -/* - * SSI Clock dividers - * Should only be called when port is inactive (i.e. SSIEN = 0). - */ -static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, - int div_id, int div) -{ - struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai); - u32 stccr, srccr; - - stccr = readl(ssi->base + SSI_STCCR); - srccr = readl(ssi->base + SSI_SRCCR); - - switch (div_id) { - case IMX_SSI_TX_DIV_2: - stccr &= ~SSI_STCCR_DIV2; - stccr |= div; - break; - case IMX_SSI_TX_DIV_PSR: - stccr &= ~SSI_STCCR_PSR; - stccr |= div; - break; - case IMX_SSI_TX_DIV_PM: - stccr &= ~0xff; - stccr |= SSI_STCCR_PM(div); - break; - case IMX_SSI_RX_DIV_2: - stccr &= ~SSI_STCCR_DIV2; - stccr |= div; - break; - case IMX_SSI_RX_DIV_PSR: - stccr &= ~SSI_STCCR_PSR; - stccr |= div; - break; - case IMX_SSI_RX_DIV_PM: - stccr &= ~0xff; - stccr |= SSI_STCCR_PM(div); - break; - default: - return -EINVAL; - } - - writel(stccr, ssi->base + SSI_STCCR); - writel(srccr, ssi->base + SSI_SRCCR); - - return 0; -} - -/* - * Should only be called when port is inactive (i.e. SSIEN = 0), - * although can be called multiple times by upper layers. - */ -static int imx_ssi_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *cpu_dai) -{ - struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai); - u32 reg, sccr; - - /* Tx/Rx config */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - reg = SSI_STCCR; - else - reg = SSI_SRCCR; - - if (ssi->flags & IMX_SSI_SYN) - reg = SSI_STCCR; - - sccr = readl(ssi->base + reg) & ~SSI_STCCR_WL_MASK; - - /* DAI data (word) size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - sccr |= SSI_SRCCR_WL(16); - break; - case SNDRV_PCM_FORMAT_S20_3LE: - sccr |= SSI_SRCCR_WL(20); - break; - case SNDRV_PCM_FORMAT_S24_LE: - sccr |= SSI_SRCCR_WL(24); - break; - } - - writel(sccr, ssi->base + reg); - - return 0; -} - -static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - struct imx_ssi *ssi = snd_soc_dai_get_drvdata(dai); - unsigned int sier_bits, sier; - unsigned int scr; - - scr = readl(ssi->base + SSI_SCR); - sier = readl(ssi->base + SSI_SIER); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (ssi->flags & IMX_SSI_DMA) - sier_bits = SSI_SIER_TDMAE; - else - sier_bits = SSI_SIER_TIE | SSI_SIER_TFE0_EN; - } else { - if (ssi->flags & IMX_SSI_DMA) - sier_bits = SSI_SIER_RDMAE; - else - sier_bits = SSI_SIER_RIE | SSI_SIER_RFF0_EN; - } - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - scr |= SSI_SCR_TE; - else - scr |= SSI_SCR_RE; - sier |= sier_bits; - - scr |= SSI_SCR_SSIEN; - - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - scr &= ~SSI_SCR_TE; - else - scr &= ~SSI_SCR_RE; - sier &= ~sier_bits; - - if (!(scr & (SSI_SCR_TE | SSI_SCR_RE))) - scr &= ~SSI_SCR_SSIEN; - - break; - default: - return -EINVAL; - } - - if (!(ssi->flags & IMX_SSI_USE_AC97)) - /* rx/tx are always enabled to access ac97 registers */ - writel(scr, ssi->base + SSI_SCR); - - writel(sier, ssi->base + SSI_SIER); - - return 0; -} - -static const struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = { - .hw_params = imx_ssi_hw_params, - .set_fmt = imx_ssi_set_dai_fmt, - .set_clkdiv = imx_ssi_set_dai_clkdiv, - .set_sysclk = imx_ssi_set_dai_sysclk, - .set_tdm_slot = imx_ssi_set_dai_tdm_slot, - .trigger = imx_ssi_trigger, -}; - -static int imx_ssi_dai_probe(struct snd_soc_dai *dai) -{ - struct imx_ssi *ssi = dev_get_drvdata(dai->dev); - uint32_t val; - - snd_soc_dai_set_drvdata(dai, ssi); - - val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.maxburst) | - SSI_SFCSR_RFWM0(ssi->dma_params_rx.maxburst); - writel(val, ssi->base + SSI_SFCSR); - - /* Tx/Rx config */ - dai->playback_dma_data = &ssi->dma_params_tx; - dai->capture_dma_data = &ssi->dma_params_rx; - - return 0; -} - -static struct snd_soc_dai_driver imx_ssi_dai = { - .probe = imx_ssi_dai_probe, - .playback = { - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_96000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .capture = { - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_96000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .ops = &imx_ssi_pcm_dai_ops, -}; - -static struct snd_soc_dai_driver imx_ac97_dai = { - .probe = imx_ssi_dai_probe, - .playback = { - .stream_name = "AC97 Playback", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .capture = { - .stream_name = "AC97 Capture", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .ops = &imx_ssi_pcm_dai_ops, -}; - -static const struct snd_soc_component_driver imx_component = { - .name = DRV_NAME, -}; - -static void setup_channel_to_ac97(struct imx_ssi *imx_ssi) -{ - void __iomem *base = imx_ssi->base; - - writel(0x0, base + SSI_SCR); - writel(0x0, base + SSI_STCR); - writel(0x0, base + SSI_SRCR); - - writel(SSI_SCR_SYN | SSI_SCR_NET, base + SSI_SCR); - - writel(SSI_SFCSR_RFWM0(8) | - SSI_SFCSR_TFWM0(8) | - SSI_SFCSR_RFWM1(8) | - SSI_SFCSR_TFWM1(8), base + SSI_SFCSR); - - writel(SSI_STCCR_WL(16) | SSI_STCCR_DC(12), base + SSI_STCCR); - writel(SSI_STCCR_WL(16) | SSI_STCCR_DC(12), base + SSI_SRCCR); - - writel(SSI_SCR_SYN | SSI_SCR_NET | SSI_SCR_SSIEN, base + SSI_SCR); - writel(SSI_SOR_WAIT(3), base + SSI_SOR); - - writel(SSI_SCR_SYN | SSI_SCR_NET | SSI_SCR_SSIEN | - SSI_SCR_TE | SSI_SCR_RE, - base + SSI_SCR); - - writel(SSI_SACNT_DEFAULT, base + SSI_SACNT); - writel(0xff, base + SSI_SACCDIS); - writel(0x300, base + SSI_SACCEN); -} - -static struct imx_ssi *ac97_ssi; - -static void imx_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg, - unsigned short val) -{ - struct imx_ssi *imx_ssi = ac97_ssi; - void __iomem *base = imx_ssi->base; - unsigned int lreg; - unsigned int lval; - - if (reg > 0x7f) - return; - - pr_debug("%s: 0x%02x 0x%04x\n", __func__, reg, val); - - lreg = reg << 12; - writel(lreg, base + SSI_SACADD); - - lval = val << 4; - writel(lval , base + SSI_SACDAT); - - writel(SSI_SACNT_DEFAULT | SSI_SACNT_WR, base + SSI_SACNT); - udelay(100); -} - -static unsigned short imx_ssi_ac97_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct imx_ssi *imx_ssi = ac97_ssi; - void __iomem *base = imx_ssi->base; - - unsigned short val = -1; - unsigned int lreg; - - lreg = (reg & 0x7f) << 12 ; - writel(lreg, base + SSI_SACADD); - writel(SSI_SACNT_DEFAULT | SSI_SACNT_RD, base + SSI_SACNT); - - udelay(100); - - val = (readl(base + SSI_SACDAT) >> 4) & 0xffff; - - pr_debug("%s: 0x%02x 0x%04x\n", __func__, reg, val); - - return val; -} - -static void imx_ssi_ac97_reset(struct snd_ac97 *ac97) -{ - struct imx_ssi *imx_ssi = ac97_ssi; - - if (imx_ssi->ac97_reset) - imx_ssi->ac97_reset(ac97); - /* First read sometimes fails, do a dummy read */ - imx_ssi_ac97_read(ac97, 0); -} - -static void imx_ssi_ac97_warm_reset(struct snd_ac97 *ac97) -{ - struct imx_ssi *imx_ssi = ac97_ssi; - - if (imx_ssi->ac97_warm_reset) - imx_ssi->ac97_warm_reset(ac97); - - /* First read sometimes fails, do a dummy read */ - imx_ssi_ac97_read(ac97, 0); -} - -static struct snd_ac97_bus_ops imx_ssi_ac97_ops = { - .read = imx_ssi_ac97_read, - .write = imx_ssi_ac97_write, - .reset = imx_ssi_ac97_reset, - .warm_reset = imx_ssi_ac97_warm_reset -}; - -static int imx_ssi_probe(struct platform_device *pdev) -{ - struct resource *res; - struct imx_ssi *ssi; - struct imx_ssi_platform_data *pdata = pdev->dev.platform_data; - int ret = 0; - struct snd_soc_dai_driver *dai; - - ssi = devm_kzalloc(&pdev->dev, sizeof(*ssi), GFP_KERNEL); - if (!ssi) - return -ENOMEM; - dev_set_drvdata(&pdev->dev, ssi); - - if (pdata) { - ssi->ac97_reset = pdata->ac97_reset; - ssi->ac97_warm_reset = pdata->ac97_warm_reset; - ssi->flags = pdata->flags; - } - - ssi->irq = platform_get_irq(pdev, 0); - if (ssi->irq < 0) - return ssi->irq; - - ssi->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(ssi->clk)) { - ret = PTR_ERR(ssi->clk); - dev_err(&pdev->dev, "Cannot get the clock: %d\n", - ret); - goto failed_clk; - } - ret = clk_prepare_enable(ssi->clk); - if (ret) - goto failed_clk; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - ssi->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(ssi->base)) { - ret = PTR_ERR(ssi->base); - goto failed_register; - } - - if (ssi->flags & IMX_SSI_USE_AC97) { - if (ac97_ssi) { - dev_err(&pdev->dev, "AC'97 SSI already registered\n"); - ret = -EBUSY; - goto failed_register; - } - ac97_ssi = ssi; - setup_channel_to_ac97(ssi); - dai = &imx_ac97_dai; - } else - dai = &imx_ssi_dai; - - writel(0x0, ssi->base + SSI_SIER); - - ssi->dma_params_rx.addr = res->start + SSI_SRX0; - ssi->dma_params_tx.addr = res->start + SSI_STX0; - - ssi->dma_params_tx.maxburst = 6; - ssi->dma_params_rx.maxburst = 4; - - ssi->dma_params_tx.filter_data = &ssi->filter_data_tx; - ssi->dma_params_rx.filter_data = &ssi->filter_data_rx; - - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0"); - if (res) { - imx_pcm_dma_params_init_data(&ssi->filter_data_tx, res->start, - IMX_DMATYPE_SSI); - } - - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx0"); - if (res) { - imx_pcm_dma_params_init_data(&ssi->filter_data_rx, res->start, - IMX_DMATYPE_SSI); - } - - platform_set_drvdata(pdev, ssi); - - ret = snd_soc_set_ac97_ops(&imx_ssi_ac97_ops); - if (ret != 0) { - dev_err(&pdev->dev, "Failed to set AC'97 ops: %d\n", ret); - goto failed_register; - } - - ret = snd_soc_register_component(&pdev->dev, &imx_component, - dai, 1); - if (ret) { - dev_err(&pdev->dev, "register DAI failed\n"); - goto failed_register; - } - - ssi->fiq_params.irq = ssi->irq; - ssi->fiq_params.base = ssi->base; - ssi->fiq_params.dma_params_rx = &ssi->dma_params_rx; - ssi->fiq_params.dma_params_tx = &ssi->dma_params_tx; - - ssi->fiq_init = imx_pcm_fiq_init(pdev, &ssi->fiq_params); - ssi->dma_init = imx_pcm_dma_init(pdev, IMX_SSI_DMABUF_SIZE); - - if (ssi->fiq_init && ssi->dma_init) { - ret = ssi->fiq_init; - goto failed_pcm; - } - - return 0; - -failed_pcm: - snd_soc_unregister_component(&pdev->dev); -failed_register: - clk_disable_unprepare(ssi->clk); -failed_clk: - snd_soc_set_ac97_ops(NULL); - - return ret; -} - -static int imx_ssi_remove(struct platform_device *pdev) -{ - struct imx_ssi *ssi = platform_get_drvdata(pdev); - - if (!ssi->fiq_init) - imx_pcm_fiq_exit(pdev); - - snd_soc_unregister_component(&pdev->dev); - - if (ssi->flags & IMX_SSI_USE_AC97) - ac97_ssi = NULL; - - clk_disable_unprepare(ssi->clk); - snd_soc_set_ac97_ops(NULL); - - return 0; -} - -static struct platform_driver imx_ssi_driver = { - .probe = imx_ssi_probe, - .remove = imx_ssi_remove, - - .driver = { - .name = "imx-ssi", - }, -}; - -module_platform_driver(imx_ssi_driver); - -/* Module information */ -MODULE_AUTHOR("Sascha Hauer, "); -MODULE_DESCRIPTION("i.MX I2S/ac97 SoC Interface"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:imx-ssi"); -- cgit v1.2.3 From 674226db62ec758c4575bcdb933a2410f1a29bbf Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 10 Nov 2020 15:51:20 +0100 Subject: ASoC: fsl: SND_SOC_FSL_AUD2HTX should depend on ARCH_MXC The Freescale/NXP AUDIO TO HDMI TX module is only present on NXP i.MX 8 Series SoCs. Hence add a dependency on ARCH_MXC, to prevent asking the user about this driver when configuring a kernel without i.MX 8 platform support. Fixes: 8a24c834c053ef1b ("ASoC: fsl_aud2htx: Add aud2htx module driver") Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20201110145120.3280658-1-geert+renesas@glider.be Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc/fsl/Kconfig') diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index a299f61e529e..06a2d225d644 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -107,6 +107,7 @@ config SND_SOC_FSL_XCVR config SND_SOC_FSL_AUD2HTX tristate "AUDIO TO HDMI TX module support" + depends on CONFIG_ARCH_MXC || COMPILE_TEST help Say Y if you want to add AUDIO TO HDMI TX support for NXP. -- cgit v1.2.3 From c61d1142cfd45f58b63bf9d2d59523f91096e873 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Thu, 26 Nov 2020 14:14:53 +0800 Subject: ASoC: fsl: Fix config name of CONFIG_ARCH_MXC CONFIG_ARCH_MXC should be ARCH_MXC Fixes: 674226db62ec ("ASoC: fsl: SND_SOC_FSL_AUD2HTX should depend on ARCH_MXC") Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1606371293-29099-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/fsl/Kconfig') diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 06a2d225d644..24710decd38a 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -107,7 +107,7 @@ config SND_SOC_FSL_XCVR config SND_SOC_FSL_AUD2HTX tristate "AUDIO TO HDMI TX module support" - depends on CONFIG_ARCH_MXC || COMPILE_TEST + depends on ARCH_MXC || COMPILE_TEST help Say Y if you want to add AUDIO TO HDMI TX support for NXP. -- cgit v1.2.3 From 6a5f850aa83a1d844d27e3e53ca2f247e55d438b Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Sun, 6 Dec 2020 18:41:59 +0800 Subject: ASoC: fsl: Add imx-hdmi machine driver The driver is initially designed for sound card using HDMI interface on i.MX platform. There is internal HDMI IP or external HDMI modules connect with SAI or AUD2HTX interface. It supports both transmitter and receiver devices. Signed-off-by: Shengjiu Wang Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/1607251319-5821-2-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 12 +++ sound/soc/fsl/Makefile | 2 + sound/soc/fsl/imx-hdmi.c | 236 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 250 insertions(+) create mode 100644 sound/soc/fsl/imx-hdmi.c (limited to 'sound/soc/fsl/Kconfig') diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 24710decd38a..84db0b7b9d59 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -305,6 +305,18 @@ config SND_SOC_IMX_AUDMIX Say Y if you want to add support for SoC audio on an i.MX board with an Audio Mixer. +config SND_SOC_IMX_HDMI + tristate "SoC Audio support for i.MX boards with HDMI port" + select SND_SOC_FSL_SAI + select SND_SOC_FSL_AUD2HTX + select SND_SOC_HDMI_CODEC + help + ALSA SoC Audio support with HDMI feature for Freescale SoCs that have + SAI/AUD2HTX and connect with internal HDMI IP or external module + SII902X. + Say Y if you want to add support for SoC audio on an i.MX board with + IMX HDMI. + endif # SND_IMX_SOC endmenu diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 0b20e038b65b..8c5fa8a859c0 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -65,9 +65,11 @@ snd-soc-imx-es8328-objs := imx-es8328.o snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o snd-soc-imx-spdif-objs := imx-spdif.o snd-soc-imx-audmix-objs := imx-audmix.o +snd-soc-imx-hdmi-objs := imx-hdmi.o obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o obj-$(CONFIG_SND_SOC_IMX_ES8328) += snd-soc-imx-es8328.o obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o obj-$(CONFIG_SND_SOC_IMX_AUDMIX) += snd-soc-imx-audmix.o +obj-$(CONFIG_SND_SOC_IMX_HDMI) += snd-soc-imx-hdmi.o diff --git a/sound/soc/fsl/imx-hdmi.c b/sound/soc/fsl/imx-hdmi.c new file mode 100644 index 000000000000..2c2a76a71940 --- /dev/null +++ b/sound/soc/fsl/imx-hdmi.c @@ -0,0 +1,236 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright 2017-2020 NXP + +#include +#include +#include +#include +#include +#include "fsl_sai.h" + +/** + * struct cpu_priv - CPU private data + * @sysclk_freq: SYSCLK rates for set_sysclk() + * @sysclk_dir: SYSCLK directions for set_sysclk() + * @sysclk_id: SYSCLK ids for set_sysclk() + * @slot_width: Slot width of each frame + * + * Note: [1] for tx and [0] for rx + */ +struct cpu_priv { + unsigned long sysclk_freq[2]; + u32 sysclk_dir[2]; + u32 sysclk_id[2]; + u32 slot_width; +}; + +struct imx_hdmi_data { + struct snd_soc_dai_link dai; + struct snd_soc_card card; + struct snd_soc_jack hdmi_jack; + struct snd_soc_jack_pin hdmi_jack_pin; + struct cpu_priv cpu_priv; + u32 dai_fmt; +}; + +static int imx_hdmi_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct imx_hdmi_data *data = snd_soc_card_get_drvdata(rtd->card); + bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + struct snd_soc_card *card = rtd->card; + struct device *dev = card->dev; + u32 slot_width = data->cpu_priv.slot_width; + int ret; + + /* MCLK always is (256 or 192) * rate. */ + ret = snd_soc_dai_set_sysclk(cpu_dai, data->cpu_priv.sysclk_id[tx], + 8 * slot_width * params_rate(params), + tx ? SND_SOC_CLOCK_OUT : SND_SOC_CLOCK_IN); + if (ret && ret != -ENOTSUPP) { + dev_err(dev, "failed to set cpu sysclk: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, 0, 2, slot_width); + if (ret && ret != -ENOTSUPP) { + dev_err(dev, "failed to set cpu dai tdm slot: %d\n", ret); + return ret; + } + + return 0; +} + +static struct snd_soc_ops imx_hdmi_ops = { + .hw_params = imx_hdmi_hw_params, +}; + +static const struct snd_soc_dapm_widget imx_hdmi_widgets[] = { + SND_SOC_DAPM_LINE("HDMI Jack", NULL), +}; + +static int imx_hdmi_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_component *component = codec_dai->component; + struct imx_hdmi_data *data = snd_soc_card_get_drvdata(card); + int ret; + + data->hdmi_jack_pin.pin = "HDMI Jack"; + data->hdmi_jack_pin.mask = SND_JACK_LINEOUT; + /* enable jack detection */ + ret = snd_soc_card_jack_new(card, "HDMI Jack", SND_JACK_LINEOUT, + &data->hdmi_jack, &data->hdmi_jack_pin, 1); + if (ret) { + dev_err(card->dev, "Can't new HDMI Jack %d\n", ret); + return ret; + } + + ret = snd_soc_component_set_jack(component, &data->hdmi_jack, NULL); + if (ret && ret != -EOPNOTSUPP) { + dev_err(card->dev, "Can't set HDMI Jack %d\n", ret); + return ret; + } + + return 0; +}; + +static int imx_hdmi_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + bool hdmi_out = of_property_read_bool(np, "hdmi-out"); + bool hdmi_in = of_property_read_bool(np, "hdmi-in"); + struct snd_soc_dai_link_component *dlc; + struct platform_device *cpu_pdev; + struct device_node *cpu_np; + struct imx_hdmi_data *data; + int ret; + + dlc = devm_kzalloc(&pdev->dev, 3 * sizeof(*dlc), GFP_KERNEL); + if (!dlc) + return -ENOMEM; + + cpu_np = of_parse_phandle(np, "audio-cpu", 0); + if (!cpu_np) { + dev_err(&pdev->dev, "cpu dai phandle missing or invalid\n"); + ret = -EINVAL; + goto fail; + } + + cpu_pdev = of_find_device_by_node(cpu_np); + if (!cpu_pdev) { + dev_err(&pdev->dev, "failed to find SAI platform device\n"); + ret = -EINVAL; + goto fail; + } + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto fail; + } + + data->dai.cpus = &dlc[0]; + data->dai.num_cpus = 1; + data->dai.platforms = &dlc[1]; + data->dai.num_platforms = 1; + data->dai.codecs = &dlc[2]; + data->dai.num_codecs = 1; + + data->dai.name = "i.MX HDMI"; + data->dai.stream_name = "i.MX HDMI"; + data->dai.cpus->dai_name = dev_name(&cpu_pdev->dev); + data->dai.platforms->of_node = cpu_np; + data->dai.ops = &imx_hdmi_ops; + data->dai.playback_only = true; + data->dai.capture_only = false; + data->dai.init = imx_hdmi_init; + + if (of_node_name_eq(cpu_np, "sai")) { + data->cpu_priv.sysclk_id[1] = FSL_SAI_CLK_MAST1; + data->cpu_priv.sysclk_id[0] = FSL_SAI_CLK_MAST1; + } + + if (of_device_is_compatible(np, "fsl,imx-audio-sii902x")) { + data->dai_fmt = SND_SOC_DAIFMT_LEFT_J; + data->cpu_priv.slot_width = 24; + } else { + data->dai_fmt = SND_SOC_DAIFMT_I2S; + data->cpu_priv.slot_width = 32; + } + + if ((hdmi_out && hdmi_in) || (!hdmi_out && !hdmi_in)) { + dev_err(&pdev->dev, "Invalid HDMI DAI link\n"); + goto fail; + } + + if (hdmi_out) { + data->dai.playback_only = true; + data->dai.capture_only = false; + data->dai.codecs->dai_name = "i2s-hifi"; + data->dai.codecs->name = "hdmi-audio-codec.1"; + data->dai.dai_fmt = data->dai_fmt | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS; + } + + if (hdmi_in) { + data->dai.playback_only = false; + data->dai.capture_only = true; + data->dai.codecs->dai_name = "i2s-hifi"; + data->dai.codecs->name = "hdmi-audio-codec.2"; + data->dai.dai_fmt = data->dai_fmt | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM; + } + + data->card.dapm_widgets = imx_hdmi_widgets; + data->card.num_dapm_widgets = ARRAY_SIZE(imx_hdmi_widgets); + data->card.dev = &pdev->dev; + data->card.owner = THIS_MODULE; + ret = snd_soc_of_parse_card_name(&data->card, "model"); + if (ret) + goto fail; + + data->card.num_links = 1; + data->card.dai_link = &data->dai; + + snd_soc_card_set_drvdata(&data->card, data); + ret = devm_snd_soc_register_card(&pdev->dev, &data->card); + if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); + goto fail; + } + +fail: + if (cpu_np) + of_node_put(cpu_np); + + return ret; +} + +static const struct of_device_id imx_hdmi_dt_ids[] = { + { .compatible = "fsl,imx-audio-hdmi", }, + { .compatible = "fsl,imx-audio-sii902x", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, imx_hdmi_dt_ids); + +static struct platform_driver imx_hdmi_driver = { + .driver = { + .name = "imx-hdmi", + .owner = THIS_MODULE, + .pm = &snd_soc_pm_ops, + .of_match_table = imx_hdmi_dt_ids, + }, + .probe = imx_hdmi_probe, +}; +module_platform_driver(imx_hdmi_driver); + +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_DESCRIPTION("Freescale i.MX hdmi audio ASoC machine driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:imx-hdmi"); -- cgit v1.2.3